예제 #1
0
  @Override
  public boolean matches(ExpressionTree expressionTree, VisitorState state) {
    Symbol sym = ASTHelpers.getSymbol(expressionTree);
    if (sym == null) {
      return false;
    }
    if (!(sym instanceof MethodSymbol)) {
      throw new IllegalArgumentException(
          "DescendantOf matcher expects a method call but found "
              + sym.getClass()
              + ". Expression: "
              + expressionTree);
    }
    if (sym.isStatic()) {
      return false;
    }

    if (methodName.equals(sym.toString())) {
      Type accessedReferenceType = sym.owner.type;
      Type collectionType = state.getTypeFromString(fullClassName);
      if (collectionType != null) {
        return state
            .getTypes()
            .isSubtype(accessedReferenceType, state.getTypes().erasure(collectionType));
      }
    }

    return false;
  }
예제 #2
0
  public static Set<MethodSymbol> findSuperMethods(MethodSymbol methodSymbol, Types types) {
    Set<MethodSymbol> supers = new HashSet<>();
    if (methodSymbol.isStatic()) {
      return supers;
    }

    TypeSymbol owner = (TypeSymbol) methodSymbol.owner;
    // Iterates over an ordered list of all super classes and interfaces.
    for (Type sup : types.closure(owner.type)) {
      if (sup == owner.type) {
        continue; // Skip the owner of the method
      }
      Scope scope = sup.tsym.members();
      for (Symbol sym : scope.getSymbolsByName(methodSymbol.name)) {
        if (sym != null
            && !sym.isStatic()
            && ((sym.flags() & Flags.SYNTHETIC) == 0)
            && sym.name.contentEquals(methodSymbol.name)
            && methodSymbol.overrides(sym, owner, types, true)) {
          supers.add((MethodSymbol) sym);
        }
      }
    }
    return supers;
  }
예제 #3
0
  /**
   * Determines whether two expressions refer to the same variable. Note that returning false
   * doesn't necessarily mean the expressions do *not* refer to the same field. We don't attempt to
   * do any complex analysis here, just catch the obvious cases.
   */
  public static boolean sameVariable(ExpressionTree expr1, ExpressionTree expr2) {
    // Throw up our hands if we're not comparing identifiers and/or field accesses.
    if ((expr1.getKind() != Kind.IDENTIFIER && expr1.getKind() != Kind.MEMBER_SELECT)
        || (expr2.getKind() != Kind.IDENTIFIER && expr2.getKind() != Kind.MEMBER_SELECT)) {
      return false;
    }

    Symbol sym1 = getSymbol(expr1);
    Symbol sym2 = getSymbol(expr2);
    if (sym1 == null) {
      throw new IllegalStateException("Couldn't get symbol for " + expr1);
    } else if (sym2 == null) {
      throw new IllegalStateException("Couldn't get symbol for " + expr2);
    }

    if (expr1.getKind() == Kind.IDENTIFIER && expr2.getKind() == Kind.IDENTIFIER) {
      // foo == foo?
      return sym1.equals(sym2);
    } else if (expr1.getKind() == Kind.MEMBER_SELECT && expr2.getKind() == Kind.MEMBER_SELECT) {
      // foo.baz.bar == foo.baz.bar?
      return sym1.equals(sym2)
          && sameVariable(((JCFieldAccess) expr1).selected, ((JCFieldAccess) expr2).selected);
    } else {
      // this.foo == foo?
      ExpressionTree selected = null;
      if (expr1.getKind() == Kind.IDENTIFIER) {
        selected = ((JCFieldAccess) expr2).selected;
      } else {
        selected = ((JCFieldAccess) expr1).selected;
      }
      // TODO(eaftan): really shouldn't be relying on .toString()
      return selected.toString().equals("this") && sym1.equals(sym2);
    }
  }
예제 #4
0
 /**
  * Returns the type of an element when that element is viewed as a member of, or otherwise
  * directly contained by, a given type. For example, when viewed as a member of the parameterized
  * type {@code Set<String>}, the {@code Set.add} method is an {@code ExecutableType} whose
  * parameter is of type {@code String}.
  *
  * @param containing the containing type
  * @param element the element
  * @return the type of the element as viewed from the containing type
  * @throws IllegalArgumentException if the element is not a valid one for the given type
  */
 public TypeMirror asMemberOf(DeclaredType containing, Element element) {
   Type site = (Type) containing;
   Symbol sym = (Symbol) element;
   if (types.asSuper(site, sym.getEnclosingElement()) == null)
     throw new IllegalArgumentException(sym + "@" + site);
   return types.memberType(site, sym);
 }
