Skip to content

Commit 5978524

Browse files
JEP 413: External Snippets and Snippet Attributes Support (#3498)
* Added external snippet, snippet attributes, and copy snippet support Co-authored-by: singhs-akhilesh <akhilesh.s.singh@oracle.com>
1 parent 71f182d commit 5978524

File tree

39 files changed

+403
-310
lines changed

39 files changed

+403
-310
lines changed

ide/editor.completion/src/org/netbeans/modules/editor/completion/DocumentationScrollPane.java

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
package org.netbeans.modules.editor.completion;
2222

2323
import java.awt.*;
24+
import java.awt.datatransfer.Clipboard;
25+
import java.awt.datatransfer.StringSelection;
2426
import java.awt.event.ActionEvent;
2527
import java.awt.event.InputEvent;
2628
import java.awt.event.KeyEvent;
@@ -34,11 +36,15 @@
3436
import javax.swing.event.HyperlinkEvent;
3537
import javax.swing.event.HyperlinkListener;
3638
import javax.swing.plaf.TextUI;
39+
import javax.swing.text.BadLocationException;
3740
import javax.swing.text.Caret;
41+
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
3842
import javax.swing.text.Document;
3943
import javax.swing.text.EditorKit;
44+
import javax.swing.text.Element;
4045
import javax.swing.text.JTextComponent;
4146
import javax.swing.text.Keymap;
47+
import javax.swing.text.html.HTML;
4248
import javax.swing.text.html.HTMLDocument;
4349

4450
import org.netbeans.editor.*;
@@ -47,6 +53,7 @@
4753

4854
import org.openide.awt.HtmlBrowser;
4955
import org.openide.awt.StatusDisplayer;
56+
import org.openide.util.Exceptions;
5057
import org.openide.util.ImageUtilities;
5158
import org.openide.util.NbBundle;
5259
import org.openide.util.RequestProcessor;
@@ -62,7 +69,7 @@ public class DocumentationScrollPane extends JScrollPane {
6269
private static final String FORWARD = "org/netbeans/modules/editor/completion/resources/forward.png"; //NOI18N
6370
private static final String GOTO_SOURCE = "org/netbeans/modules/editor/completion/resources/open_source_in_editor.png"; //NOI18N
6471
private static final String SHOW_WEB = "org/netbeans/modules/editor/completion/resources/open_in_external_browser.png"; //NOI18N
65-
72+
6673
private static final String JAVADOC_ESCAPE = "javadoc-escape"; //NOI18N
6774
private static final String JAVADOC_BACK = "javadoc-back"; //NOI18N
6875
private static final String JAVADOC_FORWARD = "javadoc-forward"; //NOI18N
@@ -118,7 +125,7 @@ public DocumentationScrollPane(JTextComponent editorComponent) {
118125
}
119126
view.addHyperlinkListener(new HyperlinkAction());
120127
setViewportView(view);
121-
128+
122129
installTitleComponent();
123130
installKeybindings(editorComponent);
124131
this.editorComponent = editorComponent;
@@ -451,8 +458,26 @@ private class MouseEventListener extends MouseAdapter {
451458

452459
private class HyperlinkAction implements HyperlinkListener {
453460

461+
@Override
454462
public void hyperlinkUpdate(HyperlinkEvent e) {
455-
if (e != null && HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
463+
if (e != null && e.getEventType() == HyperlinkEvent.EventType.ACTIVATED && e.getDescription().startsWith("copy.snippet")) {
464+
Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
465+
String snippetCount = e.getDescription().replaceAll("[^0-9]", "");
466+
HTMLDocument HtmlDoc = (HTMLDocument) e.getSourceElement().getDocument();
467+
HTMLDocView source = (HTMLDocView) e.getSource();
468+
source.getText();
469+
Element snippetElement = HtmlDoc.getElement("snippet" + snippetCount);
470+
StringBuilder text = new StringBuilder();
471+
getTextToCopy(HtmlDoc, text, snippetElement);
472+
handleTextToCopy(HtmlDoc, snippetElement, text);
473+
systemClipboard.setContents(new StringSelection(text.toString()), null);
474+
view.getHighlighter().removeAllHighlights();
475+
try {
476+
view.getHighlighter().addHighlight(e.getSourceElement().getStartOffset(), e.getSourceElement().getEndOffset(), new DefaultHighlightPainter(Color.GRAY));
477+
} catch (BadLocationException ex) {
478+
Exceptions.printStackTrace(ex);
479+
}
480+
} else if (e != null && HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) {
456481
final String desc = e.getDescription();
457482
if (desc != null) {
458483
RP.post(new Runnable() {
@@ -470,7 +495,48 @@ public void hyperlinkUpdate(HyperlinkEvent e) {
470495
}
471496
}
472497
});
473-
}
498+
}
499+
}
500+
}
501+
502+
private void handleTextToCopy(HTMLDocument HtmlDoc, Element snippetElement, StringBuilder text) {
503+
HTMLDocument.Iterator it = HtmlDoc.getIterator(HTML.Tag.A);
504+
int startOffset = snippetElement.getStartOffset();
505+
int endOffset = snippetElement.getEndOffset();
506+
int count = 0;
507+
while (it.isValid()) {
508+
int startOffset1 = it.getStartOffset();
509+
int endOffset1 = it.getEndOffset();
510+
try {
511+
String aTagText = HtmlDoc.getText(startOffset1, endOffset1 - startOffset1);
512+
if (startOffset1 > startOffset && endOffset1 < endOffset
513+
&& aTagText.length() == 1 && Character.isWhitespace(aTagText.charAt(0))) {
514+
text.deleteCharAt(startOffset1 - startOffset - count);
515+
count++;
516+
}
517+
} catch (BadLocationException ex) {
518+
Exceptions.printStackTrace(ex);
519+
}
520+
it.next();
521+
}
522+
text.delete(0, text.indexOf("\n") + 1); //removing first line of div i.e. "Copy"
523+
}
524+
525+
private void getTextToCopy(HTMLDocument HtmlDoc, StringBuilder sb, Element snippetElement) {
526+
int elementCount = snippetElement.getElementCount();
527+
if (elementCount == 0) {
528+
int startOffset = snippetElement.getStartOffset();
529+
int endOffset = snippetElement.getEndOffset();
530+
try {
531+
sb.append(HtmlDoc.getText(startOffset, endOffset - startOffset));
532+
} catch (BadLocationException ex) {
533+
Exceptions.printStackTrace(ex);
534+
}
535+
return;
536+
}
537+
for (int i = 0; i < elementCount; i++) {
538+
Element element = snippetElement.getElement(i);
539+
getTextToCopy(HtmlDoc, sb, element);
474540
}
475541
}
476542
}

ide/editor.completion/src/org/netbeans/modules/editor/completion/HTMLDocView.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ public HTMLDocView(Color bgColor) {
6565
//add listeners for selection support
6666
addMouseListener(new MouseListener() {
6767
public void mouseClicked(MouseEvent e) {
68-
getHighlighter().removeAllHighlights();
6968
}
7069
public void mousePressed(MouseEvent e) {
7170
getHighlighter().removeAllHighlights();
@@ -77,7 +76,11 @@ public void mousePressed(MouseEvent e) {
7776
}
7877
}
7978

80-
public void mouseReleased(MouseEvent e) {}
79+
public void mouseReleased(MouseEvent e) {
80+
if(getSelectedText() == null){
81+
getHighlighter().removeAllHighlights();
82+
}
83+
}
8184
public void mouseEntered(MouseEvent e) {}
8285
public void mouseExited(MouseEvent e) {}
8386
});

java/java.editor/src/org/netbeans/modules/java/editor/javadoc/TagRegistery.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ private TagRegistery() {
100100
addTag("@uses", false, EnumSet.of(ElementKind.MODULE));
101101

102102
addTag("@code", true, ALL_KINDS);
103-
addTag("@snippet", true, ALL_KINDS);
103+
addTag("@snippet", true, ALL_KINDS);
104104
addTag("@docRoot", true, ALL_KINDS);
105105
// just in empty tag description
106106
addTag("@inheritDoc", true, EnumSet.of(ElementKind.METHOD));
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testHighlightAndReplace_cornercase</b>()</pre><p><pre><code> public static void \bmain\b(String... args) {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testHighlightAndReplace_cornercase</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> public static void \bmain\b(String... args) {
23
S<b>y</b><b>s</b>replace<b>.</b><b>o</b><b>u</b><b>t</b>.println("tests");
34
}
45

5-
</code></pre><p>
6+
</code></pre></div><p>

java/java.editor/test/unit/data/goldenfiles/org/netbeans/modules/editor/java/GoToSupportTest/javadocsnippet_NestedRegion_Highlight_And_replace.pass

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testNestedRegion_Highlight_And_replace</b>()</pre><p><pre><code> public static void \bmain\b(String... args) {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testNestedRegion_Highlight_And_replace</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> public static void \bmain\b(String... args) {
23
for (var <i><b>a</b></i><i><b>r</b></i><i><b>g</b></i> : <i><b>a</b></i><i><b>r</b></i><i><b>g</b></i>s) {
34
if (!<b>a</b><b>r</b><b>g</b>.isBl<b>a</b><b>r</b><b>g</b>k()) {
45
System.<b><b>a</b></b><b><b>r</b></b><b><b>g</b></b>.println("<b><b>a</b></b><b><b>r</b></b><b><b>g</b></b>");
@@ -13,4 +14,4 @@
1314
}
1415
}
1516

16-
</code></pre><p>
17+
</code></pre></div><p>
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testNestedRegion_ReplaceAnnotation_Regex</b>()</pre><p><pre><code> class HelloWorld<span style="background-color:yellow;">1</span> {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testNestedRegion_ReplaceAnnotation_Regex</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> class HelloWorld<span style="background-color:yellow;">1</span> {
23
public static void main(String... args) {
34
UPPERystem.out.println(num);
45
UPPERystem.out.println(num);
@@ -7,4 +8,4 @@
78
}
89
}
910

10-
</code></pre><p>
11+
</code></pre></div><p>
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testNestedRegion_ReplaceAnnotation_Substring</b>()</pre><p><pre><code> class HelloWorld {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testNestedRegion_ReplaceAnnotation_Substring</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> class HelloWorld {
23
public static void main(String... args) {
34
System.err.println("print");
45
System.err.println("print" + "to-do");
@@ -7,4 +8,4 @@
78
}
89
}
910

10-
</code></pre><p>
11+
</code></pre></div><p>
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testRegion_ReplaceAnnotation_Regex</b>()</pre><p><pre><code> class HelloWorld {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testRegion_ReplaceAnnotation_Regex</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> class HelloWorld {
23
public static void main(String... args) {
34
System.out.println("...replace..."); //to-do
45
System.out.println("...replace..."
56
System.out.println("...replace...");
67
}
78
}
89

9-
</code></pre><p>
10+
</code></pre></div><p>
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testRegion_ReplaceAnnotation_RegexInnComment</b>()</pre><p><pre><code> class HelloWorld {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testRegion_ReplaceAnnotation_RegexInnComment</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> class HelloWorld {
23
public static void main(String... args) {
34
System.out.println("...replace..." + "Good morning"); //"...replace..."
45
System.out.println("Hello World!" + "...replace...");
56
}
67
}
78

8-
</code></pre><p>
9+
</code></pre></div><p>
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testSingleLine_MultipleReplaceAnnotation_Regex</b>()</pre><p><pre><code> class HelloWorld {
1+
<html><body><font size='+0'><b><a href='*0'>test.&#x200B;Test</a></b></font><pre>public void <b>testSingleLine_MultipleReplaceAnnotation_Regex</b>()</pre><p><div id="snippet1" style="font-size: 10px; border: 1px solid black; margin-top: 2px; margin-bottom: 2px"><div align=right><a href="copy.snippet1">Copy</a></div>
2+
<pre><code> class HelloWorld {
23
public static void main(String... args) {
34
System.err.println(...replace...);
45
}
56
}
67

7-
</code></pre><p>
8+
</code></pre></div><p>

0 commit comments

Comments
 (0)