// Path: lang/java/src/main/java/com/google/devtools/build/bfg/ReferencedClassesParser.java
// @AutoValue
// public abstract static class ImportDeclaration {
//   public abstract QualifiedName name();
// 
//   public abstract boolean isStatic();
// 
//   public static ImportDeclaration create(QualifiedName qname, boolean isStatic) {
//     return new AutoValue_ReferencedClassesParser_ImportDeclaration(qname, isStatic);
//   }
// }
// 
// Path: lang/java/src/main/java/com/google/devtools/build/bfg/ReferencedClassesParser.java
// @AutoValue
// public abstract static class Metadata {
//   static final Metadata EMPTY = create(0, 0, false);
// 
//   /** Line where a simple/qualified name starts. */
//   public abstract int line();
// 
//   /** Column where a simple/qualified name starts. */
//   public abstract int column();
// 
//   public abstract boolean isMethod();
// 
//   public static Metadata create(int line, int column, boolean isMethod) {
//     return new AutoValue_ReferencedClassesParser_Metadata(line, column, isMethod);
//   }
// }
// 
// Path: lang/java/src/main/java/com/google/devtools/build/bfg/ReferencedClassesParser.java
// @AutoValue
// public abstract static class QualifiedName {
//   public static final Pattern CLASS_NAME_PATTERN = Pattern.compile("^[A-Z][a-zA-Z0-9_$]*$");
// 
//   public static QualifiedName create(String value, Metadata metadata) {
//     return new AutoValue_ReferencedClassesParser_QualifiedName(value, metadata);
//   }
// 
//   public abstract String value();
// 
//   public abstract Metadata metadata();
// 
//   @Memoized
//   public ImmutableList<String> parts() {
//     return ImmutableList.copyOf(DOT_SPLITTER.split(value()));
//   }
// 
//   private static int findTopLevelName(List<String> parts) {
//     for (int i = 0; i < parts.size(); i++) {
//       String part = parts.get(i);
//       if (CLASS_NAME_PATTERN.matcher(part).matches()) {
//         // if i == 0, 's' starts with a capitalized-camel name,
//         // e.g., "MobileLocalDetailsJslayoutProto".
//         return i > 0 ? i : -1;
//       }
//       if (isLowerCase(part)) {
//         continue;
//       }
//       return -1;
//     }
//     return -1;
//   }
// 
//   /**
//    * "java.util.Map" => "java.util.Map" "java.util.Map.Entry" => "java.util.Map"
//    * "org.mockito.Mockito.mock" => "org.mockito.Mockito"
//    */
//   public QualifiedName getTopLevelQualifiedName() {
//     return create(DOT_JOINER.join(parts().subList(0, findTopLevelName(parts()) + 1)), metadata());
//   }
// }