예제 #5
0
 /**
  * Collect dependencies in the enclosing class
  *
  * @param from The enclosing class sym
  * @param to The enclosing classes references this sym.
  */
 @Override
 public void reportDependence(Symbol from, Symbol to) {
   // Capture dependencies between the packages.
   deps.reportPackageDep(from.packge().fullname, to.packge().fullname);
   // It would be convenient to check if to.outermost comes from source or classpath
   // and only report it, if its from the classpath. This would reduce the amount
   // of data sent over the wire to the sjavac client. Can this be done? All interesting
   // classes are private within javac/file or javac/jvm....
   deps.reportClassDep(to.outermostClass());
 }
예제 #6
0
 /** {@inheritDoc} */
 public Collection<ConstructorDeclaration> getConstructors() {
   ArrayList<ConstructorDeclaration> res = new ArrayList<ConstructorDeclaration>();
   for (Symbol s : getMembers(true)) {
     if (s.isConstructor()) {
       MethodSymbol m = (MethodSymbol) s;
       res.add((ConstructorDeclaration) env.declMaker.getExecutableDeclaration(m));
     }
   }
   return res;
 }
 private void addAllFireListenerMethods(
     final JavacType type, final TypeSymbol interfaze, final TypeSymbol superInterfaze) {
   for (Symbol member : superInterfaze.getEnclosedElements()) {
     if (member.getKind() != ElementKind.METHOD) continue;
     handler.addFireListenerMethod(type, interfaze, (MethodSymbol) member);
   }
   ClassType superInterfazeType = (ClassType) superInterfaze.type;
   if (superInterfazeType.interfaces_field != null)
     for (Type iface : superInterfazeType.interfaces_field) {
       addAllFireListenerMethods(type, interfaze, iface.asElement());
     }
 }
예제 #8
0
 @Override
 @Nullable
 protected Unifier defaultAction(Tree node, @Nullable Unifier unifier) {
   Symbol symbol = ASTHelpers.getSymbol(node);
   if (symbol != null
       && symbol.getEnclosingElement() != null
       && symbol
           .getEnclosingElement()
           .getQualifiedName()
           .contentEquals(classIdent().getQualifiedName())
       && symbol.getSimpleName().contentEquals(member())) {
     return memberType().unify(symbol.asType(), unifier);
   }
   return null;
 }
 /** {@inheritDoc} */
 public Collection<AnnotationMirror> getAnnotationMirrors() {
   Collection<AnnotationMirror> res = new ArrayList<AnnotationMirror>();
   for (Attribute.Compound a : sym.getAnnotationMirrors()) {
     res.add(env.declMaker.getAnnotationMirror(a, this));
   }
   return res;
 }
 /** 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));
 }
예제 #11
0
 Item invoke() {
   MethodType mtype = (MethodType) member.erasure(types);
   int argsize = Code.width(mtype.argtypes);
   int rescode = Code.typecode(mtype.restype);
   int sdiff = Code.width(rescode) - argsize;
   code.emitInvokestatic(pool.put(member), mtype);
   return stackItem[rescode];
 }
예제 #12
0
  /**
   * Determines whether a symbol has an annotation of the given type. This includes annotations
   * inherited from superclasses due to @Inherited.
   *
   * @param annotationType The type of the annotation to look for (e.g, "javax.annotation.Nullable")
   */
  public static boolean hasAnnotation(Symbol sym, String annotationType, VisitorState state) {
    Symbol annotationSym = state.getSymbolFromString(annotationType);
    Symbol inheritedSym = state.getSymtab().inheritedType.tsym;

    if ((sym == null) || (annotationSym == null)) {
      return false;
    }
    if ((sym instanceof ClassSymbol) && (annotationSym.attribute(inheritedSym) != null)) {
      while (sym != null) {
        if (sym.attribute(annotationSym) != null) {
          return true;
        }
        sym = ((ClassSymbol) sym).getSuperclass().tsym;
      }
      return false;
    } else {
      return sym.attribute(annotationSym) != null;
    }
  }
