Skip to content

Commit

Permalink
[JavaScript] Clean up class member code (#3850)
Browse files Browse the repository at this point in the history
Inspired by improvements from #3848.

Consolidate the code handling class members (fields and methods) into a more coherent and stack-based approach.

- Handle “backtrackable” elements (modifiers, accessor keywords, async) in a self-contained way in the `method-declaration` stack.
- As a side benefit of the above, remove the duplicate get/set/async code that was needed due to sublimehq/sublime_text#3494.
- Also expand function scopes to include modifiers.
- Explicitly handle semicolons in class field declarations, letting us mark extraneous semicolons `punctuation.terminator.statement.empty.js` like in statement contexts. (This has proved useful for testing in the past.)
- Remove `static-block-body`, which can be replaced with the regular `block` context.
- Various minor improvements.

Co-authored-by: deathaxe <[email protected]>
  • Loading branch information
Thom1729 and deathaxe authored Oct 31, 2023
1 parent b1f90e4 commit 4e10175
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 110 deletions.
183 changes: 77 additions & 106 deletions JavaScript/JavaScript.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,15 @@ contexts:
pop: 2

immediately-pop:
- meta_include_prototype: false
- match: ''
pop: 1

immediately-pop-2:
- meta_include_prototype: false
- match: ''
pop: 2

comma-separator:
- match: ','
scope: punctuation.separator.comma.js
Expand Down Expand Up @@ -1485,7 +1491,7 @@ contexts:
pop: 1

- match: \;
scope: punctuation.terminator.statement.js
scope: punctuation.terminator.statement.empty.js

- include: decorator

Expand All @@ -1500,68 +1506,19 @@ contexts:
branch_point: static-block
branch:
- static-block
- class-element-modifiers

- match: (?={{modifier}})
push: class-element-modifiers

- match: |-
(?x)(?=
\#? {{identifier_name}}
\s* = \s*
{{either_func_lookahead}}
)
push:
- initializer
- function-name-meta
- literal-variable-base
- match: (?=(?:get|set|async){{identifier_break}})
branch_point: prefixed-method
branch:
- prefixed-method
- class-element

- match: (?=\*)
push: method-declaration

- match: (?={{class_element_name}})
- match: (?=\S)
push: class-element

static-block:
- match: static{{identifier_break}}
scope: storage.modifier.js
set:
- match: \{
scope: punctuation.section.block.begin.js
set: static-block-body
- include: block
- match: (?=\S)
fail: static-block

static-block-body:
- meta_scope: meta.block.js
- match: \}
scope: punctuation.section.block.end.js
pop: 1
- include: statements

class-element-modifiers:
- match: ''
pop: 1
branch_point: class-element-modifier
branch:
- class-element-modifier
- class-element

class-element-modifier:
- match: '{{modifier}}'
scope: storage.modifier.js
set:
- match: (?={{class_element_name}}|\*)
pop: 1
- match: (?=\S)
fail: class-element-modifier

class-extends:
- match: extends{{identifier_break}}
scope: storage.modifier.extends.js
Expand Down Expand Up @@ -1595,61 +1552,46 @@ contexts:
- include: else-pop

class-element:
- meta_include_prototype: false
- match: (?=\*)
set: method-declaration
- match: ''
pop: 1
branch_point: class-field
branch:
- class-field
- method-declaration

prefixed-method:
- match: (?:get|set){{identifier_break}}
scope: storage.type.accessor.js
set:
- meta_scope: meta.function.js
- match: (?={{class_element_name}})
set: method-declaration
- match: (?=\S)
fail: prefixed-method
- match: (?:async){{identifier_break}}
scope: keyword.declaration.async.js
set:
- meta_scope: meta.function.js
- match: (?=\*|{{class_element_name}})
set: method-declaration
- match: (?=\S)
fail: prefixed-method

prefixed-object-literal-method:
- match: (?:get|set){{identifier_break}}
scope: storage.type.accessor.js
set:
- meta_scope: meta.function.js
- match: (?={{class_element_name}})
set: method-declaration
- match: (?=\S)
fail: prefixed-object-literal-method
- match: (?:async){{identifier_break}}
scope: keyword.declaration.async.js
set:
- meta_scope: meta.function.js
- match: (?=\*|{{class_element_name}})
set: method-declaration
- match: (?=\S)
fail: prefixed-object-literal-method

class-field:
- meta_include_prototype: false
- match: ''
set:
- expect-semicolon
- initializer
- class-field-check
- field-name
- class-element-modifiers

class-field-check:
- match: (?=\()
fail: class-field
- include: else-pop

class-element-modifiers:
- match: (?={{modifier}})
branch_point: class-element-modifier
branch:
- - match: '{{modifier}}'
scope: storage.modifier.js
set:
- match: (?={{class_element_name}}|\*)
pop: 1
- match: (?=\S)
fail: class-element-modifier

- immediately-pop-2
- include: else-pop

special-name:
- match: true{{identifier_break}}
scope: constant.language.boolean.true.js
Expand Down Expand Up @@ -1813,12 +1755,6 @@ contexts:
- match: (?=\*)
push: method-declaration

- match: (?=(?:get|set|async){{identifier_break}})
branch_point: prefixed-object-literal-method
branch:
- prefixed-object-literal-method
- object-literal-element

- match: (?={{property_name}})
push: object-literal-element

Expand Down Expand Up @@ -1856,6 +1792,13 @@ contexts:
- include: literal-string
- include: literal-number

- match: (?:get|set|async){{identifier_break}}
pop: 2
set:
- match: (?=\*|{{class_element_name}})
fail: object-literal-property
- include: else-pop

- match: '{{identifier_name}}'
pop: 1

Expand All @@ -1878,6 +1821,7 @@ contexts:
push: expression

object-literal-meta-key:
- meta_include_prototype: false
- meta_scope: meta.mapping.key.js
- include: else-pop

Expand Down Expand Up @@ -1927,19 +1871,24 @@ contexts:
- include: else-pop

field-name:
- match: '{{dollar_identifier}}'
scope: meta.mapping.key.dollar.js variable.other.readwrite.js
captures:
1: punctuation.dollar.js
pop: 1
- match: '{{identifier_name}}'
- match: |-
(?x)(?=
\#? {{identifier_name}}
{{nothing}} =
{{nothing}} {{either_func_lookahead}}
)
set:
- function-name-meta
- literal-variable-base
- match: (?:get|set|async){{identifier_break}}
scope: variable.other.readwrite.js
pop: 1
- match: (#)({{identifier_name}})
captures:
1: punctuation.definition.variable.js
2: variable.other.readwrite.js
pop: 1
set:
- match: (?=\*|{{class_element_name}})
fail: class-field
- include: else-pop
- include: literal-variable-base

- match: "'"
scope: punctuation.definition.string.begin.js
set:
Expand Down Expand Up @@ -1980,12 +1929,34 @@ contexts:
- function-declaration-expect-parameters
- method-name
- method-declaration-expect-asterisk
- method-declaration-prefix
- class-element-modifiers

method-declaration-expect-asterisk:
- match: \*
scope: keyword.generator.asterisk.js
- include: else-pop

method-declaration-prefix:
- match: (?=(?:get|set|async){{identifier_break}})
pop: 1
branch_point: method-declaration-prefix
branch:
- - match: (?:get|set){{identifier_break}}
scope: storage.type.accessor.js
set: method-declaration-prefix-check
- match: (?:async){{identifier_break}}
scope: keyword.declaration.async.js
set: method-declaration-prefix-check
- immediately-pop
- include: else-pop

method-declaration-prefix-check:
- match: (?=\*|{{class_element_name}})
pop: 1
- match: (?=\S)
fail: method-declaration-prefix

parenthesized-expression:
- match: \(
scope: punctuation.section.group.begin.js
Expand Down
9 changes: 6 additions & 3 deletions JavaScript/TypeScript.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -397,19 +397,18 @@ contexts:
- match: '\+|-'
scope: storage.modifier.js
- match: (?={{modifier}})
pop: 1
branch_point: ts-type-member-modifier
branch:
- ts-type-member-modifier
- immediately-pop
- immediately-pop-2
- include: else-pop

ts-type-member-modifier:
- match: '{{modifier}}'
scope: storage.modifier.js
set:
- match: (?={{identifier_start}}|[-+*''"\[\d])
set: ts-type-element-modifiers
pop: 1
- match: (?=\S)
fail: ts-type-member-modifier

Expand Down Expand Up @@ -665,12 +664,14 @@ contexts:
- meta_include_prototype: false
- match: ''
set:
- expect-semicolon
- initializer
- ts-type-annotation
- ts-type-annotation-optional
- ts-type-annotation-definite
- class-field-check
- field-name
- class-element-modifiers

class-field-check:
- match: (?=[(<])
Expand All @@ -688,6 +689,8 @@ contexts:
- ts-type-parameter-list
- method-name
- method-declaration-expect-asterisk
- method-declaration-prefix
- class-element-modifiers

expression-end:
- meta_prepend: true
Expand Down
18 changes: 17 additions & 1 deletion JavaScript/tests/syntax_test_js_class.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class MyClass extends TheirClass {
// ^ variable.other.readwrite
// ^ keyword.operator.assignment
// ^^ constant.numeric
// ^ punctuation.terminator.statement - punctuation.terminator.statement.empty

'y' = 42;
// ^^^ meta.string string.quoted.single
Expand Down Expand Up @@ -121,10 +122,19 @@ class MyClass extends TheirClass {
static = 42;
// ^^^^^^ variable.other.readwrite

static static = 42;
// ^^^^^^ storage.modifier.js
// ^^^^^^ variable.other.readwrite

static() {}
// ^^^^^^^^^^^ meta.function
// ^^^^^^ entity.name.function

static static() {}
// ^^^^^^^^^^^^^^^^^^ meta.function
// ^^^^^^ storage.modifier.js
// ^^^^^^ entity.name.function

accessor foo;
// ^^^^^^^^ storage.modifier
// ^^^ variable.other.readwrite
Expand All @@ -142,7 +152,8 @@ class MyClass extends TheirClass {
for (const param of this.#data.get('value')) {}
// ^ punctuation.definition.variable
// ^^^^ meta.property.object
}
};
// ^ punctuation.terminator.statement.empty.js

#privateMethod() {}
// ^^^^^^^^^^^^^^^^^^^ meta.function
Expand All @@ -168,8 +179,13 @@ class MyClass extends TheirClass {
}

get *foo()
// ^^^^^^^^ meta.function
// ^^^ storage.type.accessor
// ^ keyword.generator.asterisk
// ^^^ entity.name.function

static foo(baz) {
// ^^^^^^^^^^^^^^^^^ meta.function
// ^^^^^^ storage.modifier
// ^^^^^^^^^^ meta.function
// ^^^ entity.name.function
Expand Down

0 comments on commit 4e10175

Please sign in to comment.