Use net.ltgt.apt gradle plugin to enable annotation processing.
diff --git a/build.gradle b/build.gradle
index d59c9fe..c0d8cd7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,3 +1,16 @@
+buildscript {
+    repositories { jcenter() }
+
+    dependencies {
+        classpath 'com.netflix.nebula:gradle-aggregate-javadocs-plugin:2.2.+'
+        classpath 'ch.raffael.pegdown-doclet:pegdown-doclet:1.3'
+    }
+}
+
+plugins {
+    id "net.ltgt.apt" version "0.12" // automatic annotation processing
+}
+
 allprojects {
     repositories {
         mavenLocal()
@@ -8,12 +21,13 @@
     version = thisVersion
 }
 
-buildscript {
-    repositories { jcenter() }
+apply plugin: 'idea'
+apply plugin: 'net.ltgt.apt-idea'
 
-    dependencies {
-        classpath 'com.netflix.nebula:gradle-aggregate-javadocs-plugin:2.2.+'
-        classpath 'ch.raffael.pegdown-doclet:pegdown-doclet:1.3'
+idea {
+    project {
+        // experimental: whether annotation processing will be configured in the IDE; only actually used with the 'idea' task.
+        configureAnnotationProcessing = true
     }
 }
 
diff --git a/buildSrc/src/main/groovy/ShadowsPlugin.groovy b/buildSrc/src/main/groovy/ShadowsPlugin.groovy
index 7b61e64..46c6c7c 100644
--- a/buildSrc/src/main/groovy/ShadowsPlugin.groovy
+++ b/buildSrc/src/main/groovy/ShadowsPlugin.groovy
@@ -7,50 +7,37 @@
 class ShadowsPlugin implements Plugin<Project> {
     @Override
     void apply(Project project) {
+        project.apply plugin: "idea"
+        project.apply plugin: "net.ltgt.apt-idea"
+
         project.extensions.create("shadows", ShadowsPluginExtension)
 
-        project.configurations {
-            robolectricProcessor
-        }
-
         project.dependencies {
-            robolectricProcessor project.project(":processor")
-        }
-
-        def generatedSourcesDir = "${project.buildDir}/generated-shadows"
-
-        project.sourceSets.main.java.srcDirs += project.file(generatedSourcesDir)
-
-        project.task("generateShadowProvider", type: JavaCompile, description: "Generate Shadows.shadowOf()s class") { task ->
-            classpath = project.configurations.robolectricProcessor
-            source = project.sourceSets.main.java
-            destinationDir = project.file(generatedSourcesDir)
-
-            doFirst {
-                logger.info "Generating Shadows.java for ${project.name}…"
-
-                // reset our classpath at the last minute, since other plugins might mutate
-                //   compileJava's classpath and we want to pick up any changes…
-                classpath = project.tasks['compileJava'].classpath + project.configurations.robolectricProcessor
-
-                options.compilerArgs.addAll(
-                        "-proc:only",
-                        "-processor", "org.robolectric.annotation.processing.RobolectricProcessor",
-                        "-Aorg.robolectric.annotation.processing.shadowPackage=${project.shadows.packageName}"
-                )
-            }
-
-            doLast {
-                def src = project.file("$generatedSourcesDir/META-INF/services/org.robolectric.internal.ShadowProvider")
-                def dest = project.file("${project.buildDir}/resources/main/META-INF/services/org.robolectric.internal.ShadowProvider")
-
-                GFileUtils.mkdirs(dest.getParentFile());
-                GFileUtils.copyFile(src, dest);
-            }
+            apt project.project(":processor")
         }
 
         def compileJavaTask = project.tasks["compileJava"]
-        compileJavaTask.dependsOn("generateShadowProvider")
+        compileJavaTask.doFirst {
+            options.compilerArgs.add("-Aorg.robolectric.annotation.processing.shadowPackage=${project.shadows.packageName}")
+        }
+
+        project.idea {
+            module {
+                apt {
+                    // whether generated sources dirs are added as generated sources root
+                    addGeneratedSourcesDirs = true
+                    // whether the apt and testApt dependencies are added as module dependencies
+                    addAptDependencies = true
+
+                    // The following are mostly internal details; you shouldn't ever need to configure them.
+                    // whether the compileOnly and testCompileOnly dependencies are added as module dependencies
+                    addCompileOnlyDependencies = false // defaults to true in Gradle < 2.12
+                    // the dependency scope used for apt and/or compileOnly dependencies (when enabled above)
+                    mainDependenciesScope = "PROVIDED" // defaults to "COMPILE" in Gradle < 3.4, or when using the Gradle integration in IntelliJ IDEA
+                }
+            }
+
+        }
     }
 
     static class ShadowsPluginExtension {
diff --git a/processor/build.gradle b/processor/build.gradle
index 03de51a..5ee7454 100644
--- a/processor/build.gradle
+++ b/processor/build.gradle
@@ -6,6 +6,10 @@
         deploy: true
 ).apply(project)
 
+// Disable annotation processor for tests
+compileTestJava {
+    options.compilerArgs.add("-proc:none")
+}
 
 dependencies {
     // Project dependencies
diff --git a/processor/src/main/java/org/robolectric/annotation/processing/RobolectricProcessor.java b/processor/src/main/java/org/robolectric/annotation/processing/RobolectricProcessor.java
index 0b0fd48..95882bd 100644
--- a/processor/src/main/java/org/robolectric/annotation/processing/RobolectricProcessor.java
+++ b/processor/src/main/java/org/robolectric/annotation/processing/RobolectricProcessor.java
@@ -1,5 +1,6 @@
 package org.robolectric.annotation.processing;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -57,7 +58,8 @@
    * @param options simulated options that would ordinarily
    *                be passed in the {@link ProcessingEnvironment}.
    */
-  RobolectricProcessor(Map<String, String> options) {
+  @VisibleForTesting
+  public RobolectricProcessor(Map<String, String> options) {
     processOptions(options);
   }
 
@@ -108,6 +110,10 @@
       this.shadowPackage = options.get(PACKAGE_OPT);
       this.shouldInstrumentPackages =
           !"false".equalsIgnoreCase(options.get(SHOULD_INSTRUMENT_PKG_OPT));
+
+      if (this.shadowPackage == null) {
+        throw new IllegalArgumentException("no package specified for " + PACKAGE_OPT);
+      }
     }
   }
 
diff --git a/processor/src/test/java/org/robolectric/annotation/processing/RobolectricProcessorTest.java b/processor/src/test/java/org/robolectric/annotation/processing/RobolectricProcessorTest.java
index 33501a2..6b7a772 100644
--- a/processor/src/test/java/org/robolectric/annotation/processing/RobolectricProcessorTest.java
+++ b/processor/src/test/java/org/robolectric/annotation/processing/RobolectricProcessorTest.java
@@ -32,21 +32,19 @@
 
 @RunWith(JUnit4.class)
 public class RobolectricProcessorTest {
-  private static final Map<String,String> DEFAULT_OPTS = new HashMap<>();
-
-  static {
-    DEFAULT_OPTS.put(PACKAGE_OPT, "org.robolectric");
-  }
+  public static final Map<String,String> DEFAULT_OPTS = new HashMap<String, String>() {{
+    put(PACKAGE_OPT, "org.robolectric");
+  }};
 
   @Test
   public void robolectricProcessor_supportsPackageOption() {
-    assertThat(new RobolectricProcessor().getSupportedOptions()).contains(PACKAGE_OPT);
+    assertThat(new RobolectricProcessor(DEFAULT_OPTS).getSupportedOptions()).contains(PACKAGE_OPT);
   }
 
   @Test
   public void robolectricProcessor_supportsShouldInstrumentPackageOption() {
     assertThat(
-        new RobolectricProcessor().getSupportedOptions()).contains(SHOULD_INSTRUMENT_PKG_OPT);
+        new RobolectricProcessor(DEFAULT_OPTS).getSupportedOptions()).contains(SHOULD_INSTRUMENT_PKG_OPT);
   }
 
   @Test
@@ -57,7 +55,7 @@
           SHADOW_PROVIDER_SOURCE,
           SHADOW_EXTRACTOR_SOURCE,
           forSourceString("HelloWorld", "final class HelloWorld {}")))
-      .processedWith(new RobolectricProcessor())
+      .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
       .compilesWithoutError();
     //.and().generatesNoSources(); Should add this assertion onces
     // it becomes available in compile-testing
@@ -190,7 +188,7 @@
           SHADOW_PROVIDER_SOURCE,
           SHADOW_EXTRACTOR_SOURCE,
           forResource("org/robolectric/annotation/TestWithUnrecognizedAnnotation.java")))
