@Test public void failsIfHasReturnType() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnClick;\n" + "public class Test {\n" + " @OnClick(1)\n" + " public String doStuff() {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("@OnClick methods must have a 'void' return type. (test.Test.doStuff)") .in(source).onLine(5); }
/** * Verify that an alternate file manager can be specified: * in this case, a TestFileManager. */ @Test public void testFileManager() throws Exception { JavaFileObject srcFile = createSimpleJavaFileObject(); DocumentationTool tool = ToolProvider.getSystemDocumentationTool(); StandardJavaFileManager fm = new TestFileManager(); File outDir = getOutDir(); fm.setLocation(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(outDir)); Iterable<? extends JavaFileObject> files = Arrays.asList(srcFile); DocumentationTask t = tool.getTask(null, fm, null, null, Arrays.asList("-verbose"), files); if (t.call()) { System.err.println("task succeeded"); checkFiles(outDir, standardExpectFiles); } else { throw new Exception("task failed"); } }
@Test public void testNUnrelatedORToOneAP_creates_GeneratedFiles_WhenTwoFileToProcess() { //GIVEN JavaFileObject source0 = forSourceString("test.Test0", "" // + "package test;\n" // + "import org.gradle.incap.Annotation1;\n" // + "@Annotation1\n" // + "public class Test0 {\n" // + "}\n" // + "@Annotation1\n" // + "class Test1 {\n" // + "}"); JavaFileObject expected = forSourceString("NUnrelatedORToOneAP_OR_Gen0", "" // + "\n" // + "public class NUnrelatedORToOneAP_OR_Gen0 {\n" // + "}"); //WHEN //THEN Truth.assertAbout(JavaSourceSubjectFactory.javaSource()).that(source0) // .withCompilerOptions("-Xlint:-processing","-Aincap.mapping.folder=.", "-Aincap.incremental=true") // .processedWith(new NUnrelatedORToOneAP()) // .compilesWithoutError().and().generatesSources(expected); }
/** * Emit a class file for a given class. * * @param c The class from which a class file is generated. */ public JavaFileObject writeClass(ClassSymbol c) throws IOException, PoolOverflow, StringOverflow { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, c.flatname.toString(), JavaFileObject.Kind.CLASS, c.sourcefile); OutputStream out = outFile.openOutputStream(); try { writeClassFile(out, c); if (verbose) log.printVerbose("wrote.file", outFile); out.close(); out = null; } finally { if (out != null) { // if we are propogating an exception, delete the file out.close(); outFile.delete(); outFile = null; } } return outFile; // may be null if write failed }
@Override public JavaFileObject getJavaFileForOutput( final Location location, final String className, final Kind kind, final FileObject sibling) throws IOException { final URI uri = createUri(location, className, kind); if (!files.containsKey(uri)) { files.put(uri, new InMemoryJavaFileObject(uri)); } return files.get(uri); }
@Override public void test(TestCase testCase, Map<String, ? extends JavaFileObject> classes) throws IOException, ConstantPoolException, Descriptor.InvalidDescriptor { for (Map.Entry<String, ? extends JavaFileObject> entry : classes.entrySet()) { ClassFile classFile = readClassFile(classes.get(entry.getKey())); Set<String> foundMethods = new HashSet<>(); String className = classFile.getName(); TestCase.TestClassInfo testClassInfo = testCase.classes.get(className); for (Method method : classFile.methods) { String methodName = method.getName(classFile.constant_pool) + method.descriptor.getParameterTypes(classFile.constant_pool); if (methodName.startsWith("<init>")) { methodName = methodName.replace("<init>", className); } foundMethods.add(methodName); echo("Testing method : " + methodName); TestCase.TestMethodInfo testMethod = testClassInfo.getTestMethodInfo(methodName); if (testMethod == null) { continue; } testAttributes(testMethod, classFile, method); } checkContains(foundMethods, testClassInfo.methods.keySet(), "Methods in " + className); } }
@Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { Map<String, Integer> map = new HashMap<>(); Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(ContentView.class); for (Element element : elements) { TypeElement type = (TypeElement) element; ContentView annotation = type.getAnnotation(ContentView.class); String name = type.getQualifiedName().toString(); map.put(name, annotation.value()); } try { JavaFileObject sourceFile = filer.createSourceFile(API_PATH); Writer writer = sourceFile.openWriter(); writer.write(generateCode(map)); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } return true; }
@Test public void testConfigurationMayNotHaveNonPublicConstructors() throws IOException { JavaFileObject definitionClass = JavaFileObjects.forSourceLines( "test.TestClass", "package test;", "", "import org.springframework.context.annotation.Bean;", "import org.springframework.context.annotation.Configuration;", "", "@com.salesforce.aptspring.Verified", "@Configuration", "public class TestClass {", "", " private TestClass() {", " }", "", "}"); assertAbout(javaSources()) .that(Arrays.asList(definitionClass)) .processedWith(new VerifiedSpringConfiguration()) .failsToCompile() .withErrorContaining("@Configuration should not have any non-public constructors.") .in(definitionClass) .onLine(10); }
public ModuleSymbol findSingleModule() { try { JavaFileObject src_fo = getModuleInfoFromLocation(StandardLocation.SOURCE_PATH, Kind.SOURCE); JavaFileObject class_fo = getModuleInfoFromLocation(StandardLocation.CLASS_OUTPUT, Kind.CLASS); JavaFileObject fo = (src_fo == null) ? class_fo : (class_fo == null) ? src_fo : classFinder.preferredFileObject(src_fo, class_fo); ModuleSymbol msym; if (fo == null) { msym = syms.unnamedModule; } else { msym = readModule(fo); } if (msym.patchLocation == null) { msym.classLocation = StandardLocation.CLASS_OUTPUT; } else { msym.patchOutputLocation = StandardLocation.CLASS_OUTPUT; } return msym; } catch (IOException e) { throw new Error(e); // FIXME } }
@Test public void testNRelatedToOneAP_creates_GeneratedFiles_WhenSingleFileToProcess() { //GIVEN JavaFileObject source = forSourceString("test.Test", "" // + "package test;\n" // + "import org.gradle.incap.Annotation1;\n" // + "@Annotation1\n" // + "public class Test {\n" // + "}"); //WHEN //THEN //we can't test that no files were generated, but we would need it. Truth.assertAbout(JavaSourceSubjectFactory.javaSource()).that(source) // .withCompilerOptions("-Xlint:-processing","-Aincap.mapping.folder=.") // .processedWith(new NRelatedToOneAP()) // .compilesWithoutError(); }
@Test public void testAnnotatedClass_asBoundInGenericParameter() { List<Diagnostic<? extends JavaFileObject>> diagnostics = compiler.compile( BETA, ANNOTATED_CLASS, JavaFileObjects.forSourceLines("example.Test", "package example;", "", "import com.google.common.foo.AnnotatedClass;", "", "import java.util.List;", "", "public class Test {", " public static void foo(List<? super AnnotatedClass> list) {", // error " }", "}") ); compiler.assertErrorsOnLines("example/Test.java", diagnostics, 8); }
/** * Emit plain Java source for a class. * * @param env The attribution environment of the outermost class * containing this class. * @param cdef The class definition to be printed. */ JavaFileObject printSource(Env<AttrContext> env, JCClassDecl cdef) throws IOException { JavaFileObject outFile = fileManager.getJavaFileForOutput(CLASS_OUTPUT, cdef.sym.flatname.toString(), JavaFileObject.Kind.SOURCE, null); if (inputFiles.contains(outFile)) { log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); return null; } else { BufferedWriter out = new BufferedWriter(outFile.openWriter()); try { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) log.printVerbose("wrote.file", outFile); } finally { out.close(); } return outFile; } }
public void run() throws IOException { File srcDir = new File(System.getProperty("test.src")); File thisFile = new File(srcDir, getClass().getName() + ".java"); JavaCompiler c = ToolProvider.getSystemJavaCompiler(); try (StandardJavaFileManager fm = c.getStandardFileManager(null, null, null)) { List<String> opts = Arrays.asList("-proc:only", "-doe"); Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(thisFile); JavacTask t = (JavacTask) c.getTask(null, fm, null, opts, null, files); t.setProcessors(Collections.singleton(this)); boolean ok = t.call(); if (!ok) throw new Error("compilation failed"); } }
@CheckForNull private static String getResourceName (@NullAllowed final CompilationUnitTree cu) { if (cu instanceof JCTree.JCCompilationUnit) { JavaFileObject jfo = ((JCTree.JCCompilationUnit)cu).sourcefile; if (jfo != null) { URI uri = jfo.toUri(); if (uri != null && uri.isAbsolute()) { try { FileObject fo = URLMapper.findFileObject(uri.toURL()); if (fo != null) { ClassPath cp = ClassPath.getClassPath(fo,ClassPath.SOURCE); if (cp != null) { return cp.getResourceName(fo,'.',false); } } } catch (MalformedURLException e) { Exceptions.printStackTrace(e); } } } } return null; }
@NonNull @Override public Iterable<JavaFileObject> getFiles( @NonNull final String folderName, @NullAllowed final ClassPath.Entry entry, @NullAllowed final Set<JavaFileObject.Kind> kinds, @NullAllowed final JavaFileFilterImplementation filter, final boolean recursive) throws IOException { final Collection<Iterable<JavaFileObject>> collector = new ArrayList<>(); for (Archive delegate : getDelegates(this)) { final Iterable<JavaFileObject> it = delegate.getFiles(folderName, entry, kinds, filter, recursive); if (!isEmpty(it)) { collector.add(it); } } return Iterators.chained(collector); }
@Test void testVariableInIfThen2() throws IOException { String code = "package t; class Test { " + "private static void t(String name) { " + "if (name != null) class X {} } }"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); ct.parse(); List<String> codes = new LinkedList<String>(); for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { codes.add(d.getCode()); } assertEquals("testVariableInIfThen2", Arrays.<String>asList("compiler.err.class.not.allowed"), codes); }
@Override public boolean isNameCompatible(String cn, JavaFileObject.Kind kind) { cn.getClass(); // null check if (kind == Kind.OTHER && getKind() != kind) { return false; } String n = cn + kind.extension; if (name.equals(n)) { return true; } if (isMacOS && Normalizer.isNormalized(name, Normalizer.Form.NFD) && Normalizer.isNormalized(n, Normalizer.Form.NFC)) { // On Mac OS X it is quite possible to file name and class // name normalized in a different way - in that case we have to normalize file name // to the Normal Form Compised (NFC) String normName = Normalizer.normalize(name, Normalizer.Form.NFC); if (normName.equals(n)) { this.name = normName; return true; } } if (name.equalsIgnoreCase(n)) { try { // allow for Windows return file.getCanonicalFile().getName().equals(n); } catch (IOException e) { } } return false; }
private void checkSourceLocation(JCCompilationUnit tree, ModuleSymbol msym) { try { JavaFileObject fo = tree.sourcefile; if (fileManager.contains(msym.sourceLocation, fo)) { return; } if (msym.patchLocation != null && fileManager.contains(msym.patchLocation, fo)) { return; } if (fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT)) { if (fileManager.contains(StandardLocation.SOURCE_OUTPUT, fo)) { return; } } else { if (fileManager.contains(StandardLocation.CLASS_OUTPUT, fo)) { return; } } } catch (IOException e) { throw new Error(e); } JavaFileObject prev = log.useSource(tree.sourcefile); try { log.error(tree.pos(), Errors.FileSbOnSourceOrPatchPathForModule); } finally { log.useSource(prev); } }
public static Matcher<Diagnostic<? extends JavaFileObject>> hasMessage( Matcher<String> messageMatcher ) { return new FeatureMatcher<Diagnostic<? extends JavaFileObject>, String>(messageMatcher, "message", "message") { @Override protected String featureValueOf(Diagnostic<? extends JavaFileObject> actual) { return actual.getMessage(Locale.ENGLISH); } }; }
private void addByFile(Env<AttrContext> env) { JavaFileObject file = env.toplevel.sourcefile; if (fileMap == null) fileMap = new HashMap<JavaFileObject, FileQueue>(); FileQueue fq = fileMap.get(file); if (fq == null) { fq = new FileQueue(); fileMap.put(file, fq); contentsByFile.add(fq); } fq.fileContents.add(env); }
/***************************************** * Hackish solution reflection to access the generated class files from the compiler * @param compilation the compilation instance * @return a list of files from the compilation ****************************************/ @SuppressWarnings("unchecked") private static List<JavaFileObject> getFiles(Compilation compilation) throws NoSuchFieldException, IllegalAccessException { Field f = compilation.getClass().getDeclaredField("generatedFiles"); f.setAccessible(true); final ImmutableList<JavaFileObject> files = (ImmutableList<JavaFileObject>) f.get(compilation); List<JavaFileObject> objects = new ArrayList<>(); objects.addAll(files); return objects; }
private void showDiagnostics(DiagnosticCollector<JavaFileObject> diagnostics) { String message; for (Diagnostic<?> diagnostic : diagnostics.getDiagnostics()) { if (StringUtils.equals(diagnostic.getKind().name(), Diagnostic.Kind.ERROR.name())) { message = diagnostic.getMessage(null); new CustomMessageBox(SWT.ERROR, message, Messages.INVALID_EXPRESSION_TITLE).open(); } else { new CustomMessageBox(SWT.ICON_INFORMATION, Messages.VALID_EXPRESSION_TITLE, Messages.VALID_EXPRESSION_TITLE).open(); } break; } }
private static TypeMirror attributeTree(JavacTaskImpl jti, Tree tree, Scope scope, final List<Diagnostic<? extends JavaFileObject>> errors) { Log log = Log.instance(jti.getContext()); JavaFileObject prev = log.useSource(new DummyJFO()); Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log) { @Override public void report(JCDiagnostic diag) { errors.add(diag); } }; NBResolve resolve = NBResolve.instance(jti.getContext()); resolve.disableAccessibilityChecks(); // Enter enter = Enter.instance(jti.getContext()); // enter.shadowTypeEnvs(true); // ArgumentAttr argumentAttr = ArgumentAttr.instance(jti.getContext()); // ArgumentAttr.LocalCacheContext cacheContext = argumentAttr.withLocalCacheContext(); try { Attr attr = Attr.instance(jti.getContext()); Env<AttrContext> env = getEnv(scope); if (tree instanceof JCExpression) return attr.attribExpr((JCTree) tree,env, Type.noType); return attr.attribStat((JCTree) tree,env); } finally { // cacheContext.leave(); log.useSource(prev); log.popDiagnosticHandler(discardHandler); resolve.restoreAccessbilityChecks(); // enter.shadowTypeEnvs(false); } }
public static void main(String... args) { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>(); String source = "class Test extends CompleteOnClosedOther {" + " class Inner extends Undefined { }" + "}"; Iterable<JavaFileObject> files = Arrays.<JavaFileObject>asList(new ToolBox.JavaSource(source)); Iterable<String> options = Arrays.asList("-processor", "CompleteOnClosed"); CompilationTask task = compiler.getTask(null, null, collector, options, null, files); task.call(); for (Diagnostic<? extends JavaFileObject> d : collector.getDiagnostics()) { System.out.println(d.toString()); } }
@Override @NonNull Iterable<JavaFileObject> filter( @NonNull final Location location, @NonNull final String packageName, @NonNull final Iterable<JavaFileObject> files) { return files; }
/** * Main method: compile a list of files, return all compiled classes * * @param sourceFileObjects file objects to be compiled * @param classnames class names to process for annotations * @param processors user provided annotation processors to bypass * discovery, {@code null} means that no processors were provided */ public void compile(List<JavaFileObject> sourceFileObjects, List<String> classnames, Iterable<? extends Processor> processors) { if (processors != null && processors.iterator().hasNext()) explicitAnnotationProcessingRequested = true; // as a JavaCompiler can only be used once, throw an exception if // it has been used before. if (hasBeenUsed) throw new AssertionError("attempt to reuse JavaCompiler"); hasBeenUsed = true; // forcibly set the equivalent of -Xlint:-options, so that no further // warnings about command line options are generated from this point on options.put(XLINT_CUSTOM.text + "-" + LintCategory.OPTIONS.option, "true"); options.remove(XLINT_CUSTOM.text + LintCategory.OPTIONS.option); start_msec = now(); try { initProcessAnnotations(processors); // These method calls must be chained to avoid memory leaks delegateCompiler = processAnnotations( enterTrees(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))), classnames); delegateCompiler.compile2(); delegateCompiler.close(); elapsed_msec = delegateCompiler.elapsed_msec; } catch (Abort ex) { if (devVerbose) ex.printStackTrace(System.err); } finally { if (procEnvImpl != null) procEnvImpl.close(); } }
public NativeHeaderTask getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes) { return new JavahTask(out, fileManager, diagnosticListener, options, classes); }
void testNativeHeaderOutput() throws IOException { String test = "testNativeHeaderOutput"; System.err.println("test: " + test); for (int i = 1; i <= 5; i++) { File classes = createDir(test + "/" + i + "/classes"); File headers = createDir(test + "/" + i + "/hdrs"); List<String> options; switch (i) { default: options = getOptions("-d", classes.getPath(), "-h", headers.getPath()); break; case 3: setLocation(NATIVE_HEADER_OUTPUT, headers); options = getOptions("-d", classes.getPath()); break; } List<JavaFileObject> sources = getSources("class C" + i + " { native void m(); }"); callTask(options, sources); checkPath(NATIVE_HEADER_OUTPUT, Mode.EQUALS, headers); checkFile(NATIVE_HEADER_OUTPUT, "C" + i + ".h"); } tested.add(StandardLocation.NATIVE_HEADER_OUTPUT); System.err.println(); }
void run(List<JavaFileObject> sources) throws Exception { javax.tools.DiagnosticListener<JavaFileObject> dc = (diagnostic) -> { if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { throw new AssertionError("unexpected diagnostic: " + diagnostic.getMessage(Locale.getDefault())); } }; JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); try (StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null)) { JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, sources); ct.analyze(); } }
private void parse(JavaFileObject fo, ListBuffer<JCCompilationUnit> trees, boolean trace) { if (uniquefiles.add(fo)) { // ignore duplicates if (trace) docenv.notice("main.Loading_source_file", fo.getName()); trees.append(parse(fo)); } }
private List<PackageSymbol> getPackageInfoFiles(List<? extends JCCompilationUnit> units) { List<PackageSymbol> packages = List.nil(); for (JCCompilationUnit unit : units) { if (isPkgInfo(unit.sourcefile, JavaFileObject.Kind.SOURCE)) { packages = packages.prepend(unit.packge); } } return packages.reverse(); }
void run() throws Exception { List<File> files = new ArrayList<File>(); File testSrc = new File(System.getProperty("test.src")); for (File f: testSrc.listFiles()) { if (f.isFile() && f.getName().endsWith(".java")) files.add(f); } JavacTool javac = JavacTool.create(); try (StandardJavaFileManager fm = javac.getStandardFileManager(null, null, null)) { Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files); JavacTask t = javac.getTask(null, fm, null, null, null, fos); DocTrees trees = DocTrees.instance(t); Iterable<? extends CompilationUnitTree> units = t.parse(); Set<DocTree.Kind> found = EnumSet.noneOf(DocTree.Kind.class); DeclScanner ds = new DeclScanner(trees, found); for (CompilationUnitTree unit: units) { ds.scan(unit, null); } for (DocTree.Kind k: DocTree.Kind.values()) { if (!found.contains(k) && k != DocTree.Kind.OTHER) error("not found: " + k); } if (errors > 0) throw new Exception(errors + " errors occurred"); } }
/** * Implement policy to choose to derive information from a source * file or a class file when both are present. May be overridden * by subclasses. */ protected JavaFileObject preferredFileObject(JavaFileObject a, JavaFileObject b) { if (preferSource) return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b; else { long adate = a.getLastModified(); long bdate = b.getLastModified(); // 6449326: policy for bad lastModifiedTime in ClassReader //assert adate >= 0 && bdate >= 0; return (adate > bdate) ? a : b; } }
/** * Override extraFileActions to check for package documentation */ @Override protected void extraFileActions(PackageSymbol pack, JavaFileObject fo) { if (fo.isNameCompatible("package", JavaFileObject.Kind.HTML)) { pack.sourcefile = fo; } }
public String[] divineClassName(JavaFileObject jfo) { if (misplacedSource2FQNs.isEmpty()) { return null; } List<String> result = misplacedSource2FQNs.get(jfo); if (result != null) { return result.toArray(new String[result.size()]); } return null; }
@Override public String inferBinaryName(Location location, JavaFileObject file) { if (hasLocation(location)) { return ((InferableJavaFileObject)file).inferBinaryName(); } return null; }
@Test public void processSuccessfulWhereTypeResolvedInInheritanceHierarchy() throws Exception { final JavaFileObject source1 = JavaFileObjects.forResource( "input/com/example/type_params/AbstractModel.java" ); final JavaFileObject source2 = JavaFileObjects.forResource( "input/com/example/type_params/MiddleModel.java" ); final JavaFileObject source3 = JavaFileObjects.forResource( "input/com/example/type_params/ConcreteModel.java" ); final String output1 = "expected/com/example/type_params/Arez_ConcreteModel.java"; assertSuccessfulCompile( Arrays.asList( source1, source2, source3 ), Collections.singletonList( output1 ) ); }
public JdkCompileTask(JdkCompilerClassLoader classLoader, Iterable<String> options){ compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { throw new IllegalStateException("Cannot find the system Java compiler. " + "Check that your class path includes tools.jar"); } this.classLoader = classLoader; ClassLoader loader = classLoader.getParent(); diagnostics = new DiagnosticCollector<JavaFileObject>(); final StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null); if (loader instanceof URLClassLoader && (!loader.getClass().getName().equalsIgnoreCase("sun.misc.Launcher$AppClassLoader"))) { try { @SuppressWarnings("resource") URLClassLoader urlClassLoader = (URLClassLoader) loader; List<File> path = new ArrayList<File>(); for (URL url : urlClassLoader.getURLs()) { File file = new File(url.getFile()); path.add(file); } fileManager.setLocation(StandardLocation.CLASS_PATH, path); } catch (IOException e) { throw new RuntimeException(e); } } javaFileManager = new JavaFileManagerImpl(fileManager, classLoader); this.options = new ArrayList<String>(); if (options != null) { // make a save copy of input options for (String option : options) { this.options.add(option); } } }
private void assertFailedCompileResource( @Nonnull final String inputResource, @Nonnull final String errorMessageFragment ) throws Exception { final JavaFileObject source = fixture( inputResource ); assert_().about( JavaSourceSubjectFactory.javaSource() ). that( source ). processedWith( new ReactProcessor(), new ArezProcessor() ). failsToCompile(). withErrorContaining( errorMessageFragment ); }
@Test public void typeMustBeDrawable() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.BindDrawable;\n" + "public class Test {\n" + " @BindDrawable(1) String one;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("@BindDrawable field type must be 'Drawable'. (test.Test.one)") .in(source).onLine(4); }