JDK9 support for delombok (and thus, for running the tests under JDK9).

This commit is contained in:
Reinier Zwitserloot
2017-11-28 00:59:52 +01:00
parent b1b49e062e
commit 15c44f54cc
13 changed files with 361 additions and 36 deletions
+55 -3
View File
@@ -627,8 +627,61 @@ You can also create your own by writing a 'testenvironment.properties' file. The
* test.javaversion = 6
</fail>
</target>
<target name="test" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj" unless="tests.skip" description="Runs the tests.">
<target name="test" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj, -test-check, -test8, -test9" />
<target name="-test-check">
<condition property="test9.run">
<and>
<not><isset property="tests.skip" /></not>
<equals arg1="${ant.java.version}" arg2="9" />
</and>
</condition>
<condition property="test8.run">
<and>
<not><isset property="tests.skip" /></not>
<not><equals arg1="${ant.java.version}" arg2="9" /></not>
</and>
</condition>
</target>
<target name="-test9" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj" if="test9.run">
<echo>Running test suite in JDK9+ mode</echo>
<junit haltonfailure="no" fork="true">
<jvmarg value="-javaagent:dist/lombok.jar" />
<jvmarg value="-Ddelombok.bootclasspath=${test.location.bootclasspath}" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" />
<jvmarg value="--add-opens" />
<jvmarg value="jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED" />
<formatter type="plain" usefile="false" unless="tests.quiet" />
<classpath refid="test.path" />
<classpath path="${test.location.ecj}" />
<classpath path="${test.location.javac}" />
<classpath path="build/lombok" />
<classpath path="build/tests" />
<batchtest>
<fileset dir="test/core/src">
<include name="lombok/RunAllTests.java" />
</fileset>
</batchtest>
</junit>
</target>
<target name="-test8" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj" if="test8.run" description="Runs the tests.">
<echo>Running test suite in JDK6-8 mode</echo>
<junit haltonfailure="no" fork="true">
<jvmarg value="-javaagent:dist/lombok.jar" />
<jvmarg value="-Ddelombok.bootclasspath=${test.location.bootclasspath}" />
@@ -644,7 +697,6 @@ You can also create your own by writing a 'testenvironment.properties' file. The
</fileset>
</batchtest>
</junit>
<echo level="info">All tests successful.</echo>
</target>
<target name="utils-javadoc" depends="compile">
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 The Project Lombok Authors.
* Copyright (C) 2013-2017 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
@@ -28,7 +28,7 @@ import com.sun.tools.javac.util.Options;
public class Javac8BasedLombokOptions extends LombokOptions {
public static Javac8BasedLombokOptions replaceWithDelombokOptions(Context context) {
Options options = Options.instance(context);
context.put(optionsKey, (Options)null);
context.put(optionsKey, (Options) null);
Javac8BasedLombokOptions result = new Javac8BasedLombokOptions(context);
result.putAll(options);
return result;
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2017 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.javac;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Options;
public class Javac9BasedLombokOptions extends LombokOptions {
public static Javac9BasedLombokOptions replaceWithDelombokOptions(Context context) {
Options options = Options.instance(context);
context.put(optionsKey, (Options) null);
Javac9BasedLombokOptions result = new Javac9BasedLombokOptions(context);
result.putAll(options);
return result;
}
private Javac9BasedLombokOptions(Context context) {
super(context);
}
@Override public void putJavacOption(String optionName, String value) {
if (optionName.equals("SOURCEPATH")) optionName = "SOURCE_PATH";
if (optionName.equals("BOOTCLASSPATH")) optionName = "BOOT_CLASS_PATH";
String optionText = Option.valueOf(optionName).primaryName;
put(optionText, value);
}
}
-23
View File
@@ -48,8 +48,6 @@ import com.sun.tools.javac.tree.JCTree.JCCatch;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTry;
@@ -106,27 +104,6 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return cu.sourcefile == null ? null : cu.sourcefile.toString();
}
// jdk9 support, types have changed, names stay the same
static class PackageName {
private static final Method packageNameMethod;
static {
Method m = null;
try {
m = JCCompilationUnit.class.getDeclaredMethod("getPackageName");
} catch (Exception e) {}
packageNameMethod = m;
}
static String getPackageName(JCCompilationUnit cu) {
try {
Object pkg = packageNameMethod.invoke(cu);
return (pkg instanceof JCFieldAccess || pkg instanceof JCIdent) ? pkg.toString() : null;
} catch (Exception e) {}
return null;
}
}
public Context getContext() {
return context;
}
@@ -26,7 +26,6 @@ import java.util.Collection;
import lombok.core.ImportList;
import lombok.core.LombokInternalAliasing;
import lombok.javac.JavacAST.PackageName;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+44 -3
View File
@@ -30,12 +30,14 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
@@ -43,14 +45,18 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import lombok.Lombok;
import lombok.javac.CommentCatcher;
import lombok.javac.Javac;
import lombok.javac.LombokOptions;
import lombok.javac.apt.LombokProcessor;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Todo;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -466,6 +472,17 @@ public class Delombok {
return out;
}
private static final Field MODULE_FIELD = getModuleField();
private static Field getModuleField() {
try {
return JCCompilationUnit.class.getField("modle");
} catch (NoSuchFieldException e) {
return null;
} catch (SecurityException e) {
return null;
}
}
public boolean delombok() throws IOException {
LombokOptions options = LombokOptionsFactory.getDelombokOptions(context);
options.deleteLombokAnnotations();
@@ -482,10 +499,24 @@ public class Delombok {
List<JCCompilationUnit> roots = new ArrayList<JCCompilationUnit>();
Map<JCCompilationUnit, File> baseMap = new IdentityHashMap<JCCompilationUnit, File>();
compiler.initProcessAnnotations(Collections.singleton(new lombok.javac.apt.LombokProcessor()));
Set<LombokProcessor> processors = Collections.singleton(new lombok.javac.apt.LombokProcessor());
if (Javac.getJavaCompilerVersion() < 9) {
compiler.initProcessAnnotations(processors);
} else {
compiler.initProcessAnnotations(processors, Collections.<JavaFileObject>emptySet(), Collections.<String>emptySet());
}
Object unnamedModule = null;
if (Javac.getJavaCompilerVersion() >= 9) unnamedModule = Symtab.instance(context).unnamedModule;
for (File fileToParse : filesToParse) {
@SuppressWarnings("deprecation") JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());
JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());
if (Javac.getJavaCompilerVersion() >= 9) try {
MODULE_FIELD.set(unit, unnamedModule);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
baseMap.put(unit, fileToBase.get(fileToParse));
roots.add(unit);
}
@@ -498,9 +529,19 @@ public class Delombok {
catcher.setComments(unit, new DocCommentIntegrator().integrate(catcher.getComments(unit), unit));
}
if (Javac.getJavaCompilerVersion() >= 9) {
compiler.initModules(com.sun.tools.javac.util.List.from(roots.toArray(new JCCompilationUnit[0])));
}
com.sun.tools.javac.util.List<JCCompilationUnit> trees = compiler.enterTrees(toJavacList(roots));
JavaCompiler delegate = compiler.processAnnotations(trees);
JavaCompiler delegate;
if (Javac.getJavaCompilerVersion() < 9) {
delegate = compiler.processAnnotations(trees, com.sun.tools.javac.util.List.<String>nil());
} else {
delegate = compiler;
Collection<String> c = com.sun.tools.javac.util.List.nil();
compiler.processAnnotations(trees, c);
}
Object care = callAttributeMethodOnJavaCompiler(delegate, delegate.todo);
@@ -24,6 +24,7 @@ package lombok.delombok;
import lombok.javac.Javac;
import lombok.javac.Javac6BasedLombokOptions;
import lombok.javac.Javac8BasedLombokOptions;
import lombok.javac.Javac9BasedLombokOptions;
import lombok.javac.LombokOptions;
import com.sun.tools.javac.util.Context;
@@ -41,6 +42,12 @@ public class LombokOptionsFactory {
@Override LombokOptions createAndRegisterOptions(Context context) {
return Javac8BasedLombokOptions.replaceWithDelombokOptions(context);
}
},
JDK9 {
@Override LombokOptions createAndRegisterOptions(Context context) {
return Javac9BasedLombokOptions.replaceWithDelombokOptions(context);
}
};
abstract LombokOptions createAndRegisterOptions(Context context);
@@ -53,8 +60,10 @@ public class LombokOptionsFactory {
LombokOptions options;
if (Javac.getJavaCompilerVersion() < 8) {
options = LombokOptionCompilerVersion.JDK7_AND_LOWER.createAndRegisterOptions(context);
} else {
} else if (Javac.getJavaCompilerVersion() == 8) {
options = LombokOptionCompilerVersion.JDK8.createAndRegisterOptions(context);
} else {
options = LombokOptionCompilerVersion.JDK9.createAndRegisterOptions(context);
}
return options;
}
@@ -92,6 +92,7 @@ import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
import lombok.javac.CommentInfo;
import lombok.javac.PackageName;
import lombok.javac.CommentInfo.EndConnection;
import lombok.javac.CommentInfo.StartConnection;
import lombok.javac.JavacTreeMaker.TreeTag;
@@ -457,11 +458,12 @@ public class PrettyPrinter extends JCTree.Visitor {
@Override public void visitTopLevel(JCCompilationUnit tree) {
printDocComment(tree);
if (tree.pid != null) {
JCTree n = PackageName.getPackageNode(tree);
if (n != null) {
consumeComments(tree);
aPrint("package ");
print(tree.pid);
println(";", tree.pid);
print(n);
println(";", n);
}
boolean first = true;
@@ -0,0 +1,85 @@
/*
* These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
*/
package com.sun.tools.javac.code;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import com.sun.tools.javac.util.Name;
public abstract class Symbol implements Element {
public Type type;
public Name name;
public long flags() { return 0; }
public boolean isStatic() { return false; }
public boolean isConstructor() { return false; }
public boolean isLocal() { return false; }
public Name flatName() { return null; }
public Name getQualifiedName() { return null; }
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annoType) { return null; }
@Override public List<Attribute.Compound> getAnnotationMirrors() { return null; }
@Override public TypeMirror asType() { return null; }
public <A extends java.lang.annotation.Annotation> A getAnnotation(Class<A> annoType) { return null; }
@Override public Name getSimpleName() { return null; }
@Override public List<Symbol> getEnclosedElements() { return null; }
@Override public Element getEnclosingElement() { return null; }
public static abstract class TypeSymbol extends Symbol {}
public static class MethodSymbol extends Symbol implements ExecutableElement {
public MethodSymbol(long flags, Name name, Type type, Symbol owner) {}
@Override public ElementKind getKind() { return null; }
@Override public Set<Modifier> getModifiers() { return null; }
@Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
@Override public List<? extends TypeParameterElement> getTypeParameters() { return null; }
@Override public TypeMirror getReturnType() { return null; }
@Override public List<? extends VariableElement> getParameters() { return null; }
@Override public boolean isVarArgs() { return false; }
@Override public List<? extends TypeMirror> getThrownTypes() { return null; }
@Override public AnnotationValue getDefaultValue() { return null; }
public TypeMirror getReceiverType() { return null; }
public boolean isDefault() { return false; }
public List<VarSymbol> params() { return null; }
}
public static class VarSymbol extends Symbol implements VariableElement {
public Type type;
@Override public ElementKind getKind() { return null; }
@Override public Set<Modifier> getModifiers() { return null; }
@Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
@Override public Object getConstantValue() { return null; }
}
public static class ClassSymbol extends TypeSymbol implements TypeElement {
@Override public Name getQualifiedName() { return null; }
@Override public List<? extends TypeMirror> getInterfaces() { return null; }
@Override public TypeMirror getSuperclass() { return null; }
@Override public ElementKind getKind() { return null; }
@Override public Set<Modifier> getModifiers() { return null; }
@Override public NestingKind getNestingKind() { return null; }
@Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
@Override public List<? extends TypeParameterElement> getTypeParameters() { return null; }
}
// JDK9
public static class ModuleSymbol extends TypeSymbol {
@Override public ElementKind getKind() { return null; }
@Override public Set<Modifier> getModifiers() { return null; }
@Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
}
}
@@ -0,0 +1,20 @@
/*
* These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
*/
package com.sun.tools.javac.code;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.util.Context;
public class Symtab {
// Shared by JDK6-9
public ClassSymbol methodClass;
public Type iterableType;
public Type objectType;
public static Symtab instance(Context context) {return null;}
public Type unknownType;
// JDK 9
public ModuleSymbol unnamedModule;
}
@@ -0,0 +1,37 @@
/*
* These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
*/
package com.sun.tools.javac.main;
import java.io.IOException;
import java.util.Collection;
import javax.annotation.processing.Processor;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.comp.Todo;
public class JavaCompiler {
// Shared by JDK6-9
public boolean keepComments;
public boolean genEndPos;
public Todo todo;
public JavaCompiler(Context context) {}
public int errorCount() { return 0; }
public static String version() { return "<stub>"; }
public JCCompilationUnit parse(String fileName) throws IOException { return null; }
public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {return null;}
//JDK up to 8
public void initProcessAnnotations(Iterable<? extends Processor> processors) throws IOException {}
public JavaCompiler processAnnotations(List<JCCompilationUnit> roots, List<String> classnames) {return this;}
// JDK 9
public void initProcessAnnotations(Iterable<? extends Processor> processors, Collection<? extends JavaFileObject> initialFiles, Collection<String> initialClassNames) {}
public void processAnnotations(List<JCCompilationUnit> roots, Collection<String> classnames) {}
public void close() {}
public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) { return null; }
}
@@ -7,4 +7,5 @@ package com.sun.tools.javac.main;
public enum Option {
;
public String text;
public String primaryName;
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2017 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.javac;
import java.lang.reflect.Method;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
// Supports JDK6-9
public class PackageName {
private static final Method packageNameMethod = getPackageNameMethod();
private static Method getPackageNameMethod() {
try {
return JCCompilationUnit.class.getDeclaredMethod("getPackageName");
} catch (Exception e) {
return null;
}
}
public static String getPackageName(JCCompilationUnit cu) {
JCTree t = getPackageNode(cu);
return t != null ? t.toString() : null;
}
public static JCTree getPackageNode(JCCompilationUnit cu) {
if (packageNameMethod != null) try {
Object pkg = packageNameMethod.invoke(cu);
return (pkg instanceof JCFieldAccess || pkg instanceof JCIdent) ? (JCTree) pkg : null;
} catch (Exception e) {}
return cu.pid instanceof JCFieldAccess || cu.pid instanceof JCIdent ? cu.pid : null;
}
}