mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-14 14:17:48 +00:00
[configuration] added facilities to override conf file resolution for test cases, and added first tests to test implementations of configuration-based stuff (FlagUsages, specifically). Error reporter has been refactored.
This commit is contained in:
1 parent
deb694033a
commit
d6ca8d5e81
12 files changed
+103
-70
No files matched your search
@@ -26,40 +26,40 @@ 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.ConfigurationProblemReporter;
|
||||
import lombok.core.configuration.ConfigurationKey;
|
||||
import lombok.core.configuration.ConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationResolverFactory;
|
||||
import lombok.core.configuration.FileSystemSourceCache;
|
||||
|
||||
public class LombokConfiguration {
|
||||
|
||||
private static FileSystemSourceCache cache = new FileSystemSourceCache();
|
||||
private static ConfigurationResolverFactory configurationResolverFactory = createFileSystemBubblingResolverFactory();
|
||||
|
||||
private LombokConfiguration() {
|
||||
// prevent instantiation
|
||||
}
|
||||
|
||||
public static void overrideConfigurationResolverFactory(ConfigurationResolverFactory crf) {
|
||||
configurationResolverFactory = crf == null ? createFileSystemBubblingResolverFactory() : crf;
|
||||
}
|
||||
|
||||
static <T> T read(ConfigurationKey<T> key, AST<?, ?, ?> ast) {
|
||||
return createResolver(ast, ConfigurationErrorReporterFactory.CONSOLE, cache).resolve(key);
|
||||
return configurationResolverFactory.createResolver(ast).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));
|
||||
}
|
||||
};
|
||||
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
|
||||
FileSystemSourceCache sourceCache = new FileSystemSourceCache();
|
||||
BubblingConfigurationResolver resolver = createResolver(ast, reporterFactory, sourceCache);
|
||||
cache.reset();
|
||||
ConfigurationResolver resolver = new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), reporter));
|
||||
for (ConfigurationKey<?> key : ConfigurationKey.registeredKeys()) {
|
||||
Object value = resolver.resolve(key);
|
||||
if (value == null || value instanceof List<?> && ((List<?>)value).isEmpty()) continue;
|
||||
@@ -77,11 +77,11 @@ public class LombokConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() {
|
||||
return new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
|
||||
return new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), ConfigurationProblemReporter.CONSOLE));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+6
-12
@@ -21,18 +21,12 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
public interface ConfigurationErrorReporterFactory {
|
||||
ConfigurationErrorReporterFactory CONSOLE = new ConfigurationErrorReporterFactory() {
|
||||
@Override
|
||||
public ConfigurationErrorReporter createFor(final String description) {
|
||||
return new ConfigurationErrorReporter() {
|
||||
@Override
|
||||
public void report(String error, int lineNumber, String line) {
|
||||
System.err.printf("%s (%s:%d)", error, description, lineNumber);
|
||||
}
|
||||
};
|
||||
public interface ConfigurationProblemReporter {
|
||||
void report(String sourceDescription, String problem, int lineNumber, CharSequence line);
|
||||
|
||||
ConfigurationProblemReporter CONSOLE = new ConfigurationProblemReporter() {
|
||||
@Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
|
||||
System.err.printf("%s (%s:%d)\n", problem, sourceDescription, lineNumber);
|
||||
}
|
||||
};
|
||||
|
||||
ConfigurationErrorReporter createFor(String description);
|
||||
}
|
||||
+5
-3
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
public interface ConfigurationErrorReporter {
|
||||
void report(String error, int lineNumber, String line);
|
||||
}
|
||||
import lombok.core.AST;
|
||||
|
||||
public interface ConfigurationResolverFactory {
|
||||
ConfigurationResolver createResolver(AST<?, ?, ?> ast);
|
||||
}
|
||||
@@ -36,14 +36,13 @@ import lombok.ConfigurationKeys;
|
||||
import lombok.core.configuration.ConfigurationSource.Result;
|
||||
|
||||
public class FileSystemSourceCache {
|
||||
|
||||
private static String LOMBOK_CONFIG_FILENAME = "lombok.config";
|
||||
private static final long RECHECK_FILESYSTEM = TimeUnit.SECONDS.toMillis(2);
|
||||
private static final long MISSING = -1;
|
||||
|
||||
private final ConcurrentMap<File, Content> cache = new ConcurrentHashMap<File, Content>();
|
||||
|
||||
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, final ConfigurationErrorReporterFactory reporterFactory) {
|
||||
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, final ConfigurationProblemReporter reporter) {
|
||||
if (javaFile == null) return Collections.emptyList();
|
||||
final File directory = new File(javaFile.normalize()).getParentFile();
|
||||
return new Iterable<ConfigurationSource>() {
|
||||
@@ -72,7 +71,7 @@ public class FileSystemSourceCache {
|
||||
|
||||
private ConfigurationSource findNext() {
|
||||
while (currentDirectory != null && next == null) {
|
||||
next = getSourceForDirectory(currentDirectory, reporterFactory);
|
||||
next = getSourceForDirectory(currentDirectory, reporter);
|
||||
currentDirectory = currentDirectory.getParentFile();
|
||||
}
|
||||
if (next != null) {
|
||||
@@ -91,7 +90,7 @@ public class FileSystemSourceCache {
|
||||
};
|
||||
}
|
||||
|
||||
ConfigurationSource getSourceForDirectory(File directory, ConfigurationErrorReporterFactory reporterFactory) {
|
||||
ConfigurationSource getSourceForDirectory(File directory, ConfigurationProblemReporter reporter) {
|
||||
if (!directory.exists() && !directory.isDirectory()) throw new IllegalArgumentException("Not a directory: " + directory);
|
||||
long now = System.currentTimeMillis();
|
||||
File configFile = new File(directory, LOMBOK_CONFIG_FILENAME);
|
||||
@@ -104,7 +103,7 @@ public class FileSystemSourceCache {
|
||||
content.lastChecked = now;
|
||||
long previouslyModified = content.lastModified;
|
||||
content.lastModified = getLastModified(configFile);
|
||||
if (content.lastModified != previouslyModified) content.source = content.lastModified == MISSING ? null : parse(configFile, reporterFactory);
|
||||
if (content.lastModified != previouslyModified) content.source = content.lastModified == MISSING ? null : parse(configFile, reporter);
|
||||
return content.source;
|
||||
}
|
||||
}
|
||||
@@ -118,12 +117,12 @@ public class FileSystemSourceCache {
|
||||
return cache.get(directory);
|
||||
}
|
||||
|
||||
private ConfigurationSource parse(File configFile, ConfigurationErrorReporterFactory reporterFactory) {
|
||||
ConfigurationErrorReporter reporter = reporterFactory.createFor(configFile.getAbsolutePath());
|
||||
private ConfigurationSource parse(File configFile, ConfigurationProblemReporter reporter) {
|
||||
String contentDescription = configFile.getAbsolutePath();
|
||||
try {
|
||||
return StringConfigurationSource.forString(fileToString(configFile), reporter);
|
||||
return StringConfigurationSource.forString(fileToString(configFile), reporter, contentDescription);
|
||||
} catch (Exception e) {
|
||||
reporter.report("Exception while reading file: " + e.getMessage(), 0, null);
|
||||
reporter.report(contentDescription, "Exception while reading file: " + e.getMessage(), 0, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -170,4 +169,8 @@ public class FileSystemSourceCache {
|
||||
return new Content(null, MISSING, MISSING);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
cache.clear();
|
||||
}
|
||||
}
|
||||
@@ -36,21 +36,23 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
|
||||
private final Map<String, Result> values;
|
||||
|
||||
public static ConfigurationSource forString(String content, ConfigurationErrorReporter reporter) {
|
||||
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);
|
||||
|
||||
Map<String, ConfigurationKey<?>> registeredKeys = ConfigurationKey.registeredKeysMap();
|
||||
int lineNumber = 0;
|
||||
for (String line : content.split("\\n")) {
|
||||
line = line.trim();
|
||||
Matcher lineMatcher = NEWLINE_FINDER.matcher(content);
|
||||
while (lineMatcher.find()) {
|
||||
CharSequence line = content.subSequence(lineMatcher.start(1), lineMatcher.end(1));
|
||||
lineNumber++;
|
||||
if (line.isEmpty() || line.startsWith("#")) continue;
|
||||
if (line.length() == 0 || line.charAt(0) == '#') continue;
|
||||
|
||||
Matcher matcher = LINE.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
reporter.report("No valid line", lineNumber, line);
|
||||
reporter.report(contentDescription, "No valid line", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -68,22 +70,22 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
}
|
||||
ConfigurationKey<?> key = registeredKeys.get(keyName);
|
||||
if (key == null) {
|
||||
reporter.report("Unknown key '" + keyName + "'", lineNumber, line);
|
||||
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("'" + keyName + "' is not a list and doesn't support " + operator + " (only = and clear)", lineNumber, line);
|
||||
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("'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line);
|
||||
reporter.report(contentDescription, "'" + keyName + "' is a list and cannot be assigned to (use +=, -= and clear instead)", lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
|
||||
processResult(values, keyName, operator, value, type, reporter, lineNumber, line);
|
||||
processResult(values, keyName, operator, value, type, reporter, contentDescription, lineNumber, line);
|
||||
}
|
||||
|
||||
return new StringConfigurationSource(values);
|
||||
@@ -101,12 +103,12 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processResult(Map<String, Result> values, String keyName, String operator, String value, ConfigurationDataType type, ConfigurationErrorReporter reporter, int lineNumber, String line) {
|
||||
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("Error while parsing the value for '" + keyName + "' value '" + value + "' (should be a " + type.getParser().description() + ")", lineNumber, line);
|
||||
reporter.report(contentDescription, "Error while parsing the value for '" + keyName + "' value '" + value + "' (should be a " + type.getParser().description() + ")", lineNumber, line);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,11 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.core.AST;
|
||||
import lombok.core.LombokConfiguration;
|
||||
import lombok.core.LombokImmutableList;
|
||||
import lombok.core.configuration.ConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationResolverFactory;
|
||||
import lombok.javac.CapturingDiagnosticListener.CompilerMessage;
|
||||
|
||||
public abstract class AbstractRunTests {
|
||||
@@ -47,7 +51,7 @@ public abstract class AbstractRunTests {
|
||||
}
|
||||
|
||||
public boolean compareFile(DirectoryRunner.TestParams params, File file) throws Throwable {
|
||||
LombokTestSource sourceDirectives = LombokTestSource.readDirectives(file);
|
||||
final LombokTestSource sourceDirectives = LombokTestSource.readDirectives(file);
|
||||
if (sourceDirectives.isIgnore()) return false;
|
||||
|
||||
String fileName = file.getName();
|
||||
@@ -57,13 +61,20 @@ public abstract class AbstractRunTests {
|
||||
|
||||
LinkedHashSet<CompilerMessage> messages = new LinkedHashSet<CompilerMessage>();
|
||||
StringWriter writer = new StringWriter();
|
||||
transformCode(messages, writer, file, sourceDirectives.getConfLines());
|
||||
|
||||
LombokConfiguration.overrideConfigurationResolverFactory(new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
|
||||
return sourceDirectives.getConfiguration();
|
||||
}
|
||||
});
|
||||
|
||||
transformCode(messages, writer, file);
|
||||
|
||||
compare(file.getName(), expected, writer.toString(), messages, params.printErrors());
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void transformCode(Collection<CompilerMessage> messages, StringWriter result, File file, LombokImmutableList<String> confLines) throws Throwable;
|
||||
protected abstract void transformCode(Collection<CompilerMessage> messages, StringWriter result, File file) throws Throwable;
|
||||
|
||||
protected String readFile(File file) throws IOException {
|
||||
BufferedReader reader;
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -35,6 +36,10 @@ import java.util.regex.Pattern;
|
||||
import org.junit.Assert;
|
||||
|
||||
import lombok.core.LombokImmutableList;
|
||||
import lombok.core.configuration.BubblingConfigurationResolver;
|
||||
import lombok.core.configuration.ConfigurationProblemReporter;
|
||||
import lombok.core.configuration.ConfigurationResolver;
|
||||
import lombok.core.configuration.StringConfigurationSource;
|
||||
|
||||
public class LombokTestSource {
|
||||
private final File file;
|
||||
@@ -42,7 +47,7 @@ public class LombokTestSource {
|
||||
private final LombokImmutableList<CompilerMessageMatcher> messages;
|
||||
private final boolean ignore;
|
||||
private final int versionLowerLimit, versionUpperLimit;
|
||||
private final LombokImmutableList<String> confLines;
|
||||
private final ConfigurationResolver configuration;
|
||||
|
||||
public boolean versionWithinLimit(int version) {
|
||||
return version >= versionLowerLimit && version <= versionUpperLimit;
|
||||
@@ -64,8 +69,8 @@ public class LombokTestSource {
|
||||
return ignore;
|
||||
}
|
||||
|
||||
public LombokImmutableList<String> getConfLines() {
|
||||
return confLines;
|
||||
public ConfigurationResolver getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
private static final Pattern VERSION_STYLE_1 = Pattern.compile("^(\\d+)$");
|
||||
@@ -106,7 +111,7 @@ public class LombokTestSource {
|
||||
this.content = content;
|
||||
this.messages = messages == null ? LombokImmutableList.<CompilerMessageMatcher>of() : LombokImmutableList.copyOf(messages);
|
||||
|
||||
List<String> conf = new ArrayList<String>();
|
||||
StringBuilder conf = new StringBuilder();
|
||||
int versionLower = 0;
|
||||
int versionUpper = Integer.MAX_VALUE;
|
||||
boolean ignore = false;
|
||||
@@ -132,7 +137,7 @@ public class LombokTestSource {
|
||||
|
||||
if (lc.startsWith("conf:")) {
|
||||
String confLine = directive.substring(5).trim();
|
||||
conf.add(confLine);
|
||||
conf.append(confLine).append("\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -143,7 +148,13 @@ public class LombokTestSource {
|
||||
this.versionLowerLimit = versionLower;
|
||||
this.versionUpperLimit = versionUpper;
|
||||
this.ignore = ignore;
|
||||
this.confLines = LombokImmutableList.copyOf(conf);
|
||||
ConfigurationProblemReporter reporter = new ConfigurationProblemReporter() {
|
||||
@Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
|
||||
Assert.fail("Problem on directive line: " + problem + " at conf line #" + lineNumber + " (" + line + ")");
|
||||
}
|
||||
};
|
||||
|
||||
this.configuration = new BubblingConfigurationResolver(Collections.singleton(StringConfigurationSource.forString(conf, reporter, file.getAbsolutePath())));
|
||||
}
|
||||
|
||||
public static LombokTestSource readDirectives(File file) throws IOException {
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.io.StringWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
import lombok.core.LombokImmutableList;
|
||||
import lombok.delombok.Delombok;
|
||||
import lombok.javac.CapturingDiagnosticListener;
|
||||
import lombok.javac.CapturingDiagnosticListener.CompilerMessage;
|
||||
@@ -35,15 +34,13 @@ public class RunTestsViaDelombok extends AbstractRunTests {
|
||||
private Delombok delombok = new Delombok();
|
||||
|
||||
@Override
|
||||
public void transformCode(Collection<CompilerMessage> messages, StringWriter result, final File file, LombokImmutableList<String> confLines) throws Throwable {
|
||||
public void transformCode(Collection<CompilerMessage> messages, StringWriter result, final File file) throws Throwable {
|
||||
delombok.setVerbose(false);
|
||||
delombok.setForceProcess(true);
|
||||
delombok.setCharset("UTF-8");
|
||||
|
||||
delombok.setDiagnosticsListener(new CapturingDiagnosticListener(file, messages));
|
||||
|
||||
// TODO: Create a configuration based on confLines and set this up so that this compile run will use them.
|
||||
|
||||
delombok.addFile(file.getAbsoluteFile().getParentFile(), file.getName());
|
||||
delombok.setSourcepath(file.getAbsoluteFile().getParent());
|
||||
String bcp = System.getProperty("delombok.bootclasspath");
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import lombok.core.LombokImmutableList;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.javac.CapturingDiagnosticListener.CompilerMessage;
|
||||
|
||||
@@ -88,7 +87,7 @@ public class RunTestsViaEcj extends AbstractRunTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformCode(Collection<CompilerMessage> messages, StringWriter result, File file, LombokImmutableList<String> confLines) throws Throwable {
|
||||
public void transformCode(Collection<CompilerMessage> messages, StringWriter result, File file) throws Throwable {
|
||||
final AtomicReference<CompilationResult> compilationResult_ = new AtomicReference<CompilationResult>();
|
||||
final AtomicReference<CompilationUnitDeclaration> compilationUnit_ = new AtomicReference<CompilationUnitDeclaration>();
|
||||
ICompilerRequestor bitbucketRequestor = new ICompilerRequestor() {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
//conf: lombok.Getter.flagUsage = WARNING
|
||||
//conf: lombok.experimental.flagUsage = ERROR
|
||||
public class FlagUsages {
|
||||
@lombok.Getter String x;
|
||||
|
||||
@lombok.experimental.Wither String z;
|
||||
|
||||
public FlagUsages(String x, String y) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
4 Use of @Getter is flagged according to lombok configuration.
|
||||
6 Use of any lombok.experimental feature is flagged according to lombok configuration.
|
||||
@@ -0,0 +1,2 @@
|
||||
4 Use of @Getter is flagged according to lombok configuration.
|
||||
6 Use of any lombok.experimental feature is flagged according to lombok configuration.
|
||||
Reference in new issue
Block a user