diff --git a/grammars/php.cson b/grammars/php.cson index 912c4299..9da58ee1 100644 --- a/grammars/php.cson +++ b/grammars/php.cson @@ -590,7 +590,7 @@ { # Constructor Property Promotion 'begin': '''(?xi) - (public|private|protected) \\s+ + ((?:(?:public|private|protected|readonly)(?:\\s+|(?=\\?)))++) (?: ( (?:\\?\\s*)? [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ | # nullable type [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)+ # union type @@ -599,7 +599,12 @@ ''' 'beginCaptures': '1': - 'name': 'storage.modifier.php' + 'patterns': [ + { + 'match': 'public|private|protected|readonly' + 'name': 'storage.modifier.php' + } + ] '2': 'patterns': [ { @@ -697,7 +702,7 @@ } { 'match': '''(?xi) - ((?:(?:public|private|protected|static)(?:\\s+|(?=\\?)))++) # At least one modifier + ((?:(?:public|private|protected|static|readonly)(?:\\s+|(?=\\?)))++) # At least one modifier ( (?:\\?\\s*)? [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ | # nullable type [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+ (?: \\s*\\|\\s* [a-z0-9_\\x{7f}-\\x{7fffffff}\\\\]+)+ # union type @@ -708,7 +713,7 @@ '1': 'patterns': [ { - 'match': 'public|private|protected|static' + 'match': 'public|private|protected|static|readonly' 'name': 'storage.modifier.php' } ] diff --git a/spec/php-spec.coffee b/spec/php-spec.coffee index 898044a2..23f24163 100644 --- a/spec/php-spec.coffee +++ b/spec/php-spec.coffee @@ -824,6 +824,30 @@ describe 'PHP grammar', -> expect(lines[3][13]).toEqual value: '$', scopes: ["source.php", "meta.class.php", "meta.class.body.php", "variable.other.php", "punctuation.definition.variable.php"] expect(lines[3][14]).toEqual value: 'c2', scopes: ["source.php", "meta.class.php", "meta.class.body.php", "variable.other.php"] + it 'tokenizes readonly properties', -> + lines = grammar.tokenizeLines ''' + class Foo { + public readonly mixed $a; + readonly string $b; + readonly public mixed $c; + } + ''' + + expect(lines[1][1]).toEqual value: 'public', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'storage.modifier.php'] + expect(lines[1][3]).toEqual value: 'readonly', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'storage.modifier.php'] + expect(lines[1][5]).toEqual value: 'mixed', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'keyword.other.type.php'] + expect(lines[1][7]).toEqual value: '$', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'variable.other.php', 'punctuation.definition.variable.php'] + expect(lines[1][8]).toEqual value: 'a', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'variable.other.php'] + expect(lines[2][1]).toEqual value: 'readonly', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'storage.modifier.php'] + expect(lines[2][3]).toEqual value: 'string', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'keyword.other.type.php'] + expect(lines[2][5]).toEqual value: '$', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'variable.other.php', 'punctuation.definition.variable.php'] + expect(lines[2][6]).toEqual value: 'b', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'variable.other.php'] + expect(lines[3][1]).toEqual value: 'readonly', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'storage.modifier.php'] + expect(lines[3][3]).toEqual value: 'public', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'storage.modifier.php'] + expect(lines[3][5]).toEqual value: 'mixed', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'keyword.other.type.php'] + expect(lines[3][7]).toEqual value: '$', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'variable.other.php', 'punctuation.definition.variable.php'] + expect(lines[3][8]).toEqual value: 'c', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'variable.other.php'] + describe 'methods', -> it 'tokenizes basic method', -> lines = grammar.tokenizeLines ''' @@ -915,6 +939,26 @@ describe 'PHP grammar', -> expect(lines[1][17]).toEqual value: '$', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.typehinted.php', 'variable.other.php', 'punctuation.definition.variable.php'] expect(lines[1][18]).toEqual value: 'b', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.typehinted.php', 'variable.other.php'] + it 'tokenizes readonly promoted properties', -> + lines = grammar.tokenizeLines ''' + class Test { + public function __construct(public readonly int $a, readonly protected? string $b) {} + } + ''' + + expect(lines[1][5]).toEqual value: '__construct', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'support.function.constructor.php'] + expect(lines[1][7]).toEqual value: 'public', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'storage.modifier.php'] + expect(lines[1][9]).toEqual value: 'readonly', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'storage.modifier.php'] + expect(lines[1][11]).toEqual value: 'int', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'keyword.other.type.php'] + expect(lines[1][13]).toEqual value: '$', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'variable.other.php', 'punctuation.definition.variable.php'] + expect(lines[1][14]).toEqual value: 'a', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'variable.other.php'] + expect(lines[1][17]).toEqual value: 'readonly', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'storage.modifier.php'] + expect(lines[1][19]).toEqual value: 'protected', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'storage.modifier.php'] + expect(lines[1][20]).toEqual value: '?', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'keyword.operator.nullable-type.php'] + expect(lines[1][22]).toEqual value: 'string', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'keyword.other.type.php'] + expect(lines[1][24]).toEqual value: '$', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'variable.other.php', 'punctuation.definition.variable.php'] + expect(lines[1][25]).toEqual value: 'b', scopes: ['source.php', 'meta.class.php', 'meta.class.body.php', 'meta.function.php', 'meta.function.parameters.php', 'meta.function.parameter.promoted-property.php', 'variable.other.php'] + it 'tokenizes constructor with illegal return type declaration', -> lines = grammar.tokenizeLines ''' class Test {