You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by lk...@apache.org on 2020/09/24 15:16:07 UTC
[netbeans] branch master updated: Show types for chained method
invocations.
This is an automated email from the ASF dual-hosted git repository.
lkishalmi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new c9ff717 Show types for chained method invocations.
c9ff717 is described below
commit c9ff7179ff55d10abb217b2b13d3d988489c5f5f
Author: Jan Lahoda <jl...@netbeans.org>
AuthorDate: Sun Sep 13 12:24:49 2020 +0200
Show types for chained method invocations.
---
.../editor/lib2/view/ParagraphViewChildren.java | 10 +++--
.../base/semantic/SemanticHighlighterBase.java | 49 +++++++++++++++++++++
.../java/editor/base/semantic/TokenList.java | 15 ++++++-
.../java/editor/base/semantic/DetectorTest.java | 51 ++++++++++++++++++++++
4 files changed, 121 insertions(+), 4 deletions(-)
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ParagraphViewChildren.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ParagraphViewChildren.java
index 38c2787..3275a68 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ParagraphViewChildren.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ParagraphViewChildren.java
@@ -168,8 +168,8 @@ final class ParagraphViewChildren extends ViewChildren<EditorView> {
view.setRawEndOffset(relEndOffset); // Below offset-gap
view.setParent(pView);
// Possibly assign text layout
- if (view instanceof HighlightsView || (view instanceof PrependedTextView && ((PrependedTextView) view).getDelegate() instanceof HighlightsView)) {
- HighlightsView hView = (HighlightsView) (view instanceof HighlightsView ? view : ((PrependedTextView) view).getDelegate());
+ if (viewOrDelegate(view) instanceof HighlightsView) {
+ HighlightsView hView = (HighlightsView) viewOrDelegate(view);
// Fill in text layout if necessary
if (hView.getTextLayout() == null) { // Fill in text layout
if (docText == null) {
@@ -430,7 +430,7 @@ final class ParagraphViewChildren extends ViewChildren<EditorView> {
while (startIndex < endIndex) {
EditorView view = get(startIndex);
Shape childAlloc = getChildAllocation(startIndex, pAlloc);
- if (view.getClass() == NewlineView.class) {
+ if (viewOrDelegate(view).getClass() == NewlineView.class) {
// Extend till end of screen (docView's width)
Rectangle2D.Double childRect = ViewUtils.shape2Bounds(childAlloc);
DocumentView docView = pView.getDocumentView();
@@ -847,6 +847,10 @@ final class ParagraphViewChildren extends ViewChildren<EditorView> {
return new StringBuilder(10).append(" x=").append(startVisualOffset(index)).toString();
}
+ private View viewOrDelegate(View view) {
+ return view instanceof PrependedTextView ? ((PrependedTextView) view).getDelegate() : view;
+ }
+
private static final class IndexAndAlloc {
/**
diff --git a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
index 00e115d..8146d84 100644
--- a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
+++ b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
@@ -21,6 +21,7 @@ package org.netbeans.modules.java.editor.base.semantic;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExportsTree;
+import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberReferenceTree;
@@ -42,9 +43,12 @@ import com.sun.source.util.TreePath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -56,6 +60,7 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
+import javax.lang.model.type.TypeMirror;
import javax.swing.text.Document;
import org.netbeans.api.java.lexer.JavaTokenId;
import org.netbeans.api.java.source.CompilationInfo;
@@ -714,6 +719,50 @@ public abstract class SemanticHighlighterBase extends JavaParserResultTask {
}
@Override
+ public Void visitExpressionStatement(ExpressionStatementTree node, Void p) {
+ List<TreePath> chain = new ArrayList<>(); //TODO: avoid creating an instance if possible!
+ TreePath current = new TreePath(getCurrentPath(), node.getExpression());
+ OUTER: while (true) {
+ chain.add(current);
+ switch (current.getLeaf().getKind()) {
+ case METHOD_INVOCATION:
+ MethodInvocationTree mit = (MethodInvocationTree) current.getLeaf();
+ if (mit.getMethodSelect().getKind() == Kind.MEMBER_SELECT) {
+ current = new TreePath(new TreePath(current, mit.getMethodSelect()), ((MemberSelectTree) mit.getMethodSelect()).getExpression());
+ break;
+ }
+ break OUTER;
+ default:
+ break OUTER;
+ }
+ }
+ int prevIndex = tl.index();
+ Collections.reverse(chain);
+ List<Pair<String, Integer>> typeToPosition = new ArrayList<>();
+ for (TreePath tp : chain) {
+ long end = info.getTrees().getSourcePositions().getEndPosition(tp.getCompilationUnit(), tp.getLeaf());
+ tl.moveToOffset(end);
+ Token t = tl.currentToken();
+ int pos;
+ if (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));
+ }
+ }
+ }
+ if (typeToPosition.size() >= 2) {
+ for (Pair<String, Integer> typeAndPosition : typeToPosition) {
+ preText.put(new int[] {(int) typeAndPosition.second(), (int) typeAndPosition.second() + 1},
+ " " + typeAndPosition.first());
+ }
+ }
+ tl.resetToIndex(prevIndex);
+ return super.visitExpressionStatement(node, p);
+ }
+
+ @Override
public Void visitIdentifier(IdentifierTree tree, Void p) {
if (info.getTreeUtilities().isSynthetic(getCurrentPath()))
return null;
diff --git a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
index cadc339..bc942f9 100644
--- a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
+++ b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
@@ -355,7 +355,20 @@ public class TokenList {
}
});
}
-
+
+ public int offset() {
+ return ts.offset();
+ }
+
+ public int index() {
+ return ts.index();
+ }
+
+ public void resetToIndex(int index) {
+ ts.moveIndex(index);
+ ts.moveNext();
+ }
+
private static List<TokenSequence<?>> embeddedTokenSequences(TokenHierarchy<Document> th, int offset) {
TokenSequence<?> embedded = th.tokenSequence();
List<TokenSequence<?>> sequences = new ArrayList<TokenSequence<?>>();
diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
index 726b65c..c34a3eb 100644
--- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
@@ -664,6 +664,57 @@ public class DetectorTest extends TestBase {
"[PACKAGE_PRIVATE, CONSTRUCTOR], 2:19-2:25");
}
+ public void testChainTypes() throws Exception {
+ setShowPrependedText(true);
+ performTest("Test.java",
+ "package test;\n" +
+ "public class Test<T> {\n" +
+ " public void test(Test<String> t) {\n" +
+ " 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" +
+ "}\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",
+ "[PARAMETER], 3:8-3:9",
+ "[PRIVATE, METHOD], 3:10-3:14",
+ "[ Test<Integer>], 3:16-4:0",
+ "[PRIVATE, METHOD], 4:10-4:14",
+ "[ Test<String>], 4:16-5:0",
+ "[PRIVATE, METHOD], 5:10-5:14",
+ "[ Test<Integer>], 5:16-6:0",
+ "[PRIVATE, METHOD], 6:10-6:14",
+ "[PUBLIC, CLASS], 8:12-8:16",
+ "[PUBLIC, CLASS], 8:17-8:24",
+ "[PRIVATE, METHOD, DECLARATION], 8:26-8:30",
+ "[PUBLIC, CLASS], 11:12-11:16",
+ "[PUBLIC, CLASS], 11:17-11:23",
+ "[PRIVATE, METHOD, DECLARATION], 11:25-11:29",
+ "[PUBLIC, CLASS], 14:12-14:16",
+ "[PUBLIC, CLASS], 14:17-14:24",
+ "[PRIVATE, METHOD, DECLARATION], 14:26-14:30",
+ "[PUBLIC, CLASS], 17:12-17:16",
+ "[PUBLIC, CLASS], 17:17-17:23",
+ "[PRIVATE, METHOD, DECLARATION], 17:25-17:29");
+ }
+
private void performTest(String fileName) throws Exception {
performTest(fileName, new Performer() {
public void compute(CompilationController parameter, Document doc, final ErrorDescriptionSetter setter) {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists