From bfade94a696b22d1aa7ce76953613d9942bf1701 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Sun, 27 May 2018 02:50:57 +1200 Subject: [PATCH 01/59] fix catch and throws clauses --- grammars/java.cson | 18 ++++++++- spec/java-spec.coffee | 87 ++++++++++++++++++++++++++++++++----------- 2 files changed, 82 insertions(+), 23 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index cb9947a..5076394 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -595,7 +595,16 @@ 'include': '#comments' } { - 'include': '#parameters' + 'match': '\\|' + 'name': 'punctuation.catch.separator' + } + { + 'match': '([a-zA-Z$_][\\.a-zA-Z0-9$_]*)\\s*(\\w+)*' + 'captures': + '1': + 'name': 'storage.type.java' + '2': + 'name': 'variable.parameter.java' } ] } @@ -1218,7 +1227,12 @@ 'name': 'meta.throwables.java' 'patterns': [ { - 'include': '#object-types' + 'match': ',' + 'name': 'punctuation.throwables.separator' + } + { + 'match': '[a-zA-Z$_][\\.a-zA-Z0-9$_]*' + 'name': 'storage.type.java' } ] 'variables': diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 0213101..faf0332 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1439,20 +1439,20 @@ describe 'Java grammar', -> it 'tokenizes try-catch-finally blocks', -> lines = grammar.tokenizeLines ''' - class Test { - public void fn() { - try { - errorProneMethod(); - } catch (RuntimeException re) { - handleRuntimeException(re); - } catch (Exception e) { - String variable = "assigning for some reason"; - } finally { - // Relax, it's over - new Thingie().call(); + class Test { + public void fn() { + try { + errorProneMethod(); + } catch (RuntimeException re) { + handleRuntimeException(re); + } catch (Exception e) { + String variable = "assigning for some reason"; + } finally { + // Relax, it's over + new Thingie().call(); + } } } - } ''' scopeStack = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java'] @@ -1512,17 +1512,17 @@ describe 'Java grammar', -> it 'tokenizes nested try-catch-finally blocks', -> lines = grammar.tokenizeLines ''' - class Test { - public void fn() { - try { + class Test { + public void fn() { try { - String nested; - } catch (Exception e) { - handleNestedException(); - } - } catch (RuntimeException re) {} + try { + String nested; + } catch (Exception e) { + handleNestedException(); + } + } catch (RuntimeException re) {} + } } - } ''' scopeStack = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java'] @@ -1605,6 +1605,51 @@ describe 'Java grammar', -> expect(lines[4][2]).toEqual value: ' ', scopes: scopes expect(lines[4][3]).toEqual value: '{', scopes: scopes.concat ['punctuation.section.try.begin.bracket.curly.java'] + it 'tokenizes list of exceptions in catch block', -> + lines = grammar.tokenizeLines ''' + class Test + { + private void method() { + try { + // do something + } catch (Exception1 | Exception2 err) { + throw new Exception3(); + } + } + } + ''' + + expect(lines[5][3]).toEqual value: 'catch', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'keyword.control.catch.java'] + expect(lines[5][5]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[5][6]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[5][8]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator'] + expect(lines[5][10]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[5][12]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] + expect(lines[5][13]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + + it 'tokenizes list of exceptions in method throws clause', -> + lines = grammar.tokenizeLines ''' + class Test { + public void test1() throws Exception1, Exception2 { + // throws exceptions + } + + public void test2() throws Exception1 { + // throws exceptions + } + } + ''' + + expect(lines[1][9]).toEqual value: 'throws', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.modifier.java'] + expect(lines[1][11]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.type.java'] + expect(lines[1][12]).toEqual value: ',', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'punctuation.throwables.separator'] + expect(lines[1][14]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.type.java'] + expect(lines[1][16]).toEqual value: '{', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'punctuation.section.method.begin.bracket.curly.java'] + + expect(lines[5][9]).toEqual value: 'throws', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.modifier.java'] + expect(lines[5][11]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.type.java'] + expect(lines[5][13]).toEqual value: '{', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'punctuation.section.method.begin.bracket.curly.java'] + it 'tokenizes comment inside method body', -> lines = grammar.tokenizeLines ''' class Test From b46fb2fa8aca6ad4a46d1ab9f2b43560cf0da562 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Sun, 27 May 2018 03:05:10 +1200 Subject: [PATCH 02/59] fix class fields with arrays as generic type --- grammars/java.cson | 2 +- spec/java-spec.coffee | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index cb9947a..db2367e 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1230,7 +1230,7 @@ (?>(\\w+\\.)*[A-Z]+\\w*) # e.g. `javax.ws.rs.Response`, or `String` ) ( - <[\\w<>,\\.?\\s]*> # e.g. `HashMap`, or `List` + <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List` )? ( (\\[\\])* # int[][] diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 0213101..7a12824 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1412,19 +1412,19 @@ describe 'Java grammar', -> expect(lines[13][5]).toEqual value: 'primitiveArray', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] expect(lines[14][1]).toEqual value: 'private', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.modifier.java'] - expect(lines[14][3]).toEqual value: 'Foo', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.java'] - expect(lines[14][4]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] - expect(lines[14][5]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.primitive.array.java'] - expect(lines[14][6]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] - expect(lines[14][7]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] - expect(lines[14][8]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] - - expect(lines[15][1]).toEqual value: 'Foo', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.java'] - expect(lines[15][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] - expect(lines[15][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.primitive.array.java'] - expect(lines[15][4]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] - expect(lines[15][5]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] - expect(lines[15][6]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] + expect(lines[14][3]).toEqual value: 'Foo', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[14][4]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[14][5]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.primitive.array.java'] + expect(lines[14][6]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[14][7]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[14][8]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + + expect(lines[15][1]).toEqual value: 'Foo', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[15][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[15][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.primitive.array.java'] + expect(lines[15][4]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[15][5]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[15][6]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] it 'tokenizes qualified storage types', -> lines = grammar.tokenizeLines ''' From 553360738bce15158ecb04da9241d00f25c996f8 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Thu, 31 May 2018 20:03:01 +0200 Subject: [PATCH 03/59] update scopes --- grammars/java.cson | 6 +++--- spec/java-spec.coffee | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 5076394..9d661f6 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -596,10 +596,10 @@ } { 'match': '\\|' - 'name': 'punctuation.catch.separator' + 'name': 'punctuation.catch.separator.java' } { - 'match': '([a-zA-Z$_][\\.a-zA-Z0-9$_]*)\\s*(\\w+)*' + 'match': '([a-zA-Z$_][\\.a-zA-Z0-9$_]*)\\s*(\\w+)?' 'captures': '1': 'name': 'storage.type.java' @@ -1228,7 +1228,7 @@ 'patterns': [ { 'match': ',' - 'name': 'punctuation.throwables.separator' + 'name': 'punctuation.separator.delimiter.java' } { 'match': '[a-zA-Z$_][\\.a-zA-Z0-9$_]*' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index faf0332..2dffdf7 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1622,7 +1622,7 @@ describe 'Java grammar', -> expect(lines[5][3]).toEqual value: 'catch', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'keyword.control.catch.java'] expect(lines[5][5]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.begin.bracket.round.java'] expect(lines[5][6]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] - expect(lines[5][8]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator'] + expect(lines[5][8]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator.java'] expect(lines[5][10]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] expect(lines[5][12]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] expect(lines[5][13]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] @@ -1642,7 +1642,7 @@ describe 'Java grammar', -> expect(lines[1][9]).toEqual value: 'throws', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.modifier.java'] expect(lines[1][11]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.type.java'] - expect(lines[1][12]).toEqual value: ',', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'punctuation.throwables.separator'] + expect(lines[1][12]).toEqual value: ',', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'punctuation.separator.delimiter.java'] expect(lines[1][14]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.throwables.java', 'storage.type.java'] expect(lines[1][16]).toEqual value: '{', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'punctuation.section.method.begin.bracket.curly.java'] From 9cefca220335cb252a7c2e9e8d94f7b175e04716 Mon Sep 17 00:00:00 2001 From: Snjezana Peco Date: Thu, 31 May 2018 16:43:44 +0200 Subject: [PATCH 04/59] Add Java 9/10 keywords Signed-off-by: Snjezana Peco --- grammars/java.cson | 36 ++++++++++++++++++++++++++++++++++++ spec/java-spec.coffee | 16 ++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index cb9947a..399c914 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -109,6 +109,9 @@ { 'include': '#code' } + { + 'include': '#module' + } ] 'repository': 'all-types': @@ -916,6 +919,39 @@ 'include': '#comments' } ] + 'module': + # a uniquely named, reusable group of related packages, as well as resources (such as images + # and XML files). + 'begin': '((open)\\s)?(module)\\s+(\\w+)' + 'end': '}' + 'beginCaptures': + '1': + 'name': 'storage.modifier.java' + '3': + 'name': 'storage.modifier.java' + '4': + 'name': 'entity.name.type.module.java' + 'endCaptures': + '0': + 'name': 'punctuation.section.module.end.bracket.curly.java' + 'name': 'meta.module.java' + 'patterns': [ + { + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.module.begin.bracket.curly.java' + 'end': '(?=})' + 'contentName': 'meta.module.body.java' + 'patterns': [ + # TODO: Write more rules for module grammar + { + 'match': '\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b' + 'name': 'keyword.module.java' + } + ] + } + ] 'numbers': # See http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.1 (integers) # and http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.2 (floats) diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 0213101..63534be 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -192,6 +192,22 @@ describe 'Java grammar', -> expect(tokens[9]).toEqual value: 'goto', scopes: ['source.java', 'keyword.reserved.java'] + it 'tokenizes module keywords', -> + lines = grammar.tokenizeLines ''' + module Provider { + requires ServiceInterface; + provides javax0.serviceinterface.ServiceInterface with javax0.serviceprovider.Provider; + } + ''' + + expect(lines[0][0]).toEqual value: 'module', scopes: ['source.java', 'meta.module.java', 'storage.modifier.java'] + expect(lines[0][2]).toEqual value: 'Provider', scopes: ['source.java', 'meta.module.java', 'entity.name.type.module.java'] + expect(lines[0][4]).toEqual value: '{', scopes: ['source.java', 'meta.module.java', 'punctuation.section.module.begin.bracket.curly.java'] + expect(lines[1][1]).toEqual value: 'requires', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'keyword.module.java'] + expect(lines[2][1]).toEqual value: 'provides', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'keyword.module.java'] + expect(lines[2][3]).toEqual value: 'with', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'keyword.module.java'] + expect(lines[3][0]).toEqual value: '}', scopes: ['source.java', 'meta.module.java', 'punctuation.section.module.end.bracket.curly.java'] + it 'tokenizes classes', -> lines = grammar.tokenizeLines ''' class Thing { From db4e97d9ed5368ee50b8cf4648d7bbcb27603b12 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 11 Jun 2018 09:46:14 -0400 Subject: [PATCH 05/59] Prepare 0.30.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ee7b81..8da3e5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.29.0", + "version": "0.30.0", "description": "Java language support in Atom", "engines": { "atom": "*", From 2f20bc5a5b07686ec0139e2969431210d81b6991 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 14 Jul 2018 08:29:34 +0200 Subject: [PATCH 06/59] Update 'variables' and 'member-variables' patterns to handle semicolon behaviour (#146) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR updates `variables` and `member-variables` patterns and changes the behaviour of the `meta.definition.variable.java` scope. This is done to fix #88 (try-with-resources issue) to handle `;`. I propose to define `meta.definition.variable.java` to be just declaration part without the following expression to initialise the variable, e.g. `[int a] = 5;` or `[int a];`, where `[...]` is `meta.definition.variable.java`. This results in the right hand side not having the scope, but I could potentially define and assign another one, like `meta.initialization.expression.java` or something similar. After patch (also passes test case mentioned in the issue): ```java class A { void func() { try (Buffer a = new Buffer()) { str = "str"; } try ( Buffer a = new Buffer(); Buffer b = new Buffer(); Buffer c = new Buffer() ) { str = "str"; } } } ``` after-patch I updated the existing tests to remove `meta.definition.variable.java` wherever it is not needed, and added more tests to check the correct behaviour. ### Alternate Designs Alternative design was considered where we apply a hack to `end` by listing `)` as another terminating character. This is a very small fix (4-8 characters change), but could potentially result in other issues, such as triggering close on closing paren (see https://github.com/atom/language-java/issues/88#issuecomment-333003571). Another alternative design was proposed in #124, but it is more intrusive and results in duplicating variables pattern code and increases maintenance cost, since both patterns must be updated in case of any changes. ### Benefits Fixes issue when not using `;` (which is allowed by specification) would break the highlighting. Potentially helps to fix other problems related to variable highlighting. ### Possible Drawbacks We remove `meta.definition.variable.java` scope from the expression that follows `=`. The left hand side is okay. Arguably, the right hand side should not be scoped as variable definition. ### Applicable Issues Fixes #88 Relates to PR #124 --- grammars/java.cson | 16 +--- spec/java-spec.coffee | 214 ++++++++++++++++++++++++------------------ 2 files changed, 124 insertions(+), 106 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 0c6a695..3d696c3 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1291,7 +1291,7 @@ \\s*(=|;) ) ''' - 'end': '(?=;)' + 'end': '(?=\\=|;)' 'name': 'meta.definition.variable.java' 'patterns': [ { @@ -1303,25 +1303,13 @@ { 'include': '#all-types' } - { - 'begin': '=' - 'beginCaptures': - '0': - 'name': 'keyword.operator.assignment.java' - 'end': '(?=;)' - 'patterns': [ - { - 'include': '#code' - } - ] - } { 'include': '#code' } ] 'member-variables': 'begin': '(?=private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final)' - 'end': '(?=;)' + 'end': '(?=\\=|;)' 'patterns': [ { 'include': '#storage-modifiers' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index de118c2..1941ff9 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -809,11 +809,13 @@ describe 'Java grammar', -> expect(lines[5][1]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[5][3]).toEqual value: 'assigned', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[5][8]).toEqual value: "Rand al'Thor", scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'string.quoted.double.java'] + expect(lines[5][5]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'keyword.operator.assignment.java'] + expect(lines[5][8]).toEqual value: "Rand al'Thor", scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'string.quoted.double.java'] expect(lines[6][1]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'storage.type.primitive.java'] expect(lines[6][3]).toEqual value: 'primitive', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[6][7]).toEqual value: '5', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'constant.numeric.decimal.java'] + expect(lines[6][5]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'keyword.operator.assignment.java'] + expect(lines[6][7]).toEqual value: '5', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'constant.numeric.decimal.java'] it 'tokenizes capitalized variables', -> lines = grammar.tokenizeLines ''' @@ -971,9 +973,9 @@ describe 'Java grammar', -> expect(lines[2][6]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] expect(lines[2][7]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] expect(lines[2][9]).toEqual value: 'map', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[2][15]).toEqual value: 'HashMap', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] - expect(lines[2][16]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] - expect(lines[2][17]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[2][15]).toEqual value: 'HashMap', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.java'] + expect(lines[2][16]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] + expect(lines[2][17]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] expect(lines[3][1]).toEqual value: 'CodeMap', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[3][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] expect(lines[3][3]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] @@ -1044,7 +1046,7 @@ describe 'Java grammar', -> expect(lines[2][6]).toEqual value: '<', scopes: ['source.java', 'keyword.operator.comparison.java'] expect(lines[5][1]).toEqual value: 'String', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[5][3]).toEqual value: 'S', scopes: ['source.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[5][5]).toEqual value: '=', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.operator.assignment.java'] + expect(lines[5][5]).toEqual value: '=', scopes: ['source.java', 'keyword.operator.assignment.java'] # check that string does not extend to/include ';' expect(lines[5][10]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] @@ -1171,8 +1173,8 @@ describe 'Java grammar', -> expect(lines[2][6]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[2][7]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[2][9]).toEqual value: 'two', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[2][11]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'keyword.operator.assignment.java'] - expect(lines[2][13]).toEqual value: 'null', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'constant.language.java'] + expect(lines[2][11]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'keyword.operator.assignment.java'] + expect(lines[2][13]).toEqual value: 'null', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'constant.language.java'] expect(lines[2][14]).toEqual value: ';', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.terminator.java'] it 'tokenizes lambda expressions', -> @@ -1188,102 +1190,102 @@ describe 'Java grammar', -> it 'tokenizes `new` statements', -> {tokens} = grammar.tokenizeLine 'int[] list = new int[10];' - expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[9]).toEqual value: ' ', scopes: ['source.java', 'meta.definition.variable.java'] - expect(tokens[10]).toEqual value: 'int', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.primitive.array.java'] - expect(tokens[11]).toEqual value: '[', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] - expect(tokens[12]).toEqual value: '10', scopes: ['source.java', 'meta.definition.variable.java', 'constant.numeric.decimal.java'] - expect(tokens[13]).toEqual value: ']', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[9]).toEqual value: ' ', scopes: ['source.java'] + expect(tokens[10]).toEqual value: 'int', scopes: ['source.java', 'storage.type.primitive.array.java'] + expect(tokens[11]).toEqual value: '[', scopes: ['source.java', 'punctuation.bracket.square.java'] + expect(tokens[12]).toEqual value: '10', scopes: ['source.java', 'constant.numeric.decimal.java'] + expect(tokens[13]).toEqual value: ']', scopes: ['source.java', 'punctuation.bracket.square.java'] expect(tokens[14]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'boolean[] list = new boolean[variable];' - expect(tokens[12]).toEqual value: 'variable', scopes: ['source.java', 'meta.definition.variable.java'] + expect(tokens[12]).toEqual value: 'variable', scopes: ['source.java'] {tokens} = grammar.tokenizeLine 'String[] list = new String[10];' - expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[10]).toEqual value: 'String', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.object.array.java'] - expect(tokens[11]).toEqual value: '[', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] - expect(tokens[12]).toEqual value: '10', scopes: ['source.java', 'meta.definition.variable.java', 'constant.numeric.decimal.java'] - expect(tokens[13]).toEqual value: ']', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[10]).toEqual value: 'String', scopes: ['source.java', 'storage.type.object.array.java'] + expect(tokens[11]).toEqual value: '[', scopes: ['source.java', 'punctuation.bracket.square.java'] + expect(tokens[12]).toEqual value: '10', scopes: ['source.java', 'constant.numeric.decimal.java'] + expect(tokens[13]).toEqual value: ']', scopes: ['source.java', 'punctuation.bracket.square.java'] expect(tokens[14]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'String[] list = new String[]{"hi", "abc", "etc"};' - expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[10]).toEqual value: 'String', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.object.array.java'] - expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.curly.java'] - expect(tokens[14]).toEqual value: '"', scopes: ['source.java', 'meta.definition.variable.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] - expect(tokens[15]).toEqual value: 'hi', scopes: ['source.java', 'meta.definition.variable.java', 'string.quoted.double.java'] - expect(tokens[16]).toEqual value: '"', scopes: ['source.java', 'meta.definition.variable.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] - expect(tokens[17]).toEqual value: ',', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.separator.delimiter.java'] - expect(tokens[18]).toEqual value: ' ', scopes: ['source.java', 'meta.definition.variable.java'] - expect(tokens[27]).toEqual value: '}', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.curly.java'] + expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[10]).toEqual value: 'String', scopes: ['source.java', 'storage.type.object.array.java'] + expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'punctuation.bracket.curly.java'] + expect(tokens[14]).toEqual value: '"', scopes: ['source.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] + expect(tokens[15]).toEqual value: 'hi', scopes: ['source.java', 'string.quoted.double.java'] + expect(tokens[16]).toEqual value: '"', scopes: ['source.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] + expect(tokens[17]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter.java'] + expect(tokens[18]).toEqual value: ' ', scopes: ['source.java'] + expect(tokens[27]).toEqual value: '}', scopes: ['source.java', 'punctuation.bracket.curly.java'] expect(tokens[28]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'A[] arr = new A[]{new A(), new A()};' - expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[10]).toEqual value: 'A', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.object.array.java'] - expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.curly.java'] - expect(tokens[14]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[16]).toEqual value: 'A', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[21]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[23]).toEqual value: 'A', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[24]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[25]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[26]).toEqual value: '}', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.bracket.curly.java'] + expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[10]).toEqual value: 'A', scopes: ['source.java', 'storage.type.object.array.java'] + expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'punctuation.bracket.curly.java'] + expect(tokens[14]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[16]).toEqual value: 'A', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[21]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[23]).toEqual value: 'A', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[24]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[25]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[26]).toEqual value: '}', scopes: ['source.java', 'punctuation.bracket.curly.java'] expect(tokens[27]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'A[] arr = {new A(), new A()};' - expect(tokens[8]).toEqual value: '{', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.section.block.begin.bracket.curly.java'] - expect(tokens[9]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[11]).toEqual value: 'A', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[12]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[13]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[16]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[18]).toEqual value: 'A', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[19]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[20]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[21]).toEqual value: '}', scopes: ['source.java', 'meta.definition.variable.java', 'punctuation.section.block.end.bracket.curly.java'] + expect(tokens[8]).toEqual value: '{', scopes: ['source.java', 'punctuation.section.block.begin.bracket.curly.java'] + expect(tokens[9]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[11]).toEqual value: 'A', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[12]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[13]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[16]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[18]).toEqual value: 'A', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[19]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[20]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[21]).toEqual value: '}', scopes: ['source.java', 'punctuation.section.block.end.bracket.curly.java'] expect(tokens[22]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'String a = (valid ? new Date().toString() + " : " : "");' - expect(tokens[16]).toEqual value: 'toString', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[20]).toEqual value: '+', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.operator.arithmetic.java'] - expect(tokens[23]).toEqual value: ' : ', scopes: ['source.java', 'meta.definition.variable.java', 'string.quoted.double.java'] - expect(tokens[26]).toEqual value: ':', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.ternary.java'] - expect(tokens[28]).toEqual value: '"', scopes: ['source.java', 'meta.definition.variable.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] - expect(tokens[29]).toEqual value: '"', scopes: ['source.java', 'meta.definition.variable.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] + expect(tokens[16]).toEqual value: 'toString', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[20]).toEqual value: '+', scopes: ['source.java', 'keyword.operator.arithmetic.java'] + expect(tokens[23]).toEqual value: ' : ', scopes: ['source.java', 'string.quoted.double.java'] + expect(tokens[26]).toEqual value: ':', scopes: ['source.java', 'keyword.control.ternary.java'] + expect(tokens[28]).toEqual value: '"', scopes: ['source.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] + expect(tokens[29]).toEqual value: '"', scopes: ['source.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] {tokens} = grammar.tokenizeLine 'String[] list = new String[variable];' - expect(tokens[12]).toEqual value: 'variable', scopes: ['source.java', 'meta.definition.variable.java'] + expect(tokens[12]).toEqual value: 'variable', scopes: ['source.java'] {tokens} = grammar.tokenizeLine 'Point point = new Point(1, 4);' - expect(tokens[6]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[8]).toEqual value: 'Point', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[9]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[14]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[6]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[8]).toEqual value: 'Point', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[9]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[14]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] expect(tokens[15]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'Point point = true ? new Point(1, 4) : new Point(0, 0);' - expect(tokens[8]).toEqual value: '?', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.ternary.java'] - expect(tokens[10]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(tokens[12]).toEqual value: 'Point', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[13]).toEqual value: '(', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[20]).toEqual value: ':', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.ternary.java'] - expect(tokens[22]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] + expect(tokens[8]).toEqual value: '?', scopes: ['source.java', 'keyword.control.ternary.java'] + expect(tokens[10]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[12]).toEqual value: 'Point', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[13]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[20]).toEqual value: ':', scopes: ['source.java', 'keyword.control.ternary.java'] + expect(tokens[22]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] expect(tokens[31]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'map.put(key, new Value(value), "extra");' @@ -1319,12 +1321,12 @@ describe 'Java grammar', -> }; ''' - expect(lines[0][6]).toEqual value: 'new', scopes: ['source.java', 'meta.definition.variable.java', 'keyword.control.new.java'] - expect(lines[0][8]).toEqual value: 'Point', scopes: ['source.java', 'meta.definition.variable.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(lines[1][0]).toEqual value: '{', scopes: ['source.java', 'meta.definition.variable.java', 'meta.inner-class.java', 'punctuation.section.inner-class.begin.bracket.curly.java'] - expect(lines[2][1]).toEqual value: 'public', scopes: ['source.java', 'meta.definition.variable.java', 'meta.inner-class.java', 'meta.method.java', 'storage.modifier.java'] - expect(lines[4][1]).toEqual value: 'int', scopes: ['source.java', 'meta.definition.variable.java', 'meta.inner-class.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'storage.type.primitive.java'] - expect(lines[6][0]).toEqual value: '}', scopes: ['source.java', 'meta.definition.variable.java', 'meta.inner-class.java', 'punctuation.section.inner-class.end.bracket.curly.java'] + expect(lines[0][6]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(lines[0][8]).toEqual value: 'Point', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(lines[1][0]).toEqual value: '{', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.begin.bracket.curly.java'] + expect(lines[2][1]).toEqual value: 'public', scopes: ['source.java', 'meta.inner-class.java', 'meta.method.java', 'storage.modifier.java'] + expect(lines[4][1]).toEqual value: 'int', scopes: ['source.java', 'meta.inner-class.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'storage.type.primitive.java'] + expect(lines[6][0]).toEqual value: '}', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.end.bracket.curly.java'] expect(lines[6][1]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] it 'tokenizes the `instanceof` operator', -> @@ -1367,9 +1369,9 @@ describe 'Java grammar', -> expect(lines[4][5]).toEqual value: 'variable', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] expect(lines[4][6]).toEqual value: ' ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java'] - expect(lines[4][7]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'keyword.operator.assignment.java'] - expect(lines[4][8]).toEqual value: ' ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java'] - expect(lines[4][9]).toEqual value: '3', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'constant.numeric.decimal.java'] + expect(lines[4][7]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'keyword.operator.assignment.java'] + expect(lines[4][8]).toEqual value: ' ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] + expect(lines[4][9]).toEqual value: '3', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'constant.numeric.decimal.java'] expect(lines[4][10]).toEqual value: ';', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.terminator.java'] expect(lines[5][5]).toEqual value: 'variable1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] @@ -1381,8 +1383,8 @@ describe 'Java grammar', -> expect(lines[6][5]).toEqual value: 'variable1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] expect(lines[6][8]).toEqual value: 'variable2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[6][10]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'keyword.operator.assignment.java'] - expect(lines[6][11]).toEqual value: ' variable', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java'] + expect(lines[6][10]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'keyword.operator.assignment.java'] + expect(lines[6][11]).toEqual value: ' variable', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] expect(lines[6][12]).toEqual value: ';', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.terminator.java'] expect(lines[7][5]).toEqual value: 'variable', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] @@ -1398,13 +1400,14 @@ describe 'Java grammar', -> expect(lines[9][6]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[9][7]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[9][9]).toEqual value: 'somevar', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] - expect(lines[9][15]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.primitive.array.java'] - expect(lines[9][16]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] - expect(lines[9][17]).toEqual value: '10', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'constant.numeric.decimal.java'] - expect(lines[9][18]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] - expect(lines[9][19]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] - expect(lines[9][20]).toEqual value: '12', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'constant.numeric.decimal.java'] - expect(lines[9][21]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[9][11]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'keyword.operator.assignment.java'] + expect(lines[9][15]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.primitive.array.java'] + expect(lines[9][16]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] + expect(lines[9][17]).toEqual value: '10', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'constant.numeric.decimal.java'] + expect(lines[9][18]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] + expect(lines[9][19]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] + expect(lines[9][20]).toEqual value: '12', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'constant.numeric.decimal.java'] + expect(lines[9][21]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] expect(lines[10][2]).toEqual value: ' int 1invalid', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] @@ -1605,6 +1608,7 @@ describe 'Java grammar', -> private void fn() { try ( BufferedReader in = new BufferedReader(); + BufferedReader br = new BufferedReader(new FileReader(path)) ) { // stuff } @@ -1617,9 +1621,35 @@ describe 'Java grammar', -> expect(lines[2][2]).toEqual value: ' ', scopes: scopes expect(lines[2][3]).toEqual value: '(', scopes: scopes.concat ['meta.try.resources.java', 'punctuation.section.try.resources.begin.bracket.round.java'] expect(lines[3][1]).toEqual value: 'BufferedReader', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'storage.type.java'] - expect(lines[4][1]).toEqual value: ')', scopes: scopes.concat ['meta.try.resources.java', 'punctuation.section.try.resources.end.bracket.round.java'] - expect(lines[4][2]).toEqual value: ' ', scopes: scopes - expect(lines[4][3]).toEqual value: '{', scopes: scopes.concat ['punctuation.section.try.begin.bracket.curly.java'] + expect(lines[4][1]).toEqual value: 'BufferedReader', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[5][1]).toEqual value: ')', scopes: scopes.concat ['meta.try.resources.java', 'punctuation.section.try.resources.end.bracket.round.java'] + expect(lines[5][2]).toEqual value: ' ', scopes: scopes + expect(lines[5][3]).toEqual value: '{', scopes: scopes.concat ['punctuation.section.try.begin.bracket.curly.java'] + + it 'tokenizes generics with dots in try-catch with resources', -> + lines = grammar.tokenizeLines ''' + class A { + void func() { + try (List a = get()) { + // do something + } + } + } + ''' + + scopes = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.try.java'] + expect(lines[2][1]).toEqual value: 'try', scopes: scopes.concat ['keyword.control.try.java'] + expect(lines[2][3]).toEqual value: '(', scopes: scopes.concat ['meta.try.resources.java', 'punctuation.section.try.resources.begin.bracket.round.java'] + expect(lines[2][4]).toEqual value: 'List', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][5]).toEqual value: '<', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[2][6]).toEqual value: 'java', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][7]).toEqual value: '.', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[2][8]).toEqual value: 'lang', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][9]).toEqual value: '.', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[2][10]).toEqual value: 'String', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][11]).toEqual value: '>', scopes: scopes.concat ['meta.try.resources.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[2][20]).toEqual value: ')', scopes: scopes.concat ['meta.try.resources.java', 'punctuation.section.try.resources.end.bracket.round.java'] + expect(lines[2][22]).toEqual value: '{', scopes: scopes.concat ['punctuation.section.try.begin.bracket.curly.java'] it 'tokenizes list of exceptions in catch block', -> lines = grammar.tokenizeLines ''' From e64afdb9a3d253bdcb39cc5f7a1496c420e5ca5b Mon Sep 17 00:00:00 2001 From: Brennen Berkley Date: Tue, 24 Jul 2018 00:15:55 -0600 Subject: [PATCH 07/59] Fix highlighting for fully qualified types (#147) ### Description of the Change Fixes issue where types containing periods were being treated as objects and properties, so I included the ```variables``` section before the ```object``` and ```property``` sections to properly recognize fully qualified variables. I also changed the regex for recognizing types to allow namespaces starting with a lowercase letter. I also added a few specs. #### Before: before #### After: after ### Alternate Designs None were considered. ### Benefits Syntax highlighting is now more accurate, all tests pass ### Possible Drawbacks None ### Applicable Issues #135 --- grammars/java.cson | 48 +++++++++++++++++++++++++++++---------- spec/java-spec.coffee | 53 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 13 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 3d696c3..5d5d7d4 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -411,13 +411,13 @@ 'include': '#function-call' } { - 'include': '#objects' + 'include': '#variables' } { - 'include': '#properties' + 'include': '#objects' } { - 'include': '#variables' + 'include': '#properties' } { 'include': '#strings' @@ -1023,10 +1023,19 @@ 'include': '#generics' } { - 'begin': '\\b(?:[A-Z]\\w*\\s*(\\.)\\s*)*([A-Z]\\w*)\\s*(?=\\[)' + 'begin': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*)([A-Z]\\w*)\\s*(?=\\[)' 'beginCaptures': '1': - 'name': 'punctuation.separator.period.java' + 'patterns': [ + { + 'match': '[A-Za-z]\\w*' + 'name': 'storage.type.java' + } + { + 'match': '\\.' + 'name': 'punctuation.separator.period.java' + } + ] '2': 'name': 'storage.type.object.array.java' 'end': '(?!\\s*\\[)' @@ -1041,12 +1050,19 @@ } { # Match possible generics first, eg Wow instead of just Wow - 'begin': '\\b((?:[A-Z]\\w*\\s*(\\.)\\s*)*[A-Z]\\w*)\\s*(?=<)' + 'begin': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\s*(?=<)' 'beginCaptures': '1': - 'name': 'storage.type.java' - '2': - 'name': 'punctuation.separator.period.java' + 'patterns': [ + { + 'match': '[A-Za-z]\\w*' + 'name': 'storage.type.java' + } + { + 'match': '\\.' + 'name': 'punctuation.separator.period.java' + } + ] # Stop after a successful generic match or if we are not at a terminator 'end': '(?<=>)|(?!;)' 'patterns': [ @@ -1059,11 +1075,19 @@ # If the above fails *then* just look for Wow # (must be followed by a variable name, we use '\n' to cover multi-line definitions, # or varargs for function definitions) - 'match': '\\b(?:[A-Z]\\w*\\s*(\\.)\\s*)*[A-Z]\\w*\\b((?=\\s*[A-Za-z$_\\n])|(?=\\s*\\.\\.\\.))' - 'name': 'storage.type.java' + 'match': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\b((?=\\s*[A-Za-z$_\\n])|(?=\\s*\\.\\.\\.))' 'captures': '1': - 'name': 'punctuation.separator.period.java' + 'patterns': [ + { + 'match': '[A-Za-z]\\w*' + 'name': 'storage.type.java' + } + { + 'match': '\\.' + 'name': 'punctuation.separator.period.java' + } + ] } ] 'object-types-inherited': diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 1941ff9..8d6a005 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1449,13 +1449,64 @@ describe 'Java grammar', -> lines = grammar.tokenizeLines ''' class Test { private Test.Double something; + java.util.Set> varA = null; + java.lang.String a = null; + java.util.List b = new java.util.ArrayList(); + java.lang.String[] arr; } ''' expect(lines[1][3]).toEqual value: 'Test', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] - expect(lines[1][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java', 'punctuation.separator.period.java'] + expect(lines[1][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] expect(lines[1][5]).toEqual value: 'Double', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[1][7]).toEqual value: 'something', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[2][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[2][3]).toEqual value: 'util', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[2][5]).toEqual value: 'Set', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][6]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[2][7]).toEqual value: 'java', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][8]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[2][9]).toEqual value: 'util', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][10]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[2][11]).toEqual value: 'List', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][12]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[2][13]).toEqual value: 'K', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[2][14]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[2][15]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + + expect(lines[3][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[3][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[3][3]).toEqual value: 'lang', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[3][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[3][5]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + + expect(lines[4][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[4][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[4][3]).toEqual value: 'util', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[4][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[4][5]).toEqual value: 'List', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[4][6]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[4][7]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[4][8]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[4][16]).toEqual value: 'java', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.java'] + expect(lines[4][17]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.separator.period.java'] + expect(lines[4][18]).toEqual value: 'util', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.java'] + expect(lines[4][19]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.separator.period.java'] + expect(lines[4][20]).toEqual value: 'ArrayList', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.java'] + expect(lines[4][21]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] + expect(lines[4][22]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.generic.java'] + expect(lines[4][23]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.angle.java'] + + expect(lines[5][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[5][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[5][3]).toEqual value: 'lang', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[5][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] + expect(lines[5][5]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.object.array.java'] + expect(lines[5][6]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[5][7]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + it 'tokenizes try-catch-finally blocks', -> lines = grammar.tokenizeLines ''' class Test { From 93322be114ac3734725a68f6beeb50215834b02b Mon Sep 17 00:00:00 2001 From: Brennen Berkley Date: Thu, 26 Jul 2018 01:18:45 -0600 Subject: [PATCH 08/59] Simplify some syntax that was more complex than necessary (#149) The end tag for the block was (?<=>)|(?!;), which could be simplified to (?!;), which always matches the next character after the begin block. This makes the size of the block 0, so nothing is actually happening inside the block, just in the beginCaptures, so I just converted the beginCaptures to their own matching group. --- grammars/java.cson | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 5d5d7d4..86b509c 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1049,9 +1049,9 @@ ] } { - # Match possible generics first, eg Wow instead of just Wow - 'begin': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\s*(?=<)' - 'beginCaptures': + # Match possible generics first, eg Foo.Bar in Foo.Bar + 'match': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\s*(?=<)' + 'captures': '1': 'patterns': [ { @@ -1063,13 +1063,6 @@ 'name': 'punctuation.separator.period.java' } ] - # Stop after a successful generic match or if we are not at a terminator - 'end': '(?<=>)|(?!;)' - 'patterns': [ - { - 'include': '#generics' - } - ] } { # If the above fails *then* just look for Wow From f213dfac7dc3726170046c8f0c174c9e9f13e4ce Mon Sep 17 00:00:00 2001 From: Brennen Berkley Date: Thu, 26 Jul 2018 01:19:25 -0600 Subject: [PATCH 09/59] Alphabetize the repository section (#150) It was mostly in order already, but it looks like a few sections were added in the wrong places --- grammars/java.cson | 428 ++++++++++++++++++++++----------------------- 1 file changed, 214 insertions(+), 214 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 86b509c..e7f1a4c 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -172,6 +172,20 @@ 'name': 'punctuation.definition.annotation.java' } ] + 'anonymous-block-and-instance-initializer': + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.block.begin.bracket.curly.java' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.section.block.end.bracket.curly.java' + 'patterns': [ + { + 'include': '#code' + } + ] 'anonymous-classes-and-new': 'begin': '\\bnew\\b' 'beginCaptures': @@ -336,30 +350,6 @@ 'include': '#code' } ] - 'anonymous-block-and-instance-initializer': - 'begin': '{' - 'beginCaptures': - '0': - 'name': 'punctuation.section.block.begin.bracket.curly.java' - 'end': '}' - 'endCaptures': - '0': - 'name': 'punctuation.section.block.end.bracket.curly.java' - 'patterns': [ - { - 'include': '#code' - } - ] - 'static-initializer': - 'patterns': [ - { - 'include': '#anonymous-block-and-instance-initializer' - } - { - 'match': 'static' - 'name': 'storage.modifier.java' - } - ] 'code': 'patterns': [ { @@ -526,147 +516,69 @@ } ] ] - 'try-catch-finally': + 'constants-and-special-vars': 'patterns': [ - # try block { - 'begin': '\\btry\\b' - 'beginCaptures': - '0': - 'name': 'keyword.control.try.java' - 'end': '}' - 'endCaptures': - '0': - 'name': 'punctuation.section.try.end.bracket.curly.java' - 'name': 'meta.try.java' - 'patterns': [ - { - 'begin': '\\(' - 'beginCaptures': - '0': - 'name': 'punctuation.section.try.resources.begin.bracket.round.java' - 'end': '\\)' - 'endCaptures': - '0': - 'name': 'punctuation.section.try.resources.end.bracket.round.java' - 'name': 'meta.try.resources.java' - 'patterns': [ - { - 'include': '#code' - } - ] - } - { - 'begin': '{' - 'beginCaptures': - '0': - 'name': 'punctuation.section.try.begin.bracket.curly.java' - 'end': '(?=})' - 'contentName': 'meta.try.body.java' - 'patterns': [ - { - 'include': '#code' - } - ] - } - ] + 'match': '\\b(true|false|null)\\b' + 'name': 'constant.language.java' } - # catch block (with "parameters") { - 'begin': '\\b(catch)\\b\\s*(?=\\(\\s*[^\\s]+\\s*[^)]+\\))' + 'match': '\\bthis\\b' + 'name': 'variable.language.this.java' + } + { + 'match': '\\bsuper\\b' + 'name': 'variable.language.java' + } + ] + 'enums': + 'begin': '^\\s*(enum)\\s+(\\w+)' + 'beginCaptures': + '1': + 'name': 'storage.modifier.java' + '2': + 'name': 'entity.name.type.enum.java' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.section.enum.end.bracket.curly.java' + 'name': 'meta.enum.java' + 'patterns': [ + { + 'begin': '{' 'beginCaptures': - '1': - 'name': 'keyword.control.catch.java' - 'end': '}' - 'endCaptures': '0': - 'name': 'punctuation.section.catch.end.bracket.curly.java' - 'name': 'meta.catch.java' + 'name': 'punctuation.section.enum.begin.bracket.curly.java' + 'end': '(?=})' 'patterns': [ { - 'begin': '\\(' - 'beginCaptures': - '0': - 'name': 'punctuation.definition.parameters.begin.bracket.round.java' - 'end': '\\)' - 'endCaptures': - '0': - 'name': 'punctuation.definition.parameters.end.bracket.round.java' - 'contentName': 'meta.catch.parameters.java' - 'patterns': [ - { - 'include': '#comments' - } - { - 'match': '\\|' - 'name': 'punctuation.catch.separator.java' - } - { - 'match': '([a-zA-Z$_][\\.a-zA-Z0-9$_]*)\\s*(\\w+)?' - 'captures': - '1': - 'name': 'storage.type.java' - '2': - 'name': 'variable.parameter.java' - } - ] + 'match': '\\w+' + 'name': 'constant.other.enum.java' } { - 'begin': '{' - 'beginCaptures': - '0': - 'name': 'punctuation.section.catch.begin.bracket.curly.java' - 'end': '(?=})' - 'contentName': 'meta.catch.body.java' - 'patterns': [ - { - 'include': '#code' - } - ] + 'include': '#class-body' } ] } - # finally block { - 'begin': '\\bfinally\\b' - 'beginCaptures': - '0': - 'name': 'keyword.control.finally.java' - 'end': '}' - 'endCaptures': - '0': - 'name': 'punctuation.section.finally.end.bracket.curly.java' - 'name': 'meta.finally.java' - 'patterns': [ - { - 'begin': '{' - 'beginCaptures': - '0': - 'name': 'punctuation.section.finally.begin.bracket.curly.java' - 'end': '(?=})' - 'contentName': 'meta.finally.body.java' - 'patterns': [ - { - 'include': '#code' - } - ] - } - ] + 'include': '#comments' } ] - 'constants-and-special-vars': + 'function-call': + 'begin': '([A-Za-z_$][\\w$]*)\\s*(\\()' + 'beginCaptures': + '1': + 'name': 'entity.name.function.java' + '2': + 'name': 'punctuation.definition.parameters.begin.bracket.round.java' + 'end': '\\)' + 'endCaptures': + '0': + 'name': 'punctuation.definition.parameters.end.bracket.round.java' + 'name': 'meta.function-call.java' 'patterns': [ { - 'match': '\\b(true|false|null)\\b' - 'name': 'constant.language.java' - } - { - 'match': '\\bthis\\b' - 'name': 'variable.language.this.java' - } - { - 'match': '\\bsuper\\b' - 'name': 'variable.language.java' + 'include': '#code' } ] 'generics': @@ -722,56 +634,6 @@ 'include': '#comments' } ] - 'enums': - 'begin': '^\\s*(enum)\\s+(\\w+)' - 'beginCaptures': - '1': - 'name': 'storage.modifier.java' - '2': - 'name': 'entity.name.type.enum.java' - 'end': '}' - 'endCaptures': - '0': - 'name': 'punctuation.section.enum.end.bracket.curly.java' - 'name': 'meta.enum.java' - 'patterns': [ - { - 'begin': '{' - 'beginCaptures': - '0': - 'name': 'punctuation.section.enum.begin.bracket.curly.java' - 'end': '(?=})' - 'patterns': [ - { - 'match': '\\w+' - 'name': 'constant.other.enum.java' - } - { - 'include': '#class-body' - } - ] - } - { - 'include': '#comments' - } - ] - 'function-call': - 'begin': '([A-Za-z_$][\\w$]*)\\s*(\\()' - 'beginCaptures': - '1': - 'name': 'entity.name.function.java' - '2': - 'name': 'punctuation.definition.parameters.begin.bracket.round.java' - 'end': '\\)' - 'endCaptures': - '0': - 'name': 'punctuation.definition.parameters.end.bracket.round.java' - 'name': 'meta.function-call.java' - 'patterns': [ - { - 'include': '#code' - } - ] 'keywords': 'patterns': [ { @@ -838,6 +700,23 @@ 'name': 'storage.type.function.arrow.java' } ] + 'member-variables': + 'begin': '(?=private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final)' + 'end': '(?=\\=|;)' + 'patterns': [ + { + 'include': '#storage-modifiers' + } + { + 'include': '#variables' + } + { + 'include': '#primitive-arrays' + } + { + 'include': '#object-types' + } + ] 'method-call': 'begin': '(\\.)\\s*([A-Za-z_$][\\w$]*)\\s*(\\()' 'beginCaptures': @@ -1231,6 +1110,16 @@ 'name': 'invalid.illegal.identifier.java' } ] + 'static-initializer': + 'patterns': [ + { + 'include': '#anonymous-block-and-instance-initializer' + } + { + 'match': 'static' + 'name': 'storage.modifier.java' + } + ] 'storage-modifiers': 'match': '\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient|volatile|default|strictfp)\\b' 'name': 'storage.modifier.java' @@ -1288,6 +1177,134 @@ 'name': 'storage.type.java' } ] + 'try-catch-finally': + 'patterns': [ + # try block + { + 'begin': '\\btry\\b' + 'beginCaptures': + '0': + 'name': 'keyword.control.try.java' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.section.try.end.bracket.curly.java' + 'name': 'meta.try.java' + 'patterns': [ + { + 'begin': '\\(' + 'beginCaptures': + '0': + 'name': 'punctuation.section.try.resources.begin.bracket.round.java' + 'end': '\\)' + 'endCaptures': + '0': + 'name': 'punctuation.section.try.resources.end.bracket.round.java' + 'name': 'meta.try.resources.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + { + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.try.begin.bracket.curly.java' + 'end': '(?=})' + 'contentName': 'meta.try.body.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + ] + } + # catch block (with "parameters") + { + 'begin': '\\b(catch)\\b\\s*(?=\\(\\s*[^\\s]+\\s*[^)]+\\))' + 'beginCaptures': + '1': + 'name': 'keyword.control.catch.java' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.section.catch.end.bracket.curly.java' + 'name': 'meta.catch.java' + 'patterns': [ + { + 'begin': '\\(' + 'beginCaptures': + '0': + 'name': 'punctuation.definition.parameters.begin.bracket.round.java' + 'end': '\\)' + 'endCaptures': + '0': + 'name': 'punctuation.definition.parameters.end.bracket.round.java' + 'contentName': 'meta.catch.parameters.java' + 'patterns': [ + { + 'include': '#comments' + } + { + 'match': '\\|' + 'name': 'punctuation.catch.separator.java' + } + { + 'match': '([a-zA-Z$_][\\.a-zA-Z0-9$_]*)\\s*(\\w+)?' + 'captures': + '1': + 'name': 'storage.type.java' + '2': + 'name': 'variable.parameter.java' + } + ] + } + { + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.catch.begin.bracket.curly.java' + 'end': '(?=})' + 'contentName': 'meta.catch.body.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + ] + } + # finally block + { + 'begin': '\\bfinally\\b' + 'beginCaptures': + '0': + 'name': 'keyword.control.finally.java' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.section.finally.end.bracket.curly.java' + 'name': 'meta.finally.java' + 'patterns': [ + { + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.finally.begin.bracket.curly.java' + 'end': '(?=})' + 'contentName': 'meta.finally.body.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + ] + } + ] 'variables': 'begin': '''(?x) (?= @@ -1324,20 +1341,3 @@ 'include': '#code' } ] - 'member-variables': - 'begin': '(?=private|protected|public|native|synchronized|abstract|threadsafe|transient|static|final)' - 'end': '(?=\\=|;)' - 'patterns': [ - { - 'include': '#storage-modifiers' - } - { - 'include': '#variables' - } - { - 'include': '#primitive-arrays' - } - { - 'include': '#object-types' - } - ] From 082c17572463e07ba124035b6dce277b01e40d54 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 22 Aug 2018 10:19:29 +0200 Subject: [PATCH 10/59] Variables rule causes loop (#152) Fixes #151 The "variables" rule looks for the occurrence of `int` without making that sure that this is a separate word, however, the subrule depends on that. As the variable rule consists only of lookahead, this causes a loop with the rule to be entered and exited again. VSCode prints a warning when that happens, Atom, silently ignored. With both grammars the rest of the line doesn't see to get any highlighting anymore. --- grammars/java.cson | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grammars/java.cson b/grammars/java.cson index e7f1a4c..1f25587 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1309,7 +1309,7 @@ 'begin': '''(?x) (?= ( - (void|boolean|byte|char|short|int|float|long|double) + \\b(void|boolean|byte|char|short|int|float|long|double)\\b | (?>(\\w+\\.)*[A-Z]+\\w*) # e.g. `javax.ws.rs.Response`, or `String` ) From bc29438039a204115e7fe0fc4fc21e0fbd5782de Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 23 Aug 2018 23:46:28 +0200 Subject: [PATCH 11/59] add test (#155) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change Adds unit test to verify the change. ### Alternate Designs Not applicable. ### Benefits Increased test coverage. ### Possible Drawbacks None ### Applicable Issues Closes #153 --- spec/java-spec.coffee | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 8d6a005..473ae1c 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -817,6 +817,21 @@ describe 'Java grammar', -> expect(lines[6][5]).toEqual value: '=', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'keyword.operator.assignment.java'] expect(lines[6][7]).toEqual value: '5', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'constant.numeric.decimal.java'] + it 'tokenizes variables defined with incorrect primitive types', -> + lines = grammar.tokenizeLines ''' + class A { + aint a = 1; int b = 2; + aboolean c = true; boolean d = false; + } + ''' + + expect(lines[1][0]).toEqual value: ' aint a ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] + expect(lines[1][6]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.primitive.java'] + expect(lines[1][8]).toEqual value: 'b', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[2][0]).toEqual value: ' aboolean c ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] + expect(lines[2][6]).toEqual value: 'boolean', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.primitive.java'] + expect(lines[2][8]).toEqual value: 'd', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + it 'tokenizes capitalized variables', -> lines = grammar.tokenizeLines ''' void func() From dbd01a1453d99b837734fcc0bf49add1dbe5162a Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 5 Sep 2018 21:42:23 +0200 Subject: [PATCH 12/59] fix javadoc comment start scope (#157) --- grammars/java.cson | 4 ++-- spec/java-spec.coffee | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 1f25587..e02a8e0 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -474,9 +474,9 @@ ] 'comments-javadoc': 'patterns': [ - 'begin': '^\\s*/\\*\\*(?!/)' + 'begin': '^\\s*(/\\*\\*)(?!/)' 'beginCaptures': - '0': + '1': 'name': 'punctuation.definition.comment.java' 'end': '\\*/' 'endCaptures': diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 473ae1c..6a3d94b 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1831,13 +1831,13 @@ describe 'Java grammar', -> } ''' - expect(lines[1][0]).toEqual value: ' /**', scopes: ['source.java', 'meta.enum.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] - expect(lines[1][1]).toEqual value: ' javadoc comment ', scopes: ['source.java', 'meta.enum.java', 'comment.block.javadoc.java'] - expect(lines[1][2]).toEqual value: '*/', scopes: ['source.java', 'meta.enum.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] + expect(lines[1][1]).toEqual value: '/**', scopes: ['source.java', 'meta.enum.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] + expect(lines[1][2]).toEqual value: ' javadoc comment ', scopes: ['source.java', 'meta.enum.java', 'comment.block.javadoc.java'] + expect(lines[1][3]).toEqual value: '*/', scopes: ['source.java', 'meta.enum.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] - expect(lines[5][0]).toEqual value: ' /**', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] - expect(lines[5][1]).toEqual value: ' javadoc comment ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] - expect(lines[5][2]).toEqual value: '*/', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] + expect(lines[5][1]).toEqual value: '/**', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] + expect(lines[5][2]).toEqual value: ' javadoc comment ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + expect(lines[5][3]).toEqual value: '*/', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'punctuation.definition.comment.java'] it 'tokenizes empty/single character comment', -> # this test checks the correct tokenizing of empty/single character comments From 295af4375e4a5da4a4352fa08a8bb3e17145ec47 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 6 Sep 2018 23:15:51 +0200 Subject: [PATCH 13/59] Fix inconsistent enum highlighting (#156) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR fixes enum scope and highlighting to make sure that we can handle different variations of enums, e.g. ```java enum Test { A, B, C } ``` ```java protected enum Test { A(123), B(234); void func() { ... } } ``` ```java class A { private enum Test { A, B, C } } ``` The proposed design extends the existing `enum` scope and adds handling of storage modifiers (`private`, `protected`, etc.) and fixes issues when enum constants were not highlighted correctly in nested enums. I also extended the existing tests and added new ones to cover added functionality. ### Alternate Designs None apart from the one mentioned in description above. ### Benefits Fixes scope and highlighting for various enums, that were not supported previously. ### Possible Drawbacks Not many, since it only affects enums. ### Applicable Issues Closes #154 --- grammars/java.cson | 52 +++++++++++++++---- spec/java-spec.coffee | 114 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 154 insertions(+), 12 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index e02a8e0..bf91a33 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -323,10 +323,10 @@ 'include': '#comments' } { - 'include': '#class' + 'include': '#enums' } { - 'include': '#enums' + 'include': '#class' } { 'include': '#generics' @@ -532,11 +532,17 @@ } ] 'enums': - 'begin': '^\\s*(enum)\\s+(\\w+)' + 'begin': '^\\s*([\\w\\s]*)(enum)\\s+(\\w+)' 'beginCaptures': '1': - 'name': 'storage.modifier.java' + 'patterns': [ + { + 'include': '#storage-modifiers' + } + ] '2': + 'name': 'storage.modifier.java' + '3': 'name': 'entity.name.type.enum.java' 'end': '}' 'endCaptures': @@ -552,17 +558,45 @@ 'end': '(?=})' 'patterns': [ { - 'match': '\\w+' - 'name': 'constant.other.enum.java' + 'begin': '(?<={)' + 'end': '(?=;|})' + 'patterns': [ + { + 'include': '#comments-javadoc' + } + { + 'include': '#comments' + } + # Represents enum's constant field with constructor, e.g. `Test(123)` + { + 'begin': '(\\w+)\\s*(\\()' + 'beginCaptures': + '1': + 'name': 'constant.other.enum.java' + '2': + 'name': 'punctuation.bracket.round.java' + 'end': '\\)' + 'endCaptures': + '0': + 'name': 'punctuation.bracket.round.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + # Represents enum's constant field, e.g. `Test` + { + 'match': '\\b\\w+\\b' + 'name': 'constant.other.enum.java' + } + ] } { 'include': '#class-body' } ] } - { - 'include': '#comments' - } ] 'function-call': 'begin': '([A-Za-z_$][\\w$]*)\\s*(\\()' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 6a3d94b..b41e670 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -225,12 +225,19 @@ describe 'Java grammar', -> A, // Comment about B - B + B, + + /** Javadoc comment about C */ + C } ''' comment = ['source.java', 'meta.enum.java', 'comment.block.java'] + commentLine = ['source.java', 'meta.enum.java', 'comment.line.double-slash.java'] + commentJavadoc = ['source.java', 'meta.enum.java', 'comment.block.javadoc.java'] commentDefinition = comment.concat('punctuation.definition.comment.java') + commentLineDefinition = commentLine.concat('punctuation.definition.comment.java') + commentJavadocDefinition = commentJavadoc.concat('punctuation.definition.comment.java') expect(lines[0][0]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] expect(lines[0][2]).toEqual value: 'Letters', scopes: ['source.java', 'meta.enum.java', 'entity.name.type.enum.java'] @@ -239,7 +246,108 @@ describe 'Java grammar', -> expect(lines[1][2]).toEqual value: ' Comment about A ', scopes: comment expect(lines[1][3]).toEqual value: '*/', scopes: commentDefinition expect(lines[2][1]).toEqual value: 'A', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] - expect(lines[6][0]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.section.enum.end.bracket.curly.java'] + expect(lines[4][1]).toEqual value: '//', scopes: commentLineDefinition + expect(lines[4][2]).toEqual value: ' Comment about B', scopes: commentLine + expect(lines[5][1]).toEqual value: 'B', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[7][1]).toEqual value: '/**', scopes: commentJavadocDefinition + expect(lines[7][2]).toEqual value: ' Javadoc comment about C ', scopes: commentJavadoc + expect(lines[8][1]).toEqual value: 'C', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[9][0]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.section.enum.end.bracket.curly.java'] + + it 'tokenizes enums with class body', -> + lines = grammar.tokenizeLines ''' + enum Colours { + RED ("red"), + GREEN (1000L), + BLUE (123); + + private String v; + + Colours(String v) { + this.v = v; + } + + Colours(long v) { + this.v = "" + v; + } + + Colours(int v) { + this.v = "" + v; + } + + public String func() { + return "RGB"; + } + } + ''' + + expect(lines[0][0]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[0][2]).toEqual value: 'Colours', scopes: ['source.java', 'meta.enum.java', 'entity.name.type.enum.java'] + expect(lines[0][4]).toEqual value: '{', scopes: ['source.java', 'meta.enum.java', 'punctuation.section.enum.begin.bracket.curly.java'] + + expect(lines[1][1]).toEqual value: 'RED', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[1][3]).toEqual value: '(', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[1][5]).toEqual value: 'red', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java'] + expect(lines[1][7]).toEqual value: ')', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + + expect(lines[2][1]).toEqual value: 'GREEN', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[2][3]).toEqual value: '(', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[2][4]).toEqual value: '1000L', scopes: ['source.java', 'meta.enum.java', 'constant.numeric.decimal.java'] + expect(lines[2][5]).toEqual value: ')', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + + expect(lines[3][1]).toEqual value: 'BLUE', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[3][3]).toEqual value: '(', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[3][4]).toEqual value: '123', scopes: ['source.java', 'meta.enum.java', 'constant.numeric.decimal.java'] + expect(lines[3][5]).toEqual value: ')', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + + expect(lines[19][1]).toEqual value: 'public', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'storage.modifier.java'] + expect(lines[19][3]).toEqual value: 'String', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.java'] + expect(lines[19][5]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[22][0]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.section.enum.end.bracket.curly.java'] + + it 'tokenizes enums with modifiers', -> + lines = grammar.tokenizeLines ''' + public enum Test { + } + + private enum Test { + } + + protected enum Test { + } + + unknown enum Test { + } + ''' + + expect(lines[0][0]).toEqual value: 'public', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[0][2]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[3][0]).toEqual value: 'private', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[3][2]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[6][0]).toEqual value: 'protected', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[6][2]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[9][0]).toEqual value: 'unknown ', scopes: ['source.java', 'meta.enum.java'] + expect(lines[9][1]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] + + it 'tokenizes enums within a class', -> + lines = grammar.tokenizeLines ''' + class A { + public enum Colours { + RED, + GREEN, + BLUE + } + } + ''' + + expect(lines[1][1]).toEqual value: 'public', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[1][3]).toEqual value: 'enum', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'storage.modifier.java'] + expect(lines[1][5]).toEqual value: 'Colours', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'entity.name.type.enum.java'] + expect(lines[1][7]).toEqual value: '{', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'punctuation.section.enum.begin.bracket.curly.java'] + expect(lines[2][1]).toEqual value: 'RED', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[3][1]).toEqual value: 'GREEN', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[4][1]).toEqual value: 'BLUE', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[5][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'punctuation.section.enum.end.bracket.curly.java'] it 'does not catastrophically backtrack when tokenizing large enums (regression)', -> # https://github.com/atom/language-java/issues/103 @@ -254,7 +362,7 @@ describe 'Java grammar', -> } """ - expect(lines[0][2]).toEqual value: 'enum', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'storage.modifier.java'] + expect(lines[0][2]).toEqual value: 'enum', scopes: ['source.java', 'meta.enum.java', 'storage.modifier.java'] it 'tokenizes methods', -> lines = grammar.tokenizeLines ''' From 2f9e732d9b205c090cc4c0254c02740b6fbb819b Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Tue, 25 Sep 2018 14:33:43 -0400 Subject: [PATCH 14/59] :memo: Update .github --- .github/no-response.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/no-response.yml diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 0000000..3c6b33d --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,15 @@ +# Configuration for probot-no-response - https://github.com/probot/no-response + +# Number of days of inactivity before an issue is closed for lack of response +daysUntilClose: 180 + +# Label requiring a response +responseRequiredLabel: more-information-needed + +# Comment to post when closing an issue for lack of response. Set to `false` to disable. +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. From 04449c6afe08e0647bc783eed264a6d6a704766c Mon Sep 17 00:00:00 2001 From: Jason Rudolph Date: Tue, 2 Oct 2018 11:42:49 -0400 Subject: [PATCH 15/59] :memo: Update .github --- .github/no-response.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/no-response.yml b/.github/no-response.yml index 3c6b33d..1c8799d 100644 --- a/.github/no-response.yml +++ b/.github/no-response.yml @@ -1,7 +1,7 @@ # Configuration for probot-no-response - https://github.com/probot/no-response # Number of days of inactivity before an issue is closed for lack of response -daysUntilClose: 180 +daysUntilClose: 28 # Label requiring a response responseRequiredLabel: more-information-needed From a64630d3c6f434b6b1f92f27079d54a93871a30f Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 23 Oct 2018 23:35:46 +0200 Subject: [PATCH 16/59] Variable highlighting in for-each loop (#163) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change I found when working on other issue that variables in for-each loops are not scoped correctly, for example: ```java class Test { void func() { // correctly highlighted in for loop for (int i = 0; i < 10; i++) { // do something } // incorrectly highlighted and scoped in for-each loop for (int i : elements) { // do something } // incorrectly highlighted and scoped in for-each loop for (HashMap map : elementsFunc()) { // do something } } } ``` Before patch: before After patch: after I simply extended the list of characters that terminate variable patterns and added `:` as such. Added test to cover this scenario. ### Alternate Designs None were considered. ### Benefits Fixes variable highlighting in for-each loops. ### Possible Drawbacks Should not be any. ### Applicable Issues None --- grammars/java.cson | 6 +++--- spec/java-spec.coffee | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index bf91a33..9edc2e2 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1356,14 +1356,14 @@ \\s+ [A-Za-z_$][\\w$]* # At least one identifier after space ([\\w\\[\\],$][\\w\\[\\],\\s]*)? # possibly primitive array or additional identifiers - \\s*(=|;) + \\s*(=|:|;) ) ''' - 'end': '(?=\\=|;)' + 'end': '(?=\\=|:|;)' 'name': 'meta.definition.variable.java' 'patterns': [ { - 'match': '([A-Za-z$_][\\w$]*)(?=\\s*(\\[\\])*\\s*(;|=|,))' + 'match': '([A-Za-z$_][\\w$]*)(?=\\s*(\\[\\])*\\s*(;|:|=|,))' 'captures': '1': 'name': 'variable.other.definition.java' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index b41e670..eaa185e 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -964,6 +964,30 @@ describe 'Java grammar', -> expect(lines[7][5]).toEqual value: '>', scopes: ['source.java', 'keyword.operator.comparison.java'] expect(lines[7][6]).toEqual value: ' g', scopes: ['source.java'] + it 'tokenizes variables in for-each loop', -> + lines = grammar.tokenizeLines ''' + void func() + { + for (int i : elements) { + // do something + } + + for (HashMap map : elementsFunc()) { + // do something + } + } + ''' + + expect(lines[2][3]).toEqual value: '(', scopes: ['source.java', 'punctuation.bracket.round.java'] + expect(lines[2][4]).toEqual value: 'int', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.primitive.java'] + expect(lines[2][6]).toEqual value: 'i', scopes: ['source.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[2][10]).toEqual value: ')', scopes: ['source.java', 'punctuation.bracket.round.java'] + + expect(lines[6][3]).toEqual value: '(', scopes: ['source.java', 'punctuation.bracket.round.java'] + expect(lines[6][4]).toEqual value: 'HashMap', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[6][12]).toEqual value: 'map', scopes: ['source.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[6][19]).toEqual value: ')', scopes: ['source.java', 'punctuation.bracket.round.java'] + it 'tokenizes function and method calls', -> lines = grammar.tokenizeLines ''' class A From 261a1fa02e8d3b857b6887cc07323fdfa0f5cfb9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 23 Oct 2018 23:52:47 +0200 Subject: [PATCH 17/59] Java 10 local variable "var" type support (#164) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR adds support for `var` storage type that is used in Java 10 to indicate local variable with inferred type. Details can be found here: http://openjdk.java.net/jeps/286. I created a new pattern `variables-local` specifically for declarations `var x = ...`. This allows to only highlight `var` keyword when it is actually a storage type. I tested on the following code: ```java class Test { void func() { A a = new A(); var b = new B(); // should be scoped as a variable name C var = new C(); // should be scoped as a variable name var = new C(); {var d = new D();} for (var d : elements()) { // should highlight as storage type } } } ``` Before: before After: after I added `#variables-local` to `#code` just next to `#variables` pattern. This has it's benefits, such as working out of the box inside for loops and code blocks. Unfortunately, this highlights `var x = ...` when defined in class body, which will result in compilation error based on the JDK doc, but I guess it should be okay. ### Alternate Designs None were considered apart from adding `variables-local` pattern separately to scopes where it should be defined, but I think this would have been messy and would have still had issues. ### Benefits Adds a feature of `var` support. ### Possible Drawbacks Should not impact any existing code, even if they use `var` as a variable name. ### Applicable Issues Closes #162 --- grammars/java.cson | 26 ++++++++++++++++++++++++++ spec/java-spec.coffee | 29 +++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index 9edc2e2..c86a785 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -403,6 +403,10 @@ { 'include': '#variables' } + { + # Java 10 local variable type + 'include': '#variables-local' + } { 'include': '#objects' } @@ -1375,3 +1379,25 @@ 'include': '#code' } ] + # Java 10 local variable type "var", should only be used inside the method body, + # see spec http://openjdk.java.net/jeps/286 + 'variables-local': + # This is simplified version of `variables` pattern + 'begin': '(?=\\b(var)\\b\\s+[A-Za-z_$][\\w$]*\\s*(=|:|;))' + 'end': '(?=\\=|:|;)' + 'name': 'meta.definition.variable.local.java' + 'patterns': [ + { + 'match': '\\bvar\\b' + 'name': 'storage.type.local.java' + } + { + 'match': '([A-Za-z$_][\\w$]*)(?=\\s*(\\[\\])*\\s*(=|:|;))' + 'captures': + '1': + 'name': 'variable.other.definition.java' + } + { + 'include': '#code' + } + ] diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index eaa185e..b8d686a 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -988,6 +988,35 @@ describe 'Java grammar', -> expect(lines[6][12]).toEqual value: 'map', scopes: ['source.java', 'meta.definition.variable.java', 'variable.other.definition.java'] expect(lines[6][19]).toEqual value: ')', scopes: ['source.java', 'punctuation.bracket.round.java'] + it 'tokenizes Java 10 local variables', -> + lines = grammar.tokenizeLines ''' + void func() { + var a = new A(); + B var = new B(); + var = new C(); + { var d = new D(); } + for (var e : elements()) { + // do something + } + } + ''' + + expect(lines[1][1]).toEqual value: 'var', scopes: ['source.java', 'meta.definition.variable.local.java', 'storage.type.local.java'] + expect(lines[1][3]).toEqual value: 'a', scopes: ['source.java', 'meta.definition.variable.local.java', 'variable.other.definition.java'] + + # should be highlighted as variable name, not storage type + expect(lines[2][1]).toEqual value: 'B', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][3]).toEqual value: 'var', scopes: ['source.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + + # should be a variable name + expect(lines[3][0]).toEqual value: ' var ', scopes: ['source.java'] + + expect(lines[4][3]).toEqual value: 'var', scopes: ['source.java', 'meta.definition.variable.local.java', 'storage.type.local.java'] + expect(lines[4][5]).toEqual value: 'd', scopes: ['source.java', 'meta.definition.variable.local.java', 'variable.other.definition.java'] + + expect(lines[5][4]).toEqual value: 'var', scopes: ['source.java', 'meta.definition.variable.local.java', 'storage.type.local.java'] + expect(lines[5][6]).toEqual value: 'e', scopes: ['source.java', 'meta.definition.variable.local.java', 'variable.other.definition.java'] + it 'tokenizes function and method calls', -> lines = grammar.tokenizeLines ''' class A From 95ebcd0b15c369666ecc4d1593495466132dd5bf Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 24 Oct 2018 00:03:09 +0200 Subject: [PATCH 18/59] Fix regression of field values being incorrectly highlighted (#161) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR fixes the regression reported in #158. This happened because our variable definition now ends with `=`, and the rest is supposed to be matched by the code, which does happen correctly, but it breaks in certain scenarios when using class fields, e.g. ```java class A { private String b = a + "a()" + a() + "" + "a();" + "" + a() + abc + b() + "b();"; private String c = "a / a();"; private int d[] = a + "a();" + func(); int abcd() { return 1; } } ``` ### Before before ### After after All of the `b`, `c`, and `d` would break a subsequent highlighting and scope of method `abcd`. The fix is fairly straightforward and might seem as a hack. We define `#class-fields-and-methods` scope instead of `#methods` and first match anything like this `... = [...];`, where `[...]` is covered by `#code`, and only then we match methods. This seems to work quite well. I also fixed comments in methods, while I was there. Added tests for both methods and class fields. ### Alternate Designs I considered reverting #146 at some point, but then we would still have to solve `;` issue in try with resources, and, to be fair, the change in that PR was more or less reasonable. I also tried updating pattern for `#methods` scope trying to restrict it, so that it does not show up in the expression part. It turned out to be quite difficult, mostly because of the return type and parameter types being potentially anything, which complicated the task. For example, I tried writing something like this: ```cson 'methods': 'begin': '(?!new)(?=[\\w<].*\\s+)(?=[\\w\\s\\[\\]<>,\\.\\?/\\*]+\\()' ``` But it did not work in certain cases. ### Benefits Fixes the regression introduced by #146. ### Possible Drawbacks Could potentially miss coverage of some other case. ### Applicable Issues Closes #158 --- grammars/java.cson | 29 ++++++-- spec/java-spec.coffee | 158 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 173 insertions(+), 14 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index c86a785..df32209 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -335,7 +335,7 @@ 'include': '#static-initializer' } { - 'include': '#methods' + 'include': '#class-fields-and-methods' } { 'include': '#annotations' @@ -350,6 +350,25 @@ 'include': '#code' } ] + 'class-fields-and-methods': + # Pattern to match both class fields and method declarations inside class body. + # For class fields, we only need to match part after '=', because the first part will be + # matched using 'variables' pattern. Only then we apply pattern to match methods, because + # it is not strict and could potentially match functions in the code (issue #158). + 'patterns': [ + { + 'begin': '(?=\\=)' + 'end': '(?=;)' + 'patterns': [ + { + 'include': '#code' + } + ] + } + { + 'include': '#methods' + } + ] 'code': 'patterns': [ { @@ -441,9 +460,6 @@ 'match': '/\\*\\*/' 'name': 'comment.block.empty.java' } - { - 'include': 'text.html.javadoc' - } { 'include': '#comments-inline' } @@ -805,7 +821,7 @@ 'include': '#parens' } { - 'include': '#comments-inline' + 'include': '#comments' } ] } @@ -823,6 +839,9 @@ { 'include': '#parens' } + { + 'include': '#comments' + } ] } { diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index b8d686a..864e632 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -366,22 +366,108 @@ describe 'Java grammar', -> it 'tokenizes methods', -> lines = grammar.tokenizeLines ''' - class A + abstract class A { A(int a, int b) { + super(); + this.prop = a + b; + } + + public /* test */ List /* test */ getList() /* test */ throws Exception + { + return null; + } + + public void nothing(); + + public java.lang.String[][] getString() + { + return null; + } + + public Map getMap() + { + return null; } + + public T call(String name, Class type) + { + return null; + } + + private int prop = 0; } ''' - expect(lines[2][1]).toEqual value: 'A', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] - expect(lines[2][2]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(lines[2][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.identifier.java', 'storage.type.primitive.java'] - expect(lines[2][5]).toEqual value: 'a', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.identifier.java', 'variable.parameter.java'] - expect(lines[2][6]).toEqual value: ',', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.identifier.java', 'punctuation.separator.delimiter.java'] - expect(lines[2][11]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(lines[3][1]).toEqual value: '{', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'punctuation.section.method.begin.bracket.curly.java'] - expect(lines[4][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'punctuation.section.method.end.bracket.curly.java'] + scopeStack = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java'] + + expect(lines[2][1]).toEqual value: 'A', scopes: scopeStack.concat ['meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[2][2]).toEqual value: '(', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[2][3]).toEqual value: 'int', scopes: scopeStack.concat ['meta.method.identifier.java', 'storage.type.primitive.java'] + expect(lines[2][5]).toEqual value: 'a', scopes: scopeStack.concat ['meta.method.identifier.java', 'variable.parameter.java'] + expect(lines[2][6]).toEqual value: ',', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.separator.delimiter.java'] + expect(lines[2][11]).toEqual value: ')', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(lines[3][1]).toEqual value: '{', scopes: scopeStack.concat ['punctuation.section.method.begin.bracket.curly.java'] + expect(lines[4][1]).toEqual value: 'super', scopes: scopeStack.concat ['meta.method.body.java', 'variable.language.java'] + expect(lines[5][1]).toEqual value: 'this', scopes: scopeStack.concat ['meta.method.body.java', 'variable.language.this.java'] + expect(lines[5][3]).toEqual value: 'prop', scopes: scopeStack.concat ['meta.method.body.java', 'variable.other.property.java'] + expect(lines[6][1]).toEqual value: '}', scopes: scopeStack.concat ['punctuation.section.method.end.bracket.curly.java'] + + expect(lines[8][1]).toEqual value: 'public', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[8][4]).toEqual value: ' test ', scopes: scopeStack.concat ['comment.block.java'] + expect(lines[8][7]).toEqual value: 'List', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.java'] + expect(lines[8][8]).toEqual value: '<', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.angle.java'] + expect(lines[8][9]).toEqual value: 'Integer', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.generic.java'] + expect(lines[8][10]).toEqual value: '>', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.angle.java'] + expect(lines[8][13]).toEqual value: ' test ', scopes: scopeStack.concat ['meta.method.return-type.java', 'comment.block.java'] + expect(lines[8][16]).toEqual value: 'getList', scopes: scopeStack.concat ['meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[8][21]).toEqual value: ' test ', scopes: scopeStack.concat ['comment.block.java'] + expect(lines[8][24]).toEqual value: 'throws', scopes: scopeStack.concat ['meta.throwables.java', 'storage.modifier.java'] + expect(lines[8][26]).toEqual value: 'Exception', scopes: scopeStack.concat ['meta.throwables.java', 'storage.type.java'] + + expect(lines[13][1]).toEqual value: 'public', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[13][3]).toEqual value: 'void', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[13][5]).toEqual value: 'nothing', scopes: scopeStack.concat ['meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[13][6]).toEqual value: '(', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[13][7]).toEqual value: ')', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java'] + + expect(lines[15][1]).toEqual value: 'public', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[15][3]).toEqual value: 'java', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.java'] + expect(lines[15][5]).toEqual value: 'lang', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.java'] + expect(lines[15][7]).toEqual value: 'String', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.object.array.java'] + expect(lines[15][8]).toEqual value: '[', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.square.java'] + expect(lines[15][9]).toEqual value: ']', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.square.java'] + expect(lines[15][10]).toEqual value: '[', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.square.java'] + expect(lines[15][11]).toEqual value: ']', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.square.java'] + expect(lines[15][13]).toEqual value: 'getString', scopes: scopeStack.concat ['meta.method.identifier.java', 'entity.name.function.java'] + + expect(lines[20][1]).toEqual value: 'public', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[20][3]).toEqual value: 'Map', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.java'] + expect(lines[20][4]).toEqual value: '<', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.angle.java'] + expect(lines[20][5]).toEqual value: 'Integer', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.generic.java'] + expect(lines[20][8]).toEqual value: 'Integer', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.generic.java'] + expect(lines[20][9]).toEqual value: '>', scopes: scopeStack.concat ['meta.method.return-type.java', 'punctuation.bracket.angle.java'] + expect(lines[20][11]).toEqual value: 'getMap', scopes: scopeStack.concat ['meta.method.identifier.java', 'entity.name.function.java'] + + expect(lines[25][1]).toEqual value: 'public', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[25][3]).toEqual value: '<', scopes: scopeStack.concat ['punctuation.bracket.angle.java'] + expect(lines[25][4]).toEqual value: 'T', scopes: scopeStack.concat ['storage.type.generic.java'] + expect(lines[25][6]).toEqual value: 'extends', scopes: scopeStack.concat ['storage.modifier.extends.java'] + expect(lines[25][8]).toEqual value: 'Box', scopes: scopeStack.concat ['storage.type.generic.java'] + expect(lines[25][9]).toEqual value: '>', scopes: scopeStack.concat ['punctuation.bracket.angle.java'] + expect(lines[25][11]).toEqual value: 'T', scopes: scopeStack.concat ['meta.method.return-type.java', 'storage.type.java'] + expect(lines[25][13]).toEqual value: 'call', scopes: scopeStack.concat ['meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[25][14]).toEqual value: '(', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[25][15]).toEqual value: 'String', scopes: scopeStack.concat ['meta.method.identifier.java', 'storage.type.java'] + expect(lines[25][17]).toEqual value: 'name', scopes: scopeStack.concat ['meta.method.identifier.java', 'variable.parameter.java'] + expect(lines[25][20]).toEqual value: 'Class', scopes: scopeStack.concat ['meta.method.identifier.java', 'storage.type.java'] + expect(lines[25][21]).toEqual value: '<', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.bracket.angle.java'] + expect(lines[25][22]).toEqual value: 'T', scopes: scopeStack.concat ['meta.method.identifier.java', 'storage.type.generic.java'] + expect(lines[25][23]).toEqual value: '>', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.bracket.angle.java'] + expect(lines[25][25]).toEqual value: 'type', scopes: scopeStack.concat ['meta.method.identifier.java', 'variable.parameter.java'] + expect(lines[25][26]).toEqual value: ')', scopes: scopeStack.concat ['meta.method.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java'] + it 'tokenizes variable-length argument list (varargs)', -> lines = grammar.tokenizeLines ''' @@ -1621,6 +1707,60 @@ describe 'Java grammar', -> expect(lines[15][5]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[15][6]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + it 'tokenizes class fields with complex definitions', -> + lines = grammar.tokenizeLines ''' + class A { + private String a = func(); + private String b = a + "a()" + a() + "" + "a();" + "" + a() + abc + b() + "b();"; + private String c = "a / a();"; + private int d[] = a + "a();" + func(); + + int abcd() { + return 1; + } + } + ''' + + scopeStack = ['source.java', 'meta.class.java', 'meta.class.body.java'] + + expect(lines[1][1]).toEqual value: 'private', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[1][3]).toEqual value: 'String', scopes: scopeStack.concat ['meta.definition.variable.java', 'storage.type.java'] + expect(lines[1][5]).toEqual value: 'a', scopes: scopeStack.concat ['meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[1][7]).toEqual value: '=', scopes: scopeStack.concat ['keyword.operator.assignment.java'] + expect(lines[1][9]).toEqual value: 'func', scopes: scopeStack.concat ['meta.function-call.java', 'entity.name.function.java'] + + expect(lines[2][1]).toEqual value: 'private', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[2][3]).toEqual value: 'String', scopes: scopeStack.concat ['meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][5]).toEqual value: 'b', scopes: scopeStack.concat ['meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[2][7]).toEqual value: '=', scopes: scopeStack.concat ['keyword.operator.assignment.java'] + expect(lines[2][8]).toEqual value: ' a ', scopes: scopeStack + expect(lines[2][12]).toEqual value: 'a()', scopes: scopeStack.concat ['string.quoted.double.java'] + expect(lines[2][17]).toEqual value: 'a', scopes: scopeStack.concat ['meta.function-call.java', 'entity.name.function.java'] + expect(lines[2][29]).toEqual value: 'a();', scopes: scopeStack.concat ['string.quoted.double.java'] + expect(lines[2][39]).toEqual value: 'a', scopes: scopeStack.concat ['meta.function-call.java', 'entity.name.function.java'] + expect(lines[2][44]).toEqual value: ' abc ', scopes: scopeStack + expect(lines[2][47]).toEqual value: 'b', scopes: scopeStack.concat ['meta.function-call.java', 'entity.name.function.java'] + expect(lines[2][54]).toEqual value: 'b();', scopes: scopeStack.concat ['string.quoted.double.java'] + + expect(lines[3][1]).toEqual value: 'private', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[3][3]).toEqual value: 'String', scopes: scopeStack.concat ['meta.definition.variable.java', 'storage.type.java'] + expect(lines[3][5]).toEqual value: 'c', scopes: scopeStack.concat ['meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[3][7]).toEqual value: '=', scopes: scopeStack.concat ['keyword.operator.assignment.java'] + expect(lines[3][10]).toEqual value: 'a / a();', scopes: scopeStack.concat ['string.quoted.double.java'] + + expect(lines[4][1]).toEqual value: 'private', scopes: scopeStack.concat ['storage.modifier.java'] + expect(lines[4][3]).toEqual value: 'int', scopes: scopeStack.concat ['meta.definition.variable.java', 'storage.type.primitive.java'] + expect(lines[4][5]).toEqual value: 'd', scopes: scopeStack.concat ['meta.definition.variable.java', 'variable.other.definition.java'] + expect(lines[4][6]).toEqual value: '[', scopes: scopeStack.concat ['meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[4][7]).toEqual value: ']', scopes: scopeStack.concat ['meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[4][9]).toEqual value: '=', scopes: scopeStack.concat ['keyword.operator.assignment.java'] + expect(lines[4][10]).toEqual value: ' a ', scopes: scopeStack + expect(lines[4][14]).toEqual value: 'a();', scopes: scopeStack.concat ['string.quoted.double.java'] + expect(lines[4][19]).toEqual value: 'func', scopes: scopeStack.concat ['meta.function-call.java', 'entity.name.function.java'] + + expect(lines[6][1]).toEqual value: 'int', scopes: scopeStack.concat ['meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[6][3]).toEqual value: 'abcd', scopes: scopeStack.concat ['meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + it 'tokenizes qualified storage types', -> lines = grammar.tokenizeLines ''' class Test { From c3dc099cd7884c8dde2a20dd13a544d539b17c0e Mon Sep 17 00:00:00 2001 From: Linus Eriksson Date: Wed, 24 Oct 2018 18:00:15 +0200 Subject: [PATCH 19/59] Prepare 0.31.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8da3e5e..16c247d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.30.0", + "version": "0.31.0", "description": "Java language support in Atom", "engines": { "atom": "*", From 3698d45ced4ac565981c6e1711d86e00ad7a45ff Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Sun, 28 Oct 2018 17:39:14 +0100 Subject: [PATCH 20/59] update class pattern --- grammars/java.cson | 2 +- spec/java-spec.coffee | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/grammars/java.cson b/grammars/java.cson index df32209..5045385 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -243,7 +243,7 @@ } ] 'class': - 'begin': '(?=\\w?[\\w\\s]*(?:class|(? class Thing { int x; } + + class classA { + int a; + } + + class Aclass { + int b; + } + + public static void main(String[] args) { + Testclass test1 = null; + TestClass test2 = null; + } ''' expect(lines[0][0]).toEqual value: 'class', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'storage.modifier.java'] expect(lines[0][2]).toEqual value: 'Thing', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'entity.name.type.class.java'] + expect(lines[4][0]).toEqual value: 'class', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'storage.modifier.java'] + expect(lines[4][2]).toEqual value: 'classA', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'entity.name.type.class.java'] + expect(lines[8][0]).toEqual value: 'class', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'storage.modifier.java'] + expect(lines[8][2]).toEqual value: 'Aclass', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'entity.name.type.class.java'] + expect(lines[13][1]).toEqual value: 'Testclass', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[14][1]).toEqual value: 'TestClass', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] it 'tokenizes enums', -> lines = grammar.tokenizeLines ''' From d48e7137f6634cc094f092b68e6b110f51f47630 Mon Sep 17 00:00:00 2001 From: Winston Liu <50Wliu@users.noreply.github.com> Date: Sun, 11 Nov 2018 15:41:58 -0500 Subject: [PATCH 21/59] Prepare 0.31.1 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16c247d..6825466 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.31.0", + "version": "0.31.1", "description": "Java language support in Atom", "engines": { "atom": "*", From 7c3d0d3e37920790cd3afb4e68830bdb215851a3 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 4 Dec 2018 09:06:48 +0100 Subject: [PATCH 22/59] fix enum with overrides (#175) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR extends support for enums and adds a pattern to handle enum's constant fields with method overrides. It is allowed to have such fields mixed with the previous two types that we have added. The fix is fairly simple - adding another pattern to handle the case of enum field starting with `{` and ending with `}` similar to inner class. For that reason, I used `include: #class-body` instead of `include: #code`. ### Alternate Designs None were considered, since it is fairly simple fix. ### Benefits Fixes enum highlighting for enums with override methods. ### Possible Drawbacks None. It only affects changes for enums. ### Applicable Issues Closes #173 --- grammars/java.cson | 20 ++++++++++++++++++++ spec/java-spec.coffee | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index 5045385..5ea37b9 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -587,6 +587,26 @@ { 'include': '#comments' } + # Represents enum's constant field with the code overrides + { + 'begin': '(\\w+)\\s*({)' + 'beginCaptures': + '1': + 'name': 'constant.other.enum.java' + '2': + 'name': 'punctuation.bracket.curly.java' + 'end': '\\}' + 'endCaptures': + '0': + 'name': 'punctuation.bracket.curly.java' + 'patterns': [ + { + # Use #class-body, because the enum field overrides enum class body. + # It is similar to inner class. + 'include': '#class-body' + } + ] + } # Represents enum's constant field with constructor, e.g. `Test(123)` { 'begin': '(\\w+)\\s*(\\()' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 9016660..934eddf 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -368,6 +368,48 @@ describe 'Java grammar', -> expect(lines[4][1]).toEqual value: 'BLUE', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'constant.other.enum.java'] expect(lines[5][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java', 'punctuation.section.enum.end.bracket.curly.java'] + it 'tokenizes enums with method overrides', -> + lines = grammar.tokenizeLines ''' + enum TYPES { + TYPE_A { + @Override + int func() { + return 1; + } + }, + TYPE_B { + @Override + int func() { + return 2; + } + }, + TYPE_DEFAULT; + + int func() { + return 0; + } + } + ''' + + expect(lines[1][1]).toEqual value: 'TYPE_A', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[1][3]).toEqual value: '{', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + expect(lines[2][2]).toEqual value: 'Override', scopes: ['source.java', 'meta.enum.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] + expect(lines[3][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[3][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[6][1]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + + expect(lines[7][1]).toEqual value: 'TYPE_B', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[7][3]).toEqual value: '{', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + expect(lines[8][2]).toEqual value: 'Override', scopes: ['source.java', 'meta.enum.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] + expect(lines[9][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[9][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[12][1]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + + expect(lines[13][1]).toEqual value: 'TYPE_DEFAULT', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + + expect(lines[15][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[15][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + it 'does not catastrophically backtrack when tokenizing large enums (regression)', -> # https://github.com/atom/language-java/issues/103 # This test 'fails' if it runs for an absurdly long time without completing. From 702e88982af7777abfd629ce5b702b5990faa5f6 Mon Sep 17 00:00:00 2001 From: 0xc0 <38927632+0xc0@users.noreply.github.com> Date: Fri, 11 Jan 2019 00:09:54 -0800 Subject: [PATCH 23/59] Add support for `final` in `catch` parameters (#188) ### Description of the Change The regex for the `catch` parameters currently does not support `final`, meaning that `final` is highlighted as a type. This change adds an optional group to account for the possibility of the Java `final` modifier. ### Alternate Designs None, as prepending the existing regex is a simple change. ### Benefits Correct syntax highlighting when `final` is within `catch` parameters ### Possible Drawbacks None. ### Applicable Issues None. --- grammars/java.cson | 3 +++ spec/java-spec.coffee | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index 5ea37b9..45e8e51 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1325,6 +1325,9 @@ { 'include': '#comments' } + { + 'include': '#storage-modifiers' + } { 'match': '\\|' 'name': 'punctuation.catch.separator.java' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 934eddf..d88350c 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2079,6 +2079,27 @@ describe 'Java grammar', -> expect(lines[2][20]).toEqual value: ')', scopes: scopes.concat ['meta.try.resources.java', 'punctuation.section.try.resources.end.bracket.round.java'] expect(lines[2][22]).toEqual value: '{', scopes: scopes.concat ['punctuation.section.try.begin.bracket.curly.java'] + it 'tokenizes storage modifier in catch block', -> + lines = grammar.tokenizeLines ''' + class Test + { + private void method() { + try { + // do something + } catch (final Exception1 ex) { + throw new Exception2(); + } + } + } + ''' + + expect(lines[5][3]).toEqual value: 'catch', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'keyword.control.catch.java'] + expect(lines[5][5]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[5][6]).toEqual value: 'final', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.modifier.java'] + expect(lines[5][8]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[5][10]).toEqual value: 'ex', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] + expect(lines[5][11]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + it 'tokenizes list of exceptions in catch block', -> lines = grammar.tokenizeLines ''' class Test From 715d4e67e9ccb9b27980f6466da6118c72a080c2 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 15 Jan 2019 08:50:11 +0100 Subject: [PATCH 24/59] add test for instanceof and assertions (#189) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change PR adds test for `instanceof` in if statements and assertions. ### Alternate Designs Not applicable. ### Benefits Improved test coverage. ### Possible Drawbacks Not applicable. ### Applicable Issues Closes #187 --- spec/java-spec.coffee | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index d88350c..7cdc5d1 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1657,6 +1657,23 @@ describe 'Java grammar', -> expect(tokens[0]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof.java'] + it 'tokenizes the `instanceof` operator in assertions and if statements', -> + lines = grammar.tokenizeLines ''' + class Test { + void func() { + A a = new A(); + if (a instanceof A) { + // do something + } + assert a instanceof A; + } + } + ''' + + scopeStack = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java'] + expect(lines[3][5]).toEqual value: 'instanceof', scopes: scopeStack.concat ['keyword.operator.instanceof.java'] + expect(lines[6][4]).toEqual value: 'instanceof', scopes: scopeStack.concat ['meta.declaration.assertion.java', 'keyword.operator.instanceof.java'] + it 'tokenizes class fields', -> lines = grammar.tokenizeLines ''' class Test From f6d349a5ca698be25d3f48511888fe62d158e42c Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 15 Jan 2019 08:52:05 +0100 Subject: [PATCH 25/59] add extends and implements to enum (#190) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR adds `extends` and `implements` to `enums` scope. Currently we have enum scope separate from class and interface, because of the complexity of enum's representations, though we did not migrate `extends` and `implements` to the enum. This work fixes the issue by copying those blocks of code from class scope and adding them to enum scope with some minor changes. ### Alternate Designs None were considered. ### Benefits Fixes a regression for enum's `extends` and `implements`. ### Possible Drawbacks This patch introduces a bit of code duplication between class and enum, mostly because of the separation of those scopes. ### Applicable Issues Closes #185 --- grammars/java.cson | 32 +++++++++++++++++++++++ spec/java-spec.coffee | 59 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index 45e8e51..6dbae04 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -570,6 +570,38 @@ 'name': 'punctuation.section.enum.end.bracket.curly.java' 'name': 'meta.enum.java' 'patterns': [ + { + 'begin': '\\b(extends)\\b' + 'beginCaptures': + '1': + 'name': 'storage.modifier.extends.java' + 'end': '(?={|\\bimplements\\b)' + 'name': 'meta.definition.class.inherited.classes.java' + 'patterns': [ + { + 'include': '#object-types-inherited' + } + { + 'include': '#comments' + } + ] + } + { + 'begin': '\\b(implements)\\b' + 'beginCaptures': + '1': + 'name': 'storage.modifier.implements.java' + 'end': '(?={|\\bextends\\b)' + 'name': 'meta.definition.class.implemented.interfaces.java' + 'patterns': [ + { + 'include': '#object-types-inherited' + } + { + 'include': '#comments' + } + ] + } { 'begin': '{' 'beginCaptures': diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 7cdc5d1..472ab62 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -410,6 +410,65 @@ describe 'Java grammar', -> expect(lines[15][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] expect(lines[15][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + it 'tokenizes enums with extends and implements', -> + lines = grammar.tokenizeLines ''' + class A { + enum Test1 extends Bclass, Cclass implements Din, Ein { + } + + enum Test2 implements Din, Ein extends Bclass, Cclass { + } + + enum Test3 extends SomeClass { + } + + enum Test4 implements SomeInterface { + } + + enum Test5 extends java.lang.SomeClass { + } + + enum Test6 implements java.lang.SomeInterface { + } + } + ''' + + scopeStack = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.enum.java'] + + # Test1 + expect(lines[1][5]).toEqual value: 'extends', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'storage.modifier.extends.java'] + expect(lines[1][7]).toEqual value: 'Bclass', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'entity.other.inherited-class.java'] + expect(lines[1][10]).toEqual value: 'Cclass', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'entity.other.inherited-class.java'] + expect(lines[1][12]).toEqual value: 'implements', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'storage.modifier.implements.java'] + expect(lines[1][14]).toEqual value: 'Din', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java'] + expect(lines[1][17]).toEqual value: 'Ein', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java'] + + # Test2 + expect(lines[4][5]).toEqual value: 'implements', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'storage.modifier.implements.java'] + expect(lines[4][7]).toEqual value: 'Din', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java'] + expect(lines[4][10]).toEqual value: 'Ein', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java'] + expect(lines[4][12]).toEqual value: 'extends', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'storage.modifier.extends.java'] + expect(lines[4][14]).toEqual value: 'Bclass', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'entity.other.inherited-class.java'] + expect(lines[4][17]).toEqual value: 'Cclass', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'entity.other.inherited-class.java'] + + # Test3 + expect(lines[7][5]).toEqual value: 'extends', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'storage.modifier.extends.java'] + expect(lines[7][7]).toEqual value: 'SomeClass', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'entity.other.inherited-class.java'] + + # Test4 + expect(lines[10][5]).toEqual value: 'implements', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'storage.modifier.implements.java'] + expect(lines[10][7]).toEqual value: 'SomeInterface', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java'] + + # Test5 + # TODO ' java.lang.' is highlighted as a single block for some reason, same for the class + expect(lines[13][5]).toEqual value: 'extends', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'storage.modifier.extends.java'] + expect(lines[13][7]).toEqual value: 'SomeClass', scopes: scopeStack.concat ['meta.definition.class.inherited.classes.java', 'entity.other.inherited-class.java'] + + # Test6 + # TODO ' java.lang.' is highlighted as a single block for some reason, same for the class + expect(lines[16][5]).toEqual value: 'implements', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'storage.modifier.implements.java'] + expect(lines[16][7]).toEqual value: 'SomeInterface', scopes: scopeStack.concat ['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java'] + it 'does not catastrophically backtrack when tokenizing large enums (regression)', -> # https://github.com/atom/language-java/issues/103 # This test 'fails' if it runs for an absurdly long time without completing. From a91b17906a2142bc61c06c6f214f135a2e3cdc96 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 29 Mar 2019 22:09:05 +0100 Subject: [PATCH 26/59] Fix annotation scope and handle spaces between @ and annotation name (#195) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR fixes the issue of scope and highlighting being invalid when space is inserted between `@` and annotation name, e.g. `@ Annotation` as opposed to `@Annotation`. We basically need to insert `\\s*` in the correct place. However, I observed that patterns are invalid in a sense that they capture `@` as part of annotation name scope. So I also fixed the scope of annotations so that `storage.type.annotation.java` does not capture `@`. They both have parent scope `meta.declaration.annotation.java`. This makes them similar to `@interface`. ### Alternate Designs None were considered. ### Benefits Fixes issue when using spaces in annotations. ### Possible Drawbacks None ### Applicable Issues Closes #194 --- grammars/java.cson | 12 ++++++------ spec/java-spec.coffee | 28 ++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 6dbae04..d71669d 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -129,13 +129,13 @@ 'annotations': 'patterns': [ { - 'begin': '((@)[^\\s(]+)(\\()' + 'begin': '((@)\\s*([^\\s(]+))(\\()' 'beginCaptures': - '1': - 'name': 'storage.type.annotation.java' '2': 'name': 'punctuation.definition.annotation.java' '3': + 'name': 'storage.type.annotation.java' + '4': 'name': 'punctuation.definition.annotation-arguments.begin.bracket.round.java' 'end': '\\)' 'endCaptures': @@ -157,7 +157,7 @@ ] } { - 'match': '(@)(interface)\\s+(\\w*)|((@)\\w*)' + 'match': '(@)(interface)\\s+(\\w*)|((@)\\s*(\\w+))' 'name': 'meta.declaration.annotation.java' 'captures': '1': @@ -166,10 +166,10 @@ 'name': 'storage.modifier.java' '3': 'name': 'storage.type.annotation.java' - '4': - 'name': 'storage.type.annotation.java' '5': 'name': 'punctuation.definition.annotation.java' + '6': + 'name': 'storage.type.annotation.java' } ] 'anonymous-block-and-instance-initializer': diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 472ab62..b518fd6 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2568,10 +2568,10 @@ describe 'Java grammar', -> public @interface Test {} ''' - expect(lines[0][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java', 'punctuation.definition.annotation.java'] + expect(lines[0][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation.java'] expect(lines[0][1]).toEqual value: 'Annotation', scopes: ['source.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] - expect(lines[1][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java', 'punctuation.definition.annotation.java'] + expect(lines[1][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation.java'] expect(lines[1][1]).toEqual value: 'Table', scopes: ['source.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] expect(lines[1][2]).toEqual value: '(', scopes: ['source.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation-arguments.begin.bracket.round.java'] expect(lines[1][3]).toEqual value: 'key', scopes: ['source.java', 'meta.declaration.annotation.java', 'constant.other.key.java'] @@ -2581,10 +2581,10 @@ describe 'Java grammar', -> expect(lines[1][9]).toEqual value: '"', scopes: ['source.java', 'meta.declaration.annotation.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] expect(lines[1][10]).toEqual value: ')', scopes: ['source.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation-arguments.end.bracket.round.java'] - expect(lines[3][1]).toEqual value: '@', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java', 'punctuation.definition.annotation.java'] + expect(lines[3][1]).toEqual value: '@', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation.java'] expect(lines[3][2]).toEqual value: 'Override', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] - expect(lines[4][1]).toEqual value: '@', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java', 'punctuation.definition.annotation.java'] + expect(lines[4][1]).toEqual value: '@', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation.java'] expect(lines[4][2]).toEqual value: 'Column', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] expect(lines[4][3]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation-arguments.begin.bracket.round.java'] expect(lines[4][4]).toEqual value: 'true', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java', 'constant.language.java'] @@ -2602,3 +2602,23 @@ describe 'Java grammar', -> expect(lines[8][2]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation.java', 'punctuation.definition.annotation.java'] expect(lines[8][3]).toEqual value: 'interface', scopes: ['source.java', 'meta.declaration.annotation.java', 'storage.modifier.java'] expect(lines[8][5]).toEqual value: 'Test', scopes: ['source.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] + + it 'tokenizes annotations with spaces', -> + lines = grammar.tokenizeLines ''' + class A { + @ Override + public void func1() { + } + + @ Message("message") + public void func2() { + } + } + ''' + + scopes = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.declaration.annotation.java'] + expect(lines[1][1]).toEqual value: '@', scopes: scopes.concat(['punctuation.definition.annotation.java']) + expect(lines[1][3]).toEqual value: 'Override', scopes: scopes.concat(['storage.type.annotation.java']) + expect(lines[5][1]).toEqual value: '@', scopes: scopes.concat(['punctuation.definition.annotation.java']) + expect(lines[5][3]).toEqual value: 'Message', scopes: scopes.concat(['storage.type.annotation.java']) + expect(lines[5][6]).toEqual value: 'message', scopes: scopes.concat(['string.quoted.double.java']) From 27fa88a4fc76649fa6dc4ea049708bb10fa0f1e7 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Fri, 29 Mar 2019 22:25:17 +0100 Subject: [PATCH 27/59] Prepare 0.31.2 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6825466..3cc4b56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.31.1", + "version": "0.31.2", "description": "Java language support in Atom", "engines": { "atom": "*", From 9fc8f699e55284c0a8ddf03d929504064eb4f757 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 13 Apr 2019 16:22:58 +0200 Subject: [PATCH 28/59] Fix whitespace issue in variable definition (#197) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR fixes an issue when inserting a whitespaces after storage type in variable definition would break highlighting. For example, ```java class A { String [] var1; int [] var2; List var3; } ``` Variables `var1`, `var2`, and `var3` would not be scoped properly. I patched `variables` scope by inserting `\s*` to handle whitespaces for generics and arrays. ### Alternate Designs Adding a whitespace inside the matching pattern, but it seemed a bit odd to have it, plus, there was already a precedent to use it outside of matching groups. ### Benefits Fixes the highlighting. ### Possible Drawbacks None. ### Applicable Issues #196 --- grammars/java.cson | 2 ++ spec/java-spec.coffee | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index d71669d..46c0b0c 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1425,9 +1425,11 @@ | (?>(\\w+\\.)*[A-Z]+\\w*) # e.g. `javax.ws.rs.Response`, or `String` ) + \\s* ( <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List` )? + \\s* ( (\\[\\])* # int[][] )? diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index b518fd6..2d63030 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1751,6 +1751,8 @@ describe 'Java grammar', -> String[] primitiveArray; private Foo hi; Foo hi; + String [] var1; + List var2; } ''' @@ -1844,6 +1846,17 @@ describe 'Java grammar', -> expect(lines[15][5]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[15][6]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[16][1]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.object.array.java'] + expect(lines[16][3]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[16][4]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + expect(lines[16][6]).toEqual value: 'var1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + + expect(lines[17][1]).toEqual value: 'List', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[17][3]).toEqual value: '<', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[17][4]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + expect(lines[17][5]).toEqual value: '>', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.angle.java'] + expect(lines[17][7]).toEqual value: 'var2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] + it 'tokenizes class fields with complex definitions', -> lines = grammar.tokenizeLines ''' class A { From 572afc787d2f4f7bf2fc445ca3acdb79e5ae91a4 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Sat, 13 Apr 2019 16:24:43 +0200 Subject: [PATCH 29/59] Prepare 0.31.3 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3cc4b56..69bef98 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.31.2", + "version": "0.31.3", "description": "Java language support in Atom", "engines": { "atom": "*", From 17b28d273dcaa9af7ea1facef7ea399d3641f668 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 15 Jun 2019 13:46:21 +0200 Subject: [PATCH 30/59] Fix underscore in class names ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change I updated patterns that relate to storage types to include underscore wherever it was missing; also updated variable pattern to capture storage types with underscore. Added unit test. ### Alternate Designs No alternative designs were considered. ### Benefits Fixes issue of having package and class names that start with underscore. ### Possible Drawbacks I had to comment out line 832 in `java-spec.coffee`, "_1" value is now highlighted as `storage.type.java`. I will open issue to fix this later. Should not affect anything else, as far as I am concerned. ### Applicable Issues Fixes #198 --- grammars/java.cson | 14 +++++++------- spec/java-spec.coffee | 23 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 46c0b0c..1cfb084 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1011,12 +1011,12 @@ 'include': '#generics' } { - 'begin': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*)([A-Z]\\w*)\\s*(?=\\[)' + 'begin': '\\b((?:[A-Za-z_]\\w*\\s*\\.\\s*)*)([A-Z_]\\w*)\\s*(?=\\[)' 'beginCaptures': '1': 'patterns': [ { - 'match': '[A-Za-z]\\w*' + 'match': '[A-Za-z_]\\w*' 'name': 'storage.type.java' } { @@ -1038,12 +1038,12 @@ } { # Match possible generics first, eg Foo.Bar in Foo.Bar - 'match': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\s*(?=<)' + 'match': '\\b((?:[A-Za-z_]\\w*\\s*\\.\\s*)*[A-Z_]\\w*)\\s*(?=<)' 'captures': '1': 'patterns': [ { - 'match': '[A-Za-z]\\w*' + 'match': '[A-Za-z_]\\w*' 'name': 'storage.type.java' } { @@ -1056,12 +1056,12 @@ # If the above fails *then* just look for Wow # (must be followed by a variable name, we use '\n' to cover multi-line definitions, # or varargs for function definitions) - 'match': '\\b((?:[A-Za-z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)\\b((?=\\s*[A-Za-z$_\\n])|(?=\\s*\\.\\.\\.))' + 'match': '\\b((?:[A-Za-z_]\\w*\\s*\\.\\s*)*[A-Z_]\\w*)\\b((?=\\s*[A-Za-z$_\\n])|(?=\\s*\\.\\.\\.))' 'captures': '1': 'patterns': [ { - 'match': '[A-Za-z]\\w*' + 'match': '[A-Za-z_]\\w*' 'name': 'storage.type.java' } { @@ -1423,7 +1423,7 @@ ( \\b(void|boolean|byte|char|short|int|float|long|double)\\b | - (?>(\\w+\\.)*[A-Z]+\\w*) # e.g. `javax.ws.rs.Response`, or `String` + (?>(\\w+\\.)*[A-Z_]+\\w*) # e.g. `javax.ws.rs.Response`, or `String` ) \\s* ( diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 2d63030..1070099 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -828,9 +828,6 @@ describe 'Java grammar', -> {tokens} = grammar.tokenizeLine '1_' expect(tokens[0]).toEqual value: '1_', scopes: ['source.java'] - {tokens} = grammar.tokenizeLine '_1' - expect(tokens[0]).toEqual value: '_1', scopes: ['source.java'] - {tokens} = grammar.tokenizeLine '2639724263Q' expect(tokens[0]).toEqual value: '2639724263Q', scopes: ['source.java'] @@ -1973,6 +1970,26 @@ describe 'Java grammar', -> expect(lines[5][6]).toEqual value: '[', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] expect(lines[5][7]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.bracket.square.java'] + it 'tokenizes storage types with underscore', -> + lines = grammar.tokenizeLines ''' + class _Class { + static _String var1; + static _abc._abc._Class var2; + static _abc._abc._Generic<_String> var3; + } + ''' + + expect(lines[1][3]).toEqual value: '_String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + + expect(lines[2][3]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][5]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[2][7]).toEqual value: '_Class', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + + expect(lines[3][3]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[3][5]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[3][7]).toEqual value: '_Generic', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[3][9]).toEqual value: '_String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.generic.java'] + it 'tokenizes try-catch-finally blocks', -> lines = grammar.tokenizeLines ''' class Test { From 759a0ac02dc091018a112b25a5a6d894918a0aa8 Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 24 Jun 2019 15:36:26 +0200 Subject: [PATCH 31/59] Update regex for `anonymous-classes-and-new` end ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR updates end pattern in `anonymous-classes-and-new` and patches variable scope after constructor, see example below: ```java class A { void func() { long a = new Date().getTime() + start.getTime(); long b = new Date().getTime() - start.getTime(); long c = new Date().getTime() * start.getTime(); long d = new Date().getTime() / start.getTime(); long e = new Date().getTime() & start.getTime(); long f = new Date().getTime() | start.getTime(); boolean g = new Date().getTime() == start.getTime(); boolean h = new Date().getTime() != start.getTime(); } } ``` Note that this is not exhaustive pattern, but should fix most of the cases. ### Alternate Designs None were considered. Note that this issue will not exist once we switch to tree-sitter. ### Benefits Enables correct scope in the case mentioned above. ### Possible Drawbacks Could fix some other highlighting case that is not captured by our tests. ### Applicable Issues Closes #192 --- grammars/java.cson | 2 +- spec/java-spec.coffee | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/grammars/java.cson b/grammars/java.cson index 1cfb084..6db5900 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -191,7 +191,7 @@ 'beginCaptures': '0': 'name': 'keyword.control.new.java' - 'end': '(?=;|\\)|,|:|}|\\+)' + 'end': '(?=;|\\)|,|:|}|\\+|\\-|\\*|\\/|%|!|&|\\||=)' 'patterns': [ { 'include': '#comments' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 1070099..6a4c5d9 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1708,6 +1708,33 @@ describe 'Java grammar', -> expect(lines[6][0]).toEqual value: '}', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.end.bracket.curly.java'] expect(lines[6][1]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + # See issue https://github.com/atom/language-java/issues/192 + lines = grammar.tokenizeLines ''' + class A { + void func() { + long a = new Date().getTime() + start.getTime(); + long b = new Date().getTime() - start.getTime(); + long c = new Date().getTime() * start.getTime(); + long d = new Date().getTime() / start.getTime(); + long e = new Date().getTime() & start.getTime(); + long f = new Date().getTime() | start.getTime(); + boolean g = new Date().getTime() == start.getTime(); + boolean h = new Date().getTime() != start.getTime(); + } + } + ''' + + expected = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] + + expect(lines[2][19]).toEqual value: 'start', scopes: expected + expect(lines[3][19]).toEqual value: 'start', scopes: expected + expect(lines[4][19]).toEqual value: 'start', scopes: expected + expect(lines[5][19]).toEqual value: 'start', scopes: expected + expect(lines[6][19]).toEqual value: 'start', scopes: expected + expect(lines[7][19]).toEqual value: 'start', scopes: expected + expect(lines[8][19]).toEqual value: 'start', scopes: expected + expect(lines[9][19]).toEqual value: 'start', scopes: expected + it 'tokenizes the `instanceof` operator', -> {tokens} = grammar.tokenizeLine 'instanceof' From ed8ad7451b4d0454374885a102dbe63befdea509 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 28 Aug 2019 21:26:12 +0200 Subject: [PATCH 32/59] Fixes order of storage modifiers, so @interface is scoped properly inside a class ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR fixes the issue when `@interface` defined within a class with a storage modifier would not be scoped properly. We change the order of `storage-modifiers` scope to make sure it gets applied before variables scope. ### Alternate Designs None were considered. ### Benefits Fixes scope and highlighting of `@interface` within a class. ### Possible Drawbacks I had to update one of the tests for class fields. Since we apply storage modifiers before variables, we now correctly parse `int` in the test example. ### Applicable Issues Closes #203 --- grammars/java.cson | 4 ++-- spec/java-spec.coffee | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 6db5900..93275fb 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -341,10 +341,10 @@ 'include': '#annotations' } { - 'include': '#member-variables' + 'include': '#storage-modifiers' } { - 'include': '#storage-modifiers' + 'include': '#member-variables' } { 'include': '#code' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 6a4c5d9..8bd261e 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1834,7 +1834,8 @@ describe 'Java grammar', -> expect(lines[9][20]).toEqual value: '12', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'constant.numeric.decimal.java'] expect(lines[9][21]).toEqual value: ']', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'punctuation.bracket.square.java'] - expect(lines[10][2]).toEqual value: ' int 1invalid', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] + expect(lines[10][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'storage.type.primitive.java'] + expect(lines[10][4]).toEqual value: ' 1invalid', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java'] expect(lines[11][3]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[11][5]).toEqual value: '$tar_war$', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] @@ -2679,3 +2680,19 @@ describe 'Java grammar', -> expect(lines[5][1]).toEqual value: '@', scopes: scopes.concat(['punctuation.definition.annotation.java']) expect(lines[5][3]).toEqual value: 'Message', scopes: scopes.concat(['storage.type.annotation.java']) expect(lines[5][6]).toEqual value: 'message', scopes: scopes.concat(['string.quoted.double.java']) + + it 'tokenizes annotations within classes', -> + lines = grammar.tokenizeLines ''' + class A { + private @interface Test { + // comment 1 + public boolean func() default true; + } + } + ''' + + scopes = ['source.java', 'meta.class.java', 'meta.class.body.java'] + expect(lines[1][3]).toEqual value: '@', scopes: scopes.concat(['meta.declaration.annotation.java', 'punctuation.definition.annotation.java']) + expect(lines[1][4]).toEqual value: 'interface', scopes: scopes.concat(['meta.declaration.annotation.java', 'storage.modifier.java']) + expect(lines[2][1]).toEqual value: '//', scopes: scopes.concat(['comment.line.double-slash.java', 'punctuation.definition.comment.java']) + expect(lines[3][5]).toEqual value: 'func', scopes: scopes.concat(['meta.function-call.java', 'entity.name.function.java']) From 123beb50115b0bfb0db8f2325df6d05fb8a016a8 Mon Sep 17 00:00:00 2001 From: CS <45906942+CsCherrYY@users.noreply.github.com> Date: Fri, 11 Oct 2019 00:12:26 +0800 Subject: [PATCH 33/59] Fix Javadoc @link tag highlighting broken issue #206 ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR uses a non-greedy match instead of a greedy match in the highlighting. This change may bring correct highlighting in the Javadoc @link tag when more than one @link tag in the same line. ### Alternate Designs It is a simple fix so no alternate designs were considered. ### Benefits Fix Javadoc @link tag highlighting broken problem. ### Possible Drawbacks None. ### Applicable Issues [#958](https://github.com/redhat-developer/vscode-java/issues/958) --- grammars/java.cson | 2 +- spec/java-spec.coffee | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 93275fb..ee73f80 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -525,7 +525,7 @@ 'name': 'entity.name.type.class.java' } { - 'match': '{(@link)\\s+(\\S+)?#([\\w$]+\\s*\\([^\\(\\)]*\\)).*}' + 'match': '{(@link)\\s+(\\S+)?#([\\w$]+\\s*\\([^\\(\\)]*\\)).*?}' 'captures': '1': 'name': 'keyword.other.documentation.javadoc.java' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 8bd261e..bf8d597 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2520,6 +2520,7 @@ describe 'Java grammar', -> * Use {@link Class#method (int a, int b)} * @link #method() * Use {@link Class#method$(int a) label {@link Class#method()}} + * Use {@link String#charAt(int)} {@link String#chars()} */ public int test() { return -1; } } @@ -2550,7 +2551,19 @@ describe 'Java grammar', -> expect(lines[8][4]).toEqual value: 'Class', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'entity.name.type.class.java'] expect(lines[8][5]).toEqual value: '#', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] expect(lines[8][6]).toEqual value: 'method$(int a)', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'variable.parameter.java'] - expect(lines[8][7]).toEqual value: ' label {@link Class#method()}}', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + expect(lines[8][7]).toEqual value: ' label {@link Class#method()}', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + + expect(lines[9][2]).toEqual value: '@link', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'keyword.other.documentation.javadoc.java'] + expect(lines[9][3]).toEqual value: ' ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + expect(lines[9][4]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'entity.name.type.class.java'] + expect(lines[9][5]).toEqual value: '#', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + expect(lines[9][6]).toEqual value: 'charAt(int)', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'variable.parameter.java'] + expect(lines[9][10]).toEqual value: '@link', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'keyword.other.documentation.javadoc.java'] + expect(lines[9][11]).toEqual value: ' ', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + expect(lines[9][12]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'entity.name.type.class.java'] + expect(lines[9][13]).toEqual value: '#', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] + expect(lines[9][14]).toEqual value: 'chars()', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'variable.parameter.java'] + it 'tokenizes class-body block initializer', -> lines = grammar.tokenizeLines ''' From 6924e64a6959f596904a8021c05deb2592958eab Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Sat, 23 Nov 2019 16:36:27 +0800 Subject: [PATCH 34/59] Parse class identifier containing a dollar char ### Description of the Change `\w` equals to`A-Za-z0-9_`. `$` is not contained, which is allowed to be part of the class identifier. ### Alternate Designs None were considered. ### Benefits Can highlight class name containing `$`. ### Possible Drawbacks I don't see any. ### Applicable Issues https://github.com/redhat-developer/vscode-java/issues/299 Screen Shot 2019-11-21 at 3 09 36 PM --- grammars/java.cson | 4 ++-- spec/java-spec.coffee | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index ee73f80..0432039 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -243,7 +243,7 @@ } ] 'class': - 'begin': '(?=\\w?[\\w\\s]*\\b(?:class|(? Testclass test1 = null; TestClass test2 = null; } + + class A$B { + int a; + } ''' expect(lines[0][0]).toEqual value: 'class', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'storage.modifier.java'] @@ -236,6 +240,8 @@ describe 'Java grammar', -> expect(lines[8][2]).toEqual value: 'Aclass', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'entity.name.type.class.java'] expect(lines[13][1]).toEqual value: 'Testclass', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[14][1]).toEqual value: 'TestClass', scopes: ['source.java', 'meta.definition.variable.java', 'storage.type.java'] + expect(lines[17][0]).toEqual value: 'class', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'storage.modifier.java'] + expect(lines[17][2]).toEqual value: 'A$B', scopes: ['source.java', 'meta.class.java', 'meta.class.identifier.java', 'entity.name.type.class.java'] it 'tokenizes enums', -> lines = grammar.tokenizeLines ''' From ad1456d9aeb4f96ec2c32fb60b323231faa145a1 Mon Sep 17 00:00:00 2001 From: Ye Zhihao Date: Mon, 25 Nov 2019 15:57:20 +0800 Subject: [PATCH 35/59] Comments should not end 'keyword.control.new.java' ### Description of the Change Currently, the divide operator ('/') will end 'keyword.control.new.java' scope. But ('/') could also be the beginning of a comment, and it should not end the scope. ### Alternate Designs No alternative considered. ### Benefits Comment would not affect the highlighting of inner class, as described in #209. ### Possible Drawbacks Nothing as far as I know. ### Applicable Issues Fix #209 --- grammars/java.cson | 2 +- spec/java-spec.coffee | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 0432039..393ff16 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -191,7 +191,7 @@ 'beginCaptures': '0': 'name': 'keyword.control.new.java' - 'end': '(?=;|\\)|,|:|}|\\+|\\-|\\*|\\/|%|!|&|\\||=)' + 'end': '(?=;|\\)|,|:|}|\\+|\\-|\\*|\\/(?!\\/|\\*)|%|!|&|\\||=)' 'patterns': [ { 'include': '#comments' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 362add3..971c4f3 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1688,6 +1688,21 @@ describe 'Java grammar', -> expect(tokens[6]).toEqual value: 'Point', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] expect(tokens[9]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + {tokens} = grammar.tokenizeLine 'new Point() /* JPanel() */ { };' + + expect(tokens[10]).toEqual value: '{', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.begin.bracket.curly.java'] + expect(tokens[11]).toEqual value: ' ', scopes: ['source.java', 'meta.inner-class.java'] + expect(tokens[12]).toEqual value: '}', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.end.bracket.curly.java'] + + lines = grammar.tokenizeLines ''' + new Point() // JPanel() + { } + ''' + + expect(lines[1][0]).toEqual value: '{', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.begin.bracket.curly.java'] + expect(lines[1][1]).toEqual value: ' ', scopes: ['source.java', 'meta.inner-class.java'] + expect(lines[1][2]).toEqual value: '}', scopes: ['source.java', 'meta.inner-class.java', 'punctuation.section.inner-class.end.bracket.curly.java'] + lines = grammar.tokenizeLines ''' map.put(key, new Value(value) @@ -2569,7 +2584,7 @@ describe 'Java grammar', -> expect(lines[9][12]).toEqual value: 'String', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'entity.name.type.class.java'] expect(lines[9][13]).toEqual value: '#', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java'] expect(lines[9][14]).toEqual value: 'chars()', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'comment.block.javadoc.java', 'variable.parameter.java'] - + it 'tokenizes class-body block initializer', -> lines = grammar.tokenizeLines ''' From 47ddbb650f00b80dbf54205a2d27ad2dd7ec9678 Mon Sep 17 00:00:00 2001 From: Ye Zhihao Date: Wed, 27 Nov 2019 03:20:24 +0800 Subject: [PATCH 36/59] More robust enum field's pattern logic ### Description of the Change The original logic uses three different patterns to match an enum constant field. This PR replaces them with a two-scope uniform pattern. ### Alternate Designs To solve #211, an alternative would be to add another to match (constructor + code overrides), but it introduces too much duplicate code, and it still cannot highlight correctly when '{' is placed at new line. ### Benefits * Can correctly highlight with all possible combinations of constructor & code overrides * Can correctly highlight when '{' is placed at new line or with a comment in between * Patterns are more neat and uniform ### Possible Drawbacks * Undetected possible regression issues ### Applicable Issues Fix #211 Fix redhat-developer/vscode-java#974 --- grammars/java.cson | 67 ++++++++++++++++++++++--------------------- spec/java-spec.coffee | 64 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 32 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 393ff16..59b33bd 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -619,49 +619,52 @@ { 'include': '#comments' } - # Represents enum's constant field with the code overrides - { - 'begin': '(\\w+)\\s*({)' + { # Represents enum's constant field entry + 'begin': '\\b(\\w+)\\b' 'beginCaptures': '1': 'name': 'constant.other.enum.java' - '2': - 'name': 'punctuation.bracket.curly.java' - 'end': '\\}' + 'end': '(,)|(?=;|})' 'endCaptures': - '0': - 'name': 'punctuation.bracket.curly.java' + '1': + 'name': 'punctuation.separator.delimiter.java' 'patterns': [ { - # Use #class-body, because the enum field overrides enum class body. - # It is similar to inner class. - 'include': '#class-body' + 'include': '#comments-javadoc' } - ] - } - # Represents enum's constant field with constructor, e.g. `Test(123)` - { - 'begin': '(\\w+)\\s*(\\()' - 'beginCaptures': - '1': - 'name': 'constant.other.enum.java' - '2': - 'name': 'punctuation.bracket.round.java' - 'end': '\\)' - 'endCaptures': - '0': - 'name': 'punctuation.bracket.round.java' - 'patterns': [ { - 'include': '#code' + 'include': '#comments' + } + { # Represents enum's constructor, e.g. `("1", 123)` in `Test("1", 123)` + 'begin': '\\(', + 'beginCaptures': + '0': + 'name': 'punctuation.bracket.round.java' + 'end': '\\)' + 'endCaptures': + '0': + 'name': 'punctuation.bracket.round.java' + 'patterns': [ + 'include': '#code' + ] + } + { # Represents enum's body with code overrides + 'begin': '{', + 'beginCaptures': + '0': + 'name': 'punctuation.bracket.curly.java' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.bracket.curly.java' + 'patterns': [ + # Use #class-body, because the enum field overrides enum class body. + # It is similar to inner class. + 'include': '#class-body' + ] } ] } - # Represents enum's constant field, e.g. `Test` - { - 'match': '\\b\\w+\\b' - 'name': 'constant.other.enum.java' - } ] } { diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 971c4f3..7341a72 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -416,6 +416,70 @@ describe 'Java grammar', -> expect(lines[15][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] expect(lines[15][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + it 'tokenizes enums with method overrides and constructor', -> + lines = grammar.tokenizeLines ''' + enum TYPES { + TYPE_A("1", 1) { + @Override + int func() { + return 1; + } + }, + TYPE_B("2", 2) + { + @Override + int func() { + return 2; + } + }, + TYPE_DEFAULT("3", 3); + + String label; + int value; + + TYPES(String label, int value) { + this.label = label; + this.value = value; + } + + int func() { + return 0; + } + } + ''' + + expect(lines[1][1]).toEqual value: 'TYPE_A', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[1][2]).toEqual value: '(', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[1][3]).toEqual value: '"', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] + expect(lines[1][4]).toEqual value: '1', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java'] + expect(lines[1][5]).toEqual value: '"', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] + expect(lines[1][6]).toEqual value: ',', scopes: ['source.java', 'meta.enum.java', 'punctuation.separator.delimiter.java'] + expect(lines[1][8]).toEqual value: '1', scopes: ['source.java', 'meta.enum.java', 'constant.numeric.decimal.java'] + expect(lines[1][9]).toEqual value: ')', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[1][11]).toEqual value: '{', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + expect(lines[2][2]).toEqual value: 'Override', scopes: ['source.java', 'meta.enum.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] + expect(lines[3][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[3][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[6][1]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + + expect(lines[7][1]).toEqual value: 'TYPE_B', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + expect(lines[7][2]).toEqual value: '(', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[7][3]).toEqual value: '"', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] + expect(lines[7][4]).toEqual value: '2', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java'] + expect(lines[7][5]).toEqual value: '"', scopes: ['source.java', 'meta.enum.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] + expect(lines[7][6]).toEqual value: ',', scopes: ['source.java', 'meta.enum.java', 'punctuation.separator.delimiter.java'] + expect(lines[7][8]).toEqual value: '2', scopes: ['source.java', 'meta.enum.java', 'constant.numeric.decimal.java'] + expect(lines[7][9]).toEqual value: ')', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.round.java'] + expect(lines[8][1]).toEqual value: '{', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] # Begin bracket placed at new line + expect(lines[9][2]).toEqual value: 'Override', scopes: ['source.java', 'meta.enum.java', 'meta.declaration.annotation.java', 'storage.type.annotation.java'] + expect(lines[10][1]).toEqual value: 'int', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.return-type.java', 'storage.type.primitive.java'] + expect(lines[10][3]).toEqual value: 'func', scopes: ['source.java', 'meta.enum.java', 'meta.method.java', 'meta.method.identifier.java', 'entity.name.function.java'] + expect(lines[13][1]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.bracket.curly.java'] + + expect(lines[14][1]).toEqual value: 'TYPE_DEFAULT', scopes: ['source.java', 'meta.enum.java', 'constant.other.enum.java'] + + expect(lines[27][0]).toEqual value: '}', scopes: ['source.java', 'meta.enum.java', 'punctuation.section.enum.end.bracket.curly.java'] # Test that enum scope correctly ends + it 'tokenizes enums with extends and implements', -> lines = grammar.tokenizeLines ''' class A { From b8ace407a8a65b61fe9f3a3ac7fe5ef4d67cac25 Mon Sep 17 00:00:00 2001 From: Ye Zhihao Date: Thu, 28 Nov 2019 04:24:54 +0800 Subject: [PATCH 37/59] Relax the too restrictive begin expression for catch block ### Description of the Change Relax the too restrictive begin expression for catch block for following reasons: * The begin pattern is not suitable for dealing with multi-line pattern. * any comments between `catch` and `(` would also break the highlighting. Leave the catch keywork be would just be fine, since syntax highlighting should only be responsible for happy path. ### Alternate Designs Any other design would introduce new complexity. ### Benefits * Can correctly highlight when caught exceptions are split in multiple lines * Can correctly highlight when '(' is placed in a new line after `catch` * Can correctly highlight when there is comment between `catch` and '(' * Reduces the complexity ### Possible Drawbacks More like a `right` hightlight for wrong syntax in code. ### Applicable Issues Fix #205 FIx https://github.com/microsoft/vscode-java-pack/issues/259 --- grammars/java.cson | 7 +++++-- spec/java-spec.coffee | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 59b33bd..cdb3b5a 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1334,9 +1334,9 @@ } ] } - # catch block (with "parameters") + # catch block { - 'begin': '\\b(catch)\\b\\s*(?=\\(\\s*[^\\s]+\\s*[^)]+\\))' + 'begin': '\\b(catch)\\b' 'beginCaptures': '1': 'name': 'keyword.control.catch.java' @@ -1346,6 +1346,9 @@ 'name': 'punctuation.section.catch.end.bracket.curly.java' 'name': 'meta.catch.java' 'patterns': [ + { + 'include': '#comments' + } { 'begin': '\\(' 'beginCaptures': diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 7341a72..2fef8d9 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2341,6 +2341,33 @@ describe 'Java grammar', -> expect(lines[5][12]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] expect(lines[5][13]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + lines = grammar.tokenizeLines ''' + class Test + { + private void method() { + try { + // do something + } catch // this is a catch + (Exception1 | + Exception2 + | Exception3 err) { + throw new Exception3(); + } + } + } + ''' + + expect(lines[5][3]).toEqual value: 'catch', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'keyword.control.catch.java'] + expect(lines[5][5]).toEqual value: '//', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java'] + expect(lines[6][1]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[6][2]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[6][4]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator.java'] + expect(lines[7][1]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[8][1]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator.java'] + expect(lines[8][3]).toEqual value: 'Exception3', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[8][5]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] + expect(lines[8][6]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + it 'tokenizes list of exceptions in method throws clause', -> lines = grammar.tokenizeLines ''' class Test { From f8b9d681eb6a86be15082d68dccbcd218c7a5c46 Mon Sep 17 00:00:00 2001 From: Ye Zhihao Date: Thu, 28 Nov 2019 15:46:32 +0800 Subject: [PATCH 38/59] Provide additional stop conditions for 'anonymous-classes-and-new' pattern ### Description of the Change * Dot should also end 'anonymous-classes-and-new', in order to propery highlight method call of temporary variable created by 'new'. * Question mark should also end 'anonymous-classes-and-new', in order to proper break out circumstances like `new Random() ? true : false`; * Right square brace should also end 'anonymous-classes-and-new', for circumstances like `[new Random()]`. * Xor should also end `anonymous-classes-and-new`, for circumstances like `new Integer(1) ^ new Integer(2)`. ### Alternate Designs ~~Non was considered.~~ Having to enumerate these much punctuations made me think of proposing a general and simple regex to end new expression. But soon I found out that I couldn't find a way to tell when `)` or `]` is met, whether there will be a `{}` block next to it. ### Benefits * The meaning of dot method call by variable and new-variable is consistent. * Every punctuation that could end a new expression is covered. ### Possible Drawbacks No obvious drawback. ### Applicable Issues Fix #213 -> dot Fix #179 -> question mark Fix #180 -> right square Fix #192 -> xor --- grammars/java.cson | 2 +- spec/java-spec.coffee | 54 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index cdb3b5a..3336e25 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -191,7 +191,7 @@ 'beginCaptures': '0': 'name': 'keyword.control.new.java' - 'end': '(?=;|\\)|,|:|}|\\+|\\-|\\*|\\/(?!\\/|\\*)|%|!|&|\\||=)' + 'end': '(?=;|\\)|\\]|\\.|,|\\?|:|}|\\+|\\-|\\*|\\/(?!\\/|\\*)|%|!|&|\\||\\^|=)' 'patterns': [ { 'include': '#comments' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 2fef8d9..a6747d0 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1705,9 +1705,10 @@ describe 'Java grammar', -> {tokens} = grammar.tokenizeLine 'String a = (valid ? new Date().toString() + " : " : "");' - expect(tokens[16]).toEqual value: 'toString', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[15]).toEqual value: '.', scopes: ['source.java', 'meta.method-call.java', 'punctuation.separator.period.java'] + expect(tokens[16]).toEqual value: 'toString', scopes: ['source.java', 'meta.method-call.java', 'entity.name.function.java'] + expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.method-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.method-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] expect(tokens[20]).toEqual value: '+', scopes: ['source.java', 'keyword.operator.arithmetic.java'] expect(tokens[23]).toEqual value: ' : ', scopes: ['source.java', 'string.quoted.double.java'] expect(tokens[26]).toEqual value: ':', scopes: ['source.java', 'keyword.control.ternary.java'] @@ -1737,6 +1738,17 @@ describe 'Java grammar', -> expect(tokens[22]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] expect(tokens[31]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + {tokens} = grammar.tokenizeLine 'Point point = new Random() ? new Point(1, 4) : new Point(0, 0);' + + expect(tokens[12]).toEqual value: '?', scopes: ['source.java', 'keyword.control.ternary.java'] + expect(tokens[14]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[16]).toEqual value: 'Point', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[22]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[24]).toEqual value: ':', scopes: ['source.java', 'keyword.control.ternary.java'] + expect(tokens[26]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[35]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + {tokens} = grammar.tokenizeLine 'map.put(key, new Value(value), "extra");' expect(tokens[12]).toEqual value: ')', scopes: ['source.java', 'meta.method-call.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] @@ -1803,6 +1815,7 @@ describe 'Java grammar', -> long d = new Date().getTime() / start.getTime(); long e = new Date().getTime() & start.getTime(); long f = new Date().getTime() | start.getTime(); + long g = new Date().getTime() ^ start.getTime(); boolean g = new Date().getTime() == start.getTime(); boolean h = new Date().getTime() != start.getTime(); } @@ -1819,6 +1832,41 @@ describe 'Java grammar', -> expect(lines[7][19]).toEqual value: 'start', scopes: expected expect(lines[8][19]).toEqual value: 'start', scopes: expected expect(lines[9][19]).toEqual value: 'start', scopes: expected + expect(lines[10][19]).toEqual value: 'start', scopes: expected + + # See issue https://github.com/atom/language-java/issues/180 + lines = grammar.tokenizeLines ''' + public class A { + void f() { + int a = 1; + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + int a = 1; + } + + void g(Object o) { + int a = 1; + } + } + ''' + + expected = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.function-call.java', 'entity.name.function.java'] + + expect(lines[3][1]).toEqual value: 'g', scopes: expected + expect(lines[4][1]).toEqual value: 'g', scopes: expected + expect(lines[5][1]).toEqual value: 'g', scopes: expected + expect(lines[6][1]).toEqual value: 'g', scopes: expected + expect(lines[7][1]).toEqual value: 'g', scopes: expected + expect(lines[8][1]).toEqual value: 'g', scopes: expected + expect(lines[9][1]).toEqual value: 'g', scopes: expected + expect(lines[10][1]).toEqual value: 'g', scopes: expected + expect(lines[15][3]).toEqual value: 'a', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.definition.variable.java', 'variable.other.definition.java'] it 'tokenizes the `instanceof` operator', -> {tokens} = grammar.tokenizeLine 'instanceof' From e0672a9392babc212d0ecf084959efb30f596a67 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 28 Nov 2019 09:18:27 +0100 Subject: [PATCH 39/59] Update test for #180 ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change Refactors and moves the test case for #180 into a separate test. ### Alternate Designs N/A ### Benefits N/A ### Possible Drawbacks N/A ### Applicable Issues Relates to #180 --- spec/java-spec.coffee | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index a6747d0..b07e0d8 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1834,25 +1834,26 @@ describe 'Java grammar', -> expect(lines[9][19]).toEqual value: 'start', scopes: expected expect(lines[10][19]).toEqual value: 'start', scopes: expected + it 'checks that accessor + new operator do not introduce extra scopes', -> # See issue https://github.com/atom/language-java/issues/180 lines = grammar.tokenizeLines ''' public class A { - void f() { - int a = 1; - g(education[new Random()]); - g(education[new Random()]); - g(education[new Random()]); - g(education[new Random()]); - g(education[new Random()]); - g(education[new Random()]); - g(education[new Random()]); - g(education[new Random()]); - int a = 1; - } + void f() { + int a = 1; + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + g(education[new Random()]); + int a = 1; + } - void g(Object o) { - int a = 1; - } + void g(Object o) { + int a = 1; + } } ''' @@ -2079,6 +2080,7 @@ describe 'Java grammar', -> java.lang.String[] arr; } ''' + expect(lines[1][3]).toEqual value: 'Test', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] expect(lines[1][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'punctuation.separator.period.java'] expect(lines[1][5]).toEqual value: 'Double', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.definition.variable.java', 'storage.type.java'] From fd80fc8b701bf5dd6ddaf8d15a2698c70f79e732 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Thu, 28 Nov 2019 21:11:44 +0100 Subject: [PATCH 40/59] Prepare 0.31.4 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 69bef98..b876444 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.31.3", + "version": "0.31.4", "description": "Java language support in Atom", "engines": { "atom": "*", From 0facf7cbe02cda460db1160fd730f2e57bf15c36 Mon Sep 17 00:00:00 2001 From: Ye Zhihao Date: Mon, 9 Dec 2019 01:17:30 +0800 Subject: [PATCH 41/59] Fix catch parameter highlighting (#220) ### Description of the Change Uses a two-scope begin/end model to correctly highlight catch parameter. It wraps `Exception ... |` or `Exception ... )` as a scope, allowing parameter to only sit in this scope, to resolve the parsing sequence issue (first exception type, then parameter identifier). ### Alternate Designs #### A more complex two-scope design: * scope 1: `(...Exception` * scope 2: `|...Exception` * scope 3: `parameter...)` Problem: cannot correctly highlight when there's a storage-modifer (like final) #### Recursive design: ```yaml catch-parameters: begin: /(?<=\()|(\|)/ beginCapture.0.name: 'catch.separator' end: /(?=\))/ patterns: - include: storage-modifier - include: exception-type - include: catch-parameters # recursive - include: paramter-identifier ``` It makes use of the fact that `catch (ex1 | ex2 | ex3 param)` is in terms of structure the same as `catch (ex1 (ex2 (ex3 param)` (every time a `|` is met, the remaining part is actually a new catch-parameter pattern) Problem: still cannot elegantly handle the base case: `catch (final ex3 param)`. ### Benefits Can correctly highlight catch parameter when it is placed in new line or with a comment in between. ### Possible Drawbacks Don't see any afak. ### Applicable Issues Fix #219 --- grammars/java.cson | 27 +++++++++++++------- spec/java-spec.coffee | 58 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 3336e25..165488d 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1367,16 +1367,25 @@ 'include': '#storage-modifiers' } { - 'match': '\\|' - 'name': 'punctuation.catch.separator.java' - } - { - 'match': '([a-zA-Z$_][\\.a-zA-Z0-9$_]*)\\s*(\\w+)?' - 'captures': - '1': + 'begin': '[a-zA-Z$_][\\.a-zA-Z0-9$_]*' + 'beginCaptures': + '0': 'name': 'storage.type.java' - '2': - 'name': 'variable.parameter.java' + 'end': '(\\|)|(?=\\))' + 'endCaptures': + '1': + 'name': 'punctuation.catch.separator.java' + 'patterns': [ + { + 'include': '#comments' + } + { + 'match': '\\w+' + 'captures': + '0': + 'name': 'variable.parameter.java' + } + ] } ] } diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index b07e0d8..ac213ab 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2418,6 +2418,64 @@ describe 'Java grammar', -> expect(lines[8][5]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] expect(lines[8][6]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + it 'tokenizes catch parameter in new line or with a comment in between', -> + lines = grammar.tokenizeLines ''' + class Test + { + private void method() { + try { + // do something + } catch // this is a catch + (Exception1 /* exception 1 */ | + final Exception2 // exception 2 + err // this is a error + /* end */) { + throw new Exception3(); + } + } + } + ''' + + expect(lines[5][3]).toEqual value: 'catch', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'keyword.control.catch.java'] + expect(lines[5][5]).toEqual value: '//', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java'] + expect(lines[6][1]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[6][2]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[6][4]).toEqual value: '/*', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.block.java', 'punctuation.definition.comment.java'] + expect(lines[6][8]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator.java'] + expect(lines[7][1]).toEqual value: 'final', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.modifier.java'] + expect(lines[7][3]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[7][5]).toEqual value: '//', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java'] + expect(lines[8][1]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] + expect(lines[8][3]).toEqual value: '//', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java'] + expect(lines[9][1]).toEqual value: '/*', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.block.java', 'punctuation.definition.comment.java'] + expect(lines[9][4]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + + lines = grammar.tokenizeLines ''' + class Test + { + private void method() { + try { + // do something + } catch (/* comment */ Exception1 /* comment */ | final Exception2 /* comment */ err /* comment */) { + throw new Exception3(); + } + } + } + ''' + + expect(lines[5][3]).toEqual value: 'catch', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'keyword.control.catch.java'] + expect(lines[5][5]).toEqual value: '(', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[5][6]).toEqual value: '/*', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.block.java', 'punctuation.definition.comment.java'] + expect(lines[5][10]).toEqual value: 'Exception1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[5][12]).toEqual value: '/*', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.block.java', 'punctuation.definition.comment.java'] + expect(lines[5][16]).toEqual value: '|', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'punctuation.catch.separator.java'] + expect(lines[5][18]).toEqual value: 'final', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.modifier.java'] + expect(lines[5][20]).toEqual value: 'Exception2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'storage.type.java'] + expect(lines[5][22]).toEqual value: '/*', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.block.java', 'punctuation.definition.comment.java'] + expect(lines[5][26]).toEqual value: 'err', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'variable.parameter.java'] + expect(lines[5][28]).toEqual value: '/*', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'meta.catch.parameters.java', 'comment.block.java', 'punctuation.definition.comment.java'] + expect(lines[5][31]).toEqual value: ')', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.catch.java', 'punctuation.definition.parameters.end.bracket.round.java'] + it 'tokenizes list of exceptions in method throws clause', -> lines = grammar.tokenizeLines ''' class Test { From eb6d555d3621c00ab11ca37969a356415af6de44 Mon Sep 17 00:00:00 2001 From: Ye Zhihao Date: Thu, 26 Mar 2020 02:29:13 +0800 Subject: [PATCH 42/59] Fix array initializer highlighting (#215) ### Description of the Change Similar to #212, it uses a two-scope pattern to distinguish `inner-class` block and `array-initializer` block. it is based on #214 to provide correct end regex for `inner-class` and `array-initializer`. #### Detailed description Conside how a syntax scope terminates: ``` new Class() ^~~~~ terminate here new Class[] ^~~~~ terminate here new Class() {} ^~~~~ terminate here new Class[] {} ^~~~~ terminate here ``` Previous new-expr grammar handles following ways of termination: * inner-class: `(? expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] expect(tokens[10]).toEqual value: 'String', scopes: ['source.java', 'storage.type.object.array.java'] - expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'punctuation.bracket.curly.java'] - expect(tokens[14]).toEqual value: '"', scopes: ['source.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] - expect(tokens[15]).toEqual value: 'hi', scopes: ['source.java', 'string.quoted.double.java'] - expect(tokens[16]).toEqual value: '"', scopes: ['source.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] - expect(tokens[17]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter.java'] - expect(tokens[18]).toEqual value: ' ', scopes: ['source.java'] - expect(tokens[27]).toEqual value: '}', scopes: ['source.java', 'punctuation.bracket.curly.java'] + expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.begin.bracket.curly.java'] + expect(tokens[14]).toEqual value: '"', scopes: ['source.java', 'meta.array-initializer.java', 'string.quoted.double.java', 'punctuation.definition.string.begin.java'] + expect(tokens[15]).toEqual value: 'hi', scopes: ['source.java', 'meta.array-initializer.java', 'string.quoted.double.java'] + expect(tokens[16]).toEqual value: '"', scopes: ['source.java', 'meta.array-initializer.java', 'string.quoted.double.java', 'punctuation.definition.string.end.java'] + expect(tokens[17]).toEqual value: ',', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.separator.delimiter.java'] + expect(tokens[18]).toEqual value: ' ', scopes: ['source.java', 'meta.array-initializer.java'] + expect(tokens[27]).toEqual value: '}', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.end.bracket.curly.java'] expect(tokens[28]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] {tokens} = grammar.tokenizeLine 'A[] arr = new A[]{new A(), new A()};' expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] expect(tokens[10]).toEqual value: 'A', scopes: ['source.java', 'storage.type.object.array.java'] - expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'punctuation.bracket.curly.java'] - expect(tokens[14]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] - expect(tokens[16]).toEqual value: 'A', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[21]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] - expect(tokens[23]).toEqual value: 'A', scopes: ['source.java', 'meta.function-call.java', 'entity.name.function.java'] - expect(tokens[24]).toEqual value: '(', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] - expect(tokens[25]).toEqual value: ')', scopes: ['source.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] - expect(tokens[26]).toEqual value: '}', scopes: ['source.java', 'punctuation.bracket.curly.java'] + expect(tokens[13]).toEqual value: '{', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.begin.bracket.curly.java'] + expect(tokens[14]).toEqual value: 'new', scopes: ['source.java', 'meta.array-initializer.java', 'keyword.control.new.java'] + expect(tokens[16]).toEqual value: 'A', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[17]).toEqual value: '(', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[18]).toEqual value: ')', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[21]).toEqual value: 'new', scopes: ['source.java', 'meta.array-initializer.java', 'keyword.control.new.java'] + expect(tokens[23]).toEqual value: 'A', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[24]).toEqual value: '(', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[25]).toEqual value: ')', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[26]).toEqual value: '}', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.end.bracket.curly.java'] expect(tokens[27]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + {tokens} = grammar.tokenizeLine 'A[] arr = new A[2] { new A(), new A() };' + + expect(tokens[8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(tokens[10]).toEqual value: 'A', scopes: ['source.java', 'storage.type.object.array.java'] + expect(tokens[15]).toEqual value: '{', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.begin.bracket.curly.java'] + expect(tokens[17]).toEqual value: 'new', scopes: ['source.java', 'meta.array-initializer.java', 'keyword.control.new.java'] + expect(tokens[19]).toEqual value: 'A', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[20]).toEqual value: '(', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[21]).toEqual value: ')', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[24]).toEqual value: 'new', scopes: ['source.java', 'meta.array-initializer.java', 'keyword.control.new.java'] + expect(tokens[26]).toEqual value: 'A', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(tokens[27]).toEqual value: '(', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(tokens[28]).toEqual value: ')', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(tokens[30]).toEqual value: '}', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.end.bracket.curly.java'] + expect(tokens[31]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + + lines = grammar.tokenizeLines ''' + A[] arr = new A[2] // new A() + { // new A() + new A(), + new A() + }; + ''' + + expect(lines[0][8]).toEqual value: 'new', scopes: ['source.java', 'keyword.control.new.java'] + expect(lines[0][10]).toEqual value: 'A', scopes: ['source.java', 'storage.type.object.array.java'] + expect(lines[0][15]).toEqual value: '//', scopes: ['source.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java'] + expect(lines[1][0]).toEqual value: '{', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.begin.bracket.curly.java'] + expect(lines[1][2]).toEqual value: '//', scopes: ['source.java', 'meta.array-initializer.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java'] + expect(lines[2][1]).toEqual value: 'new', scopes: ['source.java', 'meta.array-initializer.java', 'keyword.control.new.java'] + expect(lines[2][3]).toEqual value: 'A', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(lines[2][4]).toEqual value: '(', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[2][5]).toEqual value: ')', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(lines[3][1]).toEqual value: 'new', scopes: ['source.java', 'meta.array-initializer.java', 'keyword.control.new.java'] + expect(lines[3][3]).toEqual value: 'A', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'entity.name.function.java'] + expect(lines[3][4]).toEqual value: '(', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.begin.bracket.round.java'] + expect(lines[3][5]).toEqual value: ')', scopes: ['source.java', 'meta.array-initializer.java', 'meta.function-call.java', 'punctuation.definition.parameters.end.bracket.round.java'] + expect(lines[4][0]).toEqual value: '}', scopes: ['source.java', 'meta.array-initializer.java', 'punctuation.section.array-initializer.end.bracket.curly.java'] + expect(lines[4][1]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.java'] + {tokens} = grammar.tokenizeLine 'A[] arr = {new A(), new A()};' expect(tokens[8]).toEqual value: '{', scopes: ['source.java', 'punctuation.section.block.begin.bracket.curly.java'] From d0373f1f6dda31c94b2d032b55056eedb9ecbe69 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 2 Apr 2020 08:16:28 +0200 Subject: [PATCH 43/59] Update scope for object properties #225 ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR removes usage of `variable.other.property.java`, replaces it with `variable.other.object.property.java`. Having `variable.other.property.java` does not make sense since there is no property call without an object/instance. This change unifies object with properties in terms of scope, see below: Before ```java object.property1.property2 // would result in // object => [variable.other.object.java] // property1 => [variable.other.object.property.java] // property2 => [variable.other.property.java] ``` After ```java object.property1.property2 // would result in // object => [variable.other.object.java] // property1 => [variable.other.object.property.java] // property2 => [variable.other.object.property.java] ``` The same is applicable for `object.property`: Before: ``` [variable.other.object.java].[variable.other.property.java] ``` After: ``` [variable.other.object.java].[variable.other.object.property.java] ``` ### Alternate Designs None were considered. ### Benefits Makes the grammar consistent, all properties get scope `variable.other.object.property.java`. Allows syntax highlighting to rely on the fact that all properties will have this scope. ### Possible Drawbacks Could potentially break syntax highlighting that relies on separation between trailing and non-trailing properties. ### Applicable Issues Closes #224 --- grammars/java.cson | 2 +- spec/java-spec.coffee | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 4a9ac78..bf2a234 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1244,7 +1244,7 @@ '1': 'name': 'punctuation.separator.period.java' '2': - 'name': 'variable.other.property.java' + 'name': 'variable.other.object.property.java' } { # 123illegal in obj.123illegal, func().123illegal diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 2ef6a00..68f147f 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -601,7 +601,7 @@ describe 'Java grammar', -> expect(lines[3][1]).toEqual value: '{', scopes: scopeStack.concat ['punctuation.section.method.begin.bracket.curly.java'] expect(lines[4][1]).toEqual value: 'super', scopes: scopeStack.concat ['meta.method.body.java', 'variable.language.java'] expect(lines[5][1]).toEqual value: 'this', scopes: scopeStack.concat ['meta.method.body.java', 'variable.language.this.java'] - expect(lines[5][3]).toEqual value: 'prop', scopes: scopeStack.concat ['meta.method.body.java', 'variable.other.property.java'] + expect(lines[5][3]).toEqual value: 'prop', scopes: scopeStack.concat ['meta.method.body.java', 'variable.other.object.property.java'] expect(lines[6][1]).toEqual value: '}', scopes: scopeStack.concat ['punctuation.section.method.end.bracket.curly.java'] expect(lines[8][1]).toEqual value: 'public', scopes: scopeStack.concat ['storage.modifier.java'] @@ -1355,26 +1355,26 @@ describe 'Java grammar', -> expect(lines[4][1]).toEqual value: 'object', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] expect(lines[4][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'punctuation.separator.period.java'] - expect(lines[4][3]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.property.java'] + expect(lines[4][3]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[4][4]).toEqual value: ';', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'punctuation.terminator.java'] expect(lines[5][1]).toEqual value: 'object', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] - expect(lines[5][3]).toEqual value: 'Property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.property.java'] + expect(lines[5][3]).toEqual value: 'Property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[6][1]).toEqual value: 'Object', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] expect(lines[7][1]).toEqual value: 'object', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] - expect(lines[7][5]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.property.java'] + expect(lines[7][5]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[8][1]).toEqual value: '$object', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] - expect(lines[8][3]).toEqual value: '$property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.property.java'] + expect(lines[8][3]).toEqual value: '$property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[9][3]).toEqual value: 'property1', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] - expect(lines[9][5]).toEqual value: 'property2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.property.java'] + expect(lines[9][5]).toEqual value: 'property2', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[10][1]).toEqual value: 'object', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.java'] expect(lines[10][3]).toEqual value: 'method', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.method-call.java', 'entity.name.function.java'] - expect(lines[10][7]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.property.java'] + expect(lines[10][7]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[11][3]).toEqual value: 'property', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'variable.other.object.property.java'] expect(lines[11][5]).toEqual value: 'method', scopes: ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'meta.method-call.java', 'entity.name.function.java'] From 2e179ceac423403eb5bf0eff26884093c3edba6f Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Sat, 4 Apr 2020 19:55:48 +0800 Subject: [PATCH 44/59] Support for Java 14's Record (#226) ### Description of the Change Support "record" for Java 14, see #223 . Below are covered cases. ``` 1. basic declaration record Point() {} 2. having record constructor, meanwhile not breaking member functions public record Point(int x, int y) { public Point { // validation } private void foo() { } } 3. implemeting interfaces public record Point(int x) implements IA, IB {} 4. defined inner another class class A { record Point() {} } ``` ### Alternate Designs N/A ### Benefits Support to hightlight 'record' ### Possible Drawbacks new rules are limited to 'record' declarations, and are supposed not to causing any no regression. ### Applicable Issues Closes #223 --- grammars/java.cson | 124 ++++++++++++++++++++++++++++++++++++++++++ spec/java-spec.coffee | 93 +++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index bf2a234..3fa705a 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -417,6 +417,9 @@ { 'include': '#class' } + { + 'include': '#record' # Java 14 + } { 'include': '#anonymous-block-and-instance-initializer' } @@ -1256,6 +1259,127 @@ 'name': 'invalid.illegal.identifier.java' } ] + # Java 14 Record + # see spec http://openjdk.java.net/jeps/359 + 'record': + 'begin': '(?=\\w?[\\w\\s]*\\b(?:record)\\s+[\\w$]+)' + 'end': '}' + 'endCaptures': + '0': + 'name': 'punctuation.section.class.end.bracket.curly.java' + 'name': 'meta.record.java' + 'patterns': [ + { + 'include': '#storage-modifiers' + } + { + 'include': '#generics' + } + { + 'include': '#comments' + } + { + 'begin': '(record)\\s+([\\w$]+)(<[\\w$]+>)?(\\()' + 'beginCaptures': + '1': + 'name': 'storage.modifier.java' + '2': + 'name': 'entity.name.type.record.java' + '3': + 'patterns': [ + { + 'include': '#generics' + } + ] + '4': + 'name': 'punctuation.definition.parameters.begin.bracket.round.java' + 'end': '\\)' + 'endCaptures': + '0': + 'name': 'punctuation.definition.parameters.end.bracket.round.java' + 'name': 'meta.record.identifier.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + { + 'begin': '(implements)\\s' + 'beginCaptures': + '1': + 'name': 'storage.modifier.implements.java' + 'end': '(?=\\s*\\{)' # by design, records cannot extend any other class + 'name': 'meta.definition.class.implemented.interfaces.java' + 'patterns': [ + { + 'include': '#object-types-inherited' + } + { + 'include': '#comments' + } + ] + } + { + 'include': '#record-body' + } + ] + 'record-body': + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.class.begin.bracket.curly.java' + 'end': '(?=})' + 'name': 'meta.record.body.java' + 'patterns': [ + { + 'include': '#record-constructor' + } + { + 'include': '#class-body' + } + ] + 'record-constructor': + 'begin': '(?!new)(?=[\\w<].*\\s+)(?=([^\\(=/]|/(?!/))+(?={))' + 'end': '(})|(?=;)' + 'endCaptures': + '1': + 'name': 'punctuation.section.method.end.bracket.curly.java' + 'name': 'meta.method.java' + 'patterns': [ + { + 'include': '#storage-modifiers' + } + { + 'begin': '(\\w+)' + 'beginCaptures': + '1': + 'name': 'entity.name.function.java' + 'end': '(?=\\s*{)' + 'name': 'meta.method.identifier.java' + 'patterns': [ + { + 'include': '#comments' + } + ] + } + { + 'include': '#comments' + } + { + 'begin': '{' + 'beginCaptures': + '0': + 'name': 'punctuation.section.method.begin.bracket.curly.java' + 'end': '(?=})' + 'contentName': 'meta.method.body.java' + 'patterns': [ + { + 'include': '#code' + } + ] + } + ] 'static-initializer': 'patterns': [ { diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 68f147f..a44e2d5 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2969,3 +2969,96 @@ describe 'Java grammar', -> expect(lines[1][4]).toEqual value: 'interface', scopes: scopes.concat(['meta.declaration.annotation.java', 'storage.modifier.java']) expect(lines[2][1]).toEqual value: '//', scopes: scopes.concat(['comment.line.double-slash.java', 'punctuation.definition.comment.java']) expect(lines[3][5]).toEqual value: 'func', scopes: scopes.concat(['meta.function-call.java', 'entity.name.function.java']) + + it 'tokenizes Java 14 records', -> + lines = grammar.tokenizeLines ''' + record Point() {} + ''' + recordScopes = ['source.java', 'meta.record.java'] + expect(lines[0][0]).toEqual value: 'record', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.modifier.java']) + expect(lines[0][2]).toEqual value: 'Point', scopes: recordScopes.concat(['meta.record.identifier.java', 'entity.name.type.record.java']) + expect(lines[0][3]).toEqual value: '(', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java']) + expect(lines[0][4]).toEqual value: ')', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java']) + expect(lines[0][6]).toEqual value: '{', scopes: recordScopes.concat(['meta.record.body.java', 'punctuation.section.class.begin.bracket.curly.java']) + expect(lines[0][7]).toEqual value: '}', scopes: recordScopes.concat(['punctuation.section.class.end.bracket.curly.java']) + + it 'tokenizes Java 14 record implementing other interfaces', -> + lines = grammar.tokenizeLines ''' + public record Point(int x) implements IA, IB {} + ''' + recordScopes = ['source.java', 'meta.record.java'] + expect(lines[0][0]).toEqual value: 'public', scopes: recordScopes.concat(['storage.modifier.java']) + expect(lines[0][2]).toEqual value: 'record', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.modifier.java']) + expect(lines[0][4]).toEqual value: 'Point', scopes: recordScopes.concat(['meta.record.identifier.java', 'entity.name.type.record.java']) + expect(lines[0][5]).toEqual value: '(', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java']) + expect(lines[0][6]).toEqual value: 'int', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.type.primitive.java']) + expect(lines[0][8]).toEqual value: ')', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java']) + expect(lines[0][10]).toEqual value: 'implements', scopes: recordScopes.concat(['meta.definition.class.implemented.interfaces.java', 'storage.modifier.implements.java']) + expect(lines[0][12]).toEqual value: 'IA', scopes: recordScopes.concat(['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java']) + expect(lines[0][13]).toEqual value: ',', scopes: recordScopes.concat(['meta.definition.class.implemented.interfaces.java', 'punctuation.separator.delimiter.java']) + expect(lines[0][15]).toEqual value: 'IB', scopes: recordScopes.concat(['meta.definition.class.implemented.interfaces.java', 'entity.other.inherited-class.java']) + expect(lines[0][17]).toEqual value: '{', scopes: recordScopes.concat(['meta.record.body.java', 'punctuation.section.class.begin.bracket.curly.java']) + expect(lines[0][18]).toEqual value: '}', scopes: recordScopes.concat(['punctuation.section.class.end.bracket.curly.java']) + + it 'tokenizes Java 14 record with generic types as parameters', -> + lines = grammar.tokenizeLines ''' + public record Point(T x) { } + ''' + recordScopes = ['source.java', 'meta.record.java'] + expect(lines[0][0]).toEqual value: 'public', scopes: recordScopes.concat(['storage.modifier.java']) + expect(lines[0][2]).toEqual value: 'record', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.modifier.java']) + expect(lines[0][4]).toEqual value: 'Point', scopes: recordScopes.concat(['meta.record.identifier.java', 'entity.name.type.record.java']) + expect(lines[0][5]).toEqual value: '<', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.bracket.angle.java']) + expect(lines[0][6]).toEqual value: 'T', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.type.generic.java']) + expect(lines[0][7]).toEqual value: '>', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.bracket.angle.java']) + expect(lines[0][8]).toEqual value: '(', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java']) + expect(lines[0][9]).toEqual value: 'T', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.type.java']) + expect(lines[0][11]).toEqual value: ')', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java']) + expect(lines[0][13]).toEqual value: '{', scopes: recordScopes.concat(['meta.record.body.java', 'punctuation.section.class.begin.bracket.curly.java']) + expect(lines[0][15]).toEqual value: '}', scopes: recordScopes.concat(['punctuation.section.class.end.bracket.curly.java']) + + it 'tokenizes Java 14 record construtor', -> + lines = grammar.tokenizeLines ''' + public record Point(int x, int y) { + public Point { + // validation + } + private void foo() { } + } + ''' + recordScopes = ['source.java', 'meta.record.java'] + expect(lines[0][0]).toEqual value: 'public', scopes: recordScopes.concat(['storage.modifier.java']) + expect(lines[0][2]).toEqual value: 'record', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.modifier.java']) + expect(lines[0][4]).toEqual value: 'Point', scopes: recordScopes.concat(['meta.record.identifier.java', 'entity.name.type.record.java']) + expect(lines[0][5]).toEqual value: '(', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java']) + expect(lines[0][6]).toEqual value: 'int', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.type.primitive.java']) + expect(lines[0][8]).toEqual value: ',', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.separator.delimiter.java']) + expect(lines[0][10]).toEqual value: 'int', scopes: recordScopes.concat(['meta.record.identifier.java', 'storage.type.primitive.java']) + expect(lines[0][12]).toEqual value: ')', scopes: recordScopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java']) + expect(lines[0][14]).toEqual value: '{', scopes: recordScopes.concat(['meta.record.body.java', 'punctuation.section.class.begin.bracket.curly.java']) + expect(lines[5][0]).toEqual value: '}', scopes: recordScopes.concat(['punctuation.section.class.end.bracket.curly.java']) + + methodScopes = recordScopes.concat(['meta.record.body.java', 'meta.method.java']) + expect(lines[1][1]).toEqual value: 'public', scopes: methodScopes.concat(['storage.modifier.java']) + expect(lines[1][3]).toEqual value: 'Point', scopes: methodScopes.concat(['meta.method.identifier.java', 'entity.name.function.java']) + expect(lines[1][5]).toEqual value: '{', scopes: methodScopes.concat(['punctuation.section.method.begin.bracket.curly.java']) + expect(lines[2][1]).toEqual value: '//', scopes: methodScopes.concat(['meta.method.body.java', 'comment.line.double-slash.java', 'punctuation.definition.comment.java']) + expect(lines[3][1]).toEqual value: '}', scopes: methodScopes.concat(['punctuation.section.method.end.bracket.curly.java']) + expect(lines[4][1]).toEqual value: 'private', scopes: methodScopes.concat(['storage.modifier.java']) + expect(lines[4][3]).toEqual value: 'void', scopes: methodScopes.concat(['meta.method.return-type.java', 'storage.type.primitive.java']) + expect(lines[4][5]).toEqual value: 'foo', scopes: methodScopes.concat(['meta.method.identifier.java', 'entity.name.function.java']) + + it 'tokenizes Java 14 record as an inner class', -> + lines = grammar.tokenizeLines ''' + class A { + record Point() {} + } + ''' + + scopes = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.record.java'] + expect(lines[1][1]).toEqual value: 'record', scopes: scopes.concat(['meta.record.identifier.java', 'storage.modifier.java']) + expect(lines[1][3]).toEqual value: 'Point', scopes: scopes.concat(['meta.record.identifier.java', 'entity.name.type.record.java']) + expect(lines[1][4]).toEqual value: '(', scopes: scopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.begin.bracket.round.java']) + expect(lines[1][5]).toEqual value: ')', scopes: scopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java']) + expect(lines[1][7]).toEqual value: '{', scopes: scopes.concat(['meta.record.body.java', 'punctuation.section.class.begin.bracket.curly.java']) + expect(lines[1][8]).toEqual value: '}', scopes: scopes.concat(['punctuation.section.class.end.bracket.curly.java']) From eda218666b786e0805a9df94c1d99b758ebbacef Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Mon, 13 Apr 2020 08:31:47 +0200 Subject: [PATCH 45/59] Prepare v0.31.5 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b876444..17c6e4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.31.4", + "version": "0.31.5", "description": "Java language support in Atom", "engines": { "atom": "*", From f631536a4137d65b622f01cebeac72345f9e6f70 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 6 Sep 2020 08:59:23 +0200 Subject: [PATCH 46/59] Fix the scope of "instanceof" when using with camelCase variable names (#231) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR updates `variables` scope to restrict it to the word boundaries. This fixes the case when anything that could potentially match a variable declaration would break syntax highlighting, for example, `myVar instanceof MyClass` would result being highlighted as `my[Var instanceof MyClass]` where `[..]` would become a part of variable declaration. I generalised the word boundary (`\b`) check to make sure we never match variable declaration halfway through, particularly for usages of `instanceof`. ### Alternate Designs None were considered. ### Benefits Fixes the issue of highlighting `instanceof`. ### Possible Drawbacks This might break certain usages of variable declarations. ### Applicable Issues Fixes #229 --- grammars/java.cson | 4 +++- spec/java-spec.coffee | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/grammars/java.cson b/grammars/java.cson index 3fa705a..9f65170 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -1593,11 +1593,13 @@ 'variables': 'begin': '''(?x) (?= + \\b ( - \\b(void|boolean|byte|char|short|int|float|long|double)\\b + (void|boolean|byte|char|short|int|float|long|double) | (?>(\\w+\\.)*[A-Z_]+\\w*) # e.g. `javax.ws.rs.Response`, or `String` ) + \\b \\s* ( <[\\w<>,\\.?\\s\\[\\]]*> # e.g. `HashMap`, or `List` diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index a44e2d5..3cbcd3b 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -1931,6 +1931,29 @@ describe 'Java grammar', -> expect(lines[3][5]).toEqual value: 'instanceof', scopes: scopeStack.concat ['keyword.operator.instanceof.java'] expect(lines[6][4]).toEqual value: 'instanceof', scopes: scopeStack.concat ['meta.declaration.assertion.java', 'keyword.operator.instanceof.java'] + it 'tokenizes the `instanceof` operator in return statements and variable definitions', -> + lines = grammar.tokenizeLines ''' + class A { + boolean func1() { + return aa instanceof Test; + } + + boolean func2() { + return aaBbb instanceof Test; + } + + void func3() { + boolean test = aaBbb instanceof Test; + } + } + ''' + + expected = ['source.java', 'meta.class.java', 'meta.class.body.java', 'meta.method.java', 'meta.method.body.java', 'keyword.operator.instanceof.java'] + + expect(lines[2][3]).toEqual value: 'instanceof', scopes: expected + expect(lines[6][3]).toEqual value: 'instanceof', scopes: expected + expect(lines[10][7]).toEqual value: 'instanceof', scopes: expected + it 'tokenizes class fields', -> lines = grammar.tokenizeLines ''' class Test From 0c8743dbafe4d8651731eaa8ec6c41cea7382394 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Sep 2020 08:57:42 +0200 Subject: [PATCH 47/59] Update travis and appveyor builds (#233) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR updates travis and appveyor builds to fix the recent build failures with Atom Beta and tree-sitter. ### Alternate Designs N/A ### Benefits N/A ### Possible Drawbacks N/A ### Applicable Issues --- .travis.yml | 2 +- appveyor.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 47ee9a1..64d7056 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ git: sudo: false -dist: trusty +dist: xenial addons: apt: diff --git a/appveyor.yml b/appveyor.yml index 2b0fde4..7d07d05 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,7 @@ version: "{build}" +image: Visual Studio 2015 + platform: x64 branches: From d99f04087892a5ff9c73465a2a20019aab04abdd Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 19 Sep 2020 10:00:38 +0200 Subject: [PATCH 48/59] Add support for "yield", "sealed", and "permits" Java keywords (#234) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR adds support for JDK 13+ keywords: - `yield` - `sealed` - `permits` `yield` keyword is similar to `return`, so it is handled as "keyword.control.java". `sealed` and `permits` are only for classes and interfaces: `sealed` keyword is a "storage.modifier.java" and `permits` is handled similar to `extends` and `implements` keywords. ### Alternate Designs No alternative designs were considered. ### Benefits Fixes highlighting of the aforementioned keywords. ### Possible Drawbacks Might potentially break class `extends` and `implements` scopes, but that would have to be a corner case not handled by unit tests. ### Applicable Issues Fixes #230 Fixes #232 --- grammars/java.cson | 36 ++++++++++++++++++++++++++---------- spec/java-spec.coffee | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 9f65170..5ce9740 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -38,9 +38,9 @@ (abstract|assert|boolean|break|byte|case|catch|char|class| const|continue|default|do|double|else|enum|extends|final| finally|float|for|goto|if|implements|import|instanceof|int| - interface|long|native|new|package|private|protected|public| - return|short|static|strictfp|super|switch|syncronized|this| - throw|throws|transient|try|void|volatile|while| + interface|long|native|new|package|permits|private|protected|public| + return|sealed|short|static|strictfp|super|switch|syncronized|this| + throw|throws|transient|try|void|volatile|while|yield| true|false|null)\\b ''' 'name': 'invalid.illegal.character_not_allowed_here.java' @@ -86,9 +86,9 @@ (abstract|assert|boolean|break|byte|case|catch|char|class| const|continue|default|do|double|else|enum|extends|final| finally|float|for|goto|if|implements|import|instanceof|int| - interface|long|native|new|package|private|protected|public| - return|short|static|strictfp|super|switch|syncronized|this| - throw|throws|transient|try|void|volatile|while| + interface|long|native|new|package|permits|private|protected|public| + return|sealed|short|static|strictfp|super|switch|syncronized|this| + throw|throws|transient|try|void|volatile|while|yield| true|false|null)\\b ''' 'name': 'invalid.illegal.character_not_allowed_here.java' @@ -307,7 +307,7 @@ 'beginCaptures': '0': 'name': 'storage.modifier.extends.java' - 'end': '(?={|implements)' + 'end': '(?={|implements|permits)' 'name': 'meta.definition.class.inherited.classes.java' 'patterns': [ { @@ -323,7 +323,7 @@ 'beginCaptures': '1': 'name': 'storage.modifier.implements.java' - 'end': '(?=\\s*extends|\\{)' + 'end': '(?=\\s*extends|permits|\\{)' 'name': 'meta.definition.class.implemented.interfaces.java' 'patterns': [ { @@ -334,6 +334,22 @@ } ] } + { + 'begin': '(permits)\\s' + 'beginCaptures': + '1': + 'name': 'storage.modifier.permits.java' + 'end': '(?=\\s*extends|implements|\\{)' + 'name': 'meta.definition.class.permits.classes.java' + 'patterns': [ + { + 'include': '#object-types-inherited' + } + { + 'include': '#comments' + } + ] + } { 'begin': '{' 'beginCaptures': @@ -791,7 +807,7 @@ 'name': 'keyword.control.ternary.java' } { - 'match': '\\b(return|break|case|continue|default|do|while|for|switch|if|else)\\b' + 'match': '\\b(return|yield|break|case|continue|default|do|while|for|switch|if|else)\\b' 'name': 'keyword.control.java' } { @@ -1391,7 +1407,7 @@ } ] 'storage-modifiers': - 'match': '\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient|volatile|default|strictfp)\\b' + 'match': '\\b(public|private|protected|static|final|native|synchronized|abstract|threadsafe|transient|volatile|default|strictfp|sealed)\\b' 'name': 'storage.modifier.java' 'strings': 'patterns': [ diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index 3cbcd3b..b541063 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -3085,3 +3085,37 @@ describe 'Java grammar', -> expect(lines[1][5]).toEqual value: ')', scopes: scopes.concat(['meta.record.identifier.java', 'punctuation.definition.parameters.end.bracket.round.java']) expect(lines[1][7]).toEqual value: '{', scopes: scopes.concat(['meta.record.body.java', 'punctuation.section.class.begin.bracket.curly.java']) expect(lines[1][8]).toEqual value: '}', scopes: scopes.concat(['punctuation.section.class.end.bracket.curly.java']) + + it 'tokenizes yield keyword', -> + lines = grammar.tokenizeLines ''' + public static int calculate(int d) { + return switch (d) { + default -> { + int l = d.toString().length(); + yield l*l; + } + }; + } + ''' + + expect(lines[4][1]).toEqual value: 'yield', scopes: ['source.java', 'keyword.control.java'] + + it 'tokenizes sealed and permits keywords', -> + lines = grammar.tokenizeLines ''' + public sealed class X extends A implements B permits C { } + public sealed class X permits A extends B implements C { } + public sealed class X implements A permits B extends C { } + public sealed class Shape permits Circle, Rectangle, Square { } + public sealed interface ConstantDesc permits String, Integer { } + ''' + + expect(lines[0][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] + expect(lines[0][16]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] + expect(lines[1][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] + expect(lines[1][8]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] + expect(lines[2][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] + expect(lines[2][12]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] + expect(lines[3][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] + expect(lines[3][8]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] + expect(lines[4][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] + expect(lines[4][8]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] From 593444386a4e69e9c9d0e7e1611c8e7a5c32ed65 Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 21 Sep 2020 21:10:49 +0200 Subject: [PATCH 49/59] Tree-sitter support (#193) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change Adds tree-sitter support for language-java. I added unit tests to cover the changes in tree-sitter grammar. I had to link tree-sitter-dev (https://github.com/sadikovi/tree-sitter-java/) package that contains my patches. I will push them upstream later. ### Alternate Designs Not applicable. ### Benefits Adds support for tree-sitter, makes language highlighting more robust and fixes some of the old issues of regex highlighting. ### Possible Drawbacks None, it does not affect TextMate grammar, also users can always disable tree-sitter support in the editor settings. ### Applicable Issues N/A --- grammars/tree-sitter-java.cson | 300 ++++++++ package.json | 3 + spec/java-spec.coffee | 1 + spec/tree-sitter-java-spec.coffee | 1099 +++++++++++++++++++++++++++++ spec/unified-el-spec.coffee | 1 + 5 files changed, 1404 insertions(+) create mode 100644 grammars/tree-sitter-java.cson create mode 100644 spec/tree-sitter-java-spec.coffee diff --git a/grammars/tree-sitter-java.cson b/grammars/tree-sitter-java.cson new file mode 100644 index 0000000..65fbdc9 --- /dev/null +++ b/grammars/tree-sitter-java.cson @@ -0,0 +1,300 @@ +name: 'Java' +scopeName: 'source.java' +type: 'tree-sitter' +parser: 'tree-sitter-java-dev' + +fileTypes: [ + 'java' +] + +folds: [ + { + type: [ + 'comment', + 'class_body', + 'enum_body', + 'interface_body' + 'annotation_type_body', + 'module_body', + 'constructor_body', + 'block', + 'switch_block' + ] + } +] + +comments: + start: '// ' + +scopes: + 'program': 'source.java' + + 'comment': 'comment.block' + + ''' + "assert", + "break", + "case", + "catch", + "continue", + "default", + "do", + "else", + "finally", + "for", + "if", + "new", + "return", + "switch", + "throw", + "try", + "while" + ''': 'keyword.control' + + ''' + "const", + "goto" + ''': 'keyword.reserved' + + ''' + ternary_expression > "?", + ternary_expression > ":" + ''': 'keyword.control.ternary' + + '"instanceof"': 'keyword.operator.instanceof' + '"="': 'keyword.operator.assignment' + + ''' + "==", + "!=", + "<=", + ">=", + ">", + "<" + ''': 'keyword.operator.comparison' + + ''' + "!", + "&&", + "||" + ''': 'keyword.operator.logical' + + ''' + "-", + "+", + "*", + "/", + "%", + "-=", + "+=", + "*=", + "/=", + "%=", + "++", + "--" + ''': 'keyword.operator.arithmetic' + + ''' + "&", + "|", + "^", + "~", + "&=", + "|=", + "^=", + "<<", + ">>", + ">>>", + "<<=", + ">>=", + ">>>=" + ''': 'keyword.operator.bitwise' + + '"."': 'punctuation.separator.period' + '","': 'punctuation.separator.delimiter' + '";"': 'punctuation.terminator.statement' + '"["': 'punctuation.bracket.square' + '"]"': 'punctuation.bracket.square' + '"{"': 'punctuation.bracket.curly' + '"}"': 'punctuation.bracket.curly' + '"("': 'punctuation.bracket.round' + '")"': 'punctuation.bracket.round' + + ''' + this, + super + ''': 'variable.language' + + # Literals and constants + + 'null_literal': 'constant.language.null' + + ''' + true, + false + ''': 'constant.boolean' + + ''' + decimal_integer_literal, + hex_integer_literal, + octal_integer_literal, + binary_integer_literal + ''': 'constant.numeric' + + ''' + decimal_floating_point_literal, + hex_floating_point_literal + ''': 'constant.numeric' + + 'character_literal': 'string.quoted.single' + 'string_literal': 'string.quoted.double' + + # Primitive and simple types + + ''' + void_type, + integral_type, + floating_point_type, + boolean_type, + type_identifier, + type_parameter > identifier + ''': 'storage.type' + + # Generic types + + ''' + type_arguments > "<", + type_arguments > ">", + type_parameters > "<", + type_parameters > ">" + ''': 'punctuation.bracket.angle' + + 'type_arguments > wildcard > "?"': 'storage.type.generic.wildcard' + 'type_arguments > wildcard > "extends"': "storage.modifier.extends" + 'type_arguments > wildcard > super': "storage.modifier.super" + # generic bounds in classes + 'type_bound > "extends"': "storage.modifier.extends" + 'type_bound > "&"': 'punctuation.separator.types' + + # Modifiers and keywords + + ''' + "public", + "protected", + "private", + "abstract", + "static", + "final", + "strictfp", + "default", + "synchronized", + "native", + "transient", + "volatile", + "threadsafe" + ''': 'storage.modifier' + # "extends" keyword for classes and enums + 'superclass > "extends"': 'storage.modifier.extends' + # "extends" keyword for interfaces + 'extends_interfaces > "extends"': 'storage.modifier.extends' + 'super_interfaces > "implements"': 'storage.modifier.implements' + 'static_initializer > "static"': 'storage.modifier' + + # Package and imports + + 'package_declaration': 'meta.package' + 'package_declaration > "package"': 'keyword.other.package' + + 'import_declaration': 'meta.import' + 'import_declaration > "import"': 'keyword.other.import' + 'import_declaration > "static"': 'keyword.other.static' + 'import_declaration > asterisk > "*"': 'variable.language.wildcard' + + # Expressions + + 'lambda_expression > "->"': 'storage.type.function.arrow' + + # Statements + + 'catch_type > "|"': 'punctuation.catch.separator' + + # Class declaration + + 'class_declaration > "class"': 'keyword.other.class' + 'class_declaration > identifier': 'entity.name.type.class' + + 'class_declaration > class_body': 'meta.class.body' + + # Enum declaration + + 'enum_declaration > "enum"': 'keyword.other.enum' + 'enum_declaration > identifier': 'entity.name.type.enum' + + 'enum_declaration > enum_body': 'meta.enum.body' + + 'enum_constant > identifier': 'constant.other.enum' + + # Interface declaration + + 'interface_declaration > "interface"': 'keyword.other.interface' + 'interface_declaration > identifier': 'entity.name.type.interface' + + 'interface_declaration > interface_body': 'meta.interface.body' + + # annotated interface + 'annotation_type_declaration > "@interface"': 'keyword.other.interface.annotated' + 'annotation_type_declaration > identifier': 'entity.name.type.interface.annotated' + + 'annotation_type_declaration > annotation_type_body': 'meta.interface.annotated.body' + + 'annotation_type_element_declaration > identifier': 'entity.name.function' + + # Annotations + + 'marker_annotation': 'meta.declaration.annotation' + 'marker_annotation > "@"': 'punctuation.definition.annotation' + 'marker_annotation > identifier': 'storage.type.annotation' + + 'annotation': 'meta.declaration.annotation' + 'annotation > "@"': 'punctuation.definition.annotation' + 'annotation > identifier': 'storage.type.annotation' + + 'element_value_pair > identifier': 'variable.other.annotation.element' + + # Methods + + 'method_declaration': 'meta.method' + 'method_declaration > identifier': 'entity.name.function' + 'method_declaration > block': 'meta.method.body' + + 'constructor_declaration': 'meta.constructor' + 'constructor_declaration > identifier': 'entity.name.function' + 'constructor_body': 'meta.constructor.body' + + 'throws > "throws"': 'storage.modifier.throws' + + 'spread_parameter > "..."': 'punctuation.definition.parameters.varargs' + + # Method access and reference + + 'method_invocation > method_invocation_name > identifier': 'entity.name.function' + + # Method reference + 'method_reference > "::"': 'keyword.control.method' + + ''' + method_reference > "new", + method_reference > identifier:nth-child(2) + ''': 'entity.name.function' + + ''' + field_access > identifier, + method_reference > identifier, + method_invocation > identifier + ''': [ + {match: '^[A-Z][A-Z_]+$', scopes: 'constant.other'}, + {match: '^[A-Z]', scopes: 'storage.type'} + ] + 'identifier': [ + {match: '^[A-Z][A-Z_]+$', scopes: 'constant.other'} + ] diff --git a/package.json b/package.json index 17c6e4c..88935ed 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,9 @@ "bugs": { "url": "https://github.com/atom/language-java/issues" }, + "dependencies": { + "tree-sitter-java-dev": "^0.16.0-dev2" + }, "devDependencies": { "coffeelint": "^1.10.1" } diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index b541063..471ccc5 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -2,6 +2,7 @@ describe 'Java grammar', -> grammar = null beforeEach -> + atom.config.set('core.useTreeSitterParsers', false) waitsForPromise -> atom.packages.activatePackage('language-java') diff --git a/spec/tree-sitter-java-spec.coffee b/spec/tree-sitter-java-spec.coffee new file mode 100644 index 0000000..6e63101 --- /dev/null +++ b/spec/tree-sitter-java-spec.coffee @@ -0,0 +1,1099 @@ +{TextEditor} = require 'atom' + +describe 'Tree-sitter based Java grammar', -> + grammar = null + editor = null + buffer = null + + beforeEach -> + atom.config.set('core.useTreeSitterParsers', true) + + waitsForPromise -> + atom.packages.activatePackage('language-java') + + runs -> + editor = new TextEditor() + grammar = atom.grammars.grammarForScopeName('source.java') + editor.setGrammar(grammar) + buffer = editor.getBuffer() + + # Compatibility functions with TextMate grammar tests + + # Returns list of tokens as [{value: ..., scopes: [...]}, ...] + getTokens = (buffer, row) -> + line = buffer.lineForRow row + tokens = [] + + iterator = buffer.getLanguageMode().buildHighlightIterator() + start = {row: row, column: 0} + scopes = iterator.seek(start, row) + + while true + end = iterator.getPosition() + + if end.row > row + end.row = row + end.column = line.length + + if end.column > start.column + tokens.push({ + value: line.substring(start.column, end.column), + scopes: buffer.getLanguageMode().grammar.scopeNameForScopeId(s) for s in scopes + }) + + if end.column < line.length + for num in iterator.getCloseScopeIds() + item = scopes.pop() + scopes.push(iterator.getOpenScopeIds()...) + start = end + iterator.moveToSuccessor() + else + break + + tokens + + tokenizeLine = (text) -> + buffer.setText(text) + getTokens(buffer, 0) + + tokenizeLines = (text) -> + buffer.setText(text) + lines = buffer.getLines() + tokens = [] + row = 0 + for _ in lines + tokens.push(getTokens(buffer, row)) + row += 1 + tokens + + printTokens = (tokens) -> + console.log() + for token, i in tokens + for t, j in token + scopes = ("'#{scope}'" for scope in t.scopes).join(", ") + console.log("expect(tokens[#{i}][#{j}]).toEqual value: '#{t.value}', scopes: [#{scopes}]") + console.log() + + # Unit tests + + it 'parses the grammar', -> + expect(grammar).toBeTruthy() + expect(grammar.scopeName).toBe 'source.java' + + it 'tokenizes punctuation', -> + tokens = tokenizeLine 'int a, b, c;' + + expect(tokens[2]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[4]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[6]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.statement'] + + tokens = tokenizeLine 'a.b.c();' + + expect(tokens[1]).toEqual value: '.', scopes: ['source.java', 'punctuation.separator.period'] + expect(tokens[3]).toEqual value: '.', scopes: ['source.java', 'punctuation.separator.period'] + expect(tokens[7]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.statement'] + + tokens = tokenizeLine 'a . b' + + expect(tokens[2]).toEqual value: '.', scopes: ['source.java', 'punctuation.separator.period'] + + tokens = tokenizeLine 'new com.package.Clazz();' + + expect(tokens[3]).toEqual value: '.', scopes: ['source.java', 'punctuation.separator.period'] + expect(tokens[5]).toEqual value: '.', scopes: ['source.java', 'punctuation.separator.period'] + expect(tokens[9]).toEqual value: ';', scopes: ['source.java', 'punctuation.terminator.statement'] + + tokens = tokenizeLine 'class A implements B, C {}' + + expect(tokens[7]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + + it 'tokenizes comparison', -> + tokens = tokenizeLines ''' + a > b; + a < b; + a == b; + a >= b; + a <= b; + a != b; + ''' + + expect(tokens[0][1]).toEqual value: '>', scopes: ['source.java', 'keyword.operator.comparison'] + expect(tokens[1][1]).toEqual value: '<', scopes: ['source.java', 'keyword.operator.comparison'] + expect(tokens[2][1]).toEqual value: '==', scopes: ['source.java', 'keyword.operator.comparison'] + expect(tokens[3][1]).toEqual value: '>=', scopes: ['source.java', 'keyword.operator.comparison'] + expect(tokens[4][1]).toEqual value: '<=', scopes: ['source.java', 'keyword.operator.comparison'] + expect(tokens[5][1]).toEqual value: '!=', scopes: ['source.java', 'keyword.operator.comparison'] + + it 'tokenizes logical', -> + tokens = tokenizeLines ''' + a && b; + a || b; + !a; + ''' + + expect(tokens[0][1]).toEqual value: '&&', scopes: ['source.java', 'keyword.operator.logical'] + expect(tokens[1][1]).toEqual value: '||', scopes: ['source.java', 'keyword.operator.logical'] + expect(tokens[2][0]).toEqual value: '!', scopes: ['source.java', 'keyword.operator.logical'] + + it 'tokenizes arithmetic', -> + tokens = tokenizeLines ''' + a + b; + a - b; + a * b; + a / b; + a % b; + a += b; + a -= b; + a *= b; + a /= b; + a %= b; + a++; + --a; + ''' + + expect(tokens[0][1]).toEqual value: '+', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[1][1]).toEqual value: '-', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[2][1]).toEqual value: '*', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[3][1]).toEqual value: '/', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[4][1]).toEqual value: '%', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[5][1]).toEqual value: '+=', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[6][1]).toEqual value: '-=', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[7][1]).toEqual value: '*=', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[8][1]).toEqual value: '/=', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[9][1]).toEqual value: '%=', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[10][1]).toEqual value: '++', scopes: ['source.java', 'keyword.operator.arithmetic'] + expect(tokens[11][0]).toEqual value: '--', scopes: ['source.java', 'keyword.operator.arithmetic'] + + it 'tokenizes bitwise', -> + tokens = tokenizeLines ''' + a & b; + a | b; + a ^ b; + a >> b; + a << b; + a >>> b; + a &= b; + a |= b; + a ^= b; + a >>= b; + a <<= b; + a >>>= b; + ~a; + ''' + + expect(tokens[0][1]).toEqual value: '&', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[1][1]).toEqual value: '|', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[2][1]).toEqual value: '^', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[3][1]).toEqual value: '>>', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[4][1]).toEqual value: '<<', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[5][1]).toEqual value: '>>>', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[6][1]).toEqual value: '&=', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[7][1]).toEqual value: '|=', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[8][1]).toEqual value: '^=', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[9][1]).toEqual value: '>>=', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[10][1]).toEqual value: '<<=', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[11][1]).toEqual value: '>>>=', scopes: ['source.java', 'keyword.operator.bitwise'] + expect(tokens[12][0]).toEqual value: '~', scopes: ['source.java', 'keyword.operator.bitwise'] + + it 'tokenizes brackets', -> + tokens = tokenizeLine '{ (a + b) + c[d] }' + + expect(tokens[0]).toEqual value: '{', scopes: ['source.java', 'punctuation.bracket.curly'] + expect(tokens[2]).toEqual value: '(', scopes: ['source.java', 'punctuation.bracket.round'] + expect(tokens[6]).toEqual value: ')', scopes: ['source.java', 'punctuation.bracket.round'] + expect(tokens[10]).toEqual value: '[', scopes: ['source.java', 'punctuation.bracket.square'] + expect(tokens[12]).toEqual value: ']', scopes: ['source.java', 'punctuation.bracket.square'] + expect(tokens[14]).toEqual value: '}', scopes: ['source.java', 'punctuation.bracket.curly'] + + it 'tokenizes literals', -> + tokens = tokenizeLines ''' + a = null; + a = true; + a = false; + a = 123; + a = 0x1a; + a = 0b11010; + a = 123L; + a = 123l; + a = 123.4; + a = 123.4d; + a = 1.234e2; + a = 123.4f; + a = 'a'; + a = '\u0108' + a = "abc"; + ''' + + expect(tokens[0][3]).toEqual value: 'null', scopes: ['source.java', 'constant.language.null'] + expect(tokens[1][3]).toEqual value: 'true', scopes: ['source.java', 'constant.boolean'] + expect(tokens[2][3]).toEqual value: 'false', scopes: ['source.java', 'constant.boolean'] + expect(tokens[3][3]).toEqual value: '123', scopes: ['source.java', 'constant.numeric'] + expect(tokens[4][3]).toEqual value: '0x1a', scopes: ['source.java', 'constant.numeric'] + expect(tokens[5][3]).toEqual value: '0b11010', scopes: ['source.java', 'constant.numeric'] + expect(tokens[6][3]).toEqual value: '123L', scopes: ['source.java', 'constant.numeric'] + expect(tokens[7][3]).toEqual value: '123l', scopes: ['source.java', 'constant.numeric'] + expect(tokens[8][3]).toEqual value: '123.4', scopes: ['source.java', 'constant.numeric'] + expect(tokens[9][3]).toEqual value: '123.4d', scopes: ['source.java', 'constant.numeric'] + expect(tokens[10][3]).toEqual value: '1.234e2', scopes: ['source.java', 'constant.numeric'] + expect(tokens[11][3]).toEqual value: '123.4f', scopes: ['source.java', 'constant.numeric'] + expect(tokens[12][3]).toEqual value: '\'a\'', scopes: ['source.java', 'string.quoted.single'] + expect(tokens[13][3]).toEqual value: '\'\u0108\'', scopes: ['source.java', 'string.quoted.single'] + expect(tokens[14][3]).toEqual value: '\"abc\"', scopes: ['source.java', 'string.quoted.double'] + + it 'tokenizes constants', -> + tokens = tokenizeLines ''' + String CONSTANT_STR = "abc"; + a = CONSTANT + obj.func(); + b = conf.get(CONSTANT_ANOTHER); + c = Integer.MAX_VALUE; + ''' + + expect(tokens[0][2]).toEqual value: 'CONSTANT_STR', scopes: ['source.java', 'constant.other'] + expect(tokens[1][3]).toEqual value: 'CONSTANT', scopes: ['source.java', 'constant.other'] + expect(tokens[2][6]).toEqual value: 'CONSTANT_ANOTHER', scopes: ['source.java', 'constant.other'] + expect(tokens[3][5]).toEqual value: 'MAX_VALUE', scopes: ['source.java', 'constant.other'] + + it 'tokenizes reserved keywords', -> + tokens = tokenizeLine 'const value;' + + expect(tokens[0]).toEqual value: 'const', scopes: ['source.java', 'keyword.reserved'] + + tokens = tokenizeLine 'int a = 1; goto;' + + expect(tokens[7]).toEqual value: 'goto', scopes: ['source.java', 'keyword.reserved'] + + it 'tokenizes packages', -> + tokens = tokenizeLine 'package com.test;' + + expect(tokens[0]).toEqual value: 'package', scopes: ['source.java', 'meta.package', 'keyword.other.package'] + expect(tokens[1]).toEqual value: ' com', scopes: ['source.java', 'meta.package'] + expect(tokens[2]).toEqual value: '.', scopes: ['source.java', 'meta.package', 'punctuation.separator.period'] + expect(tokens[3]).toEqual value: 'test', scopes: ['source.java', 'meta.package'] + expect(tokens[4]).toEqual value: ';', scopes: ['source.java', 'meta.package', 'punctuation.terminator.statement'] + + it 'tokenizes imports', -> + tokens = tokenizeLine 'import com.package;' + + expect(tokens[0]).toEqual value: 'import', scopes: ['source.java', 'meta.import', 'keyword.other.import'] + + it 'tokenizes static imports', -> + tokens = tokenizeLine 'import static com.package;' + + expect(tokens[0]).toEqual value: 'import', scopes: ['source.java', 'meta.import', 'keyword.other.import'] + expect(tokens[2]).toEqual value: 'static', scopes: ['source.java', 'meta.import', 'keyword.other.static'] + + it 'tokenizes imports with asterisk', -> + tokens = tokenizeLine 'import static com.package.*;' + + expect(tokens[0]).toEqual value: 'import', scopes: ['source.java', 'meta.import', 'keyword.other.import'] + expect(tokens[2]).toEqual value: 'static', scopes: ['source.java', 'meta.import', 'keyword.other.static'] + expect(tokens[7]).toEqual value: '*', scopes: ['source.java', 'meta.import', 'variable.language.wildcard'] + + it 'tokenizes static initializers', -> + tokens = tokenizeLines ''' + class A { + private static int a = 0; + + static { + a = 1; + } + } + ''' + + expect(tokens[1][3]).toEqual value: 'static', scopes: ['source.java', 'meta.class.body', 'storage.modifier'] + expect(tokens[3][1]).toEqual value: 'static', scopes: ['source.java', 'meta.class.body', 'storage.modifier'] + + it 'tokenizes synchronized blocks', -> + tokens = tokenizeLines ''' + class A { + synchronized { + func(); + } + } + ''' + + expect(tokens[1][1]).toEqual value: 'synchronized', scopes: ['source.java', 'meta.class.body', 'storage.modifier'] + + it 'tokenizes instanceof', -> + tokens = tokenizeLines ''' + (a instanceof Tpe); + (a instanceof tpe); + (a instanceof tpTpe); + (a instanceof tp.Tpe); + if (a instanceof B) { } + if (aaBb instanceof B) { } + ''' + + expect(tokens[0][2]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof'] + expect(tokens[0][4]).toEqual value: 'Tpe', scopes: ['source.java', 'storage.type'] + expect(tokens[1][2]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof'] + expect(tokens[1][4]).toEqual value: 'tpe', scopes: ['source.java', 'storage.type'] + expect(tokens[2][2]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof'] + expect(tokens[2][4]).toEqual value: 'tpTpe', scopes: ['source.java', 'storage.type'] + expect(tokens[3][2]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof'] + expect(tokens[3][4]).toEqual value: 'tp', scopes: ['source.java', 'storage.type'] + expect(tokens[3][6]).toEqual value: 'Tpe', scopes: ['source.java', 'storage.type'] + expect(tokens[4][4]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof'] + expect(tokens[5][4]).toEqual value: 'instanceof', scopes: ['source.java', 'keyword.operator.instanceof'] + + it 'tokenizes ternary', -> + tokens = tokenizeLine '(a > b) ? a : b;' + + expect(tokens[6]).toEqual value: '?', scopes: ['source.java', 'keyword.control.ternary'] + expect(tokens[8]).toEqual value: ':', scopes: ['source.java', 'keyword.control.ternary'] + + it 'tokenizes try-catch block with multiple exceptions', -> + tokens = tokenizeLines ''' + private void method() { + try { + // do something + } catch (Exception1 | Exception2 err) { + throw new Exception3(); + } + } + ''' + + expect(tokens[1][1]).toEqual value: 'try', scopes: ['source.java', 'keyword.control'] + expect(tokens[3][3]).toEqual value: 'catch', scopes: ['source.java', 'keyword.control'] + expect(tokens[3][5]).toEqual value: '(', scopes: ['source.java', 'punctuation.bracket.round'] + expect(tokens[3][6]).toEqual value: 'Exception1', scopes: ['source.java', 'storage.type'] + expect(tokens[3][8]).toEqual value: '|', scopes: ['source.java', 'punctuation.catch.separator'] + expect(tokens[3][10]).toEqual value: 'Exception2', scopes: ['source.java', 'storage.type'] + expect(tokens[3][12]).toEqual value: ')', scopes: ['source.java', 'punctuation.bracket.round'] + expect(tokens[4][1]).toEqual value: 'throw', scopes: ['source.java', 'keyword.control'] + expect(tokens[4][3]).toEqual value: 'new', scopes: ['source.java', 'keyword.control'] + expect(tokens[4][5]).toEqual value: 'Exception3', scopes: ['source.java', 'storage.type'] + + it 'tokenizes lambda expressions', -> + tokens = tokenizeLine '(String s1) -> s1.length() - outer.length();' + + expect(tokens[5]).toEqual value: '->', scopes: ['source.java', 'storage.type.function.arrow'] + + it 'tokenizes spread parameters', -> + tokens = tokenizeLine 'public void method(String... args);' + + expect(tokens[6]).toEqual value: '...', scopes: ['source.java', 'punctuation.definition.parameters.varargs'] + + tokens = tokenizeLine 'void func(int /* ... */ arg, int ... args);' + + expect(tokens[5]).toEqual value: '/* ... */', scopes: ['source.java', 'comment.block'] + expect(tokens[11]).toEqual value: '...', scopes: ['source.java', 'punctuation.definition.parameters.varargs'] + + it 'tokenizes identifiers with `$`', -> + tokens = tokenizeLines ''' + class A$B { + void func$() { + $object.$property; + $hello(); + } + } + ''' + + expect(tokens[0][2]).toEqual value: 'A$B', scopes: ['source.java', 'entity.name.type.class'] + expect(tokens[0][3]).toEqual value: ' ', scopes: ['source.java'] + expect(tokens[0][4]).toEqual value: '{', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.curly'] + expect(tokens[1][3]).toEqual value: 'func$', scopes: ['source.java', 'meta.class.body', 'meta.method', 'entity.name.function'] + expect(tokens[2][1]).toEqual value: '$object', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body'] + expect(tokens[2][3]).toEqual value: '$property', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body'] + expect(tokens[3][1]).toEqual value: '$hello', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + + it 'tokenizes this and super', -> + tokens = tokenizeLine 'this.x + super.x;' + + expect(tokens[0]).toEqual value: 'this', scopes: ['source.java', 'variable.language'] + expect(tokens[5]).toEqual value: 'super', scopes: ['source.java', 'variable.language'] + + it 'tokenizes this and super in method invocations', -> + tokens = tokenizeLines ''' + class A { + void func() { + super.debug("debug"); + this.debug("debug"); + property.super.func("arg"); + } + } + ''' + + expect(tokens[2][1]).toEqual value: 'super', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'variable.language'] + expect(tokens[3][1]).toEqual value: 'this', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'variable.language'] + expect(tokens[4][3]).toEqual value: 'super', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'variable.language'] + + it 'tokenizes comments', -> + tokens = tokenizeLines ''' + // comment + + /* + comment + */ + ''' + + expect(tokens[0][0]).toEqual value: '// comment', scopes: ['source.java', 'comment.block'] + expect(tokens[2][0]).toEqual value: '/*', scopes: ['source.java', 'comment.block'] + expect(tokens[3][0]).toEqual value: ' comment', scopes: ['source.java', 'comment.block'] + expect(tokens[4][0]).toEqual value: ' */', scopes: ['source.java', 'comment.block'] + + it 'tokenizes type definitions', -> + tokens = tokenizeLines ''' + class A { + void method() { } + boolean method() { } + int method() { } + long method() { } + float method() { } + double method() { } + int[] method() { } + T method() { } + java.util.List method() { } + } + ''' + + expect(tokens[1][1]).toEqual value: 'void', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[2][1]).toEqual value: 'boolean', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[3][1]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[4][1]).toEqual value: 'long', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[5][1]).toEqual value: 'float', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[6][1]).toEqual value: 'double', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[7][1]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[8][1]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][3]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][5]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][7]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + + it 'tokenizes type casting', -> + tokens = tokenizeLines ''' + class A { + A method() { + return (A) a; + } + } + ''' + + expect(tokens[2][1]).toEqual value: 'return', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control'] + expect(tokens[2][3]).toEqual value: '(', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.round'] + expect(tokens[2][4]).toEqual value: 'A', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[2][5]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.angle'] + expect(tokens[2][6]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[2][7]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.angle'] + expect(tokens[2][8]).toEqual value: ')', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.round'] + + it 'tokenizes class generic type definitions', -> + tokens = tokenizeLines ''' + class Test {} + class Test> {} + class Bound {} + class Bound {} + class Bound & B> {} + class Test extends Common {} + class Test {} + class Test, S extends Conv> {} + ''' + + expect(tokens[0][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[0][4]).toEqual value: 'K', scopes: ['source.java', 'storage.type'] + expect(tokens[0][5]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[0][7]).toEqual value: 'V', scopes: ['source.java', 'storage.type'] + expect(tokens[0][8]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[1][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[1][4]).toEqual value: 'A', scopes: ['source.java', 'storage.type'] + expect(tokens[1][6]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[1][8]).toEqual value: 'java', scopes: ['source.java', 'storage.type'] + expect(tokens[1][10]).toEqual value: 'util', scopes: ['source.java', 'storage.type'] + expect(tokens[1][12]).toEqual value: 'List', scopes: ['source.java', 'storage.type'] + expect(tokens[1][13]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[1][14]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[1][15]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[1][16]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[2][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[2][4]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[2][6]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[2][8]).toEqual value: 'A', scopes: ['source.java', 'storage.type'] + expect(tokens[2][10]).toEqual value: '&', scopes: ['source.java', 'punctuation.separator.types'] + expect(tokens[2][12]).toEqual value: 'B', scopes: ['source.java', 'storage.type'] + expect(tokens[2][13]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[3][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[3][4]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[3][6]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[3][8]).toEqual value: 'java', scopes: ['source.java', 'storage.type'] + expect(tokens[3][10]).toEqual value: 'lang', scopes: ['source.java', 'storage.type'] + expect(tokens[3][12]).toEqual value: 'A', scopes: ['source.java', 'storage.type'] + expect(tokens[3][14]).toEqual value: '&', scopes: ['source.java', 'punctuation.separator.types'] + expect(tokens[3][16]).toEqual value: 'java', scopes: ['source.java', 'storage.type'] + expect(tokens[3][18]).toEqual value: 'lang', scopes: ['source.java', 'storage.type'] + expect(tokens[3][20]).toEqual value: 'B', scopes: ['source.java', 'storage.type'] + expect(tokens[3][21]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[4][4]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[4][5]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[4][7]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[4][9]).toEqual value: 'A', scopes: ['source.java', 'storage.type'] + expect(tokens[4][10]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[4][11]).toEqual value: '?', scopes: ['source.java', 'storage.type.generic.wildcard'] + expect(tokens[4][13]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[4][15]).toEqual value: 'D', scopes: ['source.java', 'storage.type'] + expect(tokens[4][16]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[4][18]).toEqual value: '&', scopes: ['source.java', 'punctuation.separator.types'] + expect(tokens[4][20]).toEqual value: 'B', scopes: ['source.java', 'storage.type'] + expect(tokens[4][21]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[5][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[5][4]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[5][5]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[5][7]).toEqual value: 'S', scopes: ['source.java', 'storage.type'] + expect(tokens[5][8]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[5][10]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[5][12]).toEqual value: 'Common', scopes: ['source.java', 'storage.type'] + expect(tokens[5][13]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[5][14]).toEqual value: '?', scopes: ['source.java', 'storage.type.generic.wildcard'] + expect(tokens[5][16]).toEqual value: 'super', scopes: ['source.java', 'storage.modifier.super'] + expect(tokens[5][18]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[5][19]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[6][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[6][4]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[6][6]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[6][8]).toEqual value: 'A', scopes: ['source.java', 'storage.type'] + expect(tokens[6][10]).toEqual value: '&', scopes: ['source.java', 'punctuation.separator.types'] + expect(tokens[6][12]).toEqual value: 'B', scopes: ['source.java', 'storage.type'] + expect(tokens[6][13]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[6][15]).toEqual value: 'String', scopes: ['source.java', 'storage.type'] + expect(tokens[6][16]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[6][18]).toEqual value: 'Integer', scopes: ['source.java', 'storage.type'] + expect(tokens[6][19]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + expect(tokens[7][3]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[7][4]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[7][6]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[7][8]).toEqual value: 'Conv', scopes: ['source.java', 'storage.type'] + expect(tokens[7][9]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[7][10]).toEqual value: 'S', scopes: ['source.java', 'storage.type'] + expect(tokens[7][11]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[7][12]).toEqual value: ',', scopes: ['source.java', 'punctuation.separator.delimiter'] + expect(tokens[7][14]).toEqual value: 'S', scopes: ['source.java', 'storage.type'] + expect(tokens[7][16]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[7][18]).toEqual value: 'Conv', scopes: ['source.java', 'storage.type'] + expect(tokens[7][19]).toEqual value: '<', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[7][20]).toEqual value: 'T', scopes: ['source.java', 'storage.type'] + expect(tokens[7][21]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + expect(tokens[7][22]).toEqual value: '>', scopes: ['source.java', 'punctuation.bracket.angle'] + + it 'tokenizes generic type definitions', -> + tokens = tokenizeLines ''' + abstract class Generics { + HashMap map = new HashMap<>(); + CodeMap codemap; + C(Map> m) {} + Map method() {} + Set> set1; + Set> set2; + + List func(); + java.util.List func(); + List<> func(); + java.util.List> func(); + java.util.List func(); + java.util.List func(); + T getAnnotation(Class annotationType); + } + ''' + + expect(tokens[1][1]).toEqual value: 'HashMap', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[1][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[1][3]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[1][4]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.delimiter'] + expect(tokens[1][6]).toEqual value: 'String', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[1][7]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[1][13]).toEqual value: 'HashMap', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[1][14]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[1][15]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + + expect(tokens[2][1]).toEqual value: 'CodeMap', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[2][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[2][3]).toEqual value: 'String', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[2][4]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.delimiter'] + expect(tokens[2][6]).toEqual value: '?', scopes: ['source.java', 'meta.class.body', 'storage.type.generic.wildcard'] + expect(tokens[2][8]).toEqual value: 'extends', scopes: ['source.java', 'meta.class.body', 'storage.modifier.extends'] + expect(tokens[2][10]).toEqual value: 'ArrayList', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[2][11]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + + expect(tokens[3][3]).toEqual value: 'Map', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.type'] + expect(tokens[3][4]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.bracket.angle'] + expect(tokens[3][5]).toEqual value: '?', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.type.generic.wildcard'] + expect(tokens[3][6]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.separator.delimiter'] + expect(tokens[3][8]).toEqual value: '?', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.type.generic.wildcard'] + expect(tokens[3][10]).toEqual value: 'extends', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.modifier.extends'] + expect(tokens[3][12]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.type'] + expect(tokens[3][13]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.bracket.angle'] + expect(tokens[3][14]).toEqual value: '?', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.type.generic.wildcard'] + expect(tokens[3][15]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.bracket.angle'] + expect(tokens[3][16]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.bracket.angle'] + + expect(tokens[4][1]).toEqual value: 'Map', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[4][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[4][3]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[4][4]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.delimiter'] + expect(tokens[4][6]).toEqual value: 'String', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[4][7]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[5][1]).toEqual value: 'Set', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[5][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[5][3]).toEqual value: 'Map', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[5][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[5][5]).toEqual value: 'Entry', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[5][6]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[5][7]).toEqual value: 'K', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[5][8]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.delimiter'] + expect(tokens[5][10]).toEqual value: 'V', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[5][11]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[5][12]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + + expect(tokens[6][1]).toEqual value: 'Set', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[6][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[6][3]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[6][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[6][5]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[6][6]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[6][7]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[6][8]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[6][9]).toEqual value: 'K', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[6][10]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[6][11]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + + expect(tokens[8][1]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[8][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[8][3]).toEqual value: 'A', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[8][4]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.delimiter'] + expect(tokens[8][6]).toEqual value: 'B', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[8][7]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.delimiter'] + expect(tokens[8][9]).toEqual value: 'C', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[8][10]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[9][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[9][3]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[9][5]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][6]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[9][7]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][8]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[10][1]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[10][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[10][3]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[11][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[11][3]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[11][5]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][6]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[11][7]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][8]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[11][9]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][10]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[11][11]).toEqual value: 'Map', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][12]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[11][13]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][14]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.delimiter'] + expect(tokens[11][16]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][17]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[11][18]).toEqual value: 'lang', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][19]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[11][20]).toEqual value: 'String', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[11][21]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[11][22]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[12][1]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[12][2]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[12][3]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[12][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[12][5]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[12][6]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[12][7]).toEqual value: '?', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type.generic.wildcard'] + expect(tokens[12][9]).toEqual value: 'extends', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier.extends'] + expect(tokens[12][11]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[12][12]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[13][1]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[13][2]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[13][4]).toEqual value: 'extends', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier.extends'] + expect(tokens[13][6]).toEqual value: 'Integer', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[13][7]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[13][9]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[13][10]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[13][11]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[13][12]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.period'] + expect(tokens[13][13]).toEqual value: 'List', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[13][14]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[13][15]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[13][16]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + expect(tokens[14][1]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[14][2]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[14][4]).toEqual value: 'extends', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier.extends'] + expect(tokens[14][6]).toEqual value: 'Annotation', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[14][7]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[14][9]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[14][14]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + expect(tokens[14][15]).toEqual value: 'T', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[14][16]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.angle'] + + it 'tokenizes generics without mixing with bitwise or comparison operators', -> + tokens = tokenizeLines ''' + class A { + void func1() { + t = M << 12; + } + + void func2() { + if (A < a) { + a = A; + } + ArrayList list; + list = new ArrayList(); + + if (A < a) { } + + if (A < a && b < a) { + b = a; + } + } + } + ''' + + expect(tokens[2][4]).toEqual value: '<<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.operator.bitwise'] + expect(tokens[6][1]).toEqual value: 'if', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control'] + expect(tokens[6][5]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.operator.comparison'] + expect(tokens[9][1]).toEqual value: 'ArrayList', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[9][2]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.angle'] + expect(tokens[9][3]).toEqual value: 'A', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[9][4]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.angle'] + expect(tokens[10][4]).toEqual value: 'new', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control'] + expect(tokens[10][6]).toEqual value: 'ArrayList', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[10][7]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.angle'] + expect(tokens[10][8]).toEqual value: 'A', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[10][9]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.angle'] + expect(tokens[12][1]).toEqual value: 'if', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control'] + expect(tokens[12][5]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.operator.comparison'] + expect(tokens[14][1]).toEqual value: 'if', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control'] + expect(tokens[14][5]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.operator.comparison'] + expect(tokens[14][7]).toEqual value: '&&', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.operator.logical'] + expect(tokens[14][9]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.operator.comparison'] + + it 'tokenizes types and class names with underscore', -> + tokens = tokenizeLines ''' + class _Class { + static _String var1; + static _abc._abc._Class var2; + static _abc._abc._Generic<_String> var3; + } + ''' + + expect(tokens[0][2]).toEqual value: '_Class', scopes: ['source.java', 'entity.name.type.class'] + expect(tokens[1][3]).toEqual value: '_String', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[2][3]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[2][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[2][5]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[2][6]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[2][7]).toEqual value: '_Class', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[3][3]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[3][4]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[3][5]).toEqual value: '_abc', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[3][6]).toEqual value: '.', scopes: ['source.java', 'meta.class.body', 'punctuation.separator.period'] + expect(tokens[3][7]).toEqual value: '_Generic', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[3][8]).toEqual value: '<', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + expect(tokens[3][9]).toEqual value: '_String', scopes: ['source.java', 'meta.class.body', 'storage.type'] + expect(tokens[3][10]).toEqual value: '>', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.angle'] + + it 'tokenizes classes', -> + tokens = tokenizeLine 'public abstract static class A { }' + + expect(tokens[0]).toEqual value: 'public', scopes: ['source.java', 'storage.modifier'] + expect(tokens[2]).toEqual value: 'abstract', scopes: ['source.java', 'storage.modifier'] + expect(tokens[4]).toEqual value: 'static', scopes: ['source.java', 'storage.modifier'] + expect(tokens[6]).toEqual value: 'class', scopes: ['source.java', 'keyword.other.class'] + expect(tokens[8]).toEqual value: 'A', scopes: ['source.java', 'entity.name.type.class'] + expect(tokens[10]).toEqual value: '{', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.curly'] + expect(tokens[12]).toEqual value: '}', scopes: ['source.java', 'meta.class.body', 'punctuation.bracket.curly'] + + tokens = tokenizeLine 'class A extends B implements C, D { }' + + expect(tokens[0]).toEqual value: 'class', scopes: ['source.java', 'keyword.other.class'] + expect(tokens[2]).toEqual value: 'A', scopes: ['source.java', 'entity.name.type.class'] + expect(tokens[4]).toEqual value: 'extends', scopes: ['source.java', 'storage.modifier.extends'] + expect(tokens[6]).toEqual value: 'B', scopes: ['source.java', 'storage.type'] + expect(tokens[8]).toEqual value: 'implements', scopes: ['source.java', 'storage.modifier.implements'] + expect(tokens[10]).toEqual value: 'C', scopes: ['source.java', 'storage.type'] + expect(tokens[13]).toEqual value: 'D', scopes: ['source.java', 'storage.type'] + + it 'tokenizes interfaces', -> + tokens = tokenizeLine 'public interface A { }' + + expect(tokens[0]).toEqual value: 'public', scopes: ['source.java', 'storage.modifier'] + expect(tokens[2]).toEqual value: 'interface', scopes: ['source.java', 'keyword.other.interface'] + expect(tokens[4]).toEqual value: 'A', scopes: ['source.java', 'entity.name.type.interface'] + expect(tokens[6]).toEqual value: '{', scopes: ['source.java', 'meta.interface.body', 'punctuation.bracket.curly'] + expect(tokens[8]).toEqual value: '}', scopes: ['source.java', 'meta.interface.body', 'punctuation.bracket.curly'] + + it 'tokenizes annotated interfaces', -> + tokens = tokenizeLines ''' + public @interface A { + String method() default "abc"; + } + ''' + + expect(tokens[0][0]).toEqual value: 'public', scopes: ['source.java', 'storage.modifier'] + expect(tokens[0][2]).toEqual value: '@interface', scopes: ['source.java', 'keyword.other.interface.annotated'] + expect(tokens[0][4]).toEqual value: 'A', scopes: ['source.java', 'entity.name.type.interface.annotated'] + expect(tokens[0][6]).toEqual value: '{', scopes: ['source.java', 'meta.interface.annotated.body', 'punctuation.bracket.curly'] + expect(tokens[1][1]).toEqual value: 'String', scopes: ['source.java', 'meta.interface.annotated.body', 'storage.type'] + expect(tokens[1][3]).toEqual value: 'method', scopes: ['source.java', 'meta.interface.annotated.body', 'entity.name.function'] + expect(tokens[1][7]).toEqual value: 'default', scopes: ['source.java', 'meta.interface.annotated.body', 'keyword.control'] + expect(tokens[1][9]).toEqual value: '\"abc\"', scopes: ['source.java', 'meta.interface.annotated.body', 'string.quoted.double'] + expect(tokens[2][0]).toEqual value: '}', scopes: ['source.java', 'meta.interface.annotated.body', 'punctuation.bracket.curly'] + + it 'tokenizes enums', -> + tokens = tokenizeLines ''' + public enum A implements B { + CONSTANT1, + CONSTANT2, + Constant3, + constant4 + } + ''' + + expect(tokens[0][0]).toEqual value: 'public', scopes: ['source.java', 'storage.modifier'] + expect(tokens[0][2]).toEqual value: 'enum', scopes: ['source.java', 'keyword.other.enum'] + expect(tokens[0][4]).toEqual value: 'A', scopes: ['source.java', 'entity.name.type.enum'] + expect(tokens[0][6]).toEqual value: 'implements', scopes: ['source.java', 'storage.modifier.implements'] + expect(tokens[0][8]).toEqual value: 'B', scopes: ['source.java', 'storage.type'] + expect(tokens[0][10]).toEqual value: '{', scopes: ['source.java', 'meta.enum.body', 'punctuation.bracket.curly'] + expect(tokens[1][1]).toEqual value: 'CONSTANT1', scopes: ['source.java', 'meta.enum.body', 'constant.other.enum'] + expect(tokens[2][1]).toEqual value: 'CONSTANT2', scopes: ['source.java', 'meta.enum.body', 'constant.other.enum'] + expect(tokens[3][1]).toEqual value: 'Constant3', scopes: ['source.java', 'meta.enum.body', 'constant.other.enum'] + expect(tokens[4][1]).toEqual value: 'constant4', scopes: ['source.java', 'meta.enum.body', 'constant.other.enum'] + expect(tokens[5][0]).toEqual value: '}', scopes: ['source.java', 'meta.enum.body', 'punctuation.bracket.curly'] + + it 'tokenizes enums with modifiers', -> + tokens = tokenizeLines ''' + public enum Test { } + private enum Test { } + protected enum Test { } + ''' + + expect(tokens[0][0]).toEqual value: 'public', scopes: ['source.java', 'storage.modifier'] + expect(tokens[0][2]).toEqual value: 'enum', scopes: ['source.java', 'keyword.other.enum'] + expect(tokens[0][4]).toEqual value: 'Test', scopes: ['source.java', 'entity.name.type.enum'] + expect(tokens[1][0]).toEqual value: 'private', scopes: ['source.java', 'storage.modifier'] + expect(tokens[1][2]).toEqual value: 'enum', scopes: ['source.java', 'keyword.other.enum'] + expect(tokens[1][4]).toEqual value: 'Test', scopes: ['source.java', 'entity.name.type.enum'] + expect(tokens[2][0]).toEqual value: 'protected', scopes: ['source.java', 'storage.modifier'] + expect(tokens[2][2]).toEqual value: 'enum', scopes: ['source.java', 'keyword.other.enum'] + expect(tokens[2][4]).toEqual value: 'Test', scopes: ['source.java', 'entity.name.type.enum'] + + it 'tokenizes annotations', -> + tokens = tokenizeLines ''' + @Annotation1 + @Annotation2() + @Annotation3("value") + @Annotation4(key = "value") + class A { } + ''' + + expect(tokens[0][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.definition.annotation'] + expect(tokens[0][1]).toEqual value: 'Annotation1', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + + expect(tokens[1][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.definition.annotation'] + expect(tokens[1][1]).toEqual value: 'Annotation2', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + expect(tokens[1][2]).toEqual value: '(', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + expect(tokens[1][3]).toEqual value: ')', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + + expect(tokens[2][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.definition.annotation'] + expect(tokens[2][1]).toEqual value: 'Annotation3', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + expect(tokens[2][2]).toEqual value: '(', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + expect(tokens[2][3]).toEqual value: '\"value\"', scopes: ['source.java', 'meta.declaration.annotation', 'string.quoted.double'] + expect(tokens[2][4]).toEqual value: ')', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + + expect(tokens[3][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.definition.annotation'] + expect(tokens[3][1]).toEqual value: 'Annotation4', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + expect(tokens[3][2]).toEqual value: '(', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + expect(tokens[3][3]).toEqual value: 'key', scopes: ['source.java', 'meta.declaration.annotation', 'variable.other.annotation.element'] + expect(tokens[3][5]).toEqual value: '=', scopes: ['source.java', 'meta.declaration.annotation', 'keyword.operator.assignment'] + expect(tokens[3][7]).toEqual value: '\"value\"', scopes: ['source.java', 'meta.declaration.annotation', 'string.quoted.double'] + expect(tokens[3][8]).toEqual value: ')', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + + it 'tokenizes constructor declarations', -> + tokens = tokenizeLines ''' + class A { + public A() throws Exception { + super(); + this.a = 1; + } + } + ''' + + expect(tokens[1][1]).toEqual value: 'public', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.modifier'] + expect(tokens[1][3]).toEqual value: 'A', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'entity.name.function'] + expect(tokens[1][4]).toEqual value: '(', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.bracket.round'] + expect(tokens[1][5]).toEqual value: ')', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'punctuation.bracket.round'] + expect(tokens[1][7]).toEqual value: 'throws', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.modifier.throws'] + expect(tokens[1][9]).toEqual value: 'Exception', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'storage.type'] + expect(tokens[1][11]).toEqual value: '{', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'punctuation.bracket.curly'] + expect(tokens[2][1]).toEqual value: 'super', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'variable.language'] + expect(tokens[2][2]).toEqual value: '(', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'punctuation.bracket.round'] + expect(tokens[2][3]).toEqual value: ')', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'punctuation.bracket.round'] + expect(tokens[2][4]).toEqual value: ';', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'punctuation.terminator.statement'] + expect(tokens[3][1]).toEqual value: 'this', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'variable.language'] + expect(tokens[4][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.body', 'meta.constructor', 'meta.constructor.body', 'punctuation.bracket.curly'] + + it 'tokenizes method declarations', -> + tokens = tokenizeLines ''' + class A { + public int[] func(int size) throws Exception { + return null; + } + + public int FUNC() { + return 1; + } + + public int func2(final int finalScore, final int scorefinal) { + return finalScore; + } + } + ''' + + expect(tokens[1][1]).toEqual value: 'public', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier'] + expect(tokens[1][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[1][4]).toEqual value: '[', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.square'] + expect(tokens[1][5]).toEqual value: ']', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.square'] + expect(tokens[1][7]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'entity.name.function'] + expect(tokens[1][8]).toEqual value: '(', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.round'] + expect(tokens[1][9]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[1][11]).toEqual value: ')', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.round'] + expect(tokens[1][13]).toEqual value: 'throws', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier.throws'] + expect(tokens[1][15]).toEqual value: 'Exception', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[1][17]).toEqual value: '{', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.curly'] + expect(tokens[2][1]).toEqual value: 'return', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control'] + expect(tokens[2][3]).toEqual value: 'null', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'constant.language.null'] + expect(tokens[2][4]).toEqual value: ';', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.terminator.statement'] + expect(tokens[3][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.curly'] + + expect(tokens[5][1]).toEqual value: 'public', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier'] + expect(tokens[5][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[5][5]).toEqual value: 'FUNC', scopes: ['source.java', 'meta.class.body', 'meta.method', 'entity.name.function'] + expect(tokens[5][6]).toEqual value: '(', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.round'] + expect(tokens[5][7]).toEqual value: ')', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.round'] + expect(tokens[5][9]).toEqual value: '{', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.curly'] + expect(tokens[7][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.curly'] + + expect(tokens[9][1]).toEqual value: 'public', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier'] + expect(tokens[9][3]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][5]).toEqual value: 'func2', scopes: ['source.java', 'meta.class.body', 'meta.method', 'entity.name.function'] + expect(tokens[9][6]).toEqual value: '(', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.round'] + expect(tokens[9][7]).toEqual value: 'final', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier'] + expect(tokens[9][9]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][11]).toEqual value: ',', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.separator.delimiter'] + expect(tokens[9][13]).toEqual value: 'final', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.modifier'] + expect(tokens[9][15]).toEqual value: 'int', scopes: ['source.java', 'meta.class.body', 'meta.method', 'storage.type'] + expect(tokens[9][17]).toEqual value: ')', scopes: ['source.java', 'meta.class.body', 'meta.method', 'punctuation.bracket.round'] + expect(tokens[9][19]).toEqual value: '{', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.curly'] + expect(tokens[11][1]).toEqual value: '}', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'punctuation.bracket.curly'] + + it 'tokenizes method invocations', -> + tokens = tokenizeLines ''' + class A { + void func() { + func("arg"); + obj.func("arg"); + obj.prop1.prop2.func(); + obj.prop1.func().prop2.func(); + super.func("arg"); + super.prop1.func("arg"); + this.func("arg"); + this.prop1.func("arg"); + this.prop1.prop2.func("arg"); + this.prop1.func().func("arg"); + property.super.func("arg"); + } + } + ''' + + expect(tokens[2][1]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[3][3]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[4][7]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[5][5]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[5][11]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[6][3]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[7][5]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[8][3]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[9][5]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[10][7]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[11][5]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[11][9]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[12][5]).toEqual value: 'func', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + + it 'tokenizes method references', -> + tokens = tokenizeLines ''' + class A { + void func() { + Arrays.sort(rosterAsArray, Person::compareByAge); + call(Person::new); + call(java.util.ArrayList::new); + call(com.test.Util::create); + call(super::new); + call(testObject::method); + } + } + ''' + + expect(tokens[2][8]).toEqual value: 'Person', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[2][9]).toEqual value: '::', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control.method'] + expect(tokens[2][10]).toEqual value: 'compareByAge', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[3][3]).toEqual value: 'Person', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[3][4]).toEqual value: '::', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control.method'] + expect(tokens[3][5]).toEqual value: 'new', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + expect(tokens[4][3]).toEqual value: 'java', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[4][5]).toEqual value: 'util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[4][7]).toEqual value: 'ArrayList', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[4][9]).toEqual value: 'String', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[4][11]).toEqual value: '::', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control.method'] + expect(tokens[4][12]).toEqual value: 'new', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + # We cannot parse "com.test.Util" correctly in this example + # TODO: fix parsing of "com.test.Util::create" + expect(tokens[5][7]).toEqual value: 'Util', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[5][8]).toEqual value: '::', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control.method'] + expect(tokens[5][9]).toEqual value: 'create', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + + expect(tokens[6][3]).toEqual value: 'super', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'variable.language'] + expect(tokens[6][4]).toEqual value: '::', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control.method'] + expect(tokens[6][5]).toEqual value: 'new', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + # testObject is not scoped as "storage.type" + expect(tokens[7][3]).toEqual value: 'testObject', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body'] + expect(tokens[7][4]).toEqual value: '::', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'keyword.control.method'] + expect(tokens[7][5]).toEqual value: 'method', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'entity.name.function'] + + it 'tokenizes field access', -> + tokens = tokenizeLines ''' + class A { + void func() { + var1 = Test.class; + var2 = com.test.Test.class; + var5 = Test.staticProperty; + System.out.println("test"); + Arrays.sort(array); + } + } + ''' + + expect(tokens[2][4]).toEqual value: 'Test', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + # TODO: it would be good to fix the scope for "com.test" component of the class name + expect(tokens[3][3]).toEqual value: ' com', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body'] + expect(tokens[3][5]).toEqual value: 'test', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body'] + expect(tokens[3][7]).toEqual value: 'Test', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[4][4]).toEqual value: 'Test', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[5][1]).toEqual value: 'System', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] + expect(tokens[6][1]).toEqual value: 'Arrays', scopes: ['source.java', 'meta.class.body', 'meta.method', 'meta.method.body', 'storage.type'] diff --git a/spec/unified-el-spec.coffee b/spec/unified-el-spec.coffee index 29af6ee..af46c58 100644 --- a/spec/unified-el-spec.coffee +++ b/spec/unified-el-spec.coffee @@ -2,6 +2,7 @@ describe 'Unified expression language grammar', -> grammar = null beforeEach -> + atom.config.set('core.useTreeSitterParsers', false) waitsForPromise -> atom.packages.activatePackage('language-java') From 57c3371a69f7d903c88e5b20dfa039420ed8172c Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Sat, 26 Sep 2020 08:08:53 +0200 Subject: [PATCH 50/59] Prepare v0.32.0 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88935ed..bfe89ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.31.5", + "version": "0.32.0", "description": "Java language support in Atom", "engines": { "atom": "*", From 2bd3e55a72b08e171f811a2445343e2df9d89b71 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 3 Oct 2020 18:53:31 +0200 Subject: [PATCH 51/59] Add support for non-sealed keyword (#237) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR adds `non-sealed` keyword as a follow-up to #234. I also had to update the class pattern to capture `-` that is in the keyword. ### Alternate Designs N/A. ### Benefits Adds support for `non-sealed` keyword. ### Possible Drawbacks N/A. ### Applicable Issues Fixes #236 --- grammars/java.cson | 8 ++++---- spec/java-spec.coffee | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/grammars/java.cson b/grammars/java.cson index 5ce9740..c38dca4 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -38,7 +38,7 @@ (abstract|assert|boolean|break|byte|case|catch|char|class| const|continue|default|do|double|else|enum|extends|final| finally|float|for|goto|if|implements|import|instanceof|int| - interface|long|native|new|package|permits|private|protected|public| + interface|long|native|new|non-sealed|package|permits|private|protected|public| return|sealed|short|static|strictfp|super|switch|syncronized|this| throw|throws|transient|try|void|volatile|while|yield| true|false|null)\\b @@ -86,7 +86,7 @@ (abstract|assert|boolean|break|byte|case|catch|char|class| const|continue|default|do|double|else|enum|extends|final| finally|float|for|goto|if|implements|import|instanceof|int| - interface|long|native|new|package|permits|private|protected|public| + interface|long|native|new|non-sealed|package|permits|private|protected|public| return|sealed|short|static|strictfp|super|switch|syncronized|this| throw|throws|transient|try|void|volatile|while|yield| true|false|null)\\b @@ -277,7 +277,7 @@ } ] 'class': - 'begin': '(?=\\w?[\\w\\s]*\\b(?:class|(? expect(lines[4][1]).toEqual value: 'yield', scopes: ['source.java', 'keyword.control.java'] - it 'tokenizes sealed and permits keywords', -> + it 'tokenizes sealed, non-sealed, and permits keywords', -> lines = grammar.tokenizeLines ''' public sealed class X extends A implements B permits C { } public sealed class X permits A extends B implements C { } public sealed class X implements A permits B extends C { } public sealed class Shape permits Circle, Rectangle, Square { } public sealed interface ConstantDesc permits String, Integer { } + public non-sealed class Square extends Shape {} ''' expect(lines[0][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] @@ -3120,3 +3121,4 @@ describe 'Java grammar', -> expect(lines[3][8]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] expect(lines[4][2]).toEqual value: 'sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] expect(lines[4][8]).toEqual value: 'permits', scopes: ['source.java', 'meta.class.java', 'meta.definition.class.permits.classes.java', 'storage.modifier.permits.java'] + expect(lines[5][2]).toEqual value: 'non-sealed', scopes: ['source.java', 'meta.class.java', 'storage.modifier.java'] From 3f1bb765d63dc5481b707fa7baf9612997327631 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 20 Dec 2020 21:53:08 +0100 Subject: [PATCH 52/59] Update CI build ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR updates CI build from Travis and Appveyor to GitHub Actions. This is motivated by the following reasons: - Travis CI API has been having some issues with status propagation, the same applies to Appveyor. - Builds on Travis are stuck sometimes. - Definition is extended to run against ubuntu, macos, and windows. - Consolidates execution into a single file, there is no disparity between configuration files. ### Alternate Designs There was another PR that adds GitHub Actions to this repository; however, it was incomplete, e.g. missing lint step, and did not clean up the previous build files. ### Benefits Fast and reliable builds. ### Possible Drawbacks Potential updates to Atom builds will have to be handled manually instead of relying on community updates to the installation scripts. ### Applicable Issues --- .github/workflows/build.yml | 88 +++++++++++++++++++++++++++++++++++++ .travis.yml | 41 ----------------- README.md | 3 +- appveyor.yml | 30 +------------ 4 files changed, 90 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..c680bdc --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,88 @@ +name: build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + channel: [ stable, beta ] + steps: + - uses: actions/checkout@v2 + + - name: Install Atom and APM (Linux) + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + curl -s -L "https://atom.io/download/deb?channel=${{ matrix.channel }}" -o "atom-amd64.deb" + /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 + dpkg-deb -x atom-amd64.deb ${HOME}/atom + if [ ${{ matrix.channel }} == "stable" ]; then + APP_DIR="${HOME}/atom/usr/share/atom" + else + APP_DIR="${HOME}/atom/usr/share/atom-${{ matrix.channel }}" + fi + echo DISPLAY=":99" >> $GITHUB_ENV + echo "${APP_DIR}" >> $GITHUB_PATH + echo "${APP_DIR}/resources/app/apm/node_modules/.bin" >> $GITHUB_PATH + echo "./node_modules/.bin" >> $GITHUB_PATH + + - name: Install Atom and APM (MacOS) + if: ${{ matrix.os == 'macos-latest' }} + run: | + curl -s -L "https://atom.io/download/mac?channel=${{ matrix.channel }}" -o "atom.zip" + mkdir ${HOME}/.atom && unzip -q atom.zip -d ${HOME}/.atom + if [ ${{ matrix.channel }} == "stable" ]; then + APP_DIR="${HOME}/.atom/Atom.app/Contents/Resources/app" + else + APP_DIR="${HOME}/.atom/Atom ${{ matrix.channel }}.app/Contents/Resources/app" + fi + ln -s "${APP_DIR}/atom.sh" "${APP_DIR}/atom" + echo "${APP_DIR}" >> $GITHUB_PATH + echo "${APP_DIR}/apm/bin" >> $GITHUB_PATH + echo "./node_modules/.bin" >> $GITHUB_PATH + + - name: Install Atom and APM (Windows) + if: ${{ matrix.os == 'windows-latest' }} + run: | + Invoke-WebRequest -Uri "https://atom.io/download/windows_zip?channel=${{ matrix.channel }}" -OutFile "atom.zip" + Unzip "atom.zip" + $ATOM_CHANNEL = "Atom" + if ("${{ matrix.channel }}" -ne "stable") { + $ATOM_CHANNEL += " " + $ATOM_CHANNEL += "${{ matrix.channel }}".substring(0, 1).toupper() + $ATOM_CHANNEL += "${{ matrix.channel }}".substring(1).tolower() + } + echo npm_config_msvs_version="2019" >> ${env:GITHUB_ENV} + echo "$ATOM_CHANNEL/resources/cli" >> ${env:GITHUB_PATH} + echo "$ATOM_CHANNEL/resources/app/apm/bin" >> ${env:GITHUB_PATH} + echo "./node_modules/.bin" >> ${env:GITHUB_PATH} + + - name: Print Atom and APM versions + run: | + atom -v + apm -v + + - name: Install dependencies + run: | + apm install + apm clean + npm install + + - name: Test + run: | + atom --test spec + + - name: Lint + run: | + coffeelint grammars + coffeelint spec diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 64d7056..0000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -### Project specific config ### -language: generic - -env: - global: - - APM_TEST_PACKAGES="" - - ATOM_LINT_WITH_BUNDLED_NODE="true" - - matrix: - - ATOM_CHANNEL=stable - - ATOM_CHANNEL=beta - -### Generic setup follows ### -script: - - curl -s -O https://raw.githubusercontent.com/atom/ci/master/build-package.sh - - chmod u+x build-package.sh - - ./build-package.sh - -notifications: - email: - on_success: never - on_failure: change - -branches: - only: - - master - -git: - depth: 10 - -sudo: false - -dist: xenial - -addons: - apt: - packages: - - build-essential - - fakeroot - - git - - libsecret-1-dev diff --git a/README.md b/README.md index 87380f6..4059238 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Java language support in Atom -[![macOS Build Status](https://travis-ci.org/atom/language-java.svg?branch=master)](https://travis-ci.org/atom/language-java) -[![Windows Build Status](https://ci.appveyor.com/api/projects/status/utoftje56n9u5x4h/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-java/branch/master) +![build](https://github.com/atom/language-java/workflows/build/badge.svg) [![Dependency Status](https://david-dm.org/atom/language-java.svg)](https://david-dm.org/atom/language-java) Add syntax highlighting and snippets to Java/JSP files in Atom. diff --git a/appveyor.yml b/appveyor.yml index 7d07d05..4dd7b0a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,29 +1 @@ -version: "{build}" - -image: Visual Studio 2015 - -platform: x64 - -branches: - only: - - master - -clone_depth: 10 - -skip_tags: true - -environment: - APM_TEST_PACKAGES: - - matrix: - - ATOM_CHANNEL: stable - - ATOM_CHANNEL: beta - -install: - - ps: Install-Product node 4 - -build_script: - - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/atom/ci/master/build-package.ps1')) - -test: off -deploy: off +build: off From 28175882272c411665a5aaf041b3ab4bba0f1812 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 20 Dec 2020 21:58:08 +0100 Subject: [PATCH 53/59] Fix tree-sitter annotations (#242) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR adds missing annotations with scoped identifiers. Previously we only handled single identifiers. This fixes the following cases: ```java class A { @Test.Annotation @Test.Annotation() void func() { // test } } ``` ### Alternate Designs N/A ### Benefits N/A ### Possible Drawbacks ### Applicable Issues Fixes #239 --- grammars/tree-sitter-java.cson | 10 ++++++++-- spec/tree-sitter-java-spec.coffee | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/grammars/tree-sitter-java.cson b/grammars/tree-sitter-java.cson index 65fbdc9..9b026f5 100644 --- a/grammars/tree-sitter-java.cson +++ b/grammars/tree-sitter-java.cson @@ -253,11 +253,17 @@ scopes: 'marker_annotation': 'meta.declaration.annotation' 'marker_annotation > "@"': 'punctuation.definition.annotation' - 'marker_annotation > identifier': 'storage.type.annotation' + ''' + marker_annotation > identifier, + marker_annotation > scoped_identifier > identifier + ''': 'storage.type.annotation' 'annotation': 'meta.declaration.annotation' 'annotation > "@"': 'punctuation.definition.annotation' - 'annotation > identifier': 'storage.type.annotation' + ''' + annotation > identifier, + annotation > scoped_identifier > identifier + ''': 'storage.type.annotation' 'element_value_pair > identifier': 'variable.other.annotation.element' diff --git a/spec/tree-sitter-java-spec.coffee b/spec/tree-sitter-java-spec.coffee index 6e63101..7918e07 100644 --- a/spec/tree-sitter-java-spec.coffee +++ b/spec/tree-sitter-java-spec.coffee @@ -900,6 +900,8 @@ describe 'Tree-sitter based Java grammar', -> @Annotation2() @Annotation3("value") @Annotation4(key = "value") + @Test.Annotation5 + @Test.Annotation6() class A { } ''' @@ -925,6 +927,18 @@ describe 'Tree-sitter based Java grammar', -> expect(tokens[3][7]).toEqual value: '\"value\"', scopes: ['source.java', 'meta.declaration.annotation', 'string.quoted.double'] expect(tokens[3][8]).toEqual value: ')', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + expect(tokens[4][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.definition.annotation'] + expect(tokens[4][1]).toEqual value: 'Test', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + expect(tokens[4][2]).toEqual value: '.', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.separator.period'] + expect(tokens[4][3]).toEqual value: 'Annotation5', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + + expect(tokens[5][0]).toEqual value: '@', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.definition.annotation'] + expect(tokens[5][1]).toEqual value: 'Test', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + expect(tokens[5][2]).toEqual value: '.', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.separator.period'] + expect(tokens[5][3]).toEqual value: 'Annotation6', scopes: ['source.java', 'meta.declaration.annotation', 'storage.type.annotation'] + expect(tokens[5][4]).toEqual value: '(', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + expect(tokens[5][5]).toEqual value: ')', scopes: ['source.java', 'meta.declaration.annotation', 'punctuation.bracket.round'] + it 'tokenizes constructor declarations', -> tokens = tokenizeLines ''' class A { From a757708189c95f9bd8a3bfebc8cf489f9bfa32e5 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 20 Dec 2020 21:59:06 +0100 Subject: [PATCH 54/59] Fix tree-sitter constants (#241) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change This PR fixes syntax highlighting for constants when using tree-sitter. Examples that are fixed now: ```java d = A1_B2_C3; e = A1_B2_C$; f = Test.A1_B2_C3; ``` ### Alternate Designs N/A ### Benefits N/A ### Possible Drawbacks ### Applicable Issues Fixes #240 --- grammars/tree-sitter-java.cson | 4 ++-- spec/tree-sitter-java-spec.coffee | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/grammars/tree-sitter-java.cson b/grammars/tree-sitter-java.cson index 9b026f5..a4cce4d 100644 --- a/grammars/tree-sitter-java.cson +++ b/grammars/tree-sitter-java.cson @@ -298,9 +298,9 @@ scopes: method_reference > identifier, method_invocation > identifier ''': [ - {match: '^[A-Z][A-Z_]+$', scopes: 'constant.other'}, + {match: '^[A-Z][A-Z0-9_\\$]+$', scopes: 'constant.other'}, {match: '^[A-Z]', scopes: 'storage.type'} ] 'identifier': [ - {match: '^[A-Z][A-Z_]+$', scopes: 'constant.other'} + {match: '^[A-Z][A-Z0-9_\\$]+$', scopes: 'constant.other'} ] diff --git a/spec/tree-sitter-java-spec.coffee b/spec/tree-sitter-java-spec.coffee index 7918e07..212ba77 100644 --- a/spec/tree-sitter-java-spec.coffee +++ b/spec/tree-sitter-java-spec.coffee @@ -246,12 +246,18 @@ describe 'Tree-sitter based Java grammar', -> a = CONSTANT + obj.func(); b = conf.get(CONSTANT_ANOTHER); c = Integer.MAX_VALUE; + d = A1_B2_C3; + e = A1_B2_C$; + f = Test.A1_B2_C3; ''' expect(tokens[0][2]).toEqual value: 'CONSTANT_STR', scopes: ['source.java', 'constant.other'] expect(tokens[1][3]).toEqual value: 'CONSTANT', scopes: ['source.java', 'constant.other'] expect(tokens[2][6]).toEqual value: 'CONSTANT_ANOTHER', scopes: ['source.java', 'constant.other'] expect(tokens[3][5]).toEqual value: 'MAX_VALUE', scopes: ['source.java', 'constant.other'] + expect(tokens[4][3]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] + expect(tokens[5][3]).toEqual value: 'A1_B2_C$', scopes: ['source.java', 'constant.other'] + expect(tokens[6][5]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] it 'tokenizes reserved keywords', -> tokens = tokenizeLine 'const value;' From 5f2f890609752c358d093efbfb1d8b0ce91af2f1 Mon Sep 17 00:00:00 2001 From: Ivan Sadikov Date: Sat, 9 Jan 2021 15:40:13 +0100 Subject: [PATCH 55/59] Prepare v0.32.1 release --- package-lock.json | 169 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a6c91c7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,169 @@ +{ + "name": "language-java", + "version": "0.32.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "coffee-script": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.11.1.tgz", + "integrity": "sha1-vxxHrWREOg2V0S3ysUfMCk2q1uk=", + "dev": true + }, + "coffeelint": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-1.16.2.tgz", + "integrity": "sha512-6mzgOo4zb17WfdrSui/cSUEgQ0AQkW3gXDht+6lHkfkqGUtSYKwGdGcXsDfAyuScVzTlTtKdfwkAlJWfqul7zg==", + "dev": true, + "requires": { + "coffee-script": "~1.11.0", + "glob": "^7.0.6", + "ignore": "^3.0.9", + "optimist": "^0.6.1", + "resolve": "^0.6.3", + "strip-json-comments": "^1.0.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "resolve": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", + "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", + "dev": true + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "tree-sitter-java-dev": { + "version": "0.16.0-dev2", + "resolved": "https://registry.npmjs.org/tree-sitter-java-dev/-/tree-sitter-java-dev-0.16.0-dev2.tgz", + "integrity": "sha512-BilPJ2SwvRKMTeq2WZdvVX5HiMYTLSncJATkqWiPRGUl157FcBjY42mzm3M42/5QQybb1nDJjW0tAvVA5iEHmw==", + "requires": { + "nan": "^2.12.1" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/package.json b/package.json index bfe89ad..9d156c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "language-java", - "version": "0.32.0", + "version": "0.32.1", "description": "Java language support in Atom", "engines": { "atom": "*", From 29f977dc42a7e2568b39bb6fb34c4ef108eb59b3 Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Sat, 23 Jan 2021 16:30:07 +0800 Subject: [PATCH 56/59] Highlight comments in module (#246) Signed-off-by: Yan Zhang ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change To enable comments and javadocs in `module` ### Alternate Designs unknown ### Benefits To fix part of #245 ### Possible Drawbacks unknown ### Applicable Issues #245 --- grammars/java.cson | 6 ++++++ spec/java-spec.coffee | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/grammars/java.cson b/grammars/java.cson index c38dca4..fabc151 100644 --- a/grammars/java.cson +++ b/grammars/java.cson @@ -998,6 +998,12 @@ 'contentName': 'meta.module.body.java' 'patterns': [ # TODO: Write more rules for module grammar + { + 'include': '#comments' + } + { + 'include': '#comments-javadoc' + } { 'match': '\\b(requires|transitive|exports|opens|to|uses|provides|with)\\b' 'name': 'keyword.module.java' diff --git a/spec/java-spec.coffee b/spec/java-spec.coffee index fa0f0de..757e071 100644 --- a/spec/java-spec.coffee +++ b/spec/java-spec.coffee @@ -209,6 +209,24 @@ describe 'Java grammar', -> expect(lines[2][3]).toEqual value: 'with', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'keyword.module.java'] expect(lines[3][0]).toEqual value: '}', scopes: ['source.java', 'meta.module.java', 'punctuation.section.module.end.bracket.curly.java'] + it 'tokenizes comments inside module', -> + lines = grammar.tokenizeLines ''' + module com.foo.bar { + // comments + /* comments */ + /** javadoc */ + requires java.base; + } + ''' + + expect(lines[0][0]).toEqual value: 'module', scopes: ['source.java', 'meta.module.java', 'storage.modifier.java'] + expect(lines[0][4]).toEqual value: '{', scopes: ['source.java', 'meta.module.java', 'punctuation.section.module.begin.bracket.curly.java'] + expect(lines[1][2]).toEqual value: ' comments', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'comment.line.double-slash.java'] + expect(lines[2][2]).toEqual value: ' comments ', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'comment.block.java'] + expect(lines[3][2]).toEqual value: ' javadoc ', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'comment.block.javadoc.java'] + expect(lines[4][1]).toEqual value: 'requires', scopes: ['source.java', 'meta.module.java', 'meta.module.body.java', 'keyword.module.java'] + expect(lines[5][0]).toEqual value: '}', scopes: ['source.java', 'meta.module.java', 'punctuation.section.module.end.bracket.curly.java'] + it 'tokenizes classes', -> lines = grammar.tokenizeLines ''' class Thing { From e2874260f8be1ea8de741ed254ddaa2c529e2fa2 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 20 Mar 2021 16:56:25 +0100 Subject: [PATCH 57/59] Add more tests for constants in tree-sitter grammar (#247) ### Requirements * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. * All new code requires tests to ensure against regressions ### Description of the Change The PR adds more tests for various types of constants in situations when they are used as class fields, method names, field names, and in switch statements. ### Alternate Designs N/A ### Benefits N/A ### Possible Drawbacks N/A ### Applicable Issues --- spec/tree-sitter-java-spec.coffee | 42 +++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/spec/tree-sitter-java-spec.coffee b/spec/tree-sitter-java-spec.coffee index 212ba77..0426a2e 100644 --- a/spec/tree-sitter-java-spec.coffee +++ b/spec/tree-sitter-java-spec.coffee @@ -242,7 +242,11 @@ describe 'Tree-sitter based Java grammar', -> it 'tokenizes constants', -> tokens = tokenizeLines ''' - String CONSTANT_STR = "abc"; + String CONSTANT_STR = "value"; + int CONST0 = 0; + int CONST_1 = 1; + String A1_B2_C3 = "abc"; + String A$_B$_C$ = "abc"; a = CONSTANT + obj.func(); b = conf.get(CONSTANT_ANOTHER); c = Integer.MAX_VALUE; @@ -252,12 +256,36 @@ describe 'Tree-sitter based Java grammar', -> ''' expect(tokens[0][2]).toEqual value: 'CONSTANT_STR', scopes: ['source.java', 'constant.other'] - expect(tokens[1][3]).toEqual value: 'CONSTANT', scopes: ['source.java', 'constant.other'] - expect(tokens[2][6]).toEqual value: 'CONSTANT_ANOTHER', scopes: ['source.java', 'constant.other'] - expect(tokens[3][5]).toEqual value: 'MAX_VALUE', scopes: ['source.java', 'constant.other'] - expect(tokens[4][3]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] - expect(tokens[5][3]).toEqual value: 'A1_B2_C$', scopes: ['source.java', 'constant.other'] - expect(tokens[6][5]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] + expect(tokens[1][2]).toEqual value: 'CONST0', scopes: ['source.java', 'constant.other'] + expect(tokens[2][2]).toEqual value: 'CONST_1', scopes: ['source.java', 'constant.other'] + expect(tokens[3][2]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] + expect(tokens[4][2]).toEqual value: 'A$_B$_C$', scopes: ['source.java', 'constant.other'] + expect(tokens[5][3]).toEqual value: 'CONSTANT', scopes: ['source.java', 'constant.other'] + expect(tokens[6][6]).toEqual value: 'CONSTANT_ANOTHER', scopes: ['source.java', 'constant.other'] + expect(tokens[7][5]).toEqual value: 'MAX_VALUE', scopes: ['source.java', 'constant.other'] + expect(tokens[8][3]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] + expect(tokens[9][3]).toEqual value: 'A1_B2_C$', scopes: ['source.java', 'constant.other'] + expect(tokens[10][5]).toEqual value: 'A1_B2_C3', scopes: ['source.java', 'constant.other'] + + it 'tokenizes constants in switch statement', -> + tokens = tokenizeLines ''' + switch (value) { + case CONST: break; + case CONST_STR: break; + case CONST0: break; + case CONST_1: break; + case C0_STR1_DEF2: break; + case C$_STR$_DEF$: break; + default: break; + } + ''' + + expect(tokens[1][3]).toEqual value: 'CONST', scopes: ['source.java', 'constant.other'] + expect(tokens[2][3]).toEqual value: 'CONST_STR', scopes: ['source.java', 'constant.other'] + expect(tokens[3][3]).toEqual value: 'CONST0', scopes: ['source.java', 'constant.other'] + expect(tokens[4][3]).toEqual value: 'CONST_1', scopes: ['source.java', 'constant.other'] + expect(tokens[5][3]).toEqual value: 'C0_STR1_DEF2', scopes: ['source.java', 'constant.other'] + expect(tokens[6][3]).toEqual value: 'C$_STR$_DEF$', scopes: ['source.java', 'constant.other'] it 'tokenizes reserved keywords', -> tokens = tokenizeLine 'const value;' From f1c92ef983fd35947901fb1c853645758390d8e8 Mon Sep 17 00:00:00 2001 From: sadick254 Date: Fri, 23 Apr 2021 20:19:11 +0300 Subject: [PATCH 58/59] Remove appveyor from CI pipeline --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 4dd7b0a..0000000 --- a/appveyor.yml +++ /dev/null @@ -1 +0,0 @@ -build: off From 047fd33bd12f4926bc5dbc0c930cd9d5fa280602 Mon Sep 17 00:00:00 2001 From: Musa Ibrahim Date: Wed, 28 Sep 2022 11:52:01 +0100 Subject: [PATCH 59/59] add sunset message --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4059238..300e493 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# Java language support in Atom +##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/) + # Java language support in Atom ![build](https://github.com/atom/language-java/workflows/build/badge.svg) [![Dependency Status](https://david-dm.org/atom/language-java.svg)](https://david-dm.org/atom/language-java)