/** Add a name usage to the simplifier's internal cache */
 protected void addUsage(Symbol sym) {
   Name n = sym.getSimpleName();
   List<Symbol> conflicts = nameClashes.get(n);
   if (conflicts == null) {
     conflicts = List.nil();
   }
   if (!conflicts.contains(sym)) nameClashes.put(n, conflicts.append(sym));
 }
 /**
  * Build a list of multiline diagnostics containing detailed info about type-variables, captured
  * types, and intersection types
  *
  * @return where clause list
  */
 protected List<JCDiagnostic> getWhereClauses() {
   List<JCDiagnostic> clauses = List.nil();
   for (WhereClauseKind kind : WhereClauseKind.values()) {
     List<JCDiagnostic> lines = List.nil();
     for (Map.Entry<Type, JCDiagnostic> entry : whereClauses.get(kind).entrySet()) {
       lines = lines.prepend(entry.getValue());
     }
     if (!lines.isEmpty()) {
       String key = kind.key();
       if (lines.size() > 1) key += ".1";
       JCDiagnostic d = diags.fragment(key, whereClauses.get(kind).keySet());
       d = new JCDiagnostic.MultilineDiagnostic(d, lines.reverse());
       clauses = clauses.prepend(d);
     }
   }
   return clauses.reverse();
 }
 @Override
 public Void visitClassType(ClassType t, Void ignored) {
   if (t.isCompound()) {
     if (indexOf(t, WhereClauseKind.INTERSECTION) == -1) {
       Type supertype = types.supertype(t);
       List<Type> interfaces = types.interfaces(t);
       JCDiagnostic d =
           diags.fragment("where.intersection", t, interfaces.prepend(supertype));
       whereClauses.get(WhereClauseKind.INTERSECTION).put(t, d);
       visit(supertype);
       visit(interfaces);
     }
   }
   nameSimplifier.addUsage(t.tsym);
   visit(t.getTypeArguments());
   if (t.getEnclosingType() != Type.noType) visit(t.getEnclosingType());
   return null;
 }
 /**
  * Process a single compound annotation, returning its Attribute. Used from MemberEnter for
  * attaching the attributes to the annotated symbol.
  */
 Attribute.Compound enterAnnotation(JCAnnotation a, Type expected, Env<AttrContext> env) {
   // The annotation might have had its type attributed (but not checked)
   // by attr.attribAnnotationTypes during MemberEnter, in which case we do not
   // need to do it again.
   Type at =
       (a.annotationType.type != null
           ? a.annotationType.type
           : attr.attribType(a.annotationType, env));
   a.type = chk.checkType(a.annotationType.pos(), at, expected);
   if (a.type.isErroneous())
     return new Attribute.Compound(a.type, List.<Pair<MethodSymbol, Attribute>>nil());
   if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) {
     log.error(a.annotationType.pos(), "not.annotation.type", a.type.toString());
     return new Attribute.Compound(a.type, List.<Pair<MethodSymbol, Attribute>>nil());
   }
   List<JCExpression> args = a.args;
   if (args.length() == 1 && args.head.getTag() != JCTree.ASSIGN) {
     // special case: elided "value=" assumed
     args.head = make.at(args.head.pos).Assign(make.Ident(names.value), args.head);
   }
   ListBuffer<Pair<MethodSymbol, Attribute>> buf = new ListBuffer<Pair<MethodSymbol, Attribute>>();
   for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
     JCExpression t = tl.head;
     if (t.getTag() != JCTree.ASSIGN) {
       log.error(t.pos(), "annotation.value.must.be.name.value");
       continue;
     }
     JCAssign assign = (JCAssign) t;
     if (assign.lhs.getTag() != JCTree.IDENT) {
       log.error(t.pos(), "annotation.value.must.be.name.value");
       continue;
     }
     JCIdent left = (JCIdent) assign.lhs;
     Symbol method =
         rs.resolveQualifiedMethod(left.pos(), env, a.type, left.name, List.<Type>nil(), null);
     left.sym = method;
     left.type = method.type;
     if (method.owner != a.type.tsym)
       log.error(left.pos(), "no.annotation.member", left.name, a.type);
     Type result = method.type.getReturnType();
     Attribute value = enterAttributeValue(result, assign.rhs, env);
     if (!method.type.isErroneous())
       buf.append(new Pair<MethodSymbol, Attribute>((MethodSymbol) method, value));
     t.type = result;
   }
   return new Attribute.Compound(a.type, buf.toList());
 }
        @Override
        public Void visitTypeVar(TypeVar t, Void ignored) {
          if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
            // access the bound type and skip error types
            Type bound = t.bound;
            while ((bound instanceof ErrorType)) bound = ((ErrorType) bound).getOriginalType();
            // retrieve the bound list - if the type variable
            // has not been attributed the bound is not set
            List<Type> bounds =
                (bound != null && bound.tsym != null) ? types.getBounds(t) : List.<Type>nil();

            nameSimplifier.addUsage(t.tsym);

            boolean boundErroneous =
                bounds.head == null || bounds.head.tag == NONE || bounds.head.tag == ERROR;

            if ((t.tsym.flags() & SYNTHETIC) == 0) {
              // this is a true typevar
              JCDiagnostic d =
                  diags.fragment(
                      "where.typevar" + (boundErroneous ? ".1" : ""),
                      t,
                      bounds,
                      Kinds.kindName(t.tsym.location()),
                      t.tsym.location());
              whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d);
              symbolPreprocessor.visit(t.tsym.location(), null);
              visit(bounds);
            } else {
              Assert.check(!boundErroneous);
              // this is a fresh (synthetic) tvar
              JCDiagnostic d = diags.fragment("where.fresh.typevar", t, bounds);
              whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d);
              visit(bounds);
            }
          }
          return null;
        }
 public String simplify(Symbol s) {
   String name = s.getQualifiedName().toString();
   if (!s.type.isCompound()) {
     List<Symbol> conflicts = nameClashes.get(s.getSimpleName());
     if (conflicts == null || (conflicts.size() == 1 && conflicts.contains(s))) {
       List<Name> l = List.nil();
       Symbol s2 = s;
       while (s2.type.getEnclosingType().tag == CLASS && s2.owner.kind == Kinds.TYP) {
         l = l.prepend(s2.getSimpleName());
         s2 = s2.owner;
       }
       l = l.prepend(s2.getSimpleName());
       StringBuilder buf = new StringBuilder();
       String sep = "";
       for (Name n2 : l) {
         buf.append(sep);
         buf.append(n2);
         sep = ".";
       }
       name = buf.toString();
     }
   }
   return name;
 }
  /**
   * Main method: compile a list of files, return all compiled classes
   *
   * @param filenames The names of all files to be compiled.
   */
  public List<ClassSymbol> compile(
      List<String> filenames,
      Map<String, String> origOptions,
      ClassLoader aptCL,
      AnnotationProcessorFactory providedFactory,
      java.util.Set<Class<? extends AnnotationProcessorFactory>> productiveFactories,
      java.util.Set<java.io.File> aggregateGenFiles)
      throws Throwable {
    // as a JavaCompiler can only be used once, throw an exception if
    // it has been used before.
    assert !hasBeenUsed : "attempt to reuse JavaCompiler";
    hasBeenUsed = true;

    this.aggregateGenFiles = aggregateGenFiles;

    long msec = System.currentTimeMillis();

    ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>();
    try {
      JavacFileManager fm = (JavacFileManager) fileManager;
      // parse all files
      ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>();
      for (List<String> l = filenames; l.nonEmpty(); l = l.tail) {
        if (classesAsDecls) {
          if (!l.head.endsWith(".java")) { // process as class file
            ClassSymbol cs = reader.enterClass(names.fromString(l.head));
            try {
              cs.complete();
            } catch (Symbol.CompletionFailure cf) {
              bark.aptError("CantFindClass", l);
              continue;
            }

            classes.append(cs); // add to list of classes
            continue;
          }
        }
        JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next();
        trees.append(parse(fo));
      }

      // enter symbols for all files
      List<JCCompilationUnit> roots = trees.toList();

      if (errorCount() == 0) {
        boolean prev = bark.setDiagnosticsIgnored(true);
        try {
          enter.main(roots);
        } finally {
          bark.setDiagnosticsIgnored(prev);
        }
      }

      if (errorCount() == 0) {
        apt.main(roots, classes, origOptions, aptCL, providedFactory, productiveFactories);
        genSourceFileNames.addAll(apt.getSourceFileNames());
        genClassFileNames.addAll(apt.getClassFileNames());
      }

    } catch (Abort ex) {
    }

    if (verbose) log.printVerbose("total", Long.toString(System.currentTimeMillis() - msec));

    chk.reportDeferredDiagnostics();

    printCount("error", errorCount());
    printCount("warn", warningCount());

    return classes.toList();
  }
 Attribute enterAttributeValue(Type expected, JCExpression tree, Env<AttrContext> env) {
   // first, try completing the attribution value sym - if a completion
   // error is thrown, we should recover gracefully, and display an
   // ordinary resolution diagnostic.
   try {
     expected.tsym.complete();
   } catch (CompletionFailure e) {
     log.error(tree.pos(), "cant.resolve", Kinds.kindName(e.sym), e.sym);
     return new Attribute.Error(expected);
   }
   if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) {
     Type result = attr.attribExpr(tree, env, expected);
     if (result.isErroneous()) return new Attribute.Error(expected);
     if (result.constValue() == null) {
       log.error(tree.pos(), "attribute.value.must.be.constant");
       return new Attribute.Error(expected);
     }
     result = cfolder.coerce(result, expected);
     return new Attribute.Constant(expected, result.constValue());
   }
   if (expected.tsym == syms.classType.tsym) {
     Type result = attr.attribExpr(tree, env, expected);
     if (result.isErroneous()) return new Attribute.Error(expected);
     if (TreeInfo.name(tree) != names._class) {
       log.error(tree.pos(), "annotation.value.must.be.class.literal");
       return new Attribute.Error(expected);
     }
     return new Attribute.Class(types, (((JCFieldAccess) tree).selected).type);
   }
   if ((expected.tsym.flags() & Flags.ANNOTATION) != 0
       || types.isSameType(expected, syms.annotationType)) {
     if (tree.getTag() != JCTree.ANNOTATION) {
       log.error(tree.pos(), "annotation.value.must.be.annotation");
       expected = syms.errorType;
     }
     return enterAnnotation((JCAnnotation) tree, expected, env);
   }
   if (expected.tag == TypeTags.ARRAY) { // should really be isArray()
     if (tree.getTag() != JCTree.NEWARRAY) {
       tree = make.at(tree.pos).NewArray(null, List.<JCExpression>nil(), List.of(tree));
     }
     JCNewArray na = (JCNewArray) tree;
     if (na.elemtype != null) {
       log.error(na.elemtype.pos(), "new.not.allowed.in.annotation");
       return new Attribute.Error(expected);
     }
     ListBuffer<Attribute> buf = new ListBuffer<Attribute>();
     for (List<JCExpression> l = na.elems; l.nonEmpty(); l = l.tail) {
       buf.append(enterAttributeValue(types.elemtype(expected), l.head, env));
     }
     na.type = expected;
     return new Attribute.Array(expected, buf.toArray(new Attribute[buf.length()]));
   }
   if (expected.tag == TypeTags.CLASS && (expected.tsym.flags() & Flags.ENUM) != 0) {
     attr.attribExpr(tree, env, expected);
     Symbol sym = TreeInfo.symbol(tree);
     if (sym == null
         || TreeInfo.nonstaticSelect(tree)
         || sym.kind != Kinds.VAR
         || (sym.flags() & Flags.ENUM) == 0) {
       log.error(tree.pos(), "enum.annotation.must.be.enum.constant");
       return new Attribute.Error(expected);
     }
     VarSymbol enumerator = (VarSymbol) sym;
     return new Attribute.Enum(expected, enumerator);
   }
   if (!expected.isErroneous()) log.error(tree.pos(), "annotation.value.not.allowable.type");
   return new Attribute.Error(attr.attribExpr(tree, env, expected));
 }