From f50050623bc02df3f3c588d23c06d6d97935462c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Ch=C5=82odnicki?= Date: Wed, 18 Nov 2020 23:04:14 +0100 Subject: [PATCH] [JavaScript] Handle type argument in JSDoc documentation Enables parsing of types that can follow some block tags. The type is scoped with a single scope instead of trying to parse the type in a "correct" way (how typescript syntax does for types). This is for one due to the fact that I don't know how to do it "properly" but even more importantly because typing it properly would make the type more noisy visually. The only exception is that the dot is scoped as an accessor so that it triggers completions (especially useful when using LSP). --- JavaScript/JavaScript.sublime-syntax | 36 ++++++++++++++++++++++++ JavaScript/tests/syntax_test_js_jsdoc.js | 35 +++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/JavaScript/JavaScript.sublime-syntax b/JavaScript/JavaScript.sublime-syntax index 465bd25aec..83fa4bcd06 100644 --- a/JavaScript/JavaScript.sublime-syntax +++ b/JavaScript/JavaScript.sublime-syntax @@ -106,6 +106,8 @@ variables: # '@' followed by a pattern like \S but excluding literal '*' and '@'. jsdoc_block_tag: \@[^\n\t\f\v *@]+ + # Tags that are optionally followed by a type expression. + jsdoc_block_tag_with_type: \@(?:arg(?:ument|)|param|type(?:def|)|returns?|prop(?:erty|)|enum|implements|member|module|namespace|(?:pr(?:ivate|otected))|template|this|throws|exception|yields?|var)\b contexts: main: @@ -164,12 +166,46 @@ contexts: push: jsdoc-block-tag jsdoc-block-tag: + - match: '{{jsdoc_block_tag_with_type}}' + scope: entity.other.attribute-name.documentation.js + set: + - match: '\s+(?=\{)' + set: jsdoc-type-expression + - match: '' + pop: 1 - match: '{{jsdoc_block_tag}}' scope: entity.other.attribute-name.documentation.js pop: 1 - match: (?=\S)|$ pop: 1 + jsdoc-type-expression: + - match: '\{' + scope: punctuation.definition.type.begin.js, meta.tag.jsdoc + set: + - match: '\}' + scope: punctuation.definition.type.end.js, meta.tag.jsdoc + pop: 1 + - include: jsdoc-type-expression-body + + jsdoc-type-expression-body: + - match: (?=\*/) + pop: 1 + - match: '^\s*\*' + - match: \. + scope: support.type.js punctuation.accessor.js + - match: '\{' + scope: support.type.js + push: jsdoc-type-expression-body-nested + - match: '(?:(?!\*\/|^\s*\*|\}|\{|\.).)*' + scope: support.type.js + + jsdoc-type-expression-body-nested: + - match: '\}' + scope: support.type.js + pop: 1 + - include: jsdoc-type-expression-body + line-comments: - match: /{4,} scope: punctuation.definition.comment.js diff --git a/JavaScript/tests/syntax_test_js_jsdoc.js b/JavaScript/tests/syntax_test_js_jsdoc.js index 5a269f99b5..17b437f5e5 100644 --- a/JavaScript/tests/syntax_test_js_jsdoc.js +++ b/JavaScript/tests/syntax_test_js_jsdoc.js @@ -40,3 +40,38 @@ /*@a */ //^^ - entity.other.attribute-name.documentation // ^^ punctuation.definition.comment.end + +/** @type {string[]} */ +// ^^^^^^^^ support.type +// ^^^^ - support.type +// ^ punctuation.definition.type.begin +// ^ punctuation.definition.type.end + +/** @type {import('fs').FSWatcher} */ +// ^^^^^^^^^^^^^^^^^^^^^^ support.type +// ^^^^ - support.type +// ^ punctuation.accessor +// ^ punctuation.definition.type.end + + /** + * @param {{ +// ^ support.type + * foo: A.B +//^^ - support.type +// ^^^^^^^^^^^ support.type +// ^ punctuation.accessor + * }} foo +// ^^ support.type +// ^^^^^ - support.type + */ + +/** @type{string} */ +// ^^^^^^^^ - support.type + +/** @type {string */ +// ^^^^^^^ support.type +// ^^ punctuation.definition.comment.end - support.type + +/** @type {{foo: number */ +// ^^^^^^^^^^^^^ support.type +// ^^ punctuation.definition.comment.end - support.type