diff options
author | Roel Spilker <r.spilker@gmail.com> | 2014-01-17 21:13:37 +0100 |
---|---|---|
committer | Roel Spilker <r.spilker@gmail.com> | 2014-01-17 21:13:37 +0100 |
commit | fee535eae94557287c1762edd32374ddfc311367 (patch) | |
tree | 1463734034734721ff2f6c2a41cf1100f16603bb | |
parent | 610f250c1d84d98537ecd480ce19c4894bce503b (diff) | |
download | lombok-fee535eae94557287c1762edd32374ddfc311367.tar.gz lombok-fee535eae94557287c1762edd32374ddfc311367.tar.bz2 lombok-fee535eae94557287c1762edd32374ddfc311367.zip |
[configuration] Added @PrintConfiguration to print the combined interpreted configuration for a certain java file, improved problem reporting
9 files changed, 270 insertions, 27 deletions
diff --git a/src/core/lombok/core/LombokConfiguration.java b/src/core/lombok/core/LombokConfiguration.java index 0c391bf4..e64ddbbc 100644 --- a/src/core/lombok/core/LombokConfiguration.java +++ b/src/core/lombok/core/LombokConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Project Lombok Authors. + * Copyright (C) 2013-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 @@ -21,7 +21,12 @@ */ package lombok.core; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; + import lombok.core.configuration.BubblingConfigurationResolver; +import lombok.core.configuration.ConfigurationErrorReporter; import lombok.core.configuration.ConfigurationErrorReporterFactory; import lombok.core.configuration.ConfigurationKey; import lombok.core.configuration.FileSystemSourceCache; @@ -35,6 +40,48 @@ public class LombokConfiguration { } static <T> T read(ConfigurationKey<T> key, AST<?, ?, ?> ast) { - return new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), ConfigurationErrorReporterFactory.CONSOLE)).resolve(key); + return createResolver(ast, ConfigurationErrorReporterFactory.CONSOLE, cache).resolve(key); + } + + public static void writeConfiguration(AST<?, ?, ?> ast, PrintStream stream) { + final List<String> problems = new ArrayList<String>(); + ConfigurationErrorReporterFactory reporterFactory = new ConfigurationErrorReporterFactory() { + @Override public ConfigurationErrorReporter createFor(final String description) { + return new ConfigurationErrorReporter() { + @Override + public void report(String error, int lineNumber, String line) { + problems.add(String.format("%s (%s:%d)", error, description, lineNumber)); + } + }; + } + }; + + stream.printf("Combined lombok configuration for '%s'\n\n", ast.getAbsoluteFileLocation()); + // create a new empty 'cache' to make sure all problems are reported + FileSystemSourceCache sourceCache = new FileSystemSourceCache(); + BubblingConfigurationResolver resolver = createResolver(ast, reporterFactory, sourceCache); + for (ConfigurationKey<?> key : ConfigurationKey.registeredKeys()) { + 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 BubblingConfigurationResolver createResolver(AST<?, ?, ?> ast, ConfigurationErrorReporterFactory reporterFactory, FileSystemSourceCache sourceCache) { + return new BubblingConfigurationResolver(sourceCache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), reporterFactory)); + } + + public static void main(String[] args) { + System.out.println(" \n \n ".trim().length()); } } diff --git a/src/core/lombok/core/PrintConfiguration.java b/src/core/lombok/core/PrintConfiguration.java new file mode 100644 index 00000000..05d4ab4d --- /dev/null +++ b/src/core/lombok/core/PrintConfiguration.java @@ -0,0 +1,40 @@ +/* + * 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/ConfigurationErrorReporter.java b/src/core/lombok/core/configuration/ConfigurationErrorReporter.java index 26fa9cc2..901d313b 100644 --- a/src/core/lombok/core/configuration/ConfigurationErrorReporter.java +++ b/src/core/lombok/core/configuration/ConfigurationErrorReporter.java @@ -22,11 +22,5 @@ package lombok.core.configuration; public interface ConfigurationErrorReporter { - ConfigurationErrorReporter CONSOLE = new ConfigurationErrorReporter() { - @Override public void report(String error) { - System.err.println(error); - } - }; - - void report(String error); + void report(String error, int lineNumber, String line); }
\ No newline at end of file diff --git a/src/core/lombok/core/configuration/ConfigurationErrorReporterFactory.java b/src/core/lombok/core/configuration/ConfigurationErrorReporterFactory.java index b5bd9056..2ae1cb08 100644 --- a/src/core/lombok/core/configuration/ConfigurationErrorReporterFactory.java +++ b/src/core/lombok/core/configuration/ConfigurationErrorReporterFactory.java @@ -27,8 +27,8 @@ public interface ConfigurationErrorReporterFactory { public ConfigurationErrorReporter createFor(final String description) { return new ConfigurationErrorReporter() { @Override - public void report(String error) { - System.err.printf("Error in %s: %s\n", description, error); + public void report(String error, int lineNumber, String line) { + System.err.printf("%s (%s:%d)", error, description, lineNumber); } }; } diff --git a/src/core/lombok/core/configuration/ConfigurationKey.java b/src/core/lombok/core/configuration/ConfigurationKey.java index 81a5dfaa..f6711cca 100644 --- a/src/core/lombok/core/configuration/ConfigurationKey.java +++ b/src/core/lombok/core/configuration/ConfigurationKey.java @@ -22,7 +22,9 @@ package lombok.core.configuration; import java.util.Collections; +import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.TreeMap; /** @@ -48,7 +50,12 @@ public abstract class ConfigurationKey<T> { registerKey(keyName, type); } - + + private ConfigurationKey(String keyName, ConfigurationDataType type) { + this.keyName = keyName; + this.type = type; + } + public final String getKeyName() { return keyName; } @@ -87,13 +94,41 @@ public abstract class ConfigurationKey<T> { * Returns a copy of the currently registered keys. */ @SuppressWarnings("unchecked") - public static Map<String, ConfigurationDataType> registeredKeys() { + public static Map<String, ConfigurationDataType> registeredKeysAsMap() { synchronized (registeredKeys) { if (copy == null) copy = Collections.unmodifiableMap((Map<String, ConfigurationDataType>) registeredKeys.clone()); return copy; } } + public static Iterable<ConfigurationKey<?>> registeredKeys() { + class LocalConfigurationKey extends ConfigurationKey<Object> { + public LocalConfigurationKey(Entry<String, ConfigurationDataType> entry) { + super(entry.getKey(), entry.getValue()); + } + } + final Map<String, ConfigurationDataType> map = registeredKeysAsMap(); + return new Iterable<ConfigurationKey<?>>() { + @Override public Iterator<ConfigurationKey<?>> iterator() { + final Iterator<Entry<String, ConfigurationDataType>> entries = map.entrySet().iterator(); + return new Iterator<ConfigurationKey<?>>() { + @Override + public boolean hasNext() { + return entries.hasNext(); + } + + @Override public ConfigurationKey<?> next() { + return new LocalConfigurationKey(entries.next()); + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + private static void registerKey(String keyName, ConfigurationDataType type) { synchronized (registeredKeys) { ConfigurationDataType existingType = registeredKeys.get(keyName); diff --git a/src/core/lombok/core/configuration/FileSystemSourceCache.java b/src/core/lombok/core/configuration/FileSystemSourceCache.java index 822a5a2d..3c51fbff 100644 --- a/src/core/lombok/core/configuration/FileSystemSourceCache.java +++ b/src/core/lombok/core/configuration/FileSystemSourceCache.java @@ -114,7 +114,7 @@ public class FileSystemSourceCache { try { return StringConfigurationSource.forString(fileToString(configFile), reporter); } catch (Exception e) { - reporter.report("Exception while reading file: " + e.getMessage()); + reporter.report("Exception while reading file: " + e.getMessage(), 0, null); return null; } } diff --git a/src/core/lombok/core/configuration/StringConfigurationSource.java b/src/core/lombok/core/configuration/StringConfigurationSource.java index 3a6cd9e3..da01b6ee 100644 --- a/src/core/lombok/core/configuration/StringConfigurationSource.java +++ b/src/core/lombok/core/configuration/StringConfigurationSource.java @@ -36,17 +36,16 @@ public class StringConfigurationSource implements ConfigurationSource { private final Map<String, Result<?>> values; - public static ConfigurationSource forString(String content) { - return forString(content, ConfigurationErrorReporter.CONSOLE); - } - public static ConfigurationSource forString(String content, ConfigurationErrorReporter reporter) { if (reporter == null) throw new NullPointerException("reporter"); Map<String, Result<?>> values = new TreeMap<String, Result<?>>(String.CASE_INSENSITIVE_ORDER); - Map<String, ConfigurationDataType> registeredKeys = ConfigurationKey.registeredKeys(); - for (String line : content.trim().split("\\s*\\n\\s*")) { + Map<String, ConfigurationDataType> registeredKeys = ConfigurationKey.registeredKeysAsMap(); + int lineNumber = 0; + for (String line : content.split("\\n")) { + line = line.trim(); + lineNumber++; if (line.isEmpty() || line.startsWith("#")) continue; Matcher matcher = LINE.matcher(line); @@ -66,19 +65,19 @@ public class StringConfigurationSource implements ConfigurationSource { } ConfigurationDataType type = registeredKeys.get(keyName); if (type == null) { - reporter.report("Unknown key '" + keyName + "' on line: " + line); + reporter.report("Unknown key '" + keyName + "'", lineNumber, line); } else { boolean listOperator = operator.equals("+=") || operator.equals("-="); if (listOperator && !type.isList()) { - reporter.report("'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear): " + line); + reporter.report("'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear)", lineNumber, line); } else if (operator.equals("=") && type.isList()) { - reporter.report("'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead): " + line); + reporter.report("'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line); } else { - processResult(values, keyName, operator, value, type, reporter); + processResult(values, keyName, operator, value, type, reporter, lineNumber, line); } } } else { - reporter.report("No valid line: " + line); + reporter.report("No valid line", lineNumber, line); } } @@ -97,12 +96,12 @@ public class StringConfigurationSource implements ConfigurationSource { } } - private static void processResult(Map<String, Result<?>> values, String keyName, String operator, String value, ConfigurationDataType type, ConfigurationErrorReporter reporter) { + private static void processResult(Map<String, Result<?>> values, String keyName, String operator, String value, ConfigurationDataType type, ConfigurationErrorReporter reporter, int lineNumber, String line) { Object element = null; if (value != null) try { element = type.getParser().parse(value); } catch (Exception e) { - reporter.report("Error while parsing the value for '" + keyName + "' value '" + value + "' (should be a " + type.getParser().description() + ")"); + reporter.report("Error while parsing the value for '" + keyName + "' value '" + value + "' (should be a " + type.getParser().description() + ")", lineNumber, line); return; } diff --git a/src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java b/src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java new file mode 100644 index 00000000..e2bae525 --- /dev/null +++ b/src/core/lombok/eclipse/handlers/HandlePrintConfiguration.java @@ -0,0 +1,63 @@ +/* + * 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 new file mode 100644 index 00000000..dd0ef839 --- /dev/null +++ b/src/core/lombok/javac/handlers/HandlePrintConfiguration.java @@ -0,0 +1,65 @@ +/* + * 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); + } + } + } + } +} |