import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.truth.Truth.assertThat;
import static java.util.stream.Collectors.toMap;
import static org.junit.Assert.assertTrue;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.google.devtools.build.bfg.ReferencedClassesParser.ImportDeclaration;
import com.google.devtools.build.bfg.ReferencedClassesParser.Metadata;
import com.google.devtools.build.bfg.ReferencedClassesParser.QualifiedName;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
            "class A {", "  void foo() throws IOException, java.io.FileNotFoundException {}", "}");
    ReferencedClassesParser parser = parse(source);
    assertThat(parser.symbols.keySet())
        .containsExactly("IOException", "java.io.FileNotFoundException");
  }

  @Test
  public void allCapsFieldNamesAreNotConsideredClassNames() {
    String source =
        joiner.join(
            "class A {",
            "  FormattingLogger LOG = null;",
            "  void foo() {",
            "    LOG.warning();",
            "  }",
            "}");
    ReferencedClassesParser parser = parse(source);
    assertThat(parser.symbols.keySet()).containsExactly("FormattingLogger");
  }

  @Test
  public void dontReportJavaLangInnerClasses() {
    ReferencedClassesParser parser = parse("class A extends Thread.UncaughtExceptionHandler { }");
    assertThat(parser.symbols.keySet()).doesNotContain("Thread");
    assertThat(parser.symbols.keySet()).isEmpty();
  }

  @Test
  public void dontReportJavaLangImports() {
    ReferencedClassesParser parser = parse("import static java.lang.String.format;");
// Path: lang/java/src/main/java/com/google/devtools/build/bfg/ReferencedClassesParser.java
// @AutoValue
// public abstract static class ImportDeclaration {
//   public abstract QualifiedName name();
// 
//   public abstract boolean isStatic();
// 
//   public static ImportDeclaration create(QualifiedName qname, boolean isStatic) {
//     return new AutoValue_ReferencedClassesParser_ImportDeclaration(qname, isStatic);
//   }
// }
// 
// Path: lang/java/src/main/java/com/google/devtools/build/bfg/ReferencedClassesParser.java
// @AutoValue
// public abstract static class Metadata {
//   static final Metadata EMPTY = create(0, 0, false);
// 
//   /** Line where a simple/qualified name starts. */
//   public abstract int line();
// 
//   /** Column where a simple/qualified name starts. */
//   public abstract int column();
// 
//   public abstract boolean isMethod();
// 
//   public static Metadata create(int line, int column, boolean isMethod) {
//     return new AutoValue_ReferencedClassesParser_Metadata(line, column, isMethod);
//   }
// }
// 
// Path: lang/java/src/main/java/com/google/devtools/build/bfg/ReferencedClassesParser.java
// @AutoValue
// public abstract static class QualifiedName {
//   public static final Pattern CLASS_NAME_PATTERN = Pattern.compile("^[A-Z][a-zA-Z0-9_$]*$");
// 
//   public static QualifiedName create(String value, Metadata metadata) {
//     return new AutoValue_ReferencedClassesParser_QualifiedName(value, metadata);
//   }
// 
//   public abstract String value();
// 
//   public abstract Metadata metadata();
// 
//   @Memoized
//   public ImmutableList<String> parts() {
//     return ImmutableList.copyOf(DOT_SPLITTER.split(value()));
//   }
// 
//   private static int findTopLevelName(List<String> parts) {
//     for (int i = 0; i < parts.size(); i++) {
//       String part = parts.get(i);
//       if (CLASS_NAME_PATTERN.matcher(part).matches()) {
//         // if i == 0, 's' starts with a capitalized-camel name,
//         // e.g., "MobileLocalDetailsJslayoutProto".
//         return i > 0 ? i : -1;
//       }
//       if (isLowerCase(part)) {
//         continue;
//       }
//       return -1;
//     }
//     return -1;
//   }
// 
//   /**
//    * "java.util.Map" => "java.util.Map" "java.util.Map.Entry" => "java.util.Map"
//    * "org.mockito.Mockito.mock" => "org.mockito.Mockito"
//    */
//   public QualifiedName getTopLevelQualifiedName() {
//     return create(DOT_JOINER.join(parts().subList(0, findTopLevelName(parts()) + 1)), metadata());
//   }
// }


// Path: lang/java/src/test/java/com/google/devtools/build/bfg/ReferencedClassesParserTest.java
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.truth.Truth.assertThat;
import static java.util.stream.Collectors.toMap;
import static org.junit.Assert.assertTrue;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.google.devtools.build.bfg.ReferencedClassesParser.ImportDeclaration;
import com.google.devtools.build.bfg.ReferencedClassesParser.Metadata;
import com.google.devtools.build.bfg.ReferencedClassesParser.QualifiedName;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

            "class A {", "  void foo() throws IOException, java.io.FileNotFoundException {}", "}");
    ReferencedClassesParser parser = parse(source);
    assertThat(parser.symbols.keySet())
        .containsExactly("IOException", "java.io.FileNotFoundException");
  }

  @Test
  public void allCapsFieldNamesAreNotConsideredClassNames() {
    String source =
        joiner.join(
            "class A {",
            "  FormattingLogger LOG = null;",
            "  void foo() {",
            "    LOG.warning();",
            "  }",
            "}");
    ReferencedClassesParser parser = parse(source);
    assertThat(parser.symbols.keySet()).containsExactly("FormattingLogger");
  }

  @Test
  public void dontReportJavaLangInnerClasses() {
    ReferencedClassesParser parser = parse("class A extends Thread.UncaughtExceptionHandler { }");
    assertThat(parser.symbols.keySet()).doesNotContain("Thread");
    assertThat(parser.symbols.keySet()).isEmpty();
  }

  @Test
  public void dontReportJavaLangImports() {
    ReferencedClassesParser parser = parse("import static java.lang.String.format;");
    for (ImportDeclaration decl : parser.importDeclarations) {