-
Notifications
You must be signed in to change notification settings - Fork 890
Added bracket highlighting for generic angle brackets #8500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,11 +50,12 @@ | |
*/ | ||
public final class JavaBracesMatcher implements BracesMatcher, BracesMatcherFactory, BracesMatcher.ContextLocator { | ||
|
||
private static final char [] PAIRS = new char [] { '(', ')', '[', ']', '{', '}' }; //NOI18N | ||
private static final char [] PAIRS = new char [] { '(', ')', '[', ']', '{', '}', '<', '>' }; //NOI18N | ||
private static final JavaTokenId [] PAIR_TOKEN_IDS = new JavaTokenId [] { | ||
JavaTokenId.LPAREN, JavaTokenId.RPAREN, | ||
JavaTokenId.LBRACKET, JavaTokenId.RBRACKET, | ||
JavaTokenId.LBRACE, JavaTokenId.RBRACE | ||
JavaTokenId.LBRACE, JavaTokenId.RBRACE, | ||
JavaTokenId.LT, JavaTokenId.GT | ||
}; | ||
|
||
private final MatcherContext context; | ||
|
@@ -98,13 +99,13 @@ public int[] findOrigin() throws BadLocationException, InterruptedException { | |
context.getLimitOffset(), | ||
PAIRS | ||
); | ||
|
||
if (origin != null) { | ||
originOffset = origin[0]; | ||
originChar = PAIRS[origin[1]]; | ||
matchingChar = PAIRS[origin[1] + origin[2]]; | ||
backward = origin[2] < 0; | ||
|
||
// Filter out block and line comments | ||
TokenHierarchy<Document> th = TokenHierarchy.get(context.getDocument()); | ||
sequences = getEmbeddedTokenSequences(th, originOffset, backward, JavaTokenId.language()); | ||
|
@@ -146,17 +147,17 @@ public int[] findMatches() throws InterruptedException, BadLocationException { | |
list = th.tokenSequenceList(seq.languagePath(), originOffset + 1, context.getDocument().getLength()); | ||
} | ||
int counter = 0; | ||
|
||
seq.move(originOffset); | ||
if (seq.moveNext()) { | ||
Token<?> token = seq.token(); | ||
|
||
if (token.id() == JavaTokenId.STRING_LITERAL || | ||
token.id() == JavaTokenId.MULTILINE_STRING_LITERAL) { | ||
|
||
for(TokenSequenceIterator tsi = new TokenSequenceIterator(list, backward); tsi.hasMore(); ) { | ||
TokenSequence<?> sq = tsi.getSequence(); | ||
|
||
if (sq.token().id() == JavaTokenId.STRING_LITERAL || | ||
sq.token().id() == JavaTokenId.MULTILINE_STRING_LITERAL) { | ||
|
||
|
@@ -249,6 +250,97 @@ public int[] findMatches() throws InterruptedException, BadLocationException { | |
|
||
JavaTokenId originId = getTokenId(originChar); | ||
JavaTokenId lookingForId = getTokenId(matchingChar); | ||
|
||
/* The lexer tokenizes << and >> because they are bit shift | ||
** operators. Special handler is required to bracematch angle | ||
** brackets in generic types so that generic angles are | ||
** differentiated from bitwise operators.*/ | ||
|
||
/* One idea was to modify the input TokenHierachy to split | ||
** GTGT tokens into 2 separate GT and GT tokens. However, | ||
** it seems like almost all token related classes are immutable | ||
** or inaccessible due to private constructors. Leading me to | ||
** write this. */ | ||
Comment on lines
+259
to
+263
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The TokenHierarchy/-sequence represents the lexing result and yes, for analysis they are read-only. This comment gives reasoning for the current implementation, but reads more like "note to self", then intentional for others. |
||
if (originId == JavaTokenId.LT || originId == JavaTokenId.GT) { | ||
|
||
for(TokenSequenceIterator tsi = new TokenSequenceIterator(list, backward); tsi.hasMore();) { | ||
TokenSequence<?> sq = tsi.getSequence(); | ||
|
||
if (sq.token().id() == JavaTokenId.GTGT) { | ||
if (originId == JavaTokenId.GT) { | ||
if (originOffset != sq.offset()) { | ||
counter += (originOffset - sq.offset()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the idea here. Why is the |
||
} else { | ||
counter++; | ||
} | ||
} | ||
|
||
if (lookingForId == JavaTokenId.GT) { | ||
if (counter <= 1) { | ||
return new int [] {sq.offset() + counter, sq.offset() + 1 + counter}; | ||
} else { | ||
counter -= 2; | ||
} | ||
} | ||
} | ||
|
||
if (sq.token().id() == JavaTokenId.GTGTGT) { | ||
if (originId == JavaTokenId.GT) { | ||
if (originOffset != sq.offset()) { | ||
int test = sq.offset(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. stray test code? |
||
counter += (originOffset - sq.offset()); | ||
} else { | ||
counter++; | ||
} | ||
} | ||
|
||
if (lookingForId == JavaTokenId.GT) { | ||
if (counter <= 2) { | ||
return new int [] {sq.offset() + counter, sq.offset() + 1 + counter}; | ||
} else { | ||
counter -= 3; | ||
} | ||
} | ||
} | ||
|
||
if (sq.token().id() == JavaTokenId.LTLT) { | ||
if (originId == JavaTokenId.LT) { | ||
if (originOffset != sq.offset()) { | ||
counter += 2; | ||
} else { | ||
counter++; | ||
} | ||
} | ||
|
||
//Shouldn't happen, but added it anyways. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume that this refers to the fact, that after each opening brace a type must be placed? I mean |
||
if (lookingForId == JavaTokenId.LT) { | ||
switch (counter) { | ||
case 1: | ||
return new int [] {sq.offset(), sq.offset() + 1 + counter}; | ||
case 0: | ||
return new int [] {sq.offset() + 1, sq.offset() + 1 + counter}; | ||
default: | ||
counter -= 2; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (originId == sq.token().id()) { | ||
counter++; | ||
} | ||
|
||
if (lookingForId == sq.token().id()) { | ||
if (counter == 0) { | ||
return new int [] {sq.offset(), sq.offset() + sq.token().length()}; | ||
} else { | ||
counter--; | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
for(TokenSequenceIterator tsi = new TokenSequenceIterator(list, backward); tsi.hasMore(); ) { | ||
TokenSequence<?> sq = tsi.getSequence(); | ||
|
@@ -428,7 +520,7 @@ public static List<TokenSequence<?>> getEmbeddedTokenSequences( | |
for(int i = sequences.size() - 1; i >= 0; i--) { | ||
TokenSequence<?> seq = sequences.get(i); | ||
if (seq.language() == language) { | ||
break; | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong indentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change is unnessary and wrong as already indicated by @essien. Please remove. |
||
} else { | ||
sequences.remove(i); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,13 @@ public void testMultilineStringBrackets() throws Exception { | |
+ "^)\n" | ||
+ "\"\"\""); | ||
} | ||
|
||
public void testAngleBrackets() throws Exception { | ||
assertMatches2("^<test^>"); | ||
assertMatches2("Map^<Class<? extends AbstractStudent>, Map<CourseTime, List<? extends AbstractCourse>>^>"); | ||
assertMatches2("Map<Class<? extends AbstractStudent>, Map^<CourseTime, List<? extends AbstractCourse>^>>"); | ||
assertMatches2("Map x = new HashMap<String, List^<String^>>()"); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs more test cases. I added some and hit a bug: assertMatches2("^<test^>");
assertMatches2("Map^<Class<? extends AbstractStudent>, Map<CourseTime, List<? extends AbstractCourse>>^>");
assertMatches2("Map<Class<? extends AbstractStudent>, Map^<CourseTime, List<? extends AbstractCourse>^>>");
assertMatches2("Map<Class<? extends AbstractStudent>, Map<CourseTime, List^<? extends AbstractCourse^>>>");
assertMatches2("Map<Class^<? extends AbstractStudent^>, Map<CourseTime, List<? extends AbstractCourse>>>");
assertMatches2("Map^<Map<CourseTime, List<? extends AbstractCourse>>, Class<? extends AbstractStudent>^>");
assertMatches2("Map<Map^<CourseTime, List<? extends AbstractCourse>^>, Class<? extends AbstractStudent>>");
assertMatches2("Map<Map<CourseTime, List^<? extends AbstractCourse^>>, Class<? extends AbstractStudent>>");
assertMatches2("Map<Map<CourseTime, List<? extends AbstractCourse>>, Class^<? extends AbstractStudent^>>");
assertMatches2("Map x = new HashMap<String, List^<String^>>()");
assertMatches2("Map x = new HashMap^<String, List<String>^>()"); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May I also add that class LinkedList < T extends Object & Serializable > {
} but int Object = 2;
int Serializable = 3;
boolean result = 1 < Object & Serializable > 4; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, there needs to be some way to differentiate generic brackets from comparison/operator brackets. |
||
|
||
//from CslTestBase: | ||
protected void assertMatches2(String original) throws Exception { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove space at end of lines (see lines 102, 108, 150, 154, 160)