public CompileTester.ChainingClause<SingleFileClause> onLine(long lineNumber) { try { lineClause.onLine(lineNumber); return new CompileTester.ChainingClause<SingleFileClause>() { @Override public SingleFileClause and() { return SingleFileClause.this; } }; } catch (AssertionError e) { failWithoutActual(simpleFact(e.getMessage())); } return null; }
@Test public void failsIfParameterNotView() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnClick;\n" + "public class Test {\n" + " @OnClick(1)\n" + " public void doStuff(String thing) {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("" + "Unable to match @OnClick method arguments. (test.Test.doStuff)\n" + " \n" + " Parameter #1: java.lang.String\n" + " did not match any listener parameters\n" + " \n" + " Methods may have up to 1 parameter(s):\n" + " \n" + " android.view.View\n" + " \n" + " These may be listed in any order but will be searched for from top to bottom.") .in(source).onLine(5); }
@Test public void failsOptionalRootViewBinding() throws Exception { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.content.Context;\n" + "import android.view.View;\n" + "import butterknife.OnClick;\n" + "import butterknife.Optional;\n" + "public class Test extends View {\n" + " @Optional @OnClick void doStuff() {}\n" + " public Test(Context context) {\n" + " super(context);\n" + " }\n" + "}" ); assertAbout(javaSource()) .that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "ID-free binding must not be annotated with @Optional. (test.Test.doStuff)") .in(source) .onLine(7); }
@Test public void failsIfMoreThanOneParameter() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.view.View;\n" + "import butterknife.OnClick;\n" + "public class Test {\n" + " @OnClick(1)\n" + " public void doStuff(View thing, View otherThing) {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@OnClick methods can have at most 1 parameter(s). (test.Test.doStuff)") .in(source).onLine(6); }
@Test public void failsIfMissingReturnType() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnLongClick;\n" + "public class Test {\n" + " @OnLongClick(1)\n" + " public void doStuff() {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@OnLongClick methods must have a 'boolean' return type. (test.Test.doStuff)") .in(source).onLine(5); } }
@Test public void failsIfInPrivateClass() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.view.View;\n" + "import butterknife.BindView;\n" + "public class Test {\n" + " private static class Inner {\n" + " @BindView(1) View thing;\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindView fields may not be contained in private classes. (test.Test.Inner.thing)") .in(source).onLine(5); }
@Test public void failsIfHasDuplicateIds() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnClick;\n" + "public class Test {\n" + " @OnClick({1, 2, 3, 1})\n" + " void doStuff() {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@OnClick annotation for method contains duplicate ID 1. (test.Test.doStuff)") .in(source).onLine(5); } }
@Test public void styleMustBeValid() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.graphics.Typeface;\n" + "import butterknife.BindFont;\n" + "public class Test {\n" + " @BindFont(value = 1, style = 5) Typeface one;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindFont style must be NORMAL, BOLD, ITALIC, or BOLD_ITALIC. (test.Test.one)") .in(source).onLine(5); } }
@Test public void duplicateBindingFails() throws Exception { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.view.View;\n" + "import butterknife.BindView;\n" + "public class Test {\n" + " @BindView(1) View thing1;\n" + " @BindView(1) View thing2;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "Attempt to use @BindView for an already bound ID 1 on 'thing1'. (test.Test.thing2)") .in(source).onLine(6); }
@Test public void typeMustBeSupported() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.BindArray;\n" + "public class Test {\n" + " @BindArray(1) String one;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindArray field type must be one of: String[], int[], CharSequence[], " + "android.content.res.TypedArray. (test.Test.one)") .in(source).onLine(4); } }
@Test public void failsInJavaPackage() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package java.test;\n" + "import android.view.View;\n" + "import butterknife.BindView;\n" + "public class Test {\n" + " @BindView(1) View thing;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindView-annotated class incorrectly in Java framework package. (java.test.Test)") .in(source).onLine(5); }
@Test public void failsIfPrivateMethod() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnClick;\n" + "public class Test {\n" + " @OnClick(1)\n" + " private void doStuff() {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("@OnClick methods must not be private or static. (test.Test.doStuff)") .in(source).onLine(5); }
@Test public void failsIfInInterface() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.view.View;\n" + "import butterknife.BindView;\n" + "public interface Test {\n" + " @BindView(1) View thing = null;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindView fields may only be contained in classes. (test.Test.thing)") .in(source).onLine(4); }
@Test public void failsInAndroidPackage() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package android.test;\n" + "import android.view.View;\n" + "import butterknife.BindView;\n" + "public class Test {\n" + " @BindView(1) View thing;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindView-annotated class incorrectly in Android framework package. (android.test.Test)") .in(source).onLine(5); }
@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); }
@Test public void failsIfGenericNotView() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.BindViews;\n" + "import java.util.List;\n" + "public class Test {\n" + " @BindViews(1) List<String> thing;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@BindViews List or array type must extend from View or be an interface. (test.Test.thing)") .in(source).onLine(5); }
@Test public void failsIfInInterface() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnClick;\n" + "public interface Test {\n" + " @OnClick(1)\n" + " void doStuff();\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining( "@OnClick methods may only be contained in classes. (test.Test.doStuff)") .in(source).onLine(3); }
@Test public void failsIfStatic() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import butterknife.OnClick;\n" + "public class Test {\n" + " @OnClick(1)\n" + " public static void doStuff() {\n" + " }\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("@OnClick methods must not be private or static. (test.Test.doStuff)") .in(source).onLine(5); }
@Test public void failsIfContainsDuplicateIds() throws Exception { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.view.View;\n" + "import butterknife.BindViews;\n" + "import java.util.List;\n" + "public class Test {\n" + " @BindViews({1, 1}) List<View> thing;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("@BindViews annotation contains duplicate ID 1. (test.Test.thing)") .in(source).onLine(6); }
@Test public void failsIfNoIds() { JavaFileObject source = JavaFileObjects.forSourceString("test.Test", "" + "package test;\n" + "import android.view.View;\n" + "import butterknife.BindViews;\n" + "import java.util.List;\n" + "public class Test {\n" + " @BindViews({}) List<View> thing;\n" + "}" ); assertAbout(javaSource()).that(source) .processedWith(new ButterKnifeProcessor()) .failsToCompile() .withErrorContaining("@BindViews must specify at least one ID. (test.Test.thing)") .in(source).onLine(6); }