-      .processedWith(new RobolectricProcessor())
+      .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
       .compilesWithoutError();
   }
 
@@ -198,7 +196,7 @@
   public void shouldGracefullyHandleNoAnythingClass_withNoRealObject() {
     assertAbout(javaSource())
       .that(forResource("org/robolectric/annotation/processing/shadows/ShadowAnything.java"))
-      .processedWith(new RobolectricProcessor())
+      .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
       .failsToCompile();
   }
 
@@ -209,7 +207,7 @@
           SHADOW_PROVIDER_SOURCE,
           SHADOW_EXTRACTOR_SOURCE,
           forResource("org/robolectric/annotation/processing/shadows/ShadowRealObjectWithCorrectAnything.java")))
-      .processedWith(new RobolectricProcessor())
+      .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
       .failsToCompile();
   }
 
@@ -253,7 +251,7 @@
         .that(ImmutableList.of(
             ROBO_SOURCE,
             forResource("org/robolectric/annotation/processing/shadows/DocumentedObjectShadow.java")))
-        .processedWith(new RobolectricProcessor())
+        .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
         .compilesWithoutError();
     JsonParser jsonParser = new JsonParser();
     String jsonFile = "build/docs/json/org.robolectric.Robolectric.DocumentedObject.json";
diff --git a/processor/src/test/java/org/robolectric/annotation/processing/validator/RealObjectValidatorTest.java b/processor/src/test/java/org/robolectric/annotation/processing/validator/RealObjectValidatorTest.java
index a37796b..38dd39f 100644
--- a/processor/src/test/java/org/robolectric/annotation/processing/validator/RealObjectValidatorTest.java
+++ b/processor/src/test/java/org/robolectric/annotation/processing/validator/RealObjectValidatorTest.java
@@ -3,6 +3,7 @@
 import static com.google.common.truth.Truth.assertAbout;
 import static com.google.testing.compile.JavaFileObjects.forResource;
 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
