mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 18:18:48 +00:00
[configuration] Extended the configuration app to display the resulting configuration for a path and have 'blame'. Removed the PrintConfiguration annotation and handlers. Separated the parsing and the interpreting.
This commit is contained in:
1 parent
ff01574864
commit
ed061712f5
9 files changed
+388
-308
No files matched your search
@@ -21,13 +21,9 @@
|
||||
*/
|
||||
package lombok.core;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.core.configuration.BubblingConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationProblemReporter;
|
||||
import lombok.core.configuration.ConfigurationKey;
|
||||
import lombok.core.configuration.ConfigurationProblemReporter;
|
||||
import lombok.core.configuration.ConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationResolverFactory;
|
||||
import lombok.core.configuration.FileSystemSourceCache;
|
||||
@@ -48,35 +44,6 @@ public class LombokConfiguration {
|
||||
return configurationResolverFactory.createResolver(ast).resolve(key);
|
||||
}
|
||||
|
||||
public static void writeConfiguration(AST<?, ?, ?> ast, PrintStream stream) {
|
||||
final List<String> problems = new ArrayList<String>();
|
||||
ConfigurationProblemReporter reporter = new ConfigurationProblemReporter() {
|
||||
@Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
|
||||
problems.add(String.format("%s (%s:%d)", problem, sourceDescription, lineNumber));
|
||||
}
|
||||
};
|
||||
|
||||
stream.printf("Combined lombok configuration for '%s'\n\n", ast.getAbsoluteFileLocation());
|
||||
// create a new empty 'cache' to make sure all problems are reported
|
||||
cache.reset();
|
||||
ConfigurationResolver resolver = new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), reporter));
|
||||
for (ConfigurationKey<?> key : ConfigurationKey.registeredKeys().values()) {
|
||||
Object value = resolver.resolve(key);
|
||||
if (value == null || value instanceof List<?> && ((List<?>)value).isEmpty()) continue;
|
||||
stream.printf("%s: %s\n", key.getKeyName(), value);
|
||||
}
|
||||
|
||||
if (!problems.isEmpty()) {
|
||||
stream.println();
|
||||
stream.printf("Problems encountered during parsing: %d\n", problems.size());
|
||||
int i = 1;
|
||||
for (String problem : problems) {
|
||||
stream.printf("%4d - %s\n", i, problem);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() {
|
||||
return new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.core;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Will print the combined interpreted configuration from 'lombok.config' files.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface PrintConfiguration {
|
||||
/**
|
||||
* Normally, the configuration is printed to standard out, but you can pick a filename instead. Useful for many IDEs
|
||||
* which don't have a console unless you start them from the command line.
|
||||
*/
|
||||
String outfile() default "";
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class BubblingConfigurationResolver implements ConfigurationResolver {
|
||||
List<Object> listValues = new ArrayList<Object>();
|
||||
Collections.reverse(listModificationsList);
|
||||
for (List<ListModification> listModifications : listModificationsList) {
|
||||
for (ListModification modification : listModifications) {
|
||||
if (listModifications != null) for (ListModification modification : listModifications) {
|
||||
listValues.remove(modification.getValue());
|
||||
if (modification.isAdded()) {
|
||||
listValues.add(modification.getValue());
|
||||
|
||||
@@ -21,12 +21,27 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
import static lombok.core.configuration.FileSystemSourceCache.fileToString;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.LombokApp;
|
||||
import lombok.core.configuration.ConfigurationParser.Collector;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@@ -40,6 +55,7 @@ import com.zwitserloot.cmdreader.Shorthand;
|
||||
|
||||
@ProviderFor(LombokApp.class)
|
||||
public class ConfigurationApp extends LombokApp {
|
||||
private static final URI NO_CONFIG = URI.create("");
|
||||
|
||||
@Override public String getAppName() {
|
||||
return "configuration";
|
||||
@@ -68,6 +84,10 @@ public class ConfigurationApp extends LombokApp {
|
||||
@Description("Displays more information.")
|
||||
boolean verbose = false;
|
||||
|
||||
@Shorthand("k")
|
||||
@Description("Limit the result to these keys.")
|
||||
private List<String> key = new ArrayList<String>();
|
||||
|
||||
@Shorthand({"h", "?"})
|
||||
@Description("Shows this help text.")
|
||||
boolean help = false;
|
||||
@@ -89,34 +109,21 @@ public class ConfigurationApp extends LombokApp {
|
||||
}
|
||||
|
||||
ConfigurationKeysLoader.LoaderLoader.loadAllConfigurationKeys();
|
||||
Collection<ConfigurationKey<?>> keys = checkKeys(args.key);
|
||||
if (keys == null) return 1;
|
||||
|
||||
if (args.generate) {
|
||||
printConfiguration(System.out, args.verbose);
|
||||
} else {
|
||||
System.out.println("Not generating anything...");
|
||||
return generate(System.out, args.verbose, keys);
|
||||
}
|
||||
|
||||
|
||||
// List<File> filesToProcess = PostCompilerApp.cmdArgsToFiles(args.classFiles);
|
||||
int filesVisited = 0;
|
||||
// boolean moreThanOne = filesToProcess.size() > 1;
|
||||
// for (File file : filesToProcess) {
|
||||
// if (!file.exists() || !file.isFile()) {
|
||||
// System.out.printf("Cannot find file '%s'\n", file.getAbsolutePath());
|
||||
// continue;
|
||||
// }
|
||||
// filesVisited++;
|
||||
// if (moreThanOne) System.out.printf("Processing '%s'\n", file.getAbsolutePath());
|
||||
// System.out.println(new ClassFileMetaData(PostCompilerApp.readFile(file)).poolContent());
|
||||
// }
|
||||
//
|
||||
// if (moreThanOne) System.out.printf("Total files visited: %d\n", filesVisited);
|
||||
TreeMap<URI, Set<String>> sharedDirectories = findSharedDirectories(args.paths);
|
||||
if (sharedDirectories == null) return 1;
|
||||
|
||||
return filesVisited == 0 ? 1 : 0;
|
||||
return display(System.out, args.verbose, sharedDirectories, keys, args.paths.size() == 1, !args.key.isEmpty());
|
||||
}
|
||||
|
||||
private void printConfiguration(PrintStream out, boolean verbose) {
|
||||
for (ConfigurationKey<?> key : ConfigurationKey.registeredKeys().values()) {
|
||||
private int generate(PrintStream out, boolean verbose, Collection<ConfigurationKey<?>> keys) {
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
String keyName = key.getKeyName();
|
||||
ConfigurationDataType type = key.getType();
|
||||
String description = key.getDescription();
|
||||
@@ -136,20 +143,220 @@ public class ConfigurationApp extends LombokApp {
|
||||
}
|
||||
out.println("##\n## Examples:\n#");
|
||||
out.printf("# clear %s\n", keyName);
|
||||
String exampleValue = type.getParser().exampleValue();
|
||||
if (type.isList()) {
|
||||
out.printf("# %s += %s\n", keyName, exampleValue(type));
|
||||
out.printf("# %s -= %s\n", keyName, exampleValue(type));
|
||||
out.printf("# %s += %s\n", keyName, exampleValue);
|
||||
out.printf("# %s -= %s\n", keyName, exampleValue);
|
||||
} else {
|
||||
out.printf("# %s = %s\n", keyName, exampleValue(type));
|
||||
out.printf("# %s = %s\n", keyName, exampleValue);
|
||||
}
|
||||
out.println("#\n");
|
||||
}
|
||||
if (!verbose) {
|
||||
out.println("Use --verbose for more information.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int display(PrintStream out, boolean verbose, TreeMap<URI, Set<String>> sharedDirectories, Collection<ConfigurationKey<?>> keys, boolean onlyOne, boolean explicitKeys) throws Exception {
|
||||
Set<String> none = sharedDirectories.remove(NO_CONFIG);
|
||||
if (none != null) {
|
||||
if (none.size() == 1) {
|
||||
out.printf("No 'lombok.config' found for '%s'.\n", none.iterator().next());
|
||||
} else {
|
||||
out.println("No 'lombok.config' found for: ");
|
||||
for (String path : none) out.printf("- %s\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> problems = new ArrayList<String>();
|
||||
ConfigurationProblemReporter reporter = new ConfigurationProblemReporter() {
|
||||
@Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
|
||||
problems.add(String.format("%s: %s (%s:%d)", problem, line, sourceDescription, lineNumber));
|
||||
}
|
||||
};
|
||||
|
||||
FileSystemSourceCache cache = new FileSystemSourceCache();
|
||||
boolean first = true;
|
||||
for (Entry<URI, Set<String>> entry : sharedDirectories.entrySet()) {
|
||||
if (!first) {
|
||||
out.print("\n\n");
|
||||
}
|
||||
Set<String> paths = entry.getValue();
|
||||
if (paths.size() == 1) {
|
||||
if (!onlyOne) out.printf("Configuration for '%s'.\n\n", paths.iterator().next());
|
||||
} else {
|
||||
out.printf("Configuration for:\n", paths.iterator().next());
|
||||
for (String path : paths) out.printf("- %s\n", path);
|
||||
out.println();
|
||||
}
|
||||
URI directory = entry.getKey();
|
||||
ConfigurationResolver resolver = new BubblingConfigurationResolver(cache.sourcesForDirectory(directory, reporter));
|
||||
Map<ConfigurationKey<?>, ? extends Collection<String>> traces = trace(keys, directory, verbose);
|
||||
boolean printed = false;
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
Object value = resolver.resolve(key);
|
||||
if (value == null || (value instanceof List<?> && ((List<?>)value).isEmpty())) {
|
||||
if (explicitKeys) {
|
||||
if (printed && verbose) out.println();
|
||||
printValue(out, key, value, verbose, traces.get(key));
|
||||
printed = true;
|
||||
}
|
||||
} else {
|
||||
if (printed && verbose) out.println();
|
||||
printValue(out, key, value, verbose, traces.get(key));
|
||||
printed = true;
|
||||
}
|
||||
}
|
||||
if (!printed) out.println("<default>");
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!problems.isEmpty()) {
|
||||
out.printf("\nProblems in the configuration files: \n");
|
||||
for (String problem : problems) out.printf("- %s\n", problem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void printValue(PrintStream out, ConfigurationKey<?> key, Object value, boolean verbose, Collection<String> history) {
|
||||
if (verbose) out.printf("# %s\n", key.getDescription());
|
||||
if (value == null) {
|
||||
out.printf("clear %s\n", key.getKeyName());
|
||||
} else if (value instanceof List<?>) {
|
||||
for (Object element : (List<?>)value) out.printf("%s += %s\n", key.getKeyName(), element);
|
||||
} else {
|
||||
out.printf("%s = %s\n", key.getKeyName(), value);
|
||||
}
|
||||
if (!verbose) return;
|
||||
for (String modification : history) out.printf("# %s\n", modification);
|
||||
}
|
||||
|
||||
private static final ConfigurationProblemReporter VOID = new ConfigurationProblemReporter() {
|
||||
@Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {}
|
||||
};
|
||||
|
||||
private Map<ConfigurationKey<?>, ? extends Collection<String>> trace(Collection<ConfigurationKey<?>> keys, URI directory, boolean verbose) throws Exception {
|
||||
if (!verbose) return Collections.emptyMap();
|
||||
|
||||
Map<ConfigurationKey<?>, List<String>> result = new HashMap<ConfigurationKey<?>, List<String>>();
|
||||
for (ConfigurationKey<?> key : keys) result.put(key, new ArrayList<String>());
|
||||
|
||||
boolean stopBubbling = false;
|
||||
String previousFileName = null;
|
||||
for (File currentDirectory = new File(directory); currentDirectory != null && !stopBubbling; currentDirectory = currentDirectory.getParentFile()) {
|
||||
File configFile = new File(currentDirectory, "lombok.config");
|
||||
if (!configFile.exists() || !configFile.isFile()) continue;
|
||||
|
||||
Map<ConfigurationKey<?>, List<String>> traces = trace(fileToString(configFile), configFile.getAbsolutePath(), keys);
|
||||
|
||||
stopBubbling = stopBubbling(traces.get(ConfigurationKeys.STOP_BUBBLING));
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
List<String> modifications = traces.get(key);
|
||||
if (modifications == null) {
|
||||
modifications = new ArrayList<String>();
|
||||
modifications.add(" <'" + key.getKeyName() + "' not mentioned>");
|
||||
}
|
||||
if (previousFileName != null) {
|
||||
modifications.add("");
|
||||
modifications.add(previousFileName + ":");
|
||||
}
|
||||
result.get(key).addAll(0, modifications);
|
||||
}
|
||||
previousFileName = configFile.getAbsolutePath();
|
||||
}
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
result.get(key).add(0, previousFileName + (stopBubbling ? " (stop bubbling):" : " (highest found):"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<ConfigurationKey<?>, List<String>> trace(String content, String contentDescription, final Collection<ConfigurationKey<?>> keys) {
|
||||
final Map<ConfigurationKey<?>, List<String>> result = new HashMap<ConfigurationKey<?>, List<String>>();
|
||||
|
||||
Collector collector = new Collector() {
|
||||
@Override public void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber) {
|
||||
trace(key, "clear " + key.getKeyName(), lineNumber);
|
||||
}
|
||||
|
||||
private String exampleValue(ConfigurationDataType type) {
|
||||
return type.getParser().exampleValue();
|
||||
@Override public void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
|
||||
trace(key, key.getKeyName() + " = " + value, lineNumber);
|
||||
}
|
||||
|
||||
@Override public void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
|
||||
trace(key, key.getKeyName() + " += " + value, lineNumber);
|
||||
}
|
||||
|
||||
@Override public void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
|
||||
trace(key, key.getKeyName() + " -= " + value, lineNumber);
|
||||
}
|
||||
|
||||
private void trace(ConfigurationKey<?> key, String message, int lineNumber) {
|
||||
if (!keys.contains(key)) return;
|
||||
List<String> traces = result.get(key);
|
||||
if (traces == null) {
|
||||
traces = new ArrayList<String>();
|
||||
result.put(key, traces);
|
||||
}
|
||||
traces.add(String.format("%4d: %s", lineNumber, message));
|
||||
}
|
||||
};
|
||||
new ConfigurationParser(VOID).parse(content, contentDescription, collector);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean stopBubbling(List<String> stops) {
|
||||
return stops != null && !stops.isEmpty() && stops.get(stops.size() -1).endsWith("true");
|
||||
}
|
||||
|
||||
private Collection<ConfigurationKey<?>> checkKeys(List<String> keyList) {
|
||||
Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys();
|
||||
if (keyList.isEmpty()) return registeredKeys.values();
|
||||
|
||||
Collection<ConfigurationKey<?>> keys = new ArrayList<ConfigurationKey<?>>();
|
||||
for (String keyName : keyList) {
|
||||
ConfigurationKey<?> key = registeredKeys.get(keyName);
|
||||
if (key == null) {
|
||||
System.err.printf("Unknown key '%s'\n", keyName);
|
||||
return null;
|
||||
}
|
||||
keys.remove(key);
|
||||
keys.add(key);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
private TreeMap<URI, Set<String>> findSharedDirectories(List<String> paths) {
|
||||
TreeMap<URI,Set<String>> sharedDirectories = new TreeMap<URI, Set<String>>(new Comparator<URI>() {
|
||||
@Override public int compare(URI o1, URI o2) {
|
||||
return o1.toString().compareTo(o2.toString());
|
||||
}
|
||||
});
|
||||
for (String path : paths) {
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
System.err.printf("File not found: '%s'\n", path);
|
||||
return null;
|
||||
}
|
||||
URI first = findFirstLombokDirectory(file);
|
||||
Set<String> sharedBy = sharedDirectories.get(first);
|
||||
if (sharedBy == null) {
|
||||
sharedBy = new TreeSet<String>();
|
||||
sharedDirectories.put(first, sharedBy);
|
||||
}
|
||||
sharedBy.add(path);
|
||||
}
|
||||
return sharedDirectories;
|
||||
}
|
||||
|
||||
private URI findFirstLombokDirectory(File file) {
|
||||
File current = new File(file.toURI().normalize());
|
||||
if (file.isFile()) current = current.getParentFile();
|
||||
while (current != null) {
|
||||
if (new File(current, "lombok.config").exists()) return current.toURI();
|
||||
current = current.getParentFile();
|
||||
}
|
||||
return NO_CONFIG;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ConfigurationParser {
|
||||
private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))");
|
||||
private static final Pattern NEWLINE_FINDER = Pattern.compile("^\\s*(.*?)\\s*$", Pattern.MULTILINE);
|
||||
|
||||
private ConfigurationProblemReporter reporter;
|
||||
|
||||
public ConfigurationParser(ConfigurationProblemReporter reporter) {
|
||||
if (reporter == null) throw new NullPointerException("reporter");
|
||||
this.reporter = reporter;
|
||||
}
|
||||
|
||||
public void parse(CharSequence content, String contentDescription, Collector collector) {
|
||||
Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys();
|
||||
int lineNumber = 0;
|
||||
Matcher lineMatcher = NEWLINE_FINDER.matcher(content);
|
||||
while (lineMatcher.find()) {
|
||||
CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1));
|
||||
lineNumber++;
|
||||
if (line.length() == 0 || line.charAt(0) == '#') continue;
|
||||
|
||||
Matcher matcher = LINE.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
reporter.report(contentDescription, "Invalid line", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
String operator = null;
|
||||
String keyName = null;
|
||||
String stringValue;
|
||||
if (matcher.group(1) == null) {
|
||||
keyName = matcher.group(2);
|
||||
operator = matcher.group(3);
|
||||
stringValue = matcher.group(4);
|
||||
} else {
|
||||
keyName = matcher.group(1);
|
||||
operator = "clear";
|
||||
stringValue = null;
|
||||
}
|
||||
ConfigurationKey<?> key = registeredKeys.get(keyName);
|
||||
if (key == null) {
|
||||
reporter.report(contentDescription, "Unknown key '" + keyName + "'", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
ConfigurationDataType type = key.getType();
|
||||
boolean listOperator = operator.equals("+=") || operator.equals("-=");
|
||||
if (listOperator && !type.isList()) {
|
||||
reporter.report(contentDescription, "'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear)", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
if (operator.equals("=") && type.isList()) {
|
||||
reporter.report(contentDescription, "'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
if (stringValue != null) try {
|
||||
value = type.getParser().parse(stringValue);
|
||||
} catch (Exception e) {
|
||||
reporter.report(contentDescription, "Error while parsing the value for '" + keyName + "' value '" + stringValue + "' (should be a " + type.getParser().description() + ")", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (operator.equals("clear")) {
|
||||
collector.clear(key, contentDescription, lineNumber);
|
||||
} else if (operator.equals("=")) {
|
||||
collector.set(key, value, contentDescription, lineNumber);
|
||||
} else if (operator.equals("+=")) {
|
||||
collector.add(key, value, contentDescription, lineNumber);
|
||||
} else {
|
||||
collector.remove(key, value, contentDescription, lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Collector {
|
||||
void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber);
|
||||
void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber);
|
||||
void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber);
|
||||
void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber);
|
||||
}
|
||||
}
|
||||
@@ -42,9 +42,17 @@ public class FileSystemSourceCache {
|
||||
|
||||
private final ConcurrentMap<File, Content> cache = new ConcurrentHashMap<File, Content>();
|
||||
|
||||
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, final ConfigurationProblemReporter reporter) {
|
||||
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, ConfigurationProblemReporter reporter) {
|
||||
if (javaFile == null) return Collections.emptyList();
|
||||
final File directory = new File(javaFile.normalize()).getParentFile();
|
||||
return sourcesForDirectory(new File(javaFile.normalize()).getParentFile(), reporter);
|
||||
}
|
||||
|
||||
public Iterable<ConfigurationSource> sourcesForDirectory(URI directory, ConfigurationProblemReporter reporter) {
|
||||
if (directory == null) return Collections.emptyList();
|
||||
return sourcesForDirectory(new File(directory.normalize()), reporter);
|
||||
}
|
||||
|
||||
private Iterable<ConfigurationSource> sourcesForDirectory(final File directory, final ConfigurationProblemReporter reporter) {
|
||||
return new Iterable<ConfigurationSource>() {
|
||||
@Override
|
||||
public Iterator<ConfigurationSource> iterator() {
|
||||
@@ -133,7 +141,7 @@ public class FileSystemSourceCache {
|
||||
}
|
||||
};
|
||||
|
||||
private String fileToString(File configFile) throws Exception {
|
||||
static String fileToString(File configFile) throws Exception {
|
||||
byte[] b = buffers.get();
|
||||
FileInputStream fis = new FileInputStream(configFile);
|
||||
try {
|
||||
|
||||
@@ -23,77 +23,57 @@ package lombok.core.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import lombok.core.configuration.ConfigurationParser.Collector;
|
||||
|
||||
public class StringConfigurationSource implements ConfigurationSource {
|
||||
private final Map<ConfigurationKey<?>, Result> values;
|
||||
|
||||
private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))");
|
||||
|
||||
private final Map<String, Result> values;
|
||||
|
||||
private static final Pattern NEWLINE_FINDER = Pattern.compile("^\\s*(.*?)\\s*$", Pattern.MULTILINE);
|
||||
public static ConfigurationSource forString(CharSequence content, ConfigurationProblemReporter reporter, String contentDescription) {
|
||||
if (reporter == null) throw new NullPointerException("reporter");
|
||||
|
||||
Map<String, Result> values = new TreeMap<String, Result>(String.CASE_INSENSITIVE_ORDER);
|
||||
final Map<ConfigurationKey<?>, Result> values = new HashMap<ConfigurationKey<?>, Result>();
|
||||
|
||||
Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys();
|
||||
int lineNumber = 0;
|
||||
Matcher lineMatcher = NEWLINE_FINDER.matcher(content);
|
||||
while (lineMatcher.find()) {
|
||||
CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1));
|
||||
lineNumber++;
|
||||
if (line.length() == 0 || line.charAt(0) == '#') continue;
|
||||
|
||||
Matcher matcher = LINE.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
reporter.report(contentDescription, "No valid line", lineNumber, line);
|
||||
continue;
|
||||
new ConfigurationParser(reporter).parse(content, contentDescription, new Collector() {
|
||||
@Override public void clear(ConfigurationKey<?> key, String contentDescription, int lineNumber) {
|
||||
values.put(key, new Result(null, true));
|
||||
}
|
||||
|
||||
String operator = null;
|
||||
String keyName = null;
|
||||
String value;
|
||||
if (matcher.group(1) == null) {
|
||||
keyName = matcher.group(2);
|
||||
operator = matcher.group(3);
|
||||
value = matcher.group(4);
|
||||
} else {
|
||||
keyName = matcher.group(1);
|
||||
operator = "clear";
|
||||
value = null;
|
||||
}
|
||||
ConfigurationKey<?> key = registeredKeys.get(keyName);
|
||||
if (key == null) {
|
||||
reporter.report(contentDescription, "Unknown key '" + keyName + "'", lineNumber, line);
|
||||
continue;
|
||||
@Override public void set(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
|
||||
values.put(key, new Result(value, true));
|
||||
}
|
||||
|
||||
ConfigurationDataType type = key.getType();
|
||||
boolean listOperator = operator.equals("+=") || operator.equals("-=");
|
||||
if (listOperator && !type.isList()) {
|
||||
reporter.report(contentDescription, "'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear)", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
if (operator.equals("=") && type.isList()) {
|
||||
reporter.report(contentDescription, "'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line);
|
||||
continue;
|
||||
@Override public void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
|
||||
modifyList(key, value, true);
|
||||
}
|
||||
|
||||
processResult(values, keyName, operator, value, type, reporter, contentDescription, lineNumber, line);
|
||||
}
|
||||
@Override public void remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
|
||||
modifyList(key, value, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void modifyList(ConfigurationKey<?> key, Object value, boolean add) {
|
||||
Result result = values.get(key);
|
||||
List<ListModification> list;
|
||||
if (result == null || result.getValue() == null) {
|
||||
list = new ArrayList<ConfigurationSource.ListModification>();
|
||||
values.put(key, new Result(list, result != null));
|
||||
} else {
|
||||
list = (List<ListModification>) result.getValue();
|
||||
}
|
||||
list.add(new ListModification(value, add));
|
||||
}
|
||||
});
|
||||
|
||||
return new StringConfigurationSource(values);
|
||||
}
|
||||
|
||||
private StringConfigurationSource(Map<String, Result> values) {
|
||||
this.values = new TreeMap<String, Result>(String.CASE_INSENSITIVE_ORDER);
|
||||
for (Entry<String, Result> entry : values.entrySet()) {
|
||||
private StringConfigurationSource(Map<ConfigurationKey<?>, Result> values) {
|
||||
this.values = new HashMap<ConfigurationKey<?>, Result>();
|
||||
for (Entry<ConfigurationKey<?>, Result> entry : values.entrySet()) {
|
||||
Result result = entry.getValue();
|
||||
if (result.getValue() instanceof List<?>) {
|
||||
this.values.put(entry.getKey(), new Result(Collections.unmodifiableList((List<?>) result.getValue()), result.isAuthoritative()));
|
||||
@@ -103,31 +83,8 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processResult(Map<String, Result> values, String keyName, String operator, String value, ConfigurationDataType type, ConfigurationProblemReporter reporter, String contentDescription, int lineNumber, CharSequence line) {
|
||||
Object element = null;
|
||||
if (value != null) try {
|
||||
element = type.getParser().parse(value);
|
||||
} catch (Exception e) {
|
||||
reporter.report(contentDescription, "Error while parsing the value for '" + keyName + "' value '" + value + "' (should be a " + type.getParser().description() + ")", lineNumber, line);
|
||||
return;
|
||||
}
|
||||
|
||||
if (operator.equals("clear") || operator.equals("=")) {
|
||||
if (element == null && type.isList()) {
|
||||
element = new ArrayList<ListModification>();
|
||||
}
|
||||
values.put(keyName, new Result(element, true));
|
||||
} else {
|
||||
Result result = values.get(keyName);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ListModification> list = result == null ? new ArrayList<ListModification>() : (List<ListModification>) result.getValue();
|
||||
if (result == null) values.put(keyName, new Result(list, false));
|
||||
list.add(new ListModification(element, operator.equals("+=")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result resolve(ConfigurationKey<?> key) {
|
||||
return values.get(key.getKeyName());
|
||||
return values.get(key);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.eclipse.handlers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import lombok.Lombok;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.LombokConfiguration;
|
||||
import lombok.core.PrintConfiguration;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
/**
|
||||
* Handles the {@code lombok.core.PrintConfiguration} annotation for eclipse.
|
||||
*/
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandlePrintConfiguration extends EclipseAnnotationHandler<PrintConfiguration> {
|
||||
public void handle(AnnotationValues<PrintConfiguration> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
PrintStream stream = System.out;
|
||||
String fileName = annotation.getInstance().outfile();
|
||||
if (fileName.length() > 0) try {
|
||||
stream = new PrintStream(new File(fileName));
|
||||
} catch (FileNotFoundException e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
try {
|
||||
LombokConfiguration.writeConfiguration(annotationNode.getAst(), stream);
|
||||
} finally {
|
||||
if (stream != System.out) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package lombok.javac.handlers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import lombok.Lombok;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.LombokConfiguration;
|
||||
import lombok.core.PrintConfiguration;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
import lombok.javac.JavacNode;
|
||||
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
|
||||
/**
|
||||
* Handles the {@code lombok.core.PrintConfiguration} annotation for javac.
|
||||
*/
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandlePrintConfiguration extends JavacAnnotationHandler<PrintConfiguration> {
|
||||
@Override public void handle(AnnotationValues<PrintConfiguration> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
PrintStream stream = System.out;
|
||||
String fileName = annotation.getInstance().outfile();
|
||||
if (fileName.length() > 0) try {
|
||||
stream = new PrintStream(new File(fileName));
|
||||
} catch (FileNotFoundException e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
|
||||
try {
|
||||
LombokConfiguration.writeConfiguration(annotationNode.getAst(), stream);
|
||||
} finally {
|
||||
if (stream != System.out) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
Lombok.sneakyThrow(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user