From 40ec1f2f9b56fb55d739e17ecd003cc9e8c9b096 Mon Sep 17 00:00:00 2001 From: wbond Date: Fri, 10 Jul 2020 14:28:49 -0400 Subject: [PATCH] [JavaScript] Add JSX and TypeScript syntaxes from Thom1729/JSCustom --- JavaScript/JSX.sublime-syntax | 154 +++++ JavaScript/TypeScript.sublime-syntax | 706 +++++++++++++++++++++ JavaScript/tests/syntax_test_jsx.jsx | 184 ++++++ JavaScript/tests/syntax_test_typescript.ts | 690 ++++++++++++++++++++ 4 files changed, 1734 insertions(+) create mode 100644 JavaScript/JSX.sublime-syntax create mode 100644 JavaScript/TypeScript.sublime-syntax create mode 100644 JavaScript/tests/syntax_test_jsx.jsx create mode 100644 JavaScript/tests/syntax_test_typescript.ts diff --git a/JavaScript/JSX.sublime-syntax b/JavaScript/JSX.sublime-syntax new file mode 100644 index 0000000000..617696d638 --- /dev/null +++ b/JavaScript/JSX.sublime-syntax @@ -0,0 +1,154 @@ +%YAML 1.2 +--- +name: JSX +file_extensions: + - jsx +scope: source.jsx +extends: Packages/JavaScript/JavaScript.sublime-syntax + +variables: + jsx_identifier_part: (?:{{identifier_part}}|-) + jsx_identifier_break: (?!{{jsx_identifier_part}}) + jsx_identifier: '{{identifier_start}}{{jsx_identifier_part}}*{{jsx_identifier_break}}' + +contexts: + expression-begin: + - meta_prepend: true + - include: jsx-tag + + jsx-interpolation: + - match: '{' + scope: punctuation.definition.interpolation.begin.js + push: + - - meta_scope: meta.interpolation.js + - meta_content_scope: source.js.embedded.jsx + - match: '}' + scope: punctuation.definition.interpolation.end.js + pop: true + - expression + + jsx-expect-tag-end: + - meta_content_scope: meta.tag.js + - match: '>' + scope: meta.tag.js punctuation.definition.tag.end.js + pop: true + - include: else-pop + + jsx-meta: + - meta_scope: meta.jsx.js + - include: immediately-pop + + jsx-tag: + - match: '<' + scope: punctuation.definition.tag.begin.js + set: + - jsx-meta + - jsx-tag-attributes-top + + jsx-tag-attributes-top: + - meta_scope: meta.tag.js + - match: '/' + scope: punctuation.definition.tag.begin.js + set: + - - meta_scope: invalid.illegal.unmatched-tag.js + - include: immediately-pop + - jsx-expect-tag-end + - jsx-tag-name + + - match: (?=\S) + set: + - jsx-tag-attributes + - jsx-tag-name + + jsx-tag-attributes: + - meta_content_scope: meta.tag.js + + - match: '>' + scope: punctuation.definition.tag.end.js + set: jsx-body + + - match: '/' + scope: punctuation.definition.tag.end.js + set: jsx-expect-tag-end + + - include: jsx-interpolation + + - match: '{{jsx_identifier}}' + scope: entity.other.attribute-name.js + + - match: '=' + scope: punctuation.separator.key-value.js + push: jsx-attribute-value + + jsx-attribute-value: + - include: jsx-tag + - include: jsx-interpolation + + - match: "'" + scope: punctuation.definition.string.begin.js + set: + - meta_include_prototype: false + - meta_scope: string.quoted.single.js + - match: \' + scope: punctuation.definition.string.end.js + pop: true + - include: jsx-html-escapes + - match: '"' + scope: punctuation.definition.string.begin.js + set: + - meta_include_prototype: false + - meta_scope: string.quoted.double.js + - match: \" + scope: punctuation.definition.string.end.js + pop: true + - include: jsx-html-escapes + + - include: else-pop + + jsx-html-escapes: + - match: '(&)#?[[:alnum:]]+(;)' + scope: constant.character.escape.js + captures: + 1: punctuation.definition.entity.js + 2: punctuation.definition.entity.js + + jsx-tag-name: + - match: '' + set: + - - clear_scopes: 1 + - meta_scope: meta.tag.name.js + - include: immediately-pop + - jsx-tag-name-component + + jsx-tag-name-component: + - match: '{{jsx_identifier}}' + scope: entity.name.tag.js + set: + - match: '[:.]' + scope: punctuation.accessor.js + set: jsx-tag-name + - include: else-pop + - include: else-pop + + jsx-body: + - meta_include_prototype: false + + - match: '<' + scope: punctuation.definition.tag.begin.js + set: + - meta_scope: meta.tag.js + + - match: '/' + scope: punctuation.definition.tag.begin.js + set: + - jsx-expect-tag-end + - jsx-tag-name + + - match: (?=\S) + set: + - jsx-body + - jsx-tag-attributes + - jsx-tag-name + + - include: jsx-html-escapes + - include: jsx-interpolation diff --git a/JavaScript/TypeScript.sublime-syntax b/JavaScript/TypeScript.sublime-syntax new file mode 100644 index 0000000000..fa0e4574d1 --- /dev/null +++ b/JavaScript/TypeScript.sublime-syntax @@ -0,0 +1,706 @@ +%YAML 1.2 +--- +name: TypeScript +file_extensions: + - ts +scope: source.ts +extends: Packages/JavaScript/JSX.sublime-syntax + +variables: + dot_accessor: |- + (?x: # Also match !. + !\. + | + (?: + \. + (?! \? [\[(] ) + \?? + ) + ) + +contexts: + ts-import-type: + - match: type{{identifier_break}} + scope: keyword.control.import-export.js + - include: else-pop + + import-export: + - match: import{{identifier_break}}(?!{{nothing}}[.(]) + scope: keyword.control.import-export.js + set: + - meta_scope: meta.import.js + - match: (?=[.(]) # Recovery for import expressions + set: + - expression-statement-end + - import-expression-end + - match: (?=\S) + set: + - import-meta + - expect-semicolon + - import-string-or-items + - ts-import-type + + - match: export{{identifier_break}} + scope: keyword.control.import-export.js + set: + - export-meta + - export-extended + + export-extended: + - meta_prepend: true + - include: ts-type-declaration + - include: ts-interface-declaration + - include: ts-namespace-declaration + + property-access: + - meta_prepend: true + - match: \!\. + scope: punctuation.accessor.js + push: + - match: '(?={{identifier}}\s*(?:\.\?)?\()' + set: + - call-method-meta + - function-call-arguments + - call-path + - object-property + - include: object-property + + ts-type-declaration: + - match: type{{identifier_break}} + scope: storage.type.js + set: + - ts-type-alias-meta + - ts-type-alias-body + - ts-type-parameter-list + - ts-type-alias-name + + statement: + - meta_prepend: true + - include: ts-enum + - include: ts-type-declaration + - include: ts-interface-declaration + - include: ts-namespace-declaration + + - match: const{{identifier_break}} + scope: storage.type.js + set: + - include: ts-enum + - match: (?=\S) + set: + - expect-semicolon + - variable-binding-list-top + - variable-binding-top + + - match: declare{{identifier_break}} + scope: storage.type.js + set: + - include: ts-enum + - include: else-pop + + - match: abstract{{identifier_break}} + scope: storage.modifier.js + set: + - include: class + - include: else-pop + + class: + - match: class{{identifier_break}} + scope: storage.type.class.js + set: + - class-meta + - class-body + - ts-class-implements + - class-extends + - class-name + + ts-class-implements: + - match: implements{{identifier_break}} + scope: storage.modifier.implements.js + set: + - - match: \, + scope: punctuation.separator.comma.js + push: + - inherited-class-expression-end + - inherited-class-expression-begin + - include: else-pop + - inherited-class-expression-end + - inherited-class-expression-begin + - include: else-pop + + inherited-class-expression-end: + - meta_prepend: true + - include: ts-generic-type-arguments + + class-name: + - match: '{{non_reserved_identifier}}' + scope: entity.name.class.js + set: ts-type-parameter-list + - include: else-pop + + ts-interface-declaration: + - match: interface{{identifier_break}} + scope: storage.type.js + set: + - ts-interface-meta + - ts-type-body + - ts-type-parameter-list + - ts-interface-name + + ts-interface-meta: + - meta_include_prototype: false + - meta_scope: meta.interface.js + - include: immediately-pop + + ts-interface-name: + - match: '{{identifier}}' + scope: entity.name.interface.js + pop: true + - include: else-pop + + ts-type-body: + - match: \{ + scope: punctuation.section.block.begin.js + set: + - meta_scope: meta.block.js + - match: \} + scope: punctuation.section.block.end.js + pop: true + - match: '[,;]' + scope: punctuation.separator.js + - include: ts-type-member + + ts-type-member: + - match: '\+|-' + scope: storage.modifier.js + + - match: readonly{{identifier_break}} + scope: storage.modifier.js + + - match: (?=[<(]) + push: + - ts-type-annotation + - function-declaration-expect-parameters + - ts-type-parameter-list + + - match: \[ + scope: punctuation.section.brackets.begin.js + push: + - - include: immediately-pop + - ts-type-annotation + - ts-type-annotation-optional + - - match: '\+|-' + scope: storage.modifier.js + pop: true + - include: else-pop + - - meta_scope: meta.brackets.js + - match: \] + scope: punctuation.section.brackets.end.js + pop: true + - match: '{{identifier}}' + scope: variable.other.readwrite.js + push: + - match: in{{identifier_break}} + scope: keyword.operator.type.js + set: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: ts-type-annotation + + - match: new{{identifier_break}} + scope: keyword.operator.new.js + push: + - ts-type-annotation + - function-declaration-expect-parameters + - ts-type-parameter-list + + - match: '{{identifier}}' + scope: variable.other.readwrite.js + push: + - - match: (?=[<(]) + set: + - ts-type-annotation + - function-declaration-expect-parameters + - ts-type-parameter-list + - match: (?=\S) + set: ts-type-annotation + - ts-type-annotation-optional + + ts-enum: + - match: enum{{identifier_break}} + scope: storage.type.js + set: + - ts-enum-meta + - ts-enum-body + - ts-enum-name + + ts-enum-meta: + - meta_include_prototype: false + - meta_scope: meta.enum.js + - include: immediately-pop + + ts-enum-name: + - match: '{{identifier}}' + scope: entity.name.enum.js + pop: true + - include: else-pop + + ts-enum-body: + - match: \{ + scope: punctuation.section.block.begin.js + set: + - meta_scope: meta.block.js + - match: \} + scope: punctuation.section.block.end.js + pop: true + - include: comma-separator + - match: (?=['"]) + push: literal-string + - match: '{{identifier}}' + scope: variable.other.readwrite.js + push: initializer + + ts-type-alias-meta: + - meta_include_prototype: false + - meta_scope: meta.type-alias.js + - include: immediately-pop + + ts-type-alias-name: + - match: '{{identifier}}' + scope: entity.name.type.js + pop: true + - include: else-pop + + ts-type-alias-body: + - match: '=' + scope: keyword.operator.assignment.js + set: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + + ts-namespace-declaration: + - match: namespace{{identifier_break}} + scope: storage.type.js + set: + - ts-namespace-meta + - block + - ts-namespace-name + + ts-namespace-meta: + - meta_include_prototype: false + - meta_scope: meta.namespace.js + - include: immediately-pop + + ts-namespace-name: + - match: '{{identifier}}' + scope: entity.name.namespace.js + pop: true + - include: else-pop + + variable-binding-pattern: + - match: '' + set: + - - include: immediately-pop + - ts-type-annotation + - ts-type-annotation-definite + - - include: variable-binding-name + - include: variable-binding-array-destructuring + - include: variable-binding-object-destructuring + - include: else-pop + + function-declaration: + - meta_include_prototype: false + - match: '' + set: + - function-meta + - function-declaration-expect-body + - function-declaration-meta + - ts-type-annotation + - function-declaration-expect-parameters + - ts-type-parameter-list + - function-declaration-expect-name + - function-declaration-expect-generator-star + - function-declaration-expect-function-keyword + - function-declaration-expect-async + + ts-type-parameter-list: + - match: \< + scope: punctuation.definition.generic.begin.js + set: + - meta_scope: meta.generic.js + - match: \> + scope: punctuation.definition.generic.end.js + pop: true + - match: '{{identifier}}' + scope: variable.parameter.generic.js + push: + - ts-type-parameter-default + - ts-type-parameter-constraint + - include: comma-separator + - include: else-pop + + ts-type-parameter-constraint: + - match: extends{{identifier_break}} + scope: storage.modifier.extends.js + push: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + + ts-type-parameter-default: + - match: '=' + scope: keyword.operator.assignment.js + set: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + + function-parameter-binding-pattern: + - match: '' + set: + - - include: ts-type-annotation + - - include: ts-type-annotation-optional + - - include: function-parameter-binding-name + - include: function-parameter-binding-array-destructuring + - include: function-parameter-binding-object-destructuring + - include: else-pop + + function-parameter-binding-list: + - meta_prepend: true + - match: (?:private|public|protected|readonly){{identifier_break}} + scope: storage.modifier.js + + - match: this{{identifier_break}} + scope: variable.language.this.js + push: ts-type-annotation + + class-body-contents: + - meta_prepend: true + - match: (?:private|public|protected|readonly|abstract|declare){{identifier_break}} + scope: storage.modifier.js + + field-initializer-or-method-declaration: + - match: (?=\(|<) + set: + - function-meta + - function-declaration-expect-body + - function-declaration-meta + - ts-type-annotation + - function-declaration-expect-parameters + - ts-type-parameter-list + - match: (?=\S) + set: + - class-field-rest + - initializer + - ts-type-annotation + - ts-type-annotation-optional + + method-declaration: + - meta_include_prototype: false + - match: '' + set: + - function-meta + - function-declaration-expect-body + - function-declaration-meta + - ts-type-annotation + - function-declaration-expect-parameters + - ts-type-parameter-list + - method-name + - method-declaration-expect-prefix + - function-declaration-expect-async + + expression-end: + - meta_prepend: true + - include: ts-type-assertion + + expression-begin: + - meta_prepend: true + - match: \< + scope: punctuation.definition.assertion.begin.js + set: + - - meta_scope: meta.assertion.js + - match: \> + scope: punctuation.definition.assertion.end.js + pop: true + - include: else-pop + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - match: (?=\b\B) + + ts-type-assertion: + - match: '!(?!\.)' + scope: keyword.operator.type.js + + - match: as{{identifier_break}} + scope: keyword.operator.type.js + push: + - match: const{{identifier_break}} + scope: storage.modifier.const.js + pop: true + - match: (?=\S) + set: + - ts-type-meta + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + + ts-type-annotation: + - match: ':' + scope: punctuation.separator.type.js + set: + - ts-type-meta + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + + ts-type-annotation-optional: + - match: \? + scope: storage.modifier.optional.js + pop: true + - include: else-pop + + ts-type-annotation-definite: + - match: \! + scope: storage.modifier.definite.js + pop: true + - include: else-pop + + ts-type-meta: + - meta_include_prototype: false + - meta_content_scope: meta.type.js + - include: immediately-pop + + ts-type-expression-end: + - match: \& + scope: keyword.operator.type.intersection.js + push: [ts-type-expression-end-no-line-terminator, ts-type-expression-begin] + - match: \| + scope: keyword.operator.type.union.js + push: [ts-type-expression-end-no-line-terminator, ts-type-expression-begin] + - match: is{{identifier_break}} + scope: keyword.operator.word.js + push: [ts-type-expression-end-no-line-terminator, ts-type-expression-begin] + - match: \. + scope: punctuation.separator.accessor.js + push: + - match: '{{identifier}}' + scope: support.class.js + pop: true + + - match: extends{{identifier_break}} + scope: keyword.operator.type.extends.js + push: + - - match: \? + scope: keyword.operator.type.js + set: + - - match: ':' + scope: keyword.operator.type.js + set: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + + - include: else-pop + + ts-type-expression-end-no-line-terminator: + - meta_include_prototype: false + - match: '{{line_ending_ahead}}' + pop: true + - include: prototype + + - match: \[(?={{nothing}}\]) + scope: storage.modifier.array.js + push: + - match: \] + scope: storage.modifier.array.js + pop: true + - include: else-pop + + - match: \[ + scope: punctuation.section.brackets.begin.js + push: + - meta_scope: meta.brackets.js + - match: \] + scope: punctuation.section.brackets.end.js + pop: true + - match: (?=\S) + push: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + + - include: ts-generic-type-arguments + + - include: else-pop + + ts-generic-type-arguments: + - match: \< + scope: punctuation.definition.generic.begin.js + set: + - meta_scope: meta.generic.js + - match: \> + scope: punctuation.definition.generic.end.js + pop: true + - include: comma-separator + - match: (?=\S) + push: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + + ts-type-expression-begin: + - match: keyof{{identifier_break}} + scope: keyword.operator.type.js + - match: typeof{{identifier_break}} + scope: keyword.operator.type.js + - match: infer{{identifier_break}} + scope: keyword.operator.type.js + + - match: unique{{identifier_break}} + scope: storage.modifier.unique.js + - match: readonly{{identifier_break}} + scope: storage.modifier.readonly.js + - match: asserts{{identifier_break}} + scope: storage.modifier.asserts.js + + - match: import{{identifier_break}} + scope: keyword.operator.type.js + set: + - match: \( + scope: punctuation.section.group.begin.js + set: + - meta_scope: meta.group.js + - match: \) + scope: punctuation.section.group.end.js + pop: true + - match: (?=['"]) + push: literal-string + - include: else-pop + + - include: ts-type-tuple + - include: ts-type-body + - include: ts-type-special + - include: ts-type-primitive + - include: ts-type-basic + - include: ts-type-function + + - include: literal-string + - include: literal-number + + - include: else-pop + + ts-type-tuple: + - match: \[ + scope: punctuation.section.brackets.begin.js + set: + - meta_scope: meta.sequence.js + - match: \] + scope: punctuation.section.brackets.end.js + pop: true + - include: comma-separator + - match: \.\.\. + scope: keyword.operator.spread.js + - match: (?=\S) + push: + - ts-type-annotation-optional + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + + ts-type-object: + - match: \{ + scope: punctuation.section.braces.begin.js + set: + - meta_scope: meta.mapping.js + - match: \} + scope: punctuation.section.braces.end.js + pop: true + - include: comma-separator + - match: ; + scope: punctuation.separator.semicolon.js + - match: '{{identifier}}' + scope: variable.other.readwrite.js + push: + - ts-type-annotation + - ts-type-annotation-optional + + ts-type-special: + - match: 'any{{identifier_break}}' + scope: 'support.type.any.js' + pop: true + - match: 'void{{identifier_break}}' + scope: 'support.type.void.js' + pop: true + - match: 'never{{identifier_break}}' + scope: 'support.type.never.js' + pop: true + - match: 'unknown{{identifier_break}}' + scope: 'support.type.unknown.js' + pop: true + + ts-type-primitive: + - match: 'boolean{{identifier_break}}' + scope: 'support.type.primitive.boolean.js' + pop: true + - match: 'number{{identifier_break}}' + scope: 'support.type.primitive.number.js' + pop: true + - match: 'string{{identifier_break}}' + scope: 'support.type.primitive.string.js' + pop: true + - match: 'null{{identifier_break}}' + scope: 'support.type.primitive.null.js' + pop: true + - match: 'undefined{{identifier_break}}' + scope: 'support.type.primitive.undefined.js' + pop: true + - match: 'object{{identifier_break}}' + scope: 'support.type.primitive.object.js' + pop: true + - match: 'symbol{{identifier_break}}' + scope: 'support.type.primitive.symbol.js' + pop: true + - match: 'bigint{{identifier_break}}' + scope: 'support.type.primitive.bigint.js' + pop: true + + ts-type-basic: + - match: '{{identifier}}' + scope: support.class.js + pop: true + + ts-type-function: + - match: \( + scope: punctuation.section.group.begin.js + set: + - meta_scope: meta.group.js + - match: \) + scope: punctuation.section.group.end.js + set: + - match: => + scope: storage.type.function.js + set: + - ts-type-expression-end + - ts-type-expression-end-no-line-terminator + - ts-type-expression-begin + - include: else-pop + - include: comma-separator + - match: '{{identifier}}' + scope: variable.other.readwrite.js + push: + - ts-type-annotation + - ts-type-annotation-optional diff --git a/JavaScript/tests/syntax_test_jsx.jsx b/JavaScript/tests/syntax_test_jsx.jsx new file mode 100644 index 0000000000..612a726f01 --- /dev/null +++ b/JavaScript/tests/syntax_test_jsx.jsx @@ -0,0 +1,184 @@ +// SYNTAX TEST "Packages/JavaScript/JSX.sublime-syntax" + + ; +// ^^^^^^^ meta.jsx meta.tag +// ^ punctuation.definition.tag.begin +// ^^^ meta.tag.name entity.name.tag +// ^^ punctuation.definition.tag.end + + Hello!; +// ^^^^^^^^^^^^^^^^^ meta.jsx +// ^^^^^ meta.tag +// ^ punctuation.definition.tag.begin +// ^^^ meta.tag.name entity.name.tag +// ^ punctuation.definition.tag.end +// ^^^^^^ - meta.tag +// ^^^^^^ meta.tag +// ^^ punctuation.definition.tag.begin +// ^^^ meta.tag.name entity.name.tag +// ^ punctuation.definition.tag.end + + Hello!; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.jsx +// ^^^^^^^^^^^^^ meta.tag +// ^^^^^^^^^^^ meta.tag.name +// ^ punctuation.accessor +// ^ punctuation.accessor +// ^^^ entity.name.tag +// ^^^^^^ - meta.tag +// ^^^^^^^^^^^^^^ meta.tag +// ^^^^^^^^^^^ meta.tag.name +// ^ punctuation.accessor +// ^ punctuation.accessor +// ^^^ entity.name.tag + + Hello!World!; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.jsx +// ^^^^^ meta.tag +// ^^^^^^ - meta.tag +// ^^^^^^ meta.tag +// ^^^^^^ - meta.tag +// ^^^^^^ meta.tag + + +// ^^^^^^^^^^^ meta.jsx +// ^^^^^ - meta.jsx +// ^ keyword.operator.relational +// ^^^ variable +// ^ keyword.operator.relational +0; + + <>Hello!; +// ^^^^^^^^^^^ meta.jsx +// ^^ meta.tag +// ^ punctuation.definition.tag.begin +// ^ punctuation.definition.tag.end +// ^^^^^^ - meta.tag +// ^^^ meta.tag +// ^^ punctuation.definition.tag.begin +// ^ punctuation.definition.tag.end + + + +// ^^^^^ - meta.jsx +// ^ keyword.operator.relational +// ^^^ variable +// ^ keyword.operator.relational +0; + + ; +// ^^^^ invalid.illegal.unmatched-tag + +; +// <- meta.jsx meta.tag punctuation.definition.tag.end + + + // test +// ^^^^^^^^ - comment + + /* test */ +// ^^^^^^^^^^ - comment + +     ; +// ^^^^^^ constant.character.escape +// ^ punctuation.definition.entity +// ^ punctuation.definition.entity +// ^^^^^^^ - constant.character.escape + + {xyzzy} +// ^^^^^^^ meta.interpolation +// ^^^^^ source.js.embedded.jsx variable.other.readwrite + + {{ xyzzy:42 }} +// ^^^^^^^^^^^^^^ meta.interpolation +// ^^^^^^^^^^^^ source.js.embedded.jsx +// ^^^^^^^^^^^^ meta.mapping +// ^^^^^ meta.mapping.key +// ^ punctuation.separator.key-value +// ^^ constant.numeric.integer.decimal +// ^ punctuation.definition.interpolation.end + + {//} +// ^ punctuation.definition.interpolation.begin +// ^^^ comment.line.double-slash +// ^^ punctuation.definition.comment +// ^ - punctuation + } +// ^ punctuation.definition.interpolation.end + \ No newline at end of file diff --git a/JavaScript/tests/syntax_test_typescript.ts b/JavaScript/tests/syntax_test_typescript.ts new file mode 100644 index 0000000000..c8b26c5055 --- /dev/null +++ b/JavaScript/tests/syntax_test_typescript.ts @@ -0,0 +1,690 @@ +// SYNTAX TEST "Packages/JavaScript/TypeScript.sublime-syntax" + +/* Import/Export */ + + import type T from 'somewhere'; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import +// ^^^^^^ keyword.control.import-export +// ^^^^ keyword.control.import-export +// ^ variable.other.readwrite +// ^^^^ keyword.control.import-export +// ^^^^^^^^^^^ meta.string string.quoted.single + + import type { U, V } from 'somewhere'; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.import +// ^^^^^^ keyword.control.import-export +// ^^^^ keyword.control.import-export +// ^^^^^^^^ meta.block +// ^ variable.other.readwrite +// ^ punctuation.separator.comma +// ^ variable.other.readwrite +// ^^^^ keyword.control.import-export +// ^^^^^^^^^^^ meta.string string.quoted.single + + export type T = any; +// ^^^^^^^^^^^^^^^^^^^ meta.export +// ^^^^^^ keyword.control.import-export +// ^^^^^^^^^^^^ meta.type-alias +// ^ punctuation.terminator.statement.empty - meta.export + + export interface Foo {} +// ^^^^^^^^^^^^^^^^^^^^^^^ meta.export +// ^^^^^^ keyword.control.import-export +// ^^^^^^^^^^^^^^^^ meta.interface +// ^^^^^^^^^ storage.type +// ^^^ entity.name.interface +// ^^ meta.block + + export namespace Foo {} +// ^^^^^^^^^^^^^^^^^^^^^^^ meta.export +// ^^^^^^ keyword.control.import-export +// ^^^^^^^^^^^^^^^^ meta.namespace +// ^^^^^^^^^ storage.type +// ^^^ entity.name.namespace +// ^^ meta.block + +/* Declarations */ + + interface Foo { +// ^^^^^^^^^^^^^^^^ meta.interface +// ^^^^^^^^^ storage.type +// ^^^ entity.name.interface +// ^ meta.block punctuation.section.block.begin + foo: any; +//^^^^^^^^^^^^^^^^ meta.interface meta.block +// ^^^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^ punctuation.separator + bar?: any; +//^^^^^^^^^^^^^^^^^ meta.interface meta.block +// ^^^ variable.other.readwrite +// ^ storage.modifier.optional +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^ punctuation.separator + } +// ^ meta.block punctuation.section.block.end + + enum Foo { +// ^^^^^^^^^^^ meta.enum +// ^^^^ storage.type +// ^^^ entity.name.enum +// ^ punctuation.section.block.begin + x, +// ^ variable.other.readwrite +// ^ punctuation.separator.comma + y = 2, +// ^ variable.other.readwrite +// ^ keyword.operator.assignment +// ^ constant.numeric.integer.decimal +// ^ punctuation.separator.comma + + 'FOO' +// ^^^^^ meta.string string.quoted.single + "FOO" +// ^^^^^ meta.string string.quoted.double + } +// ^ meta.enum meta.block punctuation.section.block.end + + const enum Foo {} +// ^^^^^ storage.type +// ^^^^^^^^^^^ meta.enum +// ^^^^ storage.type +// ^^^ entity.name.enum + + declare enum Foo {} +// ^^^^^^^ storage.type +// ^^^^^^^^^^^ meta.enum +// ^^^^ storage.type +// ^^^ entity.name.enum + + type x < T > = any; +// ^^^^^^^^^^^^^^^^^^ meta.type-alias +// ^^^^ storage.type +// ^ entity.name.type +// ^^^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ variable.parameter.generic +// ^ punctuation.definition.generic.end +// ^ keyword.operator.assignment +// ^^^ meta.type-alias support.type.any + + type x < T = Foo > = any; +// ^^^^^^^^^^^^^^^^^^^^^^^^ meta.type-alias +// ^^^^ storage.type +// ^ entity.name.type +// ^^^^^^^^^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ variable.parameter.generic +// ^ keyword.operator.assignment +// ^^^ support.class +// ^ punctuation.definition.generic.end +// ^ keyword.operator.assignment +// ^^^ meta.type-alias support.type.any + + class Foo { + foo: any = 42; +// ^^^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^ keyword.operator.assignment + + foo?: any; +// ^^^ variable.other.readwrite +// ^ storage.modifier.optional +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any + + declare foo; +// ^^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + + #foo: any; +// ^ punctuation.definition.variable +// ^^^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any + + public foo; +// ^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + private foo; +// ^^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + protected foo; +// ^^^^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + readonly foo; +// ^^^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + + private static foo; +// ^^^^^^^ storage.modifier +// ^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + + foo(): any {} +// ^^^^^^^^^^^ meta.function.declaration +// ^^^ entity.name.function +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^^ meta.function meta.block + } + + abstract class Foo { +// ^^^^^^^^ storage.modifier +// ^^^^^ meta.class storage.type.class + + abstract foo; +// ^^^^^^^^ storage.modifier +// ^^^ variable.other.readwrite + + } + + class Foo < T > extends Bar implements Baz, Xyzzy { } +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.class +// ^^^^^ storage.type.class +// ^^^ entity.name.class +// ^^^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ variable.parameter.generic +// ^ punctuation.definition.generic.end +// ^^^^^^^ storage.modifier.extends +// ^^^ entity.other.inherited-class +// ^^^^^^^^^^ storage.modifier.implements +// ^^^ entity.other.inherited-class +// ^ punctuation.separator.comma +// ^^^^^ entity.other.inherited-class +// ^^^ meta.block + + class Foo extends Bar < T > implements Bar < T > {} +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.class +// ^^^ entity.other.inherited-class +// ^^^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ support.class +// ^ punctuation.definition.generic.end +// ^^^ entity.other.inherited-class +// ^^^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ support.class +// ^ punctuation.definition.generic.end +// ^^ meta.block + + namespace Foo { +// ^^^^^^^^^^^^^^^^ meta.namespace +// ^^^^^^^^^ storage.type +// ^^^ entity.name.namespace +// ^ meta.block punctuation.section.block.begin + } +// ^ meta.block punctuation.section.block.end + +/* Annotations */ + +var x: any = 42; +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^^^^^^ - meta.type +// ^ keyword.operator.assignment + +let x: any = 42; +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^^^^^^ - meta.type +// ^ keyword.operator.assignment + +const x: any = 42; +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^^^^^^ - meta.type +// ^ keyword.operator.assignment + +let [ x: any = 42 ]; +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^ keyword.operator.assignment + +let x !: any ; +// ^ variable.other.readwrite +// ^ storage.modifier.definite +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any + +function f(x: any = 42) {} +// ^ punctuation.separator.type +// ^^^meta.type support.type.any +// ^ keyword.operator.assignment + +function f(public x) {} +// ^^^^^^ storage.modifier +// ^ meta.binding.name variable.parameter.function + +function f(readonly x) {} +// ^^^^^^^^ storage.modifier +// ^ meta.binding.name variable.parameter.function + +function f(x?: any) {} +// ^ storage.modifier.optional +// ^ punctuation.separator.type + +function f(): any {} +//^^^^^^^^^^^^^^^^^^ meta.function +//^^^^^^ meta.function.declaration +// ^ punctuation.separator.type +// ^^^meta.type support.type.any +// ^^ meta.block + +function f ( x : any , ... y : any ) {} +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.declaration +// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.declaration +// ^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^ punctuation.separator.parameter.function +// ^^^ keyword.operator.spread +// ^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any + +function f() {} +//^^^^^^^^^^^^^^^^^^^ meta.function +//^^^^^^^^^^^^^^^^^ meta.function.declaration +// ^^^^^^ meta.generic +// ^ variable.parameter.generic +// ^ punctuation.separator.comma +// ^ variable.parameter.generic + +function f(x): x is any {}; +//^^^^^^^^^^^^^^^^^^^^^^^^ meta.function +//^^^^^^^^^^^^^^^^^^^^^^ meta.function.declaration +// ^ punctuation.separator.type +// ^^^^^^^^^ meta.type +// ^^ keyword.operator.word +// ^^^ support.type.any + +function f(x): asserts x is any {}; +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function.declaration +// ^ punctuation.separator.type +// ^^^^^^^^^^^^^^^^^ meta.type +// ^^^^^^^ storage.modifier.asserts +// ^^ keyword.operator.word +// ^^^ support.type.any + +function f(this : any) {} +// ^^^^ variable.language.this +// ^ punctuation.separator.type +// ^^^ support.type.any + + (x: any) => 42; +// ^^^^^^^^^^^^^^ meta.function +// ^^^^^^^^^^^ meta.function.declaration +// ^ punctuation.separator.type +// ^^^ meta.type support.type.any +// ^^ storage.type.function.arrow + +/* Assertions */ + +x as boolean; +//^^ keyword.operator.type +// ^^^^^^^ meta.type support.type.primitive.boolean + +x as const; +//^^ keyword.operator.type +// ^^^^^ storage.modifier.const + + foo!.bar; +// ^^ punctuation.accessor + + x ! ; +// ^ variable.other.readwrite +// ^ keyword.operator.type +// ^ punctuation.terminator.statement + + +/* Types */ + +let x: any; +// ^^^ support.type.any +let x: void; +// ^^^^ support.type.void +let x: never; +// ^^^^^ support.type.never +let x: unknown; +// ^^^^^^^ support.type.unknown + +let x: boolean; +// ^^^^^^^ support.type.primitive.boolean +let x: number; +// ^^^^^^ support.type.primitive.number +let x: string; +// ^^^^^^ support.type.primitive.string +let x: null; +// ^^^^ support.type.primitive.null +let x: undefined; +// ^^^^^^^^^ support.type.primitive.undefined +let x: object; +// ^^^^^^ support.type.primitive.object +let x: symbol; +// ^^^^^^ support.type.primitive.symbol +let x: unique symbol; +// ^^^^^^ storage.modifier.unique +// ^^^^^^ support.type.primitive.symbol +let x: bigint; +// ^^^^^^ support.type.primitive.bigint + +let x: Foo; +// ^^^ support.class + +let x: any [ ]; +// ^^^^^^ meta.type +// ^^^ support.type.any +// ^ storage.modifier.array +// ^ storage.modifier.array + +let x: readonly any []; +// ^^^^^^^^^^^^^^^ meta.type +// ^^^^^^^^ storage.modifier.readonly +// ^^^ support.type.any +// ^^ storage.modifier.array + +let x: any [ "foo" | 'bar' ]; +// ^^^^^^^^^^^^^^^^^^^^^ meta.type +// ^^^ support.type.any +// ^^^^^^^^^^^^^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^^^^^ meta.string string.quoted.double +// ^ keyword.operator.type.union +// ^^^^^ meta.string string.quoted.single +// ^ punctuation.section.brackets.end + + +let x: any [ 0 ]; +// ^^^^^ meta.type meta.brackets +// ^ punctuation.section.brackets.begin +// ^ constant.numeric.integer.decimal +// ^ punctuation.section.brackets.end + +let x: any [ +// ^^^^^^ meta.type +// ^^^ support.type.any +// ^ punctuation.section.brackets.begin + ]; +// ^ punctuation.section.brackets.end + + +let x: any +// ^^^ meta.type support.type.any + []; +// ^^ meta.sequence punctuation.section.brackets - meta.type + +let x: Foo; +// ^^^^^^^^^^^^^ meta.type +// ^^^ support.class +// ^^^^^^^^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^^^ support.type.any +// ^ punctuation.separator.comma +// ^^^ support.type.any +// ^ punctuation.definition.generic.end + + +function f() {} +// ^^^^^^^^^^^^^^^ meta.function.declaration meta.generic +// ^ variable.parameter.generic +// ^^^^^^^ storage.modifier.extends +// ^^^ support.class + +let x: [ any , any ? , ... any [] ]; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.type meta.sequence +// ^ punctuation.section.brackets.begin +// ^^^ support.type.any +// ^ punctuation.separator.comma +// ^^^ support.type.any +// ^ storage.modifier.optional +// ^ punctuation.separator.comma +// ^^^ keyword.operator.spread +// ^^^ support.type.any +// ^^ storage.modifier.array +// ^ punctuation.section.brackets.end + +let x: any & any; +// ^^^^^^^^^ meta.type +// ^^^ support.type.any +// ^ keyword.operator.type.intersection +// ^^^ support.type.any + +let x: any | any; +// ^^^^^^^^^ meta.type +// ^^^ support.type.any +// ^ keyword.operator.type.union +// ^^^ support.type.any + +let x: "a string"; +// ^ meta.type meta.string string.quoted.double + +let x: 'a string'; +// ^ meta.type meta.string string.quoted.single + +let x: 42; +// ^^ meta.type constant.numeric.integer.decimal + +let x: typeof Foo; +// ^^^^^^^^^^ meta.type +// ^^^^^ keyword.operator.type +// ^^^ support.class +let x: keyof Foo; +// ^^^^^^^^^ meta.type +// ^^^^^ keyword.operator.type +// ^^^ support.class + +let x: Foo.bar; +// ^^^^^^^ meta.type +// ^^^ support.class +// ^ punctuation.separator.accessor +// ^^^ support.class + +let x: { +// ^ meta.type punctuation.section.block.begin + + a : any , +// ^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + b ? : any ; +// ^ variable.other.readwrite +// ^ storage.modifier.optional +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + readonly c : any ; +// ^^^^^^^^ storage.modifier +// ^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + ( foo : any ) : any ; +// ^ punctuation.section.group.begin +// ^^^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + + ( foo : any ) : any ; +// ^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ meta.generic variable.parameter.generic +// ^ punctuation.definition.generic.end +// ^ punctuation.section.group.begin +// ^^^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + a ( foo : any ) : any ; +// ^ variable.other.readwrite +// ^ punctuation.section.group.begin +// ^^^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + + a ( foo : any ) : any ; +// ^ variable.other.readwrite +// ^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ meta.generic variable.parameter.generic +// ^ punctuation.definition.generic.end +// ^ punctuation.section.group.begin +// ^^^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + new ( foo : any ) : any ; +// ^ punctuation.section.group.begin +// ^^^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + new ( foo : any ) : any ; +// ^^^ meta.generic +// ^ punctuation.definition.generic.begin +// ^ meta.generic variable.parameter.generic +// ^ punctuation.definition.generic.end +// ^ punctuation.section.group.begin +// ^^^ meta.binding.name variable.parameter.function +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + [ foo : string ] : any ; +// ^^^^^^^^^^^^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^^^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^^^^ support.type.primitive.string +// ^ punctuation.section.brackets.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + [ foo : number ] : any ; +// ^^^^^^^^^^^^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^^^ variable.other.readwrite +// ^ punctuation.separator.type +// ^^^^^^ support.type.primitive.number +// ^ punctuation.section.brackets.end +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.separator + + [ P in keyof T ] : T [ P ] ; +// ^^^^^^^^^^^^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^ variable.other.readwrite +// ^^ keyword.operator.type +// ^^^^^ keyword.operator.type +// ^ meta.brackets support.class +// ^ punctuation.section.brackets.end +// ^ punctuation.separator.type +// ^ support.class +// ^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^ support.class +// ^ punctuation.section.brackets.end +// ^ punctuation.separator + + - readonly [ P in keyof T ] - ? : T [ P ] ; +// ^ storage.modifier +// ^^^^^^^^ storage.modifier +// ^^^^^^^^^^^^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^ variable.other.readwrite +// ^^ keyword.operator.type +// ^^^^^ keyword.operator.type +// ^ meta.brackets support.class +// ^ punctuation.section.brackets.end +// ^ storage.modifier +// ^ storage.modifier.optional +// ^ punctuation.separator.type +// ^ support.class +// ^^^^^ meta.brackets +// ^ punctuation.section.brackets.begin +// ^ support.class +// ^ punctuation.section.brackets.end +// ^ punctuation.separator + + } +// ^ meta.type punctuation.section.block.end + +let x: ( foo ? : any ) => bar; +// ^^^^^^^^^^^^^^^^^^^^^^ meta.type +// ^^^^^^^^^^^^^^^ meta.group +// ^ punctuation.section.group.begin +// ^^^ variable.other.readwrite +// ^ storage.modifier.optional +// ^ punctuation.separator.type +// ^^^ support.type.any +// ^ punctuation.section.group.end +// ^^ storage.type.function +// ^^^ support.class + +let x: T extends U ? V : W; +// ^^^^^^^^^^^^^^^^^^^ meta.type +// ^ support.class +// ^^^^^^^ keyword.operator.type.extends +// ^ support.class +// ^ keyword.operator.type +// ^ support.class +// ^ keyword.operator.type +// ^ support.class + +let x: T extends infer U ? V : W; +// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.type +// ^ support.class +// ^^^^^^^ keyword.operator.type.extends +// ^^^^^ keyword.operator.type +// ^ support.class +// ^ keyword.operator.type +// ^ support.class +// ^ keyword.operator.type +// ^ support.class + +let x: import ( "foo" ) . Bar ; +// ^^^^^^^^^^^^^^^^^^^^^^^ meta.type +// ^^^^^^ keyword.operator.type +// ^^^^^^^^^ meta.group +// ^ punctuation.section.group.begin +// ^^^^^ meta.string string.quoted.double +// ^ punctuation.section.group.end +// ^ punctuation.separator.accessor +// ^^^ support.class \ No newline at end of file