### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.apt.pluggable.tests Index: META-INF/services/javax.annotation.processing.Processor =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.apt.pluggable.tests/META-INF/services/javax.annotation.processing.Processor,v retrieving revision 1.5 diff -u -r1.5 javax.annotation.processing.Processor --- META-INF/services/javax.annotation.processing.Processor 28 Apr 2009 01:21:25 -0000 1.5 +++ META-INF/services/javax.annotation.processing.Processor 15 Nov 2010 19:46:41 -0000 @@ -2,4 +2,5 @@ org.eclipse.jdt.apt.pluggable.tests.processors.message6.Message6Proc org.eclipse.jdt.apt.pluggable.tests.processors.filertester.FilerTesterProc org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.InheritedAnnoProc +org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.TestFinalRoundProc org.eclipse.jdt.apt.pluggable.tests.processors.modeltester.ModelTesterProc Index: plugin.xml =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.apt.pluggable.tests/plugin.xml,v retrieving revision 1.8 diff -u -r1.8 plugin.xml --- plugin.xml 13 May 2010 12:43:50 -0000 1.8 +++ plugin.xml 15 Nov 2010 19:46:41 -0000 @@ -29,6 +29,9 @@ class="org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.InheritedAnnoProc"> + + Index: src/org/eclipse/jdt/apt/pluggable/tests/BuilderTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.apt.pluggable.tests/src/org/eclipse/jdt/apt/pluggable/tests/BuilderTests.java,v retrieving revision 1.2 diff -u -r1.2 BuilderTests.java --- src/org/eclipse/jdt/apt/pluggable/tests/BuilderTests.java 2 Dec 2009 18:34:40 -0000 1.2 +++ src/org/eclipse/jdt/apt/pluggable/tests/BuilderTests.java 15 Nov 2010 19:46:41 -0000 @@ -20,6 +20,7 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.apt.core.util.AptConfig; import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.InheritedAnnoProc; +import org.eclipse.jdt.apt.pluggable.tests.processors.buildertester.TestFinalRoundProc; import org.eclipse.jdt.core.IJavaProject; /** @@ -36,9 +37,45 @@ return new TestSuite(BuilderTests.class); } - // Need this to avoid JUnit complaining that there are no tests in this suite - public void testDummy() { - assertTrue(true); + /** + * Verify that a new type generated in the final round does not get + * annotations processed, but does get compiled. The JSR269 spec is somewhat + * vague about whether it should be possible to generate a new type during + * the final round (since the final round does not happen until after a + * round in which no new types are generated); but apparently javac behaves + * this way. + *

