private static Optional<String> getEnumName(ExpressionTree chronoField) { if (chronoField instanceof IdentifierTree) { // e.g., SECOND_OF_DAY return Optional.of(((IdentifierTree) chronoField).getName().toString()); } if (chronoField instanceof MemberSelectTree) { // e.g., ChronoField.SECOND_OF_DAY return Optional.of(((MemberSelectTree) chronoField).getIdentifier().toString()); } return Optional.empty(); } }
private static Optional<String> getEnumName(ExpressionTree temporalUnit) { if (temporalUnit instanceof IdentifierTree) { // e.g., SECONDS return Optional.of(((IdentifierTree) temporalUnit).getName().toString()); } if (temporalUnit instanceof MemberSelectTree) { // e.g., ChronoUnit.SECONDS return Optional.of(((MemberSelectTree) temporalUnit).getIdentifier().toString()); } return Optional.empty(); } }
/** Collect all on demand imports. */ private static ImmutableList<ImportTree> getWildcardImports(List<? extends ImportTree> imports) { ImmutableList.Builder<ImportTree> result = ImmutableList.builder(); for (ImportTree tree : imports) { // javac represents on-demand imports as a member select where the selected name is '*'. Tree ident = tree.getQualifiedIdentifier(); if (!(ident instanceof MemberSelectTree)) { continue; } MemberSelectTree select = (MemberSelectTree) ident; if (select.getIdentifier().contentEquals("*")) { result.add(tree); } } return result.build(); }
@Override public Void visitMemberSelect(MemberSelectTree node, Void unused) { checkForThis(node, node.getIdentifier(), thisClass, state); // Don't examine this.foo or MyClass.this.foo ExpressionTree left = node.getExpression(); if ((left instanceof IdentifierTree && ((IdentifierTree) left).getName().contentEquals("this")) || (left instanceof MemberSelectTree && ((MemberSelectTree) left).getIdentifier().contentEquals("this"))) { return null; } return super.visitMemberSelect(node, unused); }
@Override public boolean matches(ExpressionTree tree, VisitorState state) { switch (tree.getKind()) { case MEMBER_SELECT: return ((MemberSelectTree) tree).getIdentifier().contentEquals("class"); case INT_LITERAL: case LONG_LITERAL: case FLOAT_LITERAL: case DOUBLE_LITERAL: case BOOLEAN_LITERAL: case CHAR_LITERAL: // fall through case STRING_LITERAL: return true; default: return false; } } };
private static boolean hasSimpleName(AnnotationTree annotation, String name) { Tree annotationType = annotation.getAnnotationType(); javax.lang.model.element.Name simpleName; if (annotationType instanceof IdentifierTree) { simpleName = ((IdentifierTree) annotationType).getName(); } else if (annotationType instanceof MemberSelectTree) { simpleName = ((MemberSelectTree) annotationType).getIdentifier(); } else { return false; } return simpleName.contentEquals(name); }
private static Optional<TimeUnit> getTimeUnit(ExpressionTree timeUnit) { if (timeUnit instanceof IdentifierTree) { // e.g., SECONDS return Enums.getIfPresent(TimeUnit.class, ((IdentifierTree) timeUnit).getName().toString()); } if (timeUnit instanceof MemberSelectTree) { // e.g., TimeUnit.SECONDS return Enums.getIfPresent( TimeUnit.class, ((MemberSelectTree) timeUnit).getIdentifier().toString()); } return Optional.absent(); } }
@Override public boolean matches(ExpressionTree expressionTree, VisitorState state) { if (expressionTree.getKind() == Kind.MEMBER_SELECT) { MemberSelectTree select = (MemberSelectTree) expressionTree; return select.getIdentifier().contentEquals("class") && classMatcher.matches(select.getExpression(), state); } return false; } };
private static boolean isOnThis(MethodInvocationTree tree) { ExpressionTree receiver = ASTHelpers.getReceiver(tree); if (receiver == null) { return true; } Name receiverName; switch (receiver.getKind()) { case IDENTIFIER: receiverName = ((IdentifierTree) receiver).getName(); break; case MEMBER_SELECT: receiverName = ((MemberSelectTree) receiver).getIdentifier(); break; default: return false; } return receiverName.contentEquals("this") || receiverName.contentEquals("super"); } }
@Override public Symbol resolveSelect(GuardedByExpression base, MemberSelectTree node) { Symbol baseSym = base.kind() == GuardedByExpression.Kind.THIS ? enclosingClass : base.type().asElement(); return getField(baseSym, node.getIdentifier().toString()); }
@Override public Void visitMethodInvocation(MethodInvocationTree tree, ExpressionTree optionalVar) { if (tree.getArguments().stream().anyMatch(m -> ASTHelpers.sameVariable(m, optionalVar))) { hasAssignment = true; } ExpressionTree receiver = ASTHelpers.getReceiver(tree); if (receiver != null && ASTHelpers.sameVariable(receiver, optionalVar)) { ExpressionTree treeIdent = tree.getMethodSelect(); if (treeIdent instanceof MemberSelectTree) { if (((MemberSelectTree) treeIdent).getIdentifier().contentEquals("get")) { hasGet = true; } } } return super.visitMethodInvocation(tree, optionalVar); }
@Override public Boolean visitMethodInvocation(MethodInvocationTree tree, Void unused) { boolean result = false; MethodSymbol methodSym = ASTHelpers.getSymbol(tree); if (methodSym != null) { ExpressionTree methodSelect = tree.getMethodSelect(); if (methodSelect.getKind() == Kind.MEMBER_SELECT) { MemberSelectTree memberSelect = (MemberSelectTree) methodSelect; result = isSuper(memberSelect.getExpression()) && memberSelect.getIdentifier().contentEquals(overridingMethodName); } } return result || super.visitMethodInvocation(tree, unused); }
@Override public Boolean visitMemberSelect(MemberSelectTree node, Void v) { if (node.getIdentifier().contentEquals("class")) { TypeMirror tm = getType(node.getExpression()); if (!verifier.getTypeUtils().isSubtype(tm, btraceServiceTm)) { reportError("no.class.literals", node); } } return super.visitMemberSelect(node, v); }
@Override public Choice<State<JCFieldAccess>> visitMemberSelect( final MemberSelectTree node, State<?> state) { return chooseSubtrees( state, s -> unifyExpression(node.getExpression(), s), expr -> maker().Select(expr, (Name) node.getIdentifier())); }
@Override public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) { JCExpression receiverTree = (JCExpression) tree.getExpression(); if (receiverTree == null || receiverTree.type == null || receiverTree.type.getKind() == TypeKind.PACKAGE) { return Description.NO_MATCH; } // sym = null on static field imports. See https://github.com/google/error-prone/issues/1138. Symbol sym = getSymbol(tree); if ((tree instanceof JCFieldAccess) && (sym == null || sym.isStatic())) { return Description.NO_MATCH; } Description result = checkExpression( receiverTree, state, qual -> String.format( "Dereferencing method/field \"%s\" of %s null receiver %s", tree.getIdentifier(), qual, receiverTree)); return result != null ? result : Description.NO_MATCH; }
@Override public UExpression visitMemberSelect(MemberSelectTree tree, Void v) { Symbol sym = ASTHelpers.getSymbol(tree); if (sym instanceof ClassSymbol) { return UClassIdent.create((ClassSymbol) sym); } else if (sym.isStatic()) { ExpressionTree selected = tree.getExpression(); checkState( ASTHelpers.getSymbol(selected) instanceof ClassSymbol, "Refaster cannot match static methods used on instances"); return staticMember(sym); } return UMemberSelect.create( template(tree.getExpression()), tree.getIdentifier(), template(sym.type)); }
/** Returns true if this method invocation is of the form {@code super.foo()} */ private static boolean isSuperCall(Type type, MethodInvocationTree tree, VisitorState state) { if (tree.getMethodSelect().getKind() == Kind.MEMBER_SELECT) { MemberSelectTree select = (MemberSelectTree) tree.getMethodSelect(); if (select.getExpression().getKind() == Kind.IDENTIFIER) { IdentifierTree ident = (IdentifierTree) select.getExpression(); return ident.getName().contentEquals("super"); } else if (select.getExpression().getKind() == Kind.MEMBER_SELECT) { MemberSelectTree subSelect = (MemberSelectTree) select.getExpression(); return subSelect.getIdentifier().contentEquals("super") && ASTHelpers.isSameType(ASTHelpers.getType(subSelect.getExpression()), type, state); } } return false; }
@Override public Description matchVariable(VariableTree tree, VisitorState state) { ExpressionTree initializer = stripNullCheck(tree.getInitializer(), state); Tree parent = state.getPath().getParentPath().getLeaf(); // must be a static class variable with member select initializer if (initializer == null || initializer.getKind() != MEMBER_SELECT || parent.getKind() != CLASS || !tree.getModifiers().getFlags().contains(STATIC)) { return Description.NO_MATCH; } MemberSelectTree rhs = (MemberSelectTree) initializer; Symbol rhsClass = ASTHelpers.getSymbol(rhs.getExpression()); Symbol lhsClass = ASTHelpers.getSymbol(parent); if (rhsClass != null && lhsClass != null && rhsClass.equals(lhsClass) && rhs.getIdentifier().contentEquals(tree.getName())) { return describeForVarDecl(tree, state); } return Description.NO_MATCH; }
@Override public GuardedByExpression visitMemberSelect(MemberSelectTree node, BinderContext context) { String name = node.getIdentifier().toString(); if (name.equals("this")) { Symbol base = context.resolver.resolveEnclosingClass(node.getExpression()); if (context.thisClass == base) { return F.thisliteral(); } return F.qualifiedThis(context.names, context.thisClass, base); } if (name.equals("class")) { Symbol base = context.resolver.resolveTypeLiteral(node.getExpression()); return F.classLiteral(base); } GuardedByExpression base = visit(node.getExpression(), context); checkGuardedBy(base != null, "Bad expression: %s", node.getExpression()); Symbol sym = context.resolver.resolveSelect(base, node); checkGuardedBy(sym != null, "Could not resolve: %s", node); // TODO(cushon): allow MethodSymbol here once clean-up is done checkGuardedBy( sym instanceof Symbol.VarSymbol /* || sym instanceof Symbol.MethodSymbol*/, "Bad member symbol: %s", sym.getClass()); return bindSelect(normalizeBase(context, sym, base), sym); }
@Override public Choice<Unifier> visitMemberSelect(MemberSelectTree fieldAccess, Unifier unifier) { if (ASTHelpers.getSymbol(fieldAccess) != null) { return getIdentifier() .unify(fieldAccess.getIdentifier(), unifier) .thenChoose(unifications(getExpression(), fieldAccess.getExpression())) .thenChoose(unifications(type(), ASTHelpers.getSymbol(fieldAccess).asType())); } return Choice.none(); }