/** Return the enclosing {@code ClassSymbol} of the given symbol, or {@code null}. */ public static ClassSymbol enclosingClass(Symbol sym) { return sym.owner.enclClass(); }
/** * Returns the owner if the given member is declared in a lexically enclosing scope, and * {@code null} otherwise. */ private ClassSymbol isEnclosedIn(ClassSymbol startingClass, Symbol member, Types types) { for (ClassSymbol scope = startingClass.owner.enclClass(); scope != null; scope = scope.owner.enclClass()) { if (member.isMemberOf(scope.type.tsym, types)) { return scope; } } return null; } };
/** Is sym a non-static member of an enclosing class of currentClass? */ private static boolean memberOfEnclosing(Symbol owner, VisitorState state, Symbol sym) { if (sym == null || !sym.hasOuterInstance()) { return false; } for (ClassSymbol encl = owner.owner.enclClass(); encl != null; encl = encl.owner != null ? encl.owner.enclClass() : null) { if (sym.isMemberOf(encl, state.getTypes())) { return true; } } return false; }
private static Optional<ComparisonSite> getDubiousComparison( ClassSymbol encl, Tree tree, ExpressionTree lhs, ExpressionTree rhs) { Symbol lhsSymbol = getSymbol(lhs); Symbol rhsSymbol = getSymbol(rhs); if (lhsSymbol == null || rhsSymbol == null || lhsSymbol.equals(rhsSymbol)) { return Optional.empty(); } if (lhsSymbol.isStatic() || rhsSymbol.isStatic()) { return Optional.empty(); } if (!encl.equals(lhsSymbol.enclClass()) || !encl.equals(rhsSymbol.enclClass())) { return Optional.empty(); } if (!FIELD_TYPES.contains(lhsSymbol.getKind()) || !FIELD_TYPES.contains(rhsSymbol.getKind())) { return Optional.empty(); } if (getKind(lhs) != getKind(rhs)) { return Optional.empty(); } return Optional.of(ComparisonSite.of(tree, lhsSymbol, rhsSymbol)); }
@Override public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) { Symbol symbol = jcFieldAccess.sym; if (symbol.getEnclosingElement() != null && symbol.getEnclosingElement().getEnclosingElement() != null && symbol.getEnclosingElement().getEnclosingElement().enclClass() != null) { try { int value = (Integer) requireNonNull(((Symbol.VarSymbol) symbol).getConstantValue()); resourceIds.put(value, new Id(value, symbol)); } catch (Exception ignored) { } } }
private void fixQualifier(Tree tree, ExpressionTree qualifierExpression) { if (sym.equals(ASTHelpers.getSymbol(tree))) { builder.replace(qualifierExpression, sym.owner.enclClass().getSimpleName().toString()); } } }.scan(state.getPath().getCompilationUnit(), null);
private boolean isSymbolFieldInAppropriateClass(@Nullable Symbol symbol) { if (symbol == null) { return false; } return symbol.getKind().isField() && fieldSymbolIsAppropriate(symbol) && classIsAppropriate(symbol.owner.enclClass()); }
Id(int value, @Nullable Symbol rSymbol) { this.value = value; if (rSymbol != null) { ClassName className = ClassName.get(rSymbol.packge().getQualifiedName().toString(), R, rSymbol.enclClass().name.toString()); String resourceName = rSymbol.name.toString(); this.code = className.topLevelClassName().equals(ANDROID_R) ? CodeBlock.of("$L.$N", className, resourceName) : CodeBlock.of("$T.$N", className, resourceName); this.qualifed = true; } else { this.code = CodeBlock.of("$L", value); this.qualifed = false; } }
public static GuardedBySymbolResolver from(Tree tree, VisitorState visitorState) { return GuardedBySymbolResolver.from( ASTHelpers.getSymbol(tree).owner.enclClass(), visitorState.getPath().getCompilationUnit(), visitorState.context, tree); }
Symbol curr = access; do { curr = curr.owner.enclClass(); if (curr == null) { break;
@Override public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) { // This "visit" method is called for each parameter in the annotation, but only if the // parameter is a field type (eg R.layout.resource_name is a field inside the R.layout // class). This means this method will not pick up things like booleans and strings. // This is the resource parameter inside the annotation Symbol symbol = jcFieldAccess.sym; if (symbol instanceof VarSymbol && symbol.getEnclosingElement() != null // The R.resourceType class && symbol.getEnclosingElement().getEnclosingElement() != null // The R class && symbol.getEnclosingElement().getEnclosingElement().enclClass() != null) { ResourceValue result = parseResourceSymbol((VariableElement) symbol); if (result != null) { results.add(result); } } }
private static SuggestedFix fixClass(ClassTree classTree, VisitorState state) { int startPos = ((JCTree) classTree).getStartPosition(); int endPos = ((JCTree) classTree.getMembers().get(0)).getStartPosition(); ImmutableList<ErrorProneToken> tokens = ErrorProneTokens.getTokens( state.getSourceCode().subSequence(startPos, endPos).toString(), state.context); String modifiers = getSymbol(classTree).owner.enclClass() == null ? "final class" : "static final class"; SuggestedFix.Builder fix = SuggestedFix.builder(); for (ErrorProneToken token : tokens) { if (token.kind() == TokenKind.INTERFACE) { fix.replace(startPos + token.pos(), startPos + token.endPos(), modifiers); } } return fix.build(); } }
private boolean overrides(MethodSymbol sym, MethodSymbol other) { return !sym.isStatic() && !other.isStatic() && (((sym.flags() | other.flags()) & Flags.SYNTHETIC) == 0) && sym.name.contentEquals(other.name) && sym.overrides( other, sym.owner.enclClass(), state.getTypes(), /* checkResult= */ false); } }.scan(method.getBody(), null),
/** * Finds the class of the expression's receiver: the declaring class of a static member access, or * the type that an instance member is accessed on. */ private ClassSymbol getReceiver(ExpressionTree tree, Symbol sym) { if (sym.isStatic() || sym instanceof ClassSymbol) { return sym.enclClass(); } switch (tree.getKind()) { case MEMBER_SELECT: case METHOD_INVOCATION: Type receiver = ASTHelpers.getType(ASTHelpers.getReceiver(tree)); if (receiver == null) { return null; } return receiver.tsym.enclClass(); case IDENTIFIER: // Simple names are implicitly qualified by an enclosing instance, so if we get here // we're inside the compilation unit that declares the receiver, and the diff doesn't // contain accurate information. return null; default: return null; } } }
@Override public Description matchSynchronized(SynchronizedTree tree, VisitorState state) { Symbol symbol = ASTHelpers.getSymbol(stripParentheses(tree.getExpression())); if (!(symbol instanceof VarSymbol)) { return NO_MATCH; } // TODO(cushon): check that the receiver doesn't contain mutable state. // Currently 'this.locks[i].mu' is accepted if 'mu' is final but 'locks' is non-final. VarSymbol varSymbol = (VarSymbol) symbol; if (varSymbol.isLocal() || varSymbol.isStatic() || (varSymbol.flags() & Flags.FINAL) != 0) { return NO_MATCH; } if (ASTHelpers.hasAnnotation(varSymbol, LazyInit.class, state)) { return NO_MATCH; } Name ownerName = varSymbol.owner.enclClass().getQualifiedName(); if (Stream.of("java.io.Writer", "java.io.Reader").anyMatch(ownerName::contentEquals)) { // These classes contain a non-final 'lock' variable available to subclasses, and we can't // make these locks final. return NO_MATCH; } return describeMatch(tree.getExpression()); } }
/** * Returns the {@link MethodSymbol} of the first method that sym overrides in its supertype * closure, or {@code null} if no such method exists. */ private MethodSymbol getFirstOverride(Symbol sym, Types types) { ClassSymbol owner = sym.enclClass(); if (ignoreInterfaceOverrides && owner.isInterface()) { // pretend the method does not override anything return null; } for (Type s : types.closure(owner.type)) { if (s == owner.type) { continue; } for (Symbol m : s.tsym.members().getSymbolsByName(sym.name)) { if (!(m instanceof MethodSymbol)) { continue; } MethodSymbol msym = (MethodSymbol) m; if (msym.isStatic()) { continue; } if (sym.overrides(msym, owner, types, /* checkResult= */ false)) { return msym; } } } return null; } }
@Nullable private ClassTree findEnclosingLocalOrAnonymousClass(ClassTree classTree) { Symbol.ClassSymbol symbol = ASTHelpers.getSymbol(classTree); // we need this while loop since we can have a NestingKind.NESTED class (i.e., a nested // class declared at the top-level within its enclosing class) nested (possibly deeply) // within a NestingKind.ANONYMOUS or NestingKind.LOCAL class while (symbol.getNestingKind().isNested()) { if (symbol.getNestingKind().equals(NestingKind.ANONYMOUS) || symbol.getNestingKind().equals(NestingKind.LOCAL)) { return Trees.instance(JavacProcessingEnvironment.instance(context)).getTree(symbol); } else { // symbol.owner is the enclosing element, which could be a class or a method. // if it's a class, the enclClass() method will (surprisingly) return the class itself, // so this works symbol = symbol.owner.enclClass(); } } return null; }
/** * Normalizes the receiver of a select expression so that accesses on 'this' are divided * into type names (for static accesses), qualified this accesses (for members of a * lexically enclosing scope), or simple this accesses for members of the current class. */ private GuardedByExpression normalizeBase( BinderContext context, Symbol symbol, GuardedByExpression base) { if (symbol.isStatic()) { return F.typeLiteral(symbol.owner.enclClass()); } if (base != null && base.kind() != GuardedByExpression.Kind.THIS) { return base; } if (symbol.isMemberOf(context.thisClass.type.tsym, context.types)) { return F.thisliteral(); } Symbol lexicalOwner = isEnclosedIn(context.thisClass, symbol, context.types); if (lexicalOwner != null) { return F.qualifiedThis(context.names, context.thisClass, lexicalOwner); } throw new IllegalGuardedBy("Could not find the implicit receiver."); }
ClassSymbol encloser = clazzSymbol.owner.enclClass(); calledType = calledType.getEnclosingType(); tyargIndex = findTypeArgInList(encloser, typeArgName);