+ * See Bug 329156 and the corresponding + * bug in javac, which Sun fixed. + */ + public void testFinalRound() throws Throwable { + ProcessorTestStatus.reset(); + TestFinalRoundProc.resetNumRounds(); + IJavaProject jproj = createJavaProject(_projectName); + disableJava5Factories(jproj); + IProject proj = jproj.getProject(); + IPath projPath = proj.getFullPath(); + IPath root = projPath.append("src"); + + // The @FinalRoundTestTrigger processor does not generate any files when it + // first runs; but on its final round it then generates a new Java type + // that is annotated with @FinalRoundTestTrigger. + env.addClass(root, "t", "Foo", + "package t;\n" + + "import org.eclipse.jdt.apt.pluggable.tests.annotations.FinalRoundTestTrigger;\n" + + "@FinalRoundTestTrigger\n" + + "public class Foo {}" + ); + AptConfig.setEnabled(jproj, true); + + fullBuild(); + expectingNoProblems(); + + // Processor should have run total of two rounds; compiled classes + // should include Foo and FinalRoundGen. + assertEquals(2, TestFinalRoundProc.getNumRounds()); + expectingUniqueCompiledClasses(new String[] {"t.Foo", "g.FinalRoundGen"}); } /** Index: src/org/eclipse/jdt/apt/pluggable/tests/annotations/FinalRoundTestTrigger.java =================================================================== RCS file: src/org/eclipse/jdt/apt/pluggable/tests/annotations/FinalRoundTestTrigger.java diff -N src/org/eclipse/jdt/apt/pluggable/tests/annotations/FinalRoundTestTrigger.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jdt/apt/pluggable/tests/annotations/FinalRoundTestTrigger.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2010 Walter Harley 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: + * eclipse@cafewalter.com - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.apt.pluggable.tests.annotations; + +/** + * Marker interface to trigger the TestFinalRoundProc, which does nothing + * normally but on the final round of processing generates a new Java type + * that is annotated with this annotation. + *

+ * See Bug 329156 and + * the + * corresponding bug in javac, which Sun fixed. + * @since 3.7 + */ +public @interface FinalRoundTestTrigger { +} Index: src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/InheritedAnnoProc.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.apt.pluggable.tests/src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/InheritedAnnoProc.java,v retrieving revision 1.1 diff -u -r1.1 InheritedAnnoProc.java --- src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/InheritedAnnoProc.java 28 Apr 2009 01:21:24 -0000 1.1 +++ src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/InheritedAnnoProc.java 15 Nov 2010 19:46:42 -0000 @@ -43,7 +43,7 @@ @SupportedOptions( {}) public class InheritedAnnoProc extends AbstractProcessor { - private static List processedElements = new ArrayList(); + private static final List processedElements = new ArrayList(); public static List getProcessedElements() { return Collections.unmodifiableList(processedElements); Index: src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/TestFinalRoundProc.java =================================================================== RCS file: src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/TestFinalRoundProc.java diff -N src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/TestFinalRoundProc.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jdt/apt/pluggable/tests/processors/buildertester/TestFinalRoundProc.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2010 Walter Harley 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: + * eclipse@cafewalter.com - initial API and implementation + *******************************************************************************/ + +package org.eclipse.jdt.apt.pluggable.tests.processors.buildertester; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedOptions; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.JavaFileObject; + +import org.eclipse.jdt.apt.pluggable.tests.annotations.FinalRoundTestTrigger; + +/** + * Do nothing when first triggered; then, in the final round, generate a + * new type that is annotated with {@link FinalRoundTestTrigger}. + * Used to verify that a new type generated in the final round does not get + * annotations processed, but does get compiled. The JSR269 spec is somewhat + * vague about whether it should be possible to generate a new type during + * the final round (since the final round does not happen until after a + * round in which no new types are generated); but apparently javac behaves + * this way. + *

+ * See Bug 329156 and the corresponding + * bug in javac, which Sun fixed. + */ +@SupportedAnnotationTypes( { "org.eclipse.jdt.apt.pluggable.tests.annotations.FinalRoundTestTrigger" }) +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedOptions( {}) +public class TestFinalRoundProc extends AbstractProcessor { + private static int _numRounds; + + public static int getNumRounds() { + return _numRounds; + } + + public static void resetNumRounds() { + _numRounds = 0; + } + + @Override + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + createFile(); + } + _numRounds++; + return true; + } + + private void createFile() { + PrintWriter pw = null; + try { + JavaFileObject jfo = processingEnv.getFiler().createSourceFile("g.FinalRoundGen"); + pw = new PrintWriter(jfo.openWriter()); + pw.println("package g;"); + pw.println("import org.eclipse.jdt.apt.pluggable.tests.annotations.FinalRoundTestTrigger;"); + pw.println("@FinalRoundTestTrigger"); + pw.println("public class FinalRoundGen {}"); + } catch (IOException e) { + e.printStackTrace(); + processingEnv.getMessager().printMessage(Kind.ERROR, "Unable to create source file! Exception message was: " + e.getMessage()); + } finally { + if (pw != null) { + pw.close(); + } + } + } + +} #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/Compiler.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java,v retrieving revision 1.116 diff -u -r1.116 Compiler.java --- compiler/org/eclipse/jdt/internal/compiler/Compiler.java 24 Nov 2009 18:22:38 -0000 1.116 +++ compiler/org/eclipse/jdt/internal/compiler/Compiler.java 15 Nov 2010 19:46:42 -0000 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 2010 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 @@ -831,10 +831,26 @@ this.annotationProcessorManager.reset(); } } while (newUnitSize != 0 || newClassFilesSize != 0); - // one more loop to create possible resources - // this loop cannot create any java source files + this.annotationProcessorManager.processAnnotations(null, null, true); - // TODO we might want to check if this loop created new units + // process potential units added in the final round see 329156 + ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits(); + newUnitSize = newUnits.length; + if (newUnitSize != 0) { + ICompilationUnit[] newProcessedUnits = (ICompilationUnit[]) newUnits.clone(); // remember new units in case a source type collision occurs + try { + this.lookupEnvironment.isProcessingAnnotations = true; + internalBeginToCompile(newUnits, newUnitSize); + } catch (SourceTypeCollisionException e) { + e.newAnnotationProcessorUnits = newProcessedUnits; + throw e; + } finally { + this.lookupEnvironment.isProcessingAnnotations = false; + this.annotationProcessorManager.reset(); + } + } else { + this.annotationProcessorManager.reset(); + } } public void reset() {