@Override public Boolean visitMemberReference(MemberReferenceTree node, TreePath p) { if (p == null) return super.visitMemberReference(node, p); MemberReferenceTree t = (MemberReferenceTree) p.getLeaf(); if (!node.getMode().equals(t.getMode())) return false; if (!scan(node.getQualifierExpression(), t.getQualifierExpression(), p)) return false; String ident = t.getName().toString(); if (ident.startsWith("$")) { //XXX: there should be a utility method for this check if (bindState.variables2Names.containsKey(ident)) { return node.getName().contentEquals(bindState.variables2Names.get(ident)); } else { bindState.variables2Names.put(ident, node.getName().toString()); } return true; } return node.getName().contentEquals(t.getName()); }
@Override public Void visitMemberReference(MemberReferenceTree node, Void p) { Element el = info.getTrees().getElement(getCurrentPath()); if (toFind.equals(el)) { try { int[] span = treeUtils.findNameSpan(node); if(span != null) { MutablePositionRegion region = createRegion(doc, span[0], span[1]); usages.add(region); } } catch (BadLocationException ex) { Exceptions.printStackTrace(ex); } } return super.visitMemberReference(node, p); }
/** * Gets the symbol for a tree. Returns null if this tree does not have a symbol because it is of * the wrong type, if {@code tree} is null, or if the symbol cannot be found due to a compilation * error. */ // TODO(eaftan): refactor other code that accesses symbols to use this method public static Symbol getSymbol(Tree tree) { if (tree instanceof JCFieldAccess) { return ((JCFieldAccess) tree).sym; } if (tree instanceof JCIdent) { return ((JCIdent) tree).sym; } if (tree instanceof JCMethodInvocation) { return ASTHelpers.getSymbol((MethodInvocationTree) tree); } if (tree instanceof JCNewClass) { return ASTHelpers.getSymbol((NewClassTree) tree); } if (tree instanceof MemberReferenceTree) { return ((JCMemberReference) tree).sym; } if (tree instanceof JCAnnotatedType) { return getSymbol(((JCAnnotatedType) tree).underlyingType); } return getDeclaredSymbol(tree); }
/** * Returns the receiver of an expression. * * <p>Examples: * * <pre>{@code * a.foo() ==> a * a.b.foo() ==> a.b * a.bar().foo() ==> a.bar() * a.b.c ==> a.b * a.b().c ==> a.b() * this.foo() ==> this * foo() ==> null * TheClass.aStaticMethod() ==> TheClass * aStaticMethod() ==> null * aStaticallyImportedMethod() ==> null * }</pre> */ @Nullable public static ExpressionTree getReceiver(ExpressionTree expressionTree) { if (expressionTree instanceof MethodInvocationTree) { ExpressionTree methodSelect = ((MethodInvocationTree) expressionTree).getMethodSelect(); if (methodSelect instanceof IdentifierTree) { return null; } return getReceiver(methodSelect); } else if (expressionTree instanceof MemberSelectTree) { return ((MemberSelectTree) expressionTree).getExpression(); } else if (expressionTree instanceof MemberReferenceTree) { return ((MemberReferenceTree) expressionTree).getQualifierExpression(); } else { throw new IllegalStateException( String.format( "Expected expression '%s' to be a method invocation or field access, but was %s", expressionTree, expressionTree.getKind())); } }
@Override public Choice<State<JCMemberReference>> visitMemberReference( final MemberReferenceTree node, State<?> state) { return chooseSubtrees( state, s -> unifyExpression(node.getQualifierExpression(), s), expr -> maker() .Reference( node.getMode(), (Name) node.getName(), expr, List.convert( JCExpression.class, (List<? extends ExpressionTree>) node.getTypeArguments()))); }
@Override public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) { if (!tree.getName().contentEquals("equals")) { return NO_MATCH; } Type predicateType = predicateType(ASTHelpers.getType(tree), state); Type receiverType = getReceiverType(tree); if (EqualsIncompatibleType.compatibilityOfTypes(receiverType, predicateType, state) .compatible()) { return NO_MATCH; } return buildDescription(tree) .setMessage( String.format( "Using %s::equals as Predicate<%s>; the predicate will always return false", prettyType(receiverType), prettyType(predicateType))) .build(); }
@Override public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) { if (COMPILING_SUPPORT_LIBRARY_MATCHER.matches(tree, state)) { return Description.NO_MATCH; } Type refType = ASTHelpers.getUpperBound(ASTHelpers.getResultType(tree), state.getTypes()); if (checkEnclosingTypes(refType, state)) { return describe(tree, refType.asElement().enclClass(), state); } Symbol symbol = ASTHelpers.getSymbol(tree); if (!(symbol instanceof MethodSymbol)) { return Description.NO_MATCH; } MethodSymbol method = (MethodSymbol) symbol; // Directly calling a method that's restricted, or is declared on a restricted class return matchInvokedMethod(tree, method, state); }
/** * Detect member references that implement an interface that return Object, but resolve to a * method that returns Future. */ @Override public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) { Description description = super.matchMemberReference(tree, state); if (Description.NO_MATCH == description) { if (allOf( (t, s) -> t.getMode() == ReferenceMode.INVOKE, FutureReturnValueIgnored::isObjectReturningMethodReferenceExpression, not((t, s) -> isWhitelistedInterfaceType(((JCMemberReference) t).type, s)), not((t, s) -> isThrowingFunctionalInterface(s, ((JCMemberReference) t).type)), specializedMatcher()) .matches(tree, state)) { return describeMatch(tree); } } return description; }
@Override public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) { if (allOf( (t, s) -> t.getMode() == ReferenceMode.INVOKE, AbstractReturnValueIgnored::isVoidReturningMethodReferenceExpression, // Skip cases where the method we're referencing really does return void. We're only // looking for cases where the referenced method does not return void, but it's being // used on a void-returning functional interface. not((t, s) -> ASTHelpers.isVoidType(ASTHelpers.getSymbol(tree).getReturnType(), s)), not((t, s) -> isThrowingFunctionalInterface(s, ((JCMemberReference) t).type)), specializedMatcher()) .matches(tree, state)) { return describeMatch(tree); } return Description.NO_MATCH; }
@Override public CodeModel visitMemberReference(MemberReferenceTree node, VisitContext p) { if (node.getMode() == MemberReferenceTree.ReferenceMode.INVOKE) { JCTree.JCMemberReference refTree = (JCTree.JCMemberReference) node; ExecutableElement method = (ExecutableElement) refTree.sym; MethodSignature signature = createMethodSignature(method, false); ExpressionModel expression = scan(node.getQualifierExpression(), p); if (expression instanceof ThisModel) { p.getReferencedMethods().add(node.getName().toString()); } ExpressionModel methodReferenceExpression = expression.onMethodReference(signature); return methodReferenceExpression; } else { throw new UnsupportedOperationException("New reference not implemented yet"); } }
@Override public Tree visitMemberReference(MemberReferenceTree tree, Void p) { MemberReferenceTree n = make.MemberReference(tree.getMode(), tree.getName(), tree.getQualifierExpression(), (List<ExpressionTree>)tree.getTypeArguments()); model.setType(n, model.getType(tree)); comments.copyComments(tree, n); model.setPos(n, model.getPos(tree)); return n; }
public void testMethodReferenceDiff() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = hierbas.del.litoral.Test :: taragui;\n" + " }\n" + "}\n" ); String golden = "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test :: taragui;\n" + " }\n" + "}\n"; JavaSource src = getJavaSource(testFile); Task<WorkingCopy> task = new Task<WorkingCopy>() { public void run(final WorkingCopy workingCopy) throws IOException { workingCopy.toPhase(Phase.RESOLVED); final TreeMaker make = workingCopy.getTreeMaker(); new ErrorAwareTreeScanner<Void, Void>() { @Override public Void visitMemberReference(MemberReferenceTree node, Void p) { workingCopy.rewrite(node, make.MemberReference(node.getMode(), make.Identifier("Test"), node.getName(), node.getTypeArguments())); return super.visitMemberReference(node, p); } }.scan(workingCopy.getCompilationUnit(), null); } }; src.runModificationTask(task).commit(); String res = TestUtilities.copyFileToString(testFile); System.err.println(res); assertEquals(golden, res); }
public void testMethodReferenceNameDiff() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test :: taragui;\n" + " }\n" + "}\n" ); String golden = "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test :: taragui2;\n" + " }\n" + "}\n"; JavaSource src = getJavaSource(testFile); Task<WorkingCopy> task = new Task<WorkingCopy>() { public void run(final WorkingCopy workingCopy) throws IOException { workingCopy.toPhase(Phase.RESOLVED); final TreeMaker make = workingCopy.getTreeMaker(); new ErrorAwareTreeScanner<Void, Void>() { @Override public Void visitMemberReference(MemberReferenceTree node, Void p) { workingCopy.rewrite(node, make.setLabel(node, "taragui2")); return super.visitMemberReference(node, p); } }.scan(workingCopy.getCompilationUnit(), null); } }; src.runModificationTask(task).commit(); String res = TestUtilities.copyFileToString(testFile); System.err.println(res); assertEquals(golden, res); }
public void testMethodReferenceFirstTypeParam() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test::taragui;\n" + " }\n" + "}\n" ); String golden = "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test::<String>taragui;\n" + " }\n" + "}\n"; JavaSource src = getJavaSource(testFile); Task<WorkingCopy> task = new Task<WorkingCopy>() { public void run(final WorkingCopy workingCopy) throws IOException { workingCopy.toPhase(Phase.RESOLVED); final TreeMaker make = workingCopy.getTreeMaker(); new ErrorAwareTreeScanner<Void, Void>() { @Override public Void visitMemberReference(MemberReferenceTree node, Void p) { workingCopy.rewrite(node, make.MemberReference(node.getMode(), node.getQualifierExpression(), node.getName(), Collections.singletonList(make.Identifier("String")))); return super.visitMemberReference(node, p); } }.scan(workingCopy.getCompilationUnit(), null); } }; src.runModificationTask(task).commit(); String res = TestUtilities.copyFileToString(testFile); System.err.println(res); assertEquals(golden, res); }
public void testMethodReferenceLastTypeParam() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test::<String>taragui;\n" + " }\n" + "}\n" ); String golden = "package hierbas.del.litoral;\n\n" + "public class Test {\n" + " public static void taragui() {\n" + " Runnable r = Test::taragui;\n" + " }\n" + "}\n"; JavaSource src = getJavaSource(testFile); Task<WorkingCopy> task = new Task<WorkingCopy>() { public void run(final WorkingCopy workingCopy) throws IOException { workingCopy.toPhase(Phase.RESOLVED); final TreeMaker make = workingCopy.getTreeMaker(); new ErrorAwareTreeScanner<Void, Void>() { @Override public Void visitMemberReference(MemberReferenceTree node, Void p) { workingCopy.rewrite(node, make.MemberReference(node.getMode(), node.getQualifierExpression(), node.getName(), null)); return super.visitMemberReference(node, p); } }.scan(workingCopy.getCompilationUnit(), null); } }; src.runModificationTask(task).commit(); String res = TestUtilities.copyFileToString(testFile); System.err.println(res); assertEquals(golden, res); }
@Override public Void visitMemberReference(MemberReferenceTree node, EnumSet<UseTypes> p) { scan(node.getQualifierExpression(), EnumSet.of(UseTypes.READ)); tl.moveToEnd(node.getQualifierExpression()); scan(node.getTypeArguments(), null); tl.moveToEnd(node.getTypeArguments()); handlePossibleIdentifier(getCurrentPath(), EnumSet.of(UseTypes.EXECUTE)); firstIdentifier(node.getName().toString()); return null; }
private static Token<JavaTokenId> findIdentifierSpanImpl(CompilationInfo info, MemberReferenceTree tree, CompilationUnitTree cu, SourcePositions positions) { int start = (int)positions.getStartPosition(cu, tree); int endPosition = (int)positions.getEndPosition(cu, tree); if (start == (-1) || endPosition == (-1)) return null; String member = tree.getName().toString(); TokenHierarchy<?> th = info.getTokenHierarchy(); TokenSequence<JavaTokenId> ts = th.tokenSequence(JavaTokenId.language()); if (ts.move(endPosition) == Integer.MAX_VALUE) { return null; } if (ts.moveNext()) { while (ts.offset() >= start) { Token<JavaTokenId> t = ts.token(); if (t.id() == JavaTokenId.IDENTIFIER && member.equals(info.getTreeUtilities().decodeIdentifier(t.text()).toString())) { return t; } if (!ts.movePrevious()) break; } } return null; }
private static Token<JavaTokenId> createHighlightImpl(CompilationInfo info, Document doc, TreePath tree) { Tree leaf = tree.getLeaf(); SourcePositions positions = info.getTrees().getSourcePositions(); CompilationUnitTree cu = info.getCompilationUnit(); //XXX: do not use instanceof: if (leaf instanceof MethodTree || leaf instanceof VariableTree || leaf instanceof ClassTree || leaf instanceof MemberSelectTree || leaf instanceof AnnotatedTypeTree || leaf instanceof MemberReferenceTree) { return findIdentifierSpan(info, doc, tree); } int start = (int) positions.getStartPosition(cu, leaf); int end = (int) positions.getEndPosition(cu, leaf); if (start == Diagnostic.NOPOS || end == Diagnostic.NOPOS) { return null; } TokenHierarchy<?> th = info.getTokenHierarchy(); TokenSequence<JavaTokenId> ts = th.tokenSequence(JavaTokenId.language()); if (ts.move(start) == Integer.MAX_VALUE) { return null; } if (ts.moveNext()) { Token<JavaTokenId> token = ts.token(); if (ts.offset() == start && token != null) { final JavaTokenId id = token.id(); if (id == JavaTokenId.IDENTIFIER) { return token; } if (id == JavaTokenId.THIS || id == JavaTokenId.SUPER) { return ts.offsetToken(); } } } return null; }
@Override public Void visitMemberReference(MemberReferenceTree tree, List<Node> d) { List<Node> below = new ArrayList<Node>(); addCorrespondingElement(below); addCorrespondingType(below); addCorrespondingComments(below); super.visitMemberReference(tree, below); d.add(new TreeNode(info, getCurrentPath(), below)); return null; }
public static Tree newClassToConstructorReference(WorkingCopy copy, Tree tree, TreePath contextPath, List<? extends VariableTree> passedParameters, boolean addTypeCast) { NewClassTree nct = (NewClassTree)tree; if (passedParameters.size() != nct.getArguments().size()) { return null; } Element e = copy.getTrees().getElement(new TreePath(contextPath, tree)); if (e == null || e.getKind() != ElementKind.CONSTRUCTOR) { return null; } TreeMaker make = copy.getTreeMaker(); return possiblyCast(copy, make.MemberReference(MemberReferenceTree.ReferenceMode.NEW, nct.getIdentifier(), "new", (List<? extends ExpressionTree>)nct.getTypeArguments()), contextPath, addTypeCast); }
public static Tree methodInvocationToMemberReference(WorkingCopy copy, Tree tree, TreePath contextPath, List<? extends VariableTree> passedParameters, boolean addTypeCast) { if (tree.getKind() != Tree.Kind.METHOD_INVOCATION) return null; ExpressionTree ms = ((MethodInvocationTree)tree).getMethodSelect(); Element e = copy.getTrees().getElement(new TreePath(contextPath, ms)); if (e == null || e.getKind() != ElementKind.METHOD) { return null; } Name name = null; ExpressionTree expr = null; TreeMaker make = copy.getTreeMaker(); if (ms.getKind() == Tree.Kind.IDENTIFIER) { name = ((IdentifierTree)ms).getName(); expr = e.getModifiers().contains(Modifier.STATIC) ? make.Identifier(e.getEnclosingElement()) : make.Identifier("this"); //NOI18N } else if (ms.getKind() == Tree.Kind.MEMBER_SELECT) { name = ((MemberSelectTree)ms).getIdentifier(); if (passedParameters.size() == ((MethodInvocationTree)tree).getArguments().size()) { expr = ((MemberSelectTree)ms).getExpression(); } else { expr = make.Identifier(e.getEnclosingElement()); } } if (name == null || expr == null) { return null; } return possiblyCast(copy, make.MemberReference(MemberReferenceTree.ReferenceMode.INVOKE, expr, name, Collections.<ExpressionTree>emptyList()), contextPath, addTypeCast ); }
@Override public Mirror visitMemberReference(MemberReferenceTree node, EvaluationContext p) { /** * A tree node for a member reference expression. * There are two kinds of member references: * method references (ReferenceMode.INVOKE) and * constructor references (ReferenceMode.NEW). * It creates a new class, which is unsupported. */ Assert.error(node, "noNewClassWithBody"); return super.visitMemberReference(node, p); }
public static KindName kindName(MemberReferenceTree.ReferenceMode mode) { switch (mode) { case INVOKE: return KindName.METHOD; case NEW: return KindName.CONSTRUCTOR; default : throw new AssertionError("Unexpected mode: "+ mode); } }
@Override public Void visitMemberReference(MemberReferenceTree node, Void p) { if (!done) { index++; } if (tree == node) { done = true; } return super.visitMemberReference(node, p); }
@Override public Void visitMemberReference(MemberReferenceTree tree, VisitorState visitorState) { VisitorState state = visitorState.withPath(getCurrentPath()); for (MemberReferenceTreeMatcher matcher : memberReferenceMatchers) { if (!isSuppressed(matcher, state)) { try { reportMatch(matcher.matchMemberReference(tree, state), tree, state); } catch (Throwable t) { handleError(matcher, t); } } } return super.visitMemberReference(tree, state); }
@Override public UMemberReference visitMemberReference(MemberReferenceTree tree, Void v) { return UMemberReference.create( tree.getMode(), template(tree.getQualifierExpression()), tree.getName(), (tree.getTypeArguments() == null) ? null : templateExpressions(tree.getTypeArguments())); }
@Override public Choice<Unifier> visitMemberReference(MemberReferenceTree node, Unifier unifier) { return Choice.condition(getMode() == node.getMode(), unifier) .thenChoose(unifications(getQualifierExpression(), node.getQualifierExpression())) .thenChoose(unifications(getName(), node.getName())) .thenChoose(unifications(getTypeArguments(), node.getTypeArguments())); }
@Override public String toString() { if (tree instanceof LambdaExpressionTree) { return "FunctionalInterfaceNode:" + ((LambdaExpressionTree) tree).getBodyKind(); } else if (tree instanceof MemberReferenceTree) { return "FunctionalInterfaceNode:" + ((MemberReferenceTree) tree).getName(); } else { // This should never happen. ErrorReporter.errorAbort("Invalid tree in FunctionalInterfaceNode"); return null; // Dead code } }
@Override public Node visitMemberReference(MemberReferenceTree tree, Void p) { Tree enclosingExpr = tree.getQualifierExpression(); if (enclosingExpr != null) { scan(enclosingExpr, p); } Node node = new FunctionalInterfaceNode(tree); extendWithNode(node); return node; }
@Override public Void visitMemberReference(MemberReferenceTree expected, Tree actual) { Optional<MemberReferenceTree> other = checkTypeAndCast(expected, actual); if (!other.isPresent()) { addTypeMismatch(expected, actual); return null; } scan(expected.getQualifierExpression(), other.get().getQualifierExpression()); parallelScan(expected.getTypeArguments(), other.get().getTypeArguments()); checkForDiff(expected.getName().contentEquals(other.get().getName()), "Expected identifier to be <%s> but was <%s>.", expected.getName(), other.get().getName()); return null; }