aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoel Spilker <r.spilker@gmail.com>2014-01-21 22:21:58 +0100
committerRoel Spilker <r.spilker@gmail.com>2014-01-21 22:21:58 +0100
commited061712f556161d8a6eb1400fffbaace8dd1ac0 (patch)
tree92dcf0e98b946b6f8216387df12ee61021f3d52f
parentff0157486440f74c28f96e3708ed9e958086d65b (diff)
downloadlombok-ed061712f556161d8a6eb1400fffbaace8dd1ac0.tar.gz
lombok-ed061712f556161d8a6eb1400fffbaace8dd1ac0.tar.bz2
lombok-ed061712f556161d8a6eb1400fffbaace8dd1ac0.zip
[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.
-rw-r--r--src/core/lombok/core/LombokConfiguration.java35
-rw-r--r--src/core/lombok/core/PrintConfiguration.java40
-rw-r--r--src/core/lombok/core/configuration/BubblingConfigurationResolver.java2
-rw-r--r--src/core/lombok/core/configuration/ConfigurationApp.java261
-rw-r--r--src/core/lombok/core/configuration/ConfigurationParser.java109
-rw-r--r--src/core/lombok/core/configuration/FileSystemSourceCache.java14
-rw-r--r--src/core/lombok/core/configuration/StringConfigurationSource.java107
-rw-r--r--src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java63
-rw-r--r--src/core/lombok/javac/handlers/HandlePrintConfiguration.java65
9 files changed, 388 insertions, 308 deletions
diff --git a/src/core/lombok/core/LombokConfiguration.java b/src/core/lombok/core/LombokConfiguration.java
index f2661a53..137a8a83 100644
--- a/src/core/lombok/core/LombokConfiguration.java
+++ b/src/core/lombok/core/LombokConfiguration.java
@@ -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) {
diff --git a/src/core/lombok/core/PrintConfiguration.java b/src/core/lombok/core/PrintConfiguration.java
deleted file mode 100644
index 05d4ab4d..00000000
--- a/src/core/lombok/core/PrintConfiguration.java
+++ /dev/null
@@ -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 "";
-}
diff --git a/src/core/lombok/core/configuration/BubblingConfigurationResolver.java b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
index 623c6cc0..f96b4468 100644
--- a/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
+++ b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
@@ -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());
diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java
index e7f438d7..fe7f7ad4 100644
--- a/src/core/lombok/core/configuration/ConfigurationApp.java
+++ b/src/core/lombok/core/configuration/ConfigurationApp.java
@@ -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);
-
- return filesVisited == 0 ? 1 : 0;
+ TreeMap<URI, Set<String>> sharedDirectories = findSharedDirectories(args.paths);
+ if (sharedDirectories == null) return 1;
+
+ 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;
}
}
diff --git a/src/core/lombok/core/configuration/ConfigurationParser.java b/src/core/lombok/core/configuration/ConfigurationParser.java
new file mode 100644
index 00000000..e11802ca
--- /dev/null
+++ b/src/core/lombok/core/configuration/ConfigurationParser.java
@@ -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);
+ }
+}
diff --git a/src/core/lombok/core/configuration/FileSystemSourceCache.java b/src/core/lombok/core/configuration/FileSystemSourceCache.java
index 22d458b6..03e6d338 100644
--- a/src/core/lombok/core/configuration/FileSystemSourceCache.java
+++ b/src/core/lombok/core/configuration/FileSystemSourceCache.java
@@ -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 {
diff --git a/src/core/lombok/core/configuration/StringConfigurationSource.java b/src/core/lombok/core/configuration/StringConfigurationSource.java
index aad3d0c8..dd2f0319 100644
--- a/src/core/lombok/core/configuration/StringConfigurationSource.java
+++ b/src/core/lombok/core/configuration/StringConfigurationSource.java
@@ -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;
+ @Override public void add(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ modifyList(key, value, true);
}
- 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 remove(ConfigurationKey<?> key, Object value, String contentDescription, int lineNumber) {
+ modifyList(key, value, false);
}
- processResult(values, keyName, operator, value, type, reporter, contentDescription, lineNumber, line);
- }
+ @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);
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java b/src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java
deleted file mode 100644
index e2bae525..00000000
--- a/src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java
+++ /dev/null
@@ -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);
- }
- }
- }
- }
-}
diff --git a/src/core/lombok/javac/handlers/HandlePrintConfiguration.java b/src/core/lombok/javac/handlers/HandlePrintConfiguration.java
deleted file mode 100644
index dd0ef839..00000000
--- a/src/core/lombok/javac/handlers/HandlePrintConfiguration.java
+++ /dev/null
@@ -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);
- }
- }
- }
- }
-}