예제 #13
0
    @Override
    public boolean matches(ExpressionTree expressionTree, VisitorState state) {
      Symbol sym = ASTHelpers.getSymbol(expressionTree);
      if (sym != null && sym.getSimpleName().toString().startsWith("log")) {
        return true;
      }

      if (sym != null && sym.isStatic()) {
        if (sym.owner.getQualifiedName().toString().contains("Logger")) {
          return true;
        }
      } else if (expressionTree instanceof MemberSelectTree) {
        if (((MemberSelectTree) expressionTree).getExpression().toString().startsWith("log")) {
          return true;
        }
      }

      return false;
    }
예제 #14
0
 Item invoke() {
   MethodType mtype = (MethodType) member.externalType(types);
   int rescode = Code.typecode(mtype.restype);
   if ((member.owner.flags() & Flags.INTERFACE) != 0) {
     code.emitInvokeinterface(pool.put(member), mtype);
   } else if (nonvirtual) {
     code.emitInvokespecial(pool.put(member), mtype);
   } else {
     code.emitInvokevirtual(pool.put(member), mtype);
   }
   return stackItem[rescode];
 }
예제 #15
0
 protected <A extends Annotation> A getAnnotation(Class<A> annoType, Symbol annotated) {
   if (!annoType.isAnnotation()) {
     throw new IllegalArgumentException("Not an annotation type: " + annoType);
   }
   String name = annoType.getName();
   for (Attribute.Compound attr : annotated.getAnnotationMirrors()) {
     if (name.equals(attr.type.tsym.flatName().toString())) {
       return AnnotationProxyMaker.generateAnnotation(env, attr, annoType);
     }
   }
   return null;
 }
예제 #16
0
 /**
  * Returns the symbols of type or package members (and constructors) that are not synthetic or
  * otherwise unwanted. Caches the result if "cache" is true.
  */
 protected Collection<Symbol> getMembers(boolean cache) {
   if (members != null) {
     return members;
   }
   LinkedList<Symbol> res = new LinkedList<Symbol>();
   for (Scope.Entry e = sym.members().elems; e != null; e = e.sibling) {
     if (e.sym != null && !unwanted(e.sym)) {
       res.addFirst(e.sym);
     }
   }
   return cache ? (members = res) : res;
 }
예제 #17
0
  protected void printSymbol(String label, Symbol sym, Details details) {
    if (sym == null) {
      printNull(label);
    } else {
      switch (details) {
        case SUMMARY:
          printString(label, toString(sym));
          break;

        case FULL:
          indent();
          out.print(label);
          out.println(
              ": "
                  + info(
                      sym.getClass(),
                      String.format("0x%x--%s", sym.kind.ordinal(), Kinds.kindName(sym)),
                      sym.getKind())
                  + " "
                  + sym.name
                  + " "
                  + hashString(sym));

          indent(+1);
          if (showSrc) {
            JCTree tree = (JCTree) trees.getTree(sym);
            if (tree != null) printSource("src", tree);
          }
          printString(
              "flags", String.format("0x%x--%s", sym.flags_field, Flags.toString(sym.flags_field)));
          printObject("completer", sym.completer, Details.SUMMARY); // what if too long?
          printSymbol("owner", sym.owner, Details.SUMMARY);
          printType("type", sym.type, Details.SUMMARY);
          printType("erasure", sym.erasure_field, Details.SUMMARY);
          sym.accept(symVisitor, null);
          printAnnotations("annotations", sym.getMetadata(), Details.SUMMARY);
          indent(-1);
      }
    }
  }
예제 #18
0
 /** Check if the method declares or inherits an implementation of .equals() */
 public static boolean implementsEquals(Type type, VisitorState state) {
   Name equalsName = state.getName("equals");
   Symbol objectEquals = getOnlyMember(state, state.getSymtab().objectType, "equals");
   for (Type sup : state.getTypes().closure(type)) {
     if (sup.tsym.isInterface()) {
       continue;
     }
     if (ASTHelpers.isSameType(sup, state.getSymtab().objectType, state)) {
       return false;
     }
     WriteableScope scope = sup.tsym.members();
     if (scope == null) {
       continue;
     }
     for (Symbol sym : scope.getSymbolsByName(equalsName)) {
       if (sym.overrides(objectEquals, type.tsym, state.getTypes(), false)) {
         return true;
       }
     }
   }
   return false;
 }
 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;
 }
