From 36bcd70ff5066f0d268f6405e31c3340849dc001 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:26:19 -0700 Subject: [PATCH 01/29] Adjust `meta.block` scopes so that they're active only when inside curly braces --- .../grammars/ts/highlights.scm | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/language-javascript/grammars/ts/highlights.scm b/packages/language-javascript/grammars/ts/highlights.scm index 8ce5bf717..39ac3579b 100644 --- a/packages/language-javascript/grammars/ts/highlights.scm +++ b/packages/language-javascript/grammars/ts/highlights.scm @@ -543,10 +543,18 @@ (#match? @punctuation.definition.comment.js "^\/\/") (#set! adjust.startAndEndAroundFirstMatchOf "^\/\/")) +((comment) @comment.block.documentation.js + (#match? @comment.block.documentation.js "^/\\*\\*") + (#set! capture.final true) + (#set! highlight.invalidateOnChange true)) + + ; Block comments. `/* */` ((comment) @comment.block.js (#match? @comment.block.js "^/\\*") - (#match? @comment.block.js "\\*/$")) + (#match? @comment.block.js "\\*/$") + (#set! highlight.invalidateOnChange true)) + ((comment) @punctuation.definition.comment.begin.js (#match? @punctuation.definition.comment.begin.js "^/\\*") @@ -888,29 +896,43 @@ ; The interiors of functions (useful for snippets and commands). (method_definition body: (statement_block) @meta.block.function.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition) (#set! capture.final true)) (function_declaration body: (statement_block) @meta.block.function.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition) (#set! capture.final true)) (generator_function_declaration body: (statement_block) @meta.block.function.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition) (#set! capture.final true)) (function body: (statement_block) @meta.block.function.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition) (#set! capture.final true)) (generator_function body: (statement_block) @meta.block.function.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition) (#set! capture.final true)) ; The interior of a class body (useful for snippets and commands). -(class_body) @meta.block.class.js +((class_body) @meta.block.class.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition)) ; All other sorts of blocks. -(statement_block) @meta.block.js +((statement_block) @meta.block.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition)) ; The inside of a parameter definition list. ((formal_parameters) @meta.parameters.js From 54c4a3a4fb8e1e9044dfbf6ebfc2a926453d06d7 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:27:15 -0700 Subject: [PATCH 02/29] Fix JavaScript folds: * When a list of parameters is formatted with one on each line, you should be able to fold up the whole thing. * Block comment folds should end just before the closing delimiter, no matter what their indentation level. --- .../language-javascript/grammars/ts/folds.scm | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/language-javascript/grammars/ts/folds.scm b/packages/language-javascript/grammars/ts/folds.scm index d9b0e5142..d907958ad 100644 --- a/packages/language-javascript/grammars/ts/folds.scm +++ b/packages/language-javascript/grammars/ts/folds.scm @@ -3,15 +3,23 @@ (switch_body) (class_body) (object) - (formal_parameters) (template_string) (named_imports) ] @fold -((arguments) @fold +; When we've got +; +; function foo( +; bar, +; baz, +; thud +; ) +; +; we want to be able to fold up the group of function parameters while +; preserving the ability to collapse the function body. +([(arguments) (formal_parameters)] @fold (#set! fold.adjustToEndOfPreviousRow true)) - ; When we've got ; ; if (foo) { @@ -32,7 +40,7 @@ ((comment) @fold (#set! fold.endAt endPosition) - (#set! fold.adjustEndColumn 0)) + (#set! fold.offsetEnd -2)) ; When you have… From b03b56d90512d1b6913353e73487f4276a579133 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:28:08 -0700 Subject: [PATCH 03/29] JavaScript tags.scm: associate methods with their class name --- .../language-javascript/grammars/ts/tags.scm | 45 +++++++------------ 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/packages/language-javascript/grammars/ts/tags.scm b/packages/language-javascript/grammars/ts/tags.scm index b89f362be..5063d183f 100644 --- a/packages/language-javascript/grammars/ts/tags.scm +++ b/packages/language-javascript/grammars/ts/tags.scm @@ -2,8 +2,10 @@ (comment)* @doc . (method_definition - name: (property_identifier) @name) @definition.method - (#not-eq? @name "constructor") + name: (property_identifier) @name + (#set! symbol.contextNode "parent.parent.parent.firstNamedChild") + ) @definition.method + ; (#not-eq? @name "constructor") (#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$") (#select-adjacent! @doc @definition.method) ) @@ -22,19 +24,6 @@ name: (_) @name) @definition.class ) -; ( -; (comment)* @doc -; . -; [ -; (class -; name: (_) @name) -; (class_declaration -; name: (_) @name) -; ] @definition.class -; (#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$") -; (#select-adjacent! @doc @definition.class) -; ) - ( (comment)* @doc . @@ -87,19 +76,19 @@ key: (property_identifier) @name value: [(arrow_function) (function)]) @definition.function -; ( -; (call_expression -; function: (identifier) @name) @reference.call -; (#not-match? @name "^(require)$") -; ) -; -; (call_expression -; function: (member_expression -; property: (property_identifier) @name) -; arguments: (_) @reference.call) -; -; (new_expression -; constructor: (_) @name) @reference.class +( + (call_expression + function: (identifier) @name) @reference.call + (#not-match? @name "^(require)$") +) + +(call_expression + function: (member_expression + property: (property_identifier) @name) + arguments: (_)) @reference.call + +(new_expression + constructor: (_) @name) @reference.class (export_statement value: (assignment_expression left: (identifier) @name right: ([ (number) From d0b3b0829576c61b7a6645525aedc10604b10d13 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:28:52 -0700 Subject: [PATCH 04/29] JavaScript: Stop handling injections for TypeScript and TSX Instead, move that code to `language-typescript/lib/main`. --- packages/language-javascript/lib/main.js | 57 +++++++++++------------- packages/language-typescript/lib/main.js | 36 ++++++++++++++- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/packages/language-javascript/lib/main.js b/packages/language-javascript/lib/main.js index a6488be3a..9df866a6e 100644 --- a/packages/language-javascript/lib/main.js +++ b/packages/language-javascript/lib/main.js @@ -1,4 +1,4 @@ -exports.activate = function() { +exports.activate = function () { if (!atom.grammars.addInjectionPoint) return; atom.grammars.addInjectionPoint('source.js', { @@ -70,41 +70,38 @@ exports.activate = function() { const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/; const HYPERLINK_PATTERN = /\bhttps?:/ - for (const scopeName of ['source.js', 'source.ts', 'source.ts.tsx']) { - atom.grammars.addInjectionPoint(scopeName, { - type: 'comment', - language(comment) { - if (comment.text.startsWith('/**')) return 'jsdoc'; - }, - content(comment) { - return comment; - }, - languageScope: null, - coverShallowerScopes: true - }); + atom.grammars.addInjectionPoint('source.js', { + type: 'comment', + language(comment) { + if (comment.text.startsWith('/**')) return 'jsdoc'; + }, + content(comment) { + return comment; + }, + languageScope: null, + coverShallowerScopes: true + }); - // Experiment: better to have one layer with lots of nodes, or lots of - // layers each managing one node? - atom.grammars.addInjectionPoint(scopeName, { - type: 'comment', + // Experiment: better to have one layer with lots of nodes, or lots of + // layers each managing one node? + atom.grammars.addInjectionPoint('source.js', { + type: 'comment', + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + for (let type of ['template_string', 'string_fragment', 'comment']) { + atom.grammars.addInjectionPoint('source.js', { + type, language: (node) => { - return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; }, content: (node) => node, languageScope: null }); - - for (let type of ['template_string', 'string_fragment', 'comment']) { - atom.grammars.addInjectionPoint(scopeName, { - type, - language: (node) => { - return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; - }, - content: (node) => node, - languageScope: null - }); - } - } }; diff --git a/packages/language-typescript/lib/main.js b/packages/language-typescript/lib/main.js index e226ed8ce..dd7f40051 100644 --- a/packages/language-typescript/lib/main.js +++ b/packages/language-typescript/lib/main.js @@ -1,5 +1,17 @@ -exports.activate = function() { +exports.activate = function () { for (const scopeName of ['source.ts', 'source.tsx', 'source.flow']) { + atom.grammars.addInjectionPoint(scopeName, { + type: 'comment', + language(comment) { + if (comment.text.startsWith('/**')) return 'jsdoc'; + }, + content(comment) { + return comment; + }, + languageScope: null, + // coverShallowerScopes: true + }); + atom.grammars.addInjectionPoint(scopeName, { type: 'call_expression', @@ -53,9 +65,31 @@ exports.activate = function() { }, languageScope: null }); + + atom.grammars.addInjectionPoint(scopeName, { + type: 'comment', + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + for (let type of ['template_string', 'string_fragment', 'comment']) { + atom.grammars.addInjectionPoint(scopeName, { + type, + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } } }; +const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/; +const HYPERLINK_PATTERN = /\bhttps?:/ const STYLED_REGEX = /\bstyled\b/i; function languageStringForTemplateTag(tag) { From 46f5e44fd166d6e4c66077aade9c66671e3e34c9 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:30:25 -0700 Subject: [PATCH 05/29] Fix bracket-matcher failing to find a match in Tree-sitter mode Occurred in a TSX file. --- packages/bracket-matcher/lib/bracket-matcher-view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/bracket-matcher/lib/bracket-matcher-view.js b/packages/bracket-matcher/lib/bracket-matcher-view.js index 4290d1968..4d8cbb89a 100644 --- a/packages/bracket-matcher/lib/bracket-matcher-view.js +++ b/packages/bracket-matcher/lib/bracket-matcher-view.js @@ -275,14 +275,14 @@ class BracketMatcherView { startTag = firstChild endTag = lastChild } + return true } - return true } }) return {startTag, endTag} } - findMatchingEndBracketWithRegexSearch (startBracketPosition, startBracket, endBracket) { + findMatchingEndBracketWithRegexSearch(startBracketPosition, startBracket, endBracket) { const scanRange = new Range( startBracketPosition.traverse(ONE_CHAR_FORWARD_TRAVERSAL), startBracketPosition.traverse(MAX_ROWS_TO_SCAN_FORWARD_TRAVERSAL) From cc31ed935baaab838b5d5c6844d68517f8d2457f Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:30:46 -0700 Subject: [PATCH 06/29] Reformat a `bracket-matcher` file --- .../lib/bracket-matcher-view.js | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/bracket-matcher/lib/bracket-matcher-view.js b/packages/bracket-matcher/lib/bracket-matcher-view.js index 4d8cbb89a..76df8006e 100644 --- a/packages/bracket-matcher/lib/bracket-matcher-view.js +++ b/packages/bracket-matcher/lib/bracket-matcher-view.js @@ -12,7 +12,7 @@ const MAX_ROWS_TO_SCAN_BACKWARD_TRAVERSAL = Object.freeze(Point(-MAX_ROWS_TO_SCA module.exports = class BracketMatcherView { - constructor (editor, editorElement, matchManager) { + constructor(editor, editorElement, matchManager) { this.destroy = this.destroy.bind(this) this.updateMatch = this.updateMatch.bind(this) this.editor = editor @@ -65,11 +65,11 @@ class BracketMatcherView { this.updateMatch() } - destroy () { + destroy() { this.subscriptions.dispose() } - updateMatch () { + updateMatch() { if (this.pairHighlighted) { this.editor.destroyMarker(this.startMarker.id) this.editor.destroyMarker(this.endMarker.id) @@ -113,13 +113,13 @@ class BracketMatcherView { this.tagHighlighted = highlightTag } - selectMatchingBrackets () { + selectMatchingBrackets() { if (!this.bracket1Range && !this.bracket2Range) return this.editor.setSelectedBufferRanges([this.bracket1Range, this.bracket2Range]) this.matchManager.changeBracketsMode = true } - removeMatchingBrackets () { + removeMatchingBrackets() { if (this.editor.hasMultipleCursors()) { this.editor.backspace() return @@ -159,7 +159,7 @@ class BracketMatcherView { }) } - findMatchingEndBracket (startBracketPosition, startBracket, endBracket) { + findMatchingEndBracket(startBracketPosition, startBracket, endBracket) { if (startBracket === endBracket) return if (this.hasSyntaxTree()) { @@ -171,7 +171,7 @@ class BracketMatcherView { } } - findMatchingStartBracket (endBracketPosition, startBracket, endBracket) { + findMatchingStartBracket(endBracketPosition, startBracket, endBracket) { if (startBracket === endBracket) return if (this.hasSyntaxTree()) { @@ -183,7 +183,7 @@ class BracketMatcherView { } } - findMatchingEndBracketWithSyntaxTree (bracketPosition, startBracket, endBracket) { + findMatchingEndBracketWithSyntaxTree(bracketPosition, startBracket, endBracket) { let result const bracketEndPosition = bracketPosition.traverse([0, startBracket.length]) this.editor.buffer.getLanguageMode().getSyntaxNodeContainingRange( @@ -202,7 +202,7 @@ class BracketMatcherView { return result } - findMatchingStartBracketWithSyntaxTree (bracketPosition, startBracket, endBracket) { + findMatchingStartBracketWithSyntaxTree(bracketPosition, startBracket, endBracket) { let result const bracketEndPosition = bracketPosition.traverse([0, startBracket.length]) this.editor.buffer.getLanguageMode().getSyntaxNodeContainingRange( @@ -221,7 +221,7 @@ class BracketMatcherView { return result } - findMatchingTagNameRangesWithSyntaxTree () { + findMatchingTagNameRangesWithSyntaxTree() { const position = this.editor.getCursorBufferPosition() const {startTag, endTag} = this.findContainingTagsWithSyntaxTree(position) if (startTag && (startTag.range.containsPoint(position) || endTag.range.containsPoint(position))) { @@ -244,7 +244,7 @@ class BracketMatcherView { } } - findMatchingTagsWithSyntaxTree () { + findMatchingTagsWithSyntaxTree() { const position = this.editor.getCursorBufferPosition() const {startTag, endTag} = this.findContainingTagsWithSyntaxTree(position) if (startTag) { @@ -254,7 +254,7 @@ class BracketMatcherView { } } - findContainingTagsWithSyntaxTree (position) { + findContainingTagsWithSyntaxTree(position) { let startTag, endTag if (position.column === this.editor.buffer.lineLengthForRow(position.row)) position.column--; this.editor.buffer.getLanguageMode().getSyntaxNodeAtPosition(position, node => { @@ -308,7 +308,7 @@ class BracketMatcherView { return endBracketPosition } - findMatchingStartBracketWithRegexSearch (endBracketPosition, startBracket, endBracket) { + findMatchingStartBracketWithRegexSearch(endBracketPosition, startBracket, endBracket) { const scanRange = new Range( endBracketPosition.traverse(MAX_ROWS_TO_SCAN_BACKWARD_TRAVERSAL), endBracketPosition @@ -334,7 +334,7 @@ class BracketMatcherView { return startBracketPosition } - findPrecedingStartBracket (cursorPosition) { + findPrecedingStartBracket(cursorPosition) { if (this.hasSyntaxTree()) { return this.findPrecedingStartBracketWithSyntaxTree(cursorPosition) } else { @@ -342,7 +342,7 @@ class BracketMatcherView { } } - findPrecedingStartBracketWithSyntaxTree (cursorPosition) { + findPrecedingStartBracketWithSyntaxTree(cursorPosition) { let result this.editor.buffer.getLanguageMode().getSyntaxNodeAtPosition(cursorPosition, node => { for (const child of node.children) { @@ -359,7 +359,7 @@ class BracketMatcherView { return result } - findPrecedingStartBracketWithRegexSearch (cursorPosition) { + findPrecedingStartBracketWithRegexSearch(cursorPosition) { const scanRange = new Range(Point.ZERO, cursorPosition) const startBracket = _.escapeRegExp(_.keys(this.matchManager.pairedCharacters).join('')) const endBracket = _.escapeRegExp(_.keys(this.matchManager.pairedCharactersInverse).join('')) @@ -384,7 +384,7 @@ class BracketMatcherView { return startPosition } - createMarker (bufferRange) { + createMarker(bufferRange) { const marker = this.editor.markBufferRange(bufferRange) this.editor.decorateMarker(marker, {type: 'highlight', class: 'bracket-matcher', deprecatedRegionClass: 'bracket-matcher'}) if (atom.config.get('bracket-matcher.highlightMatchingLineNumber', {scope: this.editor.getRootScopeDescriptor()}) && this.gutter) { @@ -393,7 +393,7 @@ class BracketMatcherView { return marker } - findCurrentPair () { + findCurrentPair() { const currentPosition = this.editor.getCursorBufferPosition() const previousPosition = currentPosition.traverse(ONE_CHAR_BACKWARD_TRAVERSAL) const nextPosition = currentPosition.traverse(ONE_CHAR_FORWARD_TRAVERSAL) @@ -422,7 +422,7 @@ class BracketMatcherView { return {position, matchPosition, bracket: currentBracket} } - goToMatchingBracket () { + goToMatchingBracket() { if (!this.pairHighlighted) return this.gotoPrecedingStartBracket() const position = this.editor.getCursorBufferPosition() @@ -468,7 +468,7 @@ class BracketMatcherView { } } - gotoPrecedingStartBracket () { + gotoPrecedingStartBracket() { if (this.pairHighlighted) return const matchPosition = this.findPrecedingStartBracket(this.editor.getCursorBufferPosition()) @@ -522,7 +522,7 @@ class BracketMatcherView { }) } - selectInsideBrackets () { + selectInsideBrackets() { let endPosition, endRange, startPosition, startRange if (this.pairHighlighted) { startRange = this.startMarker.getBufferRange() @@ -550,7 +550,7 @@ class BracketMatcherView { // Insert at the current cursor position a closing tag if there exists an // open tag that is not closed afterwards. - closeTag () { + closeTag() { const cursorPosition = this.editor.getCursorBufferPosition() const preFragment = this.editor.getTextInBufferRange([Point.ZERO, cursorPosition]) const postFragment = this.editor.getTextInBufferRange([cursorPosition, Point.INFINITY]) @@ -561,15 +561,15 @@ class BracketMatcherView { } } - isCursorOnCommentOrString () { + isCursorOnCommentOrString() { return this.isScopeCommentedOrString(this.editor.getLastCursor().getScopeDescriptor().getScopesArray()) } - isRangeCommentedOrString (range) { + isRangeCommentedOrString(range) { return this.isScopeCommentedOrString(this.editor.scopeDescriptorForBufferPosition(range.start).getScopesArray()) } - isScopeCommentedOrString (scopesArray) { + isScopeCommentedOrString(scopesArray) { for (let scope of scopesArray.reverse()) { scope = scope.split('.') if (scope.includes('embedded') && scope.includes('source')) return false @@ -579,7 +579,7 @@ class BracketMatcherView { return false } - hasSyntaxTree () { + hasSyntaxTree() { return this.editor.buffer.getLanguageMode().getSyntaxNodeAtPosition } } From cd392dfbd6d06d785ee8a5f84aa13f06179faca9 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:31:37 -0700 Subject: [PATCH 07/29] Tweak some C/C++ queries --- .../grammars/tree-sitter-c/highlights.scm | 14 +++++++++----- .../language-c/grammars/tree-sitter-c/locals.scm | 1 - .../language-c/grammars/tree-sitter-c/tags.scm | 3 ++- .../grammars/tree-sitter-cpp/locals.scm | 1 - .../language-c/grammars/tree-sitter-cpp/tags.scm | 16 +++++++++++++++- 5 files changed, 26 insertions(+), 9 deletions(-) delete mode 100644 packages/language-c/grammars/tree-sitter-c/locals.scm delete mode 100644 packages/language-c/grammars/tree-sitter-cpp/locals.scm diff --git a/packages/language-c/grammars/tree-sitter-c/highlights.scm b/packages/language-c/grammars/tree-sitter-c/highlights.scm index 402b1069d..51778a17d 100644 --- a/packages/language-c/grammars/tree-sitter-c/highlights.scm +++ b/packages/language-c/grammars/tree-sitter-c/highlights.scm @@ -70,6 +70,10 @@ ((primitive_type) @support.type.stdint.c (#match? @support.type.stdint.c "^(int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t)$")) +(enum_specifier + name: (type_identifier) @variable.other.declaration.type.c) +(type_definition + declarator: (_) @variable.other.declaration.type.c) ; CAVEAT: tree-sitter-c doesn't identify placeholders like `%c` in strings. ; Candidate for an injection grammar. @@ -111,19 +115,19 @@ declarator: (identifier) @variable.declaration.c) (field_declaration - (field_identifier) @variable.declaration.c) + (field_identifier) @entity.other.attribute-name.c) (field_declaration (pointer_declarator - (field_identifier) @variable.declaration.c)) + (field_identifier) @entity.other.attribute-name.c)) (field_declaration (array_declarator - (field_identifier) @variable.declaration.c)) + (field_identifier) @entity.other.attribute-name.c)) (init_declarator (pointer_declarator - (identifier) @variable.declaration.c)) + (identifier) @entity.other.attribute-name.c)) (assignment_expression left: (identifier) @variable.other.assignment.c) @@ -158,7 +162,7 @@ ; The "size" in `finfo->size`. (field_expression "->" - field: (field_identifier) @variable.other.member.c) + field: (field_identifier) @support.other.property.c) ; FUNCTIONS diff --git a/packages/language-c/grammars/tree-sitter-c/locals.scm b/packages/language-c/grammars/tree-sitter-c/locals.scm deleted file mode 100644 index 092bc2b04..000000000 --- a/packages/language-c/grammars/tree-sitter-c/locals.scm +++ /dev/null @@ -1 +0,0 @@ -; diff --git a/packages/language-c/grammars/tree-sitter-c/tags.scm b/packages/language-c/grammars/tree-sitter-c/tags.scm index 3ef41679a..491007448 100644 --- a/packages/language-c/grammars/tree-sitter-c/tags.scm +++ b/packages/language-c/grammars/tree-sitter-c/tags.scm @@ -1,2 +1,3 @@ -((function_declarator (identifier) @name)) +(function_declarator + (identifier) @name) @definition.function diff --git a/packages/language-c/grammars/tree-sitter-cpp/locals.scm b/packages/language-c/grammars/tree-sitter-cpp/locals.scm deleted file mode 100644 index 092bc2b04..000000000 --- a/packages/language-c/grammars/tree-sitter-cpp/locals.scm +++ /dev/null @@ -1 +0,0 @@ -; diff --git a/packages/language-c/grammars/tree-sitter-cpp/tags.scm b/packages/language-c/grammars/tree-sitter-cpp/tags.scm index 3ef41679a..c44ee78e4 100644 --- a/packages/language-c/grammars/tree-sitter-cpp/tags.scm +++ b/packages/language-c/grammars/tree-sitter-cpp/tags.scm @@ -1,2 +1,16 @@ -((function_declarator (identifier) @name)) +(function_declarator + (identifier) @name) @definition.function + +(function_declarator + declarator: (qualified_identifier) @name) @definition.function + +(class_specifier + name: (type_identifier) @name) @definition.class + +(class_specifier + body: (field_declaration_list + (function_definition + declarator: (function_declarator + declarator: (field_identifier) @name)) @definition.method) + (#set! symbol.contextNode "parent.parent.parent.parent.firstNamedChild")) From 99d230e7c6267c074547e4b5781905358360562f Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:32:07 -0700 Subject: [PATCH 08/29] Add some recognized values to the CSS `highlights.scm` --- .../language-css/grammars/tree-sitter/queries/highlights.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/language-css/grammars/tree-sitter/queries/highlights.scm b/packages/language-css/grammars/tree-sitter/queries/highlights.scm index 4301691ed..4c4cc597d 100644 --- a/packages/language-css/grammars/tree-sitter/queries/highlights.scm +++ b/packages/language-css/grammars/tree-sitter/queries/highlights.scm @@ -156,7 +156,7 @@ ; ------------------------ ((plain_value) @support.constant.property-value.css - (#match? @support.constant.property-value.css "^(above|absolute|active|add|additive|after-edge|alias|all|all-petite-caps|all-scroll|all-small-caps|alpha|alphabetic|alternate|alternate-reverse|always|antialiased|auto|auto-pos|available|avoid|avoid-column|avoid-page|avoid-region|backwards|balance|baseline|before-edge|below|bevel|bidi-override|blink|block|block-axis|block-start|block-end|bold|bolder|border|border-box|both|bottom|bottom-outside|break-all|break-word|bullets|butt|capitalize|caption|cell|center|central|char|circle|clip|clone|close-quote|closest-corner|closest-side|col-resize|collapse|color|color-burn|color-dodge|column|column-reverse|common-ligatures|compact|condensed|contain|content|content-box|contents|context-menu|contextual|copy|cover|crisp-edges|crispEdges|crosshair|cyclic|dark|darken|dashed|decimal|default|dense|diagonal-fractions|difference|digits|disabled|disc|discretionary-ligatures|distribute|distribute-all-lines|distribute-letter|distribute-space|dot|dotted|double|double-circle|downleft|downright|e-resize|each-line|ease|ease-in|ease-in-out|ease-out|economy|ellipse|ellipsis|embed|end|evenodd|ew-resize|exact|exclude|exclusion|expanded|extends|extra-condensed|extra-expanded|fallback|farthest-corner|farthest-side|fill|fill-available|fill-box|filled|fit-content|fixed|flat|flex|flex-end|flex-start|flip|flow-root|forwards|freeze|from-image|full-width|geometricPrecision|georgian|grab|grabbing|grayscale|grid|groove|hand|hanging|hard-light|help|hidden|hide|historical-forms|historical-ligatures|horizontal|horizontal-tb|hue|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|infinite|inherit|initial|inline|inline-axis|inline-block|inline-end|inline-flex|inline-grid|inline-list-item|inline-start|inline-table|inset|inside|inter-character|inter-ideograph|inter-word|intersect|invert|isolate|isolate-override|italic|jis04|jis78|jis83|jis90|justify|justify-all|kannada|keep-all|landscape|large|larger|left|light|lighten|lighter|line|line-edge|line-through|linear|linearRGB|lining-nums|list-item|local|loose|lowercase|lr|lr-tb|ltr|luminance|luminosity|main-size|mandatory|manipulation|manual|margin-box|match-parent|match-source|mathematical|max-content|medium|menu|message-box|middle|min-content|miter|mixed|move|multiply|n-resize|narrower|ne-resize|nearest-neighbor|nesw-resize|newspaper|no-change|no-clip|no-close-quote|no-common-ligatures|no-contextual|no-discretionary-ligatures|no-drop|no-historical-ligatures|no-open-quote|no-repeat|none|nonzero|normal|not-allowed|nowrap|ns-resize|numbers|numeric|nw-resize|nwse-resize|oblique|oldstyle-nums|open|open-quote|optimizeLegibility|optimizeQuality|optimizeSpeed|optional|ordinal|outset|outside|over|overlay|overline|padding|padding-box|page|painted|pan-down|pan-left|pan-right|pan-up|pan-x|pan-y|paused|petite-caps|pixelated|plaintext|pointer|portrait|pre|pre-line|pre-wrap|preserve-3d|progress|progressive|proportional-nums|proportional-width|proximity|radial|recto|region|relative|remove|repeat|repeat-[xy]|reset-size|reverse|revert|ridge|right|rl|rl-tb|round|row|row-resize|row-reverse|row-severse|rtl|ruby|ruby-base|ruby-base-container|ruby-text|ruby-text-container|run-in|running|s-resize|saturation|scale-down|screen|scroll|scroll-position|se-resize|semi-condensed|semi-expanded|separate|sesame|show|sideways|sideways-left|sideways-lr|sideways-right|sideways-rl|simplified|slashed-zero|slice|small|small-caps|small-caption|smaller|smooth|soft-light|solid|space|space-around|space-between|space-evenly|spell-out|square|sRGB|stacked-fractions|start|static|status-bar|swap|step-end|step-start|sticky|stretch|strict|stroke|stroke-box|style|sub|subgrid|subpixel-antialiased|subtract|super|sw-resize|symbolic|table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row|table-row-group|tabular-nums|tb|tb-rl|text|text-after-edge|text-before-edge|text-bottom|text-top|thick|thin|titling-caps|top|top-outside|touch|traditional|transparent|triangle|ultra-condensed|ultra-expanded|under|underline|unicase|unset|upleft|uppercase|upright|use-glyph-orientation|use-script|verso|vertical|vertical-ideographic|vertical-lr|vertical-rl|vertical-text|view-box|visible|visibleFill|visiblePainted|visibleStroke|w-resize|wait|wavy|weight|whitespace|wider|words|wrap|wrap-reverse|x|x-large|x-small|xx-large|xx-small|y|zero|zoom-in|zoom-out)$")) + (#match? @support.constant.property-value.css "^(above|absolute|active|add|additive|after-edge|alias|all|all-petite-caps|all-scroll|all-small-caps|alpha|alphabetic|alternate|alternate-reverse|always|antialiased|auto|auto-pos|available|avoid|avoid-column|avoid-page|avoid-region|backwards|balance|baseline|before-edge|below|bevel|bidi-override|blink|block|block-axis|block-start|block-end|bold|bolder|border|border-box|both|bottom|bottom-outside|break-all|break-word|bullets|butt|capitalize|caption|cell|center|central|char|circle|clip|clone|close-quote|closest-corner|closest-side|col-resize|collapse|color|color-burn|color-dodge|column|column-reverse|common-ligatures|compact|condensed|contain|content|content-box|contents|context-menu|contextual|copy|cover|crisp-edges|crispEdges|crosshair|cyclic|dark|darken|dashed|decimal|default|dense|diagonal-fractions|difference|digits|disabled|disc|discretionary-ligatures|distribute|distribute-all-lines|distribute-letter|distribute-space|dot|dotted|double|double-circle|downleft|downright|e-resize|each-line|ease|ease-in|ease-in-out|ease-out|economy|ellipse|ellipsis|embed|end|evenodd|ew-resize|exact|exclude|exclusion|expanded|extends|extra-condensed|extra-expanded|fallback|farthest-corner|farthest-side|fill|fill-available|fill-box|filled|fit-content|fixed|flat|flex|flex-end|flex-start|flip|flow-root|forwards|freeze|from-image|full-width|geometricPrecision|georgian|grab|grabbing|grayscale|grid|groove|hand|hanging|hard-light|help|hidden|hide|historical-forms|historical-ligatures|horizontal|horizontal-tb|hue|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|infinite|inherit|initial|inline|inline-axis|inline-block|inline-end|inline-flex|inline-grid|inline-list-item|inline-size|inline-start|inline-table|inset|inside|inter-character|inter-ideograph|inter-word|intersect|invert|isolate|isolate-override|italic|jis04|jis78|jis83|jis90|justify|justify-all|kannada|keep-all|landscape|large|larger|layout|left|light|lighten|lighter|line|line-edge|line-through|linear|linearRGB|lining-nums|list-item|local|loose|lowercase|lr|lr-tb|ltr|luminance|luminosity|main-size|mandatory|manipulation|manual|margin-box|match-parent|match-source|mathematical|max-content|medium|menu|message-box|middle|min-content|miter|mixed|move|multiply|n-resize|narrower|ne-resize|nearest-neighbor|nesw-resize|newspaper|no-change|no-clip|no-close-quote|no-common-ligatures|no-contextual|no-discretionary-ligatures|no-drop|no-historical-ligatures|no-open-quote|no-repeat|none|nonzero|normal|not-allowed|nowrap|ns-resize|numbers|numeric|nw-resize|nwse-resize|oblique|oldstyle-nums|open|open-quote|optimizeLegibility|optimizeQuality|optimizeSpeed|optional|ordinal|outset|outside|over|overlay|overline|padding|padding-box|page|paint|painted|pan-down|pan-left|pan-right|pan-up|pan-x|pan-y|paused|petite-caps|pixelated|plaintext|pointer|portrait|pre|pre-line|pre-wrap|preserve-3d|progress|progressive|proportional-nums|proportional-width|proximity|radial|recto|region|relative|remove|repeat|repeat-[xy]|reset-size|reverse|revert|ridge|right|rl|rl-tb|round|row|row-resize|row-reverse|row-severse|rtl|ruby|ruby-base|ruby-base-container|ruby-text|ruby-text-container|run-in|running|s-resize|saturation|scale-down|screen|scroll|scroll-position|se-resize|semi-condensed|semi-expanded|separate|sesame|show|sideways|sideways-left|sideways-lr|sideways-right|sideways-rl|simplified|size|slashed-zero|slice|small|small-caps|small-caption|smaller|smooth|soft-light|solid|space|space-around|space-between|space-evenly|spell-out|square|sRGB|stacked-fractions|start|static|status-bar|swap|step-end|step-start|sticky|stretch|strict|stroke|stroke-box|style|sub|subgrid|subpixel-antialiased|subtract|super|sw-resize|symbolic|table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row|table-row-group|tabular-nums|tb|tb-rl|text|text-after-edge|text-before-edge|text-bottom|text-top|thick|thin|titling-caps|top|top-outside|touch|traditional|transparent|triangle|ultra-condensed|ultra-expanded|under|underline|unicase|unset|upleft|uppercase|upright|use-glyph-orientation|use-script|verso|vertical|vertical-ideographic|vertical-lr|vertical-rl|vertical-text|view-box|visible|visibleFill|visiblePainted|visibleStroke|w-resize|wait|wavy|weight|whitespace|wider|words|wrap|wrap-reverse|x|x-large|x-small|xx-large|xx-small|y|zero|zoom-in|zoom-out)$")) ; All property values that have special meaning in `font-family`. ; TODO: Restrict these to be meaningful only when the property name is font-related? From cb4679f9d88ed7f5cb6459b2645b89c29962d4fc Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:33:46 -0700 Subject: [PATCH 09/29] Tweak JSX indentation hinting --- .../language-javascript/grammars/ts/indents.scm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/language-javascript/grammars/ts/indents.scm b/packages/language-javascript/grammars/ts/indents.scm index ce46a1393..6aab803c1 100644 --- a/packages/language-javascript/grammars/ts/indents.scm +++ b/packages/language-javascript/grammars/ts/indents.scm @@ -94,23 +94,25 @@ ; ============================= ; TODO: We might want to make this configurable behavior with the -; `Config` scope test. +; `config` scope test. ; Any of these at the end of a line indicate the next line should be indented… (["||" "&&" "?"] @indent (#is? test.lastTextOnRow true)) -; …and the line after that should be dedented. +; …and the line after that should be dedented… (binary_expression ["||" "&&"] right: (_) @dedent.next (#is-not? test.startsOnSameRowAs parent.startPosition)) +; …unless it's a ternary, in which case the dedent should wait until the +; alternative clause. +; ; let foo = this.longTernaryCondition() ? ; consequenceWhichIsItselfRatherLong : ; alternativeThatIsNotBrief; ; -; …followed by a dedent. (ternary_expression alternative: (_) @dedent.next (#is-not? test.startsOnSameRowAs parent.startPosition)) @@ -153,5 +155,8 @@ ; JSX ; === -(jsx_opening_element ">") @indent -(jsx_closing_element ">") @dedent + +(jsx_opening_element ["<" ">"] @indent) +(jsx_opening_element [">"] @dedent) + +(jsx_closing_element ">" @dedent) From 7de9a82a42cad34237a9ad08d6974657a09b1bfe Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:34:01 -0700 Subject: [PATCH 10/29] Scope inline tags in JSDoc --- packages/language-javascript/grammars/ts/jsdoc/highlights.scm | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/language-javascript/grammars/ts/jsdoc/highlights.scm b/packages/language-javascript/grammars/ts/jsdoc/highlights.scm index 549d7c384..b9231f22b 100644 --- a/packages/language-javascript/grammars/ts/jsdoc/highlights.scm +++ b/packages/language-javascript/grammars/ts/jsdoc/highlights.scm @@ -19,6 +19,7 @@ ((document) @punctuation.definition.end.comment.js.jsdoc (#set! adjust.startAndEndAroundFirstMatchOf "(?:\\*)?\\*/$")) +((inline_tag) @meta.inline-tag.js.jsdoc) (tag_name) @storage.type.class.jsdoc From 5c8f6abd941ed2cc9991ada6a4f28d9e0a4f4968 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:34:27 -0700 Subject: [PATCH 11/29] Tag properties as such in JSON's `tags.scm` --- packages/language-json/grammars/tree-sitter/queries/tags.scm | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/language-json/grammars/tree-sitter/queries/tags.scm b/packages/language-json/grammars/tree-sitter/queries/tags.scm index 3c7d1defe..3e04140c3 100644 --- a/packages/language-json/grammars/tree-sitter/queries/tags.scm +++ b/packages/language-json/grammars/tree-sitter/queries/tags.scm @@ -4,6 +4,7 @@ ; Nested keys try to prepend the symbol name of their parent's key. (pair key: (string (string_content) @name (#is-not? test.descendantOfType "array") + (#set! symbol.tag "property") (#set! symbol.prependSymbolForNode parent.parent.parent.previousNamedSibling.firstNamedChild) (#set! symbol.contextNode parent.parent.parent.previousNamedSibling.firstNamedChild) (#set! symbol.joiner "."))) From 37a81ccb8200dc50bd43a7d807b20efe4c29dffa Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:36:44 -0700 Subject: [PATCH 12/29] Make the `fun` snippet work in more contexts `fun` expands to a simple function definition in JavaScript, but there are certain contexts where that syntax is invalid, making the snippet much less useful. Now that we're scoping the insides of class bodies and object literals, though, we can define more specific snippets for those contexts that use the correct syntax. The class-instance-method snippet and the inside-an-object-literal snippet are identical, except that the latter has a trailing comma. --- .../snippets/language-javascript.cson | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/language-javascript/snippets/language-javascript.cson b/packages/language-javascript/snippets/language-javascript.cson index cef3df690..47ffd586b 100644 --- a/packages/language-javascript/snippets/language-javascript.cson +++ b/packages/language-javascript/snippets/language-javascript.cson @@ -128,3 +128,18 @@ 'return': 'prefix': 'ret' 'body': 'return $1;$0' + +'.source.js .meta.block.function.js': + 'Function': + 'prefix': 'fun' + 'body': 'function ${1:functionName}($2) {\n\t$0\n}' + +'.source.js .meta.block.class.js': + 'Function': + 'prefix': 'fun' + 'body': '${1:functionName}($2) {\n\t$0\n}' + +'.source.js .meta.object.js': + 'Function': + 'prefix': 'fun' + 'body': '${1:functionName}($2) {\n\t$0\n},' From 2d802a745fe48d5db6f14e93fc23f89836db2fbe Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:37:38 -0700 Subject: [PATCH 13/29] Add TODO and Hyperlink injections to the shellscript grammar --- packages/language-shellscript/lib/main.js | 25 ++++++++++++++++++++++ packages/language-shellscript/package.json | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 packages/language-shellscript/lib/main.js diff --git a/packages/language-shellscript/lib/main.js b/packages/language-shellscript/lib/main.js new file mode 100644 index 000000000..e2eb7368a --- /dev/null +++ b/packages/language-shellscript/lib/main.js @@ -0,0 +1,25 @@ +exports.activate = () => { + + const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/; + const HYPERLINK_PATTERN = /\bhttps?:/ + + atom.grammars.addInjectionPoint('source.shell', { + type: 'comment', + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + atom.grammars.addInjectionPoint('source.shell', { + type: 'comment', + language(node) { + return HYPERLINK_PATTERN.test(node.text) ? + 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + +}; diff --git a/packages/language-shellscript/package.json b/packages/language-shellscript/package.json index 68a12c900..47fa9bc27 100644 --- a/packages/language-shellscript/package.json +++ b/packages/language-shellscript/package.json @@ -1,13 +1,14 @@ { "name": "language-shellscript", "version": "0.28.2", + "main": "lib/main", "description": "ShellScript language support in Atom", "keywords": [ "tree-sitter" ], "engines": { "atom": "*", - "node": "*" + "node": ">=12" }, "repository": "https://github.com/pulsar-edit/pulsar", "license": "MIT", From 0adb5e6dc82e4eaccc16504092f7dc4862cd05cb Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:38:09 -0700 Subject: [PATCH 14/29] Fold multi-line parameters in TypeScript and TSX --- .../language-typescript/grammars/common/folds.scm | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/language-typescript/grammars/common/folds.scm b/packages/language-typescript/grammars/common/folds.scm index cbe82351f..ee15e26e4 100644 --- a/packages/language-typescript/grammars/common/folds.scm +++ b/packages/language-typescript/grammars/common/folds.scm @@ -2,15 +2,23 @@ (switch_body) (class_body) (object) - (formal_parameters) (template_string) (named_imports) ] @fold -((arguments) @fold +; When we've got +; +; function foo( +; bar, +; baz, +; thud +; ) +; +; we want to be able to fold up the group of function parameters while +; preserving the ability to collapse the function body. +([(arguments) (formal_parameters)] @fold (#set! fold.adjustToEndOfPreviousRow true)) - ; When we've got ; ; if (foo) { From eb5d1c2198d7efde75bda7669640909c132a2f1b Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:39:12 -0700 Subject: [PATCH 15/29] Fix folding of block comments in TypeScript/TSX --- packages/language-typescript/grammars/common/folds.scm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/language-typescript/grammars/common/folds.scm b/packages/language-typescript/grammars/common/folds.scm index ee15e26e4..97c5a6f0f 100644 --- a/packages/language-typescript/grammars/common/folds.scm +++ b/packages/language-typescript/grammars/common/folds.scm @@ -39,4 +39,4 @@ ((comment) @fold (#set! fold.endAt endPosition) - (#set! fold.adjustEndColumn 0)) + (#set! fold.offsetEnd -2)) From 4402d9ada4d5e70f12a369e8d0086860378a1ce0 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:40:40 -0700 Subject: [PATCH 16/29] Add some TypeScript/TSX highlights There were some constructs that we neglected to highlight properly, like type predicates and rest parameters. --- .../grammars/common/highlights.scm | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/packages/language-typescript/grammars/common/highlights.scm b/packages/language-typescript/grammars/common/highlights.scm index e83dac3d1..385ccfff2 100644 --- a/packages/language-typescript/grammars/common/highlights.scm +++ b/packages/language-typescript/grammars/common/highlights.scm @@ -9,6 +9,10 @@ (import_specifier (identifier) @variable.other.assignment.import._LANG_) +; The "foo" in `import * as foo from './bar'` +(namespace_import + (identifier) @variable.other.assignment.import.namespace._LANG_) + ; The "Foo" in `export { Foo }` (export_specifier name: (identifier) @variable.other.assignment.export._LANG_) @@ -37,8 +41,19 @@ (#match? @punctuation.definition.comment._LANG_ "^//") (#set! adjust.startAndEndAroundFirstMatchOf "^//")) +((comment) @comment.block.documentation._LANG_ + (#match? @comment.block.documentation._LANG_ "^/\\*\\*") + (#set! capture.final true) + (#set! highlight.invalidateOnChange true)) + +; Block comments. `/* */` ((comment) @comment.block._LANG_ - (#match? @comment.block._LANG_ "^/\\*")) + (#match? @comment.block._LANG_ "^/\\*") + (#match? @comment.block._LANG_ "\\*/$") + (#set! highlight.invalidateOnChange true)) + +; ((comment) @comment.block._LANG_ +; (#match? @comment.block._LANG_ "^/\\*")) ((comment) @punctuation.definition.comment.begin._LANG_ (#match? @punctuation.definition.comment.begin._LANG_ "^/\\*") @@ -65,7 +80,8 @@ ; ======= (class_declaration - name: (type_identifier) @entity.name.type.class._LANG_) + name: (type_identifier) @entity.name.type.class._LANG_ + (#set! capture.final true)) (extends_clause value: (_) @entity.other.inherited-class._LANG_) @@ -90,12 +106,27 @@ "set" @storage.setter._LANG_) +; NAMESPACES +; ========== + +(internal_module + name: (identifier) @entity.name.type.namespace._LANG_) + + +; DECLARATIONS +; ============ + +(function_signature + name: (identifier) @entity.name.function.signature._LANG_) + + ; INTERFACES ; ========== (interface_declaration name: (_) @entity.name.type.interface._LANG_) + ; TYPES ; ===== @@ -178,6 +209,8 @@ (property_signature (property_identifier) @entity.other.attribute-name._LANG_) + + ; FUNCTIONS ; ========= @@ -259,6 +292,10 @@ (required_parameter pattern: (identifier) @variable.parameter._LANG_) +(required_parameter + pattern: (rest_pattern + (identifier) @variable.parameter.rest._LANG_)) + (required_parameter pattern: (object_pattern (shorthand_property_identifier_pattern) @variable.parameter.destructuring._LANG_) @@ -269,6 +306,9 @@ (optional_parameter "?" @keyword.operator.type.optional._LANG_) +(type_predicate + name: (identifier) @variable.other.type._LANG_ + "is" @keyword.operator.type.is._LANG_) ["var" "const" "let"] @storage.type._TYPE_._LANG_ @@ -306,7 +346,16 @@ (pair_pattern ; TODO: This arguably isn't an object key. key: (_) @entity.other.attribute-name._LANG_ - value: (identifier) @variable.other.assignment.destructuring._LANG_)) + value: (identifier) @variable.other.assignment.destructuring._LANG_) + (#set! capture.final true)) + +; A complex object alias destructuring: +; The "bar" in `let { bar: { foo: troz } } = something` +(object_pattern + (pair_pattern + ; TODO: This arguably isn't an object key. + key: (_) @entity.other.attribute-name._LANG_) + (#set! capture.final true)) ; A variable object alias destructuring with default value: ; The "bar" and "foo" in `let { bar: foo = true } = something` From 18606447cfb6530de14bc8508dd2e9842c63832c Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:41:25 -0700 Subject: [PATCH 17/29] Harmonize the TypeScript/TSX `indents.scm` with that of JavaScript --- .../grammars/common/indents.scm | 123 +++++++++++++++++- .../grammars/tree-sitter-tsx/indents.scm | 6 +- 2 files changed, 120 insertions(+), 9 deletions(-) diff --git a/packages/language-typescript/grammars/common/indents.scm b/packages/language-typescript/grammars/common/indents.scm index a85c78b0a..427f19f0c 100644 --- a/packages/language-typescript/grammars/common/indents.scm +++ b/packages/language-typescript/grammars/common/indents.scm @@ -1,14 +1,124 @@ -; The closing brace of a switch statement's body should match the indentation of the line where the switch statement starts. +; STATEMENT BLOCKS +; ================ + +; More accurate indentation matching for all blocks delimited by braces. +(statement_block "}" @match + (#set! indent.matchIndentOf parent.firstChild.startPosition)) + + +; SWITCH STATEMENTS +; ================= + +; The closing brace of a switch statement's body should match the indentation +; of the line where the switch statement starts. (switch_statement body: (switch_body "}" @match (#is? test.last true)) - (#set! indent.matchIndentOf parent.parent.startPosition)) + (#set! indent.matchIndentOf parent.startPosition)) ; 'case' and 'default' need to be indented one level more than their containing -; `switch`. - (["case" "default"] @match - (#set! indent.matchIndentOf parent.parent.startPosition) - (#set! indent.offsetIndent 1)) +; `switch`. TODO: Might need to make this configurable. +(["case" "default"] @match + (#set! indent.matchIndentOf parent.parent.startPosition) + (#set! indent.offsetIndent 1)) + + +; ONE-LINE CONDITIONALS +; ===================== + +; An `if` statement without an opening brace should indent the next line… +(if_statement + condition: (parenthesized_expression ")" @indent + (#is? test.lastTextOnRow true))) +; (as should a braceless `else`…) +("else" @indent + (#is? test.lastTextOnRow true)) + +; …and keep that indent level if the user types a comment before the +; consequence… +(if_statement + consequence: (empty_statement) @match + (#is-not? test.startsOnSameRowAs parent.startPosition) + (#set! indent.matchIndentOf parent.startPosition) + (#set! indent.offsetIndent 1)) + +; …and keep that indent level after the user starts typing… +(if_statement + condition: (_) @indent + consequence: [ + (expression_statement) + (return_statement) + (continue_statement) + (break_statement) + (throw_statement) + (debugger_statement) + ] @match + ; When an opening curly brace is unpaired, it might get interpreted as part + ; of an `expression_statement`, for some reason. + (#not-match? @match "^\\s*{") + (#set! indent.matchIndentOf parent.startPosition) + (#set! indent.offsetIndent 1)) + +; …but dedent after exactly one statement. +(if_statement + condition: (_) @indent + consequence: [ + (expression_statement) + (return_statement) + (continue_statement) + (break_statement) + (throw_statement) + (debugger_statement) + ] @dedent.next + ; When an opening curly brace is unpaired, it might get interpreted as part + ; of an `expression_statement`, for some reason. + (#not-match? @dedent.next "^\\s*{")) + +(else_clause + [ + (expression_statement) + (return_statement) + (continue_statement) + (break_statement) + (throw_statement) + (debugger_statement) + ] @dedent.next + (#is-not? test.startsOnSameRowAs parent.startPosition)) + +; HANGING INDENT ON SPLIT LINES +; ============================= + +; TODO: We might want to make this configurable behavior with the +; `config` scope test. + +; Any of these at the end of a line indicate the next line should be indented… +(["||" "&&" "?"] @indent + (#is? test.lastTextOnRow true)) + +; …and the line after that should be dedented. +(binary_expression + ["||" "&&"] + right: (_) @dedent.next + (#is-not? test.startsOnSameRowAs parent.startPosition)) + +; …unless it's a ternary, in which case the dedent should wait until the +; alternative clause. +; +; let foo = this.longTernaryCondition() ? +; consequenceWhichIsItselfRatherLong : +; alternativeThatIsNotBrief; +; +(ternary_expression + alternative: (_) @dedent.next + (#is-not? test.startsOnSameRowAs parent.startPosition)) + + +; GENERAL +; ======= + +; Weed out `}`s that should not signal dedents. +(template_substitution "}" @_IGNORE_ (#set! capture.final true)) + [ "{" @@ -27,5 +137,4 @@ (type_arguments "<" @indent) (type_arguments ">" @dedent) - ["case" "default"] @indent diff --git a/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm b/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm index dee9c2f64..bd25180c1 100644 --- a/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm +++ b/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm @@ -2,5 +2,7 @@ ; JSX ; === -(jsx_opening_element) @indent -(jsx_closing_element ">") @dedent +(jsx_opening_element ["<" ">"] @indent) +(jsx_opening_element [">"] @dedent) + +(jsx_closing_element ">" @dedent) From 220e70fc41cf6b15551e7d1f8ff5f9ed038ad2d1 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:42:54 -0700 Subject: [PATCH 18/29] Ensure `setQueryForTest` fires the `onDidChangeQueryFile` callback --- src/wasm-tree-sitter-grammar.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/wasm-tree-sitter-grammar.js b/src/wasm-tree-sitter-grammar.js index 3ebb0aa4b..1b89ba347 100644 --- a/src/wasm-tree-sitter-grammar.js +++ b/src/wasm-tree-sitter-grammar.js @@ -127,7 +127,7 @@ module.exports = class WASMTreeSitterGrammar { this.observeQueryFile(filePaths, key); } } - Promise.all(promises).then(() => resolve()); + return Promise.all(promises).then(() => resolve()); }).then(() => { this._queryFilesLoaded = true; this._loadQueryFilesPromise = null; @@ -254,7 +254,9 @@ module.exports = class WASMTreeSitterGrammar { await this.getLanguage(); this.queryCache.delete(queryType); this[queryType] = contents; - return await this.getQuery(queryType); + let query = await this.getQuery(queryType); + this.emitter.emit('did-change-query-file', { filePath: '', queryType }); + return query; } // Observe a particular query file on disk so that it can immediately be From d5fb9f50077d5d3437ad10994dc2ea78971701da Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:44:21 -0700 Subject: [PATCH 19/29] Fix bug when trying to determine indentation level of a misaligned line For example: if tab size is set to 2, we should interpret a line with 3 leading spaces as having been indented 1 level, not 1.5. --- src/wasm-tree-sitter-language-mode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm-tree-sitter-language-mode.js b/src/wasm-tree-sitter-language-mode.js index bfba2af77..d7ac1cc0d 100644 --- a/src/wasm-tree-sitter-language-mode.js +++ b/src/wasm-tree-sitter-language-mode.js @@ -1124,7 +1124,7 @@ class WASMTreeSitterLanguageMode { break; } } - return indentLength / tabLength; + return Math.floor(indentLength / tabLength); } // Get the suggested indentation level for an existing line in the buffer. From 2358e1e90d0b2e7a25e30cb31eff7b49b57ec540 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 09:46:11 -0700 Subject: [PATCH 20/29] Surface more information when a grammar fails to load Also, recover from a malformed `highlights.scm` on load by loading an empty query file instead. It'll be obvious that the real query file failed to load. --- src/wasm-tree-sitter-language-mode.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/wasm-tree-sitter-language-mode.js b/src/wasm-tree-sitter-language-mode.js index d7ac1cc0d..1fa602c4b 100644 --- a/src/wasm-tree-sitter-language-mode.js +++ b/src/wasm-tree-sitter-language-mode.js @@ -2821,10 +2821,10 @@ class GrammarLoadError extends Error { constructor(grammar, queryType) { super(`Grammar ${grammar.scopeName} failed to load its ${queryType}. Please fix this error or contact the maintainer.`); this.name = 'GrammarLoadError'; + this.queryType = queryType; } } - // Manages all aspects of a given language's parsing duties over a given region // of the buffer. // @@ -2898,6 +2898,13 @@ class LanguageLayer { }).catch((err) => { if (err.name === 'GrammarLoadError') { console.warn(err.message); + if (err.queryType === 'highlightsQuery') { + // TODO: Warning? + grammar.highlightsQuery = grammar.setQueryForTest( + 'highlightsQuery', + `; (placeholder)` + ); + } } else { throw err; } From 0039432bb46f9c3f360780d706bd9532a17d40ac Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 11:38:13 -0700 Subject: [PATCH 21/29] Rework how we find comment delimiters Checking on the grammar first means that we get no opportunity to override the answer. It also fails to account for languages in which the correct comment delimiters vary based on context. Instead, we check settings _first_, then fall back to the grammar itself. --- src/wasm-tree-sitter-grammar.js | 46 +++++++++++++++++ src/wasm-tree-sitter-language-mode.js | 71 +++++++++++++++++---------- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/src/wasm-tree-sitter-grammar.js b/src/wasm-tree-sitter-grammar.js index 1b89ba347..c14588fff 100644 --- a/src/wasm-tree-sitter-grammar.js +++ b/src/wasm-tree-sitter-grammar.js @@ -45,6 +45,8 @@ module.exports = class WASMTreeSitterGrammar { commentEndString: params.comments && params.comments.end }; + this.commentMetadata = params.comments; + this.shouldObserveQueryFiles = atom.inDevMode() && !atom.inSpecMode(); this.getLanguage(); @@ -69,6 +71,50 @@ module.exports = class WASMTreeSitterGrammar { return id; } + // Retrieve the comment delimiters for this grammar. + // + // Traditionally, grammars specified only the delimiters needed for the + // “Toggle Line Comments” command — either a line comment (if it existed) or + // a block comment. But other features might want to know _all_ of a + // language's possible comment delimiters, so we've devised new config values. + getCommentDelimiters() { + let meta = this.commentMetadata; + if (!meta) { return null; } + + let result = {}; + + // The new convention is to specify a `line` property and start/end + // properties. + let { line, block } = this.commentMetadata; + + // Failing that, we can deliver at least a partial result by inspecting the + // older convention. If `start` exists but not `end`, we know `start` must + // be a line comment delimiter. + if (!line && meta.start && !meta.end) { + line = meta.start; + } + // Likewise, if both `start` and `end` exist, we know they must be block + // comment delimiters. + if (!block && meta.start && meta.end) { + block = { start: meta.start, end: meta.end }; + } + + // Strip all whitespace from delimiters. Whatever is consuming them can + // decide if it wants whitespace. + if (line) { + line = line.strip(); + result.line = line; + } + + if (block) { + block.start = block.start?.strip(); + block.end = block.end?.strip(); + result.block = block; + } + + return result; + } + classNameForScopeId(id) { return this.classNamesById.get(id); } diff --git a/src/wasm-tree-sitter-language-mode.js b/src/wasm-tree-sitter-language-mode.js index 1fa602c4b..559274b4d 100644 --- a/src/wasm-tree-sitter-language-mode.js +++ b/src/wasm-tree-sitter-language-mode.js @@ -1056,19 +1056,42 @@ class WASMTreeSitterLanguageMode { Section - Comments */ - // TODO: I know that old tree-sitter moved toward placing this data on the - // grammar itself, but I would prefer to invert the order of these lookups. - // As a config setting it can be scoped and overridden, but as a grammar - // property it's just a fact of life that can't be worked around. - // - // TODO: Also, this should be revisited soon so that we can give the - // `snippets` package the ability to ask about all of a grammar's comment - // tokens — both line and block. + // Returns the correct comment delimiters for the given buffer position. This + // may be defined on the grammar itself, but it can also be defined as a + // scope-specific setting for scenarios where a language has different + // comment delimiters for different contexts. // + // TODO: Our understanding of the correct delimiters for a given buffer + // position is only as granular as the entire buffer row. This can bite us in + // edge cases like JSX. It's the right decision if the user toggles a comment + // with an empty selection, but if specific buffer text is selected, we + // should look up the right delmiters for that specific range. This will + // require a new branch in the “Editor: Toggle Line Comments” command. commentStringsForPosition(position) { - // First ask the grammar for its comment strings. const range = this.firstNonWhitespaceRange(position.row) || new Range(position, position); + + // Ask the config system if it has a setting for this scope. This allows + // for overrides from the grammar default. + const scope = this.scopeDescriptorForPosition(range.start); + const commentStartEntries = this.config.getAll( + 'editor.commentStart', { scope }); + const commentEndEntries = this.config.getAll( + 'editor.commentEnd', { scope }); + + const commentStartEntry = commentStartEntries[0]; + const commentEndEntry = commentEndEntries.find(entry => ( + entry.scopeSelector === commentStartEntry.scopeSelector + )); + + if (commentStartEntry) { + return { + commentStartString: commentStartEntry && commentStartEntry.value, + commentEndString: commentEndEntry && commentEndEntry.value + }; + } + + // Fall back to looking up this information on the grammar. const { grammar } = this.getSyntaxNodeAndGrammarContainingRange(range); if (grammar) { @@ -1079,22 +1102,6 @@ class WASMTreeSitterLanguageMode { return commentStrings; } } - - // Fall back to a lookup through the config system. - const scope = this.scopeDescriptorForPosition(position); - const commentStartEntries = this.config.getAll( - 'editor.commentStart', { scope }); - const commentEndEntries = this.config.getAll( - 'editor.commentEnd', { scope }); - - const commentStartEntry = commentStartEntries[0]; - const commentEndEntry = commentEndEntries.find(entry => ( - entry.scopeSelector === commentStartEntry.scopeSelector - )); - return { - commentStartString: commentStartEntry && commentStartEntry.value, - commentEndString: commentEndEntry && commentEndEntry.value - }; } isRowCommented(row) { @@ -1642,6 +1649,11 @@ class WASMTreeSitterLanguageMode { } } + if (!indentTree) { + console.error(`No indent tree!`, controllingLayer.inspect()); + return undefined; + } + const indents = indentsQuery.captures( indentTree.rootNode, { row: row, column: 0 }, @@ -2928,12 +2940,17 @@ class LanguageLayer { if (depth === 0) { languageScope = this.grammar.scopeName; } else { + // Injections can control the base scope name of the grammar being + // injected. languageScope = injectionPoint.languageScope; - // Honor an explicit `null`, but fall back to the default scope name - // otherwise. + + // The `languageScope` parameter can be a function. if (typeof languageScope === 'function') { languageScope = languageScope(this.grammar); } + + // Honor an explicit `null`, but fall back to the default scope name + // otherwise. if (languageScope === undefined) { languageScope = this.grammar.scopeName; } From ff34f2daf2ca611f2380bc289772d5305686989b Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 11:39:00 -0700 Subject: [PATCH 22/29] Use the proper comment delimiters when commenting out a range of JSX --- .../language-javascript/grammars/ts/highlights.scm | 14 ++++++++++++++ .../settings/language-javascript.cson | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/language-javascript/grammars/ts/highlights.scm b/packages/language-javascript/grammars/ts/highlights.scm index 39ac3579b..74f81c9cc 100644 --- a/packages/language-javascript/grammars/ts/highlights.scm +++ b/packages/language-javascript/grammars/ts/highlights.scm @@ -945,6 +945,20 @@ (#set! adjust.endAt lastChild.startPosition)) +([ + (jsx_opening_element) + (jsx_closing_element) +] @meta.jsx.inside-tag.js +(#set! adjust.startAt firstChild.endPosition)) + +((jsx_self_closing_element) @meta.jsx.inside-tag.js +(#set! adjust.startAt firstChild.endPosition) +(#set! adjust.endAt lastChild.startPosition)) + +((jsx_element) @meta.block.jsx.js + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition)) + ; MISC ; ==== diff --git a/packages/language-javascript/settings/language-javascript.cson b/packages/language-javascript/settings/language-javascript.cson index 37198cb09..48b832fb6 100644 --- a/packages/language-javascript/settings/language-javascript.cson +++ b/packages/language-javascript/settings/language-javascript.cson @@ -11,3 +11,13 @@ 'decreaseIndentPattern': '(?x) ^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])] ' + +'.source.js .meta.block.jsx.js': + 'editor': + 'commentStart': '{/*' + 'commentEnd': '*/}' + +'.source.js .meta.jsx.inside-tag.js': + 'editor': + 'commentStart': '{/*' + 'commentEnd': '*/}' From 10907fb40ffa00778db67a315b8dc70c5717dda9 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 11:50:29 -0700 Subject: [PATCH 23/29] Use correct comment delimiters within JSX when using a TSX grammar --- .../grammars/tree-sitter-tsx/highlights.scm | 18 ++++++++++++++++++ .../settings/TypeScriptReact.cson | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/packages/language-typescript/grammars/tree-sitter-tsx/highlights.scm b/packages/language-typescript/grammars/tree-sitter-tsx/highlights.scm index e0f995633..c8b90d23a 100644 --- a/packages/language-typescript/grammars/tree-sitter-tsx/highlights.scm +++ b/packages/language-typescript/grammars/tree-sitter-tsx/highlights.scm @@ -38,3 +38,21 @@ (#set! adjust.startAt lastChild.previousSibling.startPosition) (#set! adjust.endAt lastChild.endPosition) (#set! capture.final true)) + + +; META +; ==== + +([ + (jsx_opening_element) + (jsx_closing_element) +] @meta.jsx.inside-tag.ts.tsx +(#set! adjust.startAt firstChild.endPosition)) + +((jsx_self_closing_element) @meta.jsx.inside-tag.ts.tsx +(#set! adjust.startAt firstChild.endPosition) +(#set! adjust.endAt lastChild.startPosition)) + +((jsx_element) @meta.block.jsx.ts.tsx + (#set! adjust.startAt firstChild.endPosition) + (#set! adjust.endAt lastChild.startPosition)) diff --git a/packages/language-typescript/settings/TypeScriptReact.cson b/packages/language-typescript/settings/TypeScriptReact.cson index 941998002..4ffd62638 100644 --- a/packages/language-typescript/settings/TypeScriptReact.cson +++ b/packages/language-typescript/settings/TypeScriptReact.cson @@ -11,9 +11,9 @@ ^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])] ' -'.meta.tag.tsx': +'.meta.tag.tsx, .meta.block.jsx.ts.tsx': 'editor': 'commentStart': '{/* ', 'commentEnd': ' */}', 'increaseIndentPattern': "{[^}\"']*$|\\[[^\\]\"']*$|\\([^)\"']*$|<[a-zA-Z][^/]*$|^\\s*>$", - 'decreaseIndentPattern': "^\\s*(\\s*/[*].*[*]/\\s*)*[}\\])]|^\\s*()" \ No newline at end of file + 'decreaseIndentPattern': "^\\s*(\\s*/[*].*[*]/\\s*)*[}\\])]|^\\s*()" From 9954068f8f73261e7cc9b1bbcf3bca4491282086 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Wed, 16 Aug 2023 19:34:41 -0700 Subject: [PATCH 24/29] Fix syntax highlighting of Ruby regexes --- packages/language-ruby/grammars/ts/regex/highlights.scm | 2 -- packages/language-ruby/lib/main.js | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/language-ruby/grammars/ts/regex/highlights.scm b/packages/language-ruby/grammars/ts/regex/highlights.scm index 85255d818..b0018b6c7 100644 --- a/packages/language-ruby/grammars/ts/regex/highlights.scm +++ b/packages/language-ruby/grammars/ts/regex/highlights.scm @@ -3,8 +3,6 @@ ; * No support for lookbehind as of March 2023 (waiting on ; https://github.com/tree-sitter/tree-sitter-regex/pull/15) -(pattern) @string.regexp - (non_capturing_group) @meta.group.non-capturing.regexp [ diff --git a/packages/language-ruby/lib/main.js b/packages/language-ruby/lib/main.js index df1a0041f..5f343a42f 100644 --- a/packages/language-ruby/lib/main.js +++ b/packages/language-ruby/lib/main.js @@ -1,4 +1,4 @@ -exports.activate = function() { +exports.activate = function () { if (!atom.grammars.addInjectionPoint) return; atom.grammars.addInjectionPoint('source.ruby', { @@ -19,6 +19,7 @@ exports.activate = function() { content(node) { return node; }, + languageScope: null, includeChildren: true, // coverShallowerScopes: false }); From ebf5333022451b7855c971db6a8c1fab8a8019f1 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Mon, 21 Aug 2023 00:46:29 -0700 Subject: [PATCH 25/29] [language-c] Scope identifiers as types when they are unambiguously so Anything that is one of the reserved type words in C must be a type in all contexts. And any identifier that ends in `_t` is, by strong convention, a type. --- .../language-c/grammars/tree-sitter-c/highlights.scm | 10 ++++++++++ .../grammars/tree-sitter-cpp/highlights.scm | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/packages/language-c/grammars/tree-sitter-c/highlights.scm b/packages/language-c/grammars/tree-sitter-c/highlights.scm index 51778a17d..a85ee5977 100644 --- a/packages/language-c/grammars/tree-sitter-c/highlights.scm +++ b/packages/language-c/grammars/tree-sitter-c/highlights.scm @@ -46,6 +46,16 @@ (primitive_type) @storage.type.builtin.c (type_identifier) @storage.type.other.c +; These types are all reserved words; if we see an identifier with this name, +; it must be a type. +((identifier) @storage.type.builtin.c + (#match? @storage.type.builtin.c "^(char|int|float|double|long)$")) + +; Assume any identifier that ends in `_t` is a type. This convention is not +; always followed, but it's a very strong indicator when it's present. +((identifier) @storage.type.other.c + (#match? @storage.type.other.c "_t$")) + [ "enum" "long" diff --git a/packages/language-c/grammars/tree-sitter-cpp/highlights.scm b/packages/language-c/grammars/tree-sitter-cpp/highlights.scm index 634aa8535..ed0d2ebc9 100644 --- a/packages/language-c/grammars/tree-sitter-cpp/highlights.scm +++ b/packages/language-c/grammars/tree-sitter-cpp/highlights.scm @@ -58,6 +58,17 @@ (type_identifier) @storage.type.other.cpp ; (struct_specifier) @storage.type.cpp +; These types are all reserved words; if we see an identifier with this name, +; it must be a type. +((identifier) @storage.type.builtin.cpp + (#match? @storage.type.builtin.cpp "^(char|int|float|double|long)$")) + +; Assume any identifier that ends in `_t` is a type. This convention is not +; always followed, but it's a very strong indicator when it's present. +((identifier) @storage.type.other.cpp + (#match? @storage.type.other.cpp "_t$")) + + [ "enum" "long" From 490ff32237be2211777775bdea8cddb41da53b6e Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sun, 27 Aug 2023 00:24:42 -0700 Subject: [PATCH 26/29] [language-yaml] Highlight single-quoted strings --- packages/language-yaml/grammars/tree-sitter/highlights.scm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/language-yaml/grammars/tree-sitter/highlights.scm b/packages/language-yaml/grammars/tree-sitter/highlights.scm index 14e10bfcc..0e30f273d 100644 --- a/packages/language-yaml/grammars/tree-sitter/highlights.scm +++ b/packages/language-yaml/grammars/tree-sitter/highlights.scm @@ -35,6 +35,8 @@ ((string_scalar) @string.quoted.yaml) +(single_quote_scalar) @string.quoted.single.yaml + (double_quote_scalar) @string.quoted.double.yaml ((double_quote_scalar) @punctuation.definition.string.begin.yaml From 37e25ac49e18f906db80e1e02ebc7a4c5810c108 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sun, 27 Aug 2023 00:33:40 -0700 Subject: [PATCH 27/29] [language-yaml] Add scopes for single-quoted string delimiters --- packages/language-yaml/grammars/tree-sitter/highlights.scm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/language-yaml/grammars/tree-sitter/highlights.scm b/packages/language-yaml/grammars/tree-sitter/highlights.scm index 0e30f273d..83ef5ee70 100644 --- a/packages/language-yaml/grammars/tree-sitter/highlights.scm +++ b/packages/language-yaml/grammars/tree-sitter/highlights.scm @@ -37,6 +37,12 @@ (single_quote_scalar) @string.quoted.single.yaml +((single_quote_scalar) @punctuation.definition.string.begin.yaml + (#set! adjust.endAfterFirstMatchOf "^'")) + +((single_quote_scalar) @punctuation.definition.string.end.yaml + (#set! adjust.startBeforeFirstMatchOf "'$")) + (double_quote_scalar) @string.quoted.double.yaml ((double_quote_scalar) @punctuation.definition.string.begin.yaml From 878ef168c2c6769293e2fb3424fe68f5b478a124 Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Sun, 27 Aug 2023 00:48:48 -0700 Subject: [PATCH 28/29] [language-yaml] Fix deprecated predicate syntax --- packages/language-yaml/grammars/tree-sitter/highlights.scm | 4 ++-- packages/language-yaml/grammars/tree-sitter/indents.scm | 2 +- packages/language-yaml/grammars/tree-sitter/tags.scm | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/language-yaml/grammars/tree-sitter/highlights.scm b/packages/language-yaml/grammars/tree-sitter/highlights.scm index 83ef5ee70..2f45509bb 100644 --- a/packages/language-yaml/grammars/tree-sitter/highlights.scm +++ b/packages/language-yaml/grammars/tree-sitter/highlights.scm @@ -4,11 +4,11 @@ (block_mapping_pair key: (_) @entity.name.tag.yaml - (#set! test.final true)) + (#set! capture.final true)) (flow_pair key: (_) @entity.name.tag.yaml - (#set! test.final true)) + (#set! capture.final true)) ; COMMENTS diff --git a/packages/language-yaml/grammars/tree-sitter/indents.scm b/packages/language-yaml/grammars/tree-sitter/indents.scm index 05dec1522..1cf9c2ad2 100644 --- a/packages/language-yaml/grammars/tree-sitter/indents.scm +++ b/packages/language-yaml/grammars/tree-sitter/indents.scm @@ -1,4 +1,4 @@ (":" @indent - (#set! test.onlyIfLastTextOnRow true)) + (#is? test.lastTextOnRow true)) ["|" ">"] @indent diff --git a/packages/language-yaml/grammars/tree-sitter/tags.scm b/packages/language-yaml/grammars/tree-sitter/tags.scm index c5983fe84..4d76571af 100644 --- a/packages/language-yaml/grammars/tree-sitter/tags.scm +++ b/packages/language-yaml/grammars/tree-sitter/tags.scm @@ -1,6 +1,6 @@ (block_mapping_pair key: (_) @name - (#set! test.final true) + (#set! capture.final true) (#set! symbol.prependSymbolForNode parent.parent.parent.parent.parent.parent.parent.firstNamedChild) (#set! symbol.joiner ".")) From e9903ad9d6602f90d6146fedeab1071144b1049c Mon Sep 17 00:00:00 2001 From: Andrew Dupont Date: Mon, 11 Sep 2023 15:14:19 -0700 Subject: [PATCH 29/29] =?UTF-8?q?Change=20behavior=20of=20=E2=80=9Cadjustm?= =?UTF-8?q?ent=20exceeds=20bounds=E2=80=9D=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, we threw an error when a scope adjustment violated its bounds constraints, but that's a bit disruptive for everyday use. Instead, we throw an error in dev mode (so that the grammar's author doesn't fail to notice the problem), but downgrade it to a warning outside of dev mode so that it's recoverable. There's a chance that the warning will be _too_ subtle, but we'll give it a shot. We also include more diagnostic information so that it's clearer exactly _where_ the violation is happening. --- spec/scope-resolver-spec.js | 2 +- src/scope-resolver.js | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/spec/scope-resolver-spec.js b/spec/scope-resolver-spec.js index 5f7611d87..ccd2af6b2 100644 --- a/spec/scope-resolver-spec.js +++ b/spec/scope-resolver-spec.js @@ -228,7 +228,7 @@ describe('ScopeResolver', () => { let bar = "this is a line below a comment" `); // Prevent an exception from being thrown before we can even check the - // scopeResovler. + // scopeResolver. spyOn(languageMode, 'isRowCommented').andReturn(false); await languageMode.ready; diff --git a/src/scope-resolver.js b/src/scope-resolver.js index 5ce0a33dd..559389bf4 100644 --- a/src/scope-resolver.js +++ b/src/scope-resolver.js @@ -16,6 +16,11 @@ function comparePoints(a, b) { } } +function rangeSpecToString (range) { + let [sp, ep] = [range.startPosition, range.endPosition]; + return `(${sp.row}, ${sp.column}) - (${ep.row}, ${ep.column})`; +} + function resolveNodeDescriptor(node, descriptor) { let parts = descriptor.split('.'); let result = node; @@ -266,6 +271,20 @@ class ScopeResolver { return ScopeResolver.CAPTURE_SETTINGS[prop](...args); } + warnAboutExceededRange(range, capture) { + let msg = ['Cannot extend past original range of capture!']; + + msg.push(`Scope name: ${capture.name}`); + msg.push(`Original range: ${rangeSpecToString(capture.node)}`); + msg.push(`Adjusted range: ${rangeSpecToString(range)}`); + + if (atom.inDevMode()) { + throw new Error(msg.join('\n')); + } + + console.warn(msg.join('\n')); + } + // Given a capture and possible predicate data, determines the buffer range // that this capture wants to cover. determineCaptureRange(capture) { @@ -299,7 +318,7 @@ class ScopeResolver { } if (this.rangeExceedsBoundsOfCapture(range, capture)) { - throw new Error('Cannot extend past original range of capture'); + this.warnAboutExceededRange(range, capture); } // Any invalidity in the returned range means we shouldn't store this