diff options
author | Olivier Thomann | 2011-05-09 17:14:46 +0000 |
---|---|---|
committer | Olivier Thomann | 2011-05-09 17:14:46 +0000 |
commit | 9fe19741818ec1eef72565921ab6dbec02a6d99a (patch) | |
tree | 566b4ae0e56b7432b74ea324b698d3e2cdc72f24 /org.eclipse.jdt.compiler.apt.tests | |
parent | 93e477d77002561632d941e4267b504c8ce9ab5b (diff) | |
download | eclipse.jdt.core-9fe19741818ec1eef72565921ab6dbec02a6d99a.tar.gz eclipse.jdt.core-9fe19741818ec1eef72565921ab6dbec02a6d99a.tar.xz eclipse.jdt.core-9fe19741818ec1eef72565921ab6dbec02a6d99a.zip |
HEAD - Fixed bug 328575: Inheritance of annotation fails with generic classes
Diffstat (limited to 'org.eclipse.jdt.compiler.apt.tests')
10 files changed, 403 insertions, 3 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 e955bb9fd7..ed9bbcfd6e 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/processors/META-INF/services/javax.annotation.processing.Processor b/org.eclipse.jdt.compiler.apt.tests/processors/META-INF/services/javax.annotation.processing.Processor index 4f7f924a49..327a865eaa 100644 --- a/org.eclipse.jdt.compiler.apt.tests/processors/META-INF/services/javax.annotation.processing.Processor +++ b/org.eclipse.jdt.compiler.apt.tests/processors/META-INF/services/javax.annotation.processing.Processor @@ -10,3 +10,4 @@ org.eclipse.jdt.compiler.apt.tests.processors.elementutils.ElementUtilsProc org.eclipse.jdt.compiler.apt.tests.processors.typemirror.TypeMirrorProc org.eclipse.jdt.compiler.apt.tests.processors.typeutils.TypeUtilsProc org.eclipse.jdt.compiler.apt.tests.processors.negative.NegativeModelProc +org.eclipse.jdt.compiler.apt.tests.processors.inherited.ArgsConstructorProcessor
\ No newline at end of file diff --git a/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/annotations/ArgsConstructor.java b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/annotations/ArgsConstructor.java new file mode 100644 index 0000000000..72e1ef3471 --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/annotations/ArgsConstructor.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.compiler.apt.tests.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +@Inherited +@Documented +@Retention(SOURCE) +@Target(TYPE) +public @interface ArgsConstructor { + + Class<?>[] value(); +} 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 new file mode 100644 index 0000000000..e6e8e4692b --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/processors/org/eclipse/jdt/compiler/apt/tests/processors/inherited/ArgsConstructorProcessor.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.compiler.apt.tests.processors.inherited; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +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.util.SimpleTypeVisitor6; +import javax.lang.model.util.Types; +import javax.tools.Diagnostic.Kind; + +import org.eclipse.jdt.compiler.apt.tests.annotations.ArgsConstructor; +import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor; + +@SupportedAnnotationTypes("org.eclipse.jdt.compiler.apt.tests.annotations.ArgsConstructor") +@SupportedSourceVersion(SourceVersion.RELEASE_6) +public class ArgsConstructorProcessor extends BaseProcessor { + private TypeElement _elementAC; + + @Override + public boolean process(Set<? extends TypeElement> annotations, + RoundEnvironment env) { + + for (TypeElement type : annotations) { + processArgsConstructorClasses(env, type); + } + + if (!collectElements()) { + reportError("Failed"); + return false; + } + TypeMirror superclass = _elementAC.getSuperclass(); + if (TypeKind.DECLARED != superclass.getKind()) { + reportError("Wrong type: should be a declared type"); + return false; + } + Element typeElement = _typeUtils.asElement(superclass); + if (typeElement.getAnnotationMirrors().size() != 1) { + reportError("Should contain an annotation"); + return false; + } + reportSuccess(); + return true; + } + + /** + * Collect some elements that will be reused in various tests + * @return true if all tests passed + */ + private boolean collectElements() { + _elementAC = _elementUtils.getTypeElement("targets.inherited.TestGenericChild"); + if (_elementAC == null) { + reportError("TestGenericChild was not found"); + return false; + } + return true; + } + + private void processArgsConstructorClasses(RoundEnvironment env, + TypeElement type) { + for (Element element : env.getElementsAnnotatedWith(type)) { + processClass(element); + processingEnv.getMessager().printMessage(Kind.NOTE, + "Class " + element + " is processed"); + } + } + + private void processClass(Element element) { + + String actionName = ArgsConstructor.class.getName(); + AnnotationValue action = null; + for (AnnotationMirror am : processingEnv.getElementUtils() + .getAllAnnotationMirrors(element)) { + if (actionName.equals(am.getAnnotationType().toString())) { + for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : am + .getElementValues().entrySet()) { + if ("value".equals(entry.getKey().getSimpleName() + .toString())) { + action = entry.getValue(); + break; + } + + } + + } + } + + if (action == null) { + processingEnv.getMessager() + .printMessage( + Kind.WARNING, + "Class " + element + + " lacks a annotation with required args", + element); + return; + } + + List<TypeMirror> mirrors = new ArrayList<TypeMirror>(); + for (Object val : (List<?>) action.getValue()) { + AnnotationValue v = (AnnotationValue) val; + TypeMirror m = (TypeMirror) v.getValue(); + mirrors.add(m); + } + + if (!doesClassContainArgsConstructor(element, mirrors)) { + String s = ""; + for (TypeMirror tm : mirrors) { + if (!s.isEmpty()) { + s += ","; + } + s += tm.toString(); + + } + processingEnv.getMessager().printMessage( + Kind.ERROR, + "Class " + element + + " lacks a public constructor with args: " + s, + element); + } else { + processingEnv.getMessager().printMessage(Kind.NOTE, + "Processed type: " + element); + } + } + + private boolean doesClassContainArgsConstructor(Element el, + List<TypeMirror> annotTypes) { + for (Element subelement : el.getEnclosedElements()) { + if (subelement.getKind() == ElementKind.CONSTRUCTOR + && subelement.getModifiers().contains(Modifier.PUBLIC)) { + TypeMirror mirror = subelement.asType(); + if (mirror.accept(argsVisitor, annotTypes)) + return true; + } + } + return false; + } + + private final TypeVisitor<Boolean, List<TypeMirror>> argsVisitor = new SimpleTypeVisitor6<Boolean, List<TypeMirror>>() { + public Boolean visitExecutable(ExecutableType t, + List<TypeMirror> annotatedTypes) { + + List<? extends TypeMirror> types = t.getParameterTypes(); + if (annotatedTypes.size() != types.size()) { + return false; + } + Types tutil = processingEnv.getTypeUtils(); + + for (int i = 0; i < types.size(); i++) { + TypeMirror test = tutil.erasure(types.get(i));// because same + // type bad + // Map<String,String> + // != Map + TypeMirror expected = tutil.erasure(annotatedTypes.get(i)); + + if (!tutil.isAssignable(expected, test)) { + return false; + } + } + return true; + } + }; + +} diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestGeneric.java b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestGeneric.java new file mode 100644 index 0000000000..42b627c039 --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestGeneric.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package targets.inherited; + +import java.awt.Point; + +import org.eclipse.jdt.compiler.apt.tests.annotations.ArgsConstructor; + +@ArgsConstructor({ Point.class }) +public class TestGeneric<K extends Point> { + + public TestGeneric(K k) { + } +} diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestGenericChild.java b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestGenericChild.java new file mode 100644 index 0000000000..90bb299d18 --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestGenericChild.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package targets.inherited; + +public class TestGenericChild extends TestGeneric<TestPoint> { + + public TestGenericChild(int i, TestPoint k) { + super(k); + } + +} diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestNormal.java b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestNormal.java new file mode 100644 index 0000000000..9dbb3f3cc2 --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestNormal.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package targets.inherited; + +import java.awt.Point; + +import org.eclipse.jdt.compiler.apt.tests.annotations.ArgsConstructor; + +@ArgsConstructor({ Point.class }) +public class TestNormal { + + public TestNormal(Point p) { + } +} diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestNormalChild.java b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestNormalChild.java new file mode 100644 index 0000000000..1e3669c074 --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestNormalChild.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package targets.inherited; + +import java.awt.Point; + +public class TestNormalChild extends TestNormal { + + public TestNormalChild(Point p, int i) { + super(p); + } +} diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestPoint.java b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestPoint.java new file mode 100644 index 0000000000..af2753195e --- /dev/null +++ b/org.eclipse.jdt.compiler.apt.tests/resources/targets/inherited/TestPoint.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2011 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 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package targets.inherited; + +import java.awt.Point; + +public class TestPoint extends Point { + +} diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java index 446f12bc85..f01fc54375 100644 --- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java +++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/NegativeTests.java @@ -12,8 +12,10 @@ package org.eclipse.jdt.compiler.apt.tests; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -21,7 +23,10 @@ import java.util.List; import java.util.Set; import javax.lang.model.SourceVersion; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; import javax.tools.ToolProvider; import junit.framework.TestCase; @@ -29,10 +34,34 @@ import junit.framework.TestCase; /** * Test cases for annotation processing behavior when code contains semantic errors */ -public class NegativeTests extends TestCase -{ +public class NegativeTests extends TestCase { + static class TestDiagnosticListener implements DiagnosticListener<JavaFileObject> { + public static final int NONE = 0; + public static final int ERROR = 1; + public static final int INFO = 2; + public static final int WARNING = 4; + + public int errorCounter; + private PrintWriter writer; + + public TestDiagnosticListener(PrintWriter writer) { + this.writer = writer; + } + + @Override + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + switch(diagnostic.getKind()) { + case ERROR : + this.writer.print(diagnostic.getMessage(null)); + this.errorCounter++; + break; + } + } + } + // See corresponding usages in the NegativeModelProc class private static final String NEGATIVEMODELPROCNAME = "org.eclipse.jdt.compiler.apt.tests.processors.negative.NegativeModelProc"; + private static final String INHERITED_PROCNAME ="org.eclipse.jdt.compiler.apt.tests.processors.inherited.ArgsConstructorProcessor"; private static final String IGNOREJAVACBUGS = "ignoreJavacBugs"; @Override @@ -149,6 +178,67 @@ public class NegativeTests extends TestCase JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); internalTestNegativeModel(compiler, 9, null); } + + /* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=328575 + */ + public void testNegativeModel10WithEclipseCompiler() throws IOException { + JavaCompiler compiler = BatchTestUtils.getEclipseCompiler(); + System.clearProperty(NEGATIVEMODELPROCNAME); + System.clearProperty(INHERITED_PROCNAME); + File targetFolder = TestUtils.concatPath(BatchTestUtils.getSrcFolderName(), "targets", "inherited"); + BatchTestUtils.copyResources("targets/inherited", targetFolder); + + // Invoke processing by compiling the targets.model resources + ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); + PrintWriter printWriter = new PrintWriter(errBuffer); + TestDiagnosticListener diagnosticListener = new TestDiagnosticListener(printWriter); + boolean success = BatchTestUtils.compileTreeWithErrors(compiler, new ArrayList<String>(), targetFolder, diagnosticListener); + + assertTrue("Compilation should have failed due to expected errors, but it didn't", !success); + assertEquals("Two errors should be reported", 2, diagnosticListener.errorCounter); + printWriter.flush(); + printWriter.close(); + String expectedErrors = + "Class targets.inherited.TestGenericChild lacks a public constructor with args: java.awt.Point" + + "Class targets.inherited.TestNormalChild lacks a public constructor with args: java.awt.Point"; + + assertEquals("Wrong output", expectedErrors, String.valueOf(errBuffer)); + String property = System.getProperty(INHERITED_PROCNAME); + assertNotNull("No property - probably processing did not take place", property); + assertEquals("succeeded", property); + } + + /* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=328575 + */ + public void testNegativeModel10WithSystemCompiler() throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + System.out.println("No system java compiler available"); + return; + } + System.clearProperty(NEGATIVEMODELPROCNAME); + System.clearProperty(INHERITED_PROCNAME); + File targetFolder = TestUtils.concatPath(BatchTestUtils.getSrcFolderName(), "targets", "inherited"); + BatchTestUtils.copyResources("targets/inherited", targetFolder); + + // Invoke processing by compiling the targets.model resources + ByteArrayOutputStream errBuffer = new ByteArrayOutputStream(); + PrintWriter printWriter = new PrintWriter(errBuffer); + TestDiagnosticListener diagnosticListener = new TestDiagnosticListener(printWriter); + boolean success = BatchTestUtils.compileTreeWithErrors(compiler, new ArrayList<String>(), targetFolder, diagnosticListener); + + assertTrue("Compilation should have failed due to expected errors, but it didn't", !success); + assertEquals("Two errors should be reported", 2, diagnosticListener.errorCounter); + printWriter.flush(); + printWriter.close(); + + String property = System.getProperty(INHERITED_PROCNAME); + assertNotNull("No property - probably processing did not take place", property); + assertEquals("succeeded", property); + } + /** * Attempt to report errors on various elements. * @throws IOException @@ -168,7 +258,6 @@ public class NegativeTests extends TestCase boolean success = BatchTestUtils.compileTreeWithErrors(compiler, options, targetFolder, null); assertTrue("Compilation should have failed due to expected errors, but it didn't", !success); - // If it succeeded, the processor will have set this property to "succeeded"; // if not, it will set it to an error value. String property = System.getProperty(NEGATIVEMODELPROCNAME); |