netbeans
netbeans copied to clipboard
Add generics angle brackets (<>) highlighting for Java
Description
When we work with round brackets in java we can see the start and end bracket via highlighting. For example:
I suggest to add the same functionality for angle bracket of generics, because rather often a structure can be complex and it is not seen where the bracket starts and where it ends.
For example,
Map<Class<? extends AbstractStudent>, Map<CourseTime, List<? extends AbstractCourse>>> coursesByStudentTypeAndTime;
The issue was also opened in old jira: https://issues.apache.org/jira/browse/NETBEANS-5716
Use case/motivation
No response
Related issues
No response
Are you willing to submit a pull request?
No
Code of Conduct
Yes
@neilcsmith-net Maybe it is necessary to increase the priority of this issue? This is real a very basic feature and it is still absent.
Not sure why you're tagging me specifically, but let's add it to the contribute page and labels.
I would like to contribute to this issue.
Hi I have opened a pull request referencing this issue, but I require some guidance. Can someone please review and help me with it?
I had a look at the PR and I think all changes outside JavaBracesMatcher.java
should not be there. of course you can try to change the lexing strategy for the java language in NetBeans, but that will be an uphill battle. I suggest to modify the braces matcher to deal with situations where characters do not map to a single token.
The java lexer can generate these tokens, that could match your case:
- JavaTokenId.LT
- JavaTokenId.LTLT
- JavaTokenId.LTLTEQ
- JavaTokenId.GT
- JavaTokenId.GTEQ
- JavaTokenId.GTGT
- JavaTokenId.GTGTEQ
- JavaTokenId.GTGTGT
- JavaTokenId.GTGTGTEQ
For example this code:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class testLexer<V> {
public static <K,V2> void add(K k, V2 v) {}
public static void main(String[] argv) {
Map<String,Map<UUID,List<Map<Integer,Number>>>> m = new HashMap<>();
}
}
is lexed to this token stream:
IMPORT "import", la=1
WHITESPACE " ", la=1
IDENTIFIER "java", la=1
DOT ".", la=1
IDENTIFIER "util", la=1
DOT ".", la=1
IDENTIFIER "HashMap", la=1
SEMICOLON ";"
WHITESPACE "\n", la=1
IMPORT "import", la=1
WHITESPACE " ", la=1
IDENTIFIER "java", la=1
DOT ".", la=1
IDENTIFIER "util", la=1
DOT ".", la=1
IDENTIFIER "List", la=1
SEMICOLON ";"
WHITESPACE "\n", la=1
IMPORT "import", la=1
WHITESPACE " ", la=1
IDENTIFIER "java", la=1
DOT ".", la=1
IDENTIFIER "util", la=1
DOT ".", la=1
IDENTIFIER "Map", la=1
SEMICOLON ";"
WHITESPACE "\n", la=1
IMPORT "import", la=1
WHITESPACE " ", la=1
IDENTIFIER "java", la=1
DOT ".", la=1
IDENTIFIER "util", la=1
DOT ".", la=1
IDENTIFIER "UUID", la=1
SEMICOLON ";"
WHITESPACE "\n\n\n", la=1
PUBLIC "public", la=1
WHITESPACE " ", la=1
CLASS "class", la=1
WHITESPACE " ", la=1
IDENTIFIER "testLexer", la=1
LT "<", la=1
IDENTIFIER "V", la=1
GT ">", la=1
WHITESPACE " ", la=1
LBRACE "{"
WHITESPACE "\n ", la=1
PUBLIC "public", la=1
WHITESPACE " ", la=1
STATIC "static", la=1
WHITESPACE " ", la=1
LT "<", la=1
IDENTIFIER "K", la=1
COMMA ","
IDENTIFIER "V2", la=1
GT ">", la=1
WHITESPACE " ", la=1
VOID "void", la=1
WHITESPACE " ", la=1
IDENTIFIER "add", la=1
LPAREN "("
IDENTIFIER "K", la=1
WHITESPACE " ", la=1
IDENTIFIER "k", la=1
COMMA ","
WHITESPACE " ", la=1
IDENTIFIER "V2", la=1
WHITESPACE " ", la=1
IDENTIFIER "v", la=1
RPAREN ")"
WHITESPACE " ", la=1
LBRACE "{"
RBRACE "}"
WHITESPACE "\n\n ", la=1
PUBLIC "public", la=1
WHITESPACE " ", la=1
STATIC "static", la=1
WHITESPACE " ", la=1
VOID "void", la=1
WHITESPACE " ", la=1
IDENTIFIER "main", la=1
LPAREN "("
IDENTIFIER "String", la=1
LBRACKET "["
RBRACKET "]"
WHITESPACE " ", la=1
IDENTIFIER "argv", la=1
RPAREN ")"
WHITESPACE " ", la=1
LBRACE "{"
WHITESPACE "\n ", la=1
IDENTIFIER "Map", la=1
LT "<", la=1
IDENTIFIER "String", la=1
COMMA ","
IDENTIFIER "Map", la=1
LT "<", la=1
IDENTIFIER "UUID", la=1
COMMA ","
IDENTIFIER "List", la=1
LT "<", la=1
IDENTIFIER "Map", la=1
LT "<", la=1
IDENTIFIER "Integer", la=1
COMMA ","
IDENTIFIER "Number", la=1
GTGTGT ">>>", la=1
GT ">", la=1
WHITESPACE " ", la=1
IDENTIFIER "m", la=1
WHITESPACE " ", la=1
EQ "=", la=1
WHITESPACE " ", la=1
NEW "new", la=1
WHITESPACE " ", la=1
IDENTIFIER "HashMap", la=1
LT "<", la=1
GT ">", la=1
LPAREN "("
RPAREN ")"
SEMICOLON ";"
WHITESPACE "\n ", la=1
RBRACE "}"
WHITESPACE "\n", la=1
RBRACE "}"
----- EOF -----
The dump was generated by saving the java file to java/java.lexer/test/unit/data/testfiles/testLexer.java
, adding
public void test2() throws Exception {
LexerTestUtilities.checkTokenDump(this, "testfiles/testLexer.java",
JavaTokenId.language());
}
to JavaTokenDumpTest
and running that test.
In the sample you find both GT
and GTGTGT
. I don't know why it was done this way, but I would start with the assumption, that they author made a sane decision there.
@matthiasblaesing Thanks for the advice.
I suggest to modify the braces matcher to deal with situations where characters do not map to a single token.
Can you please elaborate how it will be possible to do this? Also, before adding support for highlighting characters that map to multiple tokens, I feel like I should make single character with single token work first, which I have not been able to do so far. The pair of single open and closing angle brackets should be highlighted, but they are not.
Not sure what you are seeing as a problem, but that case seems trivial:
--- a/java/java.editor/src/org/netbeans/modules/editor/java/JavaBracesMatcher.java
+++ b/java/java.editor/src/org/netbeans/modules/editor/java/JavaBracesMatcher.java
@@ -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;
results in (this is NetBeans colorscheme, matching braces are highlighted in yellow):
Match from left:
Match from right:
Jumping between the matching braces also worked.
Edit: This also works for simple type arguments:
Hi @matthiasblaesing, I just checked the latest netbeans source code and it looks like the changes you suggested here have already been incorporated. But upon running ant build on the latest cloned branch (I did not make any changes in it), I am still getting the same error as before, i.e., the red highlight on only one bracket rather than the yellow one on both (the color scheme is the same as before, i.e., yellow for matching braces).
Nothing I suggested was worth a direct integration and it was not done. I suspect, that you are looking at an old checkout and did not switch to the current master.
Please show the output of git log -n 1
and git status
.
Output of git log:
Output of git status:
You are right the changes were not directly integrated. I reset the local branch hard to upstream and I thought all of my previous changes to it would be wiped, as I did not want to clone the repository again for starting fresh. But that is not the case, apparently.
It was a false alarm. Apologies for any inconvenience this may have caused.
@TheMarvelFan Could you say if you are working on this issue? As I understand @matthiasblaesing has shown what it is necessary to do.
Hi @PavelTurk , Yes I am working on this issue and I will soon be adding the finishing commit to the PR.
Nothing I suggested was worth a direct integration and it was not done. I suspect, that you are looking at an old checkout and did not switch to the current master.
@matthiasblaesing Could you explain why the code you showed can't be added to master? According to your example everything works. What else should be done?
@PavelTurk no - not everything works:
The highlighting is broken.