From 15c44f54ccd7cc4502d12b79e6f91074e4e916bc Mon Sep 17 00:00:00 2001
From: Reinier Zwitserloot <reinier@zwitserloot.com>
Date: Tue, 28 Nov 2017 00:59:37 +0100
Subject: JDK9 support for delombok (and thus, for running the tests under
 JDK9).

---
 .../lombok/javac/Javac8BasedLombokOptions.java     |  4 +-
 .../lombok/javac/Javac9BasedLombokOptions.java     | 47 ++++++++++++
 src/core/lombok/javac/JavacAST.java                | 23 ------
 src/core/lombok/javac/JavacImportList.java         |  1 -
 src/delombok/lombok/delombok/Delombok.java         | 47 +++++++++++-
 .../lombok/delombok/LombokOptionsFactory.java      | 11 ++-
 src/delombok/lombok/delombok/PrettyPrinter.java    |  8 +-
 src/stubs/com/sun/tools/javac/code/Symbol.java     | 85 ++++++++++++++++++++++
 src/stubs/com/sun/tools/javac/code/Symtab.java     | 20 +++++
 .../com/sun/tools/javac/main/JavaCompiler.java     | 37 ++++++++++
 src/stubs/com/sun/tools/javac/main/Option.java     |  1 +
 src/utils/lombok/javac/PackageName.java            | 55 ++++++++++++++
 12 files changed, 306 insertions(+), 33 deletions(-)
 create mode 100644 src/core/lombok/javac/Javac9BasedLombokOptions.java
 create mode 100644 src/stubs/com/sun/tools/javac/code/Symbol.java
 create mode 100644 src/stubs/com/sun/tools/javac/code/Symtab.java
 create mode 100644 src/stubs/com/sun/tools/javac/main/JavaCompiler.java
 create mode 100644 src/utils/lombok/javac/PackageName.java

(limited to 'src')

diff --git a/src/core/lombok/javac/Javac8BasedLombokOptions.java b/src/core/lombok/javac/Javac8BasedLombokOptions.java
index 3fdea890..9a662490 100644
--- a/src/core/lombok/javac/Javac8BasedLombokOptions.java
+++ b/src/core/lombok/javac/Javac8BasedLombokOptions.java
@@ -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;
diff --git a/src/core/lombok/javac/Javac9BasedLombokOptions.java b/src/core/lombok/javac/Javac9BasedLombokOptions.java
new file mode 100644
index 00000000..95bfff77
--- /dev/null
+++ b/src/core/lombok/javac/Javac9BasedLombokOptions.java
@@ -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);
+	}
+}
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 91ed325f..bda649fa 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -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;
 	}
diff --git a/src/core/lombok/javac/JavacImportList.java b/src/core/lombok/javac/JavacImportList.java
index 0f789f45..468d8c7b 100644
--- a/src/core/lombok/javac/JavacImportList.java
+++ b/src/core/lombok/javac/JavacImportList.java
@@ -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;
diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java
index ead4aa60..4e1f5a13 100644
--- a/src/delombok/lombok/delombok/Delombok.java
+++ b/src/delombok/lombok/delombok/Delombok.java
@@ -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);
 		
diff --git a/src/delombok/lombok/delombok/LombokOptionsFactory.java b/src/delombok/lombok/delombok/LombokOptionsFactory.java
index 47921931..bd615ac5 100644
--- a/src/delombok/lombok/delombok/LombokOptionsFactory.java
+++ b/src/delombok/lombok/delombok/LombokOptionsFactory.java
@@ -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;
 	}
diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java
index b5064a33..d372463e 100644
--- a/src/delombok/lombok/delombok/PrettyPrinter.java
+++ b/src/delombok/lombok/delombok/PrettyPrinter.java
@@ -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;
diff --git a/src/stubs/com/sun/tools/javac/code/Symbol.java b/src/stubs/com/sun/tools/javac/code/Symbol.java
new file mode 100644
index 00000000..abe6c5eb
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/code/Symbol.java
@@ -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; }
+	}
+}
diff --git a/src/stubs/com/sun/tools/javac/code/Symtab.java b/src/stubs/com/sun/tools/javac/code/Symtab.java
new file mode 100644
index 00000000..2b524e4c
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/code/Symtab.java
@@ -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;
+}
diff --git a/src/stubs/com/sun/tools/javac/main/JavaCompiler.java b/src/stubs/com/sun/tools/javac/main/JavaCompiler.java
new file mode 100644
index 00000000..d0e7b38f
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/main/JavaCompiler.java
@@ -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; }
+}
diff --git a/src/stubs/com/sun/tools/javac/main/Option.java b/src/stubs/com/sun/tools/javac/main/Option.java
index f3229c78..ae955772 100644
--- a/src/stubs/com/sun/tools/javac/main/Option.java
+++ b/src/stubs/com/sun/tools/javac/main/Option.java
@@ -7,4 +7,5 @@ package com.sun.tools.javac.main;
 public enum Option {
 	;
 	public String text;
+	public String primaryName;
 }
diff --git a/src/utils/lombok/javac/PackageName.java b/src/utils/lombok/javac/PackageName.java
new file mode 100644
index 00000000..e4dd6b20
--- /dev/null
+++ b/src/utils/lombok/javac/PackageName.java
@@ -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;
+	}
+}
-- 
cgit