예제 #20
0
  /**
   * Extend suppression sets for both {@code @SuppressWarnings} and custom suppression annotations.
   * When we explore a new node, we have to extend the suppression sets with any new suppressed
   * warnings or custom suppression annotations. We also have to retain the previous suppression set
   * so that we can reinstate it when we move up the tree.
   *
   * <p>We do not modify the existing suppression sets, so they can be restored when moving up the
   * tree. We also avoid copying the suppression sets if the next node to explore does not have any
   * suppressed warnings or custom suppression annotations. This is the common case.
   *
   * @param sym The {@code Symbol} for the AST node currently being scanned
   * @param suppressWarningsType The {@code Type} for {@code @SuppressWarnings}, as given by javac's
   *     symbol table
   * @param suppressionsOnCurrentPath The set of strings in all {@code @SuppressWarnings}
   *     annotations on the current path through the AST
   * @param customSuppressionsOnCurrentPath The set of all custom suppression annotations
   */
  public NewSuppressions extendSuppressionSets(
      Symbol sym,
      Type suppressWarningsType,
      Set<String> suppressionsOnCurrentPath,
      Set<Class<? extends Annotation>> customSuppressionsOnCurrentPath,
      boolean inGeneratedCode) {

    boolean newInGeneratedCode = inGeneratedCode || ASTHelpers.hasAnnotation(sym, Generated.class);

    /** Handle custom suppression annotations. */
    Set<Class<? extends Annotation>> newCustomSuppressions = null;
    for (Class<? extends Annotation> annotationType : customSuppressionAnnotations) {
      if (ASTHelpers.hasAnnotation(sym, annotationType)) {
        if (newCustomSuppressions == null) {
          newCustomSuppressions = new HashSet<>(customSuppressionsOnCurrentPath);
        }
        newCustomSuppressions.add(annotationType);
      }
    }

    /** Handle @SuppressWarnings. */
    Set<String> newSuppressions = null;
    // Iterate over annotations on this symbol, looking for SuppressWarnings
    for (Attribute.Compound attr : sym.getAnnotationMirrors()) {
      // TODO(eaftan): use JavacElements.getAnnotation instead
      if (attr.type.tsym == suppressWarningsType.tsym) {
        for (List<Pair<MethodSymbol, Attribute>> v = attr.values; v.nonEmpty(); v = v.tail) {
          Pair<MethodSymbol, Attribute> value = v.head;
          if (value.fst.name.toString().equals("value"))
            if (value.snd instanceof Attribute.Array) { // SuppressWarnings takes an array
              for (Attribute suppress : ((Attribute.Array) value.snd).values) {
                if (newSuppressions == null) {
                  newSuppressions = new HashSet<>(suppressionsOnCurrentPath);
                }
                // TODO(eaftan): check return value to see if this was a new warning?
                newSuppressions.add((String) suppress.getValue());
              }
            } else {
              throw new RuntimeException("Expected SuppressWarnings annotation to take array type");
            }
        }
      }
    }

    return new NewSuppressions(newSuppressions, newCustomSuppressions, newInGeneratedCode);
  }
예제 #21
0
 /**
  * Collect dependencies in the enclosing class
  *
  * @param from The enclosing class sym
  * @param to The enclosing classes references this sym.
  */
 @Override
 public void reportDependence(Symbol from, Symbol to) {
   // Capture dependencies between the packages.
   deps.collect(from.packge().fullname, to.packge().fullname);
 }
예제 #22
0
 @Override
 public boolean matches(ExpressionTree expressionTree, VisitorState state) {
   Symbol sym = ASTHelpers.getSymbol(expressionTree);
   return sym != null && sym.getSimpleName().toString().startsWith("assert");
 }
예제 #23
0
 /**
  * {@inheritDoc}
  *
  * <p>ParameterDeclarationImpl overrides this implementation.
  */
 public int hashCode() {
   return sym.hashCode() + env.hashCode();
 }
