[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:
Roel Spilker committed 2014-01-21 22:21:58 +01:00
1 parent ff01574864
commit ed061712f5
9 files changed
+388 -308

No files matched your search

+1 -34
View File
@@ -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);
}
}
}
}
}