From 341ec5eafac1c4a236cbd60446043f5b6943adde Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Tue, 9 Apr 2019 21:00:36 +0200
Subject: [PATCH 01/11] A crude prototype of inline (parameter) hints.
---
.../lib2/highlighting/HighlightsList.java | 5 +-
.../lib2/view/HighlightsViewFactory.java | 4 +-
.../view/PrependedTextHighlightsView.java | 104 ++++++++++++++++++
.../semantic/SemanticHighlighterBase.java | 27 ++++-
.../editor/base/semantic/MarkOccDetTest.java | 3 +-
.../java/editor/base/semantic/TestBase.java | 2 +-
.../semantic/HighlightsLayerFactoryImpl.java | 1 +
.../editor/semantic/SemanticHighlighter.java | 27 ++++-
8 files changed, 165 insertions(+), 8 deletions(-)
create mode 100644 ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
index 1b764078727d..335e13d9ae80 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
@@ -20,6 +20,7 @@
package org.netbeans.modules.editor.lib2.highlighting;
import java.awt.Font;
+import java.util.Objects;
import java.util.logging.Logger;
import javax.swing.text.AttributeSet;
import org.netbeans.lib.editor.util.ArrayUtilities;
@@ -157,12 +158,14 @@ public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOff
// Extends beyond first highlight
Font firstFont = ViewUtils.getFont(firstAttrs, defaultFont);
+ Object firstPrependText = firstAttrs.getAttribute("virtual-text-prepend");
int index = 1;
while (true) {
item = get(index);
AttributeSet attrs = item.getAttributes();
Font font = ViewUtils.getFont(attrs, defaultFont);
- if (!font.equals(firstFont)) { // Stop at itemEndOffset
+ Object prependText = attrs != null ? attrs.getAttribute("virtual-text-prepend") : null;
+ if (!font.equals(firstFont) || !Objects.equals(firstPrependText, prependText)) { // Stop at itemEndOffset
if (index == 1) { // Just single attribute set
cutStartItems(1);
startOffset = itemEndOffset; // end offset of first item
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
index 1b2184b3d5ba..3574df72d454 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
@@ -218,8 +218,8 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
}
AttributeSet attrs = hList.cutSameFont(defaultFont, limitOffset, wsEndOffset, docText);
int length = hList.startOffset() - startOffset;
- HighlightsView view = new HighlightsView(length, attrs);
- if (origView instanceof HighlightsView && origView.getLength() == length) { // Reuse
+ HighlightsView view = attrs != null && attrs.getAttribute("virtual-text-prepend") != null ? new PrependedTextHighlightsView(length, attrs) : new HighlightsView(length, attrs);
+ if (origView != null && origView.getClass() == HighlightsView.class && origView.getLength() == length) { // Reuse XXX: reuse disabled for PrependedTextHighlightsView!
HighlightsView origHView = (HighlightsView) origView;
TextLayout origTextLayout = origHView.getTextLayout();
if (origTextLayout != null) {
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
new file mode 100644
index 000000000000..d156c3eed14b
--- /dev/null
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.editor.lib2.view;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.font.TextLayout;
+import java.awt.geom.Rectangle2D;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Position.Bias;
+import org.netbeans.spi.editor.highlighting.HighlightsSequence;
+
+/**
+ * TODO
+ */
+
+public class PrependedTextHighlightsView extends HighlightsView {
+
+ private TextLayout prependedTextLayout;
+ private double leftShift;
+ private double prependedTextWidth;
+ private double moveup;
+
+ public PrependedTextHighlightsView(int length, AttributeSet attributes) {
+ super(length, attributes);
+ }
+
+ @Override
+ void setTextLayout(TextLayout textLayout, float width) {
+ Font font = ViewUtils.getFont(getAttributes(), getDocumentView().op.getDefaultFont());
+ font = font.deriveFont((float) (font.getSize2D() * 0.75));
+ prependedTextLayout = getDocumentView().op.createTextLayout((String) getAttributes().getAttribute("virtual-text-prepend"), font);
+ Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
+ double em = getDocumentView().op.createTextLayout("m", font).getBounds().getWidth();
+ leftShift = em / 2;
+ prependedTextWidth = textBounds.getWidth() + em;
+ double actualTextHeight = textLayout.getBounds().getHeight();
+ moveup = (actualTextHeight - textBounds.getHeight()) / 2;
+// double actualTextHeight = textLayout.getAscent();
+// moveup = (actualTextHeight - prependedTextLayout.getAscent()) / 2;
+ super.setTextLayout(textLayout, (float) (width + prependedTextWidth));
+ }
+
+ //span
+ //view to model???
+ //pain
+ //break
+
+
+ @Override
+ public Shape modelToViewChecked(int offset, Shape alloc, Bias bias) {
+ Shape res = super.modelToViewChecked(offset, alloc, bias);
+ if (bias == Bias.Forward || offset > getStartOffset()) { //TODO: seems not to have any effect?
+ Rectangle2D rect = ViewUtils.shapeAsRect(res);
+ Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
+ rect.setRect(rect.getX() + textBounds.getWidth(), rect.getY(), rect.getWidth(), rect.getHeight());
+ return rect;
+ }
+ return res;
+ }
+
+ @Override
+ public void paint(Graphics2D g, Shape hViewAlloc, Rectangle clipBounds) {
+ Rectangle2D span = ViewUtils.shapeAsRect(hViewAlloc);
+ span.setRect(span.getX() + prependedTextWidth, span.getY(), span.getWidth() - prependedTextWidth, span.getHeight());
+ super.paint(g, span, clipBounds);
+ span.setRect(span.getX() - prependedTextWidth, span.getY(), prependedTextWidth, span.getHeight());
+
+ HighlightsSequence highlights = getDocumentView().getPaintHighlights(this, 0);
+
+ if (highlights.moveNext()) {
+ AttributeSet attrs = highlights.getAttributes();
+ System.err.println("attrs=" + attrs);
+ HighlightsViewUtils.fillBackground(g, span, attrs, getDocumentView().getTextComponent());
+ HighlightsViewUtils.paintBackgroundHighlights(g, span, attrs, getDocumentView()); //TODO: clear some attributes (like boxes)???
+ }
+
+ g.setColor(Color.gray);
+ span.setRect(span.getX() + leftShift, span.getY() - moveup, prependedTextWidth - 2 * leftShift, span.getHeight());
+// g.drawRoundRect((int) span.getX(), (int) span.getY(), (int) span.getWidth(), (int) span.getHeight(), 2, 2);
+ HighlightsViewUtils.paintTextLayout(g, span, prependedTextLayout, getDocumentView());
+ }
+
+}
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 c5b2015db6dc..9065d7ba979b 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
@@ -27,6 +27,7 @@
import com.sun.source.tree.ExportsTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.LambdaExpressionTree;
+import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
@@ -319,7 +320,7 @@ protected boolean process(CompilationInfo info, final Document doc, ErrorDescrip
return true;
if (computeUnusedImports) {
- setter.setHighlights(doc, imports);
+ setter.setHighlights(doc, imports, v.preText);
}
setter.setColorings(doc, newColoring);
@@ -406,6 +407,7 @@ private static class DetectorVisitor extends CancellableTreePathScanner> type2Uses;
private Map> tree2Tokens;
private List contextKeywords;
+ private Map preText;
private TokenList tl;
private long memberSelectBypass = -1;
private SourcePositions sourcePositions;
@@ -419,6 +421,7 @@ private DetectorVisitor(org.netbeans.api.java.source.CompilationInfo info, final
type2Uses = new HashMap>();
tree2Tokens = new IdentityHashMap>();
contextKeywords = new ArrayList<>();
+ preText = new HashMap<>();
tl = new TokenList(info, doc, cancel);
@@ -1060,11 +1063,31 @@ public Void visitMemberReference(MemberReferenceTree node, Void p) {
return null;
}
+ @Override
+ public Void visitLiteral(LiteralTree node, Void p) {
+ TreePath pp = getCurrentPath().getParentPath();
+ if (pp.getLeaf() != null &&
+ pp.getLeaf().getKind() == Kind.METHOD_INVOCATION) {
+ MethodInvocationTree inv = (MethodInvocationTree) pp.getLeaf();
+ int pos = inv.getArguments().indexOf(node);
+ if (pos != (-1)) {
+ Element invoked = info.getTrees().getElement(pp);
+ if (invoked != null && (invoked.getKind() == ElementKind.METHOD || invoked.getKind() == ElementKind.CONSTRUCTOR)) {
+ long start = sourcePositions.getStartPosition(info.getCompilationUnit(), node);
+ long end = sourcePositions.getEndPosition(info.getCompilationUnit(), node);
+ preText.put(new int[] {(int) start, (int) end},
+ ((ExecutableElement) invoked).getParameters().get(pos).getSimpleName() + ":");
+ }
+ }
+ }
+ return super.visitLiteral(node, p);
+ }
+
}
public static interface ErrorDescriptionSetter {
- public void setHighlights(Document doc, Collection highlights);
+ public void setHighlights(Document doc, Collection highlights, Map preText);
public void setColorings(Document doc, Map colorings);
}
}
diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
index c9fb1b19ee40..cd07ba613aa4 100644
--- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
@@ -18,6 +18,7 @@
*/
package org.netbeans.modules.java.editor.base.semantic;
+import java.util.Collections;
import java.util.List;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
@@ -354,7 +355,7 @@ protected void process(CompilationInfo info, Document doc, SchedulerEvent event)
}.processImpl(info, MarkOccurencesSettings.getCurrentNode(), doc, offset);
if (spans != null) {
- setter.setHighlights(doc, spans);
+ setter.setHighlights(doc, spans, Collections.emptyMap());
}
}
}, doCompileRecursively);
diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
index 7aa4cb397621..a095df04e724 100644
--- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
@@ -251,7 +251,7 @@ public void setErrors(Document doc, List errs, List highlights) {
+ public void setHighlights(Document doc, Collection highlights, Map preText) {
for (int[] h : highlights) {
this.highlights.add(new HighlightImpl(doc, h[0], h[1], EnumSet.of(getColoringAttribute())));
}
diff --git a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/HighlightsLayerFactoryImpl.java b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/HighlightsLayerFactoryImpl.java
index 7dc9318eef86..03a98b4267ec 100644
--- a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/HighlightsLayerFactoryImpl.java
+++ b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/HighlightsLayerFactoryImpl.java
@@ -38,6 +38,7 @@ public HighlightsLayer[] createLayers(Context context) {
return new HighlightsLayer[] {
HighlightsLayer.create(SemanticHighlighter.class.getName() + "-1", ZOrder.SYNTAX_RACK.forPosition(1000), false,semantic),
HighlightsLayer.create(SemanticHighlighter.class.getName() + "-2", ZOrder.SYNTAX_RACK.forPosition(1500), false, SemanticHighlighter.getImportHighlightsBag(context.getDocument())),
+ HighlightsLayer.create(SemanticHighlighter.class.getName() + "-3", ZOrder.SYNTAX_RACK.forPosition(1600), false, SemanticHighlighter.getPreTextBag(context.getDocument())),
//the mark occurrences layer should be "above" current row and "below" the search layers:
HighlightsLayer.create(MarkOccurrencesHighlighter.class.getName(), ZOrder.SHOW_OFF_RACK.forPosition(20), true, MarkOccurrencesHighlighter.getHighlightsBag(context.getDocument())),
//"above" mark occurrences, "below" search layers:
diff --git a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
index feae3f3628f6..065d8f80b045 100644
--- a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
+++ b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
@@ -23,12 +23,14 @@
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import javax.swing.text.Document;
+import org.netbeans.api.editor.settings.AttributesUtilities;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.TreePathHandle;
@@ -60,7 +62,7 @@ protected boolean process(final CompilationInfo info, final Document doc) {
public void setErrors(Document doc, List errors, List allUnusedImports) {}
- public void setHighlights(final Document doc, final Collection highlights) {
+ public void setHighlights(final Document doc, final Collection highlights, Map preText) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
OffsetsBag bag = new OffsetsBag(doc);
@@ -69,6 +71,12 @@ public void run() {
bag.addHighlight(highlight[0], highlight[1], ColoringManager.getColoringImpl(unused));
}
getImportHighlightsBag(doc).setHighlights(bag);
+
+ OffsetsBag preTextBag = new OffsetsBag(doc);
+ for (Entry e : preText.entrySet()) {
+ preTextBag.addHighlight(e.getKey()[0], e.getKey()[1], AttributesUtilities.createImmutable("virtual-text-prepend", e.getValue()));
+ }
+ getPreTextBag(doc).setHighlights(preTextBag);
}
});
}
@@ -109,4 +117,21 @@ static OffsetsBag getImportHighlightsBag(Document doc) {
return bag;
}
+ private static final Object KEY_PRE_TEXT = new Object();
+ static OffsetsBag getPreTextBag(Document doc) {
+ OffsetsBag bag = (OffsetsBag) doc.getProperty(KEY_PRE_TEXT);
+
+ if (bag == null) {
+ doc.putProperty(KEY_PRE_TEXT, bag = new OffsetsBag(doc));
+
+ Object stream = doc.getProperty(Document.StreamDescriptionProperty);
+
+ if (stream instanceof DataObject) {
+// TimesCollector.getDefault().reportReference(((DataObject) stream).getPrimaryFile(), "ImportsHighlightsBag", "[M] Imports Highlights Bag", bag);
+ }
+ }
+
+ return bag;
+ }
+
}
From ef3564acb7880a7496c8972de87cebc6bb32ad0a Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Wed, 10 Apr 2019 21:26:26 +0200
Subject: [PATCH 02/11] Improving appearance of the inline hints.
---
.../modules/editor/lib2/view/DocumentViewOp.java | 6 ++++++
.../lib2/view/PrependedTextHighlightsView.java | 15 +++++----------
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java
index a226a303e8eb..eba7f837ca41 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java
@@ -291,6 +291,7 @@ public final class DocumentViewOp
private Map fontInfos = new HashMap(4);
private Font defaultFont;
+ private Font defaultHintFont;
private boolean fontRenderContextFromPaint;
@@ -1060,6 +1061,7 @@ private void updateCharMetrics() { // Update default row height and other params
fontInfos.put(null, defaultFontInfo); // Alternative way to find default font info
updateRowHeight(defaultFontInfo, true);
defaultFont = font;
+ defaultHintFont = font.deriveFont((float) (font.getSize2D() * 0.75));
defaultCharWidth = defaultFontInfo.charWidth;
tabTextLayout = null;
@@ -1259,6 +1261,10 @@ public Font getDefaultFont() {
return defaultFont;
}
+ public Font getDefaultHintFont() {
+ return defaultHintFont;
+ }
+
public float getDefaultRowHeight() {
checkSettingsInfo();
return defaultRowHeightInt;
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
index d156c3eed14b..06b94484debb 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
@@ -39,7 +39,7 @@ public class PrependedTextHighlightsView extends HighlightsView {
private TextLayout prependedTextLayout;
private double leftShift;
private double prependedTextWidth;
- private double moveup;
+ private double heighCorrection;
public PrependedTextHighlightsView(int length, AttributeSet attributes) {
super(length, attributes);
@@ -47,17 +47,13 @@ public PrependedTextHighlightsView(int length, AttributeSet attributes) {
@Override
void setTextLayout(TextLayout textLayout, float width) {
- Font font = ViewUtils.getFont(getAttributes(), getDocumentView().op.getDefaultFont());
- font = font.deriveFont((float) (font.getSize2D() * 0.75));
+ DocumentViewOp op = getDocumentView().op;
+ Font font = ViewUtils.getFont(getAttributes(), op.getDefaultHintFont());
prependedTextLayout = getDocumentView().op.createTextLayout((String) getAttributes().getAttribute("virtual-text-prepend"), font);
Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
- double em = getDocumentView().op.createTextLayout("m", font).getBounds().getWidth();
+ double em = op.getDefaultCharWidth();
leftShift = em / 2;
prependedTextWidth = textBounds.getWidth() + em;
- double actualTextHeight = textLayout.getBounds().getHeight();
- moveup = (actualTextHeight - textBounds.getHeight()) / 2;
-// double actualTextHeight = textLayout.getAscent();
-// moveup = (actualTextHeight - prependedTextLayout.getAscent()) / 2;
super.setTextLayout(textLayout, (float) (width + prependedTextWidth));
}
@@ -90,13 +86,12 @@ public void paint(Graphics2D g, Shape hViewAlloc, Rectangle clipBounds) {
if (highlights.moveNext()) {
AttributeSet attrs = highlights.getAttributes();
- System.err.println("attrs=" + attrs);
HighlightsViewUtils.fillBackground(g, span, attrs, getDocumentView().getTextComponent());
HighlightsViewUtils.paintBackgroundHighlights(g, span, attrs, getDocumentView()); //TODO: clear some attributes (like boxes)???
}
g.setColor(Color.gray);
- span.setRect(span.getX() + leftShift, span.getY() - moveup, prependedTextWidth - 2 * leftShift, span.getHeight());
+ span.setRect(span.getX() + leftShift, span.getY(), prependedTextWidth - 2 * leftShift, span.getHeight());
// g.drawRoundRect((int) span.getX(), (int) span.getY(), (int) span.getWidth(), (int) span.getHeight(), 2, 2);
HighlightsViewUtils.paintTextLayout(g, span, prependedTextLayout, getDocumentView());
}
From a3df085565a0c4a022b5149bd8597999b046c912 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Wed, 10 Apr 2019 21:28:30 +0200
Subject: [PATCH 03/11] Generalizing highlighting test infrastructure.
---
.../nbproject/project.properties | 2 +-
.../editor/base/semantic/DetectorTest.java | 13 ++
.../java/editor/base/semantic/TestBase.java | 111 ++++++++++++------
3 files changed, 89 insertions(+), 37 deletions(-)
diff --git a/java/java.editor.base/nbproject/project.properties b/java/java.editor.base/nbproject/project.properties
index eb59ba01f553..8d8f77e133ab 100644
--- a/java/java.editor.base/nbproject/project.properties
+++ b/java/java.editor.base/nbproject/project.properties
@@ -16,7 +16,7 @@
# under the License.
spec.version.base=2.70.0
is.autoload=true
-javac.source=1.7
+javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
test.config.semantic.includes=\
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 522350944716..c3e754700dcf 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
@@ -411,6 +411,19 @@ protected boolean process(CompilationInfo info, Document doc) {
});
}
+ private void performTest(String fileName, String content, String expected) throws Exception {
+ performTest(fileName, content, new Performer() {
+ public void compute(CompilationController parameter, Document doc, final ErrorDescriptionSetter setter) {
+ new SemanticHighlighterBase() {
+ @Override
+ protected boolean process(CompilationInfo info, Document doc) {
+ return process(info, doc, setter);
+ }
+ }.process(parameter, doc);
+ }
+ }, false, expected);
+ }
+
private FileObject testSourceFO;
static {
diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
index a095df04e724..6719ce7e10f6 100644
--- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
@@ -26,6 +26,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
@@ -95,23 +96,76 @@ protected void performTest(String fileName, final Performer performer) throws Ex
}
protected void performTest(String fileName, final Performer performer, boolean doCompileRecursively) throws Exception {
+ performTest(() -> {
+ File wd = getWorkDir();
+ File testSource = new File(wd, "test/" + fileName + ".java");
+
+ testSource.getParentFile().mkdirs();
+
+ File dataFolder = new File(getDataDir(), "org/netbeans/modules/java/editor/base/semantic/data/");
+
+ for (File f : dataFolder.listFiles()) {
+ copyToWorkDir(f, new File(wd, "test/" + f.getName()));
+ }
+
+ return FileUtil.toFileObject(testSource);
+ }, performer, doCompileRecursively,
+ actual -> {
+ File output = new File(getWorkDir(), getName() + ".out");
+ try (Writer out2File = new FileWriter(output)) {
+ out2File.append(actual);
+ }
+
+ boolean wasException = true;
+
+ try {
+ File goldenFile = getGoldenFile();
+ File diffFile = new File(getWorkDir(), getName() + ".diff");
+
+ assertFile(output, goldenFile, diffFile);
+ wasException = false;
+ } finally {
+ if (wasException && SHOW_GUI_DIFF) {
+ try {
+ String name = getClass().getName();
+
+ name = name.substring(name.lastIndexOf('.') + 1);
+
+ ShowGoldenFiles.run(name, getName(), fileName);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ }
+
+ protected void performTest(String filename, String content, final Performer performer, boolean doCompileRecursively, String expected) throws Exception {
+ performTest(() -> {
+ FileObject wd = FileUtil.toFileObject(getWorkDir());
+ FileObject result = FileUtil.createData(wd, filename);
+
+ try (Writer out = new OuputStreamWriter(result.getOutputStream())) {
+ out.write(content);
+ }
+
+ return result;
+ }, performer, doCompileRecursively,
+ actual -> {
+ assertEquals(expected, actual);
+ });
+ }
+
+ protected void performTest(Input input, final Performer performer, boolean doCompileRecursively, Validator validator) throws Exception {
SourceUtilsTestUtil.prepareTest(new String[] {"org/netbeans/modules/java/editor/resources/layer.xml"}, new Object[] {new MIMEResolverImpl()});
FileObject scratch = SourceUtilsTestUtil.makeScratchDir(this);
FileObject cache = scratch.createFolder("cache");
File wd = getWorkDir();
- File testSource = new File(wd, "test/" + fileName + ".java");
-
- testSource.getParentFile().mkdirs();
-
- File dataFolder = new File(getDataDir(), "org/netbeans/modules/java/editor/base/semantic/data/");
-
- for (File f : dataFolder.listFiles()) {
- copyToWorkDir(f, new File(wd, "test/" + f.getName()));
- }
-
- testSourceFO = FileUtil.toFileObject(testSource);
+
+ testSourceFO = input.prepare();
assertNotNull(testSourceFO);
@@ -123,7 +177,7 @@ protected void performTest(String fileName, final Performer performer, boolean d
testBuildTo.mkdirs();
- FileObject srcRoot = FileUtil.toFileObject(testSource.getParentFile());
+ FileObject srcRoot = testSourceFO.getParent();
SourceUtilsTestUtil.prepareTest(srcRoot,FileUtil.toFileObject(testBuildTo), cache);
if (doCompileRecursively) {
@@ -162,8 +216,7 @@ public void run(CompilationController parameter) {
l.await();
- File output = new File(getWorkDir(), getName() + ".out");
- Writer out = new FileWriter(output);
+ StringWriter out = new StringWriter();
for (HighlightImpl h : highlights) {
out.write(h.getHighlightTestData());
@@ -172,29 +225,8 @@ public void run(CompilationController parameter) {
}
out.close();
-
- boolean wasException = true;
- try {
- File goldenFile = getGoldenFile();
- File diffFile = new File(getWorkDir(), getName() + ".diff");
-
- assertFile(output, goldenFile, diffFile);
- wasException = false;
- } finally {
- if (wasException && SHOW_GUI_DIFF) {
- try {
- String name = getClass().getName();
-
- name = name.substring(name.lastIndexOf('.') + 1);
-
- ShowGoldenFiles.run(name, getName(), fileName);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
+ validator.validate(out.toString());
}
protected ColoringAttributes getColoringAttribute() {
@@ -273,4 +305,11 @@ public String findMIMEType(FileObject fo) {
}
}
+ protected interface Input {
+ public FileObject prepare() throws Exception;
+ }
+
+ protected interface Validator {
+ public void validate(String actual) throws Exception;
+ }
}
From a8abb2e56dbd5709b518dcc09949153b68b85f34 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Sat, 13 Apr 2019 22:19:16 +0200
Subject: [PATCH 04/11] Adding option to disable/enable the inline hints.
---
.../modules/editor/actions/Bundle.properties | 1 +
.../editor/actions/ShowInlineHintsAction.java | 37 +++++++++++++++++++
.../lib2/highlighting/HighlightsList.java | 5 ++-
.../editor/lib2/view/DocumentViewOp.java | 10 ++++-
.../lib2/view/HighlightsViewFactory.java | 5 ++-
.../lib2/highlighting/HighlightsListTest.java | 22 +++++------
6 files changed, 64 insertions(+), 16 deletions(-)
create mode 100644 ide/editor.actions/src/org/netbeans/modules/editor/actions/ShowInlineHintsAction.java
diff --git a/ide/editor.actions/src/org/netbeans/modules/editor/actions/Bundle.properties b/ide/editor.actions/src/org/netbeans/modules/editor/actions/Bundle.properties
index 857bfa7dbf29..17b02bc04830 100644
--- a/ide/editor.actions/src/org/netbeans/modules/editor/actions/Bundle.properties
+++ b/ide/editor.actions/src/org/netbeans/modules/editor/actions/Bundle.properties
@@ -44,6 +44,7 @@ caret-next-word=Insertion Point to Next Word
caret-previous-word=Insertion Point to Previous Word
selection-next-word=Extend Selection to Next Word
selection-previous-word=Extend Selection to Previous Word
+toggle-inline-hints=Show Inline &Hints
toggle-lines-view=Show &Indent Guide Lines
clipboard-lines=Paste as Lines
remove-last-caret=Remove Last Caret
diff --git a/ide/editor.actions/src/org/netbeans/modules/editor/actions/ShowInlineHintsAction.java b/ide/editor.actions/src/org/netbeans/modules/editor/actions/ShowInlineHintsAction.java
new file mode 100644
index 000000000000..a97a8efeaa1b
--- /dev/null
+++ b/ide/editor.actions/src/org/netbeans/modules/editor/actions/ShowInlineHintsAction.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.editor.actions;
+
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import org.netbeans.api.editor.EditorActionRegistration;
+
+@EditorActionRegistration(name="toggle-inline-hints",
+ menuPath="View",
+ menuPosition=899,
+ preferencesKey=ShowInlineHintsAction.KEY_LINES,
+ preferencesDefault=ShowInlineHintsAction.DEF_LINES)
+public class ShowInlineHintsAction extends AbstractAction {
+ public static final String KEY_LINES = "enable.inline.hints";
+ public static final boolean DEF_LINES = false;
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ }
+
+}
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
index 335e13d9ae80..5152d0c4cd2a 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
@@ -118,9 +118,10 @@ public void add(HighlightItem item) {
* @param wsEndOffset whitespace end offset must be lower than or equal to maxEndOffset
* and when exceeded a first whitespace char in docText means that the cutting will end there.
* @param docText document text in order properly handle wsEndOffset parameter.
+ * @param usePrependText reflect the prepended text setting.
* @return either simple or compound attribute set.
*/
- public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOffset, CharSequence docText) {
+ public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOffset, CharSequence docText, boolean usePrependText) {
assert (maxEndOffset <= endOffset()) :
"maxEndOffset=" + maxEndOffset + " > endOffset()=" + endOffset() + ", " + this; // NOI18N
HighlightItem item = get(0);
@@ -158,7 +159,7 @@ public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOff
// Extends beyond first highlight
Font firstFont = ViewUtils.getFont(firstAttrs, defaultFont);
- Object firstPrependText = firstAttrs.getAttribute("virtual-text-prepend");
+ Object firstPrependText = usePrependText ? firstAttrs.getAttribute("virtual-text-prepend") : null;
int index = 1;
while (true) {
item = get(index);
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java
index eba7f837ca41..80f1b9ac14d1 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/DocumentViewOp.java
@@ -315,6 +315,7 @@ public final class DocumentViewOp
boolean asTextField;
private boolean guideLinesEnable;
+ private boolean inlineHintsEnable;
private int indentLevelSize;
@@ -922,10 +923,13 @@ public void run() {
// Line height correction
float lineHeightCorrectionOrig = rowHeightCorrection;
rowHeightCorrection = prefs.getFloat(SimpleValueNames.LINE_HEIGHT_CORRECTION, 1.0f);
+ boolean inlineHintsEnableOrig = inlineHintsEnable;
+ inlineHintsEnable = Boolean.TRUE.equals(prefs.getBoolean("enable.inline.hints", false)); // NOI18N
boolean updateMetrics = (rowHeightCorrection != lineHeightCorrectionOrig);
boolean releaseChildren = nonInitialUpdate &&
((nonPrintableCharactersVisible != nonPrintableCharactersVisibleOrig) ||
- (rowHeightCorrection != lineHeightCorrectionOrig));
+ (rowHeightCorrection != lineHeightCorrectionOrig) ||
+ (inlineHintsEnable != inlineHintsEnableOrig));
indentLevelSize = getIndentSize();
tabSize = prefs.getInt(SimpleValueNames.TAB_SIZE, EditorPreferencesDefaults.defaultTabSize);
if (updateMetrics) {
@@ -1167,6 +1171,10 @@ public boolean isGuideLinesEnable() {
return guideLinesEnable && !asTextField;
}
+ public boolean isInlineHintsEnable() {
+ return inlineHintsEnable;
+ }
+
public int getIndentLevelSize() {
return indentLevelSize;
}
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
index 3574df72d454..9ac388fb609a 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
@@ -216,9 +216,10 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
}
}
- AttributeSet attrs = hList.cutSameFont(defaultFont, limitOffset, wsEndOffset, docText);
+ boolean inlineHints = documentView().op.isInlineHintsEnable();
+ AttributeSet attrs = hList.cutSameFont(defaultFont, limitOffset, wsEndOffset, docText, inlineHints);
int length = hList.startOffset() - startOffset;
- HighlightsView view = attrs != null && attrs.getAttribute("virtual-text-prepend") != null ? new PrependedTextHighlightsView(length, attrs) : new HighlightsView(length, attrs);
+ HighlightsView view = attrs != null && inlineHints && attrs.getAttribute("virtual-text-prepend") != null ? new PrependedTextHighlightsView(length, attrs) : new HighlightsView(length, attrs);
if (origView != null && origView.getClass() == HighlightsView.class && origView.getLength() == length) { // Reuse XXX: reuse disabled for PrependedTextHighlightsView!
HighlightsView origHView = (HighlightsView) origView;
TextLayout origTextLayout = origHView.getTextLayout();
diff --git a/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java b/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
index f73e857de0e8..6e9082171f79 100644
--- a/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
+++ b/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
@@ -67,7 +67,7 @@ public void testSimple() throws Exception {
HighlightsList hList = highlightsListSimple(doc);
// Fetch first
- AttributeSet attrs = hList.cutSameFont(defaultFont, 10, 10, null);
+ AttributeSet attrs = hList.cutSameFont(defaultFont, 10, 10, null, false);
assert (attrs instanceof CompoundAttributes) : "Non-CompoundAttributes attrs=" + attrs;
CompoundAttributes cAttrs = (CompoundAttributes) attrs;
assert (cAttrs.startOffset() == 0) : "startOffset=" + cAttrs.startOffset();
@@ -78,21 +78,21 @@ public void testSimple() throws Exception {
assertItem(items[2], 6, null);
// Fetch next
assert (hList.startOffset() == 6);
- attrs = hList.cutSameFont(defaultFont, 10, 10, null);
+ attrs = hList.cutSameFont(defaultFont, 10, 10, null, false);
assert !(attrs instanceof CompoundAttributes);
assert attrs == attrSets[1];
assert (hList.startOffset() == 8);
- attrs = hList.cutSameFont(defaultFont, 10, 10, null);
+ attrs = hList.cutSameFont(defaultFont, 10, 10, null, false);
assert !(attrs instanceof CompoundAttributes);
assert (attrs == null);
assert (hList.startOffset() == 10);
hList = highlightsListSimple(doc);
- attrs = hList.cutSameFont(defaultFont, 2, 2, null);
+ attrs = hList.cutSameFont(defaultFont, 2, 2, null, false);
assert !(attrs instanceof CompoundAttributes);
assert (attrs == null);
- attrs = hList.cutSameFont(defaultFont, 10, 10, null);
+ attrs = hList.cutSameFont(defaultFont, 10, 10, null, false);
assert (hList.startOffset() == 6);
assert (attrs instanceof CompoundAttributes) : "Non-CompoundAttributes attrs=" + attrs;
cAttrs = (CompoundAttributes) attrs;
@@ -103,7 +103,7 @@ public void testSimple() throws Exception {
assertItem(items[1], 6, null);
hList = highlightsListSimple(doc);
- attrs = hList.cutSameFont(defaultFont, 3, 3, null);
+ attrs = hList.cutSameFont(defaultFont, 3, 3, null, false);
cAttrs = (CompoundAttributes) attrs;
assert (cAttrs.startOffset() == 0) : "startOffset=" + cAttrs.startOffset();
items = cAttrs.highlightItems();
@@ -111,7 +111,7 @@ public void testSimple() throws Exception {
assertItem(items[0], 2, null);
assertItem(items[1], 3, attrSets[0]);
// Next
- attrs = hList.cutSameFont(defaultFont, 5, 5, null);
+ attrs = hList.cutSameFont(defaultFont, 5, 5, null, false);
cAttrs = (CompoundAttributes) attrs;
assert (cAttrs.startOffset() == 3) : "startOffset=" + cAttrs.startOffset();
items = cAttrs.highlightItems();
@@ -119,22 +119,22 @@ public void testSimple() throws Exception {
assertItem(items[0], 4, attrSets[0]);
assertItem(items[1], 5, null);
// Next
- attrs = hList.cutSameFont(defaultFont, 7, 7, null);
+ attrs = hList.cutSameFont(defaultFont, 7, 7, null, false);
assert !(attrs instanceof CompoundAttributes);
assert (attrs == null);
assert (hList.startOffset() == 6);
// Next
- attrs = hList.cutSameFont(defaultFont, 7, 7, null);
+ attrs = hList.cutSameFont(defaultFont, 7, 7, null, false);
assert !(attrs instanceof CompoundAttributes);
assert (attrs == attrSets[1]);
assert (hList.startOffset() == 7);
// Next
- attrs = hList.cutSameFont(defaultFont, 10, 10, null);
+ attrs = hList.cutSameFont(defaultFont, 10, 10, null, false);
assert !(attrs instanceof CompoundAttributes);
assert (attrs == attrSets[1]);
assert (hList.startOffset() == 8);
// Next
- attrs = hList.cutSameFont(defaultFont, 10, 10, null);
+ attrs = hList.cutSameFont(defaultFont, 10, 10, null, false);
assert !(attrs instanceof CompoundAttributes);
assert (attrs == null);
assert (hList.startOffset() == 10);
From d8336724e233841e531d023aafe153cc3efae9c8 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Sun, 14 Apr 2019 07:37:33 +0200
Subject: [PATCH 05/11] Preventing NPE while preparing compound highlights,
adding simple tests.
---
.../lib2/highlighting/HighlightsList.java | 4 +-
.../lib2/highlighting/HighlightsListTest.java | 87 +++++++++++++++++++
2 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
index 5152d0c4cd2a..1e925fa5811b 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
@@ -159,13 +159,13 @@ public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOff
// Extends beyond first highlight
Font firstFont = ViewUtils.getFont(firstAttrs, defaultFont);
- Object firstPrependText = usePrependText ? firstAttrs.getAttribute("virtual-text-prepend") : null;
+ Object firstPrependText = usePrependText && firstAttrs != null ? firstAttrs.getAttribute("virtual-text-prepend") : null;
int index = 1;
while (true) {
item = get(index);
AttributeSet attrs = item.getAttributes();
Font font = ViewUtils.getFont(attrs, defaultFont);
- Object prependText = attrs != null ? attrs.getAttribute("virtual-text-prepend") : null;
+ Object prependText = usePrependText && attrs != null ? attrs.getAttribute("virtual-text-prepend") : null;
if (!font.equals(firstFont) || !Objects.equals(firstPrependText, prependText)) { // Stop at itemEndOffset
if (index == 1) { // Just single attribute set
cutStartItems(1);
diff --git a/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java b/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
index 6e9082171f79..717dfb1ac51b 100644
--- a/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
+++ b/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
@@ -151,6 +151,93 @@ private HighlightsList highlightsListSimple(Document doc) {
return reader.highlightsList();
}
+ @Test
+ public void testSplitPrependText() throws Exception {
+ Document doc = document();
+
+ OffsetsBag bag = new OffsetsBag(doc);
+ AttributeSet attrs1 = AttributesUtilities.createImmutable(
+ StyleConstants.Foreground, Color.RED,
+ StyleConstants.FontFamily, fontNames[0]);
+ AttributeSet attrs2 = AttributesUtilities.createImmutable(
+ StyleConstants.Foreground, Color.RED,
+ StyleConstants.FontFamily, fontNames[0],
+ "virtual-text-prepend", "test");
+ AttributeSet attrs3 = AttributesUtilities.createImmutable(
+ StyleConstants.Foreground, Color.RED,
+ StyleConstants.FontFamily, fontNames[1]);
+
+ bag.addHighlight(0, 2, attrs1);
+ bag.addHighlight(2, 4, attrs2);
+ bag.addHighlight(4, 6, attrs1);
+ bag.addHighlight(8, 10, attrs3);
+
+ int end = 14;
+ DirectMergeContainer dmc = new DirectMergeContainer(new HighlightsContainer[]{ bag }, true);
+
+ {
+ HighlightsReader reader = new HighlightsReader(dmc, 0, end);
+ reader.readUntil(end);
+ HighlightsList hList = reader.highlightsList();
+
+ // Fetch first
+ AttributeSet attrs = hList.cutSameFont(defaultFont, end, end, null, false);
+ assert (attrs instanceof CompoundAttributes) : "Non-CompoundAttributes attrs=" + attrs;
+ CompoundAttributes cAttrs = (CompoundAttributes) attrs;
+ assert (cAttrs.startOffset() == 0) : "startOffset=" + cAttrs.startOffset();
+ HighlightItem[] items = cAttrs.highlightItems();
+ assert (items.length == 4);
+ assertItem(items[0], 2, attrs1);
+ assertItem(items[1], 4, attrs2);
+ assertItem(items[2], 6, attrs1);
+ assertItem(items[3], 8, null);
+ // Fetch next
+ assert (hList.startOffset() == 8);
+ attrs = hList.cutSameFont(defaultFont, end, end, null, false);
+ assert !(attrs instanceof CompoundAttributes);
+ assert attrs == attrs3;
+ assert (hList.startOffset() == 10);
+ attrs = hList.cutSameFont(defaultFont, end, end, null, false);
+ assert !(attrs instanceof CompoundAttributes);
+ assert (attrs == null);
+ assert (hList.startOffset() == 14);
+ }
+
+ {
+ HighlightsReader reader = new HighlightsReader(dmc, 0, end);
+ reader.readUntil(end);
+ HighlightsList hList = reader.highlightsList();
+
+ // Fetch first
+ AttributeSet attrs = hList.cutSameFont(defaultFont, end, end, null, true);
+ assert !(attrs instanceof CompoundAttributes) : "CompoundAttributes attrs=" + attrs;
+ assert attrs == attrs1;
+ assert (hList.startOffset() == 2);
+ attrs = hList.cutSameFont(defaultFont, end, end, null, true);
+ assert !(attrs instanceof CompoundAttributes);
+ assert (attrs == attrs2);
+ assert (hList.startOffset() == 4);
+ attrs = hList.cutSameFont(defaultFont, end, end, null, true);
+ assert (attrs instanceof CompoundAttributes) : "Non-CompoundAttributes attrs=" + attrs;
+ CompoundAttributes cAttrs = (CompoundAttributes) attrs;
+ assert (cAttrs.startOffset() == 4) : "startOffset=" + cAttrs.startOffset();
+ HighlightItem[] items = cAttrs.highlightItems();
+ assert (items.length == 2);
+ assertItem(items[0], 6, attrs1);
+ assertItem(items[1], 8, null);
+ // Fetch next
+ assert (hList.startOffset() == 8);
+ attrs = hList.cutSameFont(defaultFont, end, end, null, true);
+ assert !(attrs instanceof CompoundAttributes);
+ assert attrs == attrs3;
+ assert (hList.startOffset() == 10);
+ attrs = hList.cutSameFont(defaultFont, end, end, null, true);
+ assert !(attrs instanceof CompoundAttributes);
+ assert (attrs == null);
+ assert (hList.startOffset() == 14);
+ }
+ }
+
private static void assertItem(HighlightItem item, int endOffset, AttributeSet attrs) {
assert (item.getEndOffset() == endOffset) : "itemEndOffset=" + item.getEndOffset() + " != endOffset=" + endOffset; // NOI18N
assert (item.getAttributes() == attrs) : "itemAttrs=" + item.getAttributes() + " != attrs=" + attrs; // NOI18N
From b372428624f4e0a77c222e8b272e7fa276ce09ff Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Sun, 14 Apr 2019 08:02:32 +0200
Subject: [PATCH 06/11] Adding simple tests for the parameter name hints.
---
.../editor/base/semantic/DetectorTest.java | 33 +++++++++++++++++++
.../editor/base/semantic/HighlightImpl.java | 19 ++++++++++-
.../java/editor/base/semantic/TestBase.java | 14 +++++++-
3 files changed, 64 insertions(+), 2 deletions(-)
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 c3e754700dcf..b4bdcf0b8a3e 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
@@ -252,6 +252,39 @@ public void testGenericBoundIsClassUse() throws Exception {
performTest("GenericBoundIsClassUse");
}
+ public void testParameterNames() throws Exception {
+ setShowPrependedText(true);
+ performTest("Test.java",
+ "package test;" +
+ "public class Test {" +
+ " public void api(String param1, int param2, int param3, float param4, Object param5) {" +
+ " }" +
+ " private int getValue() {" +
+ " return -1;" +
+ " }" +
+ " private void test() {" +
+ " api(\"\", 2, getValue(), 1.0f, null);" +
+ " }" +
+ "}",
+ "[PUBLIC, CLASS, DECLARATION], 0:26-0:30\n" +
+ "[PUBLIC, METHOD, DECLARATION], 0:48-0:51\n" +
+ "[PUBLIC, CLASS], 0:52-0:58\n" +
+ "[PARAMETER, DECLARATION], 0:59-0:65\n" +
+ "[PARAMETER, DECLARATION], 0:71-0:77\n" +
+ "[PARAMETER, DECLARATION], 0:83-0:89\n" +
+ "[PARAMETER, DECLARATION], 0:97-0:103\n" +
+ "[PUBLIC, CLASS], 0:105-0:111\n" +
+ "[PARAMETER, DECLARATION], 0:112-0:118\n" +
+ "[PRIVATE, METHOD, DECLARATION], 0:142-0:150\n" +
+ "[PRIVATE, METHOD, UNUSED, DECLARATION], 0:194-0:198\n" +
+ "[PUBLIC, METHOD], 0:210-0:213\n" +
+ "[param1:], 0:214-0:216\n" +
+ "[param2:], 0:218-0:219\n" +
+ "[PRIVATE, METHOD], 0:221-0:229\n" +
+ "[param4:], 0:233-0:237\n" +
+ "[param5:], 0:239-0:243\n");
+ }
+
@RandomlyFails
public void testBLE91246() throws Exception {
final boolean wasThrown[] = new boolean[1];
diff --git a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
index 98c5a3d6e235..dffd3e5ec01b 100644
--- a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
+++ b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
@@ -40,6 +40,7 @@ public final class HighlightImpl {
private int start;
private int end;
private Collection colorings;
+ private String textPrepend;
public HighlightImpl(Document doc, Token token, Collection colorings) {
this.doc = doc;
@@ -55,6 +56,14 @@ public HighlightImpl(Document doc, int start, int end, Collection highlights = new TreeSet(new Comparator() {
public int compare(HighlightImpl o1, HighlightImpl o2) {
@@ -287,6 +294,11 @@ public void setHighlights(Document doc, Collection highlights, Map e : preText.entrySet()) {
+ this.highlights.add(new HighlightImpl(doc, e.getKey()[0], e.getKey()[1], e.getValue()));
+ }
+ }
}
@Override
From f1a0d4cd8c9a0eb1c09a7bca807e205b1462a4b9 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Fri, 19 Apr 2019 21:35:47 +0200
Subject: [PATCH 07/11] Fixing varargs usage.
---
.../semantic/SemanticHighlighterBase.java | 4 ++-
.../editor/base/semantic/DetectorTest.java | 34 +++++++++++++------
2 files changed, 27 insertions(+), 11 deletions(-)
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 9065d7ba979b..e8edfbb4107f 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
@@ -1075,8 +1075,10 @@ public Void visitLiteral(LiteralTree node, Void p) {
if (invoked != null && (invoked.getKind() == ElementKind.METHOD || invoked.getKind() == ElementKind.CONSTRUCTOR)) {
long start = sourcePositions.getStartPosition(info.getCompilationUnit(), node);
long end = sourcePositions.getEndPosition(info.getCompilationUnit(), node);
+ ExecutableElement invokedMethod = (ExecutableElement) invoked;
+ pos = Math.min(pos, invokedMethod.getParameters().size() - 1);
preText.put(new int[] {(int) start, (int) end},
- ((ExecutableElement) invoked).getParameters().get(pos).getSimpleName() + ":");
+ invokedMethod.getParameters().get(pos).getSimpleName() + ":");
}
}
}
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 b4bdcf0b8a3e..57b6bcb3c728 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
@@ -257,13 +257,15 @@ public void testParameterNames() throws Exception {
performTest("Test.java",
"package test;" +
"public class Test {" +
- " public void api(String param1, int param2, int param3, float param4, Object param5) {" +
+ " public void api(String param1, int param2, int param3, float param4, Object... param5) {" +
" }" +
" private int getValue() {" +
" return -1;" +
" }" +
" private void test() {" +
+ " api(\"\", 2, getValue(), 1.0f);" +
" api(\"\", 2, getValue(), 1.0f, null);" +
+ " api(\"\", 2, getValue(), 1.0f, null, null);" +
" }" +
"}",
"[PUBLIC, CLASS, DECLARATION], 0:26-0:30\n" +
@@ -274,15 +276,27 @@ public void testParameterNames() throws Exception {
"[PARAMETER, DECLARATION], 0:83-0:89\n" +
"[PARAMETER, DECLARATION], 0:97-0:103\n" +
"[PUBLIC, CLASS], 0:105-0:111\n" +
- "[PARAMETER, DECLARATION], 0:112-0:118\n" +
- "[PRIVATE, METHOD, DECLARATION], 0:142-0:150\n" +
- "[PRIVATE, METHOD, UNUSED, DECLARATION], 0:194-0:198\n" +
- "[PUBLIC, METHOD], 0:210-0:213\n" +
- "[param1:], 0:214-0:216\n" +
- "[param2:], 0:218-0:219\n" +
- "[PRIVATE, METHOD], 0:221-0:229\n" +
- "[param4:], 0:233-0:237\n" +
- "[param5:], 0:239-0:243\n");
+ "[PARAMETER, DECLARATION], 0:115-0:121\n" +
+ "[PRIVATE, METHOD, DECLARATION], 0:145-0:153\n" +
+ "[PRIVATE, METHOD, UNUSED, DECLARATION], 0:197-0:201\n" +
+ "[PUBLIC, METHOD], 0:213-0:216\n" +
+ "[param1:], 0:217-0:219\n" +
+ "[param2:], 0:221-0:222\n" +
+ "[PRIVATE, METHOD], 0:224-0:232\n" +
+ "[param4:], 0:236-0:240\n" +
+ "[PUBLIC, METHOD], 0:250-0:253\n" +
+ "[param1:], 0:254-0:256\n" +
+ "[param2:], 0:258-0:259\n" +
+ "[PRIVATE, METHOD], 0:261-0:269\n" +
+ "[param4:], 0:273-0:277\n" +
+ "[param5:], 0:279-0:283\n" +
+ "[PUBLIC, METHOD], 0:293-0:296\n" +
+ "[param1:], 0:297-0:299\n" +
+ "[param2:], 0:301-0:302\n" +
+ "[PRIVATE, METHOD], 0:304-0:312\n" +
+ "[param4:], 0:316-0:320\n" +
+ "[param5:], 0:322-0:326\n" +
+ "[param5:], 0:328-0:332\n");
}
@RandomlyFails
From 124348405550fe793399469bed43450bf48290eb Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Wed, 24 Apr 2019 07:53:31 +0200
Subject: [PATCH 08/11] Improving the view structure by creating a wrapper view
over the existing highlight view.
---
.../lib2/view/HighlightsViewFactory.java | 10 +-
.../lib2/view/ParagraphViewChildren.java | 4 +-
.../view/PrependedTextHighlightsView.java | 99 -----------
.../editor/lib2/view/PrependedTextView.java | 155 ++++++++++++++++++
4 files changed, 164 insertions(+), 104 deletions(-)
delete mode 100644 ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
create mode 100644 ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
index 9ac388fb609a..9815b58072db 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
@@ -219,7 +219,10 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
boolean inlineHints = documentView().op.isInlineHintsEnable();
AttributeSet attrs = hList.cutSameFont(defaultFont, limitOffset, wsEndOffset, docText, inlineHints);
int length = hList.startOffset() - startOffset;
- HighlightsView view = attrs != null && inlineHints && attrs.getAttribute("virtual-text-prepend") != null ? new PrependedTextHighlightsView(length, attrs) : new HighlightsView(length, attrs);
+ EditorView view = new HighlightsView(length, attrs);
+ if (attrs != null && inlineHints && attrs.getAttribute("virtual-text-prepend") != null) {
+ view = new PrependedTextView(documentView().op, attrs, view);
+ }
if (origView != null && origView.getClass() == HighlightsView.class && origView.getLength() == length) { // Reuse XXX: reuse disabled for PrependedTextHighlightsView!
HighlightsView origHView = (HighlightsView) origView;
TextLayout origTextLayout = origHView.getTextLayout();
@@ -239,8 +242,9 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
Font origFont = ViewUtils.getFont(origView.getAttributes(), defaultFont);
if (font != null && font.equals(origFont)) {
float origWidth = origHView.getWidth();
- view.setTextLayout(origTextLayout, origWidth);
- view.setBreakInfo(origHView.getBreakInfo());
+ HighlightsView hv = (HighlightsView) (view instanceof PrependedTextView ? ((PrependedTextView) view).getDelegate() : view);
+ hv.setTextLayout(origTextLayout, origWidth);
+ hv.setBreakInfo(origHView.getBreakInfo());
ViewStats.incrementTextLayoutReused(length);
}
}
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 d67c36a9e07c..38c2787ed78b 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 @@ void replace(ParagraphView pView, int index, int removeCount, View[] addedViews)
view.setRawEndOffset(relEndOffset); // Below offset-gap
view.setParent(pView);
// Possibly assign text layout
- if (view instanceof HighlightsView) {
- HighlightsView hView = (HighlightsView) view;
+ if (view instanceof HighlightsView || (view instanceof PrependedTextView && ((PrependedTextView) view).getDelegate() instanceof HighlightsView)) {
+ HighlightsView hView = (HighlightsView) (view instanceof HighlightsView ? view : ((PrependedTextView) view).getDelegate());
// Fill in text layout if necessary
if (hView.getTextLayout() == null) { // Fill in text layout
if (docText == null) {
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
deleted file mode 100644
index 06b94484debb..000000000000
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextHighlightsView.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.netbeans.modules.editor.lib2.view;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.font.TextLayout;
-import java.awt.geom.Rectangle2D;
-import javax.swing.text.AttributeSet;
-import javax.swing.text.Position.Bias;
-import org.netbeans.spi.editor.highlighting.HighlightsSequence;
-
-/**
- * TODO
- */
-
-public class PrependedTextHighlightsView extends HighlightsView {
-
- private TextLayout prependedTextLayout;
- private double leftShift;
- private double prependedTextWidth;
- private double heighCorrection;
-
- public PrependedTextHighlightsView(int length, AttributeSet attributes) {
- super(length, attributes);
- }
-
- @Override
- void setTextLayout(TextLayout textLayout, float width) {
- DocumentViewOp op = getDocumentView().op;
- Font font = ViewUtils.getFont(getAttributes(), op.getDefaultHintFont());
- prependedTextLayout = getDocumentView().op.createTextLayout((String) getAttributes().getAttribute("virtual-text-prepend"), font);
- Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
- double em = op.getDefaultCharWidth();
- leftShift = em / 2;
- prependedTextWidth = textBounds.getWidth() + em;
- super.setTextLayout(textLayout, (float) (width + prependedTextWidth));
- }
-
- //span
- //view to model???
- //pain
- //break
-
-
- @Override
- public Shape modelToViewChecked(int offset, Shape alloc, Bias bias) {
- Shape res = super.modelToViewChecked(offset, alloc, bias);
- if (bias == Bias.Forward || offset > getStartOffset()) { //TODO: seems not to have any effect?
- Rectangle2D rect = ViewUtils.shapeAsRect(res);
- Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
- rect.setRect(rect.getX() + textBounds.getWidth(), rect.getY(), rect.getWidth(), rect.getHeight());
- return rect;
- }
- return res;
- }
-
- @Override
- public void paint(Graphics2D g, Shape hViewAlloc, Rectangle clipBounds) {
- Rectangle2D span = ViewUtils.shapeAsRect(hViewAlloc);
- span.setRect(span.getX() + prependedTextWidth, span.getY(), span.getWidth() - prependedTextWidth, span.getHeight());
- super.paint(g, span, clipBounds);
- span.setRect(span.getX() - prependedTextWidth, span.getY(), prependedTextWidth, span.getHeight());
-
- HighlightsSequence highlights = getDocumentView().getPaintHighlights(this, 0);
-
- if (highlights.moveNext()) {
- AttributeSet attrs = highlights.getAttributes();
- HighlightsViewUtils.fillBackground(g, span, attrs, getDocumentView().getTextComponent());
- HighlightsViewUtils.paintBackgroundHighlights(g, span, attrs, getDocumentView()); //TODO: clear some attributes (like boxes)???
- }
-
- g.setColor(Color.gray);
- span.setRect(span.getX() + leftShift, span.getY(), prependedTextWidth - 2 * leftShift, span.getHeight());
-// g.drawRoundRect((int) span.getX(), (int) span.getY(), (int) span.getWidth(), (int) span.getHeight(), 2, 2);
- HighlightsViewUtils.paintTextLayout(g, span, prependedTextLayout, getDocumentView());
- }
-
-}
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
new file mode 100644
index 000000000000..a5c2909d6458
--- /dev/null
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.modules.editor.lib2.view;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.font.TextLayout;
+import java.awt.geom.Rectangle2D;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Position;
+import javax.swing.text.Position.Bias;
+import javax.swing.text.View;
+import org.netbeans.spi.editor.highlighting.HighlightsSequence;
+
+/**
+ * TODO
+ */
+public class PrependedTextView extends EditorView {
+
+ private final TextLayout prependedTextLayout;
+ private final double leftShift;
+ private final double prependedTextWidth;
+ private final AttributeSet attributes;
+ private final EditorView delegate;
+
+ public PrependedTextView(DocumentViewOp op, AttributeSet attributes, EditorView delegate) {
+ super(null);
+ Font font = ViewUtils.getFont(getAttributes(), op.getDefaultHintFont());
+ prependedTextLayout = op.createTextLayout((String) attributes.getAttribute("virtual-text-prepend"), font);
+ Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
+ double em = op.getDefaultCharWidth();
+ leftShift = em / 2;
+ prependedTextWidth = Math.ceil(textBounds.getWidth() + em);
+ this.attributes = attributes;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public float getPreferredSpan(int axis) {
+ float superSpan = delegate.getPreferredSpan(axis);
+ if (axis == View.X_AXIS) {
+ superSpan += prependedTextWidth;
+ }
+ return superSpan;
+ }
+
+ @Override
+ public AttributeSet getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public Shape modelToViewChecked(int offset, Shape alloc, Bias bias) {
+ Shape res = delegate.modelToViewChecked(offset, alloc, bias);
+ Rectangle2D rect = ViewUtils.shapeAsRect(res);
+ rect.setRect(rect.getX() + prependedTextWidth, rect.getY(), rect.getWidth(), rect.getHeight());
+ return rect;
+ }
+
+ @Override
+ public void paint(Graphics2D g, Shape hViewAlloc, Rectangle clipBounds) {
+ Rectangle2D span = ViewUtils.shapeAsRect(hViewAlloc);
+ span.setRect(span.getX() + prependedTextWidth, span.getY(), span.getWidth() - prependedTextWidth, span.getHeight());
+ delegate.paint(g, span, clipBounds);
+ span.setRect(span.getX() - prependedTextWidth, span.getY(), prependedTextWidth, span.getHeight());
+
+ HighlightsSequence highlights = getDocumentView().getPaintHighlights(this, 0);
+
+ if (highlights.moveNext()) {
+ AttributeSet attrs = highlights.getAttributes();
+ HighlightsViewUtils.fillBackground(g, span, attrs, getDocumentView().getTextComponent());
+ HighlightsViewUtils.paintBackgroundHighlights(g, span, attrs, getDocumentView()); //TODO: clear some attributes (like boxes)???
+ }
+
+ g.setColor(Color.gray);
+ span.setRect(span.getX() + leftShift, span.getY(), prependedTextWidth - 2 * leftShift, span.getHeight());
+ HighlightsViewUtils.paintTextLayout(g, span, prependedTextLayout, getDocumentView());
+ }
+
+ ParagraphView getParagraphView() {
+ return (ParagraphView) getParent();
+ }
+
+ DocumentView getDocumentView() {
+ ParagraphView paragraphView = getParagraphView();
+ return (paragraphView != null) ? paragraphView.getDocumentView() : null;
+ }
+
+ @Override
+ public int getRawEndOffset() {
+ return delegate.getRawEndOffset();
+ }
+
+ @Override
+ public void setRawEndOffset(int offset) {
+ delegate.setRawEndOffset(offset);
+ }
+
+ @Override
+ public int viewToModelChecked(double x, double y, Shape alloc, Position.Bias[] biasReturn) {
+ Rectangle2D bounds = ViewUtils.shapeAsRect(alloc);
+ bounds.setRect(bounds.getX() + prependedTextWidth, bounds.getY(),
+ bounds.getWidth() - prependedTextWidth, bounds.getHeight());
+ if (x <= bounds.getX()) {
+ return getStartOffset();
+ }
+ return delegate.viewToModelChecked(x, y, bounds, biasReturn);
+ }
+
+ @Override
+ public int getLength() {
+ return delegate.getLength();
+ }
+
+ @Override
+ public int getStartOffset() {
+ return delegate.getStartOffset();
+ }
+
+ @Override
+ public int getEndOffset() {
+ return delegate.getEndOffset();
+ }
+
+ @Override
+ public void setParent(View parent) {
+ super.setParent(parent);
+ delegate.setParent(parent);
+ }
+
+ EditorView getDelegate() {
+ return delegate;
+ }
+
+}
From 6c9556c862fdf4216364d756fa5e739915431a72 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Tue, 7 May 2019 07:09:42 +0200
Subject: [PATCH 09/11] Cleaning the views implementation.
---
ide/editor.lib2/apichanges.xml | 13 +++++++++
ide/editor.lib2/nbproject/project.properties | 2 +-
.../lib2/view/HighlightsViewFactory.java | 28 +++++++++++++------
.../editor/lib2/view/PrependedTextView.java | 12 ++++----
4 files changed, 39 insertions(+), 16 deletions(-)
diff --git a/ide/editor.lib2/apichanges.xml b/ide/editor.lib2/apichanges.xml
index 6ce4e6ad4aea..a8a1c734347d 100644
--- a/ide/editor.lib2/apichanges.xml
+++ b/ide/editor.lib2/apichanges.xml
@@ -83,6 +83,19 @@ is the proper place.
+
+ Prepended text for highlights
+
+
+
+
+
+ If AttributeSet returned from HighlightsSequence contains key "virtual-text-prepend"
+ with a value of type String, the UI may optionally render the value as a
+ virtual text before the text of the highlight.
+
+
+
Added category to EditorActionRegistration
diff --git a/ide/editor.lib2/nbproject/project.properties b/ide/editor.lib2/nbproject/project.properties
index 31147b960d4c..f3f622d22629 100644
--- a/ide/editor.lib2/nbproject/project.properties
+++ b/ide/editor.lib2/nbproject/project.properties
@@ -18,7 +18,7 @@
is.autoload=true
javac.source=1.7
javac.compilerargs=-Xlint:unchecked
-spec.version.base=2.23.0
+spec.version.base=2.24.0
javadoc.arch=${basedir}/arch.xml
javadoc.apichanges=${basedir}/apichanges.xml
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
index 9815b58072db..c53a959359fe 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
@@ -28,6 +28,8 @@
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.View;
+import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.lib.editor.util.CharSequenceUtilities;
import org.netbeans.lib.editor.util.swing.DocumentUtilities;
import org.netbeans.modules.editor.lib2.highlighting.DirectMergeContainer;
@@ -188,7 +190,7 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
}
if (startOffset == lineEndOffset - 1) {
AttributeSet attrs = hList.cutSingleChar();
- return new NewlineView(attrs);
+ return wrapWithPrependedText(new NewlineView(attrs), attrs);
} else { // Regular view with possible highlight(s) or tab view
updateTabsAndHighlightsAndRTL(startOffset);
if (charType == TAB_CHAR_TYPE) {
@@ -198,7 +200,7 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
limitOffset = tabsEndOffset;
}
attrs = hList.cut(limitOffset);
- return new TabView(limitOffset - startOffset, attrs);
+ return wrapWithPrependedText(new TabView(limitOffset - startOffset, attrs), attrs);
} else { // Create regular view with either LTR or RTL text
limitOffset = Math.min(limitOffset, nextTabOrRTLOffset); // nextTabOrRTLOffset < lineEndOffset
@@ -219,12 +221,10 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
boolean inlineHints = documentView().op.isInlineHintsEnable();
AttributeSet attrs = hList.cutSameFont(defaultFont, limitOffset, wsEndOffset, docText, inlineHints);
int length = hList.startOffset() - startOffset;
- EditorView view = new HighlightsView(length, attrs);
- if (attrs != null && inlineHints && attrs.getAttribute("virtual-text-prepend") != null) {
- view = new PrependedTextView(documentView().op, attrs, view);
- }
- if (origView != null && origView.getClass() == HighlightsView.class && origView.getLength() == length) { // Reuse XXX: reuse disabled for PrependedTextHighlightsView!
- HighlightsView origHView = (HighlightsView) origView;
+ EditorView view = wrapWithPrependedText(new HighlightsView(length, attrs), attrs);
+ EditorView origViewUnwrapped = origView instanceof PrependedTextView ? ((PrependedTextView) origView).getDelegate() : origView;
+ if (origViewUnwrapped != null && origViewUnwrapped.getClass() == HighlightsView.class && origViewUnwrapped.getLength() == length) {
+ HighlightsView origHView = (HighlightsView) origViewUnwrapped;
TextLayout origTextLayout = origHView.getTextLayout();
if (origTextLayout != null) {
if (ViewHierarchyImpl.CHECK_LOG.isLoggable(Level.FINE)) {
@@ -239,7 +239,7 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
}
}
Font font = ViewUtils.getFont(attrs, defaultFont);
- Font origFont = ViewUtils.getFont(origView.getAttributes(), defaultFont);
+ Font origFont = ViewUtils.getFont(origViewUnwrapped.getAttributes(), defaultFont);
if (font != null && font.equals(origFont)) {
float origWidth = origHView.getWidth();
HighlightsView hv = (HighlightsView) (view instanceof PrependedTextView ? ((PrependedTextView) view).getDelegate() : view);
@@ -254,6 +254,16 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
}
}
+ private @NonNull EditorView wrapWithPrependedText(@NonNull EditorView origView, @NullAllowed AttributeSet attrs) {
+ boolean inlineHints = documentView().op.isInlineHintsEnable();
+
+ if (attrs != null && inlineHints && attrs.getAttribute("virtual-text-prepend") instanceof String) {
+ return new PrependedTextView(documentView().op, attrs, origView);
+ }
+
+ return origView;
+ }
+
private void updateTabsAndHighlightsAndRTL(int offset) {
if (offset >= nextTabOrRTLOffset) { // Update nextTabOrRTLOffset
// Determine situation right at offset
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
index a5c2909d6458..bb5e604dbcd7 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
@@ -35,24 +35,24 @@
/**
* TODO
*/
-public class PrependedTextView extends EditorView {
+public final class PrependedTextView extends EditorView {
+ private final AttributeSet attributes;
+ private final EditorView delegate;
private final TextLayout prependedTextLayout;
private final double leftShift;
private final double prependedTextWidth;
- private final AttributeSet attributes;
- private final EditorView delegate;
public PrependedTextView(DocumentViewOp op, AttributeSet attributes, EditorView delegate) {
super(null);
- Font font = ViewUtils.getFont(getAttributes(), op.getDefaultHintFont());
+ this.attributes = attributes;
+ this.delegate = delegate;
+ Font font = ViewUtils.getFont(attributes, op.getDefaultHintFont());
prependedTextLayout = op.createTextLayout((String) attributes.getAttribute("virtual-text-prepend"), font);
Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
double em = op.getDefaultCharWidth();
leftShift = em / 2;
prependedTextWidth = Math.ceil(textBounds.getWidth() + em);
- this.attributes = attributes;
- this.delegate = delegate;
}
@Override
From 591e75bf3aac92e268270f9a4c117617d6eb0d18 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Sun, 12 May 2019 06:47:06 +0200
Subject: [PATCH 10/11] Fix behavior of String literals which contain embedded
escape sequences.
---
ide/editor.lib2/apichanges.xml | 4 +++-
.../base/semantic/SemanticHighlighterBase.java | 2 +-
.../editor/base/semantic/DetectorTest.java | 18 +++++++++---------
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/ide/editor.lib2/apichanges.xml b/ide/editor.lib2/apichanges.xml
index a8a1c734347d..9d12ad2c15b5 100644
--- a/ide/editor.lib2/apichanges.xml
+++ b/ide/editor.lib2/apichanges.xml
@@ -92,7 +92,9 @@ is the proper place.
If AttributeSet returned from HighlightsSequence contains key "virtual-text-prepend"
with a value of type String, the UI may optionally render the value as a
- virtual text before the text of the highlight.
+ virtual text before the text of the highlight. It is recommended to make the
+ span of length 1, to avoid problems when the AttributeSet with "virtual-test-prepend"
+ is merged with other AttributeSets, which could lead to duplication.
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 e8edfbb4107f..58c7a053ed7f 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
@@ -1074,7 +1074,7 @@ public Void visitLiteral(LiteralTree node, Void p) {
Element invoked = info.getTrees().getElement(pp);
if (invoked != null && (invoked.getKind() == ElementKind.METHOD || invoked.getKind() == ElementKind.CONSTRUCTOR)) {
long start = sourcePositions.getStartPosition(info.getCompilationUnit(), node);
- long end = sourcePositions.getEndPosition(info.getCompilationUnit(), node);
+ long end = start + 1;
ExecutableElement invokedMethod = (ExecutableElement) invoked;
pos = Math.min(pos, invokedMethod.getParameters().size() - 1);
preText.put(new int[] {(int) start, (int) end},
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 57b6bcb3c728..1f25ff4d3cbd 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
@@ -280,23 +280,23 @@ public void testParameterNames() throws Exception {
"[PRIVATE, METHOD, DECLARATION], 0:145-0:153\n" +
"[PRIVATE, METHOD, UNUSED, DECLARATION], 0:197-0:201\n" +
"[PUBLIC, METHOD], 0:213-0:216\n" +
- "[param1:], 0:217-0:219\n" +
+ "[param1:], 0:217-0:218\n" +
"[param2:], 0:221-0:222\n" +
"[PRIVATE, METHOD], 0:224-0:232\n" +
- "[param4:], 0:236-0:240\n" +
+ "[param4:], 0:236-0:237\n" +
"[PUBLIC, METHOD], 0:250-0:253\n" +
- "[param1:], 0:254-0:256\n" +
+ "[param1:], 0:254-0:255\n" +
"[param2:], 0:258-0:259\n" +
"[PRIVATE, METHOD], 0:261-0:269\n" +
- "[param4:], 0:273-0:277\n" +
- "[param5:], 0:279-0:283\n" +
+ "[param4:], 0:273-0:274\n" +
+ "[param5:], 0:279-0:280\n" +
"[PUBLIC, METHOD], 0:293-0:296\n" +
- "[param1:], 0:297-0:299\n" +
+ "[param1:], 0:297-0:298\n" +
"[param2:], 0:301-0:302\n" +
"[PRIVATE, METHOD], 0:304-0:312\n" +
- "[param4:], 0:316-0:320\n" +
- "[param5:], 0:322-0:326\n" +
- "[param5:], 0:328-0:332\n");
+ "[param4:], 0:316-0:317\n" +
+ "[param5:], 0:322-0:323\n" +
+ "[param5:], 0:328-0:329\n");
}
@RandomlyFails
From 2247540a0c12b25a6260c891a40181eb77426f6b Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Mon, 3 Jun 2019 21:46:48 +0200
Subject: [PATCH 11/11] Resolving review comments Junichi
---
ide/editor.lib2/apichanges.xml | 2 +-
.../modules/editor/lib2/highlighting/HighlightsList.java | 4 ++--
.../modules/editor/lib2/view/HighlightsViewFactory.java | 2 +-
.../netbeans/modules/editor/lib2/view/PrependedTextView.java | 2 +-
.../src/org/netbeans/modules/editor/lib2/view/ViewUtils.java | 4 +++-
.../modules/editor/lib2/highlighting/HighlightsListTest.java | 3 ++-
6 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/ide/editor.lib2/apichanges.xml b/ide/editor.lib2/apichanges.xml
index 9d12ad2c15b5..03211f4ff722 100644
--- a/ide/editor.lib2/apichanges.xml
+++ b/ide/editor.lib2/apichanges.xml
@@ -87,7 +87,7 @@ is the proper place.
Prepended text for highlights
-
+
If AttributeSet returned from HighlightsSequence contains key "virtual-text-prepend"
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
index 1e925fa5811b..a97a9598ed37 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsList.java
@@ -159,13 +159,13 @@ public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOff
// Extends beyond first highlight
Font firstFont = ViewUtils.getFont(firstAttrs, defaultFont);
- Object firstPrependText = usePrependText && firstAttrs != null ? firstAttrs.getAttribute("virtual-text-prepend") : null;
+ Object firstPrependText = usePrependText && firstAttrs != null ? firstAttrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) : null;
int index = 1;
while (true) {
item = get(index);
AttributeSet attrs = item.getAttributes();
Font font = ViewUtils.getFont(attrs, defaultFont);
- Object prependText = usePrependText && attrs != null ? attrs.getAttribute("virtual-text-prepend") : null;
+ Object prependText = usePrependText && attrs != null ? attrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) : null;
if (!font.equals(firstFont) || !Objects.equals(firstPrependText, prependText)) { // Stop at itemEndOffset
if (index == 1) { // Just single attribute set
cutStartItems(1);
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
index c53a959359fe..fce916dd5bba 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/HighlightsViewFactory.java
@@ -257,7 +257,7 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
private @NonNull EditorView wrapWithPrependedText(@NonNull EditorView origView, @NullAllowed AttributeSet attrs) {
boolean inlineHints = documentView().op.isInlineHintsEnable();
- if (attrs != null && inlineHints && attrs.getAttribute("virtual-text-prepend") instanceof String) {
+ if (attrs != null && inlineHints && attrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) instanceof String) {
return new PrependedTextView(documentView().op, attrs, origView);
}
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
index bb5e604dbcd7..472c8f2bc63f 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/PrependedTextView.java
@@ -48,7 +48,7 @@ public PrependedTextView(DocumentViewOp op, AttributeSet attributes, EditorView
this.attributes = attributes;
this.delegate = delegate;
Font font = ViewUtils.getFont(attributes, op.getDefaultHintFont());
- prependedTextLayout = op.createTextLayout((String) attributes.getAttribute("virtual-text-prepend"), font);
+ prependedTextLayout = op.createTextLayout((String) attributes.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND), font);
Rectangle2D textBounds = prependedTextLayout.getBounds(); //TODO: allocation!
double em = op.getDefaultCharWidth();
leftShift = em / 2;
diff --git a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ViewUtils.java b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ViewUtils.java
index 836fd9250673..bda7b0751759 100644
--- a/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ViewUtils.java
+++ b/ide/editor.lib2/src/org/netbeans/modules/editor/lib2/view/ViewUtils.java
@@ -43,7 +43,9 @@
*/
public final class ViewUtils {
-
+
+ public static final String KEY_VIRTUAL_TEXT_PREPEND = "virtual-text-prepend"; //NOI18N
+
private ViewUtils() { // No instances
}
diff --git a/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java b/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
index 717dfb1ac51b..86e06938767b 100644
--- a/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
+++ b/ide/editor.lib2/test/unit/src/org/netbeans/modules/editor/lib2/highlighting/HighlightsListTest.java
@@ -26,6 +26,7 @@
import javax.swing.text.StyleConstants;
import org.junit.Test;
import org.netbeans.api.editor.settings.AttributesUtilities;
+import org.netbeans.modules.editor.lib2.view.ViewUtils;
import org.netbeans.spi.editor.highlighting.HighlightsContainer;
import org.netbeans.spi.editor.highlighting.support.OffsetsBag;
@@ -162,7 +163,7 @@ public void testSplitPrependText() throws Exception {
AttributeSet attrs2 = AttributesUtilities.createImmutable(
StyleConstants.Foreground, Color.RED,
StyleConstants.FontFamily, fontNames[0],
- "virtual-text-prepend", "test");
+ ViewUtils.KEY_VIRTUAL_TEXT_PREPEND, "test");
AttributeSet attrs3 = AttributesUtilities.createImmutable(
StyleConstants.Foreground, Color.RED,
StyleConstants.FontFamily, fontNames[1]);