diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java index 8019d074f3..ee2e3eee84 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java @@ -110,6 +110,7 @@ import org.androidannotations.generation.CodeModelGenerator; import org.androidannotations.helper.AndroidManifest; import org.androidannotations.helper.AndroidManifestFinder; +import org.androidannotations.helper.Option; import org.androidannotations.helper.TimeStats; import org.androidannotations.model.AndroidRes; import org.androidannotations.model.AndroidSystemServices; @@ -355,19 +356,29 @@ private void processThrowing(Set annotations, RoundEnviro AnnotationElementsHolder extractedModel = extractAnnotations(annotations, roundEnv); - AndroidManifest androidManifest = extractAndroidManifest(); + Option androidManifestOption = extractAndroidManifest(); - IRClass rClass = findRClasses(androidManifest); + if (androidManifestOption.isAbsent()) { + return; + } + + AndroidManifest androidManifest = androidManifestOption.get(); + + Option rClassOption = findRClasses(androidManifest); + + if (rClassOption.isAbsent()) { + return; + } + + IRClass rClass = rClassOption.get(); AndroidSystemServices androidSystemServices = new AndroidSystemServices(); AnnotationElements validatedModel = validateAnnotations(extractedModel, rClass, androidSystemServices, androidManifest); - if (validatedModel != null) { - ProcessResult processResult = processAnnotations(validatedModel, rClass, androidSystemServices, androidManifest); + ProcessResult processResult = processAnnotations(validatedModel, rClass, androidSystemServices, androidManifest); - generateSources(processResult); - } + generateSources(processResult); } private boolean nothingToDo(Set annotations, RoundEnvironment roundEnv) { @@ -382,39 +393,39 @@ private AnnotationElementsHolder extractAnnotations(Set a return extractedModel; } - private AndroidManifest extractAndroidManifest() { + private Option extractAndroidManifest() { timeStats.start("Extract Manifest"); AndroidManifestFinder finder = new AndroidManifestFinder(processingEnv); - AndroidManifest manifest = finder.extractAndroidManifest(); + Option manifest = finder.extractAndroidManifest(); timeStats.stop("Extract Manifest"); return manifest; } - private IRClass findRClasses(AndroidManifest androidManifest) throws IOException { + private Option findRClasses(AndroidManifest androidManifest) throws IOException { timeStats.start("Find R Classes"); ProjectRClassFinder rClassFinder = new ProjectRClassFinder(processingEnv); - IRClass rClass = rClassFinder.find(androidManifest); + + Option rClass = rClassFinder.find(androidManifest); AndroidRClassFinder androidRClassFinder = new AndroidRClassFinder(processingEnv); - IRClass androidRClass = androidRClassFinder.find(); + Option androidRClass = androidRClassFinder.find(); - CoumpoundRClass coumpoundRClass = new CoumpoundRClass(rClass, androidRClass); + if (rClass.isAbsent() || androidRClass.isAbsent()) { + return Option.absent(); + } + + IRClass coumpoundRClass = new CoumpoundRClass(rClass.get(), androidRClass.get()); timeStats.stop("Find R Classes"); - return coumpoundRClass; + return Option.of(coumpoundRClass); } private AnnotationElements validateAnnotations(AnnotationElementsHolder extractedModel, IRClass rClass, AndroidSystemServices androidSystemServices, AndroidManifest androidManifest) { timeStats.start("Validate Annotations"); - AnnotationElements validatedAnnotations; - if (rClass != null) { - ModelValidator modelValidator = buildModelValidator(rClass, androidSystemServices, androidManifest); - validatedAnnotations = modelValidator.validate(extractedModel); - } else { - validatedAnnotations = null; - } + ModelValidator modelValidator = buildModelValidator(rClass, androidSystemServices, androidManifest); + AnnotationElements validatedAnnotations = modelValidator.validate(extractedModel); timeStats.stop("Validate Annotations"); return validatedAnnotations; } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java index 162bc4e27a..c4649c191f 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java @@ -50,19 +50,14 @@ public AndroidManifestFinder(ProcessingEnvironment processingEnv) { this.processingEnv = processingEnv; } - public AndroidManifest extractAndroidManifest() { - try { - return extractAndroidManifestThrowing(); - } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } - throw new RuntimeException(e); + public Option extractAndroidManifest() { + Option androidManifestFileOption = findManifestFile(); + + if (androidManifestFileOption.isAbsent()) { + return Option.absent(); } - } - private AndroidManifest extractAndroidManifestThrowing() throws Exception { - File androidManifestFile = findManifestFileThrowing(); + File androidManifestFile = androidManifestFileOption.get(); String projectDirectory = androidManifestFile.getParent(); @@ -71,22 +66,23 @@ private AndroidManifest extractAndroidManifestThrowing() throws Exception { boolean libraryProject = false; if (projectProperties.exists()) { Properties properties = new Properties(); - properties.load(new FileInputStream(projectProperties)); - - if (properties.containsKey("android.library")) { - String androidLibraryProperty = properties.getProperty("android.library"); - libraryProject = androidLibraryProperty.equals("true"); - - Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.NOTE, "Found android.library property in project.properties, value: " + libraryProject); + try { + properties.load(new FileInputStream(projectProperties)); + if (properties.containsKey("android.library")) { + String androidLibraryProperty = properties.getProperty("android.library"); + libraryProject = androidLibraryProperty.equals("true"); + + Messager messager = processingEnv.getMessager(); + messager.printMessage(Kind.NOTE, "Found android.library property in project.properties, value: " + libraryProject); + } + } catch (IOException ignored) { } - } - return parseThrowing(androidManifestFile, libraryProject); + return parse(androidManifestFile, libraryProject); } - private File findManifestFileThrowing() throws Exception { + private Option findManifestFile() { if (processingEnv.getOptions().containsKey(ANDROID_MANIFEST_FILE_OPTION)) { return findManifestInSpecifiedPath(); } else { @@ -94,16 +90,17 @@ private File findManifestFileThrowing() throws Exception { } } - private File findManifestInSpecifiedPath() { + private Option findManifestInSpecifiedPath() { String path = processingEnv.getOptions().get(ANDROID_MANIFEST_FILE_OPTION); File androidManifestFile = new File(path); Messager messager = processingEnv.getMessager(); if (!androidManifestFile.exists()) { - throw new IllegalStateException("Could not find the AndroidManifest.xml file in specified path : " + path); + messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file in specified path : " + path); + return Option.absent(); } else { messager.printMessage(Kind.NOTE, "AndroidManifest.xml file found: " + androidManifestFile.toString()); } - return androidManifestFile; + return Option.of(androidManifestFile); } /** @@ -113,10 +110,18 @@ private File findManifestInSpecifiedPath() { * find the AndroidManifest.xml file. Any better solution will be * appreciated. */ - private File findManifestInParentsDirectories() throws IOException, URISyntaxException { + private Option findManifestInParentsDirectories() { Filer filer = processingEnv.getFiler(); - JavaFileObject dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis()); + Messager messager = processingEnv.getMessager(); + + JavaFileObject dummySourceFile; + try { + dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis()); + } catch (IOException ignored) { + messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file, unable to create a dummy source file to locate the source folder"); + return Option.absent(); + } String dummySourceFilePath = dummySourceFile.toUri().toString(); if (dummySourceFilePath.startsWith("file:")) { @@ -127,10 +132,13 @@ private File findManifestInParentsDirectories() throws IOException, URISyntaxExc dummySourceFilePath = "file://" + dummySourceFilePath; } - Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.NOTE, "Dummy source file: " + dummySourceFilePath); - - URI cleanURI = new URI(dummySourceFilePath); + URI cleanURI; + try { + cleanURI = new URI(dummySourceFilePath); + } catch (URISyntaxException e) { + messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file, path to dummy source file cannot be parsed: " + dummySourceFilePath); + return Option.absent(); + } File dummyFile = new File(cleanURI); @@ -153,19 +161,28 @@ private File findManifestInParentsDirectories() throws IOException, URISyntaxExc } if (!androidManifestFile.exists()) { - throw new IllegalStateException("Could not find the AndroidManifest.xml file, going up from path [" + sourcesGenerationFolder.getAbsolutePath() + "] found using dummy file [" + dummySourceFilePath + "] (max atempts: " + MAX_PARENTS_FROM_SOURCE_FOLDER + ")"); + messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file, going up from path [" + sourcesGenerationFolder.getAbsolutePath() + "] found using dummy file [" + dummySourceFilePath + "] (max atempts: " + MAX_PARENTS_FROM_SOURCE_FOLDER + ")"); + return Option.absent(); } else { messager.printMessage(Kind.NOTE, "AndroidManifest.xml file found: " + androidManifestFile.toString()); } - return androidManifestFile; + return Option.of(androidManifestFile); } - private AndroidManifest parseThrowing(File androidManifestFile, boolean libraryProject) throws Exception { + private Option parse(File androidManifestFile, boolean libraryProject) { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document doc = docBuilder.parse(androidManifestFile); + + Document doc; + try { + DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); + doc = docBuilder.parse(androidManifestFile); + } catch (Exception e) { + Messager messager = processingEnv.getMessager(); + messager.printMessage(Kind.ERROR, "Could not parse the AndroidManifest.xml file at path " + androidManifestFile); + return Option.absent(); + } Element documentElement = doc.getDocumentElement(); documentElement.normalize(); @@ -173,7 +190,7 @@ private AndroidManifest parseThrowing(File androidManifestFile, boolean libraryP String applicationPackage = documentElement.getAttribute("package"); if (libraryProject) { - return AndroidManifest.createLibraryManifest(applicationPackage); + return Option.of(AndroidManifest.createLibraryManifest(applicationPackage)); } NodeList applicationNodes = documentElement.getElementsByTagName("application"); @@ -214,7 +231,7 @@ private AndroidManifest parseThrowing(File androidManifestFile, boolean libraryP componentQualifiedNames.addAll(receiverQualifiedNames); componentQualifiedNames.addAll(providerQualifiedNames); - return AndroidManifest.createManifest(applicationPackage, applicationQualifiedName, componentQualifiedNames); + return Option.of(AndroidManifest.createManifest(applicationPackage, applicationQualifiedName, componentQualifiedNames)); } private List extractComponentNames(String applicationPackage, NodeList componentNodes) { diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/Option.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/Option.java new file mode 100644 index 0000000000..9d06e14cc5 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/Option.java @@ -0,0 +1,52 @@ +package org.androidannotations.helper; + +/** + * I'd love to use Guava's Optional, but we're trying to keep the dependency + * level to a minimum. + */ +public class Option { + + private static final Option ABSENT = new Option(null, false); + + public static Option of(T value) { + return new Option(value, true); + } + + @SuppressWarnings("unchecked") + public static Option absent() { + return (Option) ABSENT; + } + + private final T reference; + + private final boolean isPresent; + + private Option(T reference, boolean isPresent) { + this.reference = reference; + this.isPresent = isPresent; + } + + public boolean isPresent() { + return isPresent; + } + + public boolean isAbsent() { + return !isPresent; + } + + public T get() { + if (!isPresent) { + throw new IllegalStateException("value is absent"); + } + return reference; + } + + public T getOr(T defaultValue) { + if (isPresent) { + return reference; + } else { + return defaultValue; + } + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java index 2906bab242..96babec2f4 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java @@ -15,8 +15,12 @@ */ package org.androidannotations.rclass; +import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; + +import org.androidannotations.helper.Option; public class AndroidRClassFinder { @@ -26,9 +30,13 @@ public AndroidRClassFinder(ProcessingEnvironment processingEnv) { this.processingEnv = processingEnv; } - public IRClass find() { + public Option find() { TypeElement androidRType = processingEnv.getElementUtils().getTypeElement("android.R"); - return new RClass(androidRType); + if (androidRType == null) { + Messager messager = processingEnv.getMessager(); + messager.printMessage(Kind.ERROR, "The android.R class cannot be found"); + return Option.absent(); + } + return Option. of(new RClass(androidRType)); } - } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/IRClass.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/IRClass.java index 9a195196a7..cf5db1c08e 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/IRClass.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/IRClass.java @@ -28,11 +28,4 @@ public String rName() { IRInnerClass get(Res res); - final IRClass EMPTY_R_CLASS = new IRClass() { - @Override - public IRInnerClass get(Res res) { - return IRInnerClass.EMPTY_R_INNER_CLASS; - } - }; - } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java index d405f157dd..75eb3ec0fd 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java @@ -22,6 +22,7 @@ import javax.tools.Diagnostic.Kind; import org.androidannotations.helper.AndroidManifest; +import org.androidannotations.helper.Option; public class ProjectRClassFinder { @@ -31,7 +32,7 @@ public ProjectRClassFinder(ProcessingEnvironment processingEnv) { this.processingEnv = processingEnv; } - public IRClass find(AndroidManifest manifest) { + public Option find(AndroidManifest manifest) { Elements elementUtils = processingEnv.getElementUtils(); String rClass = manifest.getApplicationPackage() + ".R"; @@ -39,11 +40,10 @@ public IRClass find(AndroidManifest manifest) { if (rType == null) { Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.WARNING, "The AndroidManifest.xml file was found, but not the compiled R class: " + rClass); - return IRClass.EMPTY_R_CLASS; + messager.printMessage(Kind.ERROR, "The generated " + rClass + " class cannot be found"); + return Option.absent(); } - return new RClass(rType); + return Option. of(new RClass(rType)); } - } diff --git a/AndroidAnnotations/androidannotations/src/test/java/android/R.java b/AndroidAnnotations/androidannotations/src/test/java/android/R.java new file mode 100644 index 0000000000..3c7a80be53 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/java/android/R.java @@ -0,0 +1,5 @@ +package android; + +public class R { + +} diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/manifest/AndroidManifestFinderTest.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/manifest/AndroidManifestFinderTest.java index 431a32d4e4..b9c4d9ab60 100644 --- a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/manifest/AndroidManifestFinderTest.java +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/manifest/AndroidManifestFinderTest.java @@ -36,9 +36,10 @@ public void setup() { } @Test - public void fails_if_no_manifest() throws Exception { + public void fails_if_no_manifest() { CompileResult result = compileFiles(SomeClass.class); - assertCompilationError(result); + assertCompilationErrorWithNoSource(result); + assertCompilationErrorCount(1, result); } @Test @@ -48,6 +49,14 @@ public void finds_specified_manifest() { assertCompilationSuccessful(result); } + @Test + public void fails_if_cannot_find_specified_manifest() { + addProcessorParameter("androidManifestFile", "/some/random/path/AndroidManifest.xml"); + CompileResult result = compileFiles(SomeClass.class); + assertCompilationErrorWithNoSource(result); + assertCompilationErrorCount(1, result); + } + @Test public void finds_manifest_in_generated_source_parent_folder() throws Exception { copyManifestToParentOfOutputDirectory(); @@ -56,6 +65,14 @@ public void finds_manifest_in_generated_source_parent_folder() throws Exception deleteManifestFromParentOfOutputDirectory(); } + @Test + public void fails_if_cannot_parse_manifest() { + addManifestProcessorParameter(AndroidManifestFinderTest.class, "ParseErrorManifest.xml"); + CompileResult result = compileFiles(SomeClass.class); + assertCompilationErrorWithNoSource(result); + assertCompilationErrorCount(1, result); + } + private void deleteManifestFromParentOfOutputDirectory() { manifestFileInParentOfOutputDirectory().delete(); } diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/rclass/RClassFinderTest.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/rclass/RClassFinderTest.java new file mode 100644 index 0000000000..6b20155d7c --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/rclass/RClassFinderTest.java @@ -0,0 +1,24 @@ +package org.androidannotations.rclass; + +import org.androidannotations.AndroidAnnotationProcessor; +import org.androidannotations.manifest.SomeClass; +import org.androidannotations.utils.AAProcessorTestHelper; +import org.junit.Before; +import org.junit.Test; + +public class RClassFinderTest extends AAProcessorTestHelper { + + @Before + public void setup() { + addManifestProcessorParameter(RClassFinderTest.class); + addProcessor(AndroidAnnotationProcessor.class); + } + + @Test + public void fails_if_cannot_find_R_class() { + CompileResult result = compileFiles(SomeClass.class); + assertCompilationErrorWithNoSource(result); + assertCompilationErrorCount(1, result); + } + +} diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/testprocessor/R.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/testprocessor/R.java new file mode 100644 index 0000000000..23de1e999f --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/testprocessor/R.java @@ -0,0 +1,5 @@ +package org.androidannotations.testprocessor; + +public class R { + +} diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/AAProcessorTestHelper.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/AAProcessorTestHelper.java index ee0ab34ced..7828cd4b57 100644 --- a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/AAProcessorTestHelper.java +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/AAProcessorTestHelper.java @@ -22,7 +22,11 @@ public class AAProcessorTestHelper extends ProcessorTestHelper { public void addManifestProcessorParameter(Class classOfPackagingContainingManifest) { - String manifestPath = classOfPackagingContainingManifest.getResource("AndroidManifest.xml").getPath(); + addManifestProcessorParameter(classOfPackagingContainingManifest, "AndroidManifest.xml"); + } + + public void addManifestProcessorParameter(Class classOfPackagingContainingManifest, String manifestFileName) { + String manifestPath = classOfPackagingContainingManifest.getResource(manifestFileName).getPath(); addProcessorParameter("androidManifestFile", manifestPath); } diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/ProcessorTestHelper.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/ProcessorTestHelper.java index 0cf057a9be..f6b91ccf20 100644 --- a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/ProcessorTestHelper.java +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/utils/ProcessorTestHelper.java @@ -109,6 +109,28 @@ public static void assertCompilationError(CompileResult result) { fail("Expected a compilation error, diagnostics: " + result.diagnostics); } + public static void assertCompilationErrorWithNoSource(CompileResult result) { + for (Diagnostic diagnostic : result.diagnostics) { + if (diagnostic.getKind() == Kind.ERROR && diagnostic.getSource() == null) { + return; + } + } + fail("Expected a compilation error with no source, diagnostics: " + result.diagnostics); + } + + public static void assertCompilationErrorCount(int expectedErrorCount, CompileResult result) { + int errorCount = 0; + for (Diagnostic diagnostic : result.diagnostics) { + if (diagnostic.getKind() == Kind.ERROR) { + errorCount++; + } + } + + if (errorCount != expectedErrorCount) { + fail("Expected " + expectedErrorCount + " compilation error, found " + errorCount + " diagnostics: " + result.diagnostics); + } + } + public static void assertCompilationErrorOn(File expectedErrorClassFile, String expectedContentInError, CompileResult result) throws IOException { assertCompilationDiagnostingOn(Kind.ERROR, expectedErrorClassFile, expectedContentInError, result); } @@ -136,10 +158,9 @@ private static void assertCompilationDiagnostingOn(Kind expectedDiagnosticKind, } } } - } } - fail("Expected a compilation " + expectedDiagnosticKind + ", diagnostics: " + result.diagnostics); + fail("Expected a compilation " + expectedDiagnosticKind + " in " + expectedErrorClassFile.toString() + " on " + expectedContentInError + ", diagnostics: " + result.diagnostics); } private static String[] getContents(File file) { diff --git a/AndroidAnnotations/androidannotations/src/test/resources/org/androidannotations/manifest/ParseErrorManifest.xml b/AndroidAnnotations/androidannotations/src/test/resources/org/androidannotations/manifest/ParseErrorManifest.xml new file mode 100644 index 0000000000..c55b9f9ae6 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/resources/org/androidannotations/manifest/ParseErrorManifest.xml @@ -0,0 +1,19 @@ + + +OMG This isn't XML!! diff --git a/AndroidAnnotations/androidannotations/src/test/resources/org/androidannotations/rclass/AndroidManifest.xml b/AndroidAnnotations/androidannotations/src/test/resources/org/androidannotations/rclass/AndroidManifest.xml new file mode 100644 index 0000000000..54ca01042a --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/resources/org/androidannotations/rclass/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + +