From d6ccb85505c0d7a0bd6544d67f6d43e40775a76b Mon Sep 17 00:00:00 2001 From: Yohann Roussel Date: Thu, 18 Dec 2014 12:17:52 +0100 Subject: Jack support for annotation processor. Does not include any support for including class files generated by annotation processors. Change-Id: Id4006301d588875f822ff84fa90db10fd616ab00 --- .../processor/AnnotationProcessorTests.java | 292 +++++++++++++++++++++ .../processor/sample/annotated/Annotated1.java | 24 ++ .../processor/sample/annotated/Annotated2.java | 24 ++ .../processor/sample/annotated/Annotated3.java | 21 ++ .../sample/annotations/ResourceAnnotationTest.java | 29 ++ .../sample/annotations/SourceAnnotationTest.java | 29 ++ .../processors/ResourceAnnotationProcessor.java | 142 ++++++++++ .../processors/SourceAnnotationProcessor.java | 110 ++++++++ .../javax.annotation.processing.Processor | 2 + .../com/android/jack/classpath/ClasspathTests.java | 1 + .../jack/error/AnnotationProcessorErrorTest.java | 70 ++--- .../android/jack/error/FileAccessErrorTest.java | 1 + .../jack/fileconflict/FileConflictTests.java | 84 ++---- 13 files changed, 726 insertions(+), 103 deletions(-) create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/AnnotationProcessorTests.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated1.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated2.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated3.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/ResourceAnnotationTest.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/SourceAnnotationTest.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/processors/ResourceAnnotationProcessor.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/processors/SourceAnnotationProcessor.java create mode 100644 jack-tests/tests/com/android/jack/annotation/processor/sample/processors/javax.annotation.processing.Processor (limited to 'jack-tests/tests/com/android') diff --git a/jack-tests/tests/com/android/jack/annotation/processor/AnnotationProcessorTests.java b/jack-tests/tests/com/android/jack/annotation/processor/AnnotationProcessorTests.java new file mode 100644 index 00000000..2d4be981 --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/AnnotationProcessorTests.java @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor; + +import com.android.jack.annotation.processor.sample.processors.ResourceAnnotationProcessor; +import com.android.jack.annotation.processor.sample.processors.SourceAnnotationProcessor; +import com.android.jack.library.FileType; +import com.android.jack.library.FileTypeDoesNotExistException; +import com.android.jack.library.InputJackLibrary; +import com.android.jack.library.JackLibraryFactory; +import com.android.jack.test.toolchain.AbstractTestTools; +import com.android.jack.test.toolchain.JackBasedToolchain; +import com.android.jack.test.toolchain.LegacyToolchain; +import com.android.jack.test.toolchain.Toolchain; +import com.android.sched.util.config.ConfigurationException; +import com.android.sched.util.config.GatherConfigBuilder; +import com.android.sched.util.config.ThreadConfig; +import com.android.sched.util.file.Directory; +import com.android.sched.util.file.FileOrDirectory.ChangePermission; +import com.android.sched.util.file.FileOrDirectory.Existence; +import com.android.sched.util.file.FileOrDirectory.Permission; +import com.android.sched.vfs.DirectFS; +import com.android.sched.vfs.VPath; + +import junit.framework.Assert; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.util.Collections; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; + +public class AnnotationProcessorTests { + + @Nonnull + private static final File ANNOTATED_DIR = AbstractTestTools.getTestRootDir( + "com.android.jack.annotation.processor.sample.annotated"); + @Nonnull + private static final File ANNOTATIONS_DIR = AbstractTestTools.getTestRootDir( + "com.android.jack.annotation.processor.sample.annotations"); + + @CheckForNull + private static File noConfigProcessors; + + @CheckForNull + private static File autoProcessors; + + @BeforeClass + public static void setupClass() throws ConfigurationException { + // required for creating InputJackLibrary when running tests on cli + ThreadConfig.setConfig(new GatherConfigBuilder().build()); + noConfigProcessors = null; + autoProcessors = null; + } + + @Nonnull + private static File getNoConfigProcessors() throws Exception { + if (noConfigProcessors == null) { + Toolchain toolchain = AbstractTestTools.getReferenceToolchain(); + File processorsDir = AbstractTestTools.createTempDir(); + File processorsSrcDir = AbstractTestTools.getTestRootDir( + "com.android.jack.annotation.processor.sample.processors"); + toolchain.srcToLib(processorsDir, /*zipFiles=*/ false, + ANNOTATIONS_DIR, + processorsSrcDir + ); + noConfigProcessors = processorsDir; + } + return noConfigProcessors; + } + + @Nonnull + private static File getAutoProcessors() throws Exception { + if (autoProcessors == null) { + Toolchain toolchain = AbstractTestTools.getReferenceToolchain(); + File processorsDir = AbstractTestTools.createTempDir(); + File processorsSrcDir = AbstractTestTools.getTestRootDir( + "com.android.jack.annotation.processor.sample.processors"); + toolchain.srcToLib(processorsDir, /*zipFiles=*/ false, + ANNOTATIONS_DIR, + processorsSrcDir + ); + AbstractTestTools.copyFileToDir(new File(processorsSrcDir, + "javax.annotation.processing.Processor"), + "META-INF/services/javax.annotation.processing.Processor", processorsDir); + autoProcessors = processorsDir; + } + return autoProcessors; + } + + @Test + public void compileWithAnnotationProcessorAuto_classpath() throws Exception { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getAutoProcessors(); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.addToClasspath(processors); + jack.srcToLib(jackOut, /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile0", '/')); + libOut.getFile(FileType.JAYCE, new VPath("Annotated2Duplicated", '/')); + } + + @Test + public void compileWithAnnotationProcessorAuto_processorPath() throws Exception { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getAutoProcessors(); + jack.setAnnotationProcessorPath(processors.getPath()); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.srcToLib(jackOut, + /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile0", '/')); + libOut.getFile(FileType.JAYCE, new VPath("Annotated2Duplicated", '/')); + } + + @Test + public void compileWithAnnotationProcessorNoAuto_processorPath() throws Exception { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getNoConfigProcessors(); + jack.setAnnotationProcessorPath(processors.getPath()); + jack.setAnnotationProcessorClasses( + Collections.singletonList(ResourceAnnotationProcessor.class.getName())); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.srcToLib(jackOut, + /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile0", '/')); + try { + libOut.getFile(FileType.JAYCE, new VPath("Annotated2Duplicated", '/')); + Assert.fail(); + } catch (FileTypeDoesNotExistException e) { + // expected + } + } + + @Test + public void compileWithAnnotationProcessorNoAutoNoClasses_processorPath() throws Exception { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getNoConfigProcessors(); + jack.setAnnotationProcessorPath(processors.getPath()); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.srcToLib(jackOut, + /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + try { + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile0", '/')); + Assert.fail(); + } catch (FileTypeDoesNotExistException e) { + // expected + } + try { + libOut.getFile(FileType.JAYCE, new VPath("Annotated2Duplicated", '/')); + Assert.fail(); + } catch (FileTypeDoesNotExistException e) { + // expected + } + } + + @Test + public void compileWithAnnotationProcessorNoAuto_classpath() throws Exception { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getNoConfigProcessors(); + jack.setAnnotationProcessorClasses( + Collections.singletonList(SourceAnnotationProcessor.class.getName())); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.addToClasspath(processors); + jack.srcToLib(jackOut, /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + try { + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile0", '/')); + Assert.fail(); + } catch (FileTypeDoesNotExistException e) { + // expected + } + libOut.getFile(FileType.JAYCE, new VPath("Annotated2Duplicated", '/')); + } + + @Test + public void compileWithAnnotationProcessorReuseClassOut() throws Exception { + File classesOut = AbstractTestTools.createTempDir(); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getAutoProcessors(); + { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + jack.setAnnotationProcessorPath(processors.getPath()); + jack.addResource(classesOut); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.srcToLib(jackOut, + /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + } + { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + jack.setAnnotationProcessorPath(processors.getPath()); + jack.addResource(classesOut); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.srcToLib(jackOut, + /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + } + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile0", '/')); + libOut.getFile(FileType.RSC, new VPath("rscGeneratedFile1", '/')); + libOut.getFile(FileType.JAYCE, new VPath("Annotated2Duplicated", '/')); + } + + @Test + public void compileWithAnnotationProcessorOption() throws Exception { + JackBasedToolchain jack = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + File jackOut = AbstractTestTools.createTempDir(); + File processors = getAutoProcessors(); + jack.addAnnotationProcessorOption( + SourceAnnotationProcessor.SOURCE_ANNOTATION_PROCESSOR_SUFFIX, "WithOption"); + jack.addToClasspath(jack.getDefaultBootClasspath()); + jack.addToClasspath(processors); + jack.srcToLib(jackOut, /*zipFiles=*/false, + ANNOTATIONS_DIR, + ANNOTATED_DIR + ); + InputJackLibrary libOut = + JackLibraryFactory.getInputLibrary( + new DirectFS(new Directory(jackOut.getPath(), /* hooks = */ null, + Existence.MUST_EXIST, Permission.READ, ChangePermission.NOCHANGE), + Permission.READ)); + libOut.getFile(FileType.JAYCE, new VPath("Annotated2WithOption", '/')); + } +} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated1.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated1.java new file mode 100644 index 00000000..1e5fed68 --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated1.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.annotated; + +import com.android.jack.annotation.processor.sample.annotations.ResourceAnnotationTest; + +@ResourceAnnotationTest +public class Annotated1 { + +} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated2.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated2.java new file mode 100644 index 00000000..c5c00aa8 --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated2.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.annotated; + +import com.android.jack.annotation.processor.sample.annotations.SourceAnnotationTest; + +@SourceAnnotationTest +public class Annotated2 { + +} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated3.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated3.java new file mode 100644 index 00000000..bd47b551 --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotated/Annotated3.java @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.annotated; + +public class Annotated3 { + +} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/ResourceAnnotationTest.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/ResourceAnnotationTest.java new file mode 100644 index 00000000..48b88ef6 --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/ResourceAnnotationTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a class or interface with an annotation used by tests. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ResourceAnnotationTest {} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/SourceAnnotationTest.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/SourceAnnotationTest.java new file mode 100644 index 00000000..54b69579 --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/annotations/SourceAnnotationTest.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a class or interface with an annotation used by tests to generate source code. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SourceAnnotationTest {} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/ResourceAnnotationProcessor.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/ResourceAnnotationProcessor.java new file mode 100644 index 00000000..d6c61d7b --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/ResourceAnnotationProcessor.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.processors; + +import com.android.jack.annotation.processor.sample.annotations.ResourceAnnotationTest; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.processing.AbstractProcessor; +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.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; +import javax.tools.FileObject; +import javax.tools.StandardLocation; + +/** + * Annotation processor generating a dedicated resource file called {@code rscGeneratedFile}. + */ +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedAnnotationTypes("*") +public class ResourceAnnotationProcessor extends AbstractProcessor { + @CheckForNull + private ProcessingEnvironment env; + + @Nonnull + private final List data = new ArrayList(); + + @Nonnull + public final static String FILENAME = "rscGeneratedFile"; + + @Override + public synchronized void init(@Nonnull ProcessingEnvironment env) { + this.env = env; + try { + env.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", FILENAME); + } catch (IOException e) { + // Best effort + } + } + + @Override + public boolean process(@Nonnull Set annotations, + @Nonnull RoundEnvironment roundEnv) { + assert env != null; + env.getMessager().printMessage(Kind.NOTE, + "ResourceAnnotationProcessor.process"); + if (roundEnv.processingOver()) { + try { + assert env != null; + + int count = 0; + while (true) { + try { + FileObject fo = env.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", FILENAME + count); + fo.openInputStream().close(); + count ++; + } catch (IOException e) { + break; + } + } + OutputStream os = env.getFiler() + .createResource(StandardLocation.CLASS_OUTPUT, "", FILENAME + count) + .openOutputStream(); + Writer writer = new OutputStreamWriter(os); + try { + for (String val : data) { + writer.write(val); + writer.write("\n"); + } + } finally { + writer.close(); + } + } catch (IOException e) { + env.getMessager().printMessage(Kind.ERROR, + "Can not write resource file for '" + FILENAME + "': " + e.getMessage()); + } + } else { + // + // @ResourceAnnotationTest + // + + for (Element element : getElementsAnnotatedWith(roundEnv, ResourceAnnotationTest.class)) { + assert data != null; + + TypeMirror type = element.asType(); + + if (type.getKind() == TypeKind.DECLARED) { + data.add(ResourceAnnotationTest.class.getCanonicalName()); + assert env != null; + data.add(env.getElementUtils().getBinaryName((TypeElement) element).toString()); + + } + } + } + + return false; + } + + @Nonnull + private Set getElementsAnnotatedWith(@Nonnull RoundEnvironment roundEnv, + @Nonnull Class cls) { + assert env != null; + + String name = cls.getCanonicalName(); + assert name != null; + + TypeElement element = env.getElementUtils().getTypeElement(name); + assert element != null; + + return roundEnv.getElementsAnnotatedWith(element); + } +} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/SourceAnnotationProcessor.java b/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/SourceAnnotationProcessor.java new file mode 100644 index 00000000..7ef7a7ac --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/SourceAnnotationProcessor.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.annotation.processor.sample.processors; + +import com.android.jack.annotation.processor.sample.annotations.SourceAnnotationTest; + +import java.io.IOException; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.util.Set; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.processing.AbstractProcessor; +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.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; +import javax.tools.JavaFileObject; + +/** + * Annotation processor to generate a new source file. + */ +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedAnnotationTypes("*") +public class SourceAnnotationProcessor extends AbstractProcessor { + @Nonnull + public static final String SOURCE_ANNOTATION_PROCESSOR_SUFFIX = + "SourceAnnotationProcessor.suffix"; + @CheckForNull + private ProcessingEnvironment env; + @Nonnull + private String suffix; + + @Override + public synchronized void init(@Nonnull ProcessingEnvironment env) { + this.env = env; + suffix = env.getOptions().get(SOURCE_ANNOTATION_PROCESSOR_SUFFIX); + if (suffix == null) { + suffix = "Duplicated"; + } + } + + @Override + public boolean process(@Nonnull Set annotations, @Nonnull RoundEnvironment roundEnv) { + assert env != null; + env.getMessager().printMessage(Kind.NOTE, + "SourceAnnotationProcessor.process"); + if (!roundEnv.processingOver()) { + + // + // @SourceAnnotationTest + // + + for (Element element : getElementsAnnotatedWith(roundEnv, SourceAnnotationTest.class)) { + TypeMirror type = element.asType(); + + if (type.getKind() == TypeKind.DECLARED) { + TypeElement classElement = (TypeElement) element; + try { + assert env != null; + JavaFileObject jfo = + env.getFiler().createSourceFile(classElement.getQualifiedName() + suffix); + Writer writer = jfo.openWriter(); + writer.write("public class " + classElement.getSimpleName() + suffix + " {}"); + writer.close(); + } catch (IOException e) { + throw new AssertionError(e); + } + } + } + } + + return false; + } + + @Nonnull + private Set getElementsAnnotatedWith(@Nonnull RoundEnvironment roundEnv, + @Nonnull Class cls) { + assert env != null; + + String name = cls.getCanonicalName(); + assert name != null; + + TypeElement element = env.getElementUtils().getTypeElement(name); + assert element != null; + + return roundEnv.getElementsAnnotatedWith(element); + } +} diff --git a/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/javax.annotation.processing.Processor b/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/javax.annotation.processing.Processor new file mode 100644 index 00000000..975dacba --- /dev/null +++ b/jack-tests/tests/com/android/jack/annotation/processor/sample/processors/javax.annotation.processing.Processor @@ -0,0 +1,2 @@ +com.android.jack.annotation.processor.sample.processors.SourceAnnotationProcessor +com.android.jack.annotation.processor.sample.processors.ResourceAnnotationProcessor diff --git a/jack-tests/tests/com/android/jack/classpath/ClasspathTests.java b/jack-tests/tests/com/android/jack/classpath/ClasspathTests.java index 3aaa72d0..9fb98b63 100644 --- a/jack-tests/tests/com/android/jack/classpath/ClasspathTests.java +++ b/jack-tests/tests/com/android/jack/classpath/ClasspathTests.java @@ -52,6 +52,7 @@ public class ClasspathTests { .srcToLib(libOut, false, new File(AbstractTestTools.getTestRootDir("com.android.jack.classpath.test001"), "lib")); + toolchain = AbstractTestTools.getCandidateToolchain(); File testOut = AbstractTestTools.createTempDir(); toolchain.addToClasspath(toolchain.getDefaultBootClasspath()) .addToClasspath(libOut) diff --git a/jack-tests/tests/com/android/jack/error/AnnotationProcessorErrorTest.java b/jack-tests/tests/com/android/jack/error/AnnotationProcessorErrorTest.java index a5e310c3..99b58f20 100644 --- a/jack-tests/tests/com/android/jack/error/AnnotationProcessorErrorTest.java +++ b/jack-tests/tests/com/android/jack/error/AnnotationProcessorErrorTest.java @@ -18,14 +18,17 @@ package com.android.jack.error; import com.google.common.io.Files; -import com.android.jack.JackUserException; +import com.android.jack.JackAbortException; import com.android.jack.Main; +import com.android.jack.backend.jayce.JayceFileImporter.CollisionPolicy; import com.android.jack.errorhandling.annotationprocessor.ResourceAnnotationProcessor; import com.android.jack.errorhandling.annotationprocessor.ResourceAnnotationTest; import com.android.jack.errorhandling.annotationprocessor.SourceAnnotationProcessor; import com.android.jack.errorhandling.annotationprocessor.SourceAnnotationTest; import com.android.jack.errorhandling.annotationprocessor.SourceErrorAnnotationTest; import com.android.jack.frontend.FrontendCompilationException; +import com.android.jack.resource.ResourceImporter; +import com.android.jack.resource.ResourceReadingException; import com.android.jack.test.TestsProperties; import com.android.jack.test.helper.ErrorTestHelper; import com.android.jack.test.toolchain.AbstractTestTools; @@ -43,6 +46,7 @@ import java.io.File; import java.io.FileReader; import java.io.LineNumberReader; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; @@ -57,32 +61,6 @@ public class AnnotationProcessorErrorTest { Main.class.getClassLoader().setDefaultAssertionStatus(true); } - /** - * Checks that compilation fails correctly when annotation processor is called without specifying - * output folder. - */ - @Test - public void testAnnotationProcessorError001() throws Exception { - ErrorTestHelper te = new ErrorTestHelper(); - - AbstractTestTools.createFile(te.getSourceFolder(),"jack.incremental", "A.java", - "package jack.incremental; \n"+ - "public class A {} \n"); - - JackApiToolchainBase jackApiToolchain = - AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); - jackApiToolchain.setAnnotationProcessorClass(ResourceAnnotationProcessor.class); - - try { - jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath()) - .srcToExe(te.getOutputDexFolder(), /* zipFile = */ false, te.getSourceFolder()); - Assert.fail(); - } catch (JackUserException e) { - // Failure is ok since output for annotation processor is not specify. - Assert.assertTrue(e.getMessage().contains("Unknown location")); - } - } - /** * Checks that compilation succeed when running annotation processor to generate resource file. */ @@ -101,12 +79,14 @@ public class AnnotationProcessorErrorTest { runAnnotProcBuildingResource(te); - JackApiToolchainBase jackApiToolchain = - AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); - jackApiToolchain.setAnnotationProcessorClass(ResourceAnnotationProcessor.class); - jackApiToolchain.setAnnotationProcessorOutDir(te.getTestingFolder()); + JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); + jackApiToolchain.setAnnotationProcessorClasses( + Collections.singletonList(ResourceAnnotationProcessor.class.getName())); ByteArrayOutputStream errOut = new ByteArrayOutputStream(); jackApiToolchain.setErrorStream(errOut); + jackApiToolchain.addResource(te.getOutputDexFolder()); + jackApiToolchain.addProperty(ResourceImporter.RESOURCE_COLLISION_POLICY.getName(), + CollisionPolicy.FAIL.name()); try { @@ -115,10 +95,9 @@ public class AnnotationProcessorErrorTest { .srcToExe(te.getOutputDexFolder(), /* zipFile = */ false, te.getSourceFolder()); Assert.fail(); - } catch (FrontendCompilationException e) { + } catch (JackAbortException e) { + Assert.assertTrue(e.getCause() instanceof ResourceReadingException); // Failure is ok since created file already exists - } finally { - Assert.assertTrue(errOut.toString().contains("Resource already created")); } } @@ -139,10 +118,9 @@ public class AnnotationProcessorErrorTest { + "public class A {}\n"); - JackApiToolchainBase jackApiToolchain = - AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); - jackApiToolchain.setAnnotationProcessorClass(SourceAnnotationProcessor.class); - jackApiToolchain.setAnnotationProcessorOutDir(te.getTestingFolder()); + JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); + jackApiToolchain.setAnnotationProcessorClasses( + Collections.singletonList(SourceAnnotationProcessor.class.getName())); ByteArrayOutputStream errOut = new ByteArrayOutputStream(); jackApiToolchain.setErrorStream(errOut); @@ -173,10 +151,9 @@ public class AnnotationProcessorErrorTest { + "@" + SourceAnnotationTest.class.getSimpleName() + "\n" + "public class A {}\n"); - JackApiToolchainBase jackApiToolchain = - AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); - jackApiToolchain.setAnnotationProcessorClass(SourceAnnotationProcessor.class); - jackApiToolchain.setAnnotationProcessorOutDir(te.getTestingFolder()); + JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); + jackApiToolchain.setAnnotationProcessorClasses( + Collections.singletonList(SourceAnnotationProcessor.class.getName())); File dexOutput = te.getOutputDexFolder(); jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath()) @@ -202,16 +179,15 @@ public class AnnotationProcessorErrorTest { + "@" + ResourceAnnotationTest.class.getSimpleName() + "\n" + "public class A {}\n"); - JackApiToolchainBase jackApiToolchain = - AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); - jackApiToolchain.setAnnotationProcessorClass(ResourceAnnotationProcessor.class); - jackApiToolchain.setAnnotationProcessorOutDir(te.getTestingFolder()); + JackApiToolchainBase jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); + jackApiToolchain.setAnnotationProcessorClasses( + Collections.singletonList(ResourceAnnotationProcessor.class.getName())); jackApiToolchain.addToClasspath(jackApiToolchain.getDefaultBootClasspath()) .addToClasspath(te.getJackFolder()) .srcToExe(te.getOutputDexFolder(), /* zipFile = */ false, te.getSourceFolder()); - File discoverFile = new File(te.getTestingFolder(), ResourceAnnotationProcessor.FILENAME); + File discoverFile = new File(te.getOutputDexFolder(), ResourceAnnotationProcessor.FILENAME); Assert.assertTrue(discoverFile.exists()); LineNumberReader lnr = new LineNumberReader(new FileReader(discoverFile)); Assert.assertEquals(ResourceAnnotationTest.class.getName(), lnr.readLine()); diff --git a/jack-tests/tests/com/android/jack/error/FileAccessErrorTest.java b/jack-tests/tests/com/android/jack/error/FileAccessErrorTest.java index ff2cef23..259bf6a0 100644 --- a/jack-tests/tests/com/android/jack/error/FileAccessErrorTest.java +++ b/jack-tests/tests/com/android/jack/error/FileAccessErrorTest.java @@ -184,6 +184,7 @@ public class FileAccessErrorTest { "package jack.incremental; \n"+ "public class B extends A {} \n"); + jackApiToolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); ByteArrayOutputStream errOut = new ByteArrayOutputStream(); try { for (File jackFile : AbstractTestTools.getFiles(te.getJackFolder(), JayceFileImporter.JAYCE_FILE_EXTENSION)) { diff --git a/jack-tests/tests/com/android/jack/fileconflict/FileConflictTests.java b/jack-tests/tests/com/android/jack/fileconflict/FileConflictTests.java index 61be8c25..1725143c 100644 --- a/jack-tests/tests/com/android/jack/fileconflict/FileConflictTests.java +++ b/jack-tests/tests/com/android/jack/fileconflict/FileConflictTests.java @@ -36,6 +36,7 @@ import com.android.jack.test.toolchain.JackCliToolchain; import com.android.jack.test.toolchain.LegacyJillToolchain; import com.android.sched.util.stream.ByteStreamSucker; + import junit.framework.Assert; import org.junit.BeforeClass; @@ -407,14 +408,14 @@ public class FileConflictTests { // create Jack dirs to import File jackImport1 = AbstractTestTools.createTempDir(); - copyFileToDir(libProperties, libPropName, jackImport1); - copyFileToDir(myClass1, jackFilePath, jackImport1); - copyFileToDir(myClass1Dex, dexFilePath, jackImport1); - copyFileToDir(digestFile, FileType.DEX.getPrefix() + "/digest", jackImport1); + AbstractTestTools.copyFileToDir(libProperties, libPropName, jackImport1); + AbstractTestTools.copyFileToDir(myClass1, jackFilePath, jackImport1); + AbstractTestTools.copyFileToDir(myClass1Dex, dexFilePath, jackImport1); + AbstractTestTools.copyFileToDir(digestFile, FileType.DEX.getPrefix() + "/digest", jackImport1); // copy Jack file to output dir - copyFileToDir(myClass1, jackFilePath, jackOutput); - copyFileToDir(myClass1Dex, dexFilePath, jackOutput); + AbstractTestTools.copyFileToDir(myClass1, jackFilePath, jackOutput); + AbstractTestTools.copyFileToDir(myClass1Dex, dexFilePath, jackOutput); toolchain = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class, exclude); toolchain.addProguardFlags(new File(testSrcDir, "proguard.flags")); @@ -454,13 +455,13 @@ public class FileConflictTests { File jackImport1 = AbstractTestTools.createTempDir(); String resourcePath = "com/android/jack/fileconflict/test003/jack/Resource"; File resource = new File(testSrcDir, "Resource"); - copyFileToDir(libProperties, libPropName, jackImport1); - copyFileToDir(myClass1, jackFilePath, jackImport1); - copyFileToDir(resource, resourcePath, jackImport1); + AbstractTestTools.copyFileToDir(libProperties, libPropName, jackImport1); + AbstractTestTools.copyFileToDir(myClass1, jackFilePath, jackImport1); + AbstractTestTools.copyFileToDir(resource, resourcePath, jackImport1); // copy a different resource to output dir with the same name File resource2 = new File(testSrcDir, "Resource2"); - copyFileToDir(resource2, resourcePath, jackOutput); + AbstractTestTools.copyFileToDir(resource2, resourcePath, jackOutput); // run Jack on Jack dir toolchain = AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); @@ -503,13 +504,13 @@ public class FileConflictTests { // create Jack dirs to import File jackImport1 = AbstractTestTools.createTempDir(); File resource = new File(testSrcDir, "MyClass.txt"); - copyFileToDir(libProperties, libPropName, jackImport1); - copyFileToDir(myClass1, jackFilePath, jackImport1); - copyFileToDir(resource, "com/android/jack/fileconflict/test004/jack/MyClass.txt", jackImport1); + AbstractTestTools.copyFileToDir(libProperties, libPropName, jackImport1); + AbstractTestTools.copyFileToDir(myClass1, jackFilePath, jackImport1); + AbstractTestTools.copyFileToDir(resource, "com/android/jack/fileconflict/test004/jack/MyClass.txt", jackImport1); // copy a different resource to output dir with the same name File resource2 = new File(testSrcDir, "a.txt"); - copyFileToDir(resource2, "pcz/nbqfcvq/wnpx/svyrpcbsyvph/hrgh004/wnpx/ZmPyngg.txt", jackOutput); + AbstractTestTools.copyFileToDir(resource2, "pcz/nbqfcvq/wnpx/svyrpcbsyvph/hrgh004/wnpx/ZmPyngg.txt", jackOutput); // run Jack on Jack dir toolchain = AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); @@ -564,18 +565,18 @@ public class FileConflictTests { // create Jack dirs to import File jackImport1 = AbstractTestTools.createTempDir(); File jackImport2 = AbstractTestTools.createTempDir(); - copyFileToDir(digestFile, FileType.DEX.getPrefix() + "/digest", jackImport1); - copyFileToDir(digestFile, FileType.DEX.getPrefix() + "/digest", jackImport2); - copyFileToDir(libProperties, libPropName, jackImport1); - copyFileToDir(myClass1, JACK_FILE_PATH_1, jackImport1); - copyFileToDir(myClass1Dex, DEX_FILE_PATH_1, jackImport1); - copyFileToDir(myClass2, JACK_FILE_PATH_2, jackImport1); - copyFileToDir(myClass2Dex, DEX_FILE_PATH_2, jackImport1); - copyFileToDir(libProperties, libPropName, jackImport2); - copyFileToDir(myClass1, JACK_FILE_PATH_1, jackImport2); - copyFileToDir(myClass1Dex, DEX_FILE_PATH_1, jackImport2); - copyFileToDir(myClass3, JACK_FILE_PATH_3, jackImport2); - copyFileToDir(myClass3Dex, DEX_FILE_PATH_3, jackImport2); + AbstractTestTools.copyFileToDir(digestFile, FileType.DEX.getPrefix() + "/digest", jackImport1); + AbstractTestTools.copyFileToDir(digestFile, FileType.DEX.getPrefix() + "/digest", jackImport2); + AbstractTestTools.copyFileToDir(libProperties, libPropName, jackImport1); + AbstractTestTools.copyFileToDir(myClass1, JACK_FILE_PATH_1, jackImport1); + AbstractTestTools.copyFileToDir(myClass1Dex, DEX_FILE_PATH_1, jackImport1); + AbstractTestTools.copyFileToDir(myClass2, JACK_FILE_PATH_2, jackImport1); + AbstractTestTools.copyFileToDir(myClass2Dex, DEX_FILE_PATH_2, jackImport1); + AbstractTestTools.copyFileToDir(libProperties, libPropName, jackImport2); + AbstractTestTools.copyFileToDir(myClass1, JACK_FILE_PATH_1, jackImport2); + AbstractTestTools.copyFileToDir(myClass1Dex, DEX_FILE_PATH_1, jackImport2); + AbstractTestTools.copyFileToDir(myClass3, JACK_FILE_PATH_3, jackImport2); + AbstractTestTools.copyFileToDir(myClass3Dex, DEX_FILE_PATH_3, jackImport2); // run Jack on Jack dirs toolchain = getToolchain(isApiTest); @@ -608,6 +609,7 @@ public class FileConflictTests { /* zipFiles = */ false, lib1); + toolchain = getToolchain(isApiTest); File jackImport2 = AbstractTestTools.createTempDir(); File lib2 = new File(TEST002_DIR, "lib2"); toolchain = getToolchain(isApiTest); @@ -640,36 +642,6 @@ public class FileConflictTests { return jackOutput; } - private void copyFileToDir(@Nonnull File fileToCopy, @Nonnull String relativePath, - @Nonnull File dir) throws IOException { - FileOutputStream fos = null; - FileInputStream fis = null; - try { - fis = new FileInputStream(fileToCopy); - File copiedFile = new File(dir, relativePath); - File parentDir = copiedFile.getParentFile(); - if (!parentDir.exists()) { - boolean res = parentDir.mkdirs(); - if (!res) { - throw new AssertionError(); - } - } - try { - fos = new FileOutputStream(copiedFile); - ByteStreamSucker sucker = new ByteStreamSucker(fis, fos); - sucker.suck(); - } finally { - if (fos != null) { - fos.close(); - } - } - } finally { - if (fis != null) { - fis.close(); - } - } - } - private void checkResourceContent(@Nonnull File dir, @Nonnull String path, @Nonnull String expectedContent) throws IOException { assert dir.isDirectory(); -- cgit v1.2.3