metalava: Avoid eagerly loading the world

Avoids eagerly parsing the world:

- In Java (and Kotlin), import statements can only occur
  in the file's import list, so limit the visitor checking import
  statements to that.
- Code blocks and doc comments are expensive to parse, but most don't
  contain anything of interest to metalava. Don't descend into them
  when checking for syntax errors (which for code blocks, javac will
  catch anyways, and for doc comments aren't possible in the first
  place).


Benchmarks:
 - touch $HOST_BIN/metalava && time make droid
   - Before:  4m43s
   - After:   4m08s (14% speedup)

 - module-lib-api-stubs-docs-non-updatable
   - Before:  1m40s
   - After:   1m27s (15% speedup)


Test: make droid
Test: ./gradlew check
Change-Id: Ia7657ca24f384f4ed365ac06e9eed3bf133f1bf2
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
index 74b35d4..f782d27 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiBasedCodebase.kt
@@ -40,6 +40,7 @@
 import com.intellij.psi.PsiClass
 import com.intellij.psi.PsiClassOwner
 import com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiCodeBlock
 import com.intellij.psi.PsiElement
 import com.intellij.psi.PsiErrorElement
 import com.intellij.psi.PsiField
@@ -169,7 +170,9 @@
         for (psiFile in psiFiles.asSequence().distinct()) {
             tick() // show progress
 
-            psiFile.accept(object : JavaRecursiveElementVisitor() {
+            // Visiting psiFile directly would eagerly load the entire file even though we only need
+            // the importList here.
+            (psiFile as? PsiJavaFile)?.importList?.accept(object : JavaRecursiveElementVisitor() {
                 override fun visitImportStatement(element: PsiImportStatement) {
                     super.visitImportStatement(element)
                     if (element.resolve() == null) {
@@ -227,6 +230,15 @@
                                     "Syntax error: `${element.errorDescription}`"
                                 )
                             }
+
+                            override fun visitCodeBlock(block: PsiCodeBlock?) {
+                                // Ignore to avoid eagerly parsing all method bodies.
+                            }
+
+                            override fun visitDocComment(comment: PsiDocComment?) {
+                                // Ignore to avoid eagerly parsing all doc comments.
+                                // Doc comments cannot contain error elements.
+                            }
                         })
 
                         topLevelClassesFromSource += createClass(psiClass)