Skip to content

Commit

Permalink
Showing return types of chained method invocation even when the end r…
Browse files Browse the repository at this point in the history
…esult is used e.g. as a method argument.
  • Loading branch information
jlahoda authored and matthiasblaesing committed Dec 8, 2022
1 parent d9c4dd5 commit 520b92d
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.swing.text.Document;
import org.netbeans.api.java.lexer.JavaTokenId;
Expand Down Expand Up @@ -228,7 +229,9 @@ protected boolean process(CompilationInfo info, final Document doc, ErrorDescrip
return true;

if (computeUnusedImports) {
setter.setHighlights(doc, extraColoring, v.preText);
Map<int[], String> preTextWithSpans = new HashMap<>();
v.preText.forEach((pos, text) -> preTextWithSpans.put(new int[] {pos, pos + 1}, text));
setter.setHighlights(doc, extraColoring, preTextWithSpans);
}

setter.setColorings(doc, newColoring);
Expand Down Expand Up @@ -280,7 +283,7 @@ private static class DetectorVisitor extends CancellableTreePathScanner<Void, Vo
private Map<Tree, List<Token>> tree2Tokens;
private List<Token> contextKeywords;
private List<Pair<int[], Coloring>> extraColoring;
private Map<int[], String> preText;
private Map<Integer, String> preText;
private TokenList tl;
private long memberSelectBypass = -1;
private SourcePositions sourcePositions;
Expand Down Expand Up @@ -691,6 +694,7 @@ public Void visitUses(UsesTree tree, Void p) {

@Override
public Void visitMethodInvocation(MethodInvocationTree tree, Void p) {
int startTokenIndex = tl.index();
Tree possibleIdent = tree.getMethodSelect();

if (possibleIdent.getKind() == Kind.IDENTIFIER) {
Expand Down Expand Up @@ -725,21 +729,23 @@ public Void visitMethodInvocation(MethodInvocationTree tree, Void p) {

scan(tree.getTypeArguments(), null);

for (ExpressionTree arg : tree.getArguments()) {
addChainedTypes(new TreePath(getCurrentPath(), arg));
}

scan(tree.getArguments(), p);

addParameterInlineHint(tree);
return null;
}

@Override
public Void visitExpressionStatement(ExpressionStatementTree node, Void p) {
TreePath current = new TreePath(getCurrentPath(), node.getExpression());
addChainedTypes(current);
return super.visitExpressionStatement(node, p);
Tree parent = getCurrentPath().getParentPath().getLeaf();
Tree parentParent = getCurrentPath().getParentPath().getParentPath().getLeaf();

if (parent.getKind() != Kind.MEMBER_SELECT ||
parentParent.getKind() != Kind.METHOD_INVOCATION ||
((MemberSelectTree) parent).getExpression() != tree) {
int afterInvocation = tl.index();
tl.resetToIndex(startTokenIndex);
addChainedTypes(getCurrentPath());
tl.resetToIndex(afterInvocation);
}

return null;
}

private void addChainedTypes(TreePath current) {
Expand All @@ -758,29 +764,60 @@ private void addChainedTypes(TreePath current) {
break OUTER;
}
}
int prevIndex = tl.index();
Collections.reverse(chain);
List<Pair<String, Integer>> typeToPosition = new ArrayList<>();
List<Pair<String, Integer>> forcedTypeToPosition = new ArrayList<>();
for (TreePath tp : chain) {
long end = info.getTrees().getSourcePositions().getEndPosition(tp.getCompilationUnit(), tp.getLeaf());
tl.moveToOffset(end);
Token t = tl.currentToken();
if (t != null && (t.id() == JavaTokenId.COMMA || t.id() == JavaTokenId.SEMICOLON)) {
tl.moveNext();
t = tl.currentToken();
} else if (t != null && t.id() == JavaTokenId.RPAREN) {
while (t != null && t.id() == JavaTokenId.RPAREN) {
tl.moveNext();
t = tl.currentToken();
}
if (t != null && (t.id() == JavaTokenId.COMMA || t.id() == JavaTokenId.SEMICOLON)) {
tl.moveNext();
t = tl.currentToken();
}
}
int pos;
if (t != null && t.id() == JavaTokenId.WHITESPACE && (pos = t.text().toString().indexOf("\n")) != -1) {
TypeMirror type = info.getTrees().getTypeMirror(tp);
String typeName = info.getTypeUtilities().getTypeName(type).toString();
if (typeToPosition.isEmpty() || !typeName.equals(typeToPosition.get(typeToPosition.size() - 1).first())) {
typeToPosition.add(Pair.of(typeName, tl.offset() + pos));
String typeName;
if (type.getKind().isPrimitive() || type.getKind() == TypeKind.DECLARED) {
typeName = info.getTypeUtilities().getTypeName(type).toString();
} else {
typeName = "";
}
int preTextPos = tl.offset() + pos;
if (typeToPosition.isEmpty() || !typeName.equals(typeToPosition.get(typeToPosition.size() - 1).first()) || preText.containsKey(preTextPos)) {
typeToPosition.add(Pair.of(typeName, preTextPos));
}
if (preText.containsKey(preTextPos)) {
forcedTypeToPosition.add(Pair.of(typeName, preTextPos));
}
}
}
if (typeToPosition.size() >= 2) {
for (Pair<String, Integer> typeAndPosition : typeToPosition) {
preText.put(new int[] {(int) typeAndPosition.second(), (int) typeAndPosition.second() + 1},
" " + typeAndPosition.first());
preText.compute(typeAndPosition.second(),
(p, n) -> (n == null ? " " : ";" ) + " " + typeAndPosition.first());
}
} else {
for (Pair<String, Integer> typeAndPosition : forcedTypeToPosition) {
preText.compute(typeAndPosition.second(),
(p, n) -> (n == null ? " " : n + ";" ) + " " + typeAndPosition.first());
}
}
tl.resetToIndex(prevIndex);
}

@Override
public Void visitExpressionStatement(ExpressionStatementTree node, Void p) {
return super.visitExpressionStatement(node, p);
}

@Override
Expand Down Expand Up @@ -1085,7 +1122,6 @@ private void addParameterInlineHint(Tree tree) {
Element invoked = info.getTrees().getElement(pp);
if (invoked != null && (invoked.getKind() == ElementKind.METHOD || invoked.getKind() == ElementKind.CONSTRUCTOR)) {
long start = sourcePositions.getStartPosition(info.getCompilationUnit(), tree);
long end = start + 1;
ExecutableElement invokedMethod = (ExecutableElement) invoked;
pos = Math.min(pos, invokedMethod.getParameters().size() - 1);
if (pos != (-1)) {
Expand All @@ -1096,7 +1132,7 @@ private void addParameterInlineHint(Tree tree) {
shouldBeAdded = false;
}
if (shouldBeAdded) {
preText.put(new int[] {(int) start, (int) end},
preText.put((int) start,
invokedMethod.getParameters().get(pos).getSimpleName() + ":");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ public void testChainTypes() throws Exception {
"[PRIVATE, METHOD], 5:10-5:14",
"[ Test<Integer>], 5:16-6:0",
"[PRIVATE, METHOD], 6:10-6:14",
"[ Test<String>], 6:17-7:0",
"[PUBLIC, CLASS], 8:12-8:16",
"[PUBLIC, CLASS], 8:17-8:24",
"[PRIVATE, METHOD, DECLARATION], 8:26-8:30",
Expand Down Expand Up @@ -875,6 +876,7 @@ public void testChainTypes2() throws Exception {
"[PRIVATE, METHOD], 5:16-5:20",
"[ Test<Integer>], 5:22-6:0",
"[PRIVATE, METHOD], 6:16-6:20",
"[ Test<String>], 6:23-7:0",
"[t2:], 7:14-7:15",
"[PRIVATE, METHOD], 7:16-7:20",
"[ Test<Integer>], 7:22-8:0",
Expand All @@ -883,6 +885,7 @@ public void testChainTypes2() throws Exception {
"[PRIVATE, METHOD], 9:16-9:20",
"[ Test<Integer>], 9:22-10:0",
"[PRIVATE, METHOD], 10:16-10:20",
"[ Test<String>; ], 10:24-11:0",
"[PUBLIC, CLASS], 12:12-12:16",
"[PUBLIC, CLASS], 12:17-12:24",
"[PRIVATE, METHOD, DECLARATION], 12:26-12:30",
Expand Down Expand Up @@ -910,7 +913,7 @@ public void testChainTypes3() throws Exception {
"package test;\n" +
"public class Test<T> {\n" +
" public void test(Test<String> t) {\n" +
" testChain1(testChain2(testChain1(t.run1()\n" +
" testChain3(testChain2(testChain1(t.run1()\n" +
" .run2()\n" +
" .run3()\n" +
" .run4())));\n" +
Expand All @@ -930,7 +933,10 @@ public void testChainTypes3() throws Exception {
" public Test<Integer> testChain1(Test<String> t1) {\n" +
" return null;\n" +
" }\n" +
" public Test<String> testChain2(Test<Integer> t1) {\n" +
" public Test<Number> testChain2(Test<Integer> t1) {\n" +
" return null;\n" +
" }\n" +
" public String testChain3(Test<Number> t1) {\n" +
" return null;\n" +
" }\n" +
"}\n",
Expand All @@ -952,6 +958,7 @@ public void testChainTypes3() throws Exception {
"[PRIVATE, METHOD], 5:16-5:20",
"[ Test<Integer>], 5:22-6:0",
"[PRIVATE, METHOD], 6:16-6:20",
"[ Test<String>; Test<Integer>; Test<Number>; String], 6:26-7:0",
"[PUBLIC, CLASS], 8:12-8:16",
"[PUBLIC, CLASS], 8:17-8:24",
"[PRIVATE, METHOD, DECLARATION], 8:26-8:30",
Expand All @@ -971,11 +978,89 @@ public void testChainTypes3() throws Exception {
"[PUBLIC, CLASS], 20:41-20:47",
"[PARAMETER, DECLARATION], 20:49-20:51",
"[PUBLIC, CLASS], 23:11-23:15",
"[PUBLIC, CLASS], 23:16-23:22",
"[ABSTRACT, PUBLIC, CLASS], 23:16-23:22",
"[PUBLIC, METHOD, DECLARATION], 23:24-23:34",
"[PUBLIC, CLASS], 23:35-23:39",
"[PUBLIC, CLASS], 23:40-23:47",
"[PARAMETER, DECLARATION], 23:49-23:51");
"[PARAMETER, DECLARATION], 23:49-23:51",
"[PUBLIC, CLASS], 26:11-26:17",
"[PUBLIC, METHOD, DECLARATION], 26:18-26:28",
"[PUBLIC, CLASS], 26:29-26:33",
"[ABSTRACT, PUBLIC, CLASS], 26:34-26:40",
"[PARAMETER, DECLARATION], 26:42-26:44");
}

public void testChainTypes4() throws Exception {
setShowPrependedText(true);
performTest("Test.java",
"package test;\n" +
"public class Test<T> {\n" +
" public void test(Test<String> t) {\n" +
" voidMethod(t.run1()\n" +
" .run2()\n" +
" .run3()\n" +
" .run4())));\n" +
" undefinedMethod(t.run1()\n" +
" .run2()\n" +
" .run3()\n" +
" .run4())));\n" +
" }\n" +
" private Test<Integer> run1() {\n" +
" return null;\n" +
" }\n" +
" private Test<String> run2() {\n" +
" return null;\n" +
" }\n" +
" private Test<Integer> run3() {\n" +
" return null;\n" +
" }\n" +
" private Test<String> run4() {\n" +
" return null;\n" +
" }\n" +
" public void voidMethod(Test<String> t1) {\n" +
" }\n" +
"}\n",
"[PUBLIC, CLASS, DECLARATION], 1:13-1:17",
"[PUBLIC, METHOD, DECLARATION], 2:16-2:20",
"[PUBLIC, CLASS], 2:21-2:25",
"[PUBLIC, CLASS], 2:26-2:32",
"[PARAMETER, DECLARATION], 2:34-2:35",
"[PUBLIC, METHOD], 3:8-3:18",
"[t1:], 3:19-3:20",
"[PRIVATE, METHOD], 3:21-3:25",
"[ Test<Integer>], 3:27-4:0",
"[PRIVATE, METHOD], 4:16-4:20",
"[ Test<String>], 4:22-5:0",
"[PRIVATE, METHOD], 5:16-5:20",
"[ Test<Integer>], 5:22-6:0",
"[PRIVATE, METHOD], 6:16-6:20",
"[ Test<String>; ], 6:26-7:0",
"[STATIC, PUBLIC, CLASS], 7:8-7:23",
"[PARAMETER], 7:24-7:25",
"[PRIVATE, METHOD], 7:26-7:30",
"[ Test<Integer>], 7:32-8:0",
"[PRIVATE, METHOD], 8:16-8:20",
"[ Test<String>], 8:22-9:0",
"[PRIVATE, METHOD], 9:16-9:20",
"[ Test<Integer>], 9:22-10:0",
"[PRIVATE, METHOD], 10:16-10:20",
"[ Test<String>; ], 10:26-11:0",
"[PUBLIC, CLASS], 12:12-12:16",
"[PUBLIC, CLASS], 12:17-12:24",
"[PRIVATE, METHOD, DECLARATION], 12:26-12:30",
"[PUBLIC, CLASS], 15:12-15:16",
"[PUBLIC, CLASS], 15:17-15:23",
"[PRIVATE, METHOD, DECLARATION], 15:25-15:29",
"[PUBLIC, CLASS], 18:12-18:16",
"[PUBLIC, CLASS], 18:17-18:24",
"[PRIVATE, METHOD, DECLARATION], 18:26-18:30",
"[PUBLIC, CLASS], 21:12-21:16",
"[PUBLIC, CLASS], 21:17-21:23",
"[PRIVATE, METHOD, DECLARATION], 21:25-21:29",
"[PUBLIC, METHOD, DECLARATION], 24:16-24:26",
"[PUBLIC, CLASS], 24:27-24:31",
"[PUBLIC, CLASS], 24:32-24:38",
"[PARAMETER, DECLARATION], 24:40-24:42");
}

public void testRawStringLiteralNETBEANS_5118() throws Exception {
Expand Down

0 comments on commit 520b92d

Please sign in to comment.