[KeepAnno] Fill out more sections in user guide

Change-Id: Ia26dc1cfb4b90462fd0d5b6e1a445d4d2b5c3e20
diff --git a/doc/keepanno-guide.md b/doc/keepanno-guide.md
index 7b16d03..75d6b24 100644
--- a/doc/keepanno-guide.md
+++ b/doc/keepanno-guide.md
@@ -110,14 +110,66 @@
 
 ## Annotating code used by reflection (or via JNI)<a id="used-by-reflection"></a>
 
+TODO
+
 
 ## Annotating APIs<a id="apis"></a>
 
+TODO
+
 
 ## Migrating rules to annotations<a id="migrating-rules"></a>
 
+There is no automatic migration of keep rules. Keep annotations often invert the
+direction and rules have no indication of where the reflection is taking
+place or why. Thus, migrating existing keep rules requires user involvement.
+Keep rules also have a tendency to be very general, matching a large
+number of classes and members. Often the rules are much too broad and are
+keeping more than needed which will have a negative impact on the shrinkers
+ability to reduce size.
+
+First step in converting a rule is to determine the purpose of the rule. Is it
+API surface or is it reflection? Note that a very general rule may be covering
+several use cases and even a mix of both reflection and API usage.
+
+When migrating it is preferable to use [@UsesReflection](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/UsesReflection.html) instead of
+[@UsedByReflection](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/UsedByReflection.html). For very general rules it might not be easy or worth it to
+migrate without completely reevaluating the rule. If one still wants to replace
+it by annotations, the general [@KeepEdge](https://storage.googleapis.com/r8-releases/raw/main/docs/keepanno/javadoc/com/android/tools/r8/keepanno/annotations/KeepEdge.html) can be used to define a context
+independent keep annotation.
+
+For example, to keep all main methods in the program one could use:
+
+
+```
+@KeepEdge(
+    consequences = {
+      @KeepTarget(
+          kind = KeepItemKind.CLASS_AND_MEMBERS,
+          methodName = "main",
+          methodReturnType = "void",
+          methodParameters = {"java.lang.String[]"},
+          methodAccess = {MethodAccessFlags.PUBLIC, MethodAccessFlags.STATIC})
+    })
+public class SomeClass {
+  // ...
+}
+```
+
+
 
 ## My use case is not covered!<a id="other-uses"></a>
 
+The annotation library is in active development and not all use cases are
+described here or supported. Reach out to the R8 team by
+[filing a new issue in our tracker](https://issuetracker.google.com/issues/new?component=326788).
+Describe your use case and we will look at how best to support it.
+
 
 ## Troubleshooting<a id="troubleshooting"></a>
+
+If an annotation is not working as expected it may be helpful to inspect the
+rules that have been extracted for the annotation. This can be done by
+inspecting the configuration output of the shrinker. For R8 you can use the
+command line argument `--pg-conf-output <path>` to emit the full configuration
+used by R8.
diff --git a/doc/keepanno-guide.template.md b/doc/keepanno-guide.template.md
index 2002802..cfa98e2 100644
--- a/doc/keepanno-guide.template.md
+++ b/doc/keepanno-guide.template.md
@@ -72,14 +72,51 @@
 
 ## [Annotating code used by reflection (or via JNI)](used-by-reflection)
 
+TODO
+
 
 ## [Annotating APIs](apis)
 
+TODO
+
 
 ## [Migrating rules to annotations](migrating-rules)
 
+There is no automatic migration of keep rules. Keep annotations often invert the
+direction and rules have no indication of where the reflection is taking
+place or why. Thus, migrating existing keep rules requires user involvement.
+Keep rules also have a tendency to be very general, matching a large
+number of classes and members. Often the rules are much too broad and are
+keeping more than needed which will have a negative impact on the shrinkers
+ability to reduce size.
+
+First step in converting a rule is to determine the purpose of the rule. Is it
+API surface or is it reflection? Note that a very general rule may be covering
+several use cases and even a mix of both reflection and API usage.
+
+When migrating it is preferable to use `@UsesReflection` instead of
+`@UsedByReflection`. For very general rules it might not be easy or worth it to
+migrate without completely reevaluating the rule. If one still wants to replace
+it by annotations, the general `@KeepEdge` can be used to define a context
+independent keep annotation.
+
+[[[INCLUDE DOC:KeepMainMethods]]]
+
+[[[INCLUDE CODE:KeepMainMethods]]]
+
 
 ## [My use case is not covered!](other-uses)
 
+The annotation library is in active development and not all use cases are
+described here or supported. Reach out to the R8 team by
+[filing a new issue in our tracker](https://issuetracker.google.com/issues/new?component=326788).
+Describe your use case and we will look at how best to support it.
+
 
 ## [Troubleshooting](troubleshooting)
+
+If an annotation is not working as expected it may be helpful to inspect the
+rules that have been extracted for the annotation. This can be done by
+inspecting the configuration output of the shrinker. For R8 you can use the
+command line argument `--pg-conf-output <path>` to emit the full configuration
+used by R8.
diff --git a/src/test/java/com/android/tools/r8/keepanno/doctests/MainMethodsDocumentationTest.java b/src/test/java/com/android/tools/r8/keepanno/doctests/MainMethodsDocumentationTest.java
new file mode 100644
index 0000000..fdbe498
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/doctests/MainMethodsDocumentationTest.java
@@ -0,0 +1,86 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.keepanno.doctests;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.keepanno.annotations.KeepEdge;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
+import com.android.tools.r8.keepanno.annotations.MethodAccessFlags;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MainMethodsDocumentationTest extends TestBase {
+
+  static final String EXPECTED = StringUtils.lines("Hello I'm kept!");
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withDefaultRuntimes().withApiLevel(AndroidApiLevel.B).build();
+  }
+
+  public MainMethodsDocumentationTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void testReference() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(getInputClasses())
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(EXPECTED);
+  }
+
+  @Test
+  public void testWithRuleExtraction() throws Exception {
+    testForR8(parameters.getBackend())
+        .enableExperimentalKeepAnnotations()
+        .addProgramClasses(getInputClasses())
+        .setMinApi(parameters)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(EXPECTED);
+  }
+
+  public List<Class<?>> getInputClasses() {
+    return ImmutableList.of(TestClass.class, SomeClass.class);
+  }
+
+  /* INCLUDE DOC: KeepMainMethods
+  For example, to keep all main methods in the program one could use:
+  INCLUDE END */
+
+  static
+  // INCLUDE CODE: KeepMainMethods
+  @KeepEdge(
+      consequences = {
+        @KeepTarget(
+            kind = KeepItemKind.CLASS_AND_MEMBERS,
+            methodName = "main",
+            methodReturnType = "void",
+            methodParameters = {"java.lang.String[]"},
+            methodAccess = {MethodAccessFlags.PUBLIC, MethodAccessFlags.STATIC})
+      })
+  public class SomeClass {
+    // ...
+  }
+
+  // INCLUDE END
+
+  static class TestClass {
+
+    public static void main(String[] args) throws Exception {
+      System.out.println("Hello I'm kept!");
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java
index 518d613..6fd05eb 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepAnnoMarkdownGenerator.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.keepanno.annotations.UsedByNative;
 import com.android.tools.r8.keepanno.annotations.UsedByReflection;
 import com.android.tools.r8.keepanno.annotations.UsesReflection;
+import com.android.tools.r8.keepanno.doctests.MainMethodsDocumentationTest;
 import com.android.tools.r8.keepanno.doctests.UsesReflectionDocumentationTest;
 import com.android.tools.r8.keepanno.utils.KeepItemAnnotationGenerator.Generator;
 import com.android.tools.r8.utils.FileUtils;
@@ -76,7 +77,8 @@
             UsedByReflection.class,
             UsedByNative.class,
             KeepForApi.class);
-    populateCodeAndDocReplacements(UsesReflectionDocumentationTest.class);
+    populateCodeAndDocReplacements(
+        UsesReflectionDocumentationTest.class, MainMethodsDocumentationTest.class);
   }
 
   private Map<String, String> getTypeLinkReplacements(Class<?>... classes) {