mirror of
https://github.com/tiennm99/lombok.git
synced 2026-09-10 02:17:34 +00:00
Merge branch 'master' into master
This commit is contained in:
@@ -24,6 +24,7 @@ Rabea Gransberger <rgra@users.noreply.github.com>
|
||||
Reinier Zwitserloot <reinier@zwitserloot.com>
|
||||
Robbert Jan Grootjans <grootjans@gmail.com>
|
||||
Roel Spilker <r.spilker@gmail.com>
|
||||
Roland Praml <pram@gmx.de>
|
||||
Sander Koning <askoning@gmail.com>
|
||||
Szymon Pacanowski <spacanowski@gmail.com>
|
||||
Taiki Sugawara <buzz.taiki@gmail.com>
|
||||
|
||||
@@ -112,7 +112,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
</target>
|
||||
|
||||
<target name="ensureBuildDeps" depends="config-ivy,ensureOpenJdk6Rt">
|
||||
<ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="build, javac7" />
|
||||
<ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="build, javac7, moduleBuild" />
|
||||
<ivy:retrieve />
|
||||
</target>
|
||||
|
||||
@@ -163,15 +163,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
|
||||
<target name="-ensureJdk9">
|
||||
<condition property="java.version.insufficient">
|
||||
<or>
|
||||
<equals arg1="${ant.java.version}" arg2="1.2" />
|
||||
<equals arg1="${ant.java.version}" arg2="1.3" />
|
||||
<equals arg1="${ant.java.version}" arg2="1.4" />
|
||||
<equals arg1="${ant.java.version}" arg2="1.5" />
|
||||
<equals arg1="${ant.java.version}" arg2="1.6" />
|
||||
<equals arg1="${ant.java.version}" arg2="1.7" />
|
||||
<equals arg1="${ant.java.version}" arg2="1.8" />
|
||||
</or>
|
||||
<matches string="${java.version}" pattern="^1\.[2-8](\..*)?" />
|
||||
</condition>
|
||||
<fail if="java.version.insufficient">To compile lombok, you need JDK9 or higher; lombok requires this version because it's rather difficult to produce lombok builds that are compatible on JDK9 without at least building with JDK9. Sorry about that.</fail>
|
||||
</target>
|
||||
@@ -254,14 +246,18 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
|
||||
<classpath refid="build.path" />
|
||||
</ivy:compile>
|
||||
|
||||
<ivy:compile destdir="build/lombok" source="1.9" target="1.9">
|
||||
<javac includeAntRuntime="false" source="1.9" target="1.9" destdir="build/lombok" modulepath="lib/moduleBuild">
|
||||
<compilerarg value="-Xlint:none" />
|
||||
<!-- The above is because javac9 warns about 'service interface provided but not exported or used', probably because lombok uses SPI internally, and uses the 'old' classpath discovery system for it. We're fine with this, hence, ignore this warning. -->
|
||||
<src path="src/core9" />
|
||||
</javac>
|
||||
<mkdir dir="build/lombokMapstruct" />
|
||||
<javac includeAntRuntime="false" source="1.9" target="1.9" destdir="build/lombokMapstruct">
|
||||
<src path="src/j9stubs" />
|
||||
<!-- This includes org.mapstruct.ap.spi.AstModifyingAnnotationProcessor; putting this on the classpath doesn't work (needs to be internal or a module) so we just add it and then delete the class file for convenience. -->
|
||||
</ivy:compile>
|
||||
<delete file="build/lombok/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.class" />
|
||||
</javac>
|
||||
<mkdir dir="build/lombok/secondaryLoading.SCL.lombok/org/mapstruct/ap/spi" />
|
||||
<move file="build/lombokMapstruct/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.class" tofile="build/lombok/secondaryLoading.SCL.lombok/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.SCL.lombok" />
|
||||
|
||||
<ivy:compile destdir="build/lombok/Class50" source="1.5" target="1.6" ecj="true" nowarn="true" includeSystemBootclasspath="true">
|
||||
<bootclasspath location="build/stubs" />
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<conf name="netbeansBuild" />
|
||||
<conf name="buildBase" extends="netbeansBuild, javac6" />
|
||||
<conf name="build" extends="buildBase, eclipseBuild" />
|
||||
<conf name="moduleBuild" />
|
||||
<conf name="buildWithoutEclipse" extends="buildBase" />
|
||||
<conf name="runtime" />
|
||||
<conf name="test" extends="runtime" />
|
||||
@@ -64,5 +65,7 @@
|
||||
<dependency org="com.jcraft" name="jsch" rev="0.1.54" conf="supporters->default" />
|
||||
<dependency org="com.rimerosolutions.ant" name="ant-git-tasks" rev="1.3.2" conf="supporters->default" />
|
||||
<dependency org="org.slf4j" name="slf4j-simple" rev="1.6.1" conf="supporters->default" />
|
||||
|
||||
<dependency org="org.mapstruct" name="mapstruct-processor" rev="1.3.0.Beta1" conf="moduleBuild->default" />
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
Lombok Changelog
|
||||
----------------
|
||||
|
||||
### v1.18.1 "Edgy Guinea Pig"
|
||||
### v1.18.3 "Edgy Guinea Pig"
|
||||
* FEATURE: The `@FieldNameConstants` feature has been completely redesigned. [Issue #1774](https://github.com/rzwitserloot/lombok/issues/1774) [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants)
|
||||
* BUGFIX: When using lombok to compile modularized (`module-info.java`-style) code, if the module name has dots in it, it wouldn't work. [Issue #1808](https://github.com/rzwitserloot/lombok/issues/1808)
|
||||
* BUGFIX: Errors about lombok not reading a module providing `org.mapstruct.ap.spi` when trying to use lombok in jigsaw-mode on JDK 11. [Issue #1806](https://github.com/rzwitserloot/lombok/issues/1806)
|
||||
|
||||
### v1.18.2 (July 26th, 2018)
|
||||
* BUGFIX: mapstruct + lombok in eclipse should hopefully work again. [Issue #1359](https://github.com/rzwitserloot/lombok/issues/1359) and [mapstruct issue #1159](https://github.com/mapstruct/mapstruct/issues/1159)
|
||||
* BUGFIX: Equals and hashCode again exclude transient fields by default. [Issue #1724](https://github.com/rzwitserloot/lombok/issues/1724)
|
||||
* BUGFIX: Eclipse 'organize imports' feature (either explicitly, or if automatically triggered on saving via 'save actions') would remove the import for `lombok.var`. [Issue #1783](https://github.com/rzwitserloot/lombok/issues/1783)
|
||||
* BUGFIX: Lombok and gradle v4.9 didn't work together; that's been fixed. [Issue #1716](https://github.com/rzwitserloot/lombok/issues/1716) and [gradle-apt-plugin issue #87](https://github.com/tbroyer/gradle-apt-plugin/issues/87)
|
||||
* FEATURE: You can now make builders for type hierarchies, using the new (experimental) `@SuperBuilder` annotation. Thanks for the contribution, Jan Rieke. [`@SuperBuilder` documentation](https://projectlombok.org/features/experimental/SuperBuilder)
|
||||
* FEATURE: `@NoArgsConstructor`, including forcing one with `lombok.config: lombok.noArgsConstructor.extraPrivate=true` now take any defaults set with `@Builder.Default` into account. [Issue #1347](https://github.com/rzwitserloot/lombok/issues/1347)
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
jdk:
|
||||
- openjdk9
|
||||
before_install:
|
||||
- export JAVA_HOME=/usr/lib/jvm/java-9-oracle
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2017 The Project Lombok Authors.
|
||||
* Copyright (C) 2013-2018 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
|
||||
@@ -38,6 +38,13 @@ public class ConfigurationKeys {
|
||||
|
||||
// ----- global -----
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code dangerousconfig.lombok.disable} = {@code true} | {@code false}.
|
||||
*
|
||||
* If {@code true}, lombok is disabled entirely.
|
||||
*/
|
||||
public static final ConfigurationKey<Boolean> LOMBOK_DISABLE = new ConfigurationKey<Boolean>("dangerousconfig.lombok.disable", "Disables lombok transformers. It does not flag any lombok mentions (so, @Cleanup silently does nothing), and does not disable patched operations in eclipse either. Don't use this unless you know what you're doing. (default: false).", true) {};
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code lombok.addGeneratedAnnotation} = {@code true} | {@code false}.
|
||||
*
|
||||
@@ -522,18 +529,11 @@ public class ConfigurationKeys {
|
||||
public static final ConfigurationKey<FlagUsageType> FIELD_NAME_CONSTANTS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.fieldNameConstants.flagUsage", "Emit a warning or error if @FieldNameConstants is used.") {};
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code lombok.fieldNameConstants.prefix} = <String: aJavaIdentifierPrefix> (Default: {@code PREFIX_}).
|
||||
* lombok configuration: {@code lombok.fieldNameConstants.innerTypeName} = <String: AValidJavaTypeName> (Default: {@code Fields}).
|
||||
*
|
||||
* The names of the constants generated by {@code @FieldNameConstants} will be prefixed with this value.
|
||||
*/
|
||||
public static final ConfigurationKey<String> FIELD_NAME_CONSTANTS_PREFIX = new ConfigurationKey<String>("lombok.fieldNameConstants.prefix", "names of constants generated by @FieldNameConstants will be prefixed with this value. (default: 'PREFIX_').") {};
|
||||
|
||||
/**
|
||||
* lombok configuration: {@code lombok.fieldNameConstants.suffix} = <String: aJavaIdentifierPrefix> (Default: nothing).
|
||||
*
|
||||
* The names of the constants generated by {@code @FieldNameConstants} will be suffixed with this value.
|
||||
*/
|
||||
public static final ConfigurationKey<String> FIELD_NAME_CONSTANTS_SUFFIX = new ConfigurationKey<String>("lombok.fieldNameConstants.suffix", "names of constants generated by @FieldNameConstants will be suffixed with this value. (default: nothing).") {};
|
||||
public static final ConfigurationKey<String> FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey<String>("lombok.fieldNameConstants.innerTypeName", "The default name of the inner type generated by @FieldNameConstants. (default: 'Fields').") {};
|
||||
|
||||
// ----- Wither -----
|
||||
|
||||
|
||||
@@ -116,23 +116,24 @@ public class ClassFileMetaData {
|
||||
int end = pos + size;
|
||||
|
||||
// the resulting string might be smaller
|
||||
StringBuilder result = new StringBuilder(size);
|
||||
char[] result = new char[size];
|
||||
int length = 0;
|
||||
while (pos < end) {
|
||||
int first = (byteCode[pos++] & 0xFF);
|
||||
if (first < 0x80) {
|
||||
result.append((char)first);
|
||||
result[length++] = (char)first;
|
||||
} else if ((first & 0xE0) == 0xC0) {
|
||||
int x = (first & 0x1F) << 6;
|
||||
int y = (byteCode[pos++] & 0x3F);
|
||||
result.append((char)(x | y));
|
||||
result[length++] = (char)(x | y);
|
||||
} else {
|
||||
int x = (first & 0x0F) << 12;
|
||||
int y = (byteCode[pos++] & 0x3F) << 6;
|
||||
int z = (byteCode[pos++] & 0x3F);
|
||||
result.append((char)(x | y | z));
|
||||
result[length++] = (char)(x | y | z);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
return new String(result, 0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -216,19 +216,19 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
|
||||
}
|
||||
}
|
||||
|
||||
private static final ConcurrentMap<Class<?>, Collection<FieldAccess>> fieldsOfASTClasses = new ConcurrentHashMap<Class<?>, Collection<FieldAccess>>();
|
||||
private static final ConcurrentMap<Class<?>, FieldAccess[]> fieldsOfASTClasses = new ConcurrentHashMap<Class<?>, FieldAccess[]>();
|
||||
|
||||
/** Returns FieldAccess objects for the stated class. Each field that contains objects of the kind returned by
|
||||
* {@link #getStatementTypes()}, either directly or inside of an array or java.util.collection (or array-of-arrays,
|
||||
* or collection-of-collections, et cetera), is returned.
|
||||
*/
|
||||
protected Collection<FieldAccess> fieldsOf(Class<?> c) {
|
||||
Collection<FieldAccess> fields = fieldsOfASTClasses.get(c);
|
||||
protected FieldAccess[] fieldsOf(Class<?> c) {
|
||||
FieldAccess[] fields = fieldsOfASTClasses.get(c);
|
||||
if (fields != null) return fields;
|
||||
|
||||
fields = new ArrayList<FieldAccess>();
|
||||
getFields(c, fields);
|
||||
fieldsOfASTClasses.putIfAbsent(c, fields);
|
||||
List<FieldAccess> fieldList = new ArrayList<FieldAccess>();
|
||||
getFields(c, fieldList);
|
||||
fieldsOfASTClasses.putIfAbsent(c, fieldList.toArray(new FieldAccess[fieldList.size()]));
|
||||
return fieldsOfASTClasses.get(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ import lombok.patcher.ClassRootFinder;
|
||||
|
||||
@SupportedAnnotationTypes("*")
|
||||
public class AnnotationProcessor extends AbstractProcessor {
|
||||
|
||||
|
||||
private static String trace(Throwable t) {
|
||||
StringWriter w = new StringWriter();
|
||||
t.printStackTrace(new PrintWriter(w, true));
|
||||
@@ -65,42 +65,35 @@ public class AnnotationProcessor extends AbstractProcessor {
|
||||
private final List<ProcessorDescriptor> registered = Arrays.asList(new JavacDescriptor(), new EcjDescriptor());
|
||||
private final List<ProcessorDescriptor> active = new ArrayList<ProcessorDescriptor>();
|
||||
private final List<String> delayedWarnings = new ArrayList<String>();
|
||||
|
||||
|
||||
/**
|
||||
* This method is a simplified version of {@link lombok.javac.apt.LombokProcessor.getJavacProcessingEnvironment}
|
||||
* It simply returns the processing environment, but in case of gradle incremental compilation,
|
||||
* the delegate ProcessingEnvironment of the gradle wrapper is returned.
|
||||
*/
|
||||
public static ProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment procEnv, List<String> delayedWarnings) {
|
||||
ProcessingEnvironment javacProcEnv = tryRecursivelyObtainJavacProcessingEnvironment(procEnv);
|
||||
|
||||
if (javacProcEnv == null) {
|
||||
delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment.");
|
||||
}
|
||||
|
||||
return javacProcEnv;
|
||||
return tryRecursivelyObtainJavacProcessingEnvironment(procEnv);
|
||||
}
|
||||
|
||||
|
||||
private static ProcessingEnvironment tryRecursivelyObtainJavacProcessingEnvironment(ProcessingEnvironment procEnv) {
|
||||
if (procEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) {
|
||||
return procEnv;
|
||||
}
|
||||
|
||||
|
||||
for (Class<?> procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) {
|
||||
try {
|
||||
Field field = procEnvClass.getDeclaredField("delegate");
|
||||
field.setAccessible(true);
|
||||
Object delegate = field.get(procEnv);
|
||||
|
||||
|
||||
return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate);
|
||||
} catch (final Exception e) {
|
||||
// no valid delegate, try superclass
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
static class JavacDescriptor extends ProcessorDescriptor {
|
||||
private Processor processor;
|
||||
@@ -110,10 +103,13 @@ public class AnnotationProcessor extends AbstractProcessor {
|
||||
}
|
||||
|
||||
@Override boolean want(ProcessingEnvironment procEnv, List<String> delayedWarnings) {
|
||||
// do not run on ECJ as it may print warnings
|
||||
if (procEnv.getClass().getName().startsWith("org.eclipse.jdt.")) return false;
|
||||
|
||||
ProcessingEnvironment javacProcEnv = getJavacProcessingEnvironment(procEnv, delayedWarnings);
|
||||
|
||||
|
||||
if (javacProcEnv == null) return false;
|
||||
|
||||
|
||||
try {
|
||||
ClassLoader classLoader = findAndPatchClassLoader(javacProcEnv);
|
||||
processor = (Processor) Class.forName("lombok.javac.apt.LombokProcessor", false, classLoader).newInstance();
|
||||
@@ -209,7 +205,7 @@ public class AnnotationProcessor extends AbstractProcessor {
|
||||
for (TypeElement elem : annotations) {
|
||||
zeroElems = false;
|
||||
Name n = elem.getQualifiedName();
|
||||
if (n.length() > 7 && n.subSequence(0, 7).toString().equals("lombok.")) continue;
|
||||
if (n.toString().startsWith("lombok.")) continue;
|
||||
onlyLombok = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2013-2018 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;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import lombok.core.configuration.BubblingConfigurationResolver;
|
||||
@@ -44,7 +45,7 @@ public class LombokConfiguration {
|
||||
static {
|
||||
if (System.getProperty("lombok.disableConfig") != null) {
|
||||
configurationResolverFactory = new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
|
||||
@Override public ConfigurationResolver createResolver(URI sourceLocation) {
|
||||
return NULL_RESOLVER;
|
||||
}
|
||||
};
|
||||
@@ -63,13 +64,17 @@ public class LombokConfiguration {
|
||||
}
|
||||
|
||||
static <T> T read(ConfigurationKey<T> key, AST<?, ?, ?> ast) {
|
||||
return configurationResolverFactory.createResolver(ast).resolve(key);
|
||||
return configurationResolverFactory.createResolver(ast.getAbsoluteFileLocation()).resolve(key);
|
||||
}
|
||||
|
||||
public static <T> T read(ConfigurationKey<T> key, URI sourceLocation) {
|
||||
return configurationResolverFactory.createResolver(sourceLocation).resolve(key);
|
||||
}
|
||||
|
||||
private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() {
|
||||
return new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
|
||||
return new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), ConfigurationProblemReporter.CONSOLE));
|
||||
@Override public ConfigurationResolver createResolver(URI sourceLocation) {
|
||||
return new BubblingConfigurationResolver(cache.sourcesForJavaFile(sourceLocation, ConfigurationProblemReporter.CONSOLE));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,10 +36,8 @@ public class LombokInternalAliasing {
|
||||
*/
|
||||
public static String processAliases(String in) {
|
||||
if (in == null) return null;
|
||||
for (Map.Entry<String, String> e : ALIASES.entrySet()) {
|
||||
if (in.equals(e.getKey())) return e.getValue();
|
||||
}
|
||||
return in;
|
||||
String ret = ALIASES.get(in);
|
||||
return ret == null ? in : ret;
|
||||
}
|
||||
|
||||
static {
|
||||
|
||||
@@ -40,7 +40,6 @@ import lombok.core.AST.Kind;
|
||||
* For example, JCTree for javac, and ASTNode for Eclipse.
|
||||
*/
|
||||
public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> implements DiagnosticsReceiver {
|
||||
protected final A ast;
|
||||
protected final Kind kind;
|
||||
protected final N node;
|
||||
protected LombokImmutableList<L> children;
|
||||
@@ -59,8 +58,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @param kind The kind of node represented by this object.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected LombokNode(A ast, N node, List<L> children, Kind kind) {
|
||||
this.ast = ast;
|
||||
protected LombokNode(N node, List<L> children, Kind kind) {
|
||||
this.kind = kind;
|
||||
this.node = node;
|
||||
this.children = children != null ? LombokImmutableList.copyOf(children) : LombokImmutableList.<L>of();
|
||||
@@ -72,9 +70,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
this.isStructurallySignificant = calculateIsStructurallySignificant(null);
|
||||
}
|
||||
|
||||
public A getAst() {
|
||||
return ast;
|
||||
}
|
||||
public abstract A getAst();
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override public String toString() {
|
||||
@@ -88,7 +84,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#getPackageDeclaration()
|
||||
*/
|
||||
public String getPackageDeclaration() {
|
||||
return ast.getPackageDeclaration();
|
||||
return getAst().getPackageDeclaration();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +93,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#getImportList()
|
||||
*/
|
||||
public ImportList getImportList() {
|
||||
return ast.getImportList();
|
||||
return getAst().getImportList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +107,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#get(Object)
|
||||
*/
|
||||
public L getNodeFor(N obj) {
|
||||
return ast.get(obj);
|
||||
return getAst().get(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,7 +183,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#getLatestJavaSpecSupported()
|
||||
*/
|
||||
public int getLatestJavaSpecSupported() {
|
||||
return ast.getLatestJavaSpecSupported();
|
||||
return getAst().getLatestJavaSpecSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +192,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#getSourceVersion()
|
||||
*/
|
||||
public int getSourceVersion() {
|
||||
return ast.getSourceVersion();
|
||||
return getAst().getSourceVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +201,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#top()
|
||||
*/
|
||||
public L top() {
|
||||
return ast.top();
|
||||
return getAst().top();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +210,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* @see AST#getFileName()
|
||||
*/
|
||||
public String getFileName() {
|
||||
return ast.getFileName();
|
||||
return getAst().getFileName();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,8 +220,8 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public L add(N newChild, Kind newChildKind) {
|
||||
ast.setChanged();
|
||||
L n = ast.buildTree(newChild, newChildKind);
|
||||
getAst().setChanged();
|
||||
L n = getAst().buildTree(newChild, newChildKind);
|
||||
if (n == null) return null;
|
||||
n.parent = (L) this;
|
||||
children = children.append(n);
|
||||
@@ -242,20 +238,20 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
Map<N, L> oldNodes = new IdentityHashMap<N, L>();
|
||||
gatherAndRemoveChildren(oldNodes);
|
||||
|
||||
L newNode = ast.buildTree(get(), kind);
|
||||
L newNode = getAst().buildTree(get(), kind);
|
||||
|
||||
ast.setChanged();
|
||||
getAst().setChanged();
|
||||
|
||||
ast.replaceNewWithExistingOld(oldNodes, newNode);
|
||||
getAst().replaceNewWithExistingOld(oldNodes, newNode);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void gatherAndRemoveChildren(Map<N, L> map) {
|
||||
for (LombokNode child : children) child.gatherAndRemoveChildren(map);
|
||||
ast.identityDetector.remove(get());
|
||||
getAst().identityDetector.remove(get());
|
||||
map.put(get(), (L) this);
|
||||
children = LombokImmutableList.of();
|
||||
ast.getNodeMap().remove(get());
|
||||
getAst().getNodeMap().remove(get());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,7 +260,7 @@ public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A,
|
||||
* Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
|
||||
*/
|
||||
public void removeChild(L child) {
|
||||
ast.setChanged();
|
||||
getAst().setChanged();
|
||||
children = children.removeElement(child);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public class Version {
|
||||
// ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries).
|
||||
// Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example.
|
||||
// Official builds always end in an even number. (Since 0.10.2).
|
||||
private static final String VERSION = "1.18.1";
|
||||
private static final String VERSION = "1.18.3";
|
||||
private static final String RELEASE_NAME = "Edgy Guinea Pig";
|
||||
// private static final String RELEASE_NAME = "Envious Ferret";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2014-2018 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
|
||||
@@ -118,7 +118,7 @@ public class ConfigurationApp extends LombokApp {
|
||||
|
||||
boolean verbose = args.verbose;
|
||||
if (args.generate) {
|
||||
return generate(keys, verbose);
|
||||
return generate(keys, verbose, !args.key.isEmpty());
|
||||
}
|
||||
|
||||
return display(keys, verbose, args.paths, !args.key.isEmpty());
|
||||
@@ -130,8 +130,9 @@ public class ConfigurationApp extends LombokApp {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int generate(Collection<ConfigurationKey<?>> keys, boolean verbose) {
|
||||
public int generate(Collection<ConfigurationKey<?>> keys, boolean verbose, boolean explicit) {
|
||||
for (ConfigurationKey<?> key : keys) {
|
||||
if (!explicit && key.isHidden()) continue;
|
||||
String keyName = key.getKeyName();
|
||||
ConfigurationDataType type = key.getType();
|
||||
String description = key.getDescription();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2013-2018 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
|
||||
@@ -43,13 +43,19 @@ public abstract class ConfigurationKey<T> {
|
||||
private final String keyName;
|
||||
private final String description;
|
||||
private final ConfigurationDataType type;
|
||||
private final boolean hidden;
|
||||
|
||||
public ConfigurationKey(String keyName, String description) {
|
||||
this(keyName, description, false);
|
||||
}
|
||||
|
||||
public ConfigurationKey(String keyName, String description, boolean hidden) {
|
||||
this.keyName = checkName(keyName);
|
||||
@SuppressWarnings("unchecked")
|
||||
ConfigurationDataType type = ConfigurationDataType.toDataType((Class<? extends ConfigurationKey<?>>)getClass());
|
||||
this.type = type;
|
||||
this.description = description;
|
||||
this.hidden = hidden;
|
||||
registerKey(keyName, this);
|
||||
}
|
||||
|
||||
@@ -65,6 +71,10 @@ public abstract class ConfigurationKey<T> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public final boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return keyName + " (" + type + "): " + description;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2014-2018 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,8 +21,8 @@
|
||||
*/
|
||||
package lombok.core.configuration;
|
||||
|
||||
import lombok.core.AST;
|
||||
import java.net.URI;
|
||||
|
||||
public interface ConfigurationResolverFactory {
|
||||
ConfigurationResolver createResolver(AST<?, ?, ?> ast);
|
||||
ConfigurationResolver createResolver(URI sourceLocation);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ public class StringConfigurationSource implements ConfigurationSource {
|
||||
list.add(new ListModification(value, add));
|
||||
}
|
||||
});
|
||||
|
||||
return new StringConfigurationSource(values);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2013 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 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
|
||||
@@ -73,16 +73,20 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
|
||||
private static final URI NOT_CALCULATED_MARKER = URI.create("https://projectlombok.org/not/calculated");
|
||||
private URI memoizedAbsoluteFileLocation = NOT_CALCULATED_MARKER;
|
||||
|
||||
public static URI getAbsoluteFileLocation(CompilationUnitDeclaration ast) {
|
||||
return getAbsoluteFileLocation0(ast);
|
||||
}
|
||||
|
||||
public URI getAbsoluteFileLocation() {
|
||||
if (memoizedAbsoluteFileLocation != NOT_CALCULATED_MARKER) return memoizedAbsoluteFileLocation;
|
||||
|
||||
memoizedAbsoluteFileLocation = getAbsoluteFileLocation0();
|
||||
memoizedAbsoluteFileLocation = getAbsoluteFileLocation0(this.compilationUnitDeclaration);
|
||||
return memoizedAbsoluteFileLocation;
|
||||
}
|
||||
|
||||
/** This is the call, but we wrapped it to memoize this. */
|
||||
private URI getAbsoluteFileLocation0() {
|
||||
String fileName = getFileName();
|
||||
private static URI getAbsoluteFileLocation0(CompilationUnitDeclaration ast) {
|
||||
String fileName = toFileName(ast);
|
||||
if (fileName != null && (fileName.startsWith("file:") || fileName.startsWith("sourcecontrol:"))) {
|
||||
// Some exotic build systems get real fancy with filenames. Known culprits:
|
||||
// The 'jazz' source control system _probably_ (not confirmed yet) uses sourcecontrol://jazz: urls.
|
||||
|
||||
@@ -36,6 +36,9 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
* has been implemented with an empty body. Override whichever methods you need.
|
||||
*/
|
||||
public abstract class EclipseASTAdapter implements EclipseASTVisitor {
|
||||
|
||||
private final boolean deferUntilPostDiet = getClass().isAnnotationPresent(DeferUntilPostDiet.class);
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void visitCompilationUnit(EclipseNode top, CompilationUnitDeclaration unit) {}
|
||||
|
||||
@@ -98,4 +101,8 @@ public abstract class EclipseASTAdapter implements EclipseASTVisitor {
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void endVisitStatement(EclipseNode statementNode, Statement statement) {}
|
||||
|
||||
public boolean isDeferUntilPostDiet() {
|
||||
return deferUntilPostDiet ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Argument;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Block;
|
||||
@@ -38,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Statement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
|
||||
|
||||
/**
|
||||
* Implement so you can ask any EclipseAST.Node to traverse depth-first through all children,
|
||||
@@ -199,8 +202,82 @@ public interface EclipseASTVisitor {
|
||||
print("</CUD>");
|
||||
}
|
||||
|
||||
private String printFlags(int flags, ASTNode node) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
if ((flags & ClassFileConstants.AccPublic) != 0) {
|
||||
flags &= ~ClassFileConstants.AccPublic;
|
||||
out.append("public ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccPrivate) != 0) {
|
||||
flags &= ~ClassFileConstants.AccPrivate;
|
||||
out.append("private ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccProtected) != 0) {
|
||||
flags &= ~ClassFileConstants.AccProtected;
|
||||
out.append("protected ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccStatic) != 0) {
|
||||
flags &= ~ClassFileConstants.AccStatic;
|
||||
out.append("static ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccFinal) != 0) {
|
||||
flags &= ~ClassFileConstants.AccFinal;
|
||||
out.append("final ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccSynchronized) != 0) {
|
||||
flags &= ~ClassFileConstants.AccSynchronized;
|
||||
out.append("synchronized ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccNative) != 0) {
|
||||
flags &= ~ClassFileConstants.AccNative;
|
||||
out.append("native ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccInterface) != 0) {
|
||||
flags &= ~ClassFileConstants.AccInterface;
|
||||
out.append("interface ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccAbstract) != 0) {
|
||||
flags &= ~ClassFileConstants.AccAbstract;
|
||||
out.append("abstract ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccStrictfp) != 0) {
|
||||
flags &= ~ClassFileConstants.AccStrictfp;
|
||||
out.append("strictfp ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccSynthetic) != 0) {
|
||||
flags &= ~ClassFileConstants.AccSynthetic;
|
||||
out.append("synthetic ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccAnnotation) != 0) {
|
||||
flags &= ~ClassFileConstants.AccAnnotation;
|
||||
out.append("annotation ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccEnum) != 0) {
|
||||
flags &= ~ClassFileConstants.AccEnum;
|
||||
out.append("enum ");
|
||||
}
|
||||
|
||||
if ((flags & ClassFileConstants.AccVolatile) != 0) {
|
||||
flags &= ~ClassFileConstants.AccVolatile;
|
||||
if (node instanceof FieldDeclaration) out.append("volatile ");
|
||||
else out.append("volatile/bridge ");
|
||||
}
|
||||
if ((flags & ClassFileConstants.AccTransient) != 0) {
|
||||
flags &= ~ClassFileConstants.AccTransient;
|
||||
if (node instanceof Argument) out.append("varargs ");
|
||||
else if (node instanceof FieldDeclaration) out.append("transient ");
|
||||
else out.append("transient/varargs ");
|
||||
}
|
||||
|
||||
if (flags != 0) {
|
||||
out.append(String.format(" 0x%08X ", flags));
|
||||
}
|
||||
|
||||
return out.toString().trim();
|
||||
}
|
||||
|
||||
public void visitType(EclipseNode node, TypeDeclaration type) {
|
||||
print("<TYPE %s%s%s>", str(type.name), isGenerated(type) ? " (GENERATED)" : "", position(node));
|
||||
print("<TYPE %s%s%s> %s", str(type.name), isGenerated(type) ? " (GENERATED)" : "", position(node), printFlags(type.modifiers, type));
|
||||
indent++;
|
||||
if (printContent) {
|
||||
print("%s", type);
|
||||
@@ -239,8 +316,8 @@ public interface EclipseASTVisitor {
|
||||
}
|
||||
|
||||
public void visitField(EclipseNode node, FieldDeclaration field) {
|
||||
print("<FIELD%s %s %s = %s%s>", isGenerated(field) ? " (GENERATED)" : "",
|
||||
str(field.type), str(field.name), field.initialization, position(node));
|
||||
print("<FIELD%s %s %s = %s%s> %s", isGenerated(field) ? " (GENERATED)" : "",
|
||||
str(field.type), str(field.name), field.initialization, position(node), printFlags(field.modifiers, field));
|
||||
indent++;
|
||||
if (printContent) {
|
||||
if (field.initialization != null) print("%s", field.initialization);
|
||||
@@ -260,9 +337,13 @@ public interface EclipseASTVisitor {
|
||||
|
||||
public void visitMethod(EclipseNode node, AbstractMethodDeclaration method) {
|
||||
String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD";
|
||||
print("<%s %s: %s%s%s>", type, str(method.selector), method.statements != null ? "filled" : "blank",
|
||||
isGenerated(method) ? " (GENERATED)" : "", position(node));
|
||||
print("<%s %s: %s%s%s> %s", type, str(method.selector), method.statements != null ? ("filled(" + method.statements.length + ")") : "blank",
|
||||
isGenerated(method) ? " (GENERATED)" : "", position(node), printFlags(method.modifiers, method));
|
||||
indent++;
|
||||
if (method instanceof ConstructorDeclaration) {
|
||||
ConstructorDeclaration cd = (ConstructorDeclaration) method;
|
||||
print("--> constructorCall: %s", cd.constructorCall == null ? "-NONE-" : cd.constructorCall);
|
||||
}
|
||||
if (printContent) {
|
||||
if (method.statements != null) print("%s", method);
|
||||
disablePrinting++;
|
||||
@@ -281,7 +362,8 @@ public interface EclipseASTVisitor {
|
||||
}
|
||||
|
||||
public void visitMethodArgument(EclipseNode node, Argument arg, AbstractMethodDeclaration method) {
|
||||
print("<METHODARG%s %s %s = %s%s>", isGenerated(arg) ? " (GENERATED)" : "", str(arg.type), str(arg.name), arg.initialization, position(node));
|
||||
print("<METHODARG%s %s %s = %s%s> %s", isGenerated(arg) ? " (GENERATED)" : "",
|
||||
str(arg.type), str(arg.name), arg.initialization, position(node), printFlags(arg.modifiers, arg));
|
||||
indent++;
|
||||
}
|
||||
|
||||
@@ -295,7 +377,8 @@ public interface EclipseASTVisitor {
|
||||
}
|
||||
|
||||
public void visitLocal(EclipseNode node, LocalDeclaration local) {
|
||||
print("<LOCAL%s %s %s = %s%s>", isGenerated(local) ? " (GENERATED)" : "", str(local.type), str(local.name), local.initialization, position(node));
|
||||
print("<LOCAL%s %s %s = %s%s> %s", isGenerated(local) ? " (GENERATED)" : "",
|
||||
str(local.type), str(local.name), local.initialization, position(node), printFlags(local.modifiers, local));
|
||||
indent++;
|
||||
}
|
||||
|
||||
@@ -310,6 +393,14 @@ public interface EclipseASTVisitor {
|
||||
|
||||
public void visitStatement(EclipseNode node, Statement statement) {
|
||||
print("<%s%s%s>", statement.getClass(), isGenerated(statement) ? " (GENERATED)" : "", position(node));
|
||||
if (statement instanceof AllocationExpression) {
|
||||
AllocationExpression alloc = (AllocationExpression) statement;
|
||||
print(" --> arguments: %s", alloc.arguments == null ? "NULL" : alloc.arguments.length);
|
||||
print(" --> genericTypeArguments: %s", alloc.genericTypeArguments == null ? "NULL" : alloc.genericTypeArguments.length);
|
||||
print(" --> typeArguments: %s", alloc.typeArguments == null ? "NULL" : alloc.typeArguments.length);
|
||||
print(" --> enumConstant: %s", alloc.enumConstant);
|
||||
print(" --> inferredReturnType: %s", alloc.inferredReturnType);
|
||||
}
|
||||
indent++;
|
||||
print("%s", statement);
|
||||
}
|
||||
@@ -325,5 +416,11 @@ public interface EclipseASTVisitor {
|
||||
int end = node.get().sourceEnd();
|
||||
return String.format(" [%d, %d]", start, end);
|
||||
}
|
||||
|
||||
public boolean isDeferUntilPostDiet() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isDeferUntilPostDiet();
|
||||
}
|
||||
|
||||
@@ -44,16 +44,22 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
|
||||
* Eclipse specific version of the LombokNode class.
|
||||
*/
|
||||
public class EclipseNode extends lombok.core.LombokNode<EclipseAST, EclipseNode, ASTNode> {
|
||||
private EclipseAST ast;
|
||||
/** {@inheritDoc} */
|
||||
EclipseNode(EclipseAST ast, ASTNode node, List<EclipseNode> children, Kind kind) {
|
||||
super(ast, node, children, kind);
|
||||
super(node, children, kind);
|
||||
this.ast = ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EclipseAST getAst() {
|
||||
return ast;
|
||||
}
|
||||
/**
|
||||
* Visits this node and all child nodes depth-first, calling the provided visitor's visit methods.
|
||||
*/
|
||||
public void traverse(EclipseASTVisitor visitor) {
|
||||
if (!this.isCompleteParse() && visitor.getClass().isAnnotationPresent(DeferUntilPostDiet.class)) return;
|
||||
if (visitor.isDeferUntilPostDiet() && !isCompleteParse()) return;
|
||||
|
||||
switch (getKind()) {
|
||||
case COMPILATION_UNIT:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 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
|
||||
@@ -212,21 +212,25 @@ public class HandlerLibrary {
|
||||
* @param ast The Compilation Unit that contains the Annotation AST Node.
|
||||
* @param annotationNode The Lombok AST Node representing the Annotation AST Node.
|
||||
* @param annotation 'node.get()' - convenience parameter.
|
||||
* @param priority current prioritiy
|
||||
* @return the priority we want to run - MAX_VALUE means never
|
||||
*/
|
||||
public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) {
|
||||
public long handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) {
|
||||
TypeResolver resolver = new TypeResolver(annotationNode.getImportList());
|
||||
TypeReference rawType = annotation.type;
|
||||
if (rawType == null) return;
|
||||
if (rawType == null) return Long.MAX_VALUE;
|
||||
|
||||
String fqn = resolver.typeRefToFullyQualifiedName(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName()));
|
||||
if (fqn == null) return;
|
||||
if (fqn == null) return Long.MAX_VALUE;
|
||||
AnnotationHandlerContainer<?> container = annotationHandlers.get(fqn);
|
||||
if (container == null) return;
|
||||
if (priority != container.getPriority()) return;
|
||||
if (container == null) return Long.MAX_VALUE;
|
||||
|
||||
if (priority < container.getPriority()) return container.getPriority(); // we want to run at this priority
|
||||
if (priority > container.getPriority()) return Long.MAX_VALUE; // it's over- we do not want to run again
|
||||
|
||||
if (!annotationNode.isCompleteParse() && container.deferUntilPostDiet()) {
|
||||
if (needsHandling(annotation)) container.preHandle(annotation, annotationNode);
|
||||
return;
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -236,13 +240,16 @@ public class HandlerLibrary {
|
||||
} catch (Throwable t) {
|
||||
error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t);
|
||||
}
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will call all registered {@link EclipseASTVisitor} instances.
|
||||
*/
|
||||
public void callASTVisitors(EclipseAST ast, long priority, boolean isCompleteParse) {
|
||||
public long callASTVisitors(EclipseAST ast, long priority, boolean isCompleteParse) {
|
||||
long nearestPriority = Long.MAX_VALUE;
|
||||
for (VisitorContainer container : visitorHandlers) {
|
||||
if (priority < container.getPriority()) nearestPriority = Math.min(container.getPriority(), nearestPriority);
|
||||
if (!isCompleteParse && container.deferUntilPostDiet()) continue;
|
||||
if (priority != container.getPriority()) continue;
|
||||
try {
|
||||
@@ -252,5 +259,6 @@ public class HandlerLibrary {
|
||||
String.format("Lombok visitor handler %s failed", container.visitor.getClass()), t);
|
||||
}
|
||||
}
|
||||
return nearestPriority;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2012 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 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
|
||||
@@ -25,6 +25,8 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.LombokConfiguration;
|
||||
import lombok.core.debug.DebugSnapshotStore;
|
||||
import lombok.core.debug.HistogramTracker;
|
||||
import lombok.patcher.Symbols;
|
||||
@@ -143,6 +145,8 @@ public class TransformEclipseAST {
|
||||
|
||||
// Do NOT abort if (ast.bits & ASTNode.HasAllMethodBodies) != 0 - that doesn't work.
|
||||
|
||||
if (Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, EclipseAST.getAbsoluteFileLocation(ast)))) return;
|
||||
|
||||
try {
|
||||
DebugSnapshotStore.INSTANCE.snapshot(ast, "transform entry");
|
||||
long histoToken = lombokTracker == null ? 0L : lombokTracker.start();
|
||||
@@ -182,42 +186,54 @@ public class TransformEclipseAST {
|
||||
* then handles any PrintASTs.
|
||||
*/
|
||||
public void go() {
|
||||
long nextPriority = Long.MIN_VALUE;
|
||||
for (Long d : handlers.getPriorities()) {
|
||||
ast.traverse(new AnnotationVisitor(d));
|
||||
handlers.callASTVisitors(ast, d, ast.isCompleteParse());
|
||||
if (nextPriority > d) continue;
|
||||
AnnotationVisitor visitor = new AnnotationVisitor(d);
|
||||
ast.traverse(visitor);
|
||||
// if no visitor interested for this AST, nextPriority would be MAX_VALUE and we bail out immediatetly
|
||||
nextPriority = visitor.getNextPriority();
|
||||
nextPriority = Math.min(nextPriority, handlers.callASTVisitors(ast, d, ast.isCompleteParse()));
|
||||
}
|
||||
}
|
||||
|
||||
private static class AnnotationVisitor extends EclipseASTAdapter {
|
||||
private final long priority;
|
||||
// this is the next priority we continue to visit.
|
||||
// Long.MAX_VALUE means never. Each visit method will potentially reduce the next priority
|
||||
private long nextPriority = Long.MAX_VALUE;
|
||||
|
||||
public AnnotationVisitor(long priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public long getNextPriority() {
|
||||
return nextPriority;
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) {
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
handlers.handleAnnotation(top, annotationNode, annotation, priority);
|
||||
nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority));
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
handlers.handleAnnotation(top, annotationNode, annotation, priority);
|
||||
nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority));
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnLocal(LocalDeclaration local, EclipseNode annotationNode, Annotation annotation) {
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
handlers.handleAnnotation(top, annotationNode, annotation, priority);
|
||||
nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority));
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnMethod(AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) {
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
handlers.handleAnnotation(top, annotationNode, annotation, priority);
|
||||
nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority));
|
||||
}
|
||||
|
||||
@Override public void visitAnnotationOnType(TypeDeclaration type, EclipseNode annotationNode, Annotation annotation) {
|
||||
CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get();
|
||||
handlers.handleAnnotation(top, annotationNode, annotation, priority);
|
||||
nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ package lombok.eclipse.handlers;
|
||||
import static lombok.core.handlers.HandlerUtil.*;
|
||||
import static lombok.eclipse.Eclipse.*;
|
||||
import static lombok.eclipse.EclipseAugments.*;
|
||||
import static lombok.eclipse.handlers.EclipseHandlerUtil.setGeneratedBy;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
@@ -1862,4 +1863,29 @@ public class EclipseHandlerUtil {
|
||||
String p = typeDecl.superclass.toString();
|
||||
return p.equals("Object") || p.equals("java.lang.Object");
|
||||
}
|
||||
|
||||
public static NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
NameReference ref;
|
||||
|
||||
if (varNames.length > 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
|
||||
else ref = new SingleNameReference(varNames[0], p);
|
||||
setGeneratedBy(ref, source);
|
||||
return ref;
|
||||
}
|
||||
|
||||
public static TypeReference generateQualifiedTypeRef(ASTNode source, char[]... varNames) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
TypeReference ref;
|
||||
|
||||
long[] poss = Eclipse.poss(source, varNames.length);
|
||||
if (varNames.length > 1) ref = new QualifiedTypeReference(varNames, poss);
|
||||
else ref = new SingleTypeReference(varNames[0], p);
|
||||
setGeneratedBy(ref, source);
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.Assignment;
|
||||
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Expression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
@@ -47,6 +48,7 @@ import org.eclipse.jdt.internal.compiler.ast.FieldReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
|
||||
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
|
||||
@@ -146,6 +148,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
@Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
|
||||
|
||||
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
|
||||
|
||||
Builder builderInstance = annotation.getInstance();
|
||||
@@ -490,6 +494,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
}
|
||||
}
|
||||
|
||||
private static final char[] EMPTY_LIST = "emptyList".toCharArray();
|
||||
private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source) {
|
||||
// return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
|
||||
|
||||
@@ -509,19 +514,34 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
char[] setterName = fluent ? bfd.name : HandlerUtil.buildAccessorName("set", new String(bfd.name)).toCharArray();
|
||||
MessageSend ms = new MessageSend();
|
||||
Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2];
|
||||
|
||||
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
|
||||
char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray();
|
||||
FieldReference fr = new FieldReference(fieldName, 0);
|
||||
fr.receiver = new ThisReference(0, 0);
|
||||
ms.arguments = new Expression[] {fr};
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
FieldReference fr = new FieldReference(fieldName, 0);
|
||||
fr.receiver = new ThisReference(0, 0);
|
||||
tgt[i] = fr;
|
||||
}
|
||||
} else {
|
||||
String obtainName = bfd.obtainVia.method();
|
||||
boolean obtainIsStatic = bfd.obtainVia.isStatic();
|
||||
MessageSend obtainExpr = new MessageSend();
|
||||
obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0) : new ThisReference(0, 0);
|
||||
obtainExpr.selector = obtainName.toCharArray();
|
||||
if (obtainIsStatic) obtainExpr.arguments = new Expression[] {new ThisReference(0, 0)};
|
||||
ms.arguments = new Expression[] {obtainExpr};
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
MessageSend obtainExpr = new MessageSend();
|
||||
obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0) : new ThisReference(0, 0);
|
||||
obtainExpr.selector = obtainName.toCharArray();
|
||||
if (obtainIsStatic) obtainExpr.arguments = new Expression[] {new ThisReference(0, 0)};
|
||||
tgt[i] = obtainExpr;
|
||||
}
|
||||
}
|
||||
if (bfd.singularData == null) {
|
||||
ms.arguments = tgt;
|
||||
} else {
|
||||
Expression ifNull = new EqualExpression(tgt[0], new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
|
||||
MessageSend emptyList = new MessageSend();
|
||||
emptyList.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Collections".toCharArray());
|
||||
emptyList.selector = EMPTY_LIST;
|
||||
ms.arguments = new Expression[] {new ConditionalExpression(ifNull, emptyList, tgt[1])};
|
||||
}
|
||||
ms.receiver = receiver;
|
||||
ms.selector = setterName;
|
||||
|
||||
@@ -69,7 +69,6 @@ import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
|
||||
@@ -819,29 +818,4 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
|
||||
expr.sourceStart = pS; expr.sourceEnd = pE;
|
||||
return expr;
|
||||
}
|
||||
|
||||
public NameReference generateQualifiedNameRef(ASTNode source, char[]... varNames) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
NameReference ref;
|
||||
|
||||
if (varNames.length > 1) ref = new QualifiedNameReference(varNames, new long[varNames.length], pS, pE);
|
||||
else ref = new SingleNameReference(varNames[0], p);
|
||||
setGeneratedBy(ref, source);
|
||||
return ref;
|
||||
}
|
||||
|
||||
public TypeReference generateQualifiedTypeRef(ASTNode source, char[]... varNames) {
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long)pS << 32 | pE;
|
||||
|
||||
TypeReference ref;
|
||||
|
||||
long[] poss = Eclipse.poss(source, varNames.length);
|
||||
if (varNames.length > 1) ref = new QualifiedTypeReference(varNames, poss);
|
||||
else ref = new SingleTypeReference(varNames[0], p);
|
||||
setGeneratedBy(ref, source);
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,32 +24,37 @@ package lombok.eclipse.handlers;
|
||||
import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
|
||||
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.eclipse.Eclipse;
|
||||
import lombok.eclipse.EclipseAnnotationHandler;
|
||||
import lombok.eclipse.EclipseNode;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
|
||||
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Clinit;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
|
||||
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.Statement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
|
||||
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
@ProviderFor(EclipseAnnotationHandler.class)
|
||||
public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldNameConstants> {
|
||||
public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, String prefix, String suffix) {
|
||||
public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) {
|
||||
TypeDeclaration typeDecl = null;
|
||||
if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
|
||||
|
||||
@@ -57,22 +62,29 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName
|
||||
boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0;
|
||||
|
||||
if (typeDecl == null || notAClass) {
|
||||
errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field.");
|
||||
errorNode.addError("@FieldNameConstants is only supported on a class or an enum.");
|
||||
return;
|
||||
}
|
||||
|
||||
List<EclipseNode> qualified = new ArrayList<EclipseNode>();
|
||||
|
||||
for (EclipseNode field : typeNode.down()) {
|
||||
if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level, prefix, suffix);
|
||||
if (fieldQualifiesForFieldNameConstantsGeneration(field, onlyExplicit)) qualified.add(field);
|
||||
}
|
||||
|
||||
if (qualified.isEmpty()) {
|
||||
errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing");
|
||||
} else {
|
||||
createInnerTypeFieldNameConstants(typeNode, errorNode.get(), level, qualified, asEnum, innerTypeName);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateFieldNameConstantsForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, String prefix, String suffix) {
|
||||
if (hasAnnotation(FieldNameConstants.class, fieldNode)) return;
|
||||
createFieldNameConstantsForField(level, prefix, suffix, fieldNode, fieldNode, pos, false);
|
||||
}
|
||||
|
||||
private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field) {
|
||||
private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field, boolean onlyExplicit) {
|
||||
if (field.getKind() != Kind.FIELD) return false;
|
||||
if (hasAnnotation(FieldNameConstants.Exclude.class, field)) return false;
|
||||
if (hasAnnotation(FieldNameConstants.Include.class, field)) return true;
|
||||
if (onlyExplicit) return false;
|
||||
|
||||
FieldDeclaration fieldDecl = (FieldDeclaration) field.get();
|
||||
return filterField(fieldDecl);
|
||||
}
|
||||
@@ -81,55 +93,75 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler<FieldName
|
||||
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_NAME_CONSTANTS_FLAG_USAGE, "@FieldNameConstants");
|
||||
|
||||
EclipseNode node = annotationNode.up();
|
||||
FieldNameConstants annotatationInstance = annotation.getInstance();
|
||||
AccessLevel level = annotatationInstance.level();
|
||||
String prefix = annotatationInstance.prefix();
|
||||
String suffix = annotatationInstance.suffix();
|
||||
if (prefix.equals(" CONFIG DEFAULT ")) prefix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_PREFIX);
|
||||
if (suffix.equals(" CONFIG DEFAULT ")) suffix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_SUFFIX);
|
||||
if (prefix == null) prefix = "FIELD_";
|
||||
if (suffix == null) suffix = "";
|
||||
if (node == null) return;
|
||||
FieldNameConstants annotationInstance = annotation.getInstance();
|
||||
AccessLevel level = annotationInstance.level();
|
||||
boolean asEnum = annotationInstance.asEnum();
|
||||
boolean usingLombokv1_18_2 = annotation.isExplicit("prefix") || annotation.isExplicit("suffix") || node.getKind() == Kind.FIELD;
|
||||
|
||||
switch (node.getKind()) {
|
||||
case FIELD:
|
||||
if (level != AccessLevel.NONE) createFieldNameConstantsForFields(level, prefix, suffix, annotationNode.upFromAnnotationToFields(), annotationNode, annotationNode.get(), true);
|
||||
break;
|
||||
case TYPE:
|
||||
if (level == AccessLevel.NONE) {
|
||||
annotationNode.addWarning("type-level '@FieldNameConstants' does not work with AccessLevel.NONE.");
|
||||
return;
|
||||
if (usingLombokv1_18_2) {
|
||||
annotationNode.addError("@FieldNameConstants has been redesigned in lombok v1.18.4; please upgrade your project dependency on lombok. See https://projectlombok.org/features/experimental/FieldNameConstants for more information.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (level == AccessLevel.NONE) {
|
||||
annotationNode.addWarning("AccessLevel.NONE is not compatible with @FieldNameConstants. If you don't want the inner type, simply remove FieldNameConstants.");
|
||||
return;
|
||||
}
|
||||
|
||||
String innerTypeName = annotationInstance.innerTypeName();
|
||||
if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME);
|
||||
if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields";
|
||||
|
||||
generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded());
|
||||
}
|
||||
|
||||
private void createInnerTypeFieldNameConstants(EclipseNode typeNode, ASTNode source, AccessLevel level, List<EclipseNode> fields, boolean asEnum, String innerTypeName) {
|
||||
if (fields.isEmpty()) return;
|
||||
|
||||
TypeDeclaration parent = (TypeDeclaration) typeNode.get();
|
||||
TypeDeclaration innerType = new TypeDeclaration(parent.compilationResult);
|
||||
innerType.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
innerType.modifiers = toEclipseModifier(level) | (asEnum ? ClassFileConstants.AccEnum : ClassFileConstants.AccStatic | ClassFileConstants.AccFinal);
|
||||
char[] name = innerTypeName.toCharArray();
|
||||
innerType.name = name;
|
||||
innerType.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
|
||||
EclipseNode innerNode = injectType(typeNode, innerType);
|
||||
|
||||
ConstructorDeclaration constructor = new ConstructorDeclaration(parent.compilationResult);
|
||||
constructor.selector = name;
|
||||
constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
|
||||
constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
|
||||
constructor.modifiers = ClassFileConstants.AccPrivate;
|
||||
ExplicitConstructorCall superCall = new ExplicitConstructorCall(0);
|
||||
superCall.sourceStart = source.sourceStart;
|
||||
superCall.sourceEnd = source.sourceEnd;
|
||||
superCall.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
constructor.constructorCall = superCall;
|
||||
if (!asEnum) constructor.statements = new Statement[0];
|
||||
|
||||
injectMethod(innerNode, constructor);
|
||||
|
||||
if (asEnum) injectMethod(innerNode, new Clinit(parent.compilationResult));
|
||||
|
||||
for (EclipseNode fieldNode : fields) {
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
char[] fName = field.name;
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long) pS << 32 | pE;
|
||||
FieldDeclaration fieldConstant = new FieldDeclaration(fName, pS, pE);
|
||||
fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
fieldConstant.modifiers = asEnum ? 0 : ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal;
|
||||
fieldConstant.type = asEnum ? null : new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p});
|
||||
if (asEnum) {
|
||||
AllocationExpression ac = new AllocationExpression();
|
||||
ac.enumConstant = fieldConstant;
|
||||
ac.sourceStart = source.sourceStart;
|
||||
ac.sourceEnd = source.sourceEnd;
|
||||
fieldConstant.initialization = ac;
|
||||
} else {
|
||||
fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0);
|
||||
}
|
||||
generateFieldNameConstantsForType(node, annotationNode, level, prefix, suffix);
|
||||
break;
|
||||
injectField(innerNode, fieldConstant);
|
||||
}
|
||||
}
|
||||
|
||||
private void createFieldNameConstantsForFields(AccessLevel level, String prefix, String suffix, Collection<EclipseNode> fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
|
||||
for (EclipseNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, prefix, suffix, fieldNode, errorNode, source, whineIfExists);
|
||||
}
|
||||
|
||||
private void createFieldNameConstantsForField(AccessLevel level, String prefix, String suffix, EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) {
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field");
|
||||
return;
|
||||
}
|
||||
|
||||
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
|
||||
String fieldName = new String(field.name);
|
||||
String constantName = prefix + HandlerUtil.camelCaseToConstant(fieldName) + suffix;
|
||||
if (constantName.equals(fieldName)) {
|
||||
fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field.");
|
||||
return;
|
||||
}
|
||||
|
||||
int pS = source.sourceStart, pE = source.sourceEnd;
|
||||
long p = (long) pS << 32 | pE;
|
||||
FieldDeclaration fieldConstant = new FieldDeclaration(constantName.toCharArray(), pS,pE);
|
||||
fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
|
||||
fieldConstant.modifiers = toEclipseModifier(level) | Modifier.STATIC | Modifier.FINAL;
|
||||
fieldConstant.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p,p,p});
|
||||
fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0);
|
||||
injectField(fieldNode.up(), fieldConstant);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,32 @@ import java.lang.annotation.Target;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
/**
|
||||
* Generates String constants containing the field name for each field.
|
||||
* Generates an inner type, containing String constants containing the field name for each field. Alternatively, generates an inner enum with enum values matching each field name.
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface FieldNameConstants {
|
||||
lombok.AccessLevel level() default AccessLevel.PUBLIC;
|
||||
String prefix() default " CONFIG DEFAULT ";
|
||||
String suffix() default " CONFIG DEFAULT ";
|
||||
boolean asEnum() default false;
|
||||
String innerTypeName() default "";
|
||||
|
||||
/**
|
||||
* Only include fields and methods explicitly marked with {@code @FieldNameConstants.Include}.
|
||||
* Normally, all (non-static) fields are included by default.
|
||||
*/
|
||||
boolean onlyExplicitlyIncluded() default false;
|
||||
|
||||
/**
|
||||
* If present, do not include this field in the generated fieldnames inner type.
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Exclude {}
|
||||
|
||||
/**
|
||||
* If present, include this field in the generated fieldnames inner type (default).
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Include {}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 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
|
||||
@@ -93,8 +93,11 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
|
||||
}
|
||||
|
||||
@Override public URI getAbsoluteFileLocation() {
|
||||
return getAbsoluteFileLocation((JCCompilationUnit) top().get());
|
||||
}
|
||||
|
||||
public static URI getAbsoluteFileLocation(JCCompilationUnit cu) {
|
||||
try {
|
||||
JCCompilationUnit cu = (JCCompilationUnit) top().get();
|
||||
return cu.sourcefile.toUri();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
|
||||
@@ -149,8 +149,12 @@ public interface JavacASTVisitor {
|
||||
print("</CUD>");
|
||||
}
|
||||
|
||||
private String printFlags(long f) {
|
||||
return Flags.toString(f);
|
||||
}
|
||||
|
||||
@Override public void visitType(JavacNode node, JCClassDecl type) {
|
||||
print("<TYPE %s>", type.name);
|
||||
print("<TYPE %s> %s", type.name, printFlags(type.mods.flags));
|
||||
indent++;
|
||||
if (printContent) {
|
||||
print("%s", type);
|
||||
@@ -185,7 +189,7 @@ public interface JavacASTVisitor {
|
||||
}
|
||||
|
||||
@Override public void visitField(JavacNode node, JCVariableDecl field) {
|
||||
print("<FIELD %s %s>", field.vartype, field.name);
|
||||
print("<FIELD %s %s> %s", field.vartype, field.name, printFlags(field.mods.flags));
|
||||
indent++;
|
||||
if (printContent) {
|
||||
if (field.init != null) print("%s", field.init);
|
||||
@@ -210,7 +214,7 @@ public interface JavacASTVisitor {
|
||||
type = "DEFAULTCONSTRUCTOR";
|
||||
} else type = "CONSTRUCTOR";
|
||||
} else type = "METHOD";
|
||||
print("<%s %s> returns: %s", type, method.name, method.restype);
|
||||
print("<%s %s> %s returns: %s", type, method.name, printFlags(method.mods.flags), method.restype);
|
||||
indent++;
|
||||
if (printContent) {
|
||||
if (method.body == null) print("(ABSTRACT)");
|
||||
@@ -230,7 +234,7 @@ public interface JavacASTVisitor {
|
||||
}
|
||||
|
||||
@Override public void visitMethodArgument(JavacNode node, JCVariableDecl arg, JCMethodDecl method) {
|
||||
print("<METHODARG %s %s>", arg.vartype, arg.name);
|
||||
print("<METHODARG %s %s> %s", arg.vartype, arg.name, printFlags(arg.mods.flags));
|
||||
indent++;
|
||||
}
|
||||
|
||||
@@ -244,7 +248,7 @@ public interface JavacASTVisitor {
|
||||
}
|
||||
|
||||
@Override public void visitLocal(JavacNode node, JCVariableDecl local) {
|
||||
print("<LOCAL %s %s>", local.vartype, local.name);
|
||||
print("<LOCAL %s %s> %s", local.vartype, local.name, printFlags(local.mods.flags));
|
||||
indent++;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,11 +50,18 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
* Javac specific version of the LombokNode class.
|
||||
*/
|
||||
public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTree> {
|
||||
private JavacAST ast;
|
||||
/**
|
||||
* Passes through to the parent constructor.
|
||||
*/
|
||||
public JavacNode(JavacAST ast, JCTree node, List<JavacNode> children, Kind kind) {
|
||||
super(ast, node, children, kind);
|
||||
super(node, children, kind);
|
||||
this.ast = ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavacAST getAst() {
|
||||
return ast;
|
||||
}
|
||||
|
||||
public Element getElement() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 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
|
||||
@@ -35,6 +35,9 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.LombokConfiguration;
|
||||
|
||||
public class JavacTransformer {
|
||||
private final HandlerLibrary handlers;
|
||||
private final Messager messager;
|
||||
@@ -65,7 +68,11 @@ public class JavacTransformer {
|
||||
|
||||
java.util.List<JavacAST> asts = new ArrayList<JavacAST>();
|
||||
|
||||
for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit));
|
||||
for (JCCompilationUnit unit : compilationUnits) {
|
||||
if (!Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) {
|
||||
asts.add(new JavacAST(messager, context, unit));
|
||||
}
|
||||
}
|
||||
|
||||
for (JavacAST ast : asts) {
|
||||
ast.traverse(new AnnotationVisitor(priority));
|
||||
|
||||
@@ -43,6 +43,7 @@ import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.QualifiedNameable;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
import javax.tools.JavaFileManager;
|
||||
@@ -166,13 +167,13 @@ public class LombokProcessor extends AbstractProcessor {
|
||||
if (!(originalFiler instanceof InterceptingJavaFileManager)) {
|
||||
final Messager messager = processingEnv.getMessager();
|
||||
DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager);
|
||||
|
||||
|
||||
JavaFileManager newFilerManager = new InterceptingJavaFileManager(originalFiler, receiver);
|
||||
ht.put(key, newFilerManager);
|
||||
Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager");
|
||||
filerFileManagerField.setAccessible(true);
|
||||
filerFileManagerField.set(javacFiler, newFilerManager);
|
||||
|
||||
|
||||
if (lombok.javac.Javac.getJavaCompilerVersion() > 8
|
||||
&& !lombok.javac.handlers.JavacHandlerUtil.inNetbeansCompileOnSave(context)) {
|
||||
replaceFileManagerJdk9(context, newFilerManager);
|
||||
@@ -383,10 +384,7 @@ public class LombokProcessor extends AbstractProcessor {
|
||||
|
||||
private String getModuleNameFor(Element element) {
|
||||
while (element != null) {
|
||||
if (element.getKind().name().equals("MODULE")) {
|
||||
String n = element.getSimpleName().toString().trim();
|
||||
return n.isEmpty() ? null : n;
|
||||
}
|
||||
if (element.getKind().name().equals("MODULE")) return ModuleNameOracle.getModuleName(element);
|
||||
Element n = element.getEnclosingElement();
|
||||
if (n == element) return null;
|
||||
element = n;
|
||||
@@ -394,6 +392,15 @@ public class LombokProcessor extends AbstractProcessor {
|
||||
return null;
|
||||
}
|
||||
|
||||
// QualifiedNameable is a java7 thing, so to remain compatible with java6, shove this into an inner class to avoid the ClassNotFoundError.
|
||||
private static class ModuleNameOracle {
|
||||
static String getModuleName(Element element) {
|
||||
if (!(element instanceof QualifiedNameable)) return null;
|
||||
String name = ((QualifiedNameable) element).getQualifiedName().toString().trim();
|
||||
return name.isEmpty() ? null : name;
|
||||
}
|
||||
}
|
||||
|
||||
private JCCompilationUnit toUnit(Element element) {
|
||||
TreePath path = trees == null ? null : trees.getPath(element);
|
||||
if (path == null) return null;
|
||||
@@ -432,7 +439,7 @@ public class LombokProcessor extends AbstractProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* This class returns the given filer as a JavacFiler. In case the case that the filer is no
|
||||
* This class returns the given filer as a JavacFiler. In case the filer is no
|
||||
* JavacFiler (e.g. the Gradle IncrementalFiler), its "delegate" field is used to get the JavacFiler
|
||||
* (directly or through a delegate field again)
|
||||
*/
|
||||
|
||||
@@ -99,6 +99,8 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
}
|
||||
|
||||
@Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
|
||||
|
||||
Builder builderInstance = annotation.getInstance();
|
||||
|
||||
// These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
|
||||
@@ -490,18 +492,34 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
|
||||
JCExpression invoke = call;
|
||||
for (BuilderFieldData bfd : builderFields) {
|
||||
Name setterName = fluent ? bfd.name : type.toName(HandlerUtil.buildAccessorName("set", bfd.name.toString()));
|
||||
JCExpression arg;
|
||||
JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2];
|
||||
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
|
||||
arg = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field()));
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field()));
|
||||
}
|
||||
} else {
|
||||
if (bfd.obtainVia.isStatic()) {
|
||||
JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method()));
|
||||
arg = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>of(maker.Ident(type.toName("this"))));
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method()));
|
||||
tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>of(maker.Ident(type.toName("this"))));
|
||||
}
|
||||
} else {
|
||||
JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method()));
|
||||
arg = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil());
|
||||
for (int i = 0; i < tgt.length; i++) {
|
||||
JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method()));
|
||||
tgt[i] = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JCExpression arg;
|
||||
if (bfd.singularData == null) {
|
||||
arg = tgt[0];
|
||||
} else {
|
||||
JCExpression eqNull = maker.Binary(CTC_EQUAL, tgt[0], maker.Literal(CTC_BOT, null));
|
||||
JCExpression emptyList = maker.Apply(List.<JCExpression>nil(), chainDots(type, "java", "util", "Collections", "emptyList"), List.<JCExpression>nil());
|
||||
arg = maker.Conditional(eqNull, emptyList, tgt[1]);
|
||||
}
|
||||
|
||||
invoke = maker.Apply(List.<JCExpression>nil(), maker.Select(invoke, setterName), List.of(arg));
|
||||
}
|
||||
JCStatement statement = maker.Return(invoke);
|
||||
|
||||
@@ -44,7 +44,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
|
||||
/**
|
||||
* Handles the {@code lombok.FieldDefaults} annotation for eclipse.
|
||||
* Handles the {@code lombok.FieldDefaults} annotation for javac.
|
||||
*/
|
||||
@ProviderFor(JavacASTVisitor.class)
|
||||
@HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier.
|
||||
|
||||
@@ -24,13 +24,11 @@ package lombok.javac.handlers;
|
||||
import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
|
||||
import static lombok.javac.handlers.JavacHandlerUtil.*;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.ConfigurationKeys;
|
||||
import lombok.core.AST.Kind;
|
||||
import lombok.core.handlers.HandlerUtil;
|
||||
import lombok.core.AnnotationValues;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.javac.JavacAnnotationHandler;
|
||||
@@ -40,16 +38,23 @@ import lombok.javac.JavacTreeMaker;
|
||||
import org.mangosdk.spi.ProviderFor;
|
||||
|
||||
import com.sun.tools.javac.code.Flags;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBlock;
|
||||
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCModifiers;
|
||||
import com.sun.tools.javac.tree.JCTree.JCStatement;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.Name;
|
||||
|
||||
@ProviderFor(JavacAnnotationHandler.class)
|
||||
public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameConstants> {
|
||||
public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, String prefix, String suffix) {
|
||||
public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) {
|
||||
JCClassDecl typeDecl = null;
|
||||
if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
|
||||
|
||||
@@ -57,22 +62,31 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
|
||||
boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
|
||||
|
||||
if (typeDecl == null || notAClass) {
|
||||
errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field.");
|
||||
errorNode.addError("@FieldNameConstants is only supported on a class or an enum.");
|
||||
return;
|
||||
}
|
||||
|
||||
java.util.List<JavacNode> qualified = new ArrayList<JavacNode>();
|
||||
|
||||
for (JavacNode field : typeNode.down()) {
|
||||
if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level, prefix, suffix);
|
||||
if (fieldQualifiesForFieldNameConstantsGeneration(field, onlyExplicit)) qualified.add(field);
|
||||
}
|
||||
|
||||
if (qualified.isEmpty()) {
|
||||
errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing");
|
||||
} else {
|
||||
createInnerTypeFieldNameConstants(typeNode, errorNode.get(), level, qualified, asEnum, innerTypeName);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateFieldNameConstantsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, String prefix, String suffix) {
|
||||
if (hasAnnotation(FieldNameConstants.class, fieldNode)) return;
|
||||
createFieldNameConstantsForField(level, prefix, suffix, fieldNode, fieldNode, false);
|
||||
}
|
||||
|
||||
private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field) {
|
||||
private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field, boolean onlyExplicit) {
|
||||
if (field.getKind() != Kind.FIELD) return false;
|
||||
boolean exclAnn = JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(FieldNameConstants.Exclude.class, field);
|
||||
boolean inclAnn = JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(FieldNameConstants.Include.class, field);
|
||||
if (exclAnn) return false;
|
||||
if (inclAnn) return true;
|
||||
if (onlyExplicit) return false;
|
||||
|
||||
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
|
||||
if (fieldDecl.name.toString().startsWith("$")) return false;
|
||||
if ((fieldDecl.mods.flags & Flags.STATIC) != 0) return false;
|
||||
@@ -82,56 +96,61 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler<FieldNameCo
|
||||
public void handle(AnnotationValues<FieldNameConstants> annotation, JCAnnotation ast, JavacNode annotationNode) {
|
||||
handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_NAME_CONSTANTS_FLAG_USAGE, "@FieldNameConstants");
|
||||
|
||||
Collection<JavacNode> fields = annotationNode.upFromAnnotationToFields();
|
||||
deleteAnnotationIfNeccessary(annotationNode, FieldNameConstants.class);
|
||||
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
|
||||
JavacNode node = annotationNode.up();
|
||||
FieldNameConstants annotatationInstance = annotation.getInstance();
|
||||
AccessLevel level = annotatationInstance.level();
|
||||
String prefix = annotatationInstance.prefix();
|
||||
String suffix = annotatationInstance.suffix();
|
||||
if (prefix.equals(" CONFIG DEFAULT ")) prefix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_PREFIX);
|
||||
if (suffix.equals(" CONFIG DEFAULT ")) suffix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_SUFFIX);
|
||||
if (prefix == null) prefix = "FIELD_";
|
||||
if (suffix == null) suffix = "";
|
||||
if (node == null) return;
|
||||
switch (node.getKind()) {
|
||||
case FIELD:
|
||||
if (level != AccessLevel.NONE) createFieldNameConstantsForFields(level, prefix, suffix, fields, annotationNode, annotationNode, true);
|
||||
break;
|
||||
case TYPE:
|
||||
if (level == AccessLevel.NONE) {
|
||||
annotationNode.addWarning("type-level '@FieldNameConstants' does not work with AccessLevel.NONE.");
|
||||
return;
|
||||
FieldNameConstants annotationInstance = annotation.getInstance();
|
||||
AccessLevel level = annotationInstance.level();
|
||||
boolean asEnum = annotationInstance.asEnum();
|
||||
boolean usingLombokv1_18_2 = annotation.isExplicit("prefix") || annotation.isExplicit("suffix") || node.getKind() == Kind.FIELD;
|
||||
|
||||
if (usingLombokv1_18_2) {
|
||||
annotationNode.addError("@FieldNameConstants has been redesigned in lombok v1.18.4; please upgrade your project dependency on lombok. See https://projectlombok.org/features/experimental/FieldNameConstants for more information.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (level == AccessLevel.NONE) {
|
||||
annotationNode.addWarning("AccessLevel.NONE is not compatible with @FieldNameConstants. If you don't want the inner type, simply remove @FieldNameConstants.");
|
||||
return;
|
||||
}
|
||||
|
||||
String innerTypeName = annotationInstance.innerTypeName();
|
||||
if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME);
|
||||
if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields";
|
||||
|
||||
generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded());
|
||||
}
|
||||
|
||||
private void createInnerTypeFieldNameConstants(JavacNode typeNode, DiagnosticPosition pos, AccessLevel level, java.util.List<JavacNode> fields, boolean asEnum, String innerTypeName) {
|
||||
if (fields.isEmpty()) return;
|
||||
|
||||
JavacTreeMaker maker = typeNode.getTreeMaker();
|
||||
JCModifiers mods = maker.Modifiers(toJavacModifier(level) | (asEnum ? Flags.ENUM : Flags.STATIC | Flags.FINAL));
|
||||
|
||||
Name fieldsName = typeNode.toName(innerTypeName);
|
||||
JCClassDecl innerType = maker.ClassDef(mods, fieldsName, List.<JCTypeParameter>nil(), null, List.<JCExpression>nil(), List.<JCTree>nil());
|
||||
JavacNode innerNode = injectType(typeNode, innerType);
|
||||
|
||||
JCModifiers genConstrMods = maker.Modifiers(Flags.GENERATEDCONSTR | (asEnum ? 0L : Flags.PRIVATE));
|
||||
JCBlock genConstrBody = maker.Block(0L, List.<JCStatement>of(maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(typeNode.toName("super")), List.<JCExpression>nil()))));
|
||||
JCMethodDecl genConstr = maker.MethodDef(genConstrMods, typeNode.toName("<init>"), null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), genConstrBody, null);
|
||||
|
||||
injectMethod(innerNode, genConstr);
|
||||
|
||||
for (JavacNode field : fields) {
|
||||
JCModifiers enumValueMods = maker.Modifiers(Flags.PUBLIC | Flags.STATIC | Flags.FINAL | (asEnum ? Flags.ENUM : 0L));
|
||||
JCExpression returnType;
|
||||
JCExpression init;
|
||||
if (asEnum) {
|
||||
returnType = maker.Ident(fieldsName);
|
||||
init = maker.NewClass(null, List.<JCExpression>nil(), maker.Ident(fieldsName), List.<JCExpression>nil(), null);
|
||||
} else {
|
||||
returnType = chainDots(field, "java", "lang", "String");
|
||||
init = maker.Literal(field.getName());
|
||||
}
|
||||
generateFieldNameConstantsForType(node, annotationNode, level, prefix, suffix);
|
||||
break;
|
||||
JCVariableDecl enumField = maker.VarDef(enumValueMods, ((JCVariableDecl) field.get()).name, returnType, init);
|
||||
injectField(innerNode, enumField);
|
||||
}
|
||||
}
|
||||
|
||||
private void createFieldNameConstantsForFields(AccessLevel level, String prefix, String suffix, Collection<JavacNode> fieldNodes, JavacNode annotationNode, JavacNode errorNode, boolean whineIfExists) {
|
||||
for (JavacNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, prefix, suffix, fieldNode, errorNode, whineIfExists);
|
||||
}
|
||||
|
||||
private void createFieldNameConstantsForField(AccessLevel level, String prefix, String suffix, JavacNode fieldNode, JavacNode source, boolean whineIfExists) {
|
||||
if (fieldNode.getKind() != Kind.FIELD) {
|
||||
source.addError("@FieldNameConstants is only supported on a class, an enum, or a field");
|
||||
return;
|
||||
}
|
||||
|
||||
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
|
||||
String fieldName = field.name.toString();
|
||||
String constantName = prefix + HandlerUtil.camelCaseToConstant(fieldName) + suffix;
|
||||
if (constantName.equals(fieldName)) {
|
||||
fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field.");
|
||||
return;
|
||||
}
|
||||
|
||||
JavacTreeMaker treeMaker = fieldNode.getTreeMaker();
|
||||
JCModifiers modifiers = treeMaker.Modifiers(toJavacModifier(level) | Modifier.STATIC | Modifier.FINAL);
|
||||
JCExpression returnType = chainDots(fieldNode, "java", "lang", "String");
|
||||
JCExpression init = treeMaker.Literal(fieldNode.getName());
|
||||
JCVariableDecl fieldConstant = treeMaker.VarDef(modifiers, fieldNode.toName(constantName), returnType, init);
|
||||
injectField(fieldNode.up(), fieldConstant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ module lombok {
|
||||
requires java.compiler;
|
||||
requires java.instrument;
|
||||
requires jdk.unsupported;
|
||||
requires static org.mapstruct.processor;
|
||||
|
||||
exports lombok;
|
||||
exports lombok.experimental;
|
||||
@@ -36,4 +37,3 @@ module lombok {
|
||||
provides javax.annotation.processing.Processor with lombok.launch.AnnotationProcessorHider.AnnotationProcessor;
|
||||
provides org.mapstruct.ap.spi.AstModifyingAnnotationProcessor with lombok.launch.AnnotationProcessorHider.AstModificationNotifier;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import lombok.core.Version;
|
||||
public class PatchFixesShadowLoaded {
|
||||
public static String addLombokNotesToEclipseAboutDialog(String origReturnValue, String key) {
|
||||
if ("aboutText".equals(key)) {
|
||||
if (origReturnValue.contains(" is installed. https://projectlombok.org")) return origReturnValue;
|
||||
return origReturnValue + "\n\nLombok " + Version.getFullVersion() + " is installed. https://projectlombok.org/";
|
||||
}
|
||||
return origReturnValue;
|
||||
|
||||
@@ -210,16 +210,16 @@ public class PatchVal {
|
||||
if (local == null || !LocalDeclaration.class.equals(local.getClass())) return false;
|
||||
boolean decomponent = false;
|
||||
|
||||
boolean val = isVal(local, scope);
|
||||
boolean var = isVar(local, scope);
|
||||
if (!(val || var)) return false;
|
||||
boolean val = isVal(local, scope);
|
||||
boolean var = isVar(local, scope);
|
||||
if (!(val || var)) return false;
|
||||
|
||||
StackTraceElement[] st = new Throwable().getStackTrace();
|
||||
for (int i = 0; i < st.length - 2 && i < 10; i++) {
|
||||
if (st[i].getClassName().equals("lombok.launch.PatchFixesHider$Val")) {
|
||||
boolean valInForStatement = val &&
|
||||
st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
|
||||
st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement");
|
||||
st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
|
||||
st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement");
|
||||
if (valInForStatement) return false;
|
||||
break;
|
||||
}
|
||||
@@ -269,7 +269,7 @@ public class PatchVal {
|
||||
}
|
||||
}
|
||||
|
||||
if(val) local.modifiers |= ClassFileConstants.AccFinal;
|
||||
if (val) local.modifiers |= ClassFileConstants.AccFinal;
|
||||
local.annotations = addValAnnotation(local.annotations, local.type, scope);
|
||||
local.type = replacement != null ? replacement : new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(local.type, 3));
|
||||
|
||||
@@ -298,7 +298,7 @@ public class PatchVal {
|
||||
if (val) forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
|
||||
forEach.elementVariable.annotations = addValAnnotation(forEach.elementVariable.annotations, forEach.elementVariable.type, scope);
|
||||
forEach.elementVariable.type = replacement != null ? replacement :
|
||||
new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3));
|
||||
new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -326,7 +326,7 @@ public class PatchVal {
|
||||
resolved = ((ArrayBinding) resolved).elementsType();
|
||||
return resolved;
|
||||
} else if (resolved instanceof ReferenceBinding) {
|
||||
ReferenceBinding iterableType = ((ReferenceBinding)resolved).findSuperTypeOriginatingFrom(TypeIds.T_JavaLangIterable, false);
|
||||
ReferenceBinding iterableType = ((ReferenceBinding) resolved).findSuperTypeOriginatingFrom(TypeIds.T_JavaLangIterable, false);
|
||||
|
||||
TypeBinding[] arguments = null;
|
||||
if (iterableType != null) switch (iterableType.kind()) {
|
||||
|
||||
@@ -47,9 +47,9 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
|
||||
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
|
||||
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
|
||||
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
|
||||
import org.eclipse.jdt.internal.compiler.parser.Parser;
|
||||
|
||||
public class PatchValEclipse {
|
||||
@@ -103,6 +103,10 @@ public class PatchValEclipse {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean couldBeVal(ImportReference[] imports, TypeReference type) {
|
||||
return PatchVal.couldBe(imports, "lombok.val", type);
|
||||
}
|
||||
|
||||
private static boolean couldBeVar(ImportReference[] imports, TypeReference type) {
|
||||
return PatchVal.couldBe(imports, "lombok.experimental.var", type) || PatchVal.couldBe(imports, "lombok.var", type);
|
||||
}
|
||||
@@ -118,17 +122,18 @@ public class PatchValEclipse {
|
||||
}
|
||||
|
||||
public static void addFinalAndValAnnotationToModifierList(Object converter, List<IExtendedModifier> modifiers, AST ast, LocalDeclaration in) {
|
||||
// First check that 'in' has the final flag on, and a @val / @lombok.val annotation.
|
||||
if ((in.modifiers & ClassFileConstants.AccFinal) == 0) return;
|
||||
// First check that 'in' has the final flag on, and a @val / @lombok.val / @var / @lombok.var annotation.
|
||||
if (in.annotations == null) return;
|
||||
boolean found = false;
|
||||
Annotation valAnnotation = null;
|
||||
|
||||
Annotation valAnnotation = null, varAnnotation = null;
|
||||
for (Annotation ann : in.annotations) {
|
||||
if (couldBeVal(null, ann.type)) {
|
||||
found = true;
|
||||
valAnnotation = ann;
|
||||
break;
|
||||
}
|
||||
if (couldBeVar(null, ann.type)) {
|
||||
found = true;
|
||||
varAnnotation = ann;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,10 +144,11 @@ public class PatchValEclipse {
|
||||
if (modifiers == null) return; // This is null only if the project is 1.4 or less. Lombok doesn't work in that.
|
||||
boolean finalIsPresent = false;
|
||||
boolean valIsPresent = false;
|
||||
boolean varIsPresent = false;
|
||||
|
||||
for (Object present : modifiers) {
|
||||
if (present instanceof Modifier) {
|
||||
ModifierKeyword keyword = ((Modifier)present).getKeyword();
|
||||
ModifierKeyword keyword = ((Modifier) present).getKeyword();
|
||||
if (keyword == null) continue;
|
||||
if (keyword.toFlagValue() == Modifier.FINAL) finalIsPresent = true;
|
||||
}
|
||||
@@ -151,20 +157,18 @@ public class PatchValEclipse {
|
||||
Name typeName = ((org.eclipse.jdt.core.dom.Annotation) present).getTypeName();
|
||||
if (typeName != null) {
|
||||
String fullyQualifiedName = typeName.getFullyQualifiedName();
|
||||
if ("val".equals(fullyQualifiedName) || "lombok.val".equals(fullyQualifiedName)) {
|
||||
valIsPresent = true;
|
||||
}
|
||||
if ("val".equals(fullyQualifiedName) || "lombok.val".equals(fullyQualifiedName)) valIsPresent = true;
|
||||
if ("var".equals(fullyQualifiedName) || "lombok.var".equals(fullyQualifiedName) || "lombok.experimental.var".equals(fullyQualifiedName)) varIsPresent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!finalIsPresent) {
|
||||
modifiers.add(
|
||||
createModifier(ast, ModifierKeyword.FINAL_KEYWORD, valAnnotation.sourceStart, valAnnotation.sourceEnd));
|
||||
if (!finalIsPresent && valAnnotation != null) {
|
||||
modifiers.add(createModifier(ast, ModifierKeyword.FINAL_KEYWORD, valAnnotation.sourceStart, valAnnotation.sourceEnd));
|
||||
}
|
||||
|
||||
if (!valIsPresent) {
|
||||
MarkerAnnotation newAnnotation = createValAnnotation(ast, valAnnotation, valAnnotation.sourceStart, valAnnotation.sourceEnd);
|
||||
if (!valIsPresent && valAnnotation != null) {
|
||||
MarkerAnnotation newAnnotation = createValVarAnnotation(ast, valAnnotation, valAnnotation.sourceStart, valAnnotation.sourceEnd);
|
||||
try {
|
||||
Reflection.astConverterRecordNodes.invoke(converter, newAnnotation, valAnnotation);
|
||||
Reflection.astConverterRecordNodes.invoke(converter, newAnnotation.getTypeName(), valAnnotation.type);
|
||||
@@ -175,10 +179,19 @@ public class PatchValEclipse {
|
||||
}
|
||||
modifiers.add(newAnnotation);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean couldBeVal(ImportReference[] imports, TypeReference type) {
|
||||
return PatchVal.couldBe(imports, "lombok.val", type);
|
||||
|
||||
if (!varIsPresent && varAnnotation != null) {
|
||||
MarkerAnnotation newAnnotation = createValVarAnnotation(ast, varAnnotation, varAnnotation.sourceStart, varAnnotation.sourceEnd);
|
||||
try {
|
||||
Reflection.astConverterRecordNodes.invoke(converter, newAnnotation, varAnnotation);
|
||||
Reflection.astConverterRecordNodes.invoke(converter, newAnnotation.getTypeName(), varAnnotation.type);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw Lombok.sneakyThrow(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw Lombok.sneakyThrow(e.getCause());
|
||||
}
|
||||
modifiers.add(newAnnotation);
|
||||
}
|
||||
}
|
||||
|
||||
public static Modifier createModifier(AST ast, ModifierKeyword keyword, int start, int end) {
|
||||
@@ -200,7 +213,7 @@ public class PatchValEclipse {
|
||||
return modifier;
|
||||
}
|
||||
|
||||
public static MarkerAnnotation createValAnnotation(AST ast, Annotation original, int start, int end) {
|
||||
public static MarkerAnnotation createValVarAnnotation(AST ast, Annotation original, int start, int end) {
|
||||
MarkerAnnotation out = null;
|
||||
try {
|
||||
out = Reflection.markerAnnotationConstructor.newInstance(ast);
|
||||
@@ -212,13 +225,23 @@ public class PatchValEclipse {
|
||||
throw Lombok.sneakyThrow(e);
|
||||
}
|
||||
|
||||
char[][] tokens;
|
||||
if (original.type instanceof SingleTypeReference) {
|
||||
tokens = new char[1][];
|
||||
tokens[0] = ((SingleTypeReference) original.type).token;
|
||||
} else if (original.type instanceof QualifiedTypeReference) {
|
||||
tokens = ((QualifiedTypeReference) original.type).tokens;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (out != null) {
|
||||
SimpleName valName = ast.newSimpleName("val");
|
||||
SimpleName valName = ast.newSimpleName(new String(tokens[tokens.length - 1]));
|
||||
valName.setSourceRange(start, end - start + 1);
|
||||
if (original.type instanceof SingleTypeReference) {
|
||||
if (tokens.length == 1) {
|
||||
out.setTypeName(valName);
|
||||
setIndex(valName, 1);
|
||||
} else {
|
||||
} else if (tokens.length == 2) {
|
||||
SimpleName lombokName = ast.newSimpleName("lombok");
|
||||
lombokName.setSourceRange(start, end - start + 1);
|
||||
setIndex(lombokName, 1);
|
||||
@@ -227,6 +250,21 @@ public class PatchValEclipse {
|
||||
setIndex(fullName, 1);
|
||||
fullName.setSourceRange(start, end - start + 1);
|
||||
out.setTypeName(fullName);
|
||||
} else {
|
||||
SimpleName lombokName = ast.newSimpleName("lombok");
|
||||
lombokName.setSourceRange(start, end - start + 1);
|
||||
SimpleName experimentalName = ast.newSimpleName("experimental");
|
||||
lombokName.setSourceRange(start, end - start + 1);
|
||||
setIndex(lombokName, 1);
|
||||
setIndex(experimentalName, 2);
|
||||
setIndex(valName, 3);
|
||||
QualifiedName lombokExperimentalName = ast.newQualifiedName(lombokName, experimentalName);
|
||||
lombokExperimentalName.setSourceRange(start, end - start + 1);
|
||||
setIndex(lombokExperimentalName, 1);
|
||||
QualifiedName fullName = ast.newQualifiedName(lombokExperimentalName, valName);
|
||||
setIndex(fullName, 1);
|
||||
fullName.setSourceRange(start, end - start + 1);
|
||||
out.setTypeName(fullName);
|
||||
}
|
||||
out.setSourceRange(start, end - start + 1);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ final class PatchFixesHider {
|
||||
shadowLoader = Util.class.getClassLoader();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// If we get here, it isn't, and we should use the shadowloader.
|
||||
shadowLoader = Main.createShadowClassLoader();
|
||||
shadowLoader = Main.getShadowClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ final class Agent {
|
||||
}
|
||||
|
||||
private static void runLauncher(String agentArgs, Instrumentation instrumentation, boolean injected) throws Throwable {
|
||||
ClassLoader cl = Main.createShadowClassLoader();
|
||||
ClassLoader cl = Main.getShadowClassLoader();
|
||||
try {
|
||||
Class<?> c = cl.loadClass("lombok.core.AgentLauncher");
|
||||
Method m = c.getDeclaredMethod("runAgents", String.class, Instrumentation.class, boolean.class, Class.class);
|
||||
|
||||
@@ -104,7 +104,7 @@ class AnnotationProcessorHider {
|
||||
}
|
||||
|
||||
private static AbstractProcessor createWrappedInstance() {
|
||||
ClassLoader cl = Main.createShadowClassLoader();
|
||||
ClassLoader cl = Main.getShadowClassLoader();
|
||||
try {
|
||||
Class<?> mc = cl.loadClass("lombok.core.AnnotationProcessor");
|
||||
return (AbstractProcessor) mc.getDeclaredConstructor().newInstance();
|
||||
|
||||
@@ -25,12 +25,18 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
|
||||
class Main {
|
||||
static ClassLoader createShadowClassLoader() {
|
||||
return new ShadowClassLoader(Main.class.getClassLoader(), "lombok", null, Arrays.<String>asList(), Arrays.asList("lombok.patcher.Symbols"));
|
||||
|
||||
private static ShadowClassLoader classLoader;
|
||||
|
||||
static synchronized ClassLoader getShadowClassLoader() {
|
||||
if (classLoader == null) {
|
||||
classLoader = new ShadowClassLoader(Main.class.getClassLoader(), "lombok", null, Arrays.<String>asList(), Arrays.asList("lombok.patcher.Symbols"));
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ClassLoader cl = createShadowClassLoader();
|
||||
ClassLoader cl = getShadowClassLoader();
|
||||
Class<?> mc = cl.loadClass("lombok.core.Main");
|
||||
try {
|
||||
mc.getMethod("main", String[].class).invoke(null, new Object[] {args});
|
||||
|
||||
@@ -296,17 +296,18 @@ class ShadowClassLoader extends ClassLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean partOfShadow(URL item, String name) {
|
||||
return inOwnBase(item, name) || isPartOfShadowSuffix(item, name, sclSuffix);
|
||||
private boolean partOfShadow(String item, String name) {
|
||||
return !name.startsWith("java/")
|
||||
&& !name.startsWith("sun/")
|
||||
&& (inOwnBase(item, name) || isPartOfShadowSuffix(item, name, sclSuffix));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the stated item is located inside the same classpath root as the jar that hosts ShadowClassLoader.class. {@code item} and {@code name} refer to the same thing.
|
||||
*/
|
||||
private boolean inOwnBase(URL item, String name) {
|
||||
private boolean inOwnBase(String item, String name) {
|
||||
if (item == null) return false;
|
||||
String itemString = item.toString();
|
||||
return (itemString.length() == SELF_BASE_LENGTH + name.length()) && SELF_BASE.regionMatches(0, itemString, 0, SELF_BASE_LENGTH);
|
||||
return (item.length() == SELF_BASE_LENGTH + name.length()) && SELF_BASE.regionMatches(0, item, 0, SELF_BASE_LENGTH);
|
||||
}
|
||||
|
||||
private static boolean sclFileContainsSuffix(InputStream in, String suffix) throws IOException {
|
||||
@@ -386,12 +387,11 @@ class ShadowClassLoader extends ClassLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPartOfShadowSuffix(URL item, String name, String suffix) {
|
||||
private boolean isPartOfShadowSuffix(String url, String name, String suffix) {
|
||||
// Instead of throwing an exception or logging, weird, unexpected cases just return false.
|
||||
// This is better than throwing an exception, because exceptions would make your build tools unusable.
|
||||
// Such cases are marked with the comment: // *unexpected*
|
||||
if (item == null) return false;
|
||||
String url = item.toString();
|
||||
if (url == null) return false;
|
||||
if (url.startsWith("file:/")) {
|
||||
url = urlDecode(url.substring(5));
|
||||
if (url.length() <= name.length() || !url.endsWith(name) || url.charAt(url.length() - name.length() - 1) != '/') {
|
||||
@@ -436,14 +436,14 @@ class ShadowClassLoader extends ClassLoader {
|
||||
Enumeration<URL> sec = super.getResources(name);
|
||||
while (sec.hasMoreElements()) {
|
||||
URL item = sec.nextElement();
|
||||
if (!partOfShadow(item, name)) vector.add(item);
|
||||
if (!partOfShadow(item.toString(), name)) vector.add(item);
|
||||
}
|
||||
|
||||
if (altName != null) {
|
||||
Enumeration<URL> tern = super.getResources(altName);
|
||||
while (tern.hasMoreElements()) {
|
||||
URL item = tern.nextElement();
|
||||
if (!partOfShadow(item, altName)) vector.add(item);
|
||||
if (!partOfShadow(item.toString(), altName)) vector.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,11 +483,11 @@ class ShadowClassLoader extends ClassLoader {
|
||||
|
||||
if (altName != null) {
|
||||
URL res = super.getResource(altName);
|
||||
if (res != null && (!noSuper || partOfShadow(res, altName))) return res;
|
||||
if (res != null && (!noSuper || partOfShadow(res.toString(), altName))) return res;
|
||||
}
|
||||
|
||||
URL res = super.getResource(name);
|
||||
if (res != null && (!noSuper || partOfShadow(res, name))) return res;
|
||||
if (res != null && (!noSuper || partOfShadow(res.toString(), name))) return res;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -501,12 +501,12 @@ class ShadowClassLoader extends ClassLoader {
|
||||
private URL getResourceSkippingSelf(String name) throws IOException {
|
||||
URL candidate = super.getResource(name);
|
||||
if (candidate == null) return null;
|
||||
if (!partOfShadow(candidate, name)) return candidate;
|
||||
if (!partOfShadow(candidate.toString(), name)) return candidate;
|
||||
|
||||
Enumeration<URL> en = super.getResources(name);
|
||||
while (en.hasMoreElements()) {
|
||||
candidate = en.nextElement();
|
||||
if (!partOfShadow(candidate, name)) return candidate;
|
||||
if (!partOfShadow(candidate.toString(), name)) return candidate;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -526,9 +526,14 @@ class ShadowClassLoader extends ClassLoader {
|
||||
String fileNameOfClass = name.replace(".", "/") + ".class";
|
||||
URL res = getResource_(fileNameOfClass, true);
|
||||
if (res == null) {
|
||||
if (!exclusionListMatch(fileNameOfClass)) return super.loadClass(name, resolve);
|
||||
throw new ClassNotFoundException(name);
|
||||
if (!exclusionListMatch(fileNameOfClass)) try {
|
||||
return super.loadClass(name, resolve);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
res = getResource_("secondaryLoading.SCL." + sclSuffix + "/" + name.replace(".", "/") + ".SCL." + sclSuffix, true);
|
||||
if (res == null) throw cnfe;
|
||||
}
|
||||
}
|
||||
if (res == null) throw new ClassNotFoundException(name);
|
||||
|
||||
byte[] b;
|
||||
int p = 0;
|
||||
|
||||
@@ -56,6 +56,8 @@ public class Eclipse {
|
||||
*/
|
||||
public static final int ECLIPSE_DO_NOT_TOUCH_FLAG = ASTNode.Bit24;
|
||||
|
||||
private static final Pattern SPLIT_AT_DOT = Pattern.compile("\\.");
|
||||
|
||||
private Eclipse() {
|
||||
//Prevent instantiation
|
||||
}
|
||||
@@ -65,19 +67,25 @@ public class Eclipse {
|
||||
* but we need to deal with it. This turns [[java][lang][String]] into "java.lang.String".
|
||||
*/
|
||||
public static String toQualifiedName(char[][] typeName) {
|
||||
int len = typeName.length - 1;
|
||||
int len = typeName.length - 1; // number of dots
|
||||
if (len == 0) return new String(typeName[0]);
|
||||
|
||||
for (char[] c : typeName) len += c.length;
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
boolean first = true;
|
||||
for (char[] c : typeName) {
|
||||
sb.append(first ? "" : ".").append(c);
|
||||
first = false;
|
||||
char[] ret = new char[len];
|
||||
char[] part = typeName[0];
|
||||
System.arraycopy(part, 0, ret, 0, part.length);
|
||||
int pos = part.length;
|
||||
for (int i = 1; i < typeName.length; i++) {
|
||||
ret[pos++] = '.';
|
||||
part = typeName[i];
|
||||
System.arraycopy(part, 0, ret, pos, part.length);
|
||||
pos += part.length;
|
||||
}
|
||||
return sb.toString();
|
||||
return new String(ret);
|
||||
}
|
||||
|
||||
public static char[][] fromQualifiedName(String typeName) {
|
||||
String[] split = typeName.split("\\.");
|
||||
String[] split = SPLIT_AT_DOT.split(typeName);
|
||||
char[][] result = new char[split.length][];
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
result[i] = split[i].toCharArray();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2014 The Project Lombok Authors.
|
||||
* Copyright (C) 2009-2018 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
|
||||
@@ -30,6 +30,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
@@ -40,7 +41,6 @@ import java.util.Map;
|
||||
import org.junit.Assert;
|
||||
|
||||
import lombok.DirectoryRunner.FileTester;
|
||||
import lombok.core.AST;
|
||||
import lombok.core.LombokConfiguration;
|
||||
import lombok.core.LombokImmutableList;
|
||||
import lombok.core.configuration.ConfigurationKeysLoader;
|
||||
@@ -84,7 +84,7 @@ public abstract class AbstractRunTests {
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
LombokConfiguration.overrideConfigurationResolverFactory(new ConfigurationResolverFactory() {
|
||||
@Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
|
||||
@Override public ConfigurationResolver createResolver(URI sourceLocation) {
|
||||
return sourceDirectives_.getConfiguration();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -122,7 +122,7 @@ public class RunTestsViaEcj extends AbstractRunTests {
|
||||
|
||||
CompilationUnitDeclaration cud = compilationUnit_.get();
|
||||
|
||||
if (cud == null) result.append("---- NO CompilationUnit provided by ecj ----");
|
||||
if (cud == null) result.append("---- No CompilationUnit provided by ecj ----");
|
||||
else result.append(cud.toString());
|
||||
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
class BuilderSingularToBuilderWithNull {
|
||||
private java.util.List<String> elems;
|
||||
public static void test() {
|
||||
new BuilderSingularToBuilderWithNull(null).toBuilder();
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
BuilderSingularToBuilderWithNull(final java.util.List<String> elems) {
|
||||
this.elems = elems;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static class BuilderSingularToBuilderWithNullBuilder {
|
||||
@java.lang.SuppressWarnings("all")
|
||||
private java.util.ArrayList<String> elems;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
BuilderSingularToBuilderWithNullBuilder() {
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public BuilderSingularToBuilderWithNullBuilder elem(final String elem) {
|
||||
if (this.elems == null) this.elems = new java.util.ArrayList<String>();
|
||||
this.elems.add(elem);
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public BuilderSingularToBuilderWithNullBuilder elems(final java.util.Collection<? extends String> elems) {
|
||||
if (this.elems == null) this.elems = new java.util.ArrayList<String>();
|
||||
this.elems.addAll(elems);
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public BuilderSingularToBuilderWithNullBuilder clearElems() {
|
||||
if (this.elems != null) this.elems.clear();
|
||||
return this;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public BuilderSingularToBuilderWithNull build() {
|
||||
java.util.List<String> elems;
|
||||
switch (this.elems == null ? 0 : this.elems.size()) {
|
||||
case 0:
|
||||
elems = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1:
|
||||
elems = java.util.Collections.singletonList(this.elems.get(0));
|
||||
break;
|
||||
default:
|
||||
elems = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.elems));
|
||||
}
|
||||
return new BuilderSingularToBuilderWithNull(elems);
|
||||
}
|
||||
@java.lang.Override
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public java.lang.String toString() {
|
||||
return "BuilderSingularToBuilderWithNull.BuilderSingularToBuilderWithNullBuilder(elems=" + this.elems + ")";
|
||||
}
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static BuilderSingularToBuilderWithNullBuilder builder() {
|
||||
return new BuilderSingularToBuilderWithNullBuilder();
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public BuilderSingularToBuilderWithNullBuilder toBuilder() {
|
||||
return new BuilderSingularToBuilderWithNullBuilder().elems(this.elems == null ? java.util.Collections.emptyList() : this.elems);
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ class BuilderWithToBuilder<T> {
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public BuilderWithToBuilderBuilder<T> toBuilder() {
|
||||
return new BuilderWithToBuilderBuilder<T>().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars);
|
||||
return new BuilderWithToBuilderBuilder<T>().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars == null ? java.util.Collections.emptyList() : this.bars);
|
||||
}
|
||||
}
|
||||
class ConstructorWithToBuilder<T> {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
public class FieldNameConstantsBasic {
|
||||
protected static final java.lang.String FIELD_I_AM_A_DVD_PLAYER = "iAmADvdPlayer";
|
||||
public static final java.lang.String FIELD_BUT_PRINT_ME_PLEASE = "butPrintMePlease";
|
||||
String iAmADvdPlayer;
|
||||
int $skipMe;
|
||||
static double skipMeToo;
|
||||
int andMe;
|
||||
String butPrintMePlease;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
static final class Fields {
|
||||
public static final java.lang.String butPrintMePlease = "butPrintMePlease";
|
||||
public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
public class FieldNameConstantsConfigKeys {
|
||||
public static final java.lang.String I_AM_A_DVD_PLAYER_SFX = "iAmADvdPlayer";
|
||||
String iAmADvdPlayer;
|
||||
}
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public static final class Foobar {
|
||||
public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class FieldNameConstantsEnum {
|
||||
String iAmADvdPlayer;
|
||||
int $dontSkipMe;
|
||||
static double alsoDontSkipMe;
|
||||
int butSkipMe;
|
||||
@java.lang.SuppressWarnings("all")
|
||||
public enum TypeTest {
|
||||
iAmADvdPlayer, $dontSkipMe, alsoDontSkipMe;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
public class FieldNameConstantsWeird {
|
||||
public static final java.lang.String FIELD_AZ = "A";
|
||||
String iAmADvdPlayer;
|
||||
String X;
|
||||
String A;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import lombok.Singular;
|
||||
@lombok.Builder(toBuilder = true) class BuilderSingularToBuilderWithNull {
|
||||
public static @java.lang.SuppressWarnings("all") class BuilderSingularToBuilderWithNullBuilder {
|
||||
private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> elems;
|
||||
@java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder() {
|
||||
super();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder elem(String elem) {
|
||||
if ((this.elems == null))
|
||||
this.elems = new java.util.ArrayList<String>();
|
||||
this.elems.add(elem);
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder elems(java.util.Collection<? extends String> elems) {
|
||||
if ((this.elems == null))
|
||||
this.elems = new java.util.ArrayList<String>();
|
||||
this.elems.addAll(elems);
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder clearElems() {
|
||||
if ((this.elems != null))
|
||||
this.elems.clear();
|
||||
return this;
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNull build() {
|
||||
java.util.List<String> elems;
|
||||
switch (((this.elems == null) ? 0 : this.elems.size())) {
|
||||
case 0 :
|
||||
elems = java.util.Collections.emptyList();
|
||||
break;
|
||||
case 1 :
|
||||
elems = java.util.Collections.singletonList(this.elems.get(0));
|
||||
break;
|
||||
default :
|
||||
elems = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.elems));
|
||||
}
|
||||
return new BuilderSingularToBuilderWithNull(elems);
|
||||
}
|
||||
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
|
||||
return (("BuilderSingularToBuilderWithNull.BuilderSingularToBuilderWithNullBuilder(elems=" + this.elems) + ")");
|
||||
}
|
||||
}
|
||||
private @Singular java.util.List<String> elems;
|
||||
public static void test() {
|
||||
new BuilderSingularToBuilderWithNull(null).toBuilder();
|
||||
}
|
||||
@java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNull(final java.util.List<String> elems) {
|
||||
super();
|
||||
this.elems = elems;
|
||||
}
|
||||
public static @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder builder() {
|
||||
return new BuilderSingularToBuilderWithNullBuilder();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") BuilderSingularToBuilderWithNullBuilder toBuilder() {
|
||||
return new BuilderSingularToBuilderWithNullBuilder().elems(((this.elems == null) ? java.util.Collections.emptyList() : this.elems));
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ import lombok.Builder;
|
||||
return new BuilderWithToBuilderBuilder<T>();
|
||||
}
|
||||
public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> toBuilder() {
|
||||
return new BuilderWithToBuilderBuilder<T>().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars);
|
||||
return new BuilderWithToBuilderBuilder<T>().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(((this.bars == null) ? java.util.Collections.emptyList() : this.bars));
|
||||
}
|
||||
}
|
||||
@lombok.experimental.Accessors(prefix = "m") class ConstructorWithToBuilder<T> {
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.AccessLevel;
|
||||
public @FieldNameConstants class FieldNameConstantsBasic {
|
||||
public static final java.lang.String FIELD_BUT_PRINT_ME_PLEASE = "butPrintMePlease";
|
||||
protected static final java.lang.String FIELD_I_AM_A_DVD_PLAYER = "iAmADvdPlayer";
|
||||
@FieldNameConstants(level = AccessLevel.PROTECTED) String iAmADvdPlayer;
|
||||
public @FieldNameConstants(level = AccessLevel.PACKAGE) class FieldNameConstantsBasic {
|
||||
static final @java.lang.SuppressWarnings("all") class Fields {
|
||||
public static final java.lang.String butPrintMePlease = "butPrintMePlease";
|
||||
public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer";
|
||||
<clinit>() {
|
||||
}
|
||||
private @java.lang.SuppressWarnings("all") Fields() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
String iAmADvdPlayer;
|
||||
int $skipMe;
|
||||
static double skipMeToo;
|
||||
@FieldNameConstants.Exclude int andMe;
|
||||
String butPrintMePlease;
|
||||
<clinit>() {
|
||||
}
|
||||
public FieldNameConstantsBasic() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
public @lombok.experimental.FieldNameConstants class FieldNameConstantsConfigKeys {
|
||||
public static final java.lang.String I_AM_A_DVD_PLAYER_SFX = "iAmADvdPlayer";
|
||||
String iAmADvdPlayer;
|
||||
<clinit>() {
|
||||
public static final @java.lang.SuppressWarnings("all") class Foobar {
|
||||
public static final java.lang.String iAmADvdPlayer = "iAmADvdPlayer";
|
||||
<clinit>() {
|
||||
}
|
||||
private @java.lang.SuppressWarnings("all") Foobar() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
String iAmADvdPlayer;
|
||||
public FieldNameConstantsConfigKeys() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.AccessLevel;
|
||||
public @FieldNameConstants(onlyExplicitlyIncluded = true,asEnum = true,innerTypeName = "TypeTest") class FieldNameConstantsEnum {
|
||||
public @java.lang.SuppressWarnings("all") enum TypeTest {
|
||||
iAmADvdPlayer(),
|
||||
$dontSkipMe(),
|
||||
alsoDontSkipMe(),
|
||||
private @java.lang.SuppressWarnings("all") TypeTest() {
|
||||
super();
|
||||
}
|
||||
<clinit>() {
|
||||
}
|
||||
}
|
||||
@FieldNameConstants.Include String iAmADvdPlayer;
|
||||
@FieldNameConstants.Include int $dontSkipMe;
|
||||
static @FieldNameConstants.Include double alsoDontSkipMe;
|
||||
int butSkipMe;
|
||||
<clinit>() {
|
||||
}
|
||||
public FieldNameConstantsEnum() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.AccessLevel;
|
||||
public @FieldNameConstants class FieldNameConstantsWeird {
|
||||
public static final java.lang.String FIELD_AZ = "A";
|
||||
@FieldNameConstants(level = AccessLevel.NONE) String iAmADvdPlayer;
|
||||
@FieldNameConstants(prefix = "") String X;
|
||||
@FieldNameConstants(suffix = "Z") String A;
|
||||
<clinit>() {
|
||||
}
|
||||
public FieldNameConstantsWeird() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import lombok.Singular;
|
||||
|
||||
@lombok.Builder(toBuilder = true)
|
||||
class BuilderSingularToBuilderWithNull {
|
||||
@Singular private java.util.List<String> elems;
|
||||
|
||||
public static void test() {
|
||||
new BuilderSingularToBuilderWithNull(null).toBuilder();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
@FieldNameConstants
|
||||
@FieldNameConstants(level = AccessLevel.PACKAGE)
|
||||
public class FieldNameConstantsBasic {
|
||||
@FieldNameConstants(level = AccessLevel.PROTECTED)
|
||||
String iAmADvdPlayer;
|
||||
int $skipMe;
|
||||
static double skipMeToo;
|
||||
@FieldNameConstants.Exclude int andMe;
|
||||
String butPrintMePlease;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//CONF: lombok.fieldNameConstants.prefix =
|
||||
//CONF: lombok.fieldNameConstants.suffix = _SFX
|
||||
//CONF: lombok.fieldNameConstants.innerTypeName = Foobar
|
||||
|
||||
@lombok.experimental.FieldNameConstants
|
||||
public class FieldNameConstantsConfigKeys {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
@FieldNameConstants(onlyExplicitlyIncluded = true, asEnum = true, innerTypeName = "TypeTest")
|
||||
public class FieldNameConstantsEnum {
|
||||
@FieldNameConstants.Include
|
||||
String iAmADvdPlayer;
|
||||
@FieldNameConstants.Include
|
||||
int $dontSkipMe;
|
||||
@FieldNameConstants.Include
|
||||
static double alsoDontSkipMe;
|
||||
int butSkipMe;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import lombok.AccessLevel;
|
||||
|
||||
@FieldNameConstants
|
||||
public class FieldNameConstantsWeird {
|
||||
@FieldNameConstants(level = AccessLevel.NONE)
|
||||
String iAmADvdPlayer;
|
||||
@FieldNameConstants(prefix = "")
|
||||
String X;
|
||||
@FieldNameConstants(suffix = "Z")
|
||||
String A;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
9 Not generating constant for this field: The name of the constant would be equal to the name of this field.
|
||||
@@ -1 +0,0 @@
|
||||
9 Not generating constant for this field: The name of the constant would be equal to the name of this field.
|
||||
+27
-27
@@ -4,62 +4,62 @@ RewriteRule ^$ /main.html [L,END]
|
||||
RewriteRule ^(index|home)(\.html)?$ / [NC,R=301]
|
||||
|
||||
RewriteRule ^setup/overview$ /setup/main.html [L,END]
|
||||
RewriteRule ^setup/main(\.html)?$ /setup/overview [NC,R=301]
|
||||
RewriteRule ^setup/index(\.html)?$ /setup/overview [NC,R=301]
|
||||
RewriteRule ^setup(/(overview)?)?$ /setup/overview [NC,R=301]
|
||||
RewriteRule ^setup/main(\.html)?/?$ /setup/overview [NC,R=301]
|
||||
RewriteRule ^setup/index(\.html)?/?$ /setup/overview [NC,R=301]
|
||||
RewriteRule ^setup(/(overview/?)?)?$ /setup/overview [NC,R=301]
|
||||
|
||||
RewriteRule ^changelog$ /changelog.html [L,END]
|
||||
RewriteRule ^changelog(\.html)?$ /changelog [NC,R=301]
|
||||
RewriteRule ^changelog(\.html)?/?$ /changelog [NC,R=301]
|
||||
RewriteRule ^credits$ /credits.html [L,END]
|
||||
RewriteRule ^credits(\.html)?$ /credits [NC,R=301]
|
||||
RewriteRule ^credits(\.html)?/?$ /credits [NC,R=301]
|
||||
RewriteRule ^download$ /download.html [L,END]
|
||||
RewriteRule ^download(\.html)?$ /download [NC,R=301]
|
||||
RewriteRule ^download(\.html)?/?$ /download [NC,R=301]
|
||||
RewriteRule ^download-edge$ /download-edge.html [L,END]
|
||||
RewriteRule ^download-edge(\.html)?$ /download-edge [NC,R=301]
|
||||
RewriteRule ^download-edge(\.html)?/?$ /download-edge [NC,R=301]
|
||||
RewriteRule ^all-versions$ /all-versions.html [L,END]
|
||||
RewriteRule ^all-versions(\.html)?$ /all-versions [NC,R=301]
|
||||
RewriteRule ^all-versions(\.html)?/?$ /all-versions [NC,R=301]
|
||||
RewriteRule ^all-versions$ /all-versions.html [L,END]
|
||||
RewriteRule ^all-versions(\.html)?$ /all-versions [NC,R=301]
|
||||
RewriteRule ^all-versions(\.html)?/?$ /all-versions [NC,R=301]
|
||||
RewriteRule ^disable-checked-exceptions$ /disable-checked-exceptions.html [L,END]
|
||||
RewriteRule ^disable-checked-exceptions(\.html)?$ /disable-checked-exceptions [NC,R=301]
|
||||
RewriteRule ^disable-checked-exceptions(\.html)?/?$ /disable-checked-exceptions [NC,R=301]
|
||||
RewriteRule ^supporters$ /supporters.html [L,END]
|
||||
RewriteRule ^supporters(.html)?$ /supporters [NC,R=301]
|
||||
RewriteRule ^supporters(.html)?/?$ /supporters [NC,R=301]
|
||||
RewriteRule ^order-license-info$ /order-license-info.html [L,END]
|
||||
RewriteRule ^order-?license-?info(.html)?$ /order-license-info [NC,R=301]
|
||||
RewriteRule ^order-?license-?info(.html)?/?$ /order-license-info [NC,R=301]
|
||||
RewriteRule ^order-license$ /order-license.html [L,END]
|
||||
RewriteRule ^order-?license(.html)?$ /order-license [NC,R=301]
|
||||
RewriteRule ^order-?license(.html)?/?$ /order-license [NC,R=301]
|
||||
|
||||
RewriteRule ^contributing/index$ /contributing/index.html [L,END]
|
||||
RewriteRule ^contributing(\.html)?$ /contributing/index [NC,R=301]
|
||||
RewriteRule ^contributing/index(\.html)?$ /contributing/index [NC,R=301]
|
||||
RewriteRule ^contributing(\.html)?/?$ /contributing/index [NC,R=301]
|
||||
RewriteRule ^contributing/index(\.html)?/?$ /contributing/index [NC,R=301]
|
||||
RewriteRule ^contributing/contributing$ /contributing/contributing.html [L,END]
|
||||
RewriteRule ^contributing/contributing(\.html)?$ /contributing/contributing [NC,R=301]
|
||||
RewriteRule ^contributing/contributing(\.html)?/?$ /contributing/contributing [NC,R=301]
|
||||
RewriteRule ^contributing/lombok-execution-path$ /contributing/lombok-execution-path.html [L,END]
|
||||
RewriteRule ^contributing/lombok-execution-path(\.html)?$ /contributing/lombok-execution-path [NC,R=301]
|
||||
RewriteRule ^contributing/lombok-execution-path(\.html)?/?$ /contributing/lombok-execution-path [NC,R=301]
|
||||
|
||||
<#list setupPages as pg>
|
||||
RewriteRule ^setup/${pg?no_esc}$ /setup/${pg?no_esc}.html [L,END]
|
||||
RewriteRule ^setup/${pg?no_esc}(\.html)?$ /setup/${pg?no_esc} [NC,R=301]
|
||||
RewriteRule ^setup/${pg?no_esc}(\.html)?/?$ /setup/${pg?no_esc} [NC,R=301]
|
||||
</#list>
|
||||
|
||||
RewriteRule ^features/all$ /features/index.html [L,END]
|
||||
RewriteRule ^features(/all)?$ /features/all [NC,R=301]
|
||||
RewriteRule ^features/index(\.html)?$ /features/all [NC,R=301]
|
||||
RewriteRule ^features(/all)?/?$ /features/all [NC,R=301]
|
||||
RewriteRule ^features/index(\.html)?/?$ /features/all [NC,R=301]
|
||||
|
||||
<#list featurePages as pg>
|
||||
RewriteRule ^features/${pg?no_esc}$ /features/${pg?no_esc}.html [L,END]
|
||||
RewriteRule ^features/${pg?no_esc}(\.html)?$ /features/${pg?no_esc} [NC,R=301]
|
||||
RewriteRule ^features/${pg?no_esc}(\.html)?/?$ /features/${pg?no_esc} [NC,R=301]
|
||||
</#list>
|
||||
|
||||
RewriteRule ^features/experimental/Builder(\.html)?$ /features/Builder [NC,R=301]
|
||||
RewriteRule ^features/experimental/Value(\.html)?$ /features/Value [NC,R=301]
|
||||
RewriteRule ^features/experimental/var(\.html)?$ /features/var [NC,R=301]
|
||||
RewriteRule ^features/experimental/Builder(\.html)?/?$ /features/Builder [NC,R=301]
|
||||
RewriteRule ^features/experimental/Value(\.html)?/?$ /features/Value [NC,R=301]
|
||||
RewriteRule ^features/experimental/var(\.html)?/?$ /features/var [NC,R=301]
|
||||
|
||||
RewriteRule ^features/experimental/all$ /features/experimental/index.html [L,END]
|
||||
RewriteRule ^features/experimental(/all)?$ /features/experimental/all [NC,R=301]
|
||||
RewriteRule ^features/experimental/index(\.html)?$ /features/experimental/all [NC,R=301]
|
||||
RewriteRule ^features/experimental(/all)?/?$ /features/experimental/all [NC,R=301]
|
||||
RewriteRule ^features/experimental/index(\.html)?/?$ /features/experimental/all [NC,R=301]
|
||||
|
||||
<#list experimentalPages as pg>
|
||||
RewriteRule ^features/experimental/${pg?no_esc}$ /features/experimental/${pg?no_esc}.html [L,END]
|
||||
RewriteRule ^features/experimental/${pg?no_esc}(\.html)?$ /features/experimental/${pg?no_esc} [NC,R=301]
|
||||
RewriteRule ^features/experimental/${pg?no_esc}(\.html)?/?$ /features/experimental/${pg?no_esc} [NC,R=301]
|
||||
</#list>
|
||||
|
||||
@@ -111,7 +111,7 @@ ga('send', 'pageview');
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="/setup/overview" class="smallOnly"><span>Install</span></a>
|
||||
<a href="/setup/overview" class="smallOnly"><span>How to use</span></a>
|
||||
<a class="dropdown-toggle pointer wideOnly" data-toggle="dropdown">Install<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="themes">
|
||||
<#list setupTargets as cat, tgtList>
|
||||
|
||||
@@ -129,6 +129,27 @@
|
||||
</p>
|
||||
</@f.featureSection>
|
||||
|
||||
<@f.featureSection>
|
||||
<h3 id="jackson"><a name="jackson">With Jackson</a></h3>
|
||||
<p>
|
||||
You can customize parts of your builder, for example adding another method to the builder class, or annotating a method in the builder class, by making the builder class yourself. Lombok will generate everything that you do not manually add, and put it into this builder class. For example, if you are trying to configure <a href="https://github.com/FasterXML/jackson">jackson</a> to use a specific subtype for a collection, you can write something like:<div class="snippet"><div class="java" align="left"><pre>
|
||||
@Value @Builder
|
||||
@JsonDeserialize(builder = JacksonExample.JacksonExampleBuilder.class)
|
||||
public class JacksonExample {
|
||||
@Singular private List<Foo> foos;
|
||||
|
||||
@JsonPOJOBuilder(withPrefix = "")
|
||||
public static class JacksonExampleBuilder implements JacksonExampleBuilderMeta {
|
||||
}
|
||||
|
||||
private interface JacksonExampleBuilderMeta {
|
||||
@JsonDeserialize(contentAs = FooImpl.class) JacksonExampleBuilder foos(List<? extends Foo> foos)
|
||||
}
|
||||
}
|
||||
</pre></div></div>
|
||||
</p>
|
||||
</@f.featureSection>
|
||||
|
||||
<@f.snippets name="Builder" />
|
||||
|
||||
<@f.confKeys>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
<@f.history>
|
||||
<p>
|
||||
@FieldNameConstants was introduced as experimental feature in lombok v1.16.22.
|
||||
</p><p>
|
||||
@FieldNameConstants was redesigned in lombok v1.18.4.
|
||||
</p>
|
||||
</@f.history>
|
||||
|
||||
@@ -18,11 +20,11 @@
|
||||
|
||||
<@f.overview>
|
||||
<p>
|
||||
The <code>@FieldNameConstants</code> annotation generates string constants (fields marked <code>public static final</code>, of type <code>java.lang.String</code>) containing the field's name, as a string. This is useful for various marshalling and serialization frameworks. The constant field by default is named <code>FIELD_<em>NAME_OF_FIELD</em></code>, where <em>NAME_OF_FIELD</em> is the same name as the field it represents, except with all uppercase letters, with underscores in front of the uppercase letters in the original field. The prefix (and suffix) is configurable on the <code>@FieldNameConstants</code> annotation.
|
||||
The <code>@FieldNameConstants</code> annotation generates an inner type which contains 1 constant for each field in your class; either string constants (fields marked <code>public static final</code>, of type <code>java.lang.String</code>) or if you prefer, an enum type with 1 value for each field. <code>@FieldNameConstants</code> is useful for various marshalling and serialization frameworks. The constant field (whether enum value or string constant) always has the exact same name as the field, capitalization and all.
|
||||
</p><p>
|
||||
The <code>public</code> access modifier can be changed via the parameter <code>level = AccessLevel.PACKAGE</code> for example. You can force a field to be skipped by supplying <code>level = AccessLevel.NONE</code>.
|
||||
The generated inner type is by default called <code>Fields</code> and is <code>public</code>. You can modify this via <code>@FieldNameConstants(innerTypeName = "FieldNames", access = AccessLevel.PACKAGE)</code> for example. The default inner type name can also be modified via configuration key <code>lombok.fieldNameConstants.innerTypeName</code>. The generated fields are always <code>public</code>.
|
||||
</p><p>
|
||||
Can be applied to classes (in which case every field gets a constant), or to an individual field.
|
||||
Must be applied to classes (or enums, though you'd rarely want to do that). By default includes all non-transient, non-static fields. You can use <code>@FieldNameConstants.Include</code> in fields + <code>@FieldNameConstants(onlyExplicitlyIncluded = true)</code>, or <code>@FieldNameConstants.Exclude</code> for more fine-grained control.
|
||||
</p>
|
||||
</@f.overview>
|
||||
|
||||
@@ -34,21 +36,19 @@
|
||||
</dt><dd>
|
||||
Lombok will flag any usage of <code>@FieldDefaults</code> as a warning or error if configured.
|
||||
</dd><dt>
|
||||
<code>lombok.fieldNameConstants.prefix</code> = <em>a string</em> (default: 'PREFIX_')
|
||||
<code>lombok.fieldNameConstants.innerTypeName</code> = <em>a string</em> (default: 'Fields')
|
||||
</dt><dd>
|
||||
Lombok will generate the name for each fieldconstant by constant-casing the field name and then prefixing this string to the result.
|
||||
</dd><dt>
|
||||
<code>lombok.fieldNameConstants.suffix</code> = <em>a string</em> (default: '' - the blank string)
|
||||
</dt><dd>
|
||||
Lombok will generate the name for each fieldconstant by constant-casing the field name and then suffixing this string to the result.
|
||||
The name of the inner type generated by lombok can be controlled with this configuration key.
|
||||
</dd>
|
||||
</@f.confKeys>
|
||||
|
||||
<@f.smallPrint>
|
||||
<p>
|
||||
Like other lombok handlers that touch fields, any field whose name starts with a dollar (<code>$</code>) symbol is skipped entirely. Such a field will not be modified at all. Static fields are also skipped.
|
||||
From lombok v1.16.22 to lombok v1.18.2, this feature generated constants inside the type directly; the name of these fields would for example turn field <code>exampleFieldName</code> into <code>public static final String FIELD_EXAMPLE_FIELD_NAME = "exampleFieldName";</code>. The prefix and suffix (here, <code>FIELD_</code>, and the empty string) were configurable. Starting with lombok v1.18.4 this feature has been redesigned into generating an inner type as described above.
|
||||
</p><p>
|
||||
The annotation can itself be used to set prefix/suffix. If you do so, it overrides the <code>lombok.fieldNameConstants.prefix/suffix</code> config key. Example: <code>@FieldNameConstants(prefix = "")</code>: This would generate for field <code>helloWorld</code> a constant named <code>HELLO_WORLD</code> instead of the default <code>FIELD_HELLO_WORLD</code>.
|
||||
Any parameters of lombok annotations that take strings need to be supplied actual string literals; you cannot have references to constants like those generated by <code>@FieldNameConstants</code>. If you'd like to use <code>@FieldNameConstants</code> to for example fill in the <code>of</code> and/or <code>exclude</code> parameters of <code>@ToString</code> and similar lombok annotations, use the <code>@ToString.Include</code> / <code>@ToString.Exclude</code> etc system instead; these are described at the feature pages for those features.
|
||||
</p><p>
|
||||
Like other lombok handlers that touch fields, any field whose name starts with a dollar (<code>$</code>) symbol is skipped entirely. Such a field will not be modified at all. Static fields are also skipped.
|
||||
</p>
|
||||
</@f.smallPrint>
|
||||
</@f.scaffold>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</p><p>
|
||||
Note, to tell the <code>gradle-lombok</code> plugin to use the latest version of lombok, you need to explicitly tell it about the latest version number and the SHA-256. For our current latest version, put this in your <code>build.gradle</code> file:<pre>
|
||||
lombok {
|
||||
version = ${version}
|
||||
version = '${version}'
|
||||
sha256 = ""
|
||||
}</pre>
|
||||
</p>
|
||||
|
||||
@@ -2,7 +2,7 @@ public class LogExample {
|
||||
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
|
||||
|
||||
public static void main(String... args) {
|
||||
log.error("Something's wrong here");
|
||||
log.severe("Something's wrong here");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class LogExample {
|
||||
|
||||
public static void main(String... args) {
|
||||
log.error("Something's wrong here");
|
||||
log.severe("Something's wrong here");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user