diff options
author | Jay Arthanareeswaran | 2017-09-18 15:37:49 +0000 |
---|---|---|
committer | Jay Arthanareeswaran | 2017-09-18 18:19:28 +0000 |
commit | 01d653b8154c601f5850f7a0d488fa3349909127 (patch) | |
tree | 26f434f5dee3b12ada67c8632c0b26da33e10715 | |
parent | c798229d351d6daa2232cff6c15750336659223e (diff) | |
download | eclipse.jdt.core-01d653b8154c601f5850f7a0d488fa3349909127.tar.gz eclipse.jdt.core-01d653b8154c601f5850f7a0d488fa3349909127.tar.xz eclipse.jdt.core-01d653b8154c601f5850f7a0d488fa3349909127.zip |
Change-Id: I6b61e6ab32b905357b5256cd875eb8337822f3c6
Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
34 files changed, 2120 insertions, 148 deletions
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar Binary files differindex 856d5d047d..69a7439122 100644 --- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar +++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors.jar diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar Binary files differindex e312f51cb8..4fc9a5e2e9 100644 --- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar +++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar diff --git a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/AnnotationProcessorTests/Bug340635Proc.java b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/AnnotationProcessorTests/Bug340635Proc.java index ca60bf979f..47ff563fdc 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/AnnotationProcessorTests/Bug340635Proc.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/AnnotationProcessorTests/Bug340635Proc.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2015 IBM Corporation and others. + * Copyright (c) 2015, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * Kevin Pollet - SERLI - (kevin.pollet@serli.com) - initial API and implementation *******************************************************************************/ @@ -66,7 +70,7 @@ public class Bug340635Proc extends AbstractProcessor { private class GenericTypeVisitor extends SimpleTypeVisitor6<DeclaredType, Void> { private final Types types; - + @Deprecated public GenericTypeVisitor(Types types) { this.types = types; } diff --git a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLConverter.java b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLConverter.java index cb5763507e..37df722348 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLConverter.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/base/XMLConverter.java @@ -50,7 +50,7 @@ import org.w3c.dom.Node; public class XMLConverter extends ElementScanner6<Void, Node> implements IXMLNames { private final Document _doc; - + @Deprecated private XMLConverter(Document doc) { _doc = doc; } diff --git a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/inherited/ArgsConstructorProcessor.java b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/inherited/ArgsConstructorProcessor.java index e6e8e4692b..b8aa884386 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/inherited/ArgsConstructorProcessor.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/inherited/ArgsConstructorProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 IBM Corporation and others. + * Copyright (c) 2011, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -16,14 +16,20 @@ import java.util.Map.Entry; import java.util.Set; import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.*; -import javax.lang.model.type.*; +import javax.lang.model.type.ExecutableType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVisitor; import javax.lang.model.util.SimpleTypeVisitor6; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; @@ -155,6 +161,7 @@ public class ArgsConstructorProcessor extends BaseProcessor { } private final TypeVisitor<Boolean, List<TypeMirror>> argsVisitor = new SimpleTypeVisitor6<Boolean, List<TypeMirror>>() { + @Override public Boolean visitExecutable(ExecutableType t, List<TypeMirror> annotatedTypes) { diff --git a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java8ElementProcessor.java b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java8ElementProcessor.java index b2040c89b0..078e88f6f5 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java8ElementProcessor.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java8ElementProcessor.java @@ -169,7 +169,7 @@ public class Java8ElementProcessor extends BaseProcessor { testRepeatedAnnotations25(); testTypeAnnotations26(); testTypeAnnotations27(); - testPackageAnnotations(); + //testPackageAnnotations(); testBug520540(); testEnumConstArguments(); } @@ -986,6 +986,8 @@ public class Java8ElementProcessor extends BaseProcessor { } } + // Disabled for now. Javac includes the CLASS element of the package-info in the root element if there's one. + // But ECJ includes the Package element. public void testPackageAnnotations() { if ( roundNo++ == 0) { this.reportSuccessAlready = false; @@ -1001,6 +1003,8 @@ public class Java8ElementProcessor extends BaseProcessor { for (Element element : roundEnv.getRootElements()) { if (element.getKind() == ElementKind.PACKAGE) { packageEl = (PackageElement) element; + } else { + System.out.println(element); } } assertNotNull("Package element should not be null", packageEl); diff --git a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java index 6750b61f7f..6f0d9224bf 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java +++ b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java9ElementProcessor.java @@ -15,25 +15,625 @@ package org.eclipse.jdt.compiler.apt.tests.processors.elements; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; -import javax.annotation.processing.SupportedSourceVersion; -import javax.lang.model.SourceVersion; +import javax.lang.model.AnnotatedConstruct; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.ModuleElement.Directive; +import javax.lang.model.element.ModuleElement.DirectiveKind; +import javax.lang.model.element.ModuleElement.ExportsDirective; +import javax.lang.model.element.ModuleElement.ProvidesDirective; +import javax.lang.model.element.ModuleElement.RequiresDirective; +import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.NoType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; -@SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_8) // Not at compliance 9 yet -public class Java9ElementProcessor extends Java8ElementProcessor { +import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor; - int roundNo = 0; +/** + * A processor that explores the java 9 specific elements and validates the lambda and + * type annotated elements. To enable this processor, add + * -Aorg.eclipse.jdt.compiler.apt.tests.processors.elements.Java9ElementProcessor to the command line. + * @since 3.13 BETA_JAVA9 + */ +@SupportedAnnotationTypes("*") +public class Java9ElementProcessor extends BaseProcessor { boolean reportSuccessAlready = true; + RoundEnvironment roundEnv = null; + Messager _messager = null; + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + _typeUtils = processingEnv.getTypeUtils(); + _messager = processingEnv.getMessager(); + } + // Always return false from this processor, because it supports "*". + // The return value does not signify success or failure! + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return false; + } + + this.roundEnv = roundEnv; + Map<String, String> options = processingEnv.getOptions(); + if (!options.containsKey(this.getClass().getName())) { + // Disable this processor unless we are intentionally performing the test. + return false; + } else { + try { + if (!invokeTestMethods(options)) { + testAll(); + } + if (this.reportSuccessAlready) { + super.reportSuccess(); + } + } catch (AssertionFailedError e) { + super.reportError(getExceptionStackTrace(e)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return false; + } + + private boolean invokeTestMethods(Map<String, String> options) throws Throwable { + Method testMethod = null; + Set<String> keys = options.keySet(); + boolean testsFound = false; + for (String option : keys) { + if (option.startsWith("test")) { + try { + testMethod = this.getClass().getDeclaredMethod(option, new Class[0]); + if (testMethod != null) { + testsFound = true; + testMethod.invoke(this, new Object[0]); + } + } catch (InvocationTargetException e) { + throw e.getCause(); + } catch (Exception e) { + super.reportError(getExceptionStackTrace(e)); + } + } + } + return testsFound; + } + + public void testAll() throws AssertionFailedError { + testModuleAnnotation1(); + testModuleElement1(); + testModuleElement2(); + testModuleElement3(); + testModuleElement4(); + testModuleElement5(); + testModuleElement6(); + testModuleElement7(); + testModuleJavaBase1(); + testModuleJavaBase2(); + testModuleJavaBase3(); + testModuleJavaBase4(); + testModuleJavaBase5(); + testModuleTypeMirror1(); + testModuleTypeMirror2(); + testModuleJavaSql1(); + testSourceModule1(); + testSourceModule2(); + testRootElements1(); + testRootElements2(); + testUnnamedModule1(); + testUnnamedModule2(); + testUnnamedModule3(); + testUnnamedModule4(); + testUnnamedModule5(); + } + + private Element getRoot(Element elem) { + Element enclosingElement = elem.getEnclosingElement(); + while (enclosingElement != null) { + if (enclosingElement instanceof ModuleElement) { + return enclosingElement; + } + enclosingElement = enclosingElement.getEnclosingElement(); + } + return enclosingElement; + } + + public void testRootElements1() { + Set<? extends Element> rootElements = this.roundEnv.getRootElements(); + int typeCount = 0; + int moduleCount = 0; + List<String> types = new ArrayList<>(); + List<String> modules = new ArrayList<>(); + for (Element element : rootElements) { + Element root = getRoot(element); + if (element instanceof ModuleElement) { + ModuleElement mod = (ModuleElement) element; + moduleCount++; + modules.add(mod.getQualifiedName().toString()); + assertNull("module should not have an enclosing element", root); + } else { + if (element instanceof TypeElement) { + typeCount++; + types.add(((TypeElement) element).getQualifiedName().toString()); + } + assertTrue("Should be a module element", (root instanceof ModuleElement)); + assertFalse("should be a named module", ((ModuleElement) root).isUnnamed()); + } + } + Collections.sort(types, (x, y) -> x.compareTo(y)); + Collections.sort(modules, (x, y) -> x.compareTo(y)); + assertEquals("incorrect no of modules in root elements", 2, moduleCount); + assertEquals("incorrect modules among root elements", "[mod.a, mod.b]", modules.toString()); + assertEquals("incorrect no of types in root elements", 5, typeCount); + assertEquals("incorrect types among root elements", + "[abc.A, abc.internal.A, abc.internal.TypeInAModule, abc.internal.pqr.A, pqr.ext.B]", + types.toString()); + } + // Test the types part of root elements get the modules right + public void testRootElements2() { + Set<? extends Element> rootElements = this.roundEnv.getRootElements(); + TypeElement type = null; + ModuleElement modFromRoot = null; + for (Element element : rootElements) { + if (element instanceof TypeElement && ((TypeElement) element).getSimpleName().toString().equals("TypeInAModule")) { + type = (TypeElement) element; + } + if (element instanceof ModuleElement && ((ModuleElement) element).getQualifiedName().toString().equals("mod.a")) { + modFromRoot = (ModuleElement) element; + } + } + assertNotNull("type should not be null", type); + assertNotNull("module from root elements should not be null", modFromRoot); + ModuleElement module = _elementUtils.getModuleOf(type); + assertNotNull("type's module should not be null", module); + assertEquals("modules should be equals", module, modFromRoot); + } + /* + * Test module element can be retrieved and + * annotations on module declarations can be retrieved + */ + public void testModuleAnnotation1() { + CharSequence name = "mod.a"; + ModuleElement mod = _elementUtils.getModuleElement(name); + assertNotNull("Module element should not be null", mod); + List<? extends AnnotationMirror> annotationMirrors = mod.getAnnotationMirrors(); + assertNotNull("Should not be null", annotationMirrors); + verifyAnnotations(mod, new String[]{"@java.lang.Deprecated()"}); + List<? extends Element> enclosedElements = mod.getEnclosedElements(); + PackageElement pack = null; + for (Element element : enclosedElements) { + if (element instanceof PackageElement) { + pack = (PackageElement) element; + break; + } + } + assertNotNull("Package not found", pack); + Element elem = pack.getEnclosingElement(); + assertNotNull("Parent not found", elem); + assertTrue("Parent should be a module", (elem instanceof ModuleElement)); + assertEquals("Incorrect module element", "mod.a", ((ModuleElement) elem).getQualifiedName().toString()); + } + /* + * Test module element can be retrieved and attributed are + * verified against declaration + */ + public void testModuleElement1() { + CharSequence name = "mod.a"; + ModuleElement mod = _elementUtils.getModuleElement(name); + assertEquals("incorrect name", "mod.a", mod.getQualifiedName().toString()); + assertEquals("incorrect name", "mod.a", mod.getQualifiedName().toString()); + List<? extends Element> enclosedElements = mod.getEnclosedElements(); + PackageElement pack = null; + for (Element element : enclosedElements) { + if (element instanceof PackageElement && ((PackageElement) element).getQualifiedName().toString().equals("abc.internal")) { + pack = (PackageElement) element; + break; + } + } + assertNotNull("Package not found", pack); + Element elem = pack.getEnclosingElement(); + assertNotNull("Parent not found", elem); + assertTrue("Parent should be a module", (elem instanceof ModuleElement)); + assertEquals("Incorrect module element", "mod.a", ((ModuleElement) elem).getQualifiedName().toString()); + } + /* + * Test type elements can be retrieved from Elements API with and without + * the context of the module the type is in. + */ + public void testModuleElement2() { + CharSequence name = "mod.a"; + ModuleElement mod = _elementUtils.getModuleElement(name); + TypeElement typeElement = _elementUtils.getTypeElement(mod, "abc.internal.TypeInAModule"); + assertNotNull("Type should not be null", typeElement); + typeElement = _elementUtils.getTypeElement("abc.internal.TypeInAModule"); + assertNotNull("Type should not be null", typeElement); + ModuleElement m = _elementUtils.getModuleOf(typeElement); + assertEquals("modules should be same", mod, m); + ModuleElement mElement = _elementUtils.getModuleOf(typeElement); + assertNotNull("module should not be null", mElement); + assertEquals("Incorrect module element", "mod.a", mElement.getQualifiedName().toString()); + } + /* + * Test binary modules from JRT system can be loaded and its attributes + * as expected + */ + public void testModuleElement3() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + ModuleElement compiler = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.base")) { + base = moduleElement; + } + if (moduleElement.getQualifiedName().toString().equals("java.compiler")) { + compiler = moduleElement; + } + } + assertNotNull("java.base module null", base); + assertNotNull("java.compiler module null", compiler); + assertNull("Enclosing element should be null", base.getEnclosingElement()); + assertEquals("Incorrect element kind", ElementKind.MODULE, base.getKind()); + assertFalse("Should be named", base.isUnnamed()); + assertFalse("Should not be open", base.isOpen()); + + } + /* + * Test packages can be retrieved with the Elements API with and without + * the context of its module. + */ + public void testModuleElement4() { + CharSequence name = "mod.a"; + ModuleElement mod = _elementUtils.getModuleElement(name); + PackageElement pElement = _elementUtils.getPackageElement("abc.internal"); + assertNotNull("Package should not be null", pElement); + pElement = _elementUtils.getPackageElement(mod, "abc.internal"); + assertNotNull("Package should not be null", pElement); + ModuleElement mElement = _elementUtils.getModuleOf(pElement); + assertNotNull("module should not be null", mElement); + assertEquals("Incorrect module element", "mod.a", mElement.getQualifiedName().toString()); + assertEquals("Modules should be same", mod, mElement); + } + /* + * Test packages can be retrieved with Elements API and they contain + * the right module element. + */ + public void testModuleElement5() { + CharSequence name = "mod.a"; + ModuleElement mod = _elementUtils.getModuleElement(name); + Set<? extends PackageElement> allPackageElements = _elementUtils.getAllPackageElements("abc.internal.pqr"); + assertEquals("Incorrect no of packages", 1, allPackageElements.size()); + PackageElement pElement = null; + for (PackageElement packageElement : allPackageElements) { + pElement = packageElement; + } + assertNotNull("Package should not be null", pElement); + ModuleElement mElement = _elementUtils.getModuleOf(pElement); + assertNotNull("module should not be null", mElement); + assertEquals("Incorrect module element", "mod.a", mElement.getQualifiedName().toString()); + assertEquals("Modules should be same", mod, mElement); + allPackageElements = _elementUtils.getAllPackageElements("abc"); + assertEquals("Incorrect no of packages", 2, allPackageElements.size()); + List<ModuleElement> mods = new ArrayList<>(); + for (PackageElement packageElement : allPackageElements) { + mElement = _elementUtils.getModuleOf(packageElement); + mods.add(mElement); + } + assertEquals("incorrect no of modules", 2, mods.size()); + mods.remove(mod); + mod = _elementUtils.getModuleElement("mod.b"); + assertNotNull("mod b should not be null", mod); + mods.remove(mod); + assertEquals("incorrect no of modules", 0, mods.size()); + } + /* + * Test type elements can be loaded and contain the correct module + * elements + */ + public void testModuleElement6() { + CharSequence name = "mod.a"; + ModuleElement mod = _elementUtils.getModuleElement(name); + Set<? extends TypeElement> typeElements = _elementUtils.getAllTypeElements("abc.internal.A"); + assertNotNull("Type should not be null", typeElements); + assertEquals("Incorrect no of types", 1, typeElements.size()); + TypeElement tElement = null; + for (TypeElement typeElement : typeElements) { + tElement = typeElement; + } + assertNotNull("Package should not be null", tElement); + ModuleElement mElement = _elementUtils.getModuleOf(tElement); + assertNotNull("module should not be null", mElement); + assertEquals("Incorrect module element", "mod.a", mElement.getQualifiedName().toString()); + assertEquals("Modules should be same", mod, mElement); + } + /* + * Test that a module not part of the root modules can NOT be retrieved. + */ + public void testModuleElement7() { + // test that a random module from system unrelated to the module we are compiling is not loaded by the compiler + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement mod = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.desktop")) { + mod = moduleElement; + } + } + assertNull("module java.desktop should not be found", mod); + } + /* + * Test java.base module can be loaded and verify its exports attributes + */ + public void testModuleJavaBase1() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.base")) { + base = moduleElement; + } + } + assertNotNull("java.base module null", base); + List<? extends Directive> directives = base.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.EXPORTS); + assertEquals("incorrect no of exports", 108 , filterDirective.size()); + ExportsDirective pack = null; + for (Directive directive : filterDirective) { + ModuleElement.ExportsDirective exports = (ExportsDirective) directive; + if (exports.getPackage().getQualifiedName().toString().equals("sun.reflect.annotation")) { + pack = exports; + break; + } + } + assertNotNull("Package export not found", pack); + List<? extends ModuleElement> targetModules = pack.getTargetModules(); + assertEquals("incorrect no of targets", 1, targetModules.size()); + ModuleElement mod = targetModules.get(0); + assertEquals("incorrect module element", "jdk.compiler", mod.getQualifiedName().toString()); + } + /* + * Test java.base module can be loaded and verify its requires attributes + */ + public void testModuleJavaBase2() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.base")) { + base = moduleElement; + } + } + assertNotNull("java.base module null", base); + List<? extends Directive> directives = base.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.REQUIRES); + assertEquals("Incorrect no of requires", 0, filterDirective.size()); + } + /* + * Test java.base module can be loaded and verify its 'opens' attributes + */ + public void testModuleJavaBase3() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.base")) { + base = moduleElement; + } + } + assertNotNull("java.base module null", base); + List<? extends Directive> directives = base.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.OPENS); + assertEquals("incorrect no of opens", 0 , filterDirective.size()); + } + /* + * Test java.base module can be loaded and verify its 'uses' attributes + */ + public void testModuleJavaBase4() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.base")) { + base = moduleElement; + } + } + assertNotNull("java.base module null", base); + List<? extends Directive> directives = base.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.USES); + assertEquals("incorrect no of uses", 34 , filterDirective.size()); + } + /* + * Test java.base module can be loaded and verify its 'provides' attributes + */ + public void testModuleJavaBase5() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.base")) { + base = moduleElement; + } + } + assertNotNull("java.base module null", base); + List<? extends Directive> directives = base.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.PROVIDES); + assertEquals("incorrect no of provides", 1 , filterDirective.size()); + ProvidesDirective provides = (ProvidesDirective) filterDirective.get(0); + assertEquals("incorrect service name", "java.nio.file.spi.FileSystemProvider", provides.getService().getQualifiedName().toString()); + List<? extends TypeElement> implementations = provides.getImplementations(); + assertEquals("incorrect no of implementations", 1 , implementations.size()); + TypeElement typeElement = implementations.get(0); + assertEquals("incorrect implementation name", "jdk.internal.jrtfs.JrtFileSystemProvider", typeElement.getQualifiedName().toString()); + } + public void testModuleTypeMirror1() { + ModuleElement base = _elementUtils.getModuleElement("java.base"); + assertNotNull("java.base module null", base); + TypeMirror asType = base.asType(); + assertNotNull("module type should not be null", asType); + assertEquals("incorrect type kind", TypeKind.MODULE, asType.getKind()); + assertEquals("must be a NoType", (asType instanceof NoType)); + } + public void testModuleTypeMirror2() { + ModuleElement base = _elementUtils.getModuleElement("mod.a"); + assertNotNull("mod.a module null", base); + TypeMirror asType = base.asType(); + assertNotNull("module type should not be null", asType); + verifyAnnotations(asType, new String[]{}); + } + /* + * Test java.sql module can be loaded and verify its requires attributes + */ + public void testModuleJavaSql1() { + Set<? extends ModuleElement> allModuleElements = _elementUtils.getAllModuleElements(); + ModuleElement base = null; + for (ModuleElement moduleElement : allModuleElements) { + if (moduleElement.getQualifiedName().toString().equals("java.sql")) { + base = moduleElement; + break; + } + } + assertNotNull("java.sql module null", base); + List<? extends Directive> directives = base.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.REQUIRES); + assertEquals("Incorrect no of requires", 3, filterDirective.size()); + RequiresDirective req = null; + for (Directive directive : filterDirective) { + if (((RequiresDirective) directive).getDependency().getQualifiedName().toString().equals("java.logging")) { + req = (RequiresDirective) directive; + break; + } + } + assertNotNull("dependency on java.logging not found", req); + assertTrue("dependency should be transitive", req.isTransitive()); + } + /* + * Test a source module can be retrieved and verify its requires attributes + */ + public void testSourceModule1() { + ModuleElement mod = _elementUtils.getModuleElement("mod.a"); + assertNotNull("mod.a module null", mod); + List<? extends Directive> directives = mod.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.REQUIRES); + assertEquals("Incorrect no of requires", 3, filterDirective.size()); + RequiresDirective reqCompiler = null; + RequiresDirective reqSql = null; + for (Directive directive : filterDirective) { + if (((RequiresDirective) directive).getDependency().getQualifiedName().toString().equals("java.compiler")) { + reqCompiler = (RequiresDirective) directive; + } + if (((RequiresDirective) directive).getDependency().getQualifiedName().toString().equals("java.sql")) { + reqSql = (RequiresDirective) directive; + } + } + assertNotNull("dependency on java.sql not found", reqSql); + assertNotNull("dependency on java.sql not found", reqCompiler); + assertTrue("dependency should be transitive", reqSql.isTransitive()); + assertTrue("dependency should be transitive", reqCompiler.isTransitive()); + } + /* + * Test a source module can be retrieved and verify its requires attributes + */ + public void testSourceModule2() { + ModuleElement mod = _elementUtils.getModuleElement("mod.b"); + assertNotNull("mod.b module null", mod); + List<? extends Directive> directives = mod.getDirectives(); + List<Directive> filterDirective = filterDirective(directives, DirectiveKind.REQUIRES); + assertEquals("Incorrect no of requires", 2, filterDirective.size()); + RequiresDirective reqCompiler = null; + RequiresDirective reqSql = null; + RequiresDirective reqA = null; + for (Directive directive : filterDirective) { + if (((RequiresDirective) directive).getDependency().getQualifiedName().toString().equals("java.compiler")) { + reqCompiler = (RequiresDirective) directive; + } + if (((RequiresDirective) directive).getDependency().getQualifiedName().toString().equals("java.sql")) { + reqSql = (RequiresDirective) directive; + } + if (((RequiresDirective) directive).getDependency().getQualifiedName().toString().equals("mod.a")) { + reqA = (RequiresDirective) directive; + } + } + assertNull("dependency on java.sql should not be visible", reqSql); + assertNull("dependency on java.compiler should not be visible", reqCompiler); + assertNotNull("dependency on mod.a not found", reqA); + assertFalse("dependency should not be transitive", reqA.isTransitive()); + } + public void testUnnamedModule1() { + Set<? extends Element> rootElements = this.roundEnv.getRootElements(); + ModuleElement mod = null; + for (Element element : rootElements) { + if (element instanceof TypeElement) { + mod = _elementUtils.getModuleOf(element); + break; + } + } + assertNotNull("module should not be null", mod); + assertTrue("module should be unnamed", mod.isUnnamed()); + List<? extends Element> enclosedElements = mod.getEnclosedElements(); + List<? extends Directive> directives = mod.getDirectives(); + assertEquals("incorrect no of directives", 0, directives.size()); + List<Element> filterElements = filterElements(enclosedElements, ElementKind.PACKAGE); + assertEquals("incorrect no of packages", 3, filterElements.size()); + // FIXME: Note Javac fails here as well +// PackageElement packageOf = _elementUtils.getPackageOf(mod); +// assertNotNull("package should not be null", packageOf); + } + public void testUnnamedModule2() { + Set<? extends PackageElement> allPackageElements = _elementUtils.getAllPackageElements("targets.model9.p"); + assertEquals("incorrect no of packages", 1, allPackageElements.size()); + TypeElement typeElement =_elementUtils.getTypeElement("targets.model9.p.A"); + assertNotNull("Type should not be null", typeElement); + ModuleElement m = _elementUtils.getModuleOf(typeElement); + assertEquals("module should be unnamed", "", m.getQualifiedName().toString()); + } + public void testUnnamedModule3() { + Set<? extends Element> rootElements = this.roundEnv.getRootElements(); + ModuleElement moduleElement = _elementUtils.getModuleElement(""); + assertNotNull("module should not be null", moduleElement); + ModuleElement mod = null; + for (Element element : rootElements) { + if (element instanceof TypeElement) { + mod = (ModuleElement) element.getEnclosingElement().getEnclosingElement(); + break; + } + } + assertEquals("modules should be equal", mod, moduleElement); + assertNotNull("module should not be null", mod); + List<Element> filterElements = filterElements(mod.getEnclosedElements(), ElementKind.PACKAGE); + assertEquals("incorrect no of packages", 1, filterElements.size()); + } + public void testUnnamedModule4() { + ModuleElement moduleElement = _elementUtils.getModuleElement(""); + assertNotNull("module should not be null", moduleElement); + List<Element> filterElements = filterElements(moduleElement.getEnclosedElements(), ElementKind.PACKAGE); + PackageElement pack = (PackageElement) filterElements.get(0); + assertEquals("incorect package", "targets.model9a.internal", pack.getQualifiedName().toString()); + List<? extends Element> enclosedElements = pack.getEnclosedElements(); + assertEquals("incorrect no of types", 2, enclosedElements.size()); + } + public void testUnnamedModule5() { + ModuleElement moduleElement = _elementUtils.getModuleElement(""); + assertNotNull("module should not be null", moduleElement); + List<Element> filterElements = filterElements(moduleElement.getEnclosedElements(), ElementKind.PACKAGE); + PackageElement pack = (PackageElement) filterElements.get(0); + assertEquals("incorect package", "targets.model9x", pack.getQualifiedName().toString()); + List<? extends Element> enclosedElements = pack.getEnclosedElements(); + assertEquals("incorrect no of types", 1, enclosedElements.size()); + } public void testBug521723() { // private int foo1(int i) { return i; } // default int foo2(int i) {return foo(i); } @@ -86,4 +686,144 @@ public class Java9ElementProcessor extends Java8ElementProcessor { } assertTrue("modifiers still present: " + list.toString(), list.isEmpty()); } + protected <E extends Element> List<Element> filterElements(Iterable<? extends E> list, ElementKind kind) { + List<Element> elements = new ArrayList<>(); + for (Element e : list) { + if (e.getKind() == kind) + elements.add(e); + } + return elements; + } + protected <D extends Directive> List<Directive> filterDirective(Iterable<? extends Directive> list, DirectiveKind kind) { + List<Directive> directives = new ArrayList<>(); + for (Directive d : list) { + if (d.getKind() == kind) + directives.add(d); + } + return directives; + } + + @Override + public void reportError(String msg) { + throw new AssertionFailedError(msg); + } + private String getExceptionStackTrace(Throwable t) { + StringBuffer buf = new StringBuffer(t.getMessage()); + StackTraceElement[] traces = t.getStackTrace(); + for (int i = 0; i < traces.length; i++) { + StackTraceElement trace = traces[i]; + buf.append("\n\tat " + trace); + if (i == 12) + break; // Don't dump all stacks + } + return buf.toString(); + } + public void assertModifiers(Set<Modifier> modifiers, String[] expected) { + assertEquals("Incorrect no of modifiers", modifiers.size(), expected.length); + Set<String> actual = new HashSet<String>(expected.length); + for (Modifier modifier : modifiers) { + actual.add(modifier.toString()); + } + for(int i = 0, length = expected.length; i < length; i++) { + boolean result = actual.remove(expected[i]); + if (!result) reportError("Modifier not present :" + expected[i]); + } + if (!actual.isEmpty()) { + reportError("Unexpected modifiers present:" + actual.toString()); + } + } + public void assertTrue(String msg, boolean value) { + if (!value) reportError(msg); + } + public void assertFalse(String msg, boolean value) { + if (value) reportError(msg); + } + public void assertSame(String msg, Object obj1, Object obj2) { + if (obj1 != obj2) { + reportError(msg + ", should be " + obj1.toString() + " but " + obj2.toString()); + } + } + public void assertNotSame(String msg, Object obj1, Object obj2) { + if (obj1 == obj2) { + reportError(msg + ", " + obj1.toString() + " should not be same as " + obj2.toString()); + } + } + public void assertNotNull(String msg, Object obj) { + if (obj == null) { + reportError(msg); + } + } + public void assertNull(String msg, Object obj) { + if (obj != null) { + reportError(msg); + } + } + public void assertEquals(String message, Object expected, Object actual) { + if (equalsRegardingNull(expected, actual)) { + return; + } else { + reportError(message + ", expected " + expected.toString() + " but was " + actual.toString()); + } + } + + public void assertEquals(String message, Object expected, Object alternateExpected, Object actual) { + if (equalsRegardingNull(expected, actual) || equalsRegardingNull(alternateExpected, actual)) { + return; + } else { + reportError(message + ", expected " + expected.toString() + " but was " + actual.toString()); + } + } + + static boolean equalsRegardingNull(Object expected, Object actual) { + if (expected == null) { + return actual == null; + } + return expected.equals(actual); + } + + public void assertEquals(String msg, int expected, int actual) { + if (expected != actual) { + StringBuffer buf = new StringBuffer(); + buf.append(msg); + buf.append(", expected " + expected + " but was " + actual); + reportError(buf.toString()); + } + } + public void assertEquals(Object expected, Object actual) { + if (expected != actual) { + + } + } + private void verifyAnnotations(AnnotatedConstruct construct, String[] annots) { + List<? extends AnnotationMirror> annotations = construct.getAnnotationMirrors(); + assertEquals("Incorrect no of annotations", annots.length, annotations.size()); + for(int i = 0, length = annots.length; i < length; i++) { + AnnotationMirror mirror = annotations.get(i); + assertEquals("Invalid annotation value", annots[i], getAnnotationString(mirror)); + } + } + + private String getAnnotationString(AnnotationMirror annot) { + DeclaredType annotType = annot.getAnnotationType(); + TypeElement type = (TypeElement) annotType.asElement(); + StringBuffer buf = new StringBuffer("@" + type.getQualifiedName()); + Map<? extends ExecutableElement, ? extends AnnotationValue> values = annot.getElementValues(); + Set<? extends ExecutableElement> keys = values.keySet(); + buf.append('('); + for (ExecutableElement executableElement : keys) { // @Marker3() + buf.append(executableElement.getSimpleName()); + buf.append('='); + AnnotationValue value = values.get(executableElement); + buf.append(value.getValue()); + } + buf.append(')'); + return buf.toString(); + } + private class AssertionFailedError extends Error { + private static final long serialVersionUID = 1L; + + public AssertionFailedError(String msg) { + super(msg); + } + } } diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/AllTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/AllTests.java index c897d8345b..80c1046aa3 100644 --- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/AllTests.java +++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/AllTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2014 IBM, BEA Systems, Inc. and others + * Copyright (c) 2006, 2017 IBM, BEA Systems, Inc. and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -31,6 +31,7 @@ public class AllTests extends TestCase { suite.addTestSuite(ModelUtilTests.class); suite.addTestSuite(NegativeTests.class); suite.addTestSuite(Java8ElementsTests.class); + suite.addTestSuite(Java9ElementsTests.class); suite.addTestSuite(AnnotationProcessorTests.class); return suite; } diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java index 099cb11166..7bed895965 100644 --- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java +++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchTestUtils.java @@ -1,9 +1,13 @@ /******************************************************************************* - * Copyright (c) 2007, 2015 BEA Systems, Inc. + * Copyright (c) 2007, 2017 BEA Systems, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. * * Contributors: * wharley@bea.com - initial API and implementation @@ -13,9 +17,6 @@ package org.eclipse.jdt.compiler.apt.tests; -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Platform; - import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; @@ -42,6 +43,9 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Platform; + /** * Helper class to support compilation and results checking for tests running in batch mode. * @since 3.3 @@ -98,6 +102,11 @@ public class BatchTestUtils { System.err.println("Compilation failed: " + errorOutput); junit.framework.TestCase.assertTrue("Compilation failed : " + errorOutput, false); } + try { + manager.close(); + } catch (IOException e) { + e.printStackTrace(); + } } public static void compileTree(JavaCompiler compiler, List<String> options, File targetFolder) { @@ -113,6 +122,66 @@ public class BatchTestUtils { compileTree(compiler, options, targetFolder, useJLS8Processors, null); } + public static void compileInModuleMode(JavaCompiler compiler, List<String> options, String processor, + File targetFolder, DiagnosticListener<? super JavaFileObject> listener, boolean multiModule) { + StandardJavaFileManager manager = compiler.getStandardFileManager(null, Locale.getDefault(), Charset.defaultCharset()); + Iterable<? extends File> location = manager.getLocation(StandardLocation.CLASS_PATH); + // create new list containing inputfile + List<File> files = new ArrayList<File>(); + findFilesUnder(targetFolder, files); + Iterable<? extends JavaFileObject> units = manager.getJavaFileObjectsFromFiles(files); + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + + List<String> copyOptions = new ArrayList<>(); + copyOptions.add("-processor"); + copyOptions.add(processor); + copyOptions.add("-A" + processor); + copyOptions.add("-d"); + copyOptions.add(_tmpBinFolderName); + copyOptions.add("-s"); + copyOptions.add(_tmpGenFolderName); + addModuleProcessorPath(copyOptions, getSrcFolderName(), multiModule); + copyOptions.add("-XprintRounds"); + CompilationTask task = compiler.getTask(printWriter, manager, listener, copyOptions, null, units); + Boolean result = task.call(); + + if (!result.booleanValue()) { + String errorOutput = stringWriter.getBuffer().toString(); + System.err.println("Compilation failed: " + errorOutput); + junit.framework.TestCase.assertTrue("Compilation failed : " + errorOutput, false); + } + List<String> classes = new ArrayList<>(); + try { + System.clearProperty(processor); + copyOptions = new ArrayList<>(); + copyOptions.addAll(options); + copyOptions.add("-cp"); + copyOptions.add(_jls8ProcessorJarPath + File.pathSeparator + _tmpGenFolderName); + copyOptions.add("--processor-module-path"); + copyOptions.add(_jls8ProcessorJarPath); + copyOptions.add("--module-path"); + copyOptions.add(_tmpBinFolderName); + classes.add("java.base/java.lang.Object"); // This is required to make sure BTB for Object is fully populated. + findClassesUnderModules(Paths.get(_tmpBinFolderName), classes); + manager.setLocation(StandardLocation.CLASS_PATH, location); + task = compiler.getTask(printWriter, manager, listener, copyOptions, classes, null); + result = task.call(); + if (!result.booleanValue()) { + String errorOutput = stringWriter.getBuffer().toString(); + System.err.println("Compilation failed: " + errorOutput); + junit.framework.TestCase.assertTrue("Compilation failed : " + errorOutput, false); + } + } catch (IOException e) { + // print the stack just in case. + e.printStackTrace(); + } + try { + manager.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } public static void compileTree(JavaCompiler compiler, List<String> options, File targetFolder, boolean useJLS8Processors, DiagnosticListener<? super JavaFileObject> listener) { @@ -139,6 +208,11 @@ public class BatchTestUtils { System.err.println("Compilation failed: " + errorOutput); junit.framework.TestCase.assertTrue("Compilation failed : " + errorOutput, false); } + try { + manager.close(); + } catch (IOException e) { + e.printStackTrace(); + } } /* * First compiles the given files without processor, then processes them @@ -180,7 +254,7 @@ public class BatchTestUtils { copyOptions.add("-processorpath"); copyOptions.add(_jls8ProcessorJarPath); classes.add("java.lang.Object"); // This is required to make sure BTB for Object is fully populated. - findClassesUnder(Paths.get(_tmpBinFolderName), null, classes); + findClassesUnder(Paths.get(_tmpBinFolderName), null, classes, null); manager.setLocation(StandardLocation.CLASS_PATH, location); task = compiler.getTask(printWriter, manager, listener, copyOptions, classes, null); result = task.call(); @@ -241,7 +315,11 @@ public class BatchTestUtils { StringWriter writer = new StringWriter(); CompilationTask task = compiler.getTask(writer, manager, diagnosticListener, options, null, units); Boolean result = task.call(); - + try { + manager.close(); + } catch (IOException e) { + e.printStackTrace(); + } return result.booleanValue(); } @@ -265,18 +343,31 @@ public class BatchTestUtils { } } - protected static void findClassesUnder(Path root, Path folder, List<String> classes) throws IOException { + protected static void findClassesUnderModules(Path modulePath, List<String> classes) throws IOException { + try (DirectoryStream<Path> stream = Files.newDirectoryStream(modulePath)) { + for (Path entry : stream) { + if (Files.isDirectory(entry)) { + findClassesUnder(entry, entry, classes, entry.getFileName().toString()); + } + } + } + } + protected static void findClassesUnder(Path root, Path folder, List<String> classes, String moduleName) throws IOException { if (folder == null) folder = root; try (DirectoryStream<Path> stream = Files.newDirectoryStream(folder)) { for (Path entry : stream) { if (Files.isDirectory(entry)) { - findClassesUnder(root, entry, classes); + findClassesUnder(root, entry, classes, moduleName); } else { - if (entry.getFileName().toString().endsWith(".class")) { + String fileName = entry.getFileName().toString(); + if (fileName.endsWith(".class") && !fileName.startsWith("module-info")) { String className = root.relativize(entry).toString(); className = className.substring(0, className.indexOf(".class")); className = className.replace(File.separatorChar, '.'); + if (moduleName != null) { + className = moduleName + "/" + className; + } classes.add(className); } } @@ -372,6 +463,16 @@ public class BatchTestUtils { options.add("-processorpath"); options.add(path); } + private static void addModuleProcessorPath(List<String> options, String srcFolderName, boolean multiModule) { + options.add("--processor-module-path"); + options.add(_jls8ProcessorJarPath); + options.add("--module-path"); + options.add(_jls8ProcessorJarPath); + if (multiModule) { + options.add("--module-source-path"); + options.add(srcFolderName); + } + } public static void tearDown() { new File(_processorJarPath).deleteOnExit(); @@ -446,6 +547,10 @@ public class BatchTestUtils { contents = TestUtils.convertToIndependentLineDelimiter(contents); srcBytes = contents.getBytes(); } + writeFile(dest, srcBytes); + } + + public static void writeFile(File dest, byte[] srcBytes) throws IOException { File destFolder = dest.getParentFile(); if (!destFolder.exists()) { diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java index 96396308b8..b2b88767b5 100644 --- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java +++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java @@ -20,12 +20,12 @@ import javax.lang.model.SourceVersion; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; +import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; + import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; -import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; - public class Java8ElementsTests extends TestCase { private static final String JAVA8_ANNOTATION_PROC = "org.eclipse.jdt.compiler.apt.tests.processors.elements.Java8ElementProcessor"; @@ -60,7 +60,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations"); } - public void _testTypeAnnotationsWithJavac() throws Exception { + public void testTypeAnnotationsWithJavac() throws Exception { + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations"); } @@ -76,7 +78,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations2"); } - public void _testTypeAnnotations2WithJavac() throws Exception { + public void testTypeAnnotations2WithJavac() throws Exception { + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations2"); } @@ -84,7 +88,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations3"); } - public void _testTypeAnnotations3WithJavac() throws Exception { + public void testTypeAnnotations3WithJavac() throws Exception { + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations3"); } @@ -92,7 +98,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations4"); } - public void _testTypeAnnotations4WithJavac() throws Exception { + public void testTypeAnnotations4WithJavac() throws Exception { + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations4"); } @@ -100,7 +108,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations5"); } - public void _testTypeAnnotations5WithJavac() throws Exception { + public void testTypeAnnotations5WithJavac() throws Exception { + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations5"); } @@ -108,7 +118,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations6"); } - public void _testTypeAnnotations6WithJavac() throws Exception { // Disabled for now. Javac 8b108 drops annotations arrays preceding varargs. + public void testTypeAnnotations6WithJavac() throws Exception { // Disabled for now. Javac 8b108 drops annotations arrays preceding varargs. + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations6"); } @@ -148,7 +160,9 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations11"); } - public void _testTypeAnnotations11WithJavac() throws Exception { + public void testTypeAnnotations11WithJavac() throws Exception { + if (!canRunJava9()) + return; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testTypeAnnotations11"); } @@ -301,7 +315,8 @@ public class Java8ElementsTests extends TestCase { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testPackageAnnotations", null, "filer8"); } - public void testPackageAnnotationsWithJavac() throws Exception { + // See Java8ElementProcessor.testPackageAnnotations() + public void _testPackageAnnotationsWithJavac() throws Exception { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); internalTest(compiler, JAVA8_ANNOTATION_PROC, "testPackageAnnotations", null, "filer8"); } @@ -418,6 +433,14 @@ public class Java8ElementsTests extends TestCase { } return true; } + public boolean canRunJava9() { + try { + SourceVersion.valueOf("RELEASE_9"); + } catch(IllegalArgumentException iae) { + return false; + } + return true; + } @Override protected void tearDown() throws Exception { super.tearDown(); diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java9ElementsTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java9ElementsTests.java index d55a48a9ef..a3e2659e04 100644 --- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java9ElementsTests.java +++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java9ElementsTests.java @@ -24,33 +24,356 @@ import javax.lang.model.SourceVersion; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; +import junit.framework.TestCase; + public class Java9ElementsTests extends TestCase { + private static final String MODULE_PROC = "org.eclipse.jdt.compiler.apt.tests.processors.elements.Java9ElementProcessor"; + + public void testRootElements1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testRootElements1", null); + } + public void testRootElements1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testRootElements1", null); + } + + public void testRootElements2Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testRootElements2", null); + } + public void testRootElements2() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testRootElements2", null); + } + + public void testAnnotations1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleAnnotation1", null); + } + public void testAnnotations1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleAnnotation1", null); + } + + public void testModuleElement1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement1", null); + } + public void testModuleElement1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement1", null); + } + + public void testModuleElement2Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement2", null); + } + public void testModuleElement2() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement2", null); + } + + public void testModuleElement3Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement3", null); + } + public void testModuleElement3() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement3", null); + } + public void testModuleElement4Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement4", null); + } + public void testModuleElement4() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement4", null); + } + + public void testModuleElement5Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement5", null); + } + public void testModuleElement5() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement5", null); + } + + public void testModuleElement6Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement6", null); + } + public void testModuleElement6() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement6", null); + } + + public void testModuleElement7Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleElement7", null); + } + public void testModuleElement7() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleElement7", null); + } + + public void testModuleJavaBase1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase1", null); + } + public void testModuleJavaBase1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase1", null); + } + + + public void testModuleJavaBase2Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase2", null); + } + public void testModuleJavaBase2() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase2", null); + } + - private static final String JAVA9_ANNOTATION_PROC = "org.eclipse.jdt.compiler.apt.tests.processors.elements.Java9ElementProcessor"; + public void testModuleJavaBase3Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase3", null); + } + public void testModuleJavaBase3() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase3", null); + } - public static Test suite() { - return new TestSuite(Java9ElementsTests.class); + public void testModuleJavaBase4Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase4", null); + } + public void testModuleJavaBase4() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase4", null); } - @Override - protected void setUp() throws Exception { - super.setUp(); - BatchTestUtils.init(); + public void testModuleJavaBase5Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase5", null); + } + public void testModuleJavaBase5() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleJavaBase5", null); + } + + public void testModuleTypeMirror1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleTypeMirror1", null); + } + public void testModuleTypeMirror1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleTypeMirror1", null); } + public void testModuleTypeMirror2Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleTypeMirror2", null); + } + public void testModuleTypeMirror2() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleTypeMirror2", null); + } + + public void testModuleJavaSql1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testModuleJavaSql1", null); + } + public void testModuleJavaSql1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testModuleJavaSql1", null); + } + + public void testSourceModule1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testSourceModule1", null); + } + public void testSourceModule1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testSourceModule1", null); + } + + public void testSourceModule2Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest2(compiler, MODULE_PROC, "testSourceModule2", null); + } + public void testSourceModule2() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest2(compiler, MODULE_PROC, "testSourceModule2", null); + } + public void testUnnamedModule1Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest(compiler, MODULE_PROC, "testUnnamedModule1", null, "model9"); + } + public void testUnnamedModule1() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest(compiler, MODULE_PROC, "testUnnamedModule1", null, "model9"); + } + public void testUnnamedModule2Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest(compiler, MODULE_PROC, "testUnnamedModule2", null, "model9"); + } + public void testUnnamedModule2() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest(compiler, MODULE_PROC, "testUnnamedModule2", null, "model9"); + } + public void testUnnamedModule3Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest(compiler, MODULE_PROC, "testUnnamedModule3", null, "model9a"); + } + public void testUnnamedModule3() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest(compiler, MODULE_PROC, "testUnnamedModule3", null, "model9a"); + } + public void testUnnamedModule4Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest(compiler, MODULE_PROC, "testUnnamedModule4", null, "model9a"); + } + public void testUnnamedModule4() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest(compiler, MODULE_PROC, "testUnnamedModule4", null, "model9a"); + } + public void testUnnamedModule5Javac() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + internalTest(compiler, MODULE_PROC, "testUnnamedModule5", null, new String[] { + "targets/model9x/X.java", + "package targets.model9x;\n" + + "public class X {\n" + + " X(final int j) {\n" + + " j = 4;\n" + + " }\n" + + "}\n" + }); + } + public void testUnnamedModule5() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + internalTest(compiler, MODULE_PROC, "testUnnamedModule5", null, new String[] { + "targets/model9x/X.java", + "package targets.model9x;\n" + + "public class X {\n" + + " X(final int j) {\n" + + " j = 4;\n" + + " }\n" + + "}\n" + }); + } public void testBug521723() throws IOException { JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); - internalTestWithBinary(compiler, JAVA9_ANNOTATION_PROC, "9", "testBug521723", null, "bug521723"); + internalTestWithBinary(compiler, MODULE_PROC, "9", "testBug521723", null, "bug521723"); } public void testBug521723Javac() throws IOException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - internalTestWithBinary(compiler, JAVA9_ANNOTATION_PROC, "9", "testBug521723", null, "bug521723"); + internalTestWithBinary(compiler, MODULE_PROC, "9", "testBug521723", null, "bug521723"); } protected void internalTestWithBinary(JavaCompiler compiler, String processor, String compliance, String testMethod, String testClass, String resourceArea) throws IOException { @@ -84,6 +407,86 @@ public class Java9ElementsTests extends TestCase { // if not, it will set it to an error value. assertEquals("succeeded", System.getProperty(processor)); } + private void internalTest(JavaCompiler compiler, String processor, String testMethod, String testClass, String[] source) throws IOException { + if (!canRunJava9()) { + return; + } + if ((source.length % 2) != 0) return; + + File targetFolder = TestUtils.concatPath(BatchTestUtils.getSrcFolderName()); + for(int i = 0; i < source.length;) { + File targetFile = TestUtils.concatPath(BatchTestUtils.getSrcFolderName(), source[i++]); + BatchTestUtils.writeFile(targetFile, source[i++].getBytes()); + } + + List<String> options = new ArrayList<String>(); + options.add("-processor"); + options.add(MODULE_PROC); + options.add("-A" + processor); + options.add("-A" + testMethod); + if (compiler instanceof EclipseCompiler) { + options.add("-9"); + } + BatchTestUtils.compileTreeWithErrors(compiler, options, targetFolder, null, true, true); + + // If it succeeded, the processor will have set this property to "succeeded"; + // if not, it will set it to an error value. + assertEquals("succeeded", System.getProperty(processor)); + } + private void internalTest(JavaCompiler compiler, String processor, String testMethod, String testClass, String resourceArea) throws IOException { + internalTest(compiler, processor, testMethod, testClass, resourceArea, false); + } + private void internalTest(JavaCompiler compiler, String processor, String testMethod, String testClass, String resourceArea, boolean continueWithErrors) throws IOException { + if (!canRunJava9()) { + return; + } + System.clearProperty(processor); + File targetFolder = TestUtils.concatPath(BatchTestUtils.getSrcFolderName(), "targets", resourceArea); + if (testClass == null || testClass.equals("")) { + BatchTestUtils.copyResources("targets/" + resourceArea, targetFolder); + } else { + BatchTestUtils.copyResource("targets/" + resourceArea + "/" + testClass, targetFolder); + } + + + List<String> options = new ArrayList<String>(); + options.add("-A" + processor); + options.add("-A" + testMethod); + if (compiler instanceof EclipseCompiler) { + options.add("-9"); + } + if (continueWithErrors) { + BatchTestUtils.compileTreeWithErrors(compiler, options, targetFolder, null, true, true); + } else { + BatchTestUtils.compileTree(compiler, options, targetFolder, true); + } + + // If it succeeded, the processor will have set this property to "succeeded"; + // if not, it will set it to an error value. + assertEquals("succeeded", System.getProperty(processor)); + } + /* + * Tests are run in multi-module mode + */ + private void internalTest2(JavaCompiler compiler, String processor, String testMethod, String testClass) throws IOException { + if (!canRunJava9()) { + return; + } + System.clearProperty(MODULE_PROC); + File srcRoot = TestUtils.concatPath(BatchTestUtils.getSrcFolderName()); + BatchTestUtils.copyResources("mod_locations/modules", srcRoot); + + List<String> options = new ArrayList<String>(); + options.add("-processor"); + options.add(MODULE_PROC); + options.add("-A" + MODULE_PROC); + options.add("-A" + testMethod); + if (compiler instanceof EclipseCompiler) { + options.add("-9"); + } + BatchTestUtils.compileInModuleMode(compiler, options, MODULE_PROC, srcRoot, null, true); + assertEquals("succeeded", System.getProperty(MODULE_PROC)); + } public boolean canRunJava9() { try { SourceVersion.valueOf("RELEASE_9"); @@ -92,8 +495,21 @@ public class Java9ElementsTests extends TestCase { } return true; } + /* (non-Javadoc) + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + BatchTestUtils.init(); + } + + /* (non-Javadoc) + * @see junit.framework.TestCase#tearDown() + */ @Override protected void tearDown() throws Exception { super.tearDown(); } -} + +}
\ No newline at end of file diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/AnnotationDiscoveryVisitor.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/AnnotationDiscoveryVisitor.java index 6ff1af5ada..12d1b12501 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/AnnotationDiscoveryVisitor.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/AnnotationDiscoveryVisitor.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2006, 2015 IBM Corporation and others. + * Copyright (c) 2006, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -23,6 +27,7 @@ import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; @@ -35,6 +40,7 @@ import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; @@ -221,6 +227,16 @@ public class AnnotationDiscoveryVisitor extends ASTVisitor { } return true; } + @Override + public boolean visit(ModuleDeclaration module, CompilationUnitScope scope) { + ModuleBinding binding = module.binding; + if (binding == null) { + return false; + } + module.resolveTypeDirectives(scope); + // The above call also resolvesAnnotations + return true; + } private void resolveAnnotations(BlockScope scope, Annotation[] annotations, Binding currentBinding) { diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java index 2b195ff904..61903f9aae 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchAnnotationProcessorManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.apt.dispatch; +import java.io.File; import java.io.IOException; import java.net.URLClassLoader; import java.util.ArrayList; @@ -23,6 +24,9 @@ import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import javax.annotation.processing.Processor; +import javax.lang.model.SourceVersion; +import javax.tools.JavaFileManager; +import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; import org.eclipse.jdt.internal.compiler.batch.Main; @@ -74,7 +78,21 @@ public class BatchAnnotationProcessorManager extends BaseAnnotationProcessorMana } BatchProcessingEnvImpl processingEnv = new BatchProcessingEnvImpl(this, (Main) batchCompiler, commandLineArguments); _processingEnv = processingEnv; - _procLoader = processingEnv.getFileManager().getClassLoader(StandardLocation.ANNOTATION_PROCESSOR_PATH); + JavaFileManager fileManager = processingEnv.getFileManager(); + if (fileManager instanceof StandardJavaFileManager) { + Iterable<? extends File> location = null; + if (SourceVersion.latest().compareTo(SourceVersion.RELEASE_8) > 0) { + location = ((StandardJavaFileManager) fileManager).getLocation(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH); + } + if (location != null) { + _procLoader = fileManager.getClassLoader(StandardLocation.ANNOTATION_PROCESSOR_MODULE_PATH); + } else { + _procLoader = fileManager.getClassLoader(StandardLocation.ANNOTATION_PROCESSOR_PATH); + } + } else { + // Fall back to old code + _procLoader = fileManager.getClassLoader(StandardLocation.ANNOTATION_PROCESSOR_PATH); + } parseCommandLine(commandLineArguments); _round = 0; } diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/RoundEnvImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/RoundEnvImpl.java index 169a6ca35a..77fa4df7c7 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/RoundEnvImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/RoundEnvImpl.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation * IBM Corporation - Fix for bug 328575 @@ -210,6 +214,11 @@ public class RoundEnvImpl implements RoundEnvironment if (_rootElements == null) { Set<Element> elements = new HashSet<>(_units.length); for (CompilationUnitDeclaration unit : _units) { + if (unit.moduleDeclaration != null && unit.moduleDeclaration.binding != null) { + Element m = _factory.newElement(unit.moduleDeclaration.binding); + elements.add(m); + continue; + } if (null == unit.scope || null == unit.scope.topLevelTypes) continue; for (SourceTypeBinding binding : unit.scope.topLevelTypes) { diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementImpl.java index c82b8add9a..b2e7c4c40a 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2014 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -79,6 +79,7 @@ public abstract class ElementImpl return _env.getFactory().getAnnotationMirrors(getPackedAnnotationBindings()); } + @Override public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { A [] annotations = _env.getFactory().getAnnotationsByType(Factory.getUnpackedAnnotationBindings(getPackedAnnotationBindings()), annotationType); if (annotations.length != 0 || this.getKind() != ElementKind.CLASS || annotationType.getAnnotation(Inherited.class) == null) @@ -137,9 +138,10 @@ public abstract class ElementImpl /** * @return the package containing this element. The package of a PackageElement is itself. - * @see javax.lang.model.util.Elements#getPackageOf(javax.lang.model.element.Element) */ - abstract /* package */ PackageElement getPackage(); + PackageElement getPackage() { + return null; + } /** * Subclassed by VariableElementImpl, TypeElementImpl, and ExecutableElementImpl. diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java index 5191ad1d39..9026c4d594 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ElementsImpl.java @@ -31,11 +31,13 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.lang.model.AnnotatedConstruct; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.ModuleElement; import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; @@ -54,12 +56,14 @@ import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodVerifier; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; +import org.eclipse.jdt.internal.compiler.util.HashtableOfModule; /** * Utilities for working with language elements. @@ -559,14 +563,14 @@ public class ElementsImpl implements Elements { public PackageElement getPackageElement(CharSequence name) { LookupEnvironment le = _env.getLookupEnvironment(); // FIXME(SHMOD): does this lookup need to be module-aware? if (name.length() == 0) { - return new PackageElementImpl(_env, le.defaultPackage); + return (PackageElement) _env.getFactory().newElement(le.defaultPackage); } char[] packageName = name.toString().toCharArray(); PackageBinding packageBinding = le.createPackage(CharOperation.splitOn('.', packageName)); if (packageBinding == null) { return null; } - return new PackageElementImpl(_env, packageBinding); + return (PackageElement) _env.getFactory().newElement(packageBinding); } @Override @@ -614,9 +618,27 @@ public class ElementsImpl implements Elements { */ @Override public TypeElement getTypeElement(CharSequence name) { - LookupEnvironment le = _env.getLookupEnvironment(); final char[][] compoundName = CharOperation.splitOn('.', name.toString().toCharArray()); - ReferenceBinding binding = le.getType(compoundName); + Set<? extends ModuleElement> allModuleElements = getAllModuleElements(); + for (ModuleElement moduleElement : allModuleElements) { + TypeElement t = getTypeElement(compoundName, ((ModuleElementImpl) moduleElement).binding); + if (t != null) { + return t; + } + } + return null; + } + + @Override + public TypeElement getTypeElement(ModuleElement module, CharSequence name) { + ModuleBinding mBinding = ((ModuleElementImpl) module).binding; + final char[][] compoundName = CharOperation.splitOn('.', name.toString().toCharArray()); + return getTypeElement(compoundName, mBinding); + } + + private TypeElement getTypeElement(final char[][] compoundName, ModuleBinding mBinding) { + LookupEnvironment le = mBinding == null ? _env.getLookupEnvironment() : mBinding.environment; + ReferenceBinding binding = mBinding == null ? le.getType(compoundName) : le.getType(compoundName, mBinding); // If we didn't find the binding, maybe it's a nested type; // try finding the top-level type and then working downwards. if (null == binding) { @@ -706,6 +728,7 @@ public class ElementsImpl implements Elements { } } + @Override public boolean isFunctionalInterface(TypeElement type) { if (type != null && type.getKind() == ElementKind.INTERFACE) { ReferenceBinding binding = (ReferenceBinding)((TypeElementImpl) type)._binding; @@ -716,4 +739,94 @@ public class ElementsImpl implements Elements { return false; } + @Override + public + PackageElement getPackageElement(ModuleElement module, CharSequence name) { + ModuleBinding mBinding = ((ModuleElementImpl) module).binding; + final char[][] compoundName = CharOperation.splitOn('.', name.toString().toCharArray()); + PackageBinding p = null; + if (mBinding != null) { + + int length = compoundName.length; + if (length > 1) { + char[][] parent = new char[compoundName.length - 1][]; + System.arraycopy(compoundName, 0, parent, 0, length - 1); + p = mBinding.getPackage(parent, compoundName[length - 1]); + } else { + p = mBinding.getTopLevelPackage(compoundName[0]); + } + } else { + p = _env.getLookupEnvironment().createPackage(compoundName); + } + if (p == null || !p.isValidBinding()) + return null; + return (PackageElement) _env.getFactory().newElement(p); + } + + @Override + public ModuleElement getModuleElement(CharSequence name) { + LookupEnvironment lookup = _env.getLookupEnvironment(); + ModuleBinding binding = lookup.getModule(name.length() == 0 ? ModuleBinding.UNNAMED : name.toString().toCharArray()); + //TODO: Surely there has to be a better way than calling toString().toCharArray()? + if (binding == null) { + return null; + } + return new ModuleElementImpl(_env, binding); + } + + @Override + public Set<? extends ModuleElement> getAllModuleElements() { + LookupEnvironment lookup = _env.getLookupEnvironment(); + HashtableOfModule knownModules = lookup.knownModules; + ModuleBinding[] modules = knownModules.valueTable; + if (modules == null || modules.length == 0) { + return Collections.emptySet(); + } + Set<ModuleElement> mods = new HashSet<>(modules.length); + for (ModuleBinding moduleBinding : modules) { + if (moduleBinding == null) + continue; + ModuleElement element = (ModuleElement) _env.getFactory().newElement(moduleBinding); + mods.add(element); + } + mods.add((ModuleElement) _env.getFactory().newElement(lookup.UnNamedModule)); + return mods; + } + + @Override + public Origin getOrigin(Element e) { + return Origin.EXPLICIT; + } + + @Override + public Origin getOrigin(AnnotatedConstruct c, AnnotationMirror a) { + return Origin.EXPLICIT; + } + + @Override + public Origin getOrigin(ModuleElement m, ModuleElement.Directive directive) { + return Origin.EXPLICIT; + } + + @Override + public boolean isBridge(ExecutableElement e) { + MethodBinding methodBinding = (MethodBinding) ((ExecutableElementImpl) e)._binding; + return methodBinding.isBridge(); + } + + @Override + public ModuleElement getModuleOf(Element elem) { + if (elem instanceof ModuleElement) { + return (ModuleElement) elem; + } + Element parent = elem.getEnclosingElement(); + while (parent != null) { + if (parent instanceof ModuleElement) { + return (ModuleElement) parent; + } + parent = parent.getEnclosingElement(); + } + return null; + } + } diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java index 70ac259038..59ad683f9a 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/Factory.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2007, 2016 BEA Systems, Inc. and others + * Copyright (c) 2007, 2017 BEA Systems, Inc. and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * wharley@bea.com - initial API and implementation * IBM Corporation - fix for 342598 @@ -45,9 +49,11 @@ import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair; import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding; import org.eclipse.jdt.internal.compiler.lookup.TagBits; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; @@ -319,6 +325,11 @@ public class Factory { ClassFileConstants.AccStrictfp }); break; + case MODULE : + decodeModifiers(result, modifiers, new int[] { + ClassFileConstants.ACC_OPEN, + ClassFileConstants.ACC_TRANSITIVE + }); default: break; } @@ -348,7 +359,7 @@ public class Factory { return new ErrorTypeElement(this._env, referenceBinding); } if (CharOperation.equals(referenceBinding.sourceName, TypeConstants.PACKAGE_INFO_NAME)) { - return new PackageElementImpl(_env, referenceBinding.fPackage); + return newPackageElement(referenceBinding.fPackage); } return new TypeElementImpl(_env, referenceBinding, kindHint); case Binding.METHOD: @@ -357,10 +368,12 @@ public class Factory { case Binding.PARAMETERIZED_TYPE: return new TypeElementImpl(_env, ((ParameterizedTypeBinding)binding).genericType(), kindHint); case Binding.PACKAGE: - return new PackageElementImpl(_env, (PackageBinding)binding); + return newPackageElement((PackageBinding)binding); case Binding.TYPE_PARAMETER: return new TypeParameterElementImpl(_env, (TypeVariableBinding)binding); // TODO: fill in the rest of these + case Binding.MODULE: + return new ModuleElementImpl(_env, (ModuleBinding) binding); case Binding.IMPORT: case Binding.ARRAY_TYPE: case Binding.BASE_TYPE: @@ -380,6 +393,9 @@ public class Factory { */ public PackageElement newPackageElement(PackageBinding binding) { + if (binding instanceof SplitPackageBinding && binding.enclosingModule != null) { + binding = ((SplitPackageBinding) binding).getIncarnation(binding.enclosingModule); + } return new PackageElementImpl(_env, binding); } @@ -396,6 +412,8 @@ public class Factory { return NoTypeImpl.NO_TYPE_VOID; case PACKAGE: return NoTypeImpl.NO_TYPE_PACKAGE; + case MODULE: + return new NoTypeImpl(kind); default: throw new IllegalArgumentException(); } @@ -487,6 +505,8 @@ public class Factory { case Binding.TYPE_PARAMETER: return new TypeVariableImpl(_env, (TypeVariableBinding) binding); + case Binding.MODULE: + return getNoType(TypeKind.MODULE); } return null; } @@ -571,9 +591,9 @@ public class Factory { case 'c': return Character.valueOf((char) b); // narrowing. case 'd': - return new Double(b); // widening. + return Double.valueOf(b); // widening. case 'f': - return new Float(b); // widening. + return Float.valueOf(b); // widening. case 'i': return Integer.valueOf(b); // widening. case 'l': @@ -599,9 +619,9 @@ public class Factory { case 'c': return Character.valueOf((char) s); // narrowing. case 'd': - return new Double(s); // widening. + return Double.valueOf(s); // widening. case 'f': - return new Float(s); // widening. + return Float.valueOf(s); // widening. case 'i': return Integer.valueOf(s); // widening. case 'l': @@ -627,9 +647,9 @@ public class Factory { case 'c': return value; // exact match case 'd': - return new Double(c); // widening. + return Double.valueOf(c); // widening. case 'f': - return new Float(c); // widening. + return Float.valueOf(c); // widening. case 'i': return Integer.valueOf(c); // widening. case 'l': @@ -656,9 +676,9 @@ public class Factory { case 'c': return Character.valueOf((char) i); // narrowing case 'd': - return new Double(i); // widening. + return Double.valueOf(i); // widening. case 'f': - return new Float(i); // widening. + return Float.valueOf(i); // widening. case 'i': return value; // exact match case 'l': @@ -682,9 +702,9 @@ public class Factory { // completely wrong. return avoidReflectException ? getMatchingDummyValue(expectedType) : value; case 'd': - return new Double(l); // widening. + return Double.valueOf(l); // widening. case 'f': - return new Float(l); // widening. + return Float.valueOf(l); // widening. case 'l': return value; // exact match. @@ -707,7 +727,7 @@ public class Factory { // completely wrong. return avoidReflectException ? getMatchingDummyValue(expectedType) : value; case 'd': - return new Double(f); // widening. + return Double.valueOf(f); // widening. case 'f': return value; // exact match. default: @@ -877,6 +897,6 @@ public class Factory { } } } - return (AnnotationBinding[]) unpackedAnnotations.toArray(new AnnotationBinding [unpackedAnnotations.size()]); + return unpackedAnnotations.toArray(new AnnotationBinding [unpackedAnnotations.size()]); } } diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java new file mode 100644 index 0000000000..5ceca21668 --- /dev/null +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/ModuleElementImpl.java @@ -0,0 +1,378 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * + * Contributors: + * IBM Corporation - initial API and implementation + * + *******************************************************************************/ +package org.eclipse.jdt.internal.compiler.apt.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ElementVisitor; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.ModuleElement; +import javax.lang.model.element.Name; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; + +import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; +import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; +import org.eclipse.jdt.internal.compiler.lookup.SplitPackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; + +public class ModuleElementImpl extends ElementImpl implements ModuleElement { + + ModuleBinding binding; + private List<Directive> directives; + private static List<Directive> EMPTY_DIRECTIVES = Collections.emptyList(); + + /** + * In general, clients should call + * {@link Factory#newDeclaredType(ReferenceBinding)} or + * {@link Factory#newElement(org.eclipse.jdt.internal.compiler.lookup.Binding)} + * to create new instances. + */ + ModuleElementImpl(BaseProcessingEnvImpl env, ModuleBinding binding) { + super(env, binding); + this.binding = binding; + } + + private PackageBinding getModulesPackageBinding(PackageBinding binding) { + if (binding instanceof SplitPackageBinding) { + return ((SplitPackageBinding) binding).getIncarnation(this.binding); + } + return binding; + } + + @Override + public ElementKind getKind() { + return ElementKind.MODULE; + } + + @Override + public Set<Modifier> getModifiers() { + int modifiers = this.binding.tagBits; // TODO: This is wrong, this should be "modifiers" + return Factory.getModifiers(modifiers, getKind(), false); + } + + @Override + public Name getQualifiedName() { + return new NameImpl(this.binding.moduleName); + } + + @Override + public Name getSimpleName() { + return new NameImpl(this.binding.moduleName); + } + + @Override + public List<? extends Element> getEnclosedElements() { + ModuleBinding module = this.binding; + PackageBinding[] packs = module.declaredPackages.valueTable; + Set<PackageBinding> unique = new HashSet<>(); + for (PackageBinding p : packs) { + if (p == null) + continue; + if (!p.hasCompilationUnit(true)) + continue; + unique.add(getModulesPackageBinding(p)); + } + if (module.isUnnamed()) { + PackageBinding def = module.environment.defaultPackage; + // FIXME: Does it have any impact for unnamed modules - default package combo? + if (def != null && def.hasCompilationUnit(true)) { + unique.add(def); + } + } else { + packs = this.binding.getExports(); + for (PackageBinding pBinding : packs) { + unique.add(getModulesPackageBinding(pBinding)); + } + packs = this.binding.getOpens(); + for (PackageBinding pBinding : packs) { + unique.add(getModulesPackageBinding(pBinding)); + } + } + List<Element> enclosed = new ArrayList<>(unique.size()); + for (PackageBinding p : unique) { + PackageElement pElement = (PackageElement) _env.getFactory().newElement(p); + enclosed.add(pElement); + } + return Collections.unmodifiableList(enclosed); + } + + @Override + public boolean isOpen() { + return (this.binding.modifiers & ClassFileConstants.ACC_OPEN) != 0; + } + + @Override + public boolean isUnnamed() { + return this.binding.moduleName.length == 0; + } + + @Override + public Element getEnclosingElement() { + // As of today, modules have no enclosing element + return null; + } + + @Override + public List<? extends Directive> getDirectives() { + if (isUnnamed()) { + return EMPTY_DIRECTIVES; + } + if (this.directives == null) + this.directives = new ArrayList<>(); + + PackageBinding[] packs = this.binding.getExports(); + for (PackageBinding exp : packs) { + exp = getModulesPackageBinding(exp); + this.directives.add(new ExportsDirectiveImpl(exp)); + } + Set<ModuleBinding> transitive = new HashSet<>(); + for (ModuleBinding mBinding : this.binding.getRequiresTransitive()) { + transitive.add(mBinding); + } + ModuleBinding[] required = this.binding.getRequires(); + for (ModuleBinding mBinding : required) { + if (transitive.contains(mBinding)) { + this.directives.add(new RequiresDirectiveImpl(mBinding, true)); + } else { + this.directives.add(new RequiresDirectiveImpl(mBinding, false)); + } + } + + TypeBinding[] tBindings = this.binding.getUses(); + for (TypeBinding tBinding : tBindings) { + this.directives.add(new UsesDirectiveImpl(tBinding)); + } + tBindings = this.binding.getServices(); + for (TypeBinding tBinding : tBindings) { + this.directives.add(new ProvidesDirectiveImpl(tBinding)); + } + packs = this.binding.getOpens(); + for (PackageBinding exp : packs) { + exp = getModulesPackageBinding(exp); + this.directives.add(new OpensDirectiveImpl(exp)); + } + return this.directives; + } + + @Override + public <R, P> R accept(ElementVisitor<R, P> visitor, P param) { + return visitor.visitModule(this, param); + } + @Override + protected AnnotationBinding[] getAnnotationBindings() { + return ((ModuleBinding) _binding).getAnnotations(); + } + + abstract class PackageDirectiveImpl { + PackageBinding binding; + List<ModuleElement> targets; + + PackageDirectiveImpl(PackageBinding pBinding) { + this.binding = pBinding; + } + + public PackageElement getPackage() { + return _env.getFactory().newPackageElement(binding); + } + + public List<? extends ModuleElement> getTargetModules(String[] restrictions) { + if(this.targets != null) { + return targets; + } + if (restrictions.length == 0) { + return (this.targets = null); + } + List<ModuleElement> targets = new ArrayList<>(restrictions.length); + for (String string : restrictions) { + ModuleBinding target = ModuleElementImpl.this.binding.environment.getModule(string.toCharArray()); + if (target != null) { + ModuleElement element = ((ModuleElement) _env.getFactory().newElement(target)); + targets.add(element); + } + } + return (this.targets = Collections.unmodifiableList(targets)); + } + } + + class ExportsDirectiveImpl extends PackageDirectiveImpl implements ModuleElement.ExportsDirective { + + ExportsDirectiveImpl(PackageBinding pBinding) { + super(pBinding); + } + + @Override + public <R, P> R accept(DirectiveVisitor<R, P> visitor, P param) { + return visitor.visit(this); + } + + @Override + public javax.lang.model.element.ModuleElement.DirectiveKind getKind() { + return DirectiveKind.EXPORTS; + } + + @Override + public PackageElement getPackage() { + return _env.getFactory().newPackageElement(binding); + } + @Override + public List<? extends ModuleElement> getTargetModules() { + if(this.targets != null) { + return targets; + } + return getTargetModules(ModuleElementImpl.this.binding.getExportRestrictions(this.binding)); + } + + } + + class RequiresDirectiveImpl implements ModuleElement.RequiresDirective { + ModuleBinding dependency; + boolean transitive; + + RequiresDirectiveImpl(ModuleBinding dependency, boolean transitive) { + this.dependency = dependency; + this.transitive = transitive; + } + + @Override + public <R, P> R accept(DirectiveVisitor<R, P> visitor, P param) { + return visitor.visit(this); + } + + @Override + public javax.lang.model.element.ModuleElement.DirectiveKind getKind() { + return DirectiveKind.REQUIRES; + } + + @Override + public ModuleElement getDependency() { + return (ModuleElement) _env.getFactory().newElement(dependency, ElementKind.MODULE); + } + + @Override + public boolean isStatic() { + // TODO: Yet to see this in ModuleBinding. Check again. + return false; + } + + @Override + public boolean isTransitive() { + return this.transitive; + } + } + + class OpensDirectiveImpl extends PackageDirectiveImpl implements ModuleElement.OpensDirective { + + OpensDirectiveImpl(PackageBinding pBinding) { + super(pBinding); + } + + @Override + public <R, P> R accept(DirectiveVisitor<R, P> visitor, P param) { + return visitor.visit(this); + } + + @Override + public javax.lang.model.element.ModuleElement.DirectiveKind getKind() { + return DirectiveKind.OPENS; + } + @Override + public List<? extends ModuleElement> getTargetModules() { + if(this.targets != null) { + return targets; + } + return getTargetModules(ModuleElementImpl.this.binding.getOpenRestrictions(this.binding)); + } + } + + class UsesDirectiveImpl implements ModuleElement.UsesDirective { + TypeBinding binding = null; + + UsesDirectiveImpl(TypeBinding binding) { + this.binding = binding; + } + + @Override + public <R, P> R accept(DirectiveVisitor<R, P> visitor, P param) { + return visitor.visit(this); + } + + @Override + public DirectiveKind getKind() { + return DirectiveKind.USES; + } + + @Override + public TypeElement getService() { + return (TypeElement) _env.getFactory().newElement(binding); + } + + } + + class ProvidesDirectiveImpl implements ModuleElement.ProvidesDirective { + + TypeBinding service; + public List<? extends TypeElement> implementations; + + ProvidesDirectiveImpl(TypeBinding service) { + this.service = service; + } + + @Override + public <R, P> R accept(DirectiveVisitor<R, P> visitor, P param) { + return visitor.visit(this); + } + + @Override + public DirectiveKind getKind() { + return DirectiveKind.PROVIDES; + } + + @Override + public List<? extends TypeElement> getImplementations() { + if (this.implementations != null) + return this.implementations; + + TypeBinding[] implementations2 = ModuleElementImpl.this.binding.getImplementations(this.service); + if (implementations2.length == 0) { + return (this.implementations = Collections.emptyList()); + } + + List<TypeElement> list = new ArrayList<>(implementations2.length); + Factory factory = _env.getFactory(); + for (TypeBinding type: implementations2) { + TypeElement element = (TypeElement) factory.newElement(type); + list.add(element); + } + return Collections.unmodifiableList(list); + } + + @Override + public TypeElement getService() { + return (TypeElement) _env.getFactory().newElement(this.service); + } + } +} diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/NoTypeImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/NoTypeImpl.java index 2efe713c07..adc49321fb 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/NoTypeImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/NoTypeImpl.java @@ -35,7 +35,7 @@ public class NoTypeImpl implements NoType, NullType public static final NoType NO_TYPE_PACKAGE = new NoTypeImpl(TypeKind.PACKAGE); public static final NullType NULL_TYPE = new NoTypeImpl(TypeKind.NULL); - private NoTypeImpl(TypeKind kind) { + public NoTypeImpl(TypeKind kind) { _kind = kind; } @@ -57,6 +57,7 @@ public class NoTypeImpl implements NoType, NullType return _kind; } + @Override public String toString() { switch (_kind) { @@ -69,17 +70,22 @@ public class NoTypeImpl implements NoType, NullType return "void"; //$NON-NLS-1$ case PACKAGE: return "package"; //$NON-NLS-1$ + case MODULE: + return "module"; //$NON-NLS-1$ } } + @Override public List<? extends AnnotationMirror> getAnnotationMirrors() { return Factory.EMPTY_ANNOTATION_MIRRORS; } + @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) { return null; } + @Override @SuppressWarnings("unchecked") public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) { return (A[]) Array.newInstance(annotationType, 0); diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java index 99faca3fba..3d0d58b368 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/PackageElementImpl.java @@ -34,6 +34,7 @@ import org.eclipse.jdt.internal.compiler.batch.FileSystem; import org.eclipse.jdt.internal.compiler.env.INameEnvironment; import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; @@ -73,7 +74,7 @@ public class PackageElementImpl extends ElementImpl implements PackageElement { char[][][] typeNames = null; INameEnvironment nameEnvironment = binding.environment.nameEnvironment; if (nameEnvironment instanceof FileSystem) { - typeNames = ((FileSystem) nameEnvironment).findTypeNames(binding.compoundName, new String[] { null }); + typeNames = ((FileSystem) nameEnvironment).findTypeNames(binding.compoundName); } HashSet<Element> set = new HashSet<>(); Set<ReferenceBinding> types = new HashSet<>(); @@ -87,11 +88,13 @@ public class PackageElementImpl extends ElementImpl implements PackageElement { } } } - ReferenceBinding[] knownTypes = binding.knownTypes.valueTable; - for (ReferenceBinding referenceBinding : knownTypes) { - if (referenceBinding != null && referenceBinding.isValidBinding() && referenceBinding.enclosingType() == null) { - if (!types.contains(referenceBinding)) { - set.add(_env.getFactory().newElement(referenceBinding)); + if (binding.knownTypes != null) { + ReferenceBinding[] knownTypes = binding.knownTypes.valueTable; + for (ReferenceBinding referenceBinding : knownTypes) { + if (referenceBinding != null && referenceBinding.isValidBinding() && referenceBinding.enclosingType() == null) { + if (!types.contains(referenceBinding)) { + set.add(_env.getFactory().newElement(referenceBinding)); + } } } } @@ -102,8 +105,11 @@ public class PackageElementImpl extends ElementImpl implements PackageElement { @Override public Element getEnclosingElement() { - // packages have no enclosing element - return null; + PackageBinding pBinding = (PackageBinding) _binding; + ModuleBinding module = pBinding.enclosingModule; + if (module == null) + return null; + return new ModuleElementImpl(_env, module); } @Override diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/TypeElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/TypeElementImpl.java index 5b9961b49e..cf44e9bcf3 100644 --- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/TypeElementImpl.java +++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/TypeElementImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2015 IBM Corporation and others. + * Copyright (c) 2005, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -41,7 +41,6 @@ import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; -import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; @@ -263,7 +262,7 @@ public class TypeElementImpl extends ElementImpl implements TypeElement { PackageElement getPackage() { ReferenceBinding binding = (ReferenceBinding)_binding; - return _env.getFactory().newPackageElement((PackageBinding)binding.fPackage); + return _env.getFactory().newPackageElement(binding.fPackage); } @Override diff --git a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/AllTests.java b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/AllTests.java index a2eb0102f8..7713e6ef1d 100644 --- a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/AllTests.java +++ b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/AllTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 IBM Corporation and others. + * Copyright (c) 2006, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -22,6 +22,7 @@ public class AllTests extends TestCase { public static Test suite() { TestSuite suite = new TestSuite(); suite.addTestSuite(CompilerToolTests.class); + suite.addTestSuite(CompilerToolJava9Tests.class); suite.addTest(CompilerInvocationTests.suite()); return suite; } diff --git a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java index 64ca57c69e..90b8652835 100644 --- a/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java +++ b/org.eclipse.jdt.compiler.tool.tests/src/org/eclipse/jdt/compiler/tool/tests/CompilerToolJava9Tests.java @@ -59,6 +59,8 @@ public class CompilerToolJava9Tests extends TestCase { @Override protected void setUp() throws Exception { this.isJREBelow9 = SourceVersion.latest().compareTo(SourceVersion.RELEASE_8) <= 0; + if (isJREBelow9) + return; this.compilers = new JavaCompiler[2]; this.compilerNames = new String[2]; ServiceLoader<JavaCompiler> javaCompilerLoader = ServiceLoader.load(JavaCompiler.class); diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java index 74d59e83f9..97b00272f1 100644 --- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java +++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java @@ -419,10 +419,7 @@ public class EclipseCompilerImpl extends Main { location = StandardLocation.CLASS_OUTPUT; } else { // TODO: Still possible to end up with a non-null module name without JDK 9 in build path - System.out.println("module name:" + new String(modName)); //$NON-NLS-1$ - System.out.println("CU:" + new String(unitResult.compilationUnit.getFileName())); //$NON-NLS-1$ location = this.fileManager.getLocationForModule(StandardLocation.CLASS_OUTPUT, new String(modName)); - System.out.println("Location from getLocationForModule(): " + location); //$NON-NLS-1$ } JavaFileObject javaFileForOutput = this.fileManager.getJavaFileForOutput( diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java index be8bbb7683..53ea550d9a 100644 --- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java +++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java @@ -53,7 +53,6 @@ import org.eclipse.jdt.internal.compiler.util.JRTUtil; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.compiler.util.Util; -@SuppressWarnings({ "rawtypes", "unchecked" }) public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants { // Keep the type as ArrayList and not List as there are clients that are already written to expect ArrayList. @@ -143,11 +142,11 @@ public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants * @param classpaths the given classpath entries * @return the normalized classpath entries */ - public static ArrayList normalize(ArrayList classpaths) { - ArrayList normalizedClasspath = new ArrayList(); - HashSet cache = new HashSet(); - for (Iterator iterator = classpaths.iterator(); iterator.hasNext(); ) { - FileSystem.Classpath classpath = (FileSystem.Classpath) iterator.next(); + public static ArrayList<Classpath> normalize(ArrayList<Classpath> classpaths) { + ArrayList<Classpath> normalizedClasspath = new ArrayList<>(); + HashSet<Classpath> cache = new HashSet<>(); + for (Iterator<Classpath> iterator = classpaths.iterator(); iterator.hasNext(); ) { + FileSystem.Classpath classpath = iterator.next(); if (!cache.contains(classpath)) { normalizedClasspath.add(classpath); cache.add(classpath); @@ -161,7 +160,7 @@ public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants // Used only in single-module mode when the module descriptor is // provided via command line. protected IModule module; - Set knownFileNames; + Set<String> knownFileNames; protected boolean annotationsFromClasspath; // should annotation files be read from the classpath (vs. explicit separate path)? private static HashMap<File, Classpath> JRT_CLASSPATH_CACHE = null; @@ -220,15 +219,15 @@ protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annot public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) { return getClasspath(classpathName, encoding, false, accessRuleSet, null, null); } -public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map options) { +public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options) { return getClasspath(classpathName, encoding, false, accessRuleSet, null, options); } -public static Classpath getJrtClasspath(String jdkHome, String encoding, AccessRuleSet accessRuleSet, Map options) { +public static Classpath getJrtClasspath(String jdkHome, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options) { return new ClasspathJrt(new File(convertPathSeparators(jdkHome)), true, accessRuleSet, null); } public static Classpath getClasspath(String classpathName, String encoding, boolean isSourceOnly, AccessRuleSet accessRuleSet, - String destinationPath, Map options) { + String destinationPath, Map<String, String> options) { Classpath result = null; File file = new File(convertPathSeparators(classpathName)); if (file.isDirectory()) { @@ -281,10 +280,10 @@ public static Classpath getClasspath(String classpathName, String encoding, } private void initializeKnownFileNames(String[] initialFileNames) { if (initialFileNames == null) { - this.knownFileNames = new HashSet(0); + this.knownFileNames = new HashSet<>(0); return; } - this.knownFileNames = new HashSet(initialFileNames.length * 2); + this.knownFileNames = new HashSet<>(initialFileNames.length * 2); for (int i = initialFileNames.length; --i >= 0;) { File compilationUnitFile = new File(initialFileNames[i]); char[] fileName = null; @@ -455,48 +454,42 @@ public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) moduleName); return null; } -public char[][][] findTypeNames(char[][] packageName, String[] moduleNames) { +public char[][][] findTypeNames(char[][] packageName) { char[][][] result = null; if (packageName != null) { String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/')); String qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar); if (qualifiedPackageName == qualifiedPackageName2) { for (int i = 0, length = this.classpaths.length; i < length; i++) { - for (String moduleName : moduleNames) { - if (moduleName != null && !this.classpaths[i].servesModule(moduleName.toCharArray())) continue; - char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName, moduleName); - if (answers != null) { - // concat with previous answers - if (result == null) { - result = answers; - } else { - int resultLength = result.length; - int answersLength = answers.length; - System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength); - System.arraycopy(answers, 0, result, resultLength, answersLength); - } + char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName, null); + if (answers != null) { + // concat with previous answers + if (result == null) { + result = answers; + } else { + int resultLength = result.length; + int answersLength = answers.length; + System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength); + System.arraycopy(answers, 0, result, resultLength, answersLength); } } } } else { for (int i = 0, length = this.classpaths.length; i < length; i++) { Classpath p = this.classpaths[i]; - for (String moduleName : moduleNames) { - if (moduleName != null && !p.servesModule(moduleName.toCharArray())) continue; - char[][][] answers = (p instanceof ClasspathJar) - ? p.findTypeNames(qualifiedPackageName, moduleName) - : p.findTypeNames(qualifiedPackageName2, moduleName); - if (answers != null) { - // concat with previous answers - if (result == null) { - result = answers; - } else { - int resultLength = result.length; - int answersLength = answers.length; - System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength); - System.arraycopy(answers, 0, result, resultLength, answersLength); - } - } + char[][][] answers = !(p instanceof ClasspathDirectory) ? p.findTypeNames(qualifiedPackageName, null) + : p.findTypeNames(qualifiedPackageName2, null); + if (answers != null) { + // concat with previous answers + if (result == null) { + result = answers; + } else { + int resultLength = result.length; + int answersLength = answers.length; + System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, + resultLength); + System.arraycopy(answers, 0, result, resultLength, answersLength); + } } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java index b77408d7af..445cc71d5f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java @@ -1,10 +1,14 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * + * This is an implementation of an early-draft specification developed under the Java + * Community Process (JCP) and is made available for testing and evaluation purposes + * only. The code is not compatible with any specification of the JCP. + * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ @@ -584,6 +588,9 @@ public abstract class ASTVisitor { public boolean visit(Clinit clinit, ClassScope scope) { return true; // do nothing by default, keep traversing } + public boolean visit(ModuleDeclaration module, CompilationUnitScope scope) { + return true; + } public boolean visit( CompilationUnitDeclaration compilationUnitDeclaration, CompilationUnitScope scope) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java index 5170e45524..d42e057215 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java @@ -783,6 +783,10 @@ public abstract class ASTNode implements TypeConstants, TypeIds { ModuleBinding module = (ModuleBinding)recipient; if ((module.tagBits & TagBits.AnnotationResolved) != 0) return annotations; module.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); + if (length > 0) { + annotations = new AnnotationBinding[length]; + module.setAnnotations(annotations, scope); + } break; default : return annotations; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index cdc72064b6..0a1dfa4261 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -782,6 +782,9 @@ public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope, boolean this.types[i].traverse(visitor, this.scope); } } + if (this.isModuleInfo() && this.moduleDeclaration != null) { + this.moduleDeclaration.traverse(visitor, this.scope); + } } visitor.endVisit(this, this.scope); } catch (AbortCompilationUnit e) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java index 9d9a667a50..c9987b35a0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java @@ -23,6 +23,7 @@ import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; +import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -60,7 +61,7 @@ public class ModuleDeclaration extends ASTNode { public int bodyStart; public int bodyEnd; // doesn't include the trailing comment if any. public int modifiersSourceStart; - BlockScope scope; + public BlockScope scope; public char[][] tokens; public char[] moduleName; public long[] sourcePositions; @@ -68,6 +69,7 @@ public class ModuleDeclaration extends ASTNode { boolean ignoreFurtherInvestigation; boolean hasResolvedModuleDirectives; boolean hasResolvedPackageDirectives; + boolean hasResolvedTypeDirectives; CompilationResult compilationResult; public ModuleDeclaration(CompilationResult compilationResult, char[][] tokens, long[] positions) { @@ -224,6 +226,10 @@ public class ModuleDeclaration extends ASTNode { this.ignoreFurtherInvestigation = true; return; } + if (this.hasResolvedTypeDirectives) + return; + + this.hasResolvedTypeDirectives = true; ASTNode.resolveAnnotations(this.scope, this.annotations, this.binding); Set<TypeBinding> allTypes = new HashSet<TypeBinding>(); @@ -313,6 +319,10 @@ public class ModuleDeclaration extends ASTNode { } } + public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) { + visitor.visit(this, unitScope); + } + public StringBuffer printHeader(int indent, StringBuffer output) { if (this.annotations != null) { for (int i = 0; i < this.annotations.length; i++) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java index 2d3eef175f..5b6a9bcc23 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java @@ -157,6 +157,8 @@ private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironm if (arraysize > 0) { ReferenceBinding elementType = env.getResolvedType(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, null); int index = 0; + if ((bits & TagBits.AnnotationForTypeUse) != 0) + value[index++] = elementType.getField(TypeConstants.TYPE_USE_TARGET, true); if ((bits & TagBits.AnnotationForAnnotationType) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true); if ((bits & TagBits.AnnotationForConstructor) != 0) @@ -169,8 +171,6 @@ private static AnnotationBinding buildTargetAnnotation(long bits, LookupEnvironm value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true); if ((bits & TagBits.AnnotationForParameter) != 0) value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true); - if ((bits & TagBits.AnnotationForTypeUse) != 0) - value[index++] = elementType.getField(TypeConstants.TYPE_USE_TARGET, true); if ((bits & TagBits.AnnotationForTypeParameter) != 0) value[index++] = elementType.getField(TypeConstants.TYPE_PARAMETER_TARGET, true); if ((bits & TagBits.AnnotationForType) != 0) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java index 23db9de1fb..792c7b90f5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java @@ -1316,9 +1316,11 @@ public class ClassScope extends Scope { } } } - if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0) + if ((superType.tagBits & TagBits.BeginHierarchyCheck) == 0) { // ensure if this is a source superclass that it has already been checked - ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers(); + if (superType.isValidBinding() && !superType.isUnresolvedType()) + ((SourceTypeBinding) superType).scope.connectTypeHierarchyWithoutMembers(); + } if ((superType.tagBits & TagBits.HierarchyHasProblems) != 0) sourceType.tagBits |= TagBits.HierarchyHasProblems; return false; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java index c95e3f15a6..22e32e42c4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java @@ -773,6 +773,11 @@ private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isM packageBinding = parent.addPackage(packageBinding, this.module, true); } } + if (packageBinding instanceof SplitPackageBinding) { + PackageBinding incarnation = ((SplitPackageBinding) packageBinding).getIncarnation(this.module); + if (incarnation != null) + packageBinding = incarnation; + } return packageBinding; } @@ -1621,8 +1626,8 @@ public ReferenceBinding getType(char[][] compoundName, ModuleBinding mod) { referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this, false /* no raw conversion for now */); // compoundName refers to a nested type incorrectly (for example, package1.A$B) - if (referenceBinding.isNestedType()) - return new ProblemReferenceBinding(compoundName, referenceBinding, InternalNameProvided); +// if (referenceBinding.isNestedType()) +// return new ProblemReferenceBinding(compoundName, referenceBinding, InternalNameProvided); return referenceBinding; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java index 9f2dc4b061..39cb8b0b11 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ModuleBinding.java @@ -116,8 +116,13 @@ public class ModuleBinding extends Binding implements IUpdatableModule { private Set<ModuleBinding> transitiveRequires; private boolean isPackageLookupActive = false; // to prevent cyclic lookup caused by synthetic reads edges on behalf of auto-modules. - /** Packages declared in this module (indexed by qualified name). */ - HashtableOfPackage declaredPackages; // TODO(SHMOD): measure if this is worth the memory. LE->PackageBinding basically hold the same information + /** + * Packages declared in this module (indexed by qualified name). + * We consider a package as declared in a module, + * if a compilation unit associated with the module + * declares the package or a subpackage thereof. + */ + public HashtableOfPackage declaredPackages; /** Constructor for the unnamed module. */ private ModuleBinding(LookupEnvironment env) { @@ -469,7 +474,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { * When asked via the unnamed module or an automatic module all other named modules are considered visible. * </p> */ - PackageBinding getTopLevelPackage(char[] name) { + public PackageBinding getTopLevelPackage(char[] name) { // check caches: PackageBinding binding = this.declaredPackages.get(name); if (binding != null) @@ -593,7 +598,7 @@ public class ModuleBinding extends Binding implements IUpdatableModule { * read by the current module. * Accessibility (via package exports) is <strong>not</strong> checked. */ - PackageBinding getPackage(char[][] parentPackageName, char[] packageName) { + public PackageBinding getPackage(char[][] parentPackageName, char[] packageName) { // Returns a package binding if there exists such a package in the context of this module and it is observable // A package is observable if it is declared in this module or it is exported by some required module if (parentPackageName == null || parentPackageName.length == 0) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java index 693c968392..5f79a77f29 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceModuleBinding.java @@ -19,9 +19,16 @@ import java.util.HashMap; import java.util.function.IntFunction; import java.util.stream.Stream; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; +import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable; + public class SourceModuleBinding extends ModuleBinding { final public CompilationUnitScope scope; // TODO(SHMOD): consider cleanup at end of compile + private SimpleLookupTable storedAnnotations = null; /** * Construct a named module from source. @@ -90,4 +97,73 @@ public class SourceModuleBinding extends ModuleBinding { this.scope.referenceContext.moduleDeclaration.resolveModuleDirectives(this.scope); return super.getAllRequiredModules(); } + public long getAnnotationTagBits() { + //TODO: This code is untested as we don't yet get a scope in ModuleBinding + if ((this.tagBits & TagBits.AnnotationResolved) == 0 && this.scope != null) { + ModuleDeclaration module = this.scope.referenceContext.moduleDeclaration; + ASTNode.resolveAnnotations(module.scope, module.annotations, this); + if ((this.tagBits & TagBits.AnnotationDeprecated) != 0) { + this.modifiers |= ClassFileConstants.AccDeprecated; + this.tagBits |= TagBits.DeprecatedAnnotationResolved; + } + this.tagBits |= TagBits.AnnotationResolved; + } + return this.tagBits; + } + public AnnotationBinding[] getAnnotations() { + return retrieveAnnotations(this); + } + public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { + SimpleLookupTable store = storedAnnotations(forceInitialization); + return store == null ? null : (AnnotationHolder) store.get(binding); + } + + AnnotationBinding[] retrieveAnnotations(Binding binding) { + AnnotationHolder holder = retrieveAnnotationHolder(binding, true); + return holder == null ? Binding.NO_ANNOTATIONS : holder.getAnnotations(); + } + + public void setAnnotations(AnnotationBinding[] annotations) { + storeAnnotations(this, annotations); + } + void storeAnnotationHolder(Binding binding, AnnotationHolder holder) { + if (holder == null) { + SimpleLookupTable store = storedAnnotations(false); + if (store != null) + store.removeKey(binding); + } else { + SimpleLookupTable store = storedAnnotations(true); + if (store != null) + store.put(binding, holder); + } + } + + void storeAnnotations(Binding binding, AnnotationBinding[] annotations) { + AnnotationHolder holder = null; + if (annotations == null || annotations.length == 0) { + SimpleLookupTable store = storedAnnotations(false); + if (store != null) + holder = (AnnotationHolder) store.get(binding); + if (holder == null) return; // nothing to delete + } else { + SimpleLookupTable store = storedAnnotations(true); + if (store == null) return; // not supported + holder = (AnnotationHolder) store.get(binding); + if (holder == null) + holder = new AnnotationHolder(); + } + storeAnnotationHolder(binding, holder.setAnnotations(annotations)); + } + + SimpleLookupTable storedAnnotations(boolean forceInitialize) { + if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631) + this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true; + final CompilerOptions globalOptions = this.scope.environment().globalOptions; + if (!globalOptions.storeAnnotations) + return null; // not supported during this compile + this.storedAnnotations = new SimpleLookupTable(3); + } + return this.storedAnnotations; + } + } |