예제 #24
0
 /** Returns this declaration's enter environment, or null if it has none. */
 private Env<AttrContext> getEnterEnv() {
   // Get enclosing class of sym, or sym itself if it is a class
   // or package.
   TypeSymbol ts = (sym.kind != PCK) ? sym.enclClass() : (PackageSymbol) sym;
   return (ts != null) ? env.enter.getEnv(ts) : null;
 }
 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));
 }
예제 #26
0
 // Symbol#getAnnotation is not intended for internal javac use, but because error-prone is run
 // after attribution it's safe to use here.
 @SuppressWarnings("deprecation")
 public static <T extends Annotation> T getAnnotation(Symbol sym, Class<T> annotationType) {
   return sym == null ? null : sym.getAnnotation(annotationType);
 }
예제 #27
0
 Item invoke() {
   MethodType mtype = (MethodType) member.erasure(types);
   int rescode = Code.typecode(mtype.restype);
   code.emitInvokestatic(pool.put(member), mtype);
   return stackItem[rescode];
 }
예제 #28
0
 MemberItem(Symbol member, boolean nonvirtual) {
   super(Code.typecode(member.erasure(types)));
   this.member = member;
   this.nonvirtual = nonvirtual;
 }
예제 #29
0
  public void visitClassDef(JCClassDecl tree) {
    Symbol owner = env.info.scope.owner;
    Scope enclScope = enterScope(env);
    ClassSymbol c;
    if (owner.kind == PCK) {
      // We are seeing a toplevel class.
      PackageSymbol packge = (PackageSymbol) owner;
      for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS;
      c = reader.enterClass(tree.name, packge);
      packge.members().enterIfAbsent(c);
      if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
        log.error(tree.pos(), "class.public.should.be.in.file", tree.name);
      }
    } else {
      if (!tree.name.isEmpty() && !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
        result = null;
        return;
      }
      if (owner.kind == TYP) {
        // We are seeing a member class.
        c = reader.enterClass(tree.name, (TypeSymbol) owner);
        if ((owner.flags_field & INTERFACE) != 0) {
          tree.mods.flags |= PUBLIC | STATIC;
        }
      } else {
        // We are seeing a local class.
        c = reader.defineClass(tree.name, owner);
        c.flatname = chk.localClassName(c);
        if (!c.name.isEmpty()) chk.checkTransparentClass(tree.pos(), c, env.info.scope);
      }
    }
    tree.sym = c;

    // Enter class into `compiled' table and enclosing scope.
    if (chk.compiled.get(c.flatname) != null) {
      duplicateClass(tree.pos(), c);
      result = types.createErrorType(tree.name, (TypeSymbol) owner, Type.noType);
      tree.sym = (ClassSymbol) result.tsym;
      return;
    }
    chk.compiled.put(c.flatname, c);
    enclScope.enter(c);

    // Set up an environment for class block and store in `typeEnvs'
    // table, to be retrieved later in memberEnter and attribution.
    Env<AttrContext> localEnv = classEnv(tree, env);
    typeEnvs.put(c, localEnv);

    // Fill out class fields.
    c.completer = memberEnter;
    c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
    c.sourcefile = env.toplevel.sourcefile;
    c.members_field = new Scope(c);

    ClassType ct = (ClassType) c.type;
    if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
      // We are seeing a local or inner class.
      // Set outer_field of this class to closest enclosing class
      // which contains this class in a non-static context
      // (its "enclosing instance class"), provided such a class exists.
      Symbol owner1 = owner;
      while ((owner1.kind & (VAR | MTH)) != 0 && (owner1.flags_field & STATIC) == 0) {
        owner1 = owner1.owner;
      }
      if (owner1.kind == TYP) {
        ct.setEnclosingType(owner1.type);
      }
    }

    // Enter type parameters.
    ct.typarams_field = classEnter(tree.typarams, localEnv);

    // Add non-local class to uncompleted, to make sure it will be
    // completed later.
    if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
    //      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG

    // Recursively enter all member classes.
    classEnter(tree.defs, localEnv);

    result = c.type;
  }
예제 #30
0
 StaticItem(Symbol member) {
   super(Code.typecode(member.erasure(types)));
   this.member = member;
 }