Skip to content

Commit

Permalink
Merge pull request #550 from junichi11/netbeans-791
Browse files Browse the repository at this point in the history
[NETBEANS-791] Highlights for the top line of JavaDoc are done on every line.
  • Loading branch information
junichi11 authored Jul 17, 2018
2 parents 396c685 + 0238c3d commit 5de5478
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 32 deletions.
2 changes: 1 addition & 1 deletion javadoc/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# under the License.

javac.compilerargs=-Xlint:unchecked
javac.source=1.7
javac.source=1.8

# requires nb.javac for compiling of tests on Mac
requires.nb.javac=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.netbeans.modules.javadoc.highlighting;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Enumeration;
Expand All @@ -45,6 +46,7 @@
import org.netbeans.api.lexer.TokenHierarchyListener;
import org.netbeans.api.lexer.TokenId;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.api.lexer.TokenUtilities;
import org.netbeans.spi.editor.highlighting.HighlightsSequence;
import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer;
import org.openide.util.WeakListeners;
Expand All @@ -55,21 +57,26 @@
public class Highlighting extends AbstractHighlightsContainer implements TokenHierarchyListener {

private static final Logger LOG = Logger.getLogger(Highlighting.class.getName());

private static final String WS = " \t\n"; // NOI18N
private static final String JAPANESE_PERIOD = "\u3002"; // 。 NOI18N
private static final List<String> PERIODS = Arrays.asList(
JAPANESE_PERIOD
);

public static final String LAYER_ID = "org.netbeans.modules.javadoc.highlighting"; //NOI18N

private final AttributeSet fontColor;

private final Document document;
private TokenHierarchy<? extends Document> hierarchy = null;
private final AtomicLong version = new AtomicLong();

/** Creates a new instance of Highlighting */
public Highlighting(Document doc) {
AttributeSet firstLineFontColor = MimeLookup.getLookup(MimePath.get("text/x-java")).lookup(FontColorSettings.class).getTokenFontColors("javadoc-first-sentence"); //NOI18N
AttributeSet commentFontColor = MimeLookup.getLookup(MimePath.get("text/x-java")).lookup(FontColorSettings.class).getTokenFontColors("comment"); //NOI18N
if(firstLineFontColor != null && commentFontColor != null) {
Collection<Object> attrs = new LinkedList<Object>();
Collection<Object> attrs = new LinkedList<>();
for (Enumeration<?> e = firstLineFontColor.getAttributeNames(); e.hasMoreElements(); ) {
Object key = e.nextElement();
Object value = firstLineFontColor.getAttribute(key);
Expand Down Expand Up @@ -110,7 +117,7 @@ public HighlightsSequence getHighlights(int startOffset, int endOffset) {
public void tokenHierarchyChanged(TokenHierarchyEvent evt) {
TokenChange<?> tc = evt.tokenChange();
int affectedArea [] = null;

TokenSequence<? extends TokenId> seq = tc.currentTokenSequence();
if (seq.language().equals(JavadocTokenId.language())) {
// Change inside javadoc
Expand All @@ -131,7 +138,7 @@ public void tokenHierarchyChanged(TokenHierarchyEvent evt) {
// find out whether it really involves javadoc or not.
affectedArea = new int [] { tc.offset(), evt.affectedEndOffset() };
}

if (affectedArea != null) {
version.incrementAndGet();
fireHighlightsChange(affectedArea[0], affectedArea[1]);
Expand All @@ -147,13 +154,34 @@ public void tokenHierarchyChanged(TokenHierarchyEvent evt) {
if (seq.moveNext()) {
int start = seq.offset();
do {
String period = null;
int indexOfPeriod = -1;
for (String p : PERIODS) {
int index = TokenUtilities.indexOf(seq.token().text(), p);
if (index != -1) {
if (indexOfPeriod == -1 || index < indexOfPeriod) {
indexOfPeriod = index;
period = p;
}
}
}

if (seq.token().id() == JavadocTokenId.DOT) {
if (seq.moveNext()) {
if (isWhiteSpace(seq.token())) {
return new int [] { start, seq.offset()};
}
seq.movePrevious();
}
} else if (period != null && indexOfPeriod != -1) {
// NETBEANS-791
int offset = indexOfPeriod + 1;
while (offset < seq.token().length()
&& isPeriod(seq.token().text().subSequence(offset, offset + 1))) {
// e.g. 。。。
offset++;
}
return new int[]{start, seq.offset() + offset};
} else if (seq.token().id() == JavadocTokenId.TAG) {
if (seq.movePrevious()) {
if (!seq.token().text().toString().trim().endsWith("{")) {
Expand All @@ -172,21 +200,24 @@ private static boolean isWhiteSpace(Token<? extends TokenId> token) {
if (token == null || token.id() != JavadocTokenId.OTHER_TEXT) {
return false;
}
String ws = " \t\n";
return ws.indexOf(token.text().charAt(0)) >= 0;
return WS.indexOf(token.text().charAt(0)) >= 0;
}

private static boolean isPeriod(CharSequence cs) {
return PERIODS.stream().anyMatch(period -> TokenUtilities.equals(cs, period));
}

private final class HSImpl implements HighlightsSequence {
private long version;
private TokenHierarchy<? extends Document> scanner;

private final long version;
private final TokenHierarchy<? extends Document> scanner;
private List<TokenSequence<? extends TokenId>> sequences;
private int startOffset;
private int endOffset;
private final int startOffset;
private final int endOffset;

private List<Integer> lines = null;
private int linesIdx = -1;

public HSImpl(long version, TokenHierarchy<? extends Document> scanner, int startOffset, int endOffset) {
this.version = version;
this.scanner = scanner;
Expand All @@ -195,10 +226,11 @@ public HSImpl(long version, TokenHierarchy<? extends Document> scanner, int star
this.sequences = null;
}

@Override
public boolean moveNext() {
synchronized (Highlighting.this) {
checkVersion();

if (sequences == null) {
// initialize
TokenSequence<?> tokenSequence = scanner.tokenSequence();
Expand All @@ -208,7 +240,7 @@ public boolean moveNext() {
return false;
}
TokenSequence<?> seq = tokenSequence.subSequence(startOffset, endOffset);
sequences = new ArrayList<TokenSequence<? extends TokenId>>();
sequences = new ArrayList<>();
sequences.add(seq);
}

Expand All @@ -217,11 +249,11 @@ public boolean moveNext() {
linesIdx += 2;
return true;
}

lines = null;
linesIdx = -1;
}

while (!sequences.isEmpty()) {
TokenSequence<? extends TokenId> seq = sequences.get(sequences.size() - 1);

Expand Down Expand Up @@ -257,10 +289,11 @@ public boolean moveNext() {
}
}

@Override
public int getStartOffset() {
synchronized (Highlighting.this) {
checkVersion();

if (sequences == null) {
throw new NoSuchElementException("Call moveNext() first."); //NOI18N
}
Expand All @@ -273,10 +306,11 @@ public int getStartOffset() {
}
}

@Override
public int getEndOffset() {
synchronized (Highlighting.this) {
checkVersion();

if (sequences == null) {
throw new NoSuchElementException("Call moveNext() first."); //NOI18N
}
Expand All @@ -289,10 +323,11 @@ public int getEndOffset() {
}
}

@Override
public AttributeSet getAttributes() {
synchronized (Highlighting.this) {
checkVersion();

if (sequences == null) {
throw new NoSuchElementException("Call moveNext() first."); //NOI18N
}
Expand All @@ -304,17 +339,17 @@ public AttributeSet getAttributes() {
}
}
}

private void checkVersion() {
if (this.version != Highlighting.this.version.get()) {
throw new ConcurrentModificationException();
}
}

private List<Integer> splitByLines(int sentenceStart, int sentenceEnd) {
ArrayList<Integer> lines = new ArrayList<Integer>();
ArrayList<Integer> lines = new ArrayList<>();
int offset = sentenceStart;

try {
while (offset < sentenceEnd) {
Element lineElement = document.getDefaultRootElement().getElement(
Expand All @@ -325,9 +360,9 @@ private List<Integer> splitByLines(int sentenceStart, int sentenceEnd) {

String line = document.getText(rowStart, rowEnd - rowStart);
int idx = 0;
while (idx < line.length() &&
(line.charAt(idx) == ' ' ||
line.charAt(idx) == '\t' ||
while (idx < line.length() &&
(line.charAt(idx) == ' ' ||
line.charAt(idx) == '\t' ||
line.charAt(idx) == '*'))
{
idx++;
Expand All @@ -343,7 +378,7 @@ private List<Integer> splitByLines(int sentenceStart, int sentenceEnd) {
} catch (BadLocationException e) {
LOG.log(Level.WARNING, "Can't determine javadoc first sentence", e);
}

return lines.isEmpty() ? null : lines;
}
} // End of HSImpl class
Expand Down
Loading

0 comments on commit 5de5478

Please sign in to comment.