mirror of
https://github.com/tiennm99/lombok.git
synced 2026-09-05 12:17:02 +00:00
Config import: move responsibilities
This commit is contained in:
@@ -26,6 +26,7 @@ import java.util.Collections;
|
||||
|
||||
import lombok.core.configuration.BubblingConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationKey;
|
||||
import lombok.core.configuration.ConfigurationParser;
|
||||
import lombok.core.configuration.ConfigurationProblemReporter;
|
||||
import lombok.core.configuration.ConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationResolverFactory;
|
||||
@@ -74,7 +75,7 @@ public class LombokConfiguration {
|
||||
private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() {
|
||||
return new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(URI sourceLocation) {
|
||||
return new BubblingConfigurationResolver(cache.sourcesForJavaFile(sourceLocation, ConfigurationProblemReporter.CONSOLE));
|
||||
return new BubblingConfigurationResolver(cache.sourcesForJavaFile(sourceLocation, new ConfigurationParser(ConfigurationProblemReporter.CONSOLE)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public class BubblingConfigurationResolver implements ConfigurationResolver {
|
||||
List<List<ListModification>> listModificationsList = null;
|
||||
outer:
|
||||
for (ConfigurationSource source : sources) {
|
||||
source.imports();
|
||||
Result result = source.resolve(key);
|
||||
if (result == null) continue;
|
||||
if (isList) {
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
package lombok.core.configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
@@ -188,6 +189,7 @@ public class ConfigurationApp extends LombokApp {
|
||||
};
|
||||
|
||||
FileSystemSourceCache cache = new FileSystemSourceCache();
|
||||
ConfigurationParser parser = new ConfigurationParser(reporter);
|
||||
boolean first = true;
|
||||
for (Entry<URI, Set<String>> entry : sharedDirectories.entrySet()) {
|
||||
if (!first) {
|
||||
@@ -202,7 +204,7 @@ public class ConfigurationApp extends LombokApp {
|
||||
out.println();
|
||||
}
|
||||
URI directory = entry.getKey();
|
||||
ConfigurationResolver resolver = new BubblingConfigurationResolver(cache.sourcesForDirectory(directory, reporter));
|
||||
ConfigurationResolver resolver = new BubblingConfigurationResolver(cache.sourcesForDirectory(directory, parser));
|
||||
Map<ConfigurationKey<?>, ? extends Collection<String>> traces = trace(keys, directory);
|
||||
boolean printed = false;
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
@@ -257,7 +259,7 @@ public class ConfigurationApp extends LombokApp {
|
||||
if (!configFile.exists() || !configFile.isFile()) continue;
|
||||
|
||||
ConfigurationFile context = ConfigurationFile.fromFile(configFile);
|
||||
Map<ConfigurationKey<?>, List<String>> traces = trace(context.contents(), context, keys);
|
||||
Map<ConfigurationKey<?>, List<String>> traces = trace(context, keys);
|
||||
|
||||
stopBubbling = stopBubbling(traces.get(ConfigurationKeys.STOP_BUBBLING));
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
@@ -286,10 +288,13 @@ public class ConfigurationApp extends LombokApp {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<ConfigurationKey<?>, List<String>> trace(String content, ConfigurationFile context, final Collection<ConfigurationKey<?>> keys) {
|
||||
private Map<ConfigurationKey<?>, List<String>> trace(ConfigurationFile context, final Collection<ConfigurationKey<?>> keys) throws IOException {
|
||||
final Map<ConfigurationKey<?>, List<String>> result = new HashMap<ConfigurationKey<?>, List<String>>();
|
||||
|
||||
Collector collector = new Collector() {
|
||||
@Override public void addImport(ConfigurationFile importFile, ConfigurationFile context, int lineNumber) {
|
||||
// TODO Trace imports
|
||||
}
|
||||
@Override public void clear(ConfigurationKey<?> key, ConfigurationFile context, int lineNumber) {
|
||||
trace(key, "clear " + key.getKeyName(), lineNumber);
|
||||
}
|
||||
@@ -315,8 +320,9 @@ public class ConfigurationApp extends LombokApp {
|
||||
}
|
||||
traces.add(String.format("%4d: %s", lineNumber, message));
|
||||
}
|
||||
|
||||
};
|
||||
new ConfigurationParser(VOID).parse(content, context, collector);
|
||||
new ConfigurationParser(VOID).parse(context, collector);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (C) 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
|
||||
* 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.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public abstract class ConfigurationFile {
|
||||
private static final ThreadLocal<byte[]> buffers = new ThreadLocal<byte[]>() {
|
||||
protected byte[] initialValue() {
|
||||
return new byte[65536];
|
||||
}
|
||||
};
|
||||
|
||||
private final String identifier;
|
||||
|
||||
public static ConfigurationFile fromFile(File file) {
|
||||
return new RegularConfigurationFile(file);
|
||||
}
|
||||
|
||||
public static ConfigurationFile fromCharSequence(String identifier, CharSequence contents, long lastModified) {
|
||||
return new CharSequenceConfigurationFile(identifier, contents, lastModified);
|
||||
}
|
||||
|
||||
private ConfigurationFile(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
abstract long getLastModifiedOrMissing();
|
||||
abstract boolean exists();
|
||||
abstract CharSequence contents() throws IOException;
|
||||
public abstract ConfigurationFile resolve(String path);
|
||||
|
||||
final String description() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object obj) {
|
||||
if (!(obj instanceof ConfigurationFile)) return false;
|
||||
return identifier.equals(((ConfigurationFile)obj).identifier);
|
||||
}
|
||||
|
||||
@Override public int hashCode() {
|
||||
return identifier.hashCode();
|
||||
}
|
||||
|
||||
public static long getLastModifiedOrMissing(File file) {
|
||||
if (!fileExists(file)) return FileSystemSourceCache.MISSING;
|
||||
return file.lastModified();
|
||||
}
|
||||
|
||||
private static boolean fileExists(File file) {
|
||||
return file.exists() && file.isFile();
|
||||
}
|
||||
|
||||
private static String read(InputStream is) throws IOException {
|
||||
byte[] b = buffers.get();
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
while (true) {
|
||||
int r = is.read(b);
|
||||
if (r == -1) break;
|
||||
out.write(b, 0, r);
|
||||
}
|
||||
return new String(out.toByteArray(), "UTF-8");
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class RegularConfigurationFile extends ConfigurationFile {
|
||||
private final File file;
|
||||
|
||||
private RegularConfigurationFile(File file) {
|
||||
super(file.getPath());
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override boolean exists() {
|
||||
return fileExists(file);
|
||||
}
|
||||
|
||||
public ConfigurationFile resolve(String path) {
|
||||
File file = resolveFile(path);
|
||||
return file == null ? null : fromFile(file);
|
||||
}
|
||||
|
||||
private File resolveFile(String path) {
|
||||
boolean absolute = false;
|
||||
int colon = path.indexOf(':');
|
||||
if (colon != -1) {
|
||||
if (colon != 1 || path.indexOf(':', colon + 1) != -1) return null;
|
||||
char firstCharacter = Character.toLowerCase(path.charAt(0));
|
||||
if (firstCharacter < 'a' || firstCharacter > 'z') return null;
|
||||
absolute = true;
|
||||
}
|
||||
if (path.charAt(0) == '/') absolute = true;
|
||||
try {
|
||||
return absolute ? new File(path) : new File(file.toURI().resolve(path));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
long getLastModifiedOrMissing() {
|
||||
return getLastModifiedOrMissing(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
CharSequence contents() throws IOException {
|
||||
return read(new FileInputStream(file));
|
||||
}
|
||||
}
|
||||
|
||||
private static class CharSequenceConfigurationFile extends ConfigurationFile {
|
||||
private final CharSequence contents;
|
||||
private final long lastModified;
|
||||
|
||||
private CharSequenceConfigurationFile(String identifier, CharSequence contents, long lastModified) {
|
||||
super(identifier);
|
||||
this.contents = contents;
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
@Override long getLastModifiedOrMissing() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@Override CharSequence contents() throws IOException {
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override boolean exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public ConfigurationFile resolve(String path) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -37,13 +38,17 @@ public class ConfigurationParser {
|
||||
this.reporter = reporter;
|
||||
}
|
||||
|
||||
public void parse(CharSequence content, ConfigurationFile context, Collector collector) {
|
||||
public void parse(ConfigurationFile context, Collector collector) {
|
||||
CharSequence contents = contents(context);
|
||||
if (contents == null) {
|
||||
return;
|
||||
}
|
||||
Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeys();
|
||||
int lineNumber = 0;
|
||||
Matcher lineMatcher = NEWLINE_FINDER.matcher(content);
|
||||
Matcher lineMatcher = NEWLINE_FINDER.matcher(contents);
|
||||
boolean importsAllowed = true;
|
||||
while (lineMatcher.find()) {
|
||||
CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1));
|
||||
CharSequence line = contents.subSequence(lineMatcher.start(1), lineMatcher.end(1));
|
||||
lineNumber++;
|
||||
if (line.length() == 0 || line.charAt(0) == '#') continue;
|
||||
|
||||
@@ -54,9 +59,16 @@ public class ConfigurationParser {
|
||||
continue;
|
||||
}
|
||||
String imported = importMatcher.group(1);
|
||||
if (!context.importResolves(imported)) {
|
||||
reporter.report(context.description(), "Imported file does not exist", lineNumber, line);
|
||||
ConfigurationFile importFile = context.resolve(imported);
|
||||
if (importFile == null) {
|
||||
reporter.report(context.description(), "Import is not valid", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
if (!importFile.exists()) {
|
||||
reporter.report(context.description(), "Imported file does not exist", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
collector.addImport(importFile, context, lineNumber);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -116,7 +128,17 @@ public class ConfigurationParser {
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence contents(ConfigurationFile context) {
|
||||
try {
|
||||
return context.contents();
|
||||
} catch (IOException e) {
|
||||
reporter.report(context.description(), "Exception while reading file: " + e.getMessage(), 0, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public interface Collector {
|
||||
void addImport(ConfigurationFile importFile, ConfigurationFile context, int lineNumber);
|
||||
void clear(ConfigurationKey<?> key, ConfigurationFile context, int lineNumber);
|
||||
void set(ConfigurationKey<?> key, Object value, ConfigurationFile context, int lineNumber);
|
||||
void add(ConfigurationKey<?> key, Object value, ConfigurationFile context, int lineNumber);
|
||||
|
||||
@@ -21,9 +21,12 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ConfigurationSource {
|
||||
|
||||
Result resolve(ConfigurationKey<?> key);
|
||||
List<ConfigurationFile> imports();
|
||||
|
||||
public static final class Result {
|
||||
private final Object value;
|
||||
|
||||
@@ -57,7 +57,7 @@ public class FileSystemSourceCache {
|
||||
}
|
||||
}
|
||||
|
||||
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, ConfigurationProblemReporter reporter) {
|
||||
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, ConfigurationParser parser) {
|
||||
if (javaFile == null) return Collections.emptyList();
|
||||
cacheClear();
|
||||
File dir = uriCache.get(javaFile);
|
||||
@@ -86,7 +86,7 @@ public class FileSystemSourceCache {
|
||||
|
||||
if (dir != null) {
|
||||
try {
|
||||
return sourcesForDirectory(dir, reporter);
|
||||
return sourcesForDirectory(dir, parser);
|
||||
} catch (Exception e) {
|
||||
// Especially for eclipse's sake, exceptions here make eclipse borderline unusable, so let's play nice.
|
||||
ProblemReporter.error("Can't resolve config stack for dir: " + dir.getAbsolutePath(), e);
|
||||
@@ -96,11 +96,11 @@ public class FileSystemSourceCache {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Iterable<ConfigurationSource> sourcesForDirectory(URI directory, ConfigurationProblemReporter reporter) {
|
||||
return sourcesForJavaFile(directory, reporter);
|
||||
public Iterable<ConfigurationSource> sourcesForDirectory(URI directory, ConfigurationParser parser) {
|
||||
return sourcesForJavaFile(directory, parser);
|
||||
}
|
||||
|
||||
private Iterable<ConfigurationSource> sourcesForDirectory(final File directory, final ConfigurationProblemReporter reporter) {
|
||||
private Iterable<ConfigurationSource> sourcesForDirectory(final File directory, final ConfigurationParser parser) {
|
||||
return new Iterable<ConfigurationSource>() {
|
||||
@Override
|
||||
public Iterator<ConfigurationSource> iterator() {
|
||||
@@ -127,7 +127,7 @@ public class FileSystemSourceCache {
|
||||
|
||||
private ConfigurationSource findNext() {
|
||||
while (currentDirectory != null && next == null) {
|
||||
next = getSourceForDirectory(currentDirectory, reporter);
|
||||
next = getSourceForDirectory(currentDirectory, parser);
|
||||
currentDirectory = currentDirectory.getParentFile();
|
||||
}
|
||||
if (next != null) {
|
||||
@@ -146,11 +146,11 @@ public class FileSystemSourceCache {
|
||||
};
|
||||
}
|
||||
|
||||
ConfigurationSource getSourceForDirectory(File directory, ConfigurationProblemReporter reporter) {
|
||||
return getSourceForConfigFile(ConfigurationFile.fromFile(new File(directory, LOMBOK_CONFIG_FILENAME)), reporter);
|
||||
ConfigurationSource getSourceForDirectory(File directory,ConfigurationParser parser) {
|
||||
return getSourceForConfigFile(ConfigurationFile.fromFile(new File(directory, LOMBOK_CONFIG_FILENAME)), parser);
|
||||
}
|
||||
|
||||
private ConfigurationSource getSourceForConfigFile(ConfigurationFile context, ConfigurationProblemReporter reporter) {
|
||||
private ConfigurationSource getSourceForConfigFile(ConfigurationFile context, ConfigurationParser parser) {
|
||||
long now = System.currentTimeMillis();
|
||||
Content content = ensureContent(context);
|
||||
synchronized (content) {
|
||||
@@ -160,7 +160,7 @@ public class FileSystemSourceCache {
|
||||
content.lastChecked = now;
|
||||
long previouslyModified = content.lastModified;
|
||||
content.lastModified = context.getLastModifiedOrMissing();
|
||||
if (content.lastModified != previouslyModified) content.source = content.lastModified == MISSING ? null : parse(context, reporter);
|
||||
if (content.lastModified != previouslyModified) content.source = content.lastModified == MISSING ? null : parse(context, parser);
|
||||
return content.source;
|
||||
}
|
||||
}
|
||||
@@ -174,13 +174,8 @@ public class FileSystemSourceCache {
|
||||
return fileCache.get(context);
|
||||
}
|
||||
|
||||
private ConfigurationSource parse(ConfigurationFile context, ConfigurationProblemReporter reporter) {
|
||||
try {
|
||||
return StringConfigurationSource.forString(context.contents(), reporter, context);
|
||||
} catch (Exception e) {
|
||||
reporter.report(context.description(), "Exception while reading file: " + e.getMessage(), 0, null);
|
||||
return null;
|
||||
}
|
||||
private ConfigurationSource parse(ConfigurationFile context, ConfigurationParser parser) {
|
||||
return SingleConfigurationSource.parse(context, parser);
|
||||
}
|
||||
|
||||
private static class Content {
|
||||
|
||||
+17
-6
@@ -30,13 +30,18 @@ import java.util.Map.Entry;
|
||||
|
||||
import lombok.core.configuration.ConfigurationParser.Collector;
|
||||
|
||||
public class StringConfigurationSource implements ConfigurationSource {
|
||||
public final class SingleConfigurationSource implements ConfigurationSource {
|
||||
private final Map<ConfigurationKey<?>, Result> values;
|
||||
private final List<ConfigurationFile> imports;
|
||||
|
||||
public static ConfigurationSource forString(CharSequence content, ConfigurationProblemReporter reporter, ConfigurationFile context) {
|
||||
public static ConfigurationSource parse(ConfigurationFile context, ConfigurationParser parser) {
|
||||
final Map<ConfigurationKey<?>, Result> values = new HashMap<ConfigurationKey<?>, Result>();
|
||||
|
||||
final List<ConfigurationFile> imports = new ArrayList<ConfigurationFile>();
|
||||
Collector collector = new Collector() {
|
||||
@Override public void addImport(ConfigurationFile importFile, ConfigurationFile context, int lineNumber) {
|
||||
imports.add(importFile);
|
||||
}
|
||||
|
||||
@Override public void clear(ConfigurationKey<?> key, ConfigurationFile context, int lineNumber) {
|
||||
values.put(key, new Result(null, true));
|
||||
}
|
||||
@@ -66,11 +71,11 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
list.add(new ListModification(value, add));
|
||||
}
|
||||
};
|
||||
new ConfigurationParser(reporter).parse(content, context, collector);
|
||||
return new StringConfigurationSource(values);
|
||||
parser.parse(context, collector);
|
||||
return new SingleConfigurationSource(values, imports);
|
||||
}
|
||||
|
||||
private StringConfigurationSource(Map<ConfigurationKey<?>, Result> values) {
|
||||
private SingleConfigurationSource(Map<ConfigurationKey<?>, Result> values, List<ConfigurationFile> imports) {
|
||||
this.values = new HashMap<ConfigurationKey<?>, Result>();
|
||||
for (Entry<ConfigurationKey<?>, Result> entry : values.entrySet()) {
|
||||
Result result = entry.getValue();
|
||||
@@ -80,10 +85,16 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
this.values.put(entry.getKey(), result);
|
||||
}
|
||||
}
|
||||
this.imports = Collections.unmodifiableList(imports);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result resolve(ConfigurationKey<?> key) {
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigurationFile> imports() {
|
||||
return imports;
|
||||
}
|
||||
}
|
||||
@@ -42,9 +42,10 @@ import org.junit.Assert;
|
||||
import lombok.core.LombokImmutableList;
|
||||
import lombok.core.configuration.BubblingConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationFile;
|
||||
import lombok.core.configuration.ConfigurationParser;
|
||||
import lombok.core.configuration.ConfigurationProblemReporter;
|
||||
import lombok.core.configuration.ConfigurationResolver;
|
||||
import lombok.core.configuration.StringConfigurationSource;
|
||||
import lombok.core.configuration.SingleConfigurationSource;
|
||||
|
||||
public class LombokTestSource {
|
||||
private final File file;
|
||||
@@ -244,8 +245,7 @@ public class LombokTestSource {
|
||||
Assert.fail("Problem on directive line: " + problem + " at conf line #" + lineNumber + " (" + line + ")");
|
||||
}
|
||||
};
|
||||
|
||||
this.configuration = new BubblingConfigurationResolver(Collections.singleton(StringConfigurationSource.forString(conf, reporter, ConfigurationFile.fromFile(file))));
|
||||
this.configuration = new BubblingConfigurationResolver(Collections.singleton(SingleConfigurationSource.parse(ConfigurationFile.fromCharSequence(file.getAbsoluteFile().getPath(), conf, ConfigurationFile.getLastModifiedOrMissing(file)), new ConfigurationParser(reporter))));
|
||||
this.formatPreferences = Collections.unmodifiableMap(formats);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user