From 091d14bd73e4da1d2b3e34f0648eaa63473c3b1c Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Wed, 15 Jan 2020 00:53:20 +0100 Subject: Config import: Allow imports in lombok.config --- .../core/configuration/ConfigurationApp.java | 25 ++++----- .../core/configuration/ConfigurationParser.java | 62 ++++++++++++++++------ .../core/configuration/ConfigurationSource.java | 4 +- .../core/configuration/FileSystemSourceCache.java | 30 ++++++----- .../configuration/StringConfigurationSource.java | 19 +++---- test/core/src/lombok/LombokTestSource.java | 3 +- 6 files changed, 90 insertions(+), 53 deletions(-) diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java index 9cfec2e7..bbdea4ad 100644 --- a/src/core/lombok/core/configuration/ConfigurationApp.java +++ b/src/core/lombok/core/configuration/ConfigurationApp.java @@ -40,10 +40,6 @@ 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; import com.zwitserloot.cmdreader.CmdReader; @@ -54,6 +50,11 @@ import com.zwitserloot.cmdreader.Mandatory; import com.zwitserloot.cmdreader.Sequential; import com.zwitserloot.cmdreader.Shorthand; +import lombok.ConfigurationKeys; +import lombok.core.LombokApp; +import lombok.core.configuration.ConfigurationParser.Collector; +import lombok.core.configuration.ConfigurationParser.Context; + @ProviderFor(LombokApp.class) public class ConfigurationApp extends LombokApp { private static final URI NO_CONFIG = URI.create(""); @@ -258,7 +259,7 @@ public class ConfigurationApp extends LombokApp { File configFile = new File(currentDirectory, "lombok.config"); if (!configFile.exists() || !configFile.isFile()) continue; - Map, List> traces = trace(fileToString(configFile), configFile.getAbsolutePath(), keys); + Map, List> traces = trace(fileToString(configFile), Context.fromFile(configFile), keys); stopBubbling = stopBubbling(traces.get(ConfigurationKeys.STOP_BUBBLING)); for (ConfigurationKey key : keys) { @@ -287,23 +288,23 @@ public class ConfigurationApp extends LombokApp { return result; } - private Map, List> trace(String content, String contentDescription, final Collection> keys) { + private Map, List> trace(String content, Context context, final Collection> keys) { final Map, List> result = new HashMap, List>(); Collector collector = new Collector() { - @Override public void clear(ConfigurationKey key, String contentDescription, int lineNumber) { + @Override public void clear(ConfigurationKey key, Context context, int lineNumber) { trace(key, "clear " + key.getKeyName(), lineNumber); } - - @Override public void set(ConfigurationKey key, Object value, String contentDescription, int lineNumber) { + + @Override public void set(ConfigurationKey key, Object value, Context context, int lineNumber) { trace(key, key.getKeyName() + " = " + value, lineNumber); } - @Override public void add(ConfigurationKey key, Object value, String contentDescription, int lineNumber) { + @Override public void add(ConfigurationKey key, Object value, Context context, int lineNumber) { trace(key, key.getKeyName() + " += " + value, lineNumber); } - @Override public void remove(ConfigurationKey key, Object value, String contentDescription, int lineNumber) { + @Override public void remove(ConfigurationKey key, Object value, Context context, int lineNumber) { trace(key, key.getKeyName() + " -= " + value, lineNumber); } @@ -317,7 +318,7 @@ public class ConfigurationApp extends LombokApp { traces.add(String.format("%4d: %s", lineNumber, message)); } }; - new ConfigurationParser(VOID).parse(content, contentDescription, collector); + new ConfigurationParser(VOID).parse(content, context, collector); return result; } diff --git a/src/core/lombok/core/configuration/ConfigurationParser.java b/src/core/lombok/core/configuration/ConfigurationParser.java index e80793c1..0def6ce1 100644 --- a/src/core/lombok/core/configuration/ConfigurationParser.java +++ b/src/core/lombok/core/configuration/ConfigurationParser.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2016 The Project Lombok Authors. + * Copyright (C) 2014-2020 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,6 +21,7 @@ */ package lombok.core.configuration; +import java.io.File; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,6 +29,7 @@ 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("^[\t ]*(.*?)[\t\r ]*$", Pattern.MULTILINE); + private static final Pattern IMPORT = Pattern.compile("import\\s+(.*?)"); private ConfigurationProblemReporter reporter; @@ -36,20 +38,32 @@ public class ConfigurationParser { this.reporter = reporter; } - public void parse(CharSequence content, String contentDescription, Collector collector) { + public void parse(CharSequence content, Context context, Collector collector) { Map> registeredKeys = ConfigurationKey.registeredKeys(); int lineNumber = 0; Matcher lineMatcher = NEWLINE_FINDER.matcher(content); + boolean importsAllowed = true; while (lineMatcher.find()) { CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1)); lineNumber++; if (line.length() == 0 || line.charAt(0) == '#') continue; - + + Matcher importMatcher = IMPORT.matcher(line); + if (importMatcher.matches()) { + if (!importsAllowed) { + reporter.report(context.description(), "Imports are only allowed in the top of the file", lineNumber, line); + continue; + } +// collector.addImport(importMatcher.group(1), contentDescription, lineNumber); + continue; + } + Matcher matcher = LINE.matcher(line); if (!matcher.matches()) { - reporter.report(contentDescription, "Invalid line", lineNumber, line); + reporter.report(context.description(), "Invalid line", lineNumber, line); continue; } + importsAllowed = false; String operator = null; String keyName = null; @@ -65,18 +79,18 @@ public class ConfigurationParser { } ConfigurationKey key = registeredKeys.get(keyName); if (key == null) { - reporter.report(contentDescription, "Unknown key '" + keyName + "'", lineNumber, line); + reporter.report(context.description(), "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); + reporter.report(context.description(), "'" + 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); + reporter.report(context.description(), "'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line); continue; } @@ -84,26 +98,42 @@ public class ConfigurationParser { 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 " + type.getParser().exampleValue() + ")", lineNumber, line); + reporter.report(context.description(), "Error while parsing the value for '" + keyName + "' value '" + stringValue + "' (should be " + type.getParser().exampleValue() + ")", lineNumber, line); continue; } if (operator.equals("clear")) { - collector.clear(key, contentDescription, lineNumber); + collector.clear(key, context, lineNumber); } else if (operator.equals("=")) { - collector.set(key, value, contentDescription, lineNumber); + collector.set(key, value, context, lineNumber); } else if (operator.equals("+=")) { - collector.add(key, value, contentDescription, lineNumber); + collector.add(key, value, context, lineNumber); } else { - collector.remove(key, value, contentDescription, lineNumber); + collector.remove(key, value, context, 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); + void clear(ConfigurationKey key, Context context, int lineNumber); + void set(ConfigurationKey key, Object value, Context context, int lineNumber); + void add(ConfigurationKey key, Object value, Context context, int lineNumber); + void remove(ConfigurationKey key, Object value, Context context, int lineNumber); + } + + public static final class Context { + private final File file; + + public static Context fromFile(File file) { + return new Context(file); + } + + private Context(File file) { + this.file = file; + } + + public String description() { + return file.getAbsolutePath(); + } } } diff --git a/src/core/lombok/core/configuration/ConfigurationSource.java b/src/core/lombok/core/configuration/ConfigurationSource.java index 4a2b5808..1e7f9150 100644 --- a/src/core/lombok/core/configuration/ConfigurationSource.java +++ b/src/core/lombok/core/configuration/ConfigurationSource.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2020 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 @@ -47,7 +47,7 @@ public interface ConfigurationSource { } } - public static class ListModification { + public static final class ListModification { private final Object value; private final boolean added; diff --git a/src/core/lombok/core/configuration/FileSystemSourceCache.java b/src/core/lombok/core/configuration/FileSystemSourceCache.java index 8bc5050b..d0b51fa3 100644 --- a/src/core/lombok/core/configuration/FileSystemSourceCache.java +++ b/src/core/lombok/core/configuration/FileSystemSourceCache.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 The Project Lombok Authors. + * Copyright (C) 2014-2020 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 @@ -33,6 +33,7 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; import lombok.ConfigurationKeys; +import lombok.core.configuration.ConfigurationParser.Context; import lombok.core.configuration.ConfigurationSource.Result; import lombok.core.debug.ProblemReporter; @@ -43,7 +44,7 @@ public class FileSystemSourceCache { private static final long NEVER_CHECKED = -1; private static final long MISSING = -88; // Magic value; any lombok.config with this exact epochmillis last modified will never be read, so, let's ensure nobody accidentally has one with that exact last modified stamp. - private final ConcurrentMap dirCache = new ConcurrentHashMap(); // caches files (representing dirs) to the content object that tracks content. + private final ConcurrentMap fileCache = new ConcurrentHashMap(); // caches files to the content object that tracks content. private final ConcurrentMap uriCache = new ConcurrentHashMap(); // caches URIs of java source files to the dir that contains it. private volatile long lastCacheClear = System.currentTimeMillis(); @@ -54,7 +55,7 @@ public class FileSystemSourceCache { long delta = now - lastCacheClear; if (delta > FULL_CACHE_CLEAR_INTERVAL) { lastCacheClear = now; - dirCache.clear(); + fileCache.clear(); uriCache.clear(); } } @@ -149,10 +150,13 @@ public class FileSystemSourceCache { } ConfigurationSource getSourceForDirectory(File directory, ConfigurationProblemReporter reporter) { - long now = System.currentTimeMillis(); File configFile = new File(directory, LOMBOK_CONFIG_FILENAME); - - Content content = ensureContent(directory); + return getSourceForConfigFile(configFile, reporter); + } + + private ConfigurationSource getSourceForConfigFile(File configFile, ConfigurationProblemReporter reporter) { + long now = System.currentTimeMillis(); + Content content = ensureContent(configFile); synchronized (content) { if (content.lastChecked != NEVER_CHECKED && now - content.lastChecked < RECHECK_FILESYSTEM) { return content.source; @@ -165,21 +169,21 @@ public class FileSystemSourceCache { } } - private Content ensureContent(File directory) { - Content content = dirCache.get(directory); + private Content ensureContent(File configFile) { + Content content = fileCache.get(configFile); if (content != null) { return content; } - dirCache.putIfAbsent(directory, Content.empty()); - return dirCache.get(directory); + fileCache.putIfAbsent(configFile, Content.empty()); + return fileCache.get(configFile); } private ConfigurationSource parse(File configFile, ConfigurationProblemReporter reporter) { - String contentDescription = configFile.getAbsolutePath(); + Context context = Context.fromFile(configFile); try { - return StringConfigurationSource.forString(fileToString(configFile), reporter, contentDescription); + return StringConfigurationSource.forString(fileToString(configFile), reporter, context); } catch (Exception e) { - reporter.report(contentDescription, "Exception while reading file: " + e.getMessage(), 0, null); + reporter.report(context.description(), "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 abf6eea0..46ae4717 100644 --- a/src/core/lombok/core/configuration/StringConfigurationSource.java +++ b/src/core/lombok/core/configuration/StringConfigurationSource.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2020 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 @@ -29,28 +29,28 @@ import java.util.Map; import java.util.Map.Entry; import lombok.core.configuration.ConfigurationParser.Collector; +import lombok.core.configuration.ConfigurationParser.Context; public class StringConfigurationSource implements ConfigurationSource { private final Map, Result> values; - public static ConfigurationSource forString(CharSequence content, ConfigurationProblemReporter reporter, String contentDescription) { - + public static ConfigurationSource forString(CharSequence content, ConfigurationProblemReporter reporter, Context context) { final Map, Result> values = new HashMap, Result>(); - new ConfigurationParser(reporter).parse(content, contentDescription, new Collector() { - @Override public void clear(ConfigurationKey key, String contentDescription, int lineNumber) { + Collector collector = new Collector() { + @Override public void clear(ConfigurationKey key, Context context, int lineNumber) { values.put(key, new Result(null, true)); } - @Override public void set(ConfigurationKey key, Object value, String contentDescription, int lineNumber) { + @Override public void set(ConfigurationKey key, Object value, Context context, int lineNumber) { values.put(key, new Result(value, true)); } - @Override public void add(ConfigurationKey key, Object value, String contentDescription, int lineNumber) { + @Override public void add(ConfigurationKey key, Object value, Context context, int lineNumber) { modifyList(key, value, true); } - @Override public void remove(ConfigurationKey key, Object value, String contentDescription, int lineNumber) { + @Override public void remove(ConfigurationKey key, Object value, Context context, int lineNumber) { modifyList(key, value, false); } @@ -66,7 +66,8 @@ public class StringConfigurationSource implements ConfigurationSource { } list.add(new ListModification(value, add)); } - }); + }; + new ConfigurationParser(reporter).parse(content, context, collector); return new StringConfigurationSource(values); } diff --git a/test/core/src/lombok/LombokTestSource.java b/test/core/src/lombok/LombokTestSource.java index ba0aa972..d7d86a1b 100644 --- a/test/core/src/lombok/LombokTestSource.java +++ b/test/core/src/lombok/LombokTestSource.java @@ -41,6 +41,7 @@ import org.junit.Assert; import lombok.core.LombokImmutableList; import lombok.core.configuration.BubblingConfigurationResolver; +import lombok.core.configuration.ConfigurationParser.Context; import lombok.core.configuration.ConfigurationProblemReporter; import lombok.core.configuration.ConfigurationResolver; import lombok.core.configuration.StringConfigurationSource; @@ -244,7 +245,7 @@ public class LombokTestSource { } }; - this.configuration = new BubblingConfigurationResolver(Collections.singleton(StringConfigurationSource.forString(conf, reporter, file.getAbsolutePath()))); + this.configuration = new BubblingConfigurationResolver(Collections.singleton(StringConfigurationSource.forString(conf, reporter, Context.fromFile(file)))); this.formatPreferences = Collections.unmodifiableMap(formats); } -- cgit