+import static org.robolectric.annotation.processing.RobolectricProcessorTest.DEFAULT_OPTS;
 import static org.robolectric.annotation.processing.validator.SingleClassSubject.singleClass;
 import static org.robolectric.annotation.processing.validator.Utils.SHADOW_EXTRACTOR_SOURCE;
 
@@ -102,7 +103,7 @@
     .that(ImmutableList.of(
         SHADOW_EXTRACTOR_SOURCE,
         forResource("org/robolectric/annotation/processing/shadows/ShadowRealObjectWithCorrectType.java")))
-    .processedWith(new RobolectricProcessor())
+    .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
       .compilesWithoutError();
   }
 
@@ -120,7 +121,7 @@
       .that(ImmutableList.of(
           SHADOW_EXTRACTOR_SOURCE,
           forResource("org/robolectric/annotation/processing/shadows/ShadowRealObjectWithCorrectClassName.java")))
-      .processedWith(new RobolectricProcessor())
+      .processedWith(new RobolectricProcessor(DEFAULT_OPTS))
       .compilesWithoutError();
   }
   
diff --git a/processor/src/test/java/org/robolectric/annotation/processing/validator/SingleClassSubject.java b/processor/src/test/java/org/robolectric/annotation/processing/validator/SingleClassSubject.java
index 92a024b..e170612 100644
--- a/processor/src/test/java/org/robolectric/annotation/processing/validator/SingleClassSubject.java
+++ b/processor/src/test/java/org/robolectric/annotation/processing/validator/SingleClassSubject.java
@@ -2,6 +2,7 @@
 
 import static com.google.common.truth.Truth.assertAbout;
 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;
+import static org.robolectric.annotation.processing.RobolectricProcessorTest.DEFAULT_OPTS;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.truth.FailureStrategy;
@@ -37,7 +38,7 @@
     source = JavaFileObjects.forResource(Utils.toResourcePath(subject));
     tester = assertAbout(javaSources())
       .that(ImmutableList.of(source, Utils.ROBO_SOURCE, Utils.SHADOW_EXTRACTOR_SOURCE))
-      .processedWith(new RobolectricProcessor());
+      .processedWith(new RobolectricProcessor(DEFAULT_OPTS));
   }
 
   public SuccessfulCompilationClause compilesWithoutError() {