diff --git a/packages/language-c/grammars/tree-sitter-cpp/highlights.scm b/packages/language-c/grammars/tree-sitter-cpp/highlights.scm index f6a745189d..335640633d 100644 --- a/packages/language-c/grammars/tree-sitter-cpp/highlights.scm +++ b/packages/language-c/grammars/tree-sitter-cpp/highlights.scm @@ -138,6 +138,9 @@ (function_declarator (field_identifier) @entity.name.function.method.cpp) +(field_initializer + (field_identifier) @entity.name.function.cpp) + (call_expression (identifier) @support.function.c99.cpp ; Regex copied from the TM grammar. diff --git a/packages/language-c/lib/main.js b/packages/language-c/lib/main.js index 274a61af83..6e432cd646 100644 --- a/packages/language-c/lib/main.js +++ b/packages/language-c/lib/main.js @@ -1,10 +1,10 @@ -exports.activate = function() { +exports.activate = function () { // Highlight macro bodies as C/C++ for (const language of ['c', 'cpp']) { for (const nodeType of ['preproc_def', 'preproc_function_def']) { atom.grammars.addInjectionPoint(`source.${language}`, { type: nodeType, - language(node) { + language() { return language; }, content(node) { @@ -12,5 +12,28 @@ 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?:/ + + atom.grammars.addInjectionPoint(`source.${language}`, { + type: 'comment', + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + for (let type of ['string_literal', 'comment']) { + atom.grammars.addInjectionPoint(`source.${language}`, { + type, + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } } }; diff --git a/packages/language-c/package.json b/packages/language-c/package.json index 9a1ff5db85..2b891a171d 100644 --- a/packages/language-c/package.json +++ b/packages/language-c/package.json @@ -10,7 +10,7 @@ "license": "MIT", "engines": { "atom": "*", - "node": "*" + "node": ">=12" }, "dependencies": { "tree-sitter-c": "0.20.2", diff --git a/packages/language-css/lib/main.js b/packages/language-css/lib/main.js index 93ac5b607c..c12fb4b56b 100644 --- a/packages/language-css/lib/main.js +++ b/packages/language-css/lib/main.js @@ -1,22 +1,27 @@ exports.activate = () => { - atom.grammars.addInjectionPoint('source.css', { - type: 'comment', - language: () => 'todo', - content: (node) => node - }); + 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.css', { type: 'comment', - language: () => 'hyperlink', - content: (node) => node + language(node) { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null }); - atom.grammars.addInjectionPoint('source.css', { - type: 'string_value', - language: () => 'hyperlink', - content: (node) => node - }); + for (let type of ['comment', 'string_value']) { + atom.grammars.addInjectionPoint('source.css', { + type, + language(node) { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } // Catch things like // @@ -31,7 +36,8 @@ exports.activate = () => { if (!functionName === 'url') { return null; } return node.descendantsOfType('plain_value'); - } + }, + languageScope: null }); }; diff --git a/packages/language-go/lib/main.js b/packages/language-go/lib/main.js new file mode 100644 index 0000000000..a74d32bef5 --- /dev/null +++ b/packages/language-go/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?:/ + + for (let type of ['comment', 'interpreted_string_literal', 'raw_string_literal']) { + atom.grammars.addInjectionPoint('source.go', { + type, + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } + + atom.grammars.addInjectionPoint('source.go', { + type: 'comment', + language(node) { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + +}; diff --git a/packages/language-go/package.json b/packages/language-go/package.json index da3e7ffd33..91bb8d0e0a 100644 --- a/packages/language-go/package.json +++ b/packages/language-go/package.json @@ -1,6 +1,7 @@ { "name": "language-go", "description": "Go language support in Atom", + "main": "lib/main", "keywords": [ "tree-sitter" ], diff --git a/packages/language-html/grammars/tree-sitter-html/folds.scm b/packages/language-html/grammars/tree-sitter-html/folds.scm index 39a0f8eaaf..5c8919ff7f 100644 --- a/packages/language-html/grammars/tree-sitter-html/folds.scm +++ b/packages/language-html/grammars/tree-sitter-html/folds.scm @@ -1,8 +1,4 @@ -; (element) @fold -; (style_element) @fold -; (script_element) @fold - [ (element) (script_element) diff --git a/packages/language-hyperlink/spec/hyperlink-spec.js b/packages/language-hyperlink/spec/hyperlink-spec.js index a5015bce26..41be450d9c 100644 --- a/packages/language-hyperlink/spec/hyperlink-spec.js +++ b/packages/language-hyperlink/spec/hyperlink-spec.js @@ -1,21 +1,26 @@ const path = require('path'); -describe('Hyperlink grammar', function() { +describe('Hyperlink grammar', function () { let grammar = null; - beforeEach(function() { + beforeEach(function () { + // TODO: All these specs rely on the ability of a grammar to tokenize a + // line in isolation, which is something that a `WASMTreeSitterGrammar` + // cannot do. This package will need specialized tests for the modern + // Tree-sitter world the same way that most other language packages do. + atom.config.set('core.useTreeSitterParsers', false); waitsForPromise(() => atom.packages.activatePackage('language-hyperlink')); runs(() => grammar = atom.grammars.grammarForScopeName('text.hyperlink')); }); - it('parses the grammar', function() { + it('parses the grammar', function () { expect(grammar).toBeTruthy(); expect(grammar.scopeName).toBe('text.hyperlink'); }); - it('parses http: and https: links', function() { + it('parses http: and https: links', function () { const plainGrammar = atom.grammars.selectGrammar(); let {tokens} = plainGrammar.tokenizeLine('http://github.com'); @@ -29,16 +34,16 @@ describe('Hyperlink grammar', function() { ({tokens} = plainGrammar.tokenizeLine('https://github.com/atom/brightray_example')); expect(tokens[0]).toEqual({value: 'https://github.com/atom/brightray_example', scopes: ['text.plain.null-grammar', 'markup.underline.link.https.hyperlink']}); -}); + }); - it('parses http: and https: links that contains unicode characters', function() { + it('parses http: and https: links that contains unicode characters', function () { const plainGrammar = atom.grammars.selectGrammar(); const {tokens} = plainGrammar.tokenizeLine('https://sv.wikipedia.org/wiki/Mañana'); expect(tokens[0]).toEqual({value: 'https://sv.wikipedia.org/wiki/Mañana', scopes: ['text.plain.null-grammar', 'markup.underline.link.https.hyperlink']}); -}); + }); - it('parses other links', function() { + it('parses other links', function () { const plainGrammar = atom.grammars.selectGrammar(); let {tokens} = plainGrammar.tokenizeLine('mailto:noreply@example.com'); @@ -49,55 +54,57 @@ describe('Hyperlink grammar', function() { ({tokens} = plainGrammar.tokenizeLine('atom://core/open/file?filename=urlEncodedFileName&line=n&column=n')); expect(tokens[0]).toEqual({value: 'atom://core/open/file?filename=urlEncodedFileName&line=n&column=n', scopes: ['text.plain.null-grammar', 'markup.underline.link.atom.hyperlink']}); -}); + }); - it('does not parse links in a regex string', function() { + it('does not parse links in a regex string', function () { const testGrammar = atom.grammars.loadGrammarSync(path.join(__dirname, 'fixtures', 'test-grammar.cson')); const {tokens} = testGrammar.tokenizeLine('regexp:http://github.com'); expect(tokens[1]).toEqual({value: 'http://github.com', scopes: ['source.test', 'string.regexp.test']}); -}); - - describe('parsing PHP strings', () => it('does not parse links in a regex string', function() { - // PHP is unique in that its root scope is `text.html.php`, meaning that even though - // `string - string.regexp` won't match in a regex string, `text` still will. - // This is the reason the injection selector is `text - string.regexp` instead. - // https://github.com/atom/language-php/issues/219 - - waitsForPromise(() => atom.packages.activatePackage('language-php')); - - runs(function() { - const phpGrammar = atom.grammars.grammarForScopeName('text.html.php'); + }); - const {tokens} = phpGrammar.tokenizeLine(''); - expect(tokens[3]).toEqual({value: 'mailto:', scopes: ['text.html.php', 'meta.embedded.line.php', 'source.php', 'string.regexp.double-quoted.php']});}); -})); + describe('parsing PHP strings', () => { + it('does not parse links in a regex string', function () { + // PHP is unique in that its root scope is `text.html.php`, meaning that even though + // `string - string.regexp` won't match in a regex string, `text` still will. + // This is the reason the injection selector is `text - string.regexp` instead. + // https://github.com/atom/language-php/issues/219 + + waitsForPromise(() => atom.packages.activatePackage('language-php')); + + runs(() => { + const phpGrammar = atom.grammars.grammarForScopeName('text.html.php'); + const {tokens} = phpGrammar.tokenizeLine(''); + expect(tokens[3]).toEqual({ value: 'mailto:', scopes: ['text.html.php', 'meta.embedded.line.php', 'source.php', 'string.regexp.double-quoted.php']}); + }); + }); + }); - describe('parsing cfml strings', function() { - it('does not include anything between (and including) pound signs', function() { + describe('parsing cfml strings', function () { + it('does not include anything between (and including) pound signs', function () { const plainGrammar = atom.grammars.selectGrammar(); const {tokens} = plainGrammar.tokenizeLine('http://github.com/#username#'); expect(tokens[0]).toEqual({value: 'http://github.com/', scopes: ['text.plain.null-grammar', 'markup.underline.link.http.hyperlink']}); - }); + }); - it('still includes single pound signs', function() { + it('still includes single pound signs', function () { const plainGrammar = atom.grammars.selectGrammar(); const {tokens} = plainGrammar.tokenizeLine('http://github.com/atom/#start-of-content'); expect(tokens[0]).toEqual({value: 'http://github.com/atom/#start-of-content', scopes: ['text.plain.null-grammar', 'markup.underline.link.http.hyperlink']}); + }); }); -}); - describe('parsing matching parentheses', function() { - it('still includes matching parentheses', function() { + describe('parsing matching parentheses', function () { + it('still includes matching parentheses', function () { const plainGrammar = atom.grammars.selectGrammar(); const {tokens} = plainGrammar.tokenizeLine('https://en.wikipedia.org/wiki/Atom_(text_editor)'); expect(tokens[0]).toEqual({value: 'https://en.wikipedia.org/wiki/Atom_(text_editor)', scopes: ['text.plain.null-grammar', 'markup.underline.link.https.hyperlink']}); - }); + }); - it('does not include wrapping parentheses', function() { + it('does not include wrapping parentheses', function () { const plainGrammar = atom.grammars.selectGrammar(); const {tokens} = plainGrammar.tokenizeLine('(https://en.wikipedia.org/wiki/Atom_(text_editor))'); expect(tokens[1]).toEqual({value: 'https://en.wikipedia.org/wiki/Atom_(text_editor)', scopes: ['text.plain.null-grammar', 'markup.underline.link.https.hyperlink']}); + }); }); }); -}); diff --git a/packages/language-java/lib/main.js b/packages/language-java/lib/main.js index bf6d7fccda..a1e953a7a2 100644 --- a/packages/language-java/lib/main.js +++ b/packages/language-java/lib/main.js @@ -1,3 +1,24 @@ exports.activate = () => { - // TODO: Injections for language-todo and language-hyperlink. + 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.java', { + type: 'comment', + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + for (let type of ['string_literal', 'comment']) { + atom.grammars.addInjectionPoint('source.java', { + type, + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } }; diff --git a/packages/language-javascript/grammars/ts/highlights.scm b/packages/language-javascript/grammars/ts/highlights.scm index faf170e16b..cd067c58da 100644 --- a/packages/language-javascript/grammars/ts/highlights.scm +++ b/packages/language-javascript/grammars/ts/highlights.scm @@ -74,7 +74,13 @@ ; The "bar" in `foo.bar = true` (assignment_expression left: (member_expression - property: (property_identifier)) @variable.other.assignment.property.js) + property: (property_identifier) @variable.other.assignment.property.js)) + +; The "bar" in `foo.#bar = true` +(assignment_expression + left: (member_expression + property: (private_property_identifier) @variable.other.assignment.property.private.js)) + ; The "foo" in `foo += 1`. (augmented_assignment_expression @@ -84,6 +90,9 @@ (update_expression argument: (identifier) @variable.other.assignment.js) +(field_definition + property: (private_property_identifier) @variable.other.assignment.property.private.js) + ; `object_pattern` appears to only be encountered in assignment expressions, so ; this won't match other uses of object/prop shorthand. ; @@ -136,6 +145,13 @@ (array_pattern (identifier) @variable.other.assignment.destructuring.js)) +; A variable array destructuring with a default: +; The "baz" in `let [foo, bar, baz = false] = something` +(variable_declarator + (array_pattern + (assignment_pattern + (identifier) @variable.other.assignment.destructuring.js))) + ; A variable declaration in a for…(in|of) loop: ; The "foo" in `for (let foo of bar) {` (for_in_statement @@ -203,7 +219,7 @@ ; The "foo" in `function (foo = false) {`. (formal_parameters (assignment_pattern - (identifier) @variable.parameter.js)) + left: (identifier) @variable.parameter.js)) ; FUNCTIONS @@ -451,6 +467,10 @@ (member_expression property: (property_identifier) @support.other.property.js) +; The "#bar" in `foo.#bar`, `foo.#bar.baz`, and `foo.#bar[baz]`. +(member_expression + property: (private_property_identifier) @support.other.property.private.js) + ; The "BAR" in `foo.BAR` should also be scoped as a constant. (member_expression property: (property_identifier) @constant.other.property.js diff --git a/packages/language-javascript/grammars/ts/indents.scm b/packages/language-javascript/grammars/ts/indents.scm index 6aab803c11..dfac5ef7e4 100644 --- a/packages/language-javascript/grammars/ts/indents.scm +++ b/packages/language-javascript/grammars/ts/indents.scm @@ -155,8 +155,38 @@ ; JSX ; === - -(jsx_opening_element ["<" ">"] @indent) -(jsx_opening_element [">"] @dedent) - -(jsx_closing_element ">" @dedent) +(jsx_opening_element [">"] @indent) +; Support things like… +;
+(jsx_opening_element ["<"] @indent + (#is-not? test.startsOnSameRowAs parent.lastChild.startPosition)) +((jsx_opening_element [">"] @dedent) + (#is-not? test.startsOnSameRowAs parent.firstChild.startPosition)) + +; We match on the whole node here because +; (a) we need to please the dedent-while-typing heuristic, so the line text +; must match the capture node's text; and +; (b) we don't want the dedent to trigger until the very last `>` has been +; typed. +(jsx_closing_element ">") @dedent + +; Support things like… +; {'foo'} +(jsx_self_closing_element "<" @indent + (#is-not? test.startsOnSameRowAs parent.lastChild.startPosition)) + +; There isn't a single node whose exact text will match the line content at any +; point, so the usual heuristic won't work. Instead we set `indent.force` and +; use `test.lastTextOnRow` to ensure that the dedent fires exactly once while +; typing. +((jsx_self_closing_element ">" @dedent) + (#is-not? test.startsOnSameRowAs parent.firstChild.startPosition) + (#is? test.lastTextOnRow) + (#set! indent.force true)) diff --git a/packages/language-javascript/grammars/ts/jsdoc/highlights.scm b/packages/language-javascript/grammars/ts/jsdoc/highlights.scm index b9231f22bf..10d05b3a02 100644 --- a/packages/language-javascript/grammars/ts/jsdoc/highlights.scm +++ b/packages/language-javascript/grammars/ts/jsdoc/highlights.scm @@ -1,34 +1,34 @@ ; Highlight this comment even if it's not “valid” JSDoc. -((ERROR) @comment.block.documentation.js.jsdoc +((ERROR) @comment.block.documentation.jsdoc.js (#is? test.root true)) -((ERROR) @punctuation.definition.begin.comment.js.jsdoc +((ERROR) @punctuation.definition.begin.comment.jsdoc.js (#is? test.root true) (#set! adjust.startAndEndAroundFirstMatchOf "^/\\*\\*")) -((ERROR) @punctuation.definition.end.comment.js.jsdoc +((ERROR) @punctuation.definition.end.comment.jsdoc.js (#is? test.root true) (#set! adjust.startAndEndAroundFirstMatchOf "(?:\\*)?\\*/$")) -(document) @comment.block.documentation.js.jsdoc +(document) @comment.block.documentation.jsdoc.js -((document) @punctuation.definition.begin.comment.js.jsdoc +((document) @punctuation.definition.begin.comment.jsdoc.js (#set! adjust.startAndEndAroundFirstMatchOf "^/\\*\\*")) -((document) @punctuation.definition.end.comment.js.jsdoc +((document) @punctuation.definition.end.comment.jsdoc.js (#set! adjust.startAndEndAroundFirstMatchOf "(?:\\*)?\\*/$")) -((inline_tag) @meta.inline-tag.js.jsdoc) +((inline_tag) @meta.inline-tag.jsdoc.js) -(tag_name) @storage.type.class.jsdoc +(tag_name) @entity.name.tag.jsdoc.js -((tag (type)) @entity.other.type.instance.jsdoc +((tag (type)) @storage.type.instance.jsdoc.js ; Join the type with its surrounding braces. (#set! adjust.startAt firstChild.nextSibling.startPosition) (#set! adjust.endAt firstChild.nextSibling.nextSibling.nextSibling.endPosition)) -(identifier) @variable.other.jsdoc +(identifier) @variable.other.jsdoc.js -"{" @punctuation.definition.begin.bracket.curly.jsdoc -"}" @punctuation.definition.end.bracket.curly.jsdoc +"{" @punctuation.definition.begin.bracket.curly.jsdoc.js +"}" @punctuation.definition.end.bracket.curly.jsdoc.js diff --git a/packages/language-json/grammars/modern-tree-sitter-json.cson b/packages/language-json/grammars/modern-tree-sitter-json.cson index 6ecb289798..b315568dd1 100644 --- a/packages/language-json/grammars/modern-tree-sitter-json.cson +++ b/packages/language-json/grammars/modern-tree-sitter-json.cson @@ -6,6 +6,7 @@ parser: 'tree-sitter-json' injectionRegex: "^(json|JSON)$" treeSitter: + parserSource: 'github:tree-sitter/tree-sitter-json#3fef30de8aee74600f25ec2e319b62a1a870d51e' grammar: 'tree-sitter/tree-sitter-json.wasm' highlightsQuery: 'tree-sitter/queries/highlights.scm' indentsQuery: 'tree-sitter/queries/indents.scm' diff --git a/packages/language-json/grammars/tree-sitter/tree-sitter-json.wasm b/packages/language-json/grammars/tree-sitter/tree-sitter-json.wasm index 85d40ac684..63ae9457c4 100755 Binary files a/packages/language-json/grammars/tree-sitter/tree-sitter-json.wasm and b/packages/language-json/grammars/tree-sitter/tree-sitter-json.wasm differ diff --git a/packages/language-json/lib/main.js b/packages/language-json/lib/main.js new file mode 100644 index 0000000000..aea11b3811 --- /dev/null +++ b/packages/language-json/lib/main.js @@ -0,0 +1,13 @@ +exports.activate = () => { + const HYPERLINK_PATTERN = /\bhttps?:/ + + atom.grammars.addInjectionPoint('source.json', { + type: 'string_content', + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + +}; diff --git a/packages/language-json/package.json b/packages/language-json/package.json index f25f4f1512..dea51fc331 100644 --- a/packages/language-json/package.json +++ b/packages/language-json/package.json @@ -1,5 +1,6 @@ { "name": "language-json", + "main": "lib/main", "version": "1.0.5", "description": "JSON language support in Atom", "engines": { diff --git a/packages/language-php/grammars/modern-tree-sitter-php-html.cson b/packages/language-php/grammars/modern-tree-sitter-php-html.cson new file mode 100644 index 0000000000..2946872b43 --- /dev/null +++ b/packages/language-php/grammars/modern-tree-sitter-php-html.cson @@ -0,0 +1,34 @@ +name: 'PHP' +scopeName: 'text.html.php' +type: 'modern-tree-sitter' +parser: 'tree-sitter-php' + +injectionRegex: 'php|PHP' + +treeSitter: + parserSource: 'github:tree-sitter/tree-sitter-php#d5e7cacb6c27e0e131c7f76c0dbfee56dfcc61e3' + grammar: 'tree-sitter/tree-sitter-php.wasm' + highlightsQuery: 'tree-sitter/queries/highlights.scm' + tagsQuery: 'tree-sitter/queries/tags.scm' + foldsQuery: 'tree-sitter/queries/folds.scm' + indentsQuery: 'tree-sitter/queries/indents.scm' + +fileTypes: [ + 'aw' + 'ctp' + 'inc' + 'install' + 'module' + 'php' + 'php_cs' + 'php3' + 'php4' + 'php5' + 'phpt' + 'phtml' + 'profile' +] + +firstLineRegex: "^\\#!.*(?:\\s|\\/)php\\d?(?:$|\\s)|^\\s*<\\?(php|=|\\s|$)" + +contentRegex: "<\\?(php|=|\\s|$)" diff --git a/packages/language-php/grammars/modern-tree-sitter-php.cson b/packages/language-php/grammars/modern-tree-sitter-php.cson new file mode 100644 index 0000000000..01b82d73c9 --- /dev/null +++ b/packages/language-php/grammars/modern-tree-sitter-php.cson @@ -0,0 +1,12 @@ +scopeName: 'source.php' +type: 'modern-tree-sitter' +parser: 'tree-sitter-php' + +# Give it a precise injectionRegex that won't get accidentally matched with +# anything. This grammar only exists as a way to apply the `source.php` scope. +injectionRegex: '^(internal-php)$' + +treeSitter: + parserSource: 'github:tree-sitter/tree-sitter-php#594b8bad093abe739c3d2a2cae5abae33c5fb23d' + grammar: 'tree-sitter/tree-sitter-php.wasm' + highlightsQuery: 'tree-sitter/queries/empty.scm' diff --git a/packages/language-php/grammars/modern-tree-sitter-phpdoc.cson b/packages/language-php/grammars/modern-tree-sitter-phpdoc.cson new file mode 100644 index 0000000000..a3a43b1c7d --- /dev/null +++ b/packages/language-php/grammars/modern-tree-sitter-phpdoc.cson @@ -0,0 +1,11 @@ + +scopeName: 'comment.block.documentation.phpdoc.php' +type: 'modern-tree-sitter' +parser: 'tree-sitter-phpdoc' + +injectionRegex: '^(phpdoc|PHPDoc)$' + +treeSitter: + parserSource: 'github:claytonrcarter/tree-sitter-phpdoc#915a527d5aafa81b31acf67fab31b0ac6b6319c0' + grammar: 'tree-sitter/tree-sitter-phpdoc.wasm' + highlightsQuery: 'tree-sitter/queries/phpdoc/highlights.scm' diff --git a/packages/language-php/grammars/tree-sitter/queries/empty.scm b/packages/language-php/grammars/tree-sitter/queries/empty.scm new file mode 100644 index 0000000000..447212118b --- /dev/null +++ b/packages/language-php/grammars/tree-sitter/queries/empty.scm @@ -0,0 +1 @@ +; placeholder diff --git a/packages/language-php/grammars/tree-sitter/queries/folds.scm b/packages/language-php/grammars/tree-sitter/queries/folds.scm new file mode 100644 index 0000000000..2b0082226e --- /dev/null +++ b/packages/language-php/grammars/tree-sitter/queries/folds.scm @@ -0,0 +1,11 @@ + +(if_statement + body: (compound_statement) @fold + (#set! fold.adjustToEndOfPreviousRow true)) + +[ + (enum_declaration_list) + (compound_statement) + (switch_block) + (declaration_list) +] @fold diff --git a/packages/language-php/grammars/tree-sitter/queries/highlights.scm b/packages/language-php/grammars/tree-sitter/queries/highlights.scm new file mode 100644 index 0000000000..5801f81a62 --- /dev/null +++ b/packages/language-php/grammars/tree-sitter/queries/highlights.scm @@ -0,0 +1,597 @@ +; (program +; (_) @source.php +; (#is-not? test.type text) +; (#is-not? test.type text_interpolation)) + + +; SUPPORT +; ======= + +(array_creation_expression + "array" @support.function.builtin.array.php) + +(list_literal "list" @support.function.builtin.list.php) + +; The list of standard library methods in `php.cson` is… a lot. This is my +; biased attempt to pare it down to the most important functions. + +(function_call_expression + function: (name) @support.function.array.php + (#match? @support.function.array.php "^(shuffle|sizeof|sort|next|nat(case)?sort|count|compact|current|in_array|usort|uksort|uasort|pos|prev|end|each|extract|ksort|key(_exists)?|krsort|list|asort|arsort|rsort|reset|range|array(_(shift|sum|splice|search|slice|chunk|change_key_case|count_values|column|combine|(diff|intersect)(_(u)?(key|assoc))?|u(diff|intersect)(_(u)?assoc)?|unshift|unique|pop|push|pad|product|values|keys|key_exists|filter|fill(_keys)?|flip|walk(_recursive)?|reduce|replace(_recursive)?|reverse|rand|multisort|merge(_recursive)?|map)?))$")) + +(function_call_expression + function: (name) @support.function.basic-functions.php + (#match? @support.function.basic-functions.php "^(show_source|sys_getloadavg|sleep|highlight_(file|string)|constant|connection_(aborted|status)|time_(nanosleep|sleep_until)|ignore_user_abort|die|define(d)?|usleep|uniqid|unpack|__halt_compiler|php_(check_syntax|strip_whitespace)|pack|eval|exit|get_browser)$")) + +(function_call_expression + function: (name) @support.function.bcmath.php + (#match? @support.function.bcmath.php "^(bc(scale|sub|sqrt|comp|div|pow(mod)?|add|mod|mul))$")) + +(function_call_expression + function: (name) @support.function.class-obj.php + (#match? @support.function.class-obj.php "^(class_alias|all_user_method(_array)?|is_(a|subclass_of)|__autoload|(class|interface|method|property|trait)_exists|get_(class(_(vars|methods))?|(called|parent)_class|object_vars|declared_(classes|interfaces|traits)))$")) + +(function_call_expression + function: (name) @support.function.construct.php + (#match? @support.function.construct.php "^(isset|unset|eval|empty)$")) + +(function_call_expression + function: (name) @support.function.construct.output.php + (#match? @support.function.construct.output.php "^(print|echo)$")) + +(function_call_expression + function: (name) @support.function.curl.php + (#match? @support.function.curl.php "^(curl_(share_(close|init|setopt)|strerror|setopt(_array)?|copy_handle|close|init|unescape|pause|escape|errno|error|exec|version|file_create|reset|getinfo|multi_(strerror|setopt|select|close|init|info_read|(add|remove)_handle|getcontent|exec)))$")) + +(function_call_expression + function: (name) @support.function.datetime.php + (#match? @support.function.datetime.php "^(strtotime|str[fp]time|checkdate|time|timezone_name_(from_abbr|get)|idate|timezone_((location|offset|transitions|version)_get|(abbreviations|identifiers)_list|open)|date(_(sun(rise|set)|sun_info|sub|create(_(immutable_)?from_format)?|timestamp_(get|set)|timezone_(get|set)|time_set|isodate_set|interval_(create_from_date_string|format)|offset_get|diff|default_timezone_(get|set)|date_set|parse(_from_format)?|format|add|get_last_errors|modify))?|localtime|get(date|timeofday)|gm(strftime|date|mktime)|microtime|mktime)$")) + +(function_call_expression + function: (name) @support.function.dir.php + (#match? @support.function.dir.php "^(scandir|chdir|chroot|closedir|opendir|dir|rewinddir|readdir|getcwd)$")) + +(function_call_expression + function: (name) @support.function.ereg.php + (#match? @support.function.ereg.php "^(split(i)?|sql_regcase|ereg(i)?(_replace)?)$")) + +(function_call_expression + function: (name) @support.function.errorfunc.php + (#match? @support.function.errorfunc.php "^((restore|set)_(error_handler|exception_handler)|trigger_error|debug_(print_)?backtrace|user_error|error_(log|reporting|get_last))$")) + +(function_call_expression + function: (name) @support.function.exec.php + (#match? @support.function.exec.php "^(shell_exec|system|passthru|proc_(nice|close|terminate|open|get_status)|escapeshell(arg|cmd)|exec)$")) + +(function_call_expression + function: (name) @support.function.file.php + (#match? @support.function.file.php "^(symlink|stat|set_file_buffer|chown|chgrp|chmod|copy|clearstatcache|touch|tempnam|tmpfile|is_(dir|(uploaded_)?file|executable|link|readable|writ(e)?able)|disk_(free|total)_space|diskfreespace|dirname|delete|unlink|umask|pclose|popen|pathinfo|parse_ini_(file|string)|fscanf|fstat|fseek|fnmatch|fclose|ftell|ftruncate|file(size|[acm]time|type|inode|owner|perms|group)?|file_(exists|(get|put)_contents)|f(open|puts|putcsv|passthru|eof|flush|write|lock|read|gets(s)?|getc(sv)?)|lstat|lchown|lchgrp|link(info)?|rename|rewind|read(file|link)|realpath(_cache_(get|size))?|rmdir|glob|move_uploaded_file|mkdir|basename)$")) + +(function_call_expression + function: (name) @support.function.fileinfo.php + (#match? @support.function.fileinfo.php "^(finfo_(set_flags|close|open|file|buffer)|mime_content_type)$")) + +(function_call_expression + function: (name) @support.function.filter.php + (#match? @support.function.filter.php "^(filter_(has_var|input(_array)?|id|var(_array)?|list))$")) + +(function_call_expression + function: (name) @support.function.funchand.php + (#match? @support.function.funchand.php "^(call_user_(func|method)(_array)?|create_function|unregister_tick_function|forward_static_call(_array)?|function_exists|func_(num_args|get_arg(s)?)|register_(shutdown|tick)_function|get_defined_functions)$")) + +(function_call_expression + function: (name) @support.function.gmp.php + (#match? @support.function.gmp.php "^gmp_(scan[01]|strval|sign|sub|setbit|sqrt(rem)?|hamdist|neg|nextprime|com|clrbit|cmp|testbit|intval|init|invert|import|or|div(exact)?|div_(q|qr|r)|jacobi|popcount|pow(m)?|perfect_square|prob_prime|export|fact|legendre|and|add|abs|root(rem)?|random(_(bits|range))?|gcd(ext)?|xor|mod|mul)$")) + +(function_call_expression + function: (name) @support.function.hash.php + (#match? @support.function.hash.php "^(hash(_(hmac(_file)?|copy|init|update(_(file|stream))?|pbkdf2|equals|file|final|algos))?)$")) + +(function_call_expression + function: (name) @support.function.iconv.php + (#match? @support.function.iconv.php "^(iconv(_(str(pos|len|rpos)|substr|(get|set)_encoding|mime_(decode(_headers)?|encode)))?|ob_iconv_handler)$")) + +(function_call_expression + function: (name) @support.function.info.php + (#match? @support.function.info.php "^(sys_get_temp_dir|set_(time_limit|include_path|magic_quotes_runtime)|cli_(get|set)_process_title|ini_(alter|get(_all)?|restore|set)|zend_(thread_id|version|logo_guid)|dl|php(credits|info|version)|php_(sapi_name|ini_(scanned_files|loaded_file)|uname|logo_guid)|putenv|extension_loaded|version_compare|assert(_options)?|restore_include_path|gc_(collect_cycles|disable|enable(d)?)|getopt|get_(cfg_var|current_user|defined_constants|extension_funcs|include_path|included_files|loaded_extensions|magic_quotes_(gpc|runtime)|required_files|resources)|get(env|lastmod|rusage|my(inode|[gup]id))|memory_get_(peak_)?usage|main|magic_quotes_runtime )$")) + +(function_call_expression + function: (name) @support.function.json.php + (#match? @support.function.json.php "^(json_(decode|encode|last_error(_msg)?))$")) + +(function_call_expression + function: (name) @support.function.math.php + (#match? @support.function.math.php "^((a)?(cos|sin|tan)(h)?|sqrt|srand|hypot|hexdec|ceil|is_(nan|(in)?finite)|octdec|dec(hex|oct|bin)|deg2rad|pi|pow|exp(m1)?|floor|fmod|lcg_value|log(1(p|0))?|atan2|abs|round|rand|rad2deg|getrandmax|mt_(srand|rand|getrandmax)|max|min|bindec|base_convert)$")) + +(function_call_expression + function: (name) @support.function.mbstring.php + (#match? @support.function.mbstring.php "^(mb_(str(cut|str|to(lower|upper)|istr|ipos|imwidth|pos|width|len|rchr|richr|ripos|rpos)|substitute_character|substr(_count)?|split|send_mail|http_(input|output)|check_encoding|convert_(case|encoding|kana|variables)|internal_encoding|output_handler|decode_(numericentity|mimeheader)|detect_(encoding|order)|parse_str|preferred_mime_name|encoding_aliases|encode_(numericentity|mimeheader)|ereg(i(_replace)?)?|ereg_(search(_(get(pos|regs)|init|regs|(set)?pos))?|replace(_callback)?|match)|list_encodings|language|regex_(set_options|encoding)|get_info))$")) + +(function_call_expression + function: (name) @support.function.mysql.php + (#match? @support.function.mysql.php "^(mysql_(stat|set_charset|select_db|num_(fields|rows)|connect|client_encoding|close|create_db|escape_string|thread_id|tablename|insert_id|info|data_seek|drop_db|db_(name|query)|unbuffered_query|pconnect|ping|errno|error|query|field_(seek|name|type|table|flags|len)|fetch_(object|field|lengths|assoc|array|row)|free_result|list_(tables|dbs|processes|fields)|affected_rows|result|real_escape_string|get_(client|host|proto|server)_info))$")) + +(function_call_expression + function: (name) @support.function.mysqli.php + (#match? @support.function.mysqli.php "^(mysqli_(ssl_set|store_result|stat|send_(query|long_data)|set_(charset|opt|local_infile_(default|handler))|stmt_(store_result|send_long_data|next_result|close|init|data_seek|prepare|execute|fetch|free_result|attr_(get|set)|result_metadata|reset|get_(result|warnings)|more_results|bind_(param|result))|select_db|slave_query|savepoint|next_result|change_user|character_set_name|connect|commit|client_encoding|close|thread_safe|init|options|(enable|disable)_(reads_from_master|rpl_parse)|dump_debug_info|debug|data_seek|use_result|ping|poll|param_count|prepare|escape_string|execute|embedded_server_(start|end)|kill|query|field_seek|free_result|autocommit|rollback|report|refresh|fetch(_(object|fields|field(_direct)?|assoc|all|array|row))?|rpl_(parse_enabled|probe|query_type)|release_savepoint|reap_async_query|real_(connect|escape_string|query)|more_results|multi_query|get_(charset|connection_stats|client_(stats|info|version)|cache_stats|warnings|links_stats|metadata)|master_query|bind_(param|result)|begin_transaction))$")) + +(function_call_expression + function: (name) @support.function.network.php + (#match? @support.function.network.php "^(syslog|socket_(set_(blocking|timeout)|get_status)|set(raw)?cookie|http_response_code|openlog|headers_(list|sent)|header(_(register_callback|remove))?|checkdnsrr|closelog|inet_(ntop|pton)|ip2long|openlog|dns_(check_record|get_(record|mx))|define_syslog_variables|(p)?fsockopen|long2ip|get(servby(name|port)|host(name|by(name(l)?|addr))|protoby(name|number)|mxrr))$")) + +(function_call_expression + function: (name) @support.function.output.php + (#match? @support.function.output.php "^(output_(add_rewrite_var|reset_rewrite_vars)|flush|ob_(start|clean|implicit_flush|end_(clean|flush)|flush|list_handlers|gzhandler|get_(status|contents|clean|flush|length|level)))$")) + +(function_call_expression + function: (name) @support.function.pgsql.php + (#match? @support.function.pgsql.php "^(pg_(socket|send_(prepare|execute|query(_params)?)|set_(client_encoding|error_verbosity)|select|host|num_(fields|rows)|consume_input|connection_(status|reset|busy)|connect(_poll)?|convert|copy_(from|to)|client_encoding|close|cancel_query|tty|transaction_status|trace|insert|options|delete|dbname|untrace|unescape_bytea|update|pconnect|ping|port|put_line|parameter_status|prepare|version|query(_params)?|escape_(string|identifier|literal|bytea)|end_copy|execute|flush|free_result|last_(notice|error|oid)|field_(size|num|name|type(_oid)?|table|is_null|prtlen)|affected_rows|result_(status|seek|error(_field)?)|fetch_(object|assoc|all(_columns)?|array|row|result)|get_(notify|pid|result)|meta_data|lo_(seek|close|create|tell|truncate|import|open|unlink|export|write|read(_all)?)))$")) + +; TODO: Set up regex injections? +(function_call_expression + function: (name) @support.function.pcre.php + (#match? @support.function.pcre.php "^(preg_(split|quote|filter|last_error|replace(_callback)?|grep|match(_all)?))$")) + +(function_call_expression + function: (name) @support.function.posix.php + (#match? @support.function.posix.php "^(posix_(strerror|set(s|e?u|[ep]?g)id|ctermid|ttyname|times|isatty|initgroups|uname|errno|kill|access|get(sid|cwd|uid|pid|ppid|pwnam|pwuid|pgid|pgrp|euid|egid|login|rlimit|gid|grnam|groups|grgid)|get_last_error|mknod|mkfifo))$")) + +(function_call_expression + function: (name) @support.function.readline.php + (#match? @support.function.readline.php "^(readline(_(completion_function|clear_history|callback_(handler_(install|remove)|read_char)|info|on_new_line|write_history|list_history|add_history|redisplay|read_history))?)$")) + +(function_call_expression + function: (name) @support.function.session.php + (#match? @support.function.session.php "^(session_(status|start|set_(save_handler|cookie_params)|save_path|name|commit|cache_(expire|limiter)|is_registered|id|destroy|decode|unset|unregister|encode|write_close|abort|reset|register(_shutdown)?|regenerate_id|get_cookie_params|module_name))$")) + +(function_call_expression + function: (name) @support.function.socket.php + (#match? @support.function.socket.php "^(socket_(shutdown|strerror|send(to|msg)?|set_((non)?block|option)|select|connect|close|clear_error|bind|create(_(pair|listen))?|cmsg_space|import_stream|write|listen|last_error|accept|recv(from|msg)?|read|get(peer|sock)name|get_option))$")) + +(function_call_expression + function: (name) @support.function.sqlite.php + (#match? @support.function.sqlite.php "^(sqlite_(single_query|seek|has_(more|prev)|num_(fields|rows)|next|changes|column|current|close|create_(aggregate|function)|open|unbuffered_query|udf_(decode|encode)_binary|popen|prev|escape_string|error_string|exec|valid|key|query|field_name|factory|fetch_(string|single|column_types|object|all|array)|lib(encoding|version)|last_(insert_rowid|error)|array_query|rewind|busy_timeout))$")) + +(function_call_expression + function: (name) @support.function.string.php + (#match? @support.function.string.php "^(money_format|md5(_file)?|metaphone|bin2hex|sscanf|sha1(_file)?|str(str|c?spn|n(at)?(case)?cmp|chr|coll|(case)?cmp|to(upper|lower)|tok|tr|istr|pos|pbrk|len|rchr|ri?pos|rev)|str_(getcsv|ireplace|pad|repeat|replace|rot13|shuffle|split|word_count)|strip(c?slashes|os)|strip_tags|similar_text|soundex|substr(_(count|compare|replace))?|setlocale|html(specialchars(_decode)?|entities)|html_entity_decode|hex2bin|hebrev(c)?|number_format|nl2br|nl_langinfo|chop|chunk_split|chr|convert_(cyr_string|uu(decode|encode))|count_chars|crypt|crc32|trim|implode|ord|uc(first|words)|join|parse_str|print(f)?|echo|explode|v?[fs]?printf|quoted_printable_(decode|encode)|quotemeta|wordwrap|lcfirst|[lr]trim|localeconv|levenshtein|addc?slashes|get_html_translation_table)$")) + +(function_call_expression + function: (name) @support.function.url.php + (#match? @support.function.url.php "^(http_build_query|(raw)?url(decode|encode)|parse_url|get_(headers|meta_tags)|base64_(decode|encode))$")) + +(function_call_expression + function: (name) @support.function.var.php + (#match? @support.function.var.php "^(strval|settype|serialize|(bool|double|float)val|debug_zval_dump|intval|import_request_variables|isset|is_(scalar|string|null|numeric|callable|int(eger)?|object|double|float|long|array|resource|real|bool)|unset|unserialize|print_r|empty|var_(dump|export)|gettype|get_(defined_vars|resource_type))$")) + +(function_call_expression + function: (name) @support.function.xml.php + (#match? @support.function.xml.php "^(utf8_(decode|encode)|xml_(set_((notation|(end|start)_namespace|unparsed_entity)_decl_handler|(character_data|default|element|external_entity_ref|processing_instruction)_handler|object)|parse(_into_struct)?|parser_((get|set)_option|create(_ns)?|free)|error_string|get_(current_((column|line)_number|byte_index)|error_code)))$")) + + +; FUNCTIONS +; ========= + +(function_definition + name: (name) @entity.name.function.php) + +(method_declaration + name: (name) @entity.name.function.magic.constructor.php + (#eq? @entity.name.function.magic.constructor.php "__construct") + (#set! capture.final true)) + +(method_declaration + name: (name) @entity.name.function.magic.php + (#match? @entity.name.function.magic.php "^__(?:call|callStatic|get|set|isset|unset|sleep|wakeup|serialize|unserialize|toString|invoke|set_state|clone|debuginfo)$") + (#set! capture.final true)) + +(method_declaration + (static_modifier) + name: (name) @entity.name.function.method.static.php + (#set! capture.final true)) + +(method_declaration + name: (name) @entity.name.function.method.php) + +; Function calls not caught by anything in the support section. +(function_call_expression + function: [(qualified_name (name)) (name)] @support.other.function.php + (#set! capture.shy true)) + + +; NAMESPACES +; ========== + +; The "Foo" in `use Bar as Foo;` +(namespace_aliasing_clause + (name) @entity.name.type.namespace.alias.php) + +; The "Bar" in `use Bar as Foo;` +(namespace_use_clause + (name) @entity.name.type.namespace.aliased.php + . (namespace_aliasing_clause) + (#set! capture.final true) +) + +; The "Foo" and "Bar" in `use Foo\Bar\Baz;`. +(namespace_name_as_prefix + (namespace_name) @support.other.namespace.php) + +; The last segment of a namespace; the "Baz" in `Foo\Bar\Baz;`. +(qualified_name (name) @entity.name.type.namespace.php) + +; The "Foo" in `namespace Foo;` +(namespace_definition + name: (namespace_name + (name) @entity.name.type.namespace.php) + (#set! isNamespaceDefinition true)) + +; The "Foo" in `use Foo;` +(namespace_use_clause (name) @entity.name.type.namespace.php) + + +; The "Foo" in `Foo\Bar::method();` +(namespace_name + (name) @support.other.namespace.php + (#is-not? test.descendantOfType "namespace_use_clause") + (#is-not? test.rangeWithData isNamespaceDefinition)) + + +; CLASSES +; ======= + +(class_declaration (name) @entity.name.type.class.php) + +(class_declaration (base_clause (name) @entity.other.inherited-class.php)) +(class_declaration (class_interface_clause (name) @entity.other.implemented-interface.php)) + +; The "Foo" and "Bar" in `use Bar, Foo;` +(use_declaration (name) @support.other.trait.php) + +; The "Foo" in `Baz::thud insteadof Foo;` +(use_instead_of_clause (name) @support.other.trait.php . + (#set! capture.final true)) + +; In `use` lists, the "bar" in `Foo::bar` is a method, not a constant. +(use_list + (_ + (class_constant_access_expression (name) @support.other.function.method.php .) + ) + (#set! capture.final true)) + +; The "Foo" and "bar" in `Foo::bar`. +(class_constant_access_expression . (name) @support.class.php) +(class_constant_access_expression (name) @support.other.property.php .) + +; The "Foo" and "bar" in "Foo::bar()". +(scoped_call_expression + scope: (name) @support.class.php + name: (name) @support.other.function.method.static.php) + +; The "Foo" and "$bar" in "Foo::$bar()". +(scoped_call_expression + scope: (name) @support.class.php) +(scoped_call_expression + name: (variable_name) @variable.other.method.static.php) + +; The "Foo" and "$bar" in `Foo::$bar`. +(scoped_property_access_expression + scope: (name) @support.class.php) +(scoped_property_access_expression + name: (variable_name) @variable.other.property.static.php + (#set! capture.final true)) + +; The "bar" in `$foo->bar()`. +(member_call_expression + name: (name) @support.other.function.method.php) + +; The "bar" in `$foo->bar`. +(member_access_expression + name: (name) @support.other.property.php + (#set! capture.final true)) + +; The "$bar" in `$foo->$bar()`. +(member_call_expression + name: (variable_name) @variable.other.method.php + (#set! capture.final true)) + +; The "$bar" in `$foo->$bar`. +(member_access_expression + name: (variable_name) @variable.other.property.php + (#set! capture.final true)) + + +; TRAITS +; ====== + +(trait_declaration (name) @entity.name.type.trait.php) + + +; INTERFACES +; ========== + +(interface_declaration (name) @entity.name.type.interface.php) + + +; TYPES +; ===== + +(primitive_type) @storage.type.builtin.php +(cast_type) @storage.type.builtin.php +(named_type (name) @storage.type.php) +(named_type (qualified_name) @storage.type.php) + +"global" @storage.modifier.global.php + +["enum" "interface" "trait" "class"] @storage.type._TYPE_.php +(enum_case "case" @storage.type.case.php) +"function" @storage.type.function.php +"fn" @storage.type.function.arrow.php + + +; ENUMS +; ===== + +(enum_declaration + name: (name) @entity.name.type.enum.php) + +(enum_declaration_list + (enum_case + name: (name) @constant.other.enum.php)) + +; VARIABLES +; ========= + +; All usages of "$this". +((variable_name) @variable.language.builtin.this.php + (#eq? @variable.language.builtin.this.php "$this") + (#set! capture.final true)) + +; The `self` builtin (for referring to the current class) and the `parent` +; builtin (for referring to the parent class). +(relative_scope) @variable.language.builtin._TEXT_.php + +(object_creation_expression + (name ["self" "parent" "static"] @variable.language.builtin._TEXT_.php) + (#set! capture.final true)) + +; The "$foo" in `function bar($foo) {`. +(formal_parameters + (simple_parameter + (variable_name + "$" @punctuation.definition.variable.php + ) @variable.parameter.php)) + +((variable_name + ("$" @punctuation.definition.variable.php) + (name) @_IGNORE_) @variable.other.php + (#set! capture.final true)) + +; The `${foo}` in `"${foo}"`. +(dynamic_variable_name) @meta.embedded.line.interpolation.php @variable.other.interpolated.php + +((dynamic_variable_name) @punctuation.definition.variable.begin.php + (#set! adjust.endAfterFirstMatchOf "^\\$\\{")) + +((dynamic_variable_name) @punctuation.definition.variable.begin.php + (#set! adjust.startBeforeFirstMatchOf "^\\}$")) + +((name) @constant.other.php + (#match? @constant.other.php "^_?[A-Z][A-Z\\d_]+$")) + +((name) @constant.language.php + (#match? @constant.language.php "^__[A-Z][A-Z\d_]+__$")) + +(argument + name: (_) @variable.other.named-argument.php + ":" @punctuation.separator.key-value.php) + + +; STRINGS + +(string + "'" @punctuation.definition.string.begin.php + (string_value)? + "'" @punctuation.definition.string.end.php) @string.quoted.single.php + +(encapsed_string + "\"" @punctuation.definition.string.begin.php + (string_value)? + "\"" @punctuation.definition.string.end.php) @string.quoted.double.php + +(encapsed_string + (escape_sequence) @constant.character.escape.php) + +[(heredoc) (nowdoc)] @string.unquoted.heredoc.php + + +[ + "as" + "break" + "catch" + "const" + "continue" + "declare" + "default" + "do" + "echo" + "else" + "elseif" + "enddeclare" + "endforeach" + "endif" + "endswitch" + "endwhile" + "finally" + "foreach" + "if" + "include_once" + "include" + "insteadof" + "new" + "require_once" + "require" + "return" + "switch" + "throw" + "try" + "use" + "while" +] @keyword.control._TYPE_.php + +(case_statement "case" @keyword.control.case.php) + +[ + "abstract" + "extends" + "final" + "implements" + "namespace" + "private" + "protected" + "public" + "readonly" + "static" +] @storage.modifier._TYPE_.php + +(expression_statement (name) @keyword.control.exit.php + (#eq? @keyword.control.exit.php "exit")) + +; CONSTANTS +; ========= + +(boolean) @constant.language.boolean._TEXT_.php +(null) @constant.language.null.php + +(integer) @constant.numeric.decimal.integer.php +(float) @constant.numeric.decimal.float.php + +; COMMENTS +; ======== + +((comment) @comment.line.double-slash.php + (#match? @comment.line.double-slash.php "^//")) + +((comment) @punctuation.definition.comment.php + (#match? @comment.line.double-slash.php "^//") + (#set! adjust.startAndEndAroundFirstMatchOf "^//")) + +((comment) @comment.line.number-sign.php + (#match? @comment.line.number-sign.php "^#")) + +((comment) @punctuation.definition.comment.php + (#match? @punctuation.definition.comment.php "^#") + (#set! adjust.startAndEndAroundFirstMatchOf "^#")) + +; Don't highlight PHPDoc comments because the injection will handle them. +((comment) @_IGNORE_ + (#match? @_IGNORE_ "^/\\*\\*") + (#set! capture.final true)) + +((comment) @comment.block.php + (#match? @comment.block.php "^/\\*(?!\\*)")) + +((comment) @punctuation.definition.comment.begin.php + (#match? @punctuation.definition.comment.begin.php "^/\\*(?!\\*)") + (#set! adjust.startAndEndAroundFirstMatchOf "^/\\*")) + +((comment) @punctuation.definition.comment.end.php + (#match? @punctuation.definition.comment.end.php "^/\\*(?!\\*)") + (#set! adjust.startAndEndAroundFirstMatchOf "\\*/$")) + + +; OPERATORS +; ========= + +(binary_expression "." @keyword.operator.string.php) + +(optional_type "?" @keyword.operator.nullable-type.php) +(union_type "|" @keyword.operator.union-type.php) + +[ + "&&" + "||" + "??" +] @keyword.operator.logical.php + +["="] @keyword.operator.assignment.php + +(conditional_expression + ["?" ":"] @keyword.operator.ternary.php) + +(unary_op_expression "@" @keyword.operator.error-control.php) + +[ + "==" + "===" + "!=" + "!==" + ">" + "<" + "<=" + ">=" + "<>" + "<=>" +] @keyword.operator.comparison.php + +[ + "+" + "-" + "*" + "/" + "**" + "%" +] @keyword.operator.arithmetic.php + +[ + "&" + "|" + "^" + "~" + "<<" + ">>" +] @keyword.operator.bitwise.php + +[ + "+=" + "-=" + "*=" + "/=" + "%=" + "**=" + "&=" + "|=" + "^=" + "<<=" + ">>=" + ".=" + "??=" +] @keyword.operator.assignment.compound.php + +"->" @keyword.operator.class.php +"=>" @punctuation.separator.key-value.php + +"\\" @keyword.operator.namespace.php +"::" @keyword.operator.accessor.php + +";" @punctuation.terminator.statement.php; + +(unary_op_expression "!" @keyword.operator.unary.php) + +; PUNCTUATION +; =========== + +(formal_parameters + "(" @punctuation.definition.parameters.begin.bracket.round.php + ")"@punctuation.definition.parameters.end.bracket.round.php + (#set! capture.final true)) + +"{" @punctuation.definition.block.begin.bracket.curly.php +"}" @punctuation.definition.block.end.bracket.curly.php +"(" @punctuation.definition.begin.bracket.round.php +")" @punctuation.definition.end.bracket.round.php +"[" @punctuation.definition.begin.bracket.square.php +"]" @punctuation.definition.end.bracket.square.php + +(php_tag) @punctuation.section.embedded.begin.php +"?>" @punctuation.section.embedded.end.php diff --git a/packages/language-php/grammars/tree-sitter/queries/indents.scm b/packages/language-php/grammars/tree-sitter/queries/indents.scm new file mode 100644 index 0000000000..c7f198a402 --- /dev/null +++ b/packages/language-php/grammars/tree-sitter/queries/indents.scm @@ -0,0 +1,8 @@ +; + +["{" "(" "["] @indent +["}" ")" "]"] @dedent + +":" @indent + +["endif" "endfor" "endforeach" "enddeclare" "endswitch"] @dedent diff --git a/packages/language-php/grammars/tree-sitter/queries/phpdoc/highlights.scm b/packages/language-php/grammars/tree-sitter/queries/phpdoc/highlights.scm new file mode 100644 index 0000000000..e9ee2c4d6f --- /dev/null +++ b/packages/language-php/grammars/tree-sitter/queries/phpdoc/highlights.scm @@ -0,0 +1,14 @@ + +((document) @punctuation.definition.begin.comment.phpdoc.php + (#set! adjust.startAndEndAroundFirstMatchOf "^/\\*\\*")) + +((document) @punctuation.definition.end.comment.phpdoc.php + (#set! adjust.startAndEndAroundFirstMatchOf "(?:\\*)?\\*/$")) + +(tag_name) @entity.name.tag.phpdoc.php +(named_type) @storage.type.instance.phpdoc.php +(variable_name) @variable.other.phpdoc.php +(uri) @markup.underline.link.phpdoc.php + +(inline_tag "{" @punctation.definition.tag.begin.brace.curly.phpdoc.php) +(inline_tag "}" @punctation.definition.tag.end.brace.curly.phpdoc.php) diff --git a/packages/language-php/grammars/tree-sitter/queries/tags.scm b/packages/language-php/grammars/tree-sitter/queries/tags.scm new file mode 100644 index 0000000000..3d03f5bc59 --- /dev/null +++ b/packages/language-php/grammars/tree-sitter/queries/tags.scm @@ -0,0 +1,43 @@ + +(namespace_definition + name: (namespace_name) @name) @module + +(interface_declaration + name: (name) @name) @definition.interface + +(trait_declaration + name: (name) @name) @definition.interface + +(class_declaration + name: (name) @name) @definition.class + +(class_interface_clause [(name) (qualified_name)] @name) @impl + +(property_declaration + (property_element (variable_name (name) @name))) @definition.field + +(function_definition + name: (name) @name) @definition.function + +(method_declaration + name: (name) @name) @definition.function + +(object_creation_expression + [ + (qualified_name (name) @name) + (variable_name (name) @name) + ]) @reference.class + +(function_call_expression + function: [ + (qualified_name (name) @name) + (variable_name (name)) @name + ]) @reference.call + +(scoped_call_expression + name: (name) @name) @reference.call + +(member_call_expression + name: (name) @name) @reference.call + +(enum_declaration (name) @name) @definition.enum diff --git a/packages/language-php/grammars/tree-sitter/tree-sitter-php.wasm b/packages/language-php/grammars/tree-sitter/tree-sitter-php.wasm new file mode 100755 index 0000000000..759c60b33f Binary files /dev/null and b/packages/language-php/grammars/tree-sitter/tree-sitter-php.wasm differ diff --git a/packages/language-php/grammars/tree-sitter/tree-sitter-phpdoc.wasm b/packages/language-php/grammars/tree-sitter/tree-sitter-phpdoc.wasm new file mode 100755 index 0000000000..0799df476b Binary files /dev/null and b/packages/language-php/grammars/tree-sitter/tree-sitter-phpdoc.wasm differ diff --git a/packages/language-php/lib/main.js b/packages/language-php/lib/main.js new file mode 100644 index 0000000000..bc8b18c345 --- /dev/null +++ b/packages/language-php/lib/main.js @@ -0,0 +1,155 @@ +exports.activate = function () { + + // Here's how we handle the mixing of PHP and HTML: + // + // * The root language layer uses the `tree-sitter-php` parser, and handles + // all tasks: highlighting, indentation, folds. + // * HTML gets injected into all `text` nodes. + // * A corresponding PHP injection point is created for non-text nodes and + // represents all non-HTML regions of the buffer. + // + // We do it this way so that we can limit the scope `source.php` to only + // those ranges identified by the injection. The way the `tree-sitter-php` + // tree is organized rules out all other options for adding scope boundaries + // to embedded PHP ranges. And injections enjoy an ability that query + // captures do not: they are allowed to apply their base scope to arbitrary + // ranges of the tree. If we can describe the ranges in the `content` + // callback, we can scope each range the way we want. + // + // This may seem like an odd thing to do, but it's critical for us to know + // when we're in `source.php` and when we aren't. For instance, nearly all of + // the snippets in `language-php` are valid only in one mode or the other. + // + // This means that, technically speaking, the PHP injection layer doesn't + // have any tasks, and doesn't even need to do any parsing. If injections had + // the option of re-using another layer's tree, we'd want to do that, but + // right now there's not a need for such a feature. + + atom.grammars.addInjectionPoint('text.html.php', { + type: 'program', + language: () => 'html', + content(node) { + return node.descendantsOfType('text'); + }, + + // We don't need a base scope for this injection because the whole file is + // already scoped as `text.html.php`. The PHP embeds add a `source.php` + // scope, but still has `text.html.php` as the root. This is how the TM + // grammar works, so we're replicating it here. + languageScope: null + }); + + atom.grammars.addInjectionPoint('text.html.php', { + type: 'program', + language() { + return 'internal-php'; + }, + content(node) { + let results = []; + // At the top level we should ignore `text` nodes, since they're just + // HTML. We should also ignore the middle children of + // `text_interpolation` nodes (also `text`), but we need to include their + // first and last children, which correspond to `?>` and ` { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + for (let type of ['comment', 'string_value']) { + atom.grammars.addInjectionPoint('text.html.php', { + type, + language(node) { + // PHPDoc can parse URLs better than we can. + if (isPhpDoc(node)) return undefined; + return HYPERLINK_PATTERN.test(node.text) ? + 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } + + // HEREDOCS and NOWDOCS + // ==================== + + atom.grammars.addInjectionPoint('text.html.php', { + type: 'heredoc', + language(node) { + let id = node.firstNamedChild; + if (id.type !== 'heredoc_start') return null; + return id.text; + }, + content(node) { + let body = node.children.find(c => c.type === 'heredoc_body'); + let results = body.children.filter(c => c.type === 'string_value'); + return results; + } + }); + + atom.grammars.addInjectionPoint('text.html.php', { + type: 'nowdoc', + language(node) { + let id = node.firstNamedChild; + if (id.type !== 'heredoc_start') return null; + return id.text; + }, + content(node) { + let body = node.children.find(c => c.type === 'nowdoc_body'); + let results = body.children.filter(c => c.type === 'nowdoc_string'); + return results; + } + }); + + + // PHPDoc + // ====== + + atom.grammars.addInjectionPoint('text.html.php', { + type: 'comment', + language(node) { + if (isPhpDoc(node)) { + return 'phpdoc'; + } + }, + content(node) { return node; } + }); + +}; diff --git a/packages/language-php/package.json b/packages/language-php/package.json index 8d6dc17fea..2b3e7aa3c7 100644 --- a/packages/language-php/package.json +++ b/packages/language-php/package.json @@ -1,10 +1,11 @@ { "name": "language-php", "version": "0.48.1", + "main": "lib/main", "description": "PHP language support in Atom", "engines": { "atom": "*", - "node": "*" + "node": ">=12" }, "repository": "https://github.com/pulsar-edit/pulsar", "license": "MIT" diff --git a/packages/language-php/spec/html-spec.js b/packages/language-php/spec/html-spec.js index fe2cdac9a0..90a53792ad 100644 --- a/packages/language-php/spec/html-spec.js +++ b/packages/language-php/spec/html-spec.js @@ -3,6 +3,7 @@ describe('PHP in HTML', () => { let grammar = null; beforeEach(() => { + atom.config.set('core.useTreeSitterParsers', false); waitsForPromise(() => atom.packages.activatePackage('language-php')); waitsForPromise(() => // While not used explicitly in any tests, we still activate language-html diff --git a/packages/language-php/spec/php-spec.js b/packages/language-php/spec/php-spec.js index 92c6caa7d4..c7f4ee2955 100644 --- a/packages/language-php/spec/php-spec.js +++ b/packages/language-php/spec/php-spec.js @@ -3,7 +3,10 @@ describe('PHP grammar', function() { let grammar = null; beforeEach(function() { - waitsForPromise(() => atom.packages.activatePackage('language-php')); + atom.config.set('core.useTreeSitterParsers', false); + + waitsForPromise(() => + atom.packages.activatePackage('language-php')); runs(function() { grammar = atom.grammars.grammarForScopeName('source.php'); diff --git a/packages/language-ruby/grammars/ts/highlights.scm b/packages/language-ruby/grammars/ts/highlights.scm index 4359b111a2..0d9b19784b 100644 --- a/packages/language-ruby/grammars/ts/highlights.scm +++ b/packages/language-ruby/grammars/ts/highlights.scm @@ -129,6 +129,10 @@ "." @keyword.operator.accessor.ruby ) @meta.function.method.with-arguments +(singleton_method + name: (identifier) @entity.name.function.ruby + (#set! capture.final "true")) + (call method: (identifier) @keyword.other.special-method (#match? @keyword.other.special-method "^(raise|loop)$")) @@ -202,6 +206,8 @@ (#set! adjust.endAt firstChild.nextSibling.endPosition) (#set! capture.final true)) +(keyword_parameter name: (identifier) @variable.parameter.keyword.ruby) + ; This scope should span both the key and the adjacent colon. ((pair key: (hash_key_symbol)) @constant.other.symbol.hashkey.ruby (#set! adjust.startAt firstChild.startPosition) @@ -487,6 +493,9 @@ "&" ] @keyword.operator.other.ruby +".." @keyword.operator.range.inclusive.ruby +"..." @keyword.operator.range.exclusive.ruby + [ "==" "===" diff --git a/packages/language-ruby/grammars/ts/tags.scm b/packages/language-ruby/grammars/ts/tags.scm index 5a6bda78df..2d270a724d 100644 --- a/packages/language-ruby/grammars/ts/tags.scm +++ b/packages/language-ruby/grammars/ts/tags.scm @@ -21,7 +21,10 @@ ; Method names (method name: (_) @name) @definition.method -(singleton_method name: (_) @name) @definition.method +( + (singleton_method name: (_) @name) @definition.method + (#set! symbol.prepend "self.")) + ; Aliased methods (alias name: (_) @name) @definition.method diff --git a/packages/language-rust-bundled/lib/main.js b/packages/language-rust-bundled/lib/main.js index f33955eb02..e4dc9d2442 100644 --- a/packages/language-rust-bundled/lib/main.js +++ b/packages/language-rust-bundled/lib/main.js @@ -1,4 +1,4 @@ -exports.activate = function() { +exports.activate = function () { for (const nodeType of ['macro_invocation', 'macro_rule']) { atom.grammars.addInjectionPoint('source.rust', { type: nodeType, @@ -13,4 +13,29 @@ exports.activate = function() { coverShallowerScopes: true }); } + + 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 (let type of ['line_comment', 'block_comment']) { + atom.grammars.addInjectionPoint('source.rust', { + type, + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } + + for (let type of ['string_literal', 'raw_string_literal', 'line_comment', 'block_comment']) { + atom.grammars.addInjectionPoint('source.rust', { + type, + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + } }; diff --git a/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson b/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson index a814a7b1e5..965f0c5fe3 100644 --- a/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson +++ b/packages/language-shellscript/grammars/modern-tree-sitter-bash.cson @@ -6,6 +6,26 @@ parser: 'tree-sitter-bash' fileTypes: [ 'sh' 'bash' + 'ksh' + 'zsh' + 'zsh-theme' + 'zshenv' + 'zlogin' + 'zlogout' + 'zprofile' + 'zshrc' + 'bashrc' + 'bash_aliases' + 'bash_profile' + 'bash_login' + 'profile' + 'bash_logout' + 'npmrc' + 'PKGBUILD' + 'install' + 'cygport' + 'bats' + 'ebuild' ] firstLineRegex: [ diff --git a/packages/language-shellscript/grammars/tree-sitter-bash.cson b/packages/language-shellscript/grammars/tree-sitter-bash.cson index 4f74335b58..723f2c94a5 100644 --- a/packages/language-shellscript/grammars/tree-sitter-bash.cson +++ b/packages/language-shellscript/grammars/tree-sitter-bash.cson @@ -6,6 +6,26 @@ parser: 'tree-sitter-bash' fileTypes: [ 'sh' 'bash' + 'ksh' + 'zsh' + 'zsh-theme' + 'zshenv' + 'zlogin' + 'zlogout' + 'zprofile' + 'zshrc' + 'bashrc' + 'bash_aliases' + 'bash_profile' + 'bash_login' + 'profile' + 'bash_logout' + 'npmrc' + 'PKGBUILD' + 'install' + 'cygport' + 'bats' + 'ebuild' ] injectionRegex: '^(bash|sh|BASH|SH)$' diff --git a/packages/language-shellscript/grammars/tree-sitter/highlights.scm b/packages/language-shellscript/grammars/tree-sitter/highlights.scm index b969e01bda..eaf6fcee2f 100644 --- a/packages/language-shellscript/grammars/tree-sitter/highlights.scm +++ b/packages/language-shellscript/grammars/tree-sitter/highlights.scm @@ -11,11 +11,14 @@ (#eq? @keyword.control.return.shell "return") (#set! capture.final true)) -((command_name) @support.function.builtin.shell - (#match? @support.function.builtin.shell "^(?:alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|dirs|disown|echo|enable|eval|exec|exit|false|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|popd|printf|pushd|pwd|read|readonly|set|shift|shopt|source|suspend|test|times|trap|true|type|ulimit|umask|unalias|unset|wait)$") +((command_name) @support.function.builtin._TEXT_.shell + (#match? @support.function.builtin._TEXT_.shell "^(?:alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|dirs|disown|echo|enable|eval|exec|exit|false|fc|fg|getopts|hash|help|history|jobs|kill|let|logout|popd|printf|pushd|pwd|read|readonly|set|shift|shopt|source|suspend|test|times|trap|true|type|ulimit|umask|unalias|unset|wait)$") (#set! capture.final true)) -(command_name) @support.other.function.shell +(unset_command "unset" @support.function.builtin.unset.shell) + +((command_name) @support.other.function.shell + (#is-not? test.descendantOfType "command_substitution")) [ @@ -44,7 +47,7 @@ "$" @punctuation.definition.variable.shell (variable_name)) (expansion "${" @punctuation.definition.variable.begin.shell - (variable_name) + ; (variable_name) "}" @punctuation.definition.variable.end.shell) @variable.other.bracket.shell @@ -84,7 +87,10 @@ (#set! adjust.startAndEndAroundFirstMatchOf ".$")) (string - (command_substitution) @meta.embedded.line.subshell.shell) + (command_substitution) @meta.embedded.line.subshell.shell + (#set! capture.final true)) + +(command_substitution) @string.interpolation.backtick.shell (heredoc_start) @punctuation.definition.string.begin.heredoc.shell (heredoc_body) @string.unquoted.heredoc.shell @@ -103,6 +109,10 @@ (list ["&&" "||"] @keyword.operator.logical.shell) (binary_expression ["&&" "||"] @keyword.operator.logical.shell) +(pipeline "|" @keyword.operator.pipe.shell) +(expansion operator: "#" @keyword.operator.expansion.shell) + + ; "*" @keyword.operator.glob.shell [ @@ -142,6 +152,8 @@ destination: (word) @constant.numeric.file-descriptor.shell (#match? @constant.numeric.file-descriptor.shell "^[12]$")) +(number) @constant.numeric.decimal.shell + (test_command "[[" @punctuation.brace.double-square.begin.shell) (test_command diff --git a/packages/language-typescript/grammars/common/folds.scm b/packages/language-typescript/grammars/common/folds.scm index 97c5a6f0f6..54cdd8eb8a 100644 --- a/packages/language-typescript/grammars/common/folds.scm +++ b/packages/language-typescript/grammars/common/folds.scm @@ -4,6 +4,7 @@ (object) (template_string) (named_imports) + (object_type) ] @fold ; When we've got diff --git a/packages/language-typescript/grammars/common/highlights.scm b/packages/language-typescript/grammars/common/highlights.scm index 218cd8651e..8757d6b72f 100644 --- a/packages/language-typescript/grammars/common/highlights.scm +++ b/packages/language-typescript/grammars/common/highlights.scm @@ -37,6 +37,11 @@ (this) @variable.language.this._LANG_ (super) @variable.language.super._LANG_._LANG_x +(required_parameter + pattern: (identifier) @variable.parameter.with-default._LANG_ + value: (_) + (#set! capture.final true)) + (required_parameter pattern: (identifier) @variable.parameter._LANG_) @@ -49,6 +54,12 @@ (shorthand_property_identifier_pattern) @variable.parameter.destructuring._LANG_) (#set! capture.final true)) +(required_parameter + pattern: (object_pattern + (object_assignment_pattern + (shorthand_property_identifier_pattern) @variable.parameter.destructuring.with-default._LANG_)) + (#set! capture.final true)) + (optional_parameter pattern: (identifier) @variable.parameter.optional._LANG_) @@ -58,6 +69,11 @@ name: (identifier) @variable.other.type._LANG_ "is" @keyword.operator.type.is._LANG_) +; Assertion functions: the `asserts` in +; `function checkFoo(obj: unknown): asserts obj is foo` +(asserts "asserts" @keyword.type.asserts._LANG_) +(asserts (identifier) @variable.other.type._LANG_) + ["var" "const" "let"] @storage.type._TYPE_._LANG_ ; A simple variable declaration: @@ -120,6 +136,13 @@ (array_pattern (identifier) @variable.other.assignment.destructuring._LANG_)) +; A variable array destructuring with a default: +; The "baz" in `let [foo, bar, baz = false] = something` +(variable_declarator + (array_pattern + (assignment_pattern + (identifier) @variable.other.assignment.destructuring.js))) + ; A variable declaration in a for…(in|of) loop: ; The "foo" in `for (let foo of bar) {` (for_in_statement @@ -154,6 +177,12 @@ ; The "foo" in `(foo => …)` (arrow_function parameter: (identifier) @variable.parameter._LANG_) +; `infer` keywords inside `extends` clauses function as a sort of type +; parameter, so we'll try highlighting them that way. +; +; TODO: We may or may not want `capture.final` here. +(infer_type (type_identifier) @variable.parameter.type._LANG_ + (#set! capture.final true)) ; COMMENTS ; ======== @@ -255,7 +284,7 @@ ; ===== ["var" "let" "const"] @storage.modifier._TYPE_._LANG_ -["extends" "static" "async"] @storage.modifier._TYPE_._LANG_ +["extends" "static" "async" "infer"] @storage.modifier._TYPE_._LANG_ ["class" "function"] @storage.type._TYPE_._LANG_ @@ -318,6 +347,12 @@ (object (shorthand_property_identifier) @entity.other.attribute-name.shorthand._LANG_) +; The "FOO" in `FOO.bar` should be scoped as a constant. +(member_expression + object: (identifier) @constant.other.object._LANG_ + (#match? @constant.other.object._LANG_ "^[_A-Z]+$") + (#set! capture.final true)) + ; The "foo" in `foo.bar`. (member_expression object: (identifier) @support.other.object._LANG_) @@ -406,6 +441,8 @@ (generator_function_declaration "*" @storage.modifier.generator._LANG_) (method_definition "*" @storage.modifier.generator._LANG_) +(asserts "asserts" @keyword.control.type.asserts._LANG_) + ; SUPPORT ; ======= @@ -748,6 +785,9 @@ (ternary_expression ["?" ":"] @keyword.operator.ternary._LANG_) +(conditional_type + ["?" ":"] @keyword.operator.ternary._LANG_) + ; PUNCTUATION ; =========== diff --git a/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm b/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm index bd25180c16..3a12735e84 100644 --- a/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm +++ b/packages/language-typescript/grammars/tree-sitter-tsx/indents.scm @@ -2,7 +2,39 @@ ; JSX ; === -(jsx_opening_element ["<" ">"] @indent) -(jsx_opening_element [">"] @dedent) +(jsx_opening_element [">"] @indent) -(jsx_closing_element ">" @dedent) +; Support things like… +;
+(jsx_opening_element ["<"] @indent + (#is-not? test.startsOnSameRowAs parent.lastChild.startPosition)) +((jsx_opening_element [">"] @dedent) + (#is-not? test.startsOnSameRowAs parent.firstChild.startPosition)) + +; We match on the whole node here because +; (a) we need to please the dedent-while-typing heuristic, so the line text +; must match the capture node's text; and +; (b) we don't want the dedent to trigger until the very last `>` has been +; typed. +(jsx_closing_element ">") @dedent + +; Support things like… +; {'foo'} +(jsx_self_closing_element "<" @indent + (#is-not? test.startsOnSameRowAs parent.lastChild.startPosition)) + +; There isn't a single node whose exact text will match the line content at any +; point, so the usual heuristic won't work. Instead we set `indent.force` and +; use `test.lastTextOnRow` to ensure that the dedent fires exactly once while +; typing. +((jsx_self_closing_element ">" @dedent) + (#is-not? test.startsOnSameRowAs parent.firstChild.startPosition) + (#is? test.lastTextOnRow) + (#set! indent.force true)) diff --git a/packages/language-yaml/lib/main.js b/packages/language-yaml/lib/main.js new file mode 100644 index 0000000000..deab0a7082 --- /dev/null +++ b/packages/language-yaml/lib/main.js @@ -0,0 +1,23 @@ +exports.activate = () => { + const HYPERLINK_PATTERN = /\bhttps?:/ + const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/; + + atom.grammars.addInjectionPoint('source.yaml', { + type: 'comment', + language: (node) => { + return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined; + }, + content: (node) => node, + languageScope: null + }); + + atom.grammars.addInjectionPoint('source.yaml', { + type: 'comment', + language: (node) => { + return TODO_PATTERN.test(node.text) ? 'todo' : undefined; + }, + content: (node) => node, + languageScope: null + }); + +}; diff --git a/packages/language-yaml/package.json b/packages/language-yaml/package.json index 7f0be6af55..47957ef422 100644 --- a/packages/language-yaml/package.json +++ b/packages/language-yaml/package.json @@ -1,6 +1,7 @@ { "name": "language-yaml", "version": "0.32.0", + "main": "lib/main", "description": "YAML language support in Atom", "engines": { "atom": "*", diff --git a/packages/symbol-provider-ctags/lib/ctags-provider.js b/packages/symbol-provider-ctags/lib/ctags-provider.js index ea8ad638f0..6d587ce779 100644 --- a/packages/symbol-provider-ctags/lib/ctags-provider.js +++ b/packages/symbol-provider-ctags/lib/ctags-provider.js @@ -62,11 +62,11 @@ class CtagsProvider { const {resourcePath} = atom.getLoadSettings(); const currentFileWasRequiredFromSnapshot = !fs.isAbsolute(__dirname); const packageRoot = currentFileWasRequiredFromSnapshot - ? path.join(resourcePath, 'node_modules', 'symbols-view') + ? path.join(resourcePath, 'node_modules', 'symbol-provider-ctags') : path.resolve(__dirname, '..'); if (path.extname(resourcePath) === '.asar' && packageRoot.indexOf(resourcePath) === 0) { - return path.join(`${resourcePath}.unpacked`, 'node_modules', 'symbols-view'); + return path.join(`${resourcePath}.unpacked`, 'node_modules', 'symbol-provider-ctags'); } else { return packageRoot; } diff --git a/packages/symbol-provider-ctags/spec/symbol-provider-ctags-spec.js b/packages/symbol-provider-ctags/spec/symbol-provider-ctags-spec.js index ec4fea27ad..c63d1b8bc8 100644 --- a/packages/symbol-provider-ctags/spec/symbol-provider-ctags-spec.js +++ b/packages/symbol-provider-ctags/spec/symbol-provider-ctags-spec.js @@ -52,6 +52,14 @@ describe('CTagsProvider', () => { ); }); + it('identifies its project root correctly', () => { + let root = provider.getPackageRoot(); + expect(root).toContain("symbol-provider-ctags"); + expect( + fs.existsSync(path.join(root, "vendor", "ctags-darwin")) + ).toBe(true); + }); + describe('when tags can be generated for a file', () => { beforeEach(async () => { await atom.workspace.open(directory.resolve('sample.js')); diff --git a/packages/symbols-view/lib/config.js b/packages/symbols-view/lib/config.js index 0a969b86ff..2de1801498 100644 --- a/packages/symbols-view/lib/config.js +++ b/packages/symbols-view/lib/config.js @@ -19,6 +19,11 @@ const Config = { this.subscriptions?.dispose(); }, + getForEditor(editor, key) { + let grammar = editor.getGrammar(); + return atom.config.get(`symbols-view.${key}`, { scope: [grammar?.scopeName] }); + }, + get(key) { return atom.config.get(`symbols-view.${key}`); }, diff --git a/packages/symbols-view/lib/provider-broker.js b/packages/symbols-view/lib/provider-broker.js index c6b9efc675..f702336272 100644 --- a/packages/symbols-view/lib/provider-broker.js +++ b/packages/symbols-view/lib/provider-broker.js @@ -180,7 +180,7 @@ module.exports = class ProviderBroker { let exclusivesByScore = []; let results = []; - let preferredProviders = atom.config.get('symbols-view.preferCertainProviders'); + let preferredProviders = Config.getForEditor(meta.editor, 'preferCertainProviders'); if (shouldLog) { console.debug(`Provider broker choosing among ${this.providers.length} candidates:`, this.providers); diff --git a/packages/symbols-view/spec/symbols-view-spec.js b/packages/symbols-view/spec/symbols-view-spec.js index 8f97191674..04eccd9239 100644 --- a/packages/symbols-view/spec/symbols-view-spec.js +++ b/packages/symbols-view/spec/symbols-view-spec.js @@ -100,6 +100,8 @@ describe('SymbolsView', () => { activationPromise.then(() => { mainModule = atom.packages.getActivePackage('symbols-view').mainModule; }); + await activationPromise; + await atom.packages.activatePackage('language-javascript'); jasmine.attachToDOM(getWorkspaceView()); }); @@ -111,6 +113,9 @@ describe('SymbolsView', () => { beforeEach(async () => { atom.config.set('symbols-view.providerTimeout', 500); await atom.workspace.open(directory.resolve('sample.js')); + let editor = atom.workspace.getActiveTextEditor(); + let languageMode = editor.getBuffer().getLanguageMode(); + if (languageMode.ready) await languageMode.ready; }); it('displays all symbols with line numbers', async () => { @@ -303,7 +308,39 @@ describe('SymbolsView', () => { beforeEach(() => { // Last time we referred to this one by its package name; now we use // its human-friendly name. They should be interchangeable. - atom.config.set('symbols-view.preferCertainProviders', ['Competing Exclusive', 'symbol-provider-dummy']); + atom.config.set( + 'symbols-view.preferCertainProviders', + ['Competing Exclusive', 'symbol-provider-dummy'] + ); + }); + + it('prefers the one with the highest score (providers listed earlier beating those listed later)', async () => { + registerProvider(DummyProvider, CompetingExclusiveProvider); + spyOn(CompetingExclusiveProvider, 'getSymbols').andCallThrough(); + spyOn(DummyProvider, 'getSymbols').andCallThrough(); + await activationPromise; + await dispatchAndWaitForChoices('symbols-view:toggle-file-symbols'); + symbolsView = getSymbolsView(); + expect(choiceCount(symbolsView)).toBe(5); + expect(DummyProvider.getSymbols).not.toHaveBeenCalled(); + expect(CompetingExclusiveProvider.getSymbols).toHaveBeenCalled(); + }); + }); + + describe('and one has a scope-specific `preferCertainProviders` setting', () => { + beforeEach(() => { + // Last time we referred to this one by its package name; now we use + // its human-friendly name. They should be interchangeable. + atom.config.set( + 'symbols-view.preferCertainProviders', + ['Competing Exclusive', 'symbol-provider-dummy'], + { scopeSelector: '.source.js' } + ); + + atom.config.set( + 'symbols-view.preferCertainProviders', + ['symbol-provider-dummy'] + ); }); it('prefers the one with the highest score (providers listed earlier beating those listed later)', async () => { diff --git a/script/validate-wasm-grammar-prs.js b/script/validate-wasm-grammar-prs.js index 5035475302..706ce1f787 100644 --- a/script/validate-wasm-grammar-prs.js +++ b/script/validate-wasm-grammar-prs.js @@ -64,6 +64,9 @@ if (wasmFilesChanged.length === 0) { for (const wasmFile of wasmFilesChanged) { const wasmPath = path.dirname(wasmFile); + // Don't check the base `tree-sitter.wasm` file. + if (wasmFile.includes('vendor/web-tree-sitter')) continue; + const files = fs.readdirSync(path.join(wasmPath, "..")); console.log(`Detected changes to: ${wasmFile}`); @@ -76,6 +79,9 @@ for (const wasmFile of wasmFilesChanged) { } for (const file of files) { + // Only check `cson` files. + if (!file.endsWith('.cson')) continue; + const filePath = path.join(wasmPath, "..", file); console.log(`Checking: ${filePath}`); diff --git a/spec/scope-resolver-spec.js b/spec/scope-resolver-spec.js index ec6fc7f7aa..449ba82f65 100644 --- a/spec/scope-resolver-spec.js +++ b/spec/scope-resolver-spec.js @@ -301,12 +301,12 @@ describe('ScopeResolver', () => { describe('tests', () => { - it('rejects scopes for ranges that have already been claimed by another capture with (#set! capture.final true)', async () => { + it('rejects scopes for ranges that have already been claimed by another capture with (#set! capture.final)', async () => { await grammar.setQueryForTest('highlightsQuery', ` (comment) @comment (string) @string0 ((string) @string1 - (#set! capture.final true)) + (#set! capture.final)) (string) @string2 "=" @operator @@ -323,7 +323,7 @@ describe('ScopeResolver', () => { let { scopeResolver, captures } = await getAllCaptures(grammar, languageMode); for (let capture of captures) { - let { node, name } = capture; + let { name } = capture; let result = scopeResolver.store(capture); if (name === 'string0') { expect(!!result).toBe(true); @@ -373,12 +373,12 @@ describe('ScopeResolver', () => { } }); - it('rejects scopes for ranges that have already been claimed by another capture with (#set! capture.final true)', async () => { + it('rejects scopes for ranges that have already been claimed by another capture with (#set! capture.final)', async () => { await grammar.setQueryForTest('highlightsQuery', ` (comment) @comment (string) @string0 ((string) @string1 - (#set! capture.final true)) + (#set! capture.final)) (string) @string2 "=" @operator diff --git a/spec/wasm-tree-sitter-language-mode-spec.js b/spec/wasm-tree-sitter-language-mode-spec.js index 4c0ca0884a..f899f75865 100644 --- a/spec/wasm-tree-sitter-language-mode-spec.js +++ b/spec/wasm-tree-sitter-language-mode-spec.js @@ -1625,9 +1625,16 @@ describe('WASMTreeSitterLanguageMode', () => { // `suggestedIndentForBufferRows` should use the HTML grammar to // determine the indent level of `let foo` rather than the JS grammar. + // + // And on line 5, it should use the JavaScript grammar to determine + // ``'s _initial_ indentation level, but the HTML grammar to + // determine whether to dedent relative to that initial level. buffer.setText(dedent` `); @@ -1641,9 +1648,9 @@ describe('WASMTreeSitterLanguageMode', () => { buffer.setLanguageMode(languageMode); await languageMode.ready; - let map = languageMode.suggestedIndentForBufferRows(1, 1, editor.getTabLength()); + let map = languageMode.suggestedIndentForBufferRows(0, 5, editor.getTabLength()); - expect(map.get(1)).toBe(1); + expect(Array.from(map.values())).toEqual([0, 1, 1, 2, 1, 0]); }); }); diff --git a/src/scope-resolver.js b/src/scope-resolver.js index fd5fd38ef0..46864c2d21 100644 --- a/src/scope-resolver.js +++ b/src/scope-resolver.js @@ -391,6 +391,11 @@ class ScopeResolver { return range; } + isFinal(existingData = {}) { + return ('capture.final' in existingData) || + ('final' in existingData); + } + // Given a syntax capture, test whether we should include its scope in the // document. test(capture, existingData) { @@ -401,7 +406,7 @@ class ScopeResolver { refutedProperties: refuted = {} } = capture; - if (existingData?.final || existingData?.['capture.final']) { + if (this.isFinal(existingData)) { return false; } @@ -574,16 +579,16 @@ ScopeResolver.interpolateName = (name, node) => { // Special `#set!` predicates that work on “claimed” and “unclaimed” ranges. ScopeResolver.CAPTURE_SETTINGS = { // Passes only if another capture has not already declared `final` for the - // exact same range. If a capture is the first one to define `final`, then + // exact same range. If a capture is the first one to define `exact`, then // all other captures for that same range are ignored, whether they try to // define `final` or not. - final(node, existingData) { - let final = existingData?.final || existingData?.['capture.final']; - return !(existingData && final); + final(_node, existingData) { + if (!existingData) return true; + return !('capture.final' in existingData) && !('final' in existingData); }, // Passes only if no earlier capture has occurred for the exact same range. - shy(node, existingData) { + shy(_node, existingData) { return existingData === undefined; } }; diff --git a/src/wasm-tree-sitter-language-mode.js b/src/wasm-tree-sitter-language-mode.js index 7404083bf4..d25fe203ca 100644 --- a/src/wasm-tree-sitter-language-mode.js +++ b/src/wasm-tree-sitter-language-mode.js @@ -1214,7 +1214,25 @@ class WASMTreeSitterLanguageMode { // `indents.scm`, perhaps with an explanatory comment.) let controllingLayer = this.controllingLayerAtPoint( comparisonRowEnd, - (layer) => !!layer.indentsQuery + (layer) => { + if (!layer.indentsQuery) return false; + // We want to exclude layers with a content range that _begins at_ the + // cursor position. Why? Because the content that starts at the cursor + // is about to shift down to the next line. It'd be odd if that layer + // was in charge of the indentation hint if it didn't have any content + // on the preceding line. + // + // So first we test for containment exclusive of endpoints… + if (layer.containsPoint(comparisonRowEnd, true)) { + return true; + } + + // …but we'll still accept layers that have a content range which + // _ends_ at the cursor position. + return layer.getCurrentRanges()?.some(r => { + return r.end.compare(comparisonRowEnd) === 0; + }); + } ); if (!controllingLayer) { @@ -1382,6 +1400,42 @@ class WASMTreeSitterLanguageMode { if (!options.skipDedentCheck) { scopeResolver.reset(); + // The controlling layer on the previous line gets to decide what our + // starting indent is on the current line. But it might not extend to the + // current line, so we should determine which layer is in charge of the + // second phase. + let rowStart = new Point(row, 0); + let dedentControllingLayer = this.controllingLayerAtPoint( + rowStart, + (layer) => { + if (!layer.indentsQuery) return false; + // We're inverting the logic from above: now we want to allow layers + // that _begin_ at the cursor and exclude layers that _end_ at the + // cursor. Because we'll be analyzing content that comes _after_ the + // cursor to understand whether to dedent! + // + // So first we test for containment exclusive of endpoints… + if (layer.containsPoint(rowStart, true)) { + return true; + } + + // …but we'll still accept layers that have a content range which + // _starts_ at the cursor position. + return layer.getCurrentRanges()?.some(r => { + return r.start.compare(rowStart) === 0; + }); + } + ); + + if (dedentControllingLayer && dedentControllingLayer !== controllingLayer) { + // If this layer is different from the one we used above, then we + // should run this layer's indents query against its own tree. If _no_ + // layers qualify at this position, we can still reluctantly use the + // original layer. + indentsQuery = dedentControllingLayer.indentsQuery; + indentTree = dedentControllingLayer.getOrParseTree(); + } + // The second phase covers any captures on the current line that can // cause the current line to be indented or dedented. let dedentCaptures = indentsQuery.captures( @@ -1501,7 +1555,7 @@ class WASMTreeSitterLanguageMode { // because we start at the previous row to find the suggested indent for // the current row. let controllingLayer = this.controllingLayerAtPoint( - new Point(row - 1, Infinity), + this.buffer.clipPosition(new Point(row - 1, Infinity)), (layer) => !!layer.indentsQuery && !!layer.tree ); @@ -3001,7 +3055,7 @@ class LanguageLayer { this.tree = null; this.lastSyntaxTree = null; - this.temporaryTrees = null; + this.temporaryTrees = []; while (trees.length > 0) { let tree = trees.pop(); @@ -3687,9 +3741,9 @@ class LanguageLayer { return markers.map(m => m.getRange()); } - containsPoint(point) { + containsPoint(point, exclusive = false) { let ranges = this.getCurrentRanges() ?? [this.getExtent()]; - return ranges.some(r => r.containsPoint(point)); + return ranges.some(r => r.containsPoint(point, exclusive)); } getOrParseTree({ force = true, anonymous = false } = {}) { @@ -4069,7 +4123,7 @@ class NodeRangeSet { } getRanges(buffer) { - const previousRanges = this.previous && this.previous.getRanges(buffer); + const previousRanges = this.previous?.getRanges(buffer); let result = []; for (const node of this.nodeSpecs) { @@ -4211,7 +4265,7 @@ class NodeRangeSet { // For injection points with `newlinesBetween` enabled, ensure that a // newline is included between each disjoint range. _ensureNewline(buffer, newRanges, startIndex, startPosition) { - const lastRange = newRanges[newRanges.length - 1]; + const lastRange = last(newRanges); if (lastRange && lastRange.endPosition.row < startPosition.row) { newRanges.push({ startPosition: new Point( @@ -4308,7 +4362,7 @@ class RangeList { } insertOrdered(newRange) { - let index = this.ranges.findIndex((r, i) => { + let index = this.ranges.findIndex(r => { return r.start.compare(newRange.start) > 0; }); this.ranges.splice(index, 0, newRange); diff --git a/vendor/web-tree-sitter/tree-sitter.js b/vendor/web-tree-sitter/tree-sitter.js index 07c5c36f02..ed8f498a00 100644 --- a/vendor/web-tree-sitter/tree-sitter.js +++ b/vendor/web-tree-sitter/tree-sitter.js @@ -1,12 +1,10 @@ -var Module = typeof Module !== "undefined" ? Module : {}; +var Module = typeof Module != "undefined" ? Module : {}; var TreeSitter = function() { - function checkForAsmVersion(prop) { if (!(prop in Module['asm'])) { console.warn(`Warning: parser wants to call function ${prop}, but it is not defined. If parsing fails, this is probably the reason why. Please report this to the Pulsar team so that this parser can be supported properly.`); } } - var initPromise; var document = typeof window == "object" ? { currentScript: window.document.currentScript @@ -22,26 +20,15 @@ var TreeSitter = function() { if (initPromise) return initPromise; Module = Object.assign({}, Module, moduleOptions); return initPromise = new Promise(resolveInitPromise => { - var moduleOverrides = {}; - var key; - for (key in Module) { - if (Module.hasOwnProperty(key)) { - moduleOverrides[key] = Module[key] - } - } + var moduleOverrides = Object.assign({}, Module); var arguments_ = []; var thisProgram = "./this.program"; - var quit_ = function(status, toThrow) { + var quit_ = (status, toThrow) => { throw toThrow }; - var ENVIRONMENT_IS_WEB = false; - var ENVIRONMENT_IS_WORKER = false; - var ENVIRONMENT_IS_NODE = false; - var ENVIRONMENT_IS_SHELL = false; - ENVIRONMENT_IS_WEB = typeof window === "object"; - ENVIRONMENT_IS_WORKER = typeof importScripts === "function"; - ENVIRONMENT_IS_NODE = typeof process === "object" && typeof process.versions === "object" && typeof process.versions.node === "string"; - ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER; + var ENVIRONMENT_IS_WEB = typeof window == "object"; + var ENVIRONMENT_IS_WORKER = typeof importScripts == "function"; + var ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string"; var scriptDirectory = ""; function locateFile(path) { @@ -51,90 +38,65 @@ var TreeSitter = function() { return scriptDirectory + path } var read_, readAsync, readBinary, setWindowTitle; - var nodeFS; - var nodePath; if (ENVIRONMENT_IS_NODE) { + var fs = require("fs"); + var nodePath = require("path"); if (ENVIRONMENT_IS_WORKER) { - scriptDirectory = require("path").dirname(scriptDirectory) + "/" + scriptDirectory = nodePath.dirname(scriptDirectory) + "/" } else { scriptDirectory = __dirname + "/" } - read_ = function shell_read(filename, binary) { - if (!nodeFS) nodeFS = require("fs"); - if (!nodePath) nodePath = require("path"); - filename = nodePath["normalize"](filename); - return nodeFS["readFileSync"](filename, binary ? null : "utf8") + read_ = (filename, binary) => { + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + return fs.readFileSync(filename, binary ? undefined : "utf8") }; - readBinary = function readBinary(filename) { + readBinary = filename => { var ret = read_(filename, true); if (!ret.buffer) { ret = new Uint8Array(ret) } - assert(ret.buffer); return ret }; - if (process["argv"].length > 1) { - thisProgram = process["argv"][1].replace(/\\/g, "/") + readAsync = (filename, onload, onerror) => { + filename = isFileURI(filename) ? new URL(filename) : nodePath.normalize(filename); + fs.readFile(filename, function(err, data) { + if (err) onerror(err); + else onload(data.buffer) + }) + }; + if (!Module["thisProgram"] && process.argv.length > 1) { + thisProgram = process.argv[1].replace(/\\/g, "/") } - arguments_ = process["argv"].slice(2); - if (typeof module !== "undefined") { + arguments_ = process.argv.slice(2); + if (typeof module != "undefined") { module["exports"] = Module } - quit_ = function(status) { - process["exit"](status) + quit_ = (status, toThrow) => { + process.exitCode = status; + throw toThrow }; Module["inspect"] = function() { return "[Emscripten Module object]" } - } else if (ENVIRONMENT_IS_SHELL) { - if (typeof read != "undefined") { - read_ = function shell_read(f) { - return read(f) - } - } - readBinary = function readBinary(f) { - var data; - if (typeof readbuffer === "function") { - return new Uint8Array(readbuffer(f)) - } - data = read(f, "binary"); - assert(typeof data === "object"); - return data - }; - if (typeof scriptArgs != "undefined") { - arguments_ = scriptArgs - } else if (typeof arguments != "undefined") { - arguments_ = arguments - } - if (typeof quit === "function") { - quit_ = function(status) { - quit(status) - } - } - if (typeof print !== "undefined") { - if (typeof console === "undefined") console = {}; - console.log = print; - console.warn = console.error = typeof printErr !== "undefined" ? printErr : print - } } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { if (ENVIRONMENT_IS_WORKER) { scriptDirectory = self.location.href - } else if (typeof document !== "undefined" && document.currentScript) { + } else if (typeof document != "undefined" && document.currentScript) { scriptDirectory = document.currentScript.src } if (scriptDirectory.indexOf("blob:") !== 0) { - scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf("/") + 1) + scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1) } else { scriptDirectory = "" } { - read_ = function(url) { + read_ = url => { var xhr = new XMLHttpRequest; xhr.open("GET", url, false); xhr.send(null); return xhr.responseText }; if (ENVIRONMENT_IS_WORKER) { - readBinary = function(url) { + readBinary = url => { var xhr = new XMLHttpRequest; xhr.open("GET", url, false); xhr.responseType = "arraybuffer"; @@ -142,11 +104,11 @@ var TreeSitter = function() { return new Uint8Array(xhr.response) } } - readAsync = function(url, onload, onerror) { + readAsync = (url, onload, onerror) => { var xhr = new XMLHttpRequest; xhr.open("GET", url, true); xhr.responseType = "arraybuffer"; - xhr.onload = function() { + xhr.onload = () => { if (xhr.status == 200 || xhr.status == 0 && xhr.response) { onload(xhr.response); return @@ -157,354 +119,46 @@ var TreeSitter = function() { xhr.send(null) } } - setWindowTitle = function(title) { - document.title = title - } + setWindowTitle = title => document.title = title } else {} var out = Module["print"] || console.log.bind(console); var err = Module["printErr"] || console.warn.bind(console); - for (key in moduleOverrides) { - if (moduleOverrides.hasOwnProperty(key)) { - Module[key] = moduleOverrides[key] - } - } + Object.assign(Module, moduleOverrides); moduleOverrides = null; if (Module["arguments"]) arguments_ = Module["arguments"]; if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; if (Module["quit"]) quit_ = Module["quit"]; - var STACK_ALIGN = 16; - - function alignMemory(size, factor) { - if (!factor) factor = STACK_ALIGN; - return Math.ceil(size / factor) * factor - } - - function convertJsFunctionToWasm(func, sig) { - if (typeof WebAssembly.Function === "function") { - var typeNames = { - "i": "i32", - "j": "i64", - "f": "f32", - "d": "f64" - }; - var type = { - parameters: [], - results: sig[0] == "v" ? [] : [typeNames[sig[0]]] - }; - for (var i = 1; i < sig.length; ++i) { - type.parameters.push(typeNames[sig[i]]) - } - return new WebAssembly.Function(type, func) - } - var typeSection = [1, 0, 1, 96]; - var sigRet = sig.slice(0, 1); - var sigParam = sig.slice(1); - var typeCodes = { - "i": 127, - "j": 126, - "f": 125, - "d": 124 - }; - typeSection.push(sigParam.length); - for (var i = 0; i < sigParam.length; ++i) { - typeSection.push(typeCodes[sigParam[i]]) - } - if (sigRet == "v") { - typeSection.push(0) - } else { - typeSection = typeSection.concat([1, typeCodes[sigRet]]) - } - typeSection[1] = typeSection.length - 2; - var bytes = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0].concat(typeSection, [2, 7, 1, 1, 101, 1, 102, 0, 0, 7, 5, 1, 1, 102, 0, 0])); - var module = new WebAssembly.Module(bytes); - var instance = new WebAssembly.Instance(module, { - "e": { - "f": func - } - }); - var wrappedFunc = instance.exports["f"]; - return wrappedFunc - } - var freeTableIndexes = []; - var functionsInTableMap; - - function getEmptyTableSlot() { - if (freeTableIndexes.length) { - return freeTableIndexes.pop() - } - try { - wasmTable.grow(1) - } catch (err) { - if (!(err instanceof RangeError)) { - throw err - } - throw "Unable to grow wasm table. Set ALLOW_TABLE_GROWTH." - } - return wasmTable.length - 1 - } - - function addFunctionWasm(func, sig) { - if (!functionsInTableMap) { - functionsInTableMap = new WeakMap; - for (var i = 0; i < wasmTable.length; i++) { - var item = wasmTable.get(i); - if (item) { - functionsInTableMap.set(item, i) - } - } - } - if (functionsInTableMap.has(func)) { - return functionsInTableMap.get(func) - } - var ret = getEmptyTableSlot(); - try { - wasmTable.set(ret, func) - } catch (err) { - if (!(err instanceof TypeError)) { - throw err - } - var wrapped = convertJsFunctionToWasm(func, sig); - wasmTable.set(ret, wrapped) - } - functionsInTableMap.set(func, ret); - return ret - } - var tempRet0 = 0; - var setTempRet0 = function(value) { - tempRet0 = value - }; var dynamicLibraries = Module["dynamicLibraries"] || []; var wasmBinary; if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; var noExitRuntime = Module["noExitRuntime"] || true; - if (typeof WebAssembly !== "object") { + if (typeof WebAssembly != "object") { abort("no native wasm support detected") } - - function setValue(ptr, value, type, noSafe) { - type = type || "i8"; - if (type.charAt(type.length - 1) === "*") type = "i32"; - switch (type) { - case "i1": - HEAP8[ptr >> 0] = value; - break; - case "i8": - HEAP8[ptr >> 0] = value; - break; - case "i16": - HEAP16[ptr >> 1] = value; - break; - case "i32": - HEAP32[ptr >> 2] = value; - break; - case "i64": - tempI64 = [value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1]; - break; - case "float": - HEAPF32[ptr >> 2] = value; - break; - case "double": - HEAPF64[ptr >> 3] = value; - break; - default: - abort("invalid type for setValue: " + type) - } - } - - function getValue(ptr, type, noSafe) { - type = type || "i8"; - if (type.charAt(type.length - 1) === "*") type = "i32"; - switch (type) { - case "i1": - return HEAP8[ptr >> 0]; - case "i8": - return HEAP8[ptr >> 0]; - case "i16": - return HEAP16[ptr >> 1]; - case "i32": - return HEAP32[ptr >> 2]; - case "i64": - return HEAP32[ptr >> 2]; - case "float": - return HEAPF32[ptr >> 2]; - case "double": - return HEAPF64[ptr >> 3]; - default: - abort("invalid type for getValue: " + type) - } - return null - } var wasmMemory; var ABORT = false; var EXITSTATUS; function assert(condition, text) { if (!condition) { - abort("Assertion failed: " + text) - } - } - var ALLOC_STACK = 1; - - function allocate(slab, allocator) { - var ret; - if (allocator == ALLOC_STACK) { - ret = stackAlloc(slab.length) - } else { - ret = _malloc(slab.length) - } - if (slab.subarray || slab.slice) { - HEAPU8.set(slab, ret) - } else { - HEAPU8.set(new Uint8Array(slab), ret) - } - return ret - } - var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined; - - function UTF8ArrayToString(heap, idx, maxBytesToRead) { - var endIdx = idx + maxBytesToRead; - var endPtr = idx; - while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr; - if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) { - return UTF8Decoder.decode(heap.subarray(idx, endPtr)) - } else { - var str = ""; - while (idx < endPtr) { - var u0 = heap[idx++]; - if (!(u0 & 128)) { - str += String.fromCharCode(u0); - continue - } - var u1 = heap[idx++] & 63; - if ((u0 & 224) == 192) { - str += String.fromCharCode((u0 & 31) << 6 | u1); - continue - } - var u2 = heap[idx++] & 63; - if ((u0 & 240) == 224) { - u0 = (u0 & 15) << 12 | u1 << 6 | u2 - } else { - u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heap[idx++] & 63 - } - if (u0 < 65536) { - str += String.fromCharCode(u0) - } else { - var ch = u0 - 65536; - str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023) - } - } + abort(text) } - return str } + var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; - function UTF8ToString(ptr, maxBytesToRead) { - return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "" - } - - function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { - if (!(maxBytesToWrite > 0)) return 0; - var startIdx = outIdx; - var endIdx = outIdx + maxBytesToWrite - 1; - for (var i = 0; i < str.length; ++i) { - var u = str.charCodeAt(i); - if (u >= 55296 && u <= 57343) { - var u1 = str.charCodeAt(++i); - u = 65536 + ((u & 1023) << 10) | u1 & 1023 - } - if (u <= 127) { - if (outIdx >= endIdx) break; - heap[outIdx++] = u - } else if (u <= 2047) { - if (outIdx + 1 >= endIdx) break; - heap[outIdx++] = 192 | u >> 6; - heap[outIdx++] = 128 | u & 63 - } else if (u <= 65535) { - if (outIdx + 2 >= endIdx) break; - heap[outIdx++] = 224 | u >> 12; - heap[outIdx++] = 128 | u >> 6 & 63; - heap[outIdx++] = 128 | u & 63 - } else { - if (outIdx + 3 >= endIdx) break; - heap[outIdx++] = 240 | u >> 18; - heap[outIdx++] = 128 | u >> 12 & 63; - heap[outIdx++] = 128 | u >> 6 & 63; - heap[outIdx++] = 128 | u & 63 - } - } - heap[outIdx] = 0; - return outIdx - startIdx - } - - function stringToUTF8(str, outPtr, maxBytesToWrite) { - return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite) - } - - function lengthBytesUTF8(str) { - var len = 0; - for (var i = 0; i < str.length; ++i) { - var u = str.charCodeAt(i); - if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023; - if (u <= 127) ++len; - else if (u <= 2047) len += 2; - else if (u <= 65535) len += 3; - else len += 4 - } - return len - } - - function AsciiToString(ptr) { - var str = ""; - while (1) { - var ch = HEAPU8[ptr++ >> 0]; - if (!ch) return str; - str += String.fromCharCode(ch) - } - } - - function stringToUTF16(str, outPtr, maxBytesToWrite) { - if (maxBytesToWrite === undefined) { - maxBytesToWrite = 2147483647 - } - if (maxBytesToWrite < 2) return 0; - maxBytesToWrite -= 2; - var startPtr = outPtr; - var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length; - for (var i = 0; i < numCharsToWrite; ++i) { - var codeUnit = str.charCodeAt(i); - HEAP16[outPtr >> 1] = codeUnit; - outPtr += 2 - } - HEAP16[outPtr >> 1] = 0; - return outPtr - startPtr - } - - function allocateUTF8OnStack(str) { - var size = lengthBytesUTF8(str) + 1; - var ret = stackAlloc(size); - stringToUTF8Array(str, HEAP8, ret, size); - return ret - } - - function alignUp(x, multiple) { - if (x % multiple > 0) { - x += multiple - x % multiple - } - return x - } - var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; - - function updateGlobalBufferAndViews(buf) { - buffer = buf; - Module["HEAP8"] = HEAP8 = new Int8Array(buf); - Module["HEAP16"] = HEAP16 = new Int16Array(buf); - Module["HEAP32"] = HEAP32 = new Int32Array(buf); - Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf); - Module["HEAPU16"] = HEAPU16 = new Uint16Array(buf); - Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf); - Module["HEAPF32"] = HEAPF32 = new Float32Array(buf); - Module["HEAPF64"] = HEAPF64 = new Float64Array(buf) + function updateMemoryViews() { + var b = wasmMemory.buffer; + Module["HEAP8"] = HEAP8 = new Int8Array(b); + Module["HEAP16"] = HEAP16 = new Int16Array(b); + Module["HEAP32"] = HEAP32 = new Int32Array(b); + Module["HEAPU8"] = HEAPU8 = new Uint8Array(b); + Module["HEAPU16"] = HEAPU16 = new Uint16Array(b); + Module["HEAPU32"] = HEAPU32 = new Uint32Array(b); + Module["HEAPF32"] = HEAPF32 = new Float32Array(b); + Module["HEAPF64"] = HEAPF64 = new Float64Array(b) } var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 33554432; + assert(INITIAL_MEMORY >= 65536, "INITIAL_MEMORY should be larger than STACK_SIZE, was " + INITIAL_MEMORY + "! (STACK_SIZE=" + 65536 + ")"); if (Module["wasmMemory"]) { wasmMemory = Module["wasmMemory"] } else { @@ -513,21 +167,23 @@ var TreeSitter = function() { "maximum": 2147483648 / 65536 }) } - if (wasmMemory) { - buffer = wasmMemory.buffer - } - INITIAL_MEMORY = buffer.byteLength; - updateGlobalBufferAndViews(buffer); + updateMemoryViews(); + INITIAL_MEMORY = wasmMemory.buffer.byteLength; var wasmTable = new WebAssembly.Table({ - "initial": 20, + "initial": 25, "element": "anyfunc" }); var __ATPRERUN__ = []; var __ATINIT__ = []; var __ATMAIN__ = []; var __ATPOSTRUN__ = []; + var __RELOC_FUNCS__ = []; var runtimeInitialized = false; - var runtimeExited = false; + var runtimeKeepaliveCounter = 0; + + function keepRuntimeAlive() { + return noExitRuntime || runtimeKeepaliveCounter > 0 + } function preRun() { if (Module["preRun"]) { @@ -541,6 +197,7 @@ var TreeSitter = function() { function initRuntime() { runtimeInitialized = true; + callRuntimeCallbacks(__RELOC_FUNCS__); callRuntimeCallbacks(__ATINIT__) } @@ -548,10 +205,6 @@ var TreeSitter = function() { callRuntimeCallbacks(__ATMAIN__) } - function exitRuntime() { - runtimeExited = true - } - function postRun() { if (Module["postRun"]) { if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]]; @@ -601,19 +254,16 @@ var TreeSitter = function() { } } } - Module["preloadedImages"] = {}; - Module["preloadedAudios"] = {}; - Module["preloadedWasm"] = {}; function abort(what) { if (Module["onAbort"]) { Module["onAbort"](what) } - what += ""; + what = "Aborted(" + what + ")"; err(what); ABORT = true; EXITSTATUS = 1; - what = "abort(" + what + "). Build with -s ASSERTIONS=1 for more info."; + what += ". Build with -sASSERTIONS for more info."; var e = new WebAssembly.RuntimeError(what); throw e } @@ -639,31 +289,30 @@ var TreeSitter = function() { } if (readBinary) { return readBinary(file) - } else { - throw "both async and sync fetching of the wasm failed" } + throw "both async and sync fetching of the wasm failed" } catch (err) { abort(err) } } - function getBinaryPromise() { + function getBinaryPromise(binaryFile) { if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) { - if (typeof fetch === "function" && !isFileURI(wasmBinaryFile)) { - return fetch(wasmBinaryFile, { + if (typeof fetch == "function" && !isFileURI(binaryFile)) { + return fetch(binaryFile, { credentials: "same-origin" }).then(function(response) { if (!response["ok"]) { - throw "failed to load wasm binary file at '" + wasmBinaryFile + "'" + throw "failed to load wasm binary file at '" + binaryFile + "'" } return response["arrayBuffer"]() }).catch(function() { - return getBinary(wasmBinaryFile) + return getBinary(binaryFile) }) } else { if (readAsync) { return new Promise(function(resolve, reject) { - readAsync(wasmBinaryFile, function(response) { + readAsync(binaryFile, function(response) { resolve(new Uint8Array(response)) }, reject) }) @@ -671,241 +320,469 @@ var TreeSitter = function() { } } return Promise.resolve().then(function() { - return getBinary(wasmBinaryFile) + return getBinary(binaryFile) + }) + } + + function instantiateArrayBuffer(binaryFile, imports, receiver) { + return getBinaryPromise(binaryFile).then(function(binary) { + return WebAssembly.instantiate(binary, imports) + }).then(function(instance) { + return instance + }).then(receiver, function(reason) { + err("failed to asynchronously prepare wasm: " + reason); + abort(reason) }) } + function instantiateAsync(binary, binaryFile, imports, callback) { + if (!binary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(binaryFile) && !isFileURI(binaryFile) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") { + return fetch(binaryFile, { + credentials: "same-origin" + }).then(function(response) { + var result = WebAssembly.instantiateStreaming(response, imports); + return result.then(callback, function(reason) { + err("wasm streaming compile failed: " + reason); + err("falling back to ArrayBuffer instantiation"); + return instantiateArrayBuffer(binaryFile, imports, callback) + }) + }) + } else { + return instantiateArrayBuffer(binaryFile, imports, callback) + } + } + function createWasm() { var info = { - "env": asmLibraryArg, - "wasi_snapshot_preview1": asmLibraryArg, - "GOT.mem": new Proxy(asmLibraryArg, GOTHandler), - "GOT.func": new Proxy(asmLibraryArg, GOTHandler) + "env": wasmImports, + "wasi_snapshot_preview1": wasmImports, + "GOT.mem": new Proxy(wasmImports, GOTHandler), + "GOT.func": new Proxy(wasmImports, GOTHandler) }; function receiveInstance(instance, module) { var exports = instance.exports; exports = relocateExports(exports, 1024); - Module["asm"] = exports; var metadata = getDylinkMetadata(module); if (metadata.neededDynlibs) { dynamicLibraries = metadata.neededDynlibs.concat(dynamicLibraries) } mergeLibSymbols(exports, "main"); + Module["asm"] = exports; addOnInit(Module["asm"]["__wasm_call_ctors"]); - removeRunDependency("wasm-instantiate") + __RELOC_FUNCS__.push(Module["asm"]["__wasm_apply_data_relocs"]); + removeRunDependency("wasm-instantiate"); + return exports } addRunDependency("wasm-instantiate"); function receiveInstantiationResult(result) { receiveInstance(result["instance"], result["module"]) } - - function instantiateArrayBuffer(receiver) { - return getBinaryPromise().then(function(binary) { - var result = WebAssembly.instantiate(binary, info); - return result - }).then(receiver, function(reason) { - err("failed to asynchronously prepare wasm: " + reason); - abort(reason) - }) - } - - function instantiateAsync() { - if (!wasmBinary && typeof WebAssembly.instantiateStreaming === "function" && !isDataURI(wasmBinaryFile) && !isFileURI(wasmBinaryFile) && typeof fetch === "function") { - return fetch(wasmBinaryFile, { - credentials: "same-origin" - }).then(function(response) { - var result = WebAssembly.instantiateStreaming(response, info); - return result.then(receiveInstantiationResult, function(reason) { - err("wasm streaming compile failed: " + reason); - err("falling back to ArrayBuffer instantiation"); - return instantiateArrayBuffer(receiveInstantiationResult) - }) - }) - } else { - return instantiateArrayBuffer(receiveInstantiationResult) - } - } if (Module["instantiateWasm"]) { try { - var exports = Module["instantiateWasm"](info, receiveInstance); - return exports + return Module["instantiateWasm"](info, receiveInstance) } catch (e) { err("Module.instantiateWasm callback failed with error: " + e); return false } } - instantiateAsync(); + instantiateAsync(wasmBinary, wasmBinaryFile, info, receiveInstantiationResult); return {} } var tempDouble; var tempI64; + var ASM_CONSTS = {}; + + function ExitStatus(status) { + this.name = "ExitStatus"; + this.message = "Program terminated with exit(" + status + ")"; + this.status = status + } var GOT = {}; + var currentModuleWeakSymbols = new Set([]); var GOTHandler = { get: function(obj, symName) { - if (!GOT[symName]) { - GOT[symName] = new WebAssembly.Global({ + var rtn = GOT[symName]; + if (!rtn) { + rtn = GOT[symName] = new WebAssembly.Global({ "value": "i32", "mutable": true }) } - return GOT[symName] + if (!currentModuleWeakSymbols.has(symName)) { + rtn.required = true + } + return rtn + } + }; + + function callRuntimeCallbacks(callbacks) { + while (callbacks.length > 0) { + callbacks.shift()(Module) + } + } + var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined; + + function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) { + var endIdx = idx + maxBytesToRead; + var endPtr = idx; + while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr; + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)) + } + var str = ""; + while (idx < endPtr) { + var u0 = heapOrArray[idx++]; + if (!(u0 & 128)) { + str += String.fromCharCode(u0); + continue + } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 224) == 192) { + str += String.fromCharCode((u0 & 31) << 6 | u1); + continue + } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 240) == 224) { + u0 = (u0 & 15) << 12 | u1 << 6 | u2 + } else { + u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63 + } + if (u0 < 65536) { + str += String.fromCharCode(u0) + } else { + var ch = u0 - 65536; + str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023) + } + } + return str + } + + function getDylinkMetadata(binary) { + var offset = 0; + var end = 0; + + function getU8() { + return binary[offset++] + } + + function getLEB() { + var ret = 0; + var mul = 1; + while (1) { + var byte = binary[offset++]; + ret += (byte & 127) * mul; + mul *= 128; + if (!(byte & 128)) break + } + return ret + } + + function getString() { + var len = getLEB(); + offset += len; + return UTF8ArrayToString(binary, offset - len, len) + } + + function failIf(condition, message) { + if (condition) throw new Error(message) + } + var name = "dylink.0"; + if (binary instanceof WebAssembly.Module) { + var dylinkSection = WebAssembly.Module.customSections(binary, name); + if (dylinkSection.length === 0) { + name = "dylink"; + dylinkSection = WebAssembly.Module.customSections(binary, name) + } + failIf(dylinkSection.length === 0, "need dylink section"); + binary = new Uint8Array(dylinkSection[0]); + end = binary.length + } else { + var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer); + var magicNumberFound = int32View[0] == 1836278016; + failIf(!magicNumberFound, "need to see wasm magic number"); + failIf(binary[8] !== 0, "need the dylink section to be first"); + offset = 9; + var section_size = getLEB(); + end = offset + section_size; + name = getString() + } + var customSection = { + neededDynlibs: [], + tlsExports: new Set, + weakImports: new Set + }; + if (name == "dylink") { + customSection.memorySize = getLEB(); + customSection.memoryAlign = getLEB(); + customSection.tableSize = getLEB(); + customSection.tableAlign = getLEB(); + var neededDynlibsCount = getLEB(); + for (var i = 0; i < neededDynlibsCount; ++i) { + var libname = getString(); + customSection.neededDynlibs.push(libname) + } + } else { + failIf(name !== "dylink.0"); + var WASM_DYLINK_MEM_INFO = 1; + var WASM_DYLINK_NEEDED = 2; + var WASM_DYLINK_EXPORT_INFO = 3; + var WASM_DYLINK_IMPORT_INFO = 4; + var WASM_SYMBOL_TLS = 256; + var WASM_SYMBOL_BINDING_MASK = 3; + var WASM_SYMBOL_BINDING_WEAK = 1; + while (offset < end) { + var subsectionType = getU8(); + var subsectionSize = getLEB(); + if (subsectionType === WASM_DYLINK_MEM_INFO) { + customSection.memorySize = getLEB(); + customSection.memoryAlign = getLEB(); + customSection.tableSize = getLEB(); + customSection.tableAlign = getLEB() + } else if (subsectionType === WASM_DYLINK_NEEDED) { + var neededDynlibsCount = getLEB(); + for (var i = 0; i < neededDynlibsCount; ++i) { + libname = getString(); + customSection.neededDynlibs.push(libname) + } + } else if (subsectionType === WASM_DYLINK_EXPORT_INFO) { + var count = getLEB(); + while (count--) { + var symname = getString(); + var flags = getLEB(); + if (flags & WASM_SYMBOL_TLS) { + customSection.tlsExports.add(symname) + } + } + } else if (subsectionType === WASM_DYLINK_IMPORT_INFO) { + var count = getLEB(); + while (count--) { + var modname = getString(); + var symname = getString(); + var flags = getLEB(); + if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { + customSection.weakImports.add(symname) + } + } + } else { + offset += subsectionSize + } + } + } + return customSection + } + + function getValue(ptr, type = "i8") { + if (type.endsWith("*")) type = "*"; + switch (type) { + case "i1": + return HEAP8[ptr >> 0]; + case "i8": + return HEAP8[ptr >> 0]; + case "i16": + return HEAP16[ptr >> 1]; + case "i32": + return HEAP32[ptr >> 2]; + case "i64": + return HEAP32[ptr >> 2]; + case "float": + return HEAPF32[ptr >> 2]; + case "double": + return HEAPF64[ptr >> 3]; + case "*": + return HEAPU32[ptr >> 2]; + default: + abort("invalid type for getValue: " + type) + } + } + + function newDSO(name, handle, syms) { + var dso = { + refcount: Infinity, + name: name, + exports: syms, + global: true + }; + LDSO.loadedLibsByName[name] = dso; + if (handle != undefined) { + LDSO.loadedLibsByHandle[handle] = dso + } + return dso + } + var LDSO = { + loadedLibsByName: {}, + loadedLibsByHandle: {}, + init: () => newDSO("__main__", 0, wasmImports) + }; + var ___heap_base = 78160; + + function zeroMemory(address, size) { + HEAPU8.fill(0, address, address + size); + return address + } + + function getMemory(size) { + if (runtimeInitialized) { + return zeroMemory(_malloc(size), size) + } + var ret = ___heap_base; + var end = ret + size + 15 & -16; + ___heap_base = end; + GOT["__heap_base"].value = end; + return ret + } + + function isInternalSym(symName) { + return ["__cpp_exception", "__c_longjmp", "__wasm_apply_data_relocs", "__dso_handle", "__tls_size", "__tls_align", "__set_stack_limits", "_emscripten_tls_init", "__wasm_init_tls", "__wasm_call_ctors", "__start_em_asm", "__stop_em_asm"].includes(symName) + } + + function uleb128Encode(n, target) { + if (n < 128) { + target.push(n) + } else { + target.push(n % 128 | 128, n >> 7) } - }; + } - function callRuntimeCallbacks(callbacks) { - while (callbacks.length > 0) { - var callback = callbacks.shift(); - if (typeof callback == "function") { - callback(Module); - continue - } - var func = callback.func; - if (typeof func === "number") { - if (callback.arg === undefined) { - wasmTable.get(func)() - } else { - wasmTable.get(func)(callback.arg) - } - } else { - func(callback.arg === undefined ? null : callback.arg) + function sigToWasmTypes(sig) { + var typeNames = { + "i": "i32", + "j": "i32", + "f": "f32", + "d": "f64", + "p": "i32" + }; + var type = { + parameters: [], + results: sig[0] == "v" ? [] : [typeNames[sig[0]]] + }; + for (var i = 1; i < sig.length; ++i) { + type.parameters.push(typeNames[sig[i]]); + if (sig[i] === "j") { + type.parameters.push("i32") } } + return type } - function getDylinkMetadata(binary) { - var next = 0; - - function getLEB() { - var ret = 0; - var mul = 1; - while (1) { - var byte = binary[next++]; - ret += (byte & 127) * mul; - mul *= 128; - if (!(byte & 128)) break - } - return ret + function generateFuncType(sig, target) { + var sigRet = sig.slice(0, 1); + var sigParam = sig.slice(1); + var typeCodes = { + "i": 127, + "p": 127, + "j": 126, + "f": 125, + "d": 124 + }; + target.push(96); + uleb128Encode(sigParam.length, target); + for (var i = 0; i < sigParam.length; ++i) { + target.push(typeCodes[sigParam[i]]) } - if (binary instanceof WebAssembly.Module) { - var dylinkSection = WebAssembly.Module.customSections(binary, "dylink"); - assert(dylinkSection.length != 0, "need dylink section"); - binary = new Int8Array(dylinkSection[0]) + if (sigRet == "v") { + target.push(0) } else { - var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer); - assert(int32View[0] == 1836278016, "need to see wasm magic number"); - assert(binary[8] === 0, "need the dylink section to be first"); - next = 9; - getLEB(); - assert(binary[next] === 6); - next++; - assert(binary[next] === "d".charCodeAt(0)); - next++; - assert(binary[next] === "y".charCodeAt(0)); - next++; - assert(binary[next] === "l".charCodeAt(0)); - next++; - assert(binary[next] === "i".charCodeAt(0)); - next++; - assert(binary[next] === "n".charCodeAt(0)); - next++; - assert(binary[next] === "k".charCodeAt(0)); - next++ - } - var customSection = {}; - customSection.memorySize = getLEB(); - customSection.memoryAlign = getLEB(); - customSection.tableSize = getLEB(); - customSection.tableAlign = getLEB(); - var neededDynlibsCount = getLEB(); - customSection.neededDynlibs = []; - for (var i = 0; i < neededDynlibsCount; ++i) { - var nameLen = getLEB(); - var nameUTF8 = binary.subarray(next, next + nameLen); - next += nameLen; - var name = UTF8ArrayToString(nameUTF8, 0); - customSection.neededDynlibs.push(name) + target.push(1, typeCodes[sigRet]) } - return customSection } - var runtimeKeepaliveCounter = 0; - function keepRuntimeAlive() { - return noExitRuntime || runtimeKeepaliveCounter > 0 + function convertJsFunctionToWasm(func, sig) { + if (typeof WebAssembly.Function == "function") { + return new WebAssembly.Function(sigToWasmTypes(sig), func) + } + var typeSectionBody = [1]; + generateFuncType(sig, typeSectionBody); + var bytes = [0, 97, 115, 109, 1, 0, 0, 0, 1]; + uleb128Encode(typeSectionBody.length, bytes); + bytes.push.apply(bytes, typeSectionBody); + bytes.push(2, 7, 1, 1, 101, 1, 102, 0, 0, 7, 5, 1, 1, 102, 0, 0); + var module = new WebAssembly.Module(new Uint8Array(bytes)); + var instance = new WebAssembly.Instance(module, { + "e": { + "f": func + } + }); + var wrappedFunc = instance.exports["f"]; + return wrappedFunc } + var wasmTableMirror = []; - function asmjsMangle(x) { - var unmangledSymbols = ["stackAlloc", "stackSave", "stackRestore"]; - return x.indexOf("dynCall_") == 0 || unmangledSymbols.includes(x) ? x : "_" + x + function getWasmTableEntry(funcPtr) { + var func = wasmTableMirror[funcPtr]; + if (!func) { + if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1; + wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr) + } + return func } - function mergeLibSymbols(exports, libName) { - for (var sym in exports) { - if (!exports.hasOwnProperty(sym)) { - continue - } - if (!asmLibraryArg.hasOwnProperty(sym)) { - asmLibraryArg[sym] = exports[sym] - } - var module_sym = asmjsMangle(sym); - if (!Module.hasOwnProperty(module_sym)) { - Module[module_sym] = exports[sym] + function updateTableMap(offset, count) { + if (functionsInTableMap) { + for (var i = offset; i < offset + count; i++) { + var item = getWasmTableEntry(i); + if (item) { + functionsInTableMap.set(item, i) + } } } } - var LDSO = { - nextHandle: 1, - loadedLibs: {}, - loadedLibNames: {} - }; - - function dynCallLegacy(sig, ptr, args) { - var f = Module["dynCall_" + sig]; - return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr) - } + var functionsInTableMap = undefined; - function dynCall(sig, ptr, args) { - if (sig.includes("j")) { - return dynCallLegacy(sig, ptr, args) + function getFunctionAddress(func) { + if (!functionsInTableMap) { + functionsInTableMap = new WeakMap; + updateTableMap(0, wasmTable.length) } - return wasmTable.get(ptr).apply(null, args) + return functionsInTableMap.get(func) || 0 } + var freeTableIndexes = []; - function createInvokeFunction(sig) { - return function() { - var sp = stackSave(); - try { - return dynCall(sig, arguments[0], Array.prototype.slice.call(arguments, 1)) - } catch (e) { - stackRestore(sp); - if (e !== e + 0 && e !== "longjmp") throw e; - _setThrew(1, 0) + function getEmptyTableSlot() { + if (freeTableIndexes.length) { + return freeTableIndexes.pop() + } + try { + wasmTable.grow(1) + } catch (err) { + if (!(err instanceof RangeError)) { + throw err } + throw "Unable to grow wasm table. Set ALLOW_TABLE_GROWTH." } + return wasmTable.length - 1 } - var ___heap_base = 5251072; - Module["___heap_base"] = ___heap_base; - function getMemory(size) { - if (runtimeInitialized) return _malloc(size); - var ret = ___heap_base; - var end = ret + size + 15 & -16; - ___heap_base = end; - GOT["__heap_base"].value = end; - return ret + function setWasmTableEntry(idx, func) { + wasmTable.set(idx, func); + wasmTableMirror[idx] = wasmTable.get(idx) } - function isInternalSym(symName) { - return ["__cpp_exception", "__wasm_apply_data_relocs", "__dso_handle", "__set_stack_limits"].includes(symName) + function addFunction(func, sig) { + var rtn = getFunctionAddress(func); + if (rtn) { + return rtn + } + var ret = getEmptyTableSlot(); + try { + setWasmTableEntry(ret, func) + } catch (err) { + if (!(err instanceof TypeError)) { + throw err + } + var wrapped = convertJsFunctionToWasm(func, sig); + setWasmTableEntry(ret, wrapped) + } + functionsInTableMap.set(func, ret); + return ret } - function updateGOT(exports) { + function updateGOT(exports, replace) { for (var symName in exports) { if (isInternalSym(symName)) { continue } - var replace = false; var value = exports[symName]; if (symName.startsWith("orig$")) { symName = symName.split("$")[1]; @@ -918,9 +795,9 @@ var TreeSitter = function() { }) } if (replace || GOT[symName].value == 0) { - if (typeof value === "function") { - GOT[symName].value = addFunctionWasm(value) - } else if (typeof value === "number") { + if (typeof value == "function") { + GOT[symName].value = addFunction(value) + } else if (typeof value == "number") { GOT[symName].value = value } else { err("unhandled export type for `" + symName + "`: " + typeof value) @@ -929,58 +806,113 @@ var TreeSitter = function() { } } - function relocateExports(exports, memoryBase) { + function relocateExports(exports, memoryBase, replace) { var relocated = {}; for (var e in exports) { var value = exports[e]; - if (typeof value === "object") { + if (typeof value == "object") { value = value.value } - if (typeof value === "number") { + if (typeof value == "number") { value += memoryBase } relocated[e] = value } - updateGOT(relocated); + updateGOT(relocated, replace); return relocated } - function resolveGlobalSymbol(symName, direct) { + function isSymbolDefined(symName) { + var existing = wasmImports[symName]; + if (!existing || existing.stub) { + return false + } + return true + } + + function resolveGlobalSymbol(symName, direct = false) { var sym; - if (direct) { - sym = asmLibraryArg["orig$" + symName] + if (direct && "orig$" + symName in wasmImports) { + symName = "orig$" + symName + } + if (isSymbolDefined(symName)) { + sym = wasmImports[symName] + } else if (symName.startsWith("invoke_")) { + sym = wasmImports[symName] = createInvokeFunction(symName.split("_")[1]) } - if (!sym) { - sym = asmLibraryArg[symName] + return { + sym: sym, + name: symName } - if (!sym) { - sym = Module[asmjsMangle(symName)] + } + + function alignMemory(size, alignment) { + return Math.ceil(size / alignment) * alignment + } + + function dynCallLegacy(sig, ptr, args) { + var f = Module["dynCall_" + sig]; + return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr) + } + + function dynCall(sig, ptr, args) { + if (sig.includes("j")) { + return dynCallLegacy(sig, ptr, args) } - if (!sym && symName.startsWith("invoke_")) { - sym = createInvokeFunction(symName.split("_")[1]) + var rtn = getWasmTableEntry(ptr).apply(null, args); + return rtn + } + + function createInvokeFunction(sig) { + return function() { + var sp = stackSave(); + try { + return dynCall(sig, arguments[0], Array.prototype.slice.call(arguments, 1)) + } catch (e) { + stackRestore(sp); + if (e !== e + 0) throw e; + _setThrew(1, 0) + } } - return sym } - function loadWebAssemblyModule(binary, flags) { + function UTF8ToString(ptr, maxBytesToRead) { + return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "" + } + + function loadWebAssemblyModule(binary, flags, localScope, handle) { var metadata = getDylinkMetadata(binary); + currentModuleWeakSymbols = metadata.weakImports; function loadModule() { - var memAlign = Math.pow(2, metadata.memoryAlign); - memAlign = Math.max(memAlign, STACK_ALIGN); - var memoryBase = alignMemory(getMemory(metadata.memorySize + memAlign), memAlign); - var tableBase = wasmTable.length; - wasmTable.grow(metadata.tableSize); - for (var i = memoryBase; i < memoryBase + metadata.memorySize; i++) { - HEAP8[i] = 0 + var firstLoad = !handle || !HEAP8[handle + 8 >> 0]; + if (firstLoad) { + var memAlign = Math.pow(2, metadata.memoryAlign); + memAlign = Math.max(memAlign, 16); + var memoryBase = metadata.memorySize ? alignMemory(getMemory(metadata.memorySize + memAlign), memAlign) : 0; + var tableBase = metadata.tableSize ? wasmTable.length : 0; + if (handle) { + HEAP8[handle + 8 >> 0] = 1; + HEAPU32[handle + 12 >> 2] = memoryBase; + HEAP32[handle + 16 >> 2] = metadata.memorySize; + HEAPU32[handle + 20 >> 2] = tableBase; + HEAP32[handle + 24 >> 2] = metadata.tableSize + } + } else { + memoryBase = HEAPU32[handle + 12 >> 2]; + tableBase = HEAPU32[handle + 20 >> 2] } - for (var i = tableBase; i < tableBase + metadata.tableSize; i++) { - wasmTable.set(i, null) + var tableGrowthNeeded = tableBase + metadata.tableSize - wasmTable.length; + if (tableGrowthNeeded > 0) { + wasmTable.grow(tableGrowthNeeded) } var moduleExports; function resolveSymbol(sym) { - var resolved = resolveGlobalSymbol(sym, false); + var resolved = resolveGlobalSymbol(sym).sym; + if (!resolved && localScope) { + resolved = localScope[sym] + } if (!resolved) { resolved = moduleExports[sym] } @@ -994,13 +926,13 @@ var TreeSitter = function() { case "__table_base": return tableBase } - if (prop in asmLibraryArg) { - return asmLibraryArg[prop] + if (prop in wasmImports && !wasmImports[prop].stub) { + return wasmImports[prop] } if (!(prop in stubs)) { var resolved; stubs[prop] = function() { - if (!resolved) resolved = resolveSymbol(prop, true); + if (!resolved) resolved = resolveSymbol(prop); checkForAsmVersion(prop); return resolved.apply(null, arguments) } @@ -1017,20 +949,44 @@ var TreeSitter = function() { }; function postInstantiation(instance) { - for (var i = 0; i < metadata.tableSize; i++) { - var item = wasmTable.get(tableBase + i); - if (item) { - functionsInTableMap.set(item, tableBase + i) - } - } + updateTableMap(tableBase, metadata.tableSize); moduleExports = relocateExports(instance.exports, memoryBase); if (!flags.allowUndefined) { reportUndefinedSymbols() } - var init = moduleExports["__wasm_call_ctors"]; - if (!init) { - init = moduleExports["__post_instantiate"] + + function addEmAsm(addr, body) { + var args = []; + var arity = 0; + for (; arity < 16; arity++) { + if (body.indexOf("$" + arity) != -1) { + args.push("$" + arity) + } else { + break + } + } + args = args.join(","); + var func = "(" + args + " ) => { " + body + "};"; + ASM_CONSTS[start] = eval(func) + } + if ("__start_em_asm" in moduleExports) { + var start = moduleExports["__start_em_asm"]; + var stop = moduleExports["__stop_em_asm"]; + while (start < stop) { + var jsString = UTF8ToString(start); + addEmAsm(start, jsString); + start = HEAPU8.indexOf(0, start) + 1 + } + } + var applyRelocs = moduleExports["__wasm_apply_data_relocs"]; + if (applyRelocs) { + if (runtimeInitialized) { + applyRelocs() + } else { + __RELOC_FUNCS__.push(applyRelocs) + } } + var init = moduleExports["__wasm_call_ctors"]; if (init) { if (runtimeInitialized) { init() @@ -1063,67 +1019,63 @@ var TreeSitter = function() { }) } metadata.neededDynlibs.forEach(function(dynNeeded) { - loadDynamicLibrary(dynNeeded, flags) + loadDynamicLibrary(dynNeeded, flags, localScope) }); return loadModule() } - function fetchBinary(url) { - return fetch(url, { - credentials: "same-origin" - }).then(function(response) { - if (!response["ok"]) { - throw "failed to load binary file at '" + url + "'" + function mergeLibSymbols(exports, libName) { + for (var sym in exports) { + if (!exports.hasOwnProperty(sym)) { + continue } - return response["arrayBuffer"]() - }).then(function(buffer) { - return new Uint8Array(buffer) - }) - } - - function loadDynamicLibrary(lib, flags) { - if (lib == "__main__" && !LDSO.loadedLibNames[lib]) { - LDSO.loadedLibs[-1] = { - refcount: Infinity, - name: "__main__", - module: Module["asm"], - global: true + const setImport = target => { + if (!isSymbolDefined(target)) { + wasmImports[target] = exports[sym] + } }; - LDSO.loadedLibNames["__main__"] = -1 + setImport(sym); + const main_alias = "__main_argc_argv"; + if (sym == "main") { + setImport(main_alias) + } + if (sym == main_alias) { + setImport("main") + } + if (sym.startsWith("dynCall_") && !Module.hasOwnProperty(sym)) { + Module[sym] = exports[sym] + } } - flags = flags || { - global: true, - nodelete: true - }; - var handle = LDSO.loadedLibNames[lib]; - var dso; - if (handle) { - dso = LDSO.loadedLibs[handle]; + } + + function loadDynamicLibrary(libName, flags = { + global: true, + nodelete: true + }, localScope, handle) { + var dso = LDSO.loadedLibsByName[libName]; + if (dso) { if (flags.global && !dso.global) { dso.global = true; - if (dso.module !== "loading") { - mergeLibSymbols(dso.module, lib) + if (dso.exports !== "loading") { + mergeLibSymbols(dso.exports, libName) } } if (flags.nodelete && dso.refcount !== Infinity) { dso.refcount = Infinity } dso.refcount++; - return flags.loadAsync ? Promise.resolve(handle) : handle - } - handle = LDSO.nextHandle++; - dso = { - refcount: flags.nodelete ? Infinity : 1, - name: lib, - module: "loading", - global: flags.global - }; - LDSO.loadedLibNames[lib] = handle; - LDSO.loadedLibs[handle] = dso; + if (handle) { + LDSO.loadedLibsByHandle[handle] = dso + } + return flags.loadAsync ? Promise.resolve(true) : true + } + dso = newDSO(libName, handle, "loading"); + dso.refcount = flags.nodelete ? Infinity : 1; + dso.global = flags.global; - function loadLibData(libFile) { - if (flags.fs) { - var libData = flags.fs.readFile(libFile, { + function loadLibData() { + if (flags.fs && flags.fs.findObject(libName)) { + var libData = flags.fs.readFile(libName, { encoding: "binary" }); if (!(libData instanceof Uint8Array)) { @@ -1131,139 +1083,169 @@ var TreeSitter = function() { } return flags.loadAsync ? Promise.resolve(libData) : libData } + var libFile = locateFile(libName); if (flags.loadAsync) { - return fetchBinary(libFile) + return new Promise(function(resolve, reject) { + readAsync(libFile, data => resolve(new Uint8Array(data)), reject) + }) + } + if (!readBinary) { + throw new Error(libFile + ": file not found, and synchronous loading of external files is not available") } return readBinary(libFile) } - function getLibModule() { - if (Module["preloadedWasm"] !== undefined && Module["preloadedWasm"][lib] !== undefined) { - var libModule = Module["preloadedWasm"][lib]; + function getExports() { + if (typeof preloadedWasm != "undefined" && preloadedWasm[libName]) { + var libModule = preloadedWasm[libName]; return flags.loadAsync ? Promise.resolve(libModule) : libModule } if (flags.loadAsync) { - return loadLibData(lib).then(function(libData) { - return loadWebAssemblyModule(libData, flags) - }) + return loadLibData().then(libData => loadWebAssemblyModule(libData, flags, localScope, handle)) } - return loadWebAssemblyModule(loadLibData(lib), flags) + return loadWebAssemblyModule(loadLibData(), flags, localScope, handle) } - function moduleLoaded(libModule) { + function moduleLoaded(exports) { if (dso.global) { - mergeLibSymbols(libModule, lib) + mergeLibSymbols(exports, libName) + } else if (localScope) { + Object.assign(localScope, exports) } - dso.module = libModule + dso.exports = exports } if (flags.loadAsync) { - return getLibModule().then(function(libModule) { - moduleLoaded(libModule); - return handle + return getExports().then(exports => { + moduleLoaded(exports); + return true }) } - moduleLoaded(getLibModule()); - return handle + moduleLoaded(getExports()); + return true } function reportUndefinedSymbols() { for (var symName in GOT) { if (GOT[symName].value == 0) { - var value = resolveGlobalSymbol(symName, true); - if (typeof value === "function") { - GOT[symName].value = addFunctionWasm(value, value.sig) - } else if (typeof value === "number") { + var value = resolveGlobalSymbol(symName, true).sym; + if (!value && !GOT[symName].required) { + continue + } + if (typeof value == "function") { + GOT[symName].value = addFunction(value, value.sig) + } else if (typeof value == "number") { GOT[symName].value = value } else { - assert(false, "bad export type for `" + symName + "`: " + typeof value) + throw new Error("bad export type for `" + symName + "`: " + typeof value) } } } } - function preloadDylibs() { + function loadDylibs() { if (!dynamicLibraries.length) { reportUndefinedSymbols(); return } - if (!readBinary) { - addRunDependency("preloadDylibs"); - dynamicLibraries.reduce(function(chain, lib) { - return chain.then(function() { - return loadDynamicLibrary(lib, { - loadAsync: true, - global: true, - nodelete: true, - allowUndefined: true - }) + addRunDependency("loadDylibs"); + dynamicLibraries.reduce(function(chain, lib) { + return chain.then(function() { + return loadDynamicLibrary(lib, { + loadAsync: true, + global: true, + nodelete: true, + allowUndefined: true }) - }, Promise.resolve()).then(function() { - removeRunDependency("preloadDylibs"); - reportUndefinedSymbols() - }); - return - } - dynamicLibraries.forEach(function(lib) { - loadDynamicLibrary(lib, { - global: true, - nodelete: true, - allowUndefined: true }) - }); - reportUndefinedSymbols() + }, Promise.resolve()).then(function() { + reportUndefinedSymbols(); + removeRunDependency("loadDylibs") + }) } + + function setValue(ptr, value, type = "i8") { + if (type.endsWith("*")) type = "*"; + switch (type) { + case "i1": + HEAP8[ptr >> 0] = value; + break; + case "i8": + HEAP8[ptr >> 0] = value; + break; + case "i16": + HEAP16[ptr >> 1] = value; + break; + case "i32": + HEAP32[ptr >> 2] = value; + break; + case "i64": + tempI64 = [value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1]; + break; + case "float": + HEAPF32[ptr >> 2] = value; + break; + case "double": + HEAPF64[ptr >> 3] = value; + break; + case "*": + HEAPU32[ptr >> 2] = value; + break; + default: + abort("invalid type for setValue: " + type) + } + } + var ___memory_base = new WebAssembly.Global({ + "value": "i32", + "mutable": false + }, 1024); var ___stack_pointer = new WebAssembly.Global({ "value": "i32", "mutable": true - }, 5251072); + }, 78160); + var ___table_base = new WebAssembly.Global({ + "value": "i32", + "mutable": false + }, 1); + var nowIsMonotonic = true; + + function __emscripten_get_now_is_monotonic() { + return nowIsMonotonic + } + __emscripten_get_now_is_monotonic.sig = "i"; function _abort() { - abort() + abort("") } Module["_abort"] = _abort; _abort.sig = "v"; + + function _emscripten_date_now() { + return Date.now() + } + _emscripten_date_now.sig = "d"; var _emscripten_get_now; if (ENVIRONMENT_IS_NODE) { - _emscripten_get_now = function() { - var t = process["hrtime"](); + _emscripten_get_now = () => { + var t = process.hrtime(); return t[0] * 1e3 + t[1] / 1e6 } - } else if (typeof dateNow !== "undefined") { - _emscripten_get_now = dateNow - } else _emscripten_get_now = function() { - return performance.now() - }; - var _emscripten_get_now_is_monotonic = true; - - function setErrNo(value) { - HEAP32[___errno_location() >> 2] = value; - return value - } - - function _clock_gettime(clk_id, tp) { - var now; - if (clk_id === 0) { - now = Date.now() - } else if ((clk_id === 1 || clk_id === 4) && _emscripten_get_now_is_monotonic) { - now = _emscripten_get_now() - } else { - setErrNo(28); - return -1 - } - HEAP32[tp >> 2] = now / 1e3 | 0; - HEAP32[tp + 4 >> 2] = now % 1e3 * 1e3 * 1e3 | 0; - return 0 - } - _clock_gettime.sig = "iii"; + } else _emscripten_get_now = () => performance.now(); + _emscripten_get_now.sig = "d"; function _emscripten_memcpy_big(dest, src, num) { HEAPU8.copyWithin(dest, src, src + num) } + _emscripten_memcpy_big.sig = "vppp"; + + function getHeapMax() { + return 2147483648 + } function emscripten_realloc_buffer(size) { + var b = wasmMemory.buffer; try { - wasmMemory.grow(size - buffer.byteLength + 65535 >>> 16); - updateGlobalBufferAndViews(wasmMemory.buffer); + wasmMemory.grow(size - b.byteLength + 65535 >>> 16); + updateMemoryViews(); return 1 } catch (e) {} } @@ -1271,10 +1253,11 @@ var TreeSitter = function() { function _emscripten_resize_heap(requestedSize) { var oldSize = HEAPU8.length; requestedSize = requestedSize >>> 0; - var maxHeapSize = 2147483648; + var maxHeapSize = getHeapMax(); if (requestedSize > maxHeapSize) { return false } + let alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple; for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { var overGrownHeapSize = oldSize * (1 + .2 / cutDown); overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); @@ -1286,25 +1269,18 @@ var TreeSitter = function() { } return false } - - function _exit(status) { - exit(status) - } - _exit.sig = "vi"; + _emscripten_resize_heap.sig = "ip"; var SYSCALLS = { - mappings: {}, DEFAULT_POLLMASK: 5, - umask: 511, calculateAt: function(dirfd, path, allowEmpty) { - if (path[0] === "/") { + if (PATH.isAbs(path)) { return path } var dir; if (dirfd === -100) { dir = FS.cwd() } else { - var dirstream = FS.getStream(dirfd); - if (!dirstream) throw new FS.ErrnoError(8); + var dirstream = SYSCALLS.getStreamFromFD(dirfd); dir = dirstream.path } if (path.length == 0) { @@ -1325,107 +1301,36 @@ var TreeSitter = function() { throw e } HEAP32[buf >> 2] = stat.dev; - HEAP32[buf + 4 >> 2] = 0; HEAP32[buf + 8 >> 2] = stat.ino; - HEAP32[buf + 12 >> 2] = stat.mode; - HEAP32[buf + 16 >> 2] = stat.nlink; - HEAP32[buf + 20 >> 2] = stat.uid; - HEAP32[buf + 24 >> 2] = stat.gid; - HEAP32[buf + 28 >> 2] = stat.rdev; - HEAP32[buf + 32 >> 2] = 0; - tempI64 = [stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1]; - HEAP32[buf + 48 >> 2] = 4096; - HEAP32[buf + 52 >> 2] = stat.blocks; - HEAP32[buf + 56 >> 2] = stat.atime.getTime() / 1e3 | 0; - HEAP32[buf + 60 >> 2] = 0; - HEAP32[buf + 64 >> 2] = stat.mtime.getTime() / 1e3 | 0; - HEAP32[buf + 68 >> 2] = 0; - HEAP32[buf + 72 >> 2] = stat.ctime.getTime() / 1e3 | 0; - HEAP32[buf + 76 >> 2] = 0; - tempI64 = [stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 80 >> 2] = tempI64[0], HEAP32[buf + 84 >> 2] = tempI64[1]; - return 0 - }, - doMsync: function(addr, stream, len, flags, offset) { - var buffer = HEAPU8.slice(addr, addr + len); - FS.msync(stream, buffer, offset, len, flags) - }, - doMkdir: function(path, mode) { - path = PATH.normalize(path); - if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1); - FS.mkdir(path, mode, 0); - return 0 - }, - doMknod: function(path, mode, dev) { - switch (mode & 61440) { - case 32768: - case 8192: - case 24576: - case 4096: - case 49152: - break; - default: - return -28 - } - FS.mknod(path, mode, dev); - return 0 - }, - doReadlink: function(path, buf, bufsize) { - if (bufsize <= 0) return -28; - var ret = FS.readlink(path); - var len = Math.min(bufsize, lengthBytesUTF8(ret)); - var endChar = HEAP8[buf + len]; - stringToUTF8(ret, buf, bufsize + 1); - HEAP8[buf + len] = endChar; - return len - }, - doAccess: function(path, amode) { - if (amode & ~7) { - return -28 - } - var node; - var lookup = FS.lookupPath(path, { - follow: true - }); - node = lookup.node; - if (!node) { - return -44 - } - var perms = ""; - if (amode & 4) perms += "r"; - if (amode & 2) perms += "w"; - if (amode & 1) perms += "x"; - if (perms && FS.nodePermissions(node, perms)) { - return -2 - } + HEAP32[buf + 12 >> 2] = stat.mode; + HEAPU32[buf + 16 >> 2] = stat.nlink; + HEAP32[buf + 20 >> 2] = stat.uid; + HEAP32[buf + 24 >> 2] = stat.gid; + HEAP32[buf + 28 >> 2] = stat.rdev; + tempI64 = [stat.size >>> 0, (tempDouble = stat.size, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 40 >> 2] = tempI64[0], HEAP32[buf + 44 >> 2] = tempI64[1]; + HEAP32[buf + 48 >> 2] = 4096; + HEAP32[buf + 52 >> 2] = stat.blocks; + var atime = stat.atime.getTime(); + var mtime = stat.mtime.getTime(); + var ctime = stat.ctime.getTime(); + tempI64 = [Math.floor(atime / 1e3) >>> 0, (tempDouble = Math.floor(atime / 1e3), +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 56 >> 2] = tempI64[0], HEAP32[buf + 60 >> 2] = tempI64[1]; + HEAPU32[buf + 64 >> 2] = atime % 1e3 * 1e3; + tempI64 = [Math.floor(mtime / 1e3) >>> 0, (tempDouble = Math.floor(mtime / 1e3), +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 72 >> 2] = tempI64[0], HEAP32[buf + 76 >> 2] = tempI64[1]; + HEAPU32[buf + 80 >> 2] = mtime % 1e3 * 1e3; + tempI64 = [Math.floor(ctime / 1e3) >>> 0, (tempDouble = Math.floor(ctime / 1e3), +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 88 >> 2] = tempI64[0], HEAP32[buf + 92 >> 2] = tempI64[1]; + HEAPU32[buf + 96 >> 2] = ctime % 1e3 * 1e3; + tempI64 = [stat.ino >>> 0, (tempDouble = stat.ino, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[buf + 104 >> 2] = tempI64[0], HEAP32[buf + 108 >> 2] = tempI64[1]; return 0 }, - doDup: function(path, flags, suggestFD) { - var suggest = FS.getStream(suggestFD); - if (suggest) FS.close(suggest); - return FS.open(path, flags, 0, suggestFD, suggestFD).fd - }, - doReadv: function(stream, iov, iovcnt, offset) { - var ret = 0; - for (var i = 0; i < iovcnt; i++) { - var ptr = HEAP32[iov + i * 8 >> 2]; - var len = HEAP32[iov + (i * 8 + 4) >> 2]; - var curr = FS.read(stream, HEAP8, ptr, len, offset); - if (curr < 0) return -1; - ret += curr; - if (curr < len) break + doMsync: function(addr, stream, len, flags, offset) { + if (!FS.isFile(stream.node.mode)) { + throw new FS.ErrnoError(43) } - return ret - }, - doWritev: function(stream, iov, iovcnt, offset) { - var ret = 0; - for (var i = 0; i < iovcnt; i++) { - var ptr = HEAP32[iov + i * 8 >> 2]; - var len = HEAP32[iov + (i * 8 + 4) >> 2]; - var curr = FS.write(stream, HEAP8, ptr, len, offset); - if (curr < 0) return -1; - ret += curr + if (flags & 2) { + return 0 } - return ret + var buffer = HEAPU8.slice(addr, addr + len); + FS.msync(stream, buffer, offset, len, flags) }, varargs: undefined, get: function() { @@ -1441,9 +1346,6 @@ var TreeSitter = function() { var stream = FS.getStream(fd); if (!stream) throw new FS.ErrnoError(8); return stream - }, - get64: function(low, high) { - return low } }; @@ -1453,48 +1355,60 @@ var TreeSitter = function() { FS.close(stream); return 0 } catch (e) { - if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e); + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno } } _fd_close.sig = "ii"; + function convertI32PairToI53Checked(lo, hi) { + return hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN + } + function _fd_seek(fd, offset_low, offset_high, whence, newOffset) { try { + var offset = convertI32PairToI53Checked(offset_low, offset_high); + if (isNaN(offset)) return 61; var stream = SYSCALLS.getStreamFromFD(fd); - var HIGH_OFFSET = 4294967296; - var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0); - var DOUBLE_LIMIT = 9007199254740992; - if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) { - return -61 - } FS.llseek(stream, offset, whence); tempI64 = [stream.position >>> 0, (tempDouble = stream.position, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1]; if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; return 0 } catch (e) { - if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e); + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno } } + _fd_seek.sig = "iijip"; + + function doWritev(stream, iov, iovcnt, offset) { + var ret = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[iov >> 2]; + var len = HEAPU32[iov + 4 >> 2]; + iov += 8; + var curr = FS.write(stream, HEAP8, ptr, len, offset); + if (curr < 0) return -1; + ret += curr; + if (typeof offset !== "undefined") { + offset += curr + } + } + return ret + } function _fd_write(fd, iov, iovcnt, pnum) { try { var stream = SYSCALLS.getStreamFromFD(fd); - var num = SYSCALLS.doWritev(stream, iov, iovcnt); - HEAP32[pnum >> 2] = num; + var num = doWritev(stream, iov, iovcnt); + HEAPU32[pnum >> 2] = num; return 0 } catch (e) { - if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e); + if (typeof FS == "undefined" || !(e.name === "ErrnoError")) throw e; return e.errno } } - _fd_write.sig = "iiiii"; - - function _setTempRet0(val) { - setTempRet0(val) - } - _setTempRet0.sig = "vi"; + _fd_write.sig = "iippp"; function _tree_sitter_log_callback(isLexMessage, messageAddress) { if (currentLogCallback) { @@ -1516,30 +1430,141 @@ var TreeSitter = function() { setValue(lengthAddress, 0, "i32") } } - var ___memory_base = 1024; - var ___table_base = 1; - var asmLibraryArg = { + + function _proc_exit(code) { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + if (Module["onExit"]) Module["onExit"](code); + ABORT = true + } + quit_(code, new ExitStatus(code)) + } + _proc_exit.sig = "vi"; + + function exitJS(status, implicit) { + EXITSTATUS = status; + _proc_exit(status) + } + + function handleException(e) { + if (e instanceof ExitStatus || e == "unwind") { + return EXITSTATUS + } + quit_(1, e) + } + + function lengthBytesUTF8(str) { + var len = 0; + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); + if (c <= 127) { + len++ + } else if (c <= 2047) { + len += 2 + } else if (c >= 55296 && c <= 57343) { + len += 4; + ++i + } else { + len += 3 + } + } + return len + } + + function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) { + if (!(maxBytesToWrite > 0)) return 0; + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; + for (var i = 0; i < str.length; ++i) { + var u = str.charCodeAt(i); + if (u >= 55296 && u <= 57343) { + var u1 = str.charCodeAt(++i); + u = 65536 + ((u & 1023) << 10) | u1 & 1023 + } + if (u <= 127) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u + } else if (u <= 2047) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 192 | u >> 6; + heap[outIdx++] = 128 | u & 63 + } else if (u <= 65535) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 224 | u >> 12; + heap[outIdx++] = 128 | u >> 6 & 63; + heap[outIdx++] = 128 | u & 63 + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 240 | u >> 18; + heap[outIdx++] = 128 | u >> 12 & 63; + heap[outIdx++] = 128 | u >> 6 & 63; + heap[outIdx++] = 128 | u & 63 + } + } + heap[outIdx] = 0; + return outIdx - startIdx + } + + function stringToUTF8(str, outPtr, maxBytesToWrite) { + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite) + } + + function stringToUTF8OnStack(str) { + var size = lengthBytesUTF8(str) + 1; + var ret = stackAlloc(size); + stringToUTF8(str, ret, size); + return ret + } + + function stringToUTF16(str, outPtr, maxBytesToWrite) { + if (maxBytesToWrite === undefined) { + maxBytesToWrite = 2147483647 + } + if (maxBytesToWrite < 2) return 0; + maxBytesToWrite -= 2; + var startPtr = outPtr; + var numCharsToWrite = maxBytesToWrite < str.length * 2 ? maxBytesToWrite / 2 : str.length; + for (var i = 0; i < numCharsToWrite; ++i) { + var codeUnit = str.charCodeAt(i); + HEAP16[outPtr >> 1] = codeUnit; + outPtr += 2 + } + HEAP16[outPtr >> 1] = 0; + return outPtr - startPtr + } + + function AsciiToString(ptr) { + var str = ""; + while (1) { + var ch = HEAPU8[ptr++ >> 0]; + if (!ch) return str; + str += String.fromCharCode(ch) + } + } + var wasmImports = { "__heap_base": ___heap_base, "__indirect_function_table": wasmTable, "__memory_base": ___memory_base, "__stack_pointer": ___stack_pointer, "__table_base": ___table_base, + "_emscripten_get_now_is_monotonic": __emscripten_get_now_is_monotonic, "abort": _abort, - "clock_gettime": _clock_gettime, + "emscripten_get_now": _emscripten_get_now, "emscripten_memcpy_big": _emscripten_memcpy_big, "emscripten_resize_heap": _emscripten_resize_heap, - "exit": _exit, "fd_close": _fd_close, "fd_seek": _fd_seek, "fd_write": _fd_write, "memory": wasmMemory, - "setTempRet0": _setTempRet0, "tree_sitter_log_callback": _tree_sitter_log_callback, "tree_sitter_parse_callback": _tree_sitter_parse_callback }; var asm = createWasm(); - var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() { - return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["__wasm_call_ctors"]).apply(null, arguments) + var ___wasm_call_ctors = function() { + return (___wasm_call_ctors = Module["asm"]["__wasm_call_ctors"]).apply(null, arguments) + }; + var ___wasm_apply_data_relocs = Module["___wasm_apply_data_relocs"] = function() { + return (___wasm_apply_data_relocs = Module["___wasm_apply_data_relocs"] = Module["asm"]["__wasm_apply_data_relocs"]).apply(null, arguments) }; var _malloc = Module["_malloc"] = function() { return (_malloc = Module["_malloc"] = Module["asm"]["malloc"]).apply(null, arguments) @@ -1556,12 +1581,18 @@ var TreeSitter = function() { var _ts_language_symbol_count = Module["_ts_language_symbol_count"] = function() { return (_ts_language_symbol_count = Module["_ts_language_symbol_count"] = Module["asm"]["ts_language_symbol_count"]).apply(null, arguments) }; + var _ts_language_state_count = Module["_ts_language_state_count"] = function() { + return (_ts_language_state_count = Module["_ts_language_state_count"] = Module["asm"]["ts_language_state_count"]).apply(null, arguments) + }; var _ts_language_version = Module["_ts_language_version"] = function() { return (_ts_language_version = Module["_ts_language_version"] = Module["asm"]["ts_language_version"]).apply(null, arguments) }; var _ts_language_field_count = Module["_ts_language_field_count"] = function() { return (_ts_language_field_count = Module["_ts_language_field_count"] = Module["asm"]["ts_language_field_count"]).apply(null, arguments) }; + var _ts_language_next_state = Module["_ts_language_next_state"] = function() { + return (_ts_language_next_state = Module["_ts_language_next_state"] = Module["asm"]["ts_language_next_state"]).apply(null, arguments) + }; var _ts_language_symbol_name = Module["_ts_language_symbol_name"] = function() { return (_ts_language_symbol_name = Module["_ts_language_symbol_name"] = Module["asm"]["ts_language_symbol_name"]).apply(null, arguments) }; @@ -1577,6 +1608,24 @@ var TreeSitter = function() { var _ts_language_field_name_for_id = Module["_ts_language_field_name_for_id"] = function() { return (_ts_language_field_name_for_id = Module["_ts_language_field_name_for_id"] = Module["asm"]["ts_language_field_name_for_id"]).apply(null, arguments) }; + var _ts_lookahead_iterator_new = Module["_ts_lookahead_iterator_new"] = function() { + return (_ts_lookahead_iterator_new = Module["_ts_lookahead_iterator_new"] = Module["asm"]["ts_lookahead_iterator_new"]).apply(null, arguments) + }; + var _ts_lookahead_iterator_delete = Module["_ts_lookahead_iterator_delete"] = function() { + return (_ts_lookahead_iterator_delete = Module["_ts_lookahead_iterator_delete"] = Module["asm"]["ts_lookahead_iterator_delete"]).apply(null, arguments) + }; + var _ts_lookahead_iterator_reset_state = Module["_ts_lookahead_iterator_reset_state"] = function() { + return (_ts_lookahead_iterator_reset_state = Module["_ts_lookahead_iterator_reset_state"] = Module["asm"]["ts_lookahead_iterator_reset_state"]).apply(null, arguments) + }; + var _ts_lookahead_iterator_reset = Module["_ts_lookahead_iterator_reset"] = function() { + return (_ts_lookahead_iterator_reset = Module["_ts_lookahead_iterator_reset"] = Module["asm"]["ts_lookahead_iterator_reset"]).apply(null, arguments) + }; + var _ts_lookahead_iterator_next = Module["_ts_lookahead_iterator_next"] = function() { + return (_ts_lookahead_iterator_next = Module["_ts_lookahead_iterator_next"] = Module["asm"]["ts_lookahead_iterator_next"]).apply(null, arguments) + }; + var _ts_lookahead_iterator_current_symbol = Module["_ts_lookahead_iterator_current_symbol"] = function() { + return (_ts_lookahead_iterator_current_symbol = Module["_ts_lookahead_iterator_current_symbol"] = Module["asm"]["ts_lookahead_iterator_current_symbol"]).apply(null, arguments) + }; var _memset = Module["_memset"] = function() { return (_memset = Module["_memset"] = Module["asm"]["memset"]).apply(null, arguments) }; @@ -1676,18 +1725,30 @@ var TreeSitter = function() { var _ts_tree_cursor_reset_wasm = Module["_ts_tree_cursor_reset_wasm"] = function() { return (_ts_tree_cursor_reset_wasm = Module["_ts_tree_cursor_reset_wasm"] = Module["asm"]["ts_tree_cursor_reset_wasm"]).apply(null, arguments) }; + var _ts_tree_cursor_reset_to_wasm = Module["_ts_tree_cursor_reset_to_wasm"] = function() { + return (_ts_tree_cursor_reset_to_wasm = Module["_ts_tree_cursor_reset_to_wasm"] = Module["asm"]["ts_tree_cursor_reset_to_wasm"]).apply(null, arguments) + }; var _ts_tree_cursor_goto_first_child_wasm = Module["_ts_tree_cursor_goto_first_child_wasm"] = function() { return (_ts_tree_cursor_goto_first_child_wasm = Module["_ts_tree_cursor_goto_first_child_wasm"] = Module["asm"]["ts_tree_cursor_goto_first_child_wasm"]).apply(null, arguments) }; + var _ts_tree_cursor_goto_last_child_wasm = Module["_ts_tree_cursor_goto_last_child_wasm"] = function() { + return (_ts_tree_cursor_goto_last_child_wasm = Module["_ts_tree_cursor_goto_last_child_wasm"] = Module["asm"]["ts_tree_cursor_goto_last_child_wasm"]).apply(null, arguments) + }; var _ts_tree_cursor_goto_next_sibling_wasm = Module["_ts_tree_cursor_goto_next_sibling_wasm"] = function() { return (_ts_tree_cursor_goto_next_sibling_wasm = Module["_ts_tree_cursor_goto_next_sibling_wasm"] = Module["asm"]["ts_tree_cursor_goto_next_sibling_wasm"]).apply(null, arguments) }; + var _ts_tree_cursor_goto_previous_sibling_wasm = Module["_ts_tree_cursor_goto_previous_sibling_wasm"] = function() { + return (_ts_tree_cursor_goto_previous_sibling_wasm = Module["_ts_tree_cursor_goto_previous_sibling_wasm"] = Module["asm"]["ts_tree_cursor_goto_previous_sibling_wasm"]).apply(null, arguments) + }; var _ts_tree_cursor_goto_parent_wasm = Module["_ts_tree_cursor_goto_parent_wasm"] = function() { return (_ts_tree_cursor_goto_parent_wasm = Module["_ts_tree_cursor_goto_parent_wasm"] = Module["asm"]["ts_tree_cursor_goto_parent_wasm"]).apply(null, arguments) }; var _ts_tree_cursor_current_node_type_id_wasm = Module["_ts_tree_cursor_current_node_type_id_wasm"] = function() { return (_ts_tree_cursor_current_node_type_id_wasm = Module["_ts_tree_cursor_current_node_type_id_wasm"] = Module["asm"]["ts_tree_cursor_current_node_type_id_wasm"]).apply(null, arguments) }; + var _ts_tree_cursor_current_node_state_id_wasm = Module["_ts_tree_cursor_current_node_state_id_wasm"] = function() { + return (_ts_tree_cursor_current_node_state_id_wasm = Module["_ts_tree_cursor_current_node_state_id_wasm"] = Module["asm"]["ts_tree_cursor_current_node_state_id_wasm"]).apply(null, arguments) + }; var _ts_tree_cursor_current_node_is_named_wasm = Module["_ts_tree_cursor_current_node_is_named_wasm"] = function() { return (_ts_tree_cursor_current_node_is_named_wasm = Module["_ts_tree_cursor_current_node_is_named_wasm"] = Module["asm"]["ts_tree_cursor_current_node_is_named_wasm"]).apply(null, arguments) }; @@ -1718,6 +1779,12 @@ var TreeSitter = function() { var _ts_node_symbol_wasm = Module["_ts_node_symbol_wasm"] = function() { return (_ts_node_symbol_wasm = Module["_ts_node_symbol_wasm"] = Module["asm"]["ts_node_symbol_wasm"]).apply(null, arguments) }; + var _ts_node_field_name_for_child_wasm = Module["_ts_node_field_name_for_child_wasm"] = function() { + return (_ts_node_field_name_for_child_wasm = Module["_ts_node_field_name_for_child_wasm"] = Module["asm"]["ts_node_field_name_for_child_wasm"]).apply(null, arguments) + }; + var _ts_node_grammar_symbol_wasm = Module["_ts_node_grammar_symbol_wasm"] = function() { + return (_ts_node_grammar_symbol_wasm = Module["_ts_node_grammar_symbol_wasm"] = Module["asm"]["ts_node_grammar_symbol_wasm"]).apply(null, arguments) + }; var _ts_node_child_count_wasm = Module["_ts_node_child_count_wasm"] = function() { return (_ts_node_child_count_wasm = Module["_ts_node_child_count_wasm"] = Module["asm"]["ts_node_child_count_wasm"]).apply(null, arguments) }; @@ -1793,44 +1860,59 @@ var TreeSitter = function() { var _ts_node_has_error_wasm = Module["_ts_node_has_error_wasm"] = function() { return (_ts_node_has_error_wasm = Module["_ts_node_has_error_wasm"] = Module["asm"]["ts_node_has_error_wasm"]).apply(null, arguments) }; + var _ts_node_is_error_wasm = Module["_ts_node_is_error_wasm"] = function() { + return (_ts_node_is_error_wasm = Module["_ts_node_is_error_wasm"] = Module["asm"]["ts_node_is_error_wasm"]).apply(null, arguments) + }; var _ts_node_is_missing_wasm = Module["_ts_node_is_missing_wasm"] = function() { return (_ts_node_is_missing_wasm = Module["_ts_node_is_missing_wasm"] = Module["asm"]["ts_node_is_missing_wasm"]).apply(null, arguments) }; + var _ts_node_parse_state_wasm = Module["_ts_node_parse_state_wasm"] = function() { + return (_ts_node_parse_state_wasm = Module["_ts_node_parse_state_wasm"] = Module["asm"]["ts_node_parse_state_wasm"]).apply(null, arguments) + }; + var _ts_node_next_parse_state_wasm = Module["_ts_node_next_parse_state_wasm"] = function() { + return (_ts_node_next_parse_state_wasm = Module["_ts_node_next_parse_state_wasm"] = Module["asm"]["ts_node_next_parse_state_wasm"]).apply(null, arguments) + }; var _ts_query_matches_wasm = Module["_ts_query_matches_wasm"] = function() { return (_ts_query_matches_wasm = Module["_ts_query_matches_wasm"] = Module["asm"]["ts_query_matches_wasm"]).apply(null, arguments) }; var _ts_query_captures_wasm = Module["_ts_query_captures_wasm"] = function() { return (_ts_query_captures_wasm = Module["_ts_query_captures_wasm"] = Module["asm"]["ts_query_captures_wasm"]).apply(null, arguments) }; + var ___cxa_atexit = Module["___cxa_atexit"] = function() { + return (___cxa_atexit = Module["___cxa_atexit"] = Module["asm"]["__cxa_atexit"]).apply(null, arguments) + }; + var ___errno_location = function() { + return (___errno_location = Module["asm"]["__errno_location"]).apply(null, arguments) + }; + var _isalnum = Module["_isalnum"] = function() { + return (_isalnum = Module["_isalnum"] = Module["asm"]["isalnum"]).apply(null, arguments) + }; + var _isalpha = Module["_isalpha"] = function() { + return (_isalpha = Module["_isalpha"] = Module["asm"]["isalpha"]).apply(null, arguments) + }; + var _isspace = Module["_isspace"] = function() { + return (_isspace = Module["_isspace"] = Module["asm"]["isspace"]).apply(null, arguments) + }; var _iswdigit = Module["_iswdigit"] = function() { return (_iswdigit = Module["_iswdigit"] = Module["asm"]["iswdigit"]).apply(null, arguments) }; var _iswalpha = Module["_iswalpha"] = function() { return (_iswalpha = Module["_iswalpha"] = Module["asm"]["iswalpha"]).apply(null, arguments) }; - var _iswupper = Module["_iswupper"] = function() { - return (_iswupper = Module["_iswupper"] = Module["asm"]["iswupper"]).apply(null, arguments) + var _iswblank = Module["_iswblank"] = function() { + return (_iswblank = Module["_iswblank"] = Module["asm"]["iswblank"]).apply(null, arguments) }; var _iswlower = Module["_iswlower"] = function() { return (_iswlower = Module["_iswlower"] = Module["asm"]["iswlower"]).apply(null, arguments) }; + var _iswupper = Module["_iswupper"] = function() { + return (_iswupper = Module["_iswupper"] = Module["asm"]["iswupper"]).apply(null, arguments) + }; var _iswxdigit = Module["_iswxdigit"] = function() { return (_iswxdigit = Module["_iswxdigit"] = Module["asm"]["iswxdigit"]).apply(null, arguments) }; - var _towupper = Module["_towupper"] = function() { - return (_towupper = Module["_towupper"] = Module["asm"]["towupper"]).apply(null, arguments) - }; - var _towlower = Module["_towlower"] = function() { - return (_towlower = Module["_towlower"] = Module["asm"]["towlower"]).apply(null, arguments) - }; - var _isalpha = Module["_isalpha"] = function() { - return (_isalpha = Module["_isalpha"] = Module["asm"]["isalpha"]).apply(null, arguments) - }; - var _isalnum = Module["_isalnum"] = function() { - return (_isalnum = Module["_isalnum"] = Module["asm"]["isalnum"]).apply(null, arguments) - }; - var ___errno_location = Module["___errno_location"] = function() { - return (___errno_location = Module["___errno_location"] = Module["asm"]["__errno_location"]).apply(null, arguments) + var _isxdigit = Module["_isxdigit"] = function() { + return (_isxdigit = Module["_isxdigit"] = Module["asm"]["isxdigit"]).apply(null, arguments) }; var _memchr = Module["_memchr"] = function() { return (_memchr = Module["_memchr"] = Module["asm"]["memchr"]).apply(null, arguments) @@ -1844,17 +1926,32 @@ var TreeSitter = function() { var _strncpy = Module["_strncpy"] = function() { return (_strncpy = Module["_strncpy"] = Module["asm"]["strncpy"]).apply(null, arguments) }; - var stackSave = Module["stackSave"] = function() { - return (stackSave = Module["stackSave"] = Module["asm"]["stackSave"]).apply(null, arguments) + var _tolower = Module["_tolower"] = function() { + return (_tolower = Module["_tolower"] = Module["asm"]["tolower"]).apply(null, arguments) + }; + var _towlower = Module["_towlower"] = function() { + return (_towlower = Module["_towlower"] = Module["asm"]["towlower"]).apply(null, arguments) + }; + var _towupper = Module["_towupper"] = function() { + return (_towupper = Module["_towupper"] = Module["asm"]["towupper"]).apply(null, arguments) + }; + var _setThrew = function() { + return (_setThrew = Module["asm"]["setThrew"]).apply(null, arguments) + }; + var stackSave = function() { + return (stackSave = Module["asm"]["stackSave"]).apply(null, arguments) + }; + var stackRestore = function() { + return (stackRestore = Module["asm"]["stackRestore"]).apply(null, arguments) }; - var stackRestore = Module["stackRestore"] = function() { - return (stackRestore = Module["stackRestore"] = Module["asm"]["stackRestore"]).apply(null, arguments) + var stackAlloc = function() { + return (stackAlloc = Module["asm"]["stackAlloc"]).apply(null, arguments) }; - var stackAlloc = Module["stackAlloc"] = function() { - return (stackAlloc = Module["stackAlloc"] = Module["asm"]["stackAlloc"]).apply(null, arguments) + var __Znwm = Module["__Znwm"] = function() { + return (__Znwm = Module["__Znwm"] = Module["asm"]["_Znwm"]).apply(null, arguments) }; - var _setThrew = Module["_setThrew"] = function() { - return (_setThrew = Module["_setThrew"] = Module["asm"]["setThrew"]).apply(null, arguments) + var __ZdlPv = Module["__ZdlPv"] = function() { + return (__ZdlPv = Module["__ZdlPv"] = Module["asm"]["_ZdlPv"]).apply(null, arguments) }; var __ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev = Module["__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev"] = function() { return (__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev = Module["__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev"] = Module["asm"]["_ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev"]).apply(null, arguments) @@ -1886,11 +1983,8 @@ var TreeSitter = function() { var __ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw = Module["__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw"] = function() { return (__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw = Module["__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw"] = Module["asm"]["_ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw"]).apply(null, arguments) }; - var __Znwm = Module["__Znwm"] = function() { - return (__Znwm = Module["__Znwm"] = Module["asm"]["_Znwm"]).apply(null, arguments) - }; - var __ZdlPv = Module["__ZdlPv"] = function() { - return (__ZdlPv = Module["__ZdlPv"] = Module["asm"]["_ZdlPv"]).apply(null, arguments) + var __ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw = Module["__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw"] = function() { + return (__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw = Module["__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw"] = Module["asm"]["_ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw"]).apply(null, arguments) }; var dynCall_jiji = Module["dynCall_jiji"] = function() { return (dynCall_jiji = Module["dynCall_jiji"] = Module["asm"]["dynCall_jiji"]).apply(null, arguments) @@ -1901,60 +1995,43 @@ var TreeSitter = function() { var _orig$ts_parser_set_timeout_micros = Module["_orig$ts_parser_set_timeout_micros"] = function() { return (_orig$ts_parser_set_timeout_micros = Module["_orig$ts_parser_set_timeout_micros"] = Module["asm"]["orig$ts_parser_set_timeout_micros"]).apply(null, arguments) }; - Module["allocate"] = allocate; + var _stderr = Module["_stderr"] = 11824; + Module["AsciiToString"] = AsciiToString; + Module["stringToUTF16"] = stringToUTF16; var calledRun; - - function ExitStatus(status) { - this.name = "ExitStatus"; - this.message = "Program terminated with exit(" + status + ")"; - this.status = status - } - var calledMain = false; dependenciesFulfilled = function runCaller() { if (!calledRun) run(); if (!calledRun) dependenciesFulfilled = runCaller }; - function callMain(args) { - var entryFunction = Module["_main"]; + function callMain(args = []) { + var entryFunction = resolveGlobalSymbol("main").sym; if (!entryFunction) return; - args = args || []; - var argc = args.length + 1; + args.unshift(thisProgram); + var argc = args.length; var argv = stackAlloc((argc + 1) * 4); - HEAP32[argv >> 2] = allocateUTF8OnStack(thisProgram); - for (var i = 1; i < argc; i++) { - HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]) - } - HEAP32[(argv >> 2) + argc] = 0; + var argv_ptr = argv >> 2; + args.forEach(arg => { + HEAP32[argv_ptr++] = stringToUTF8OnStack(arg) + }); + HEAP32[argv_ptr] = 0; try { var ret = entryFunction(argc, argv); - exit(ret, true) + exitJS(ret, true); + return ret } catch (e) { - if (e instanceof ExitStatus) { - return - } else if (e == "unwind") { - return - } else { - var toLog = e; - if (e && typeof e === "object" && e.stack) { - toLog = [e, e.stack] - } - err("exception thrown: " + toLog); - quit_(1, e) - } - } finally { - calledMain = true + return handleException(e) } } var dylibsLoaded = false; + LDSO.init(); - function run(args) { - args = args || arguments_; + function run(args = arguments_) { if (runDependencies > 0) { return } if (!dylibsLoaded) { - preloadDylibs(); + loadDylibs(); dylibsLoaded = true; if (runDependencies > 0) { return @@ -1988,20 +2065,6 @@ var TreeSitter = function() { doRun() } } - Module["run"] = run; - - function exit(status, implicit) { - EXITSTATUS = status; - if (implicit && keepRuntimeAlive() && status === 0) { - return - } - if (keepRuntimeAlive()) {} else { - exitRuntime(); - if (Module["onExit"]) Module["onExit"](status); - ABORT = true - } - quit_(status, new ExitStatus(status)) - } if (Module["preInit"]) { if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]]; while (Module["preInit"].length > 0) { @@ -2014,6 +2077,7 @@ var TreeSitter = function() { const C = Module; const INTERNAL = {}; const SIZE_OF_INT = 4; + const SIZE_OF_CURSOR = 3 * SIZE_OF_INT; const SIZE_OF_NODE = 5 * SIZE_OF_INT; const SIZE_OF_POINT = 2 * SIZE_OF_INT; const SIZE_OF_RANGE = 2 * SIZE_OF_INT + 2 * SIZE_OF_POINT; @@ -2070,7 +2134,7 @@ var TreeSitter = function() { } parse(callback, oldTree, options) { if (typeof callback === "string") { - currentParseCallback = ((index, _, endIndex) => callback.slice(index, endIndex)) + currentParseCallback = (index, _, endIndex) => callback.slice(index, endIndex) } else if (typeof callback === "function") { currentParseCallback = callback } else { @@ -2184,9 +2248,16 @@ var TreeSitter = function() { marshalNode(this); return C._ts_node_symbol_wasm(this.tree[0]) } + get grammarId() { + marshalNode(this); + return C._ts_node_grammar_symbol_wasm(this.tree[0]) + } get type() { return this.tree.language.types[this.typeId] || "ERROR" } + get grammarType() { + return this.tree.language.types[this.grammarId] || "ERROR" + } get endPosition() { marshalNode(this); C._ts_node_end_point_wasm(this.tree[0]); @@ -2199,6 +2270,14 @@ var TreeSitter = function() { get text() { return getText(this.tree, this.startIndex, this.endIndex) } + get parseState() { + marshalNode(this); + return C._ts_node_parse_state_wasm(this.tree[0]) + } + get nextParseState() { + marshalNode(this); + return C._ts_node_next_parse_state_wasm(this.tree[0]) + } isNamed() { marshalNode(this); return C._ts_node_is_named_wasm(this.tree[0]) === 1 @@ -2211,6 +2290,10 @@ var TreeSitter = function() { marshalNode(this); return C._ts_node_has_changes_wasm(this.tree[0]) === 1 } + isError() { + marshalNode(this); + return C._ts_node_is_error_wasm(this.tree[0]) === 1 + } isMissing() { marshalNode(this); return C._ts_node_is_missing_wasm(this.tree[0]) === 1 @@ -2223,6 +2306,15 @@ var TreeSitter = function() { C._ts_node_child_wasm(this.tree[0], index); return unmarshalNode(this.tree) } + fieldNameForChild(index) { + marshalNode(this); + const address = C._ts_node_field_name_for_child_wasm(this.tree[0], index); + if (!address) { + return null + } + const result = AsciiToString(address); + return result + } namedChild(index) { marshalNode(this); C._ts_node_named_child_wasm(this.tree[0], index); @@ -2423,6 +2515,12 @@ var TreeSitter = function() { C._ts_tree_cursor_reset_wasm(this.tree[0]); unmarshalTreeCursor(this) } + resetTo(cursor) { + marshalTreeCursor(this, TRANSFER_BUFFER); + marshalTreeCursor(cursor, TRANSFER_BUFFER + SIZE_OF_CURSOR); + C._ts_tree_cursor_reset_to_wasm(this.tree[0], cursor.tree[0]); + unmarshalTreeCursor(this) + } get nodeType() { return this.tree.language.types[this.nodeTypeId] || "ERROR" } @@ -2430,6 +2528,10 @@ var TreeSitter = function() { marshalTreeCursor(this); return C._ts_tree_cursor_current_node_type_id_wasm(this.tree[0]) } + get nodeStateId() { + marshalTreeCursor(this); + return C._ts_tree_cursor_current_node_state_id_wasm(this.tree[0]) + } get nodeId() { marshalTreeCursor(this); return C._ts_tree_cursor_current_node_id_wasm(this.tree[0]) @@ -2484,12 +2586,24 @@ var TreeSitter = function() { unmarshalTreeCursor(this); return result === 1 } + gotoLastChild() { + marshalTreeCursor(this); + const result = C._ts_tree_cursor_goto_last_child_wasm(this.tree[0]); + unmarshalTreeCursor(this); + return result === 1 + } gotoNextSibling() { marshalTreeCursor(this); const result = C._ts_tree_cursor_goto_next_sibling_wasm(this.tree[0]); unmarshalTreeCursor(this); return result === 1 } + gotoPreviousSibling() { + marshalTreeCursor(this); + const result = C._ts_tree_cursor_goto_previous_sibling_wasm(this.tree[0]); + unmarshalTreeCursor(this); + return result === 1 + } gotoParent() { marshalTreeCursor(this); const result = C._ts_tree_cursor_goto_parent_wasm(this.tree[0]); @@ -2523,6 +2637,9 @@ var TreeSitter = function() { get fieldCount() { return this.fields.length - 1 } + get stateCount() { + return C._ts_language_state_count(this[0]) + } fieldIdForName(fieldName) { const result = this.fields.indexOf(fieldName); if (result !== -1) { @@ -2555,6 +2672,13 @@ var TreeSitter = function() { nodeTypeIsVisible(typeId) { return C._ts_language_type_is_visible_wasm(this[0], typeId) ? true : false } + nextState(stateId, typeId) { + return C._ts_language_next_state(this[0], stateId, typeId) + } + lookaheadIterator(stateId) { + const address = C._ts_lookahead_iterator_new(this[0], stateId); + if (address) return new LookaheadIterable(INTERNAL, address, this) + } query(source) { const sourceLength = lengthBytesUTF8(source); const sourceAddress = C._malloc(sourceLength + 1); @@ -2639,50 +2763,68 @@ var TreeSitter = function() { } const operator = steps[0].value; let isPositive = true; + let matchAll = true; + let captureName; switch (operator) { + case "any-not-eq?": case "not-eq?": isPositive = false; + case "any-eq?": case "eq?": - if (steps.length !== 3) throw new Error(`Wrong number of arguments to \`#eq?\` predicate. Expected 2, got ${steps.length-1}`); - if (steps[1].type !== "capture") throw new Error(`First argument of \`#eq?\` predicate must be a capture. Got "${steps[1].value}"`); + if (steps.length !== 3) throw new Error(`Wrong number of arguments to \`#${operator}\` predicate. Expected 2, got ${steps.length-1}`); + if (steps[1].type !== "capture") throw new Error(`First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}"`); + matchAll = !operator.startsWith("any-"); if (steps[2].type === "capture") { const captureName1 = steps[1].name; const captureName2 = steps[2].name; textPredicates[i].push(function(captures) { - let node1, node2; + let nodes_1 = []; + let nodes_2 = []; for (const c of captures) { - if (c.name === captureName1) node1 = c.node; - if (c.name === captureName2) node2 = c.node + if (c.name === captureName1) nodes_1.push(c.node); + if (c.name === captureName2) nodes_2.push(c.node) } - if (node1 === undefined || node2 === undefined) return true; - return node1.text === node2.text === isPositive + let compare = (n1, n2, positive) => { + return positive ? n1.text === n2.text : n1.text !== n2.text + }; + return matchAll ? nodes_1.every(n1 => nodes_2.some(n2 => compare(n1, n2, isPositive))) : nodes_1.some(n1 => nodes_2.some(n2 => compare(n1, n2, isPositive))) }) } else { - const captureName = steps[1].name; + captureName = steps[1].name; const stringValue = steps[2].value; + let matches = n => n.text === stringValue; + let doesNotMatch = n => n.text !== stringValue; textPredicates[i].push(function(captures) { + let nodes = []; for (const c of captures) { - if (c.name === captureName) { - return c.node.text === stringValue === isPositive - } + if (c.name === captureName) nodes.push(c.node) } - return true + let test = isPositive ? matches : doesNotMatch; + return matchAll ? nodes.every(test) : nodes.some(test) }) } break; + case "any-not-match?": case "not-match?": isPositive = false; + case "any-match?": case "match?": - if (steps.length !== 3) throw new Error(`Wrong number of arguments to \`#match?\` predicate. Expected 2, got ${steps.length-1}.`); - if (steps[1].type !== "capture") throw new Error(`First argument of \`#match?\` predicate must be a capture. Got "${steps[1].value}".`); - if (steps[2].type !== "string") throw new Error(`Second argument of \`#match?\` predicate must be a string. Got @${steps[2].value}.`); - const captureName = steps[1].name; + if (steps.length !== 3) throw new Error(`Wrong number of arguments to \`#${operator}\` predicate. Expected 2, got ${steps.length-1}.`); + if (steps[1].type !== "capture") throw new Error(`First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".`); + if (steps[2].type !== "string") throw new Error(`Second argument of \`#${operator}\` predicate must be a string. Got @${steps[2].value}.`); + captureName = steps[1].name; const regex = new RegExp(steps[2].value); + matchAll = !operator.startsWith("any-"); textPredicates[i].push(function(captures) { + const nodes = []; for (const c of captures) { - if (c.name === captureName) return regex.test(c.node.text) === isPositive + if (c.name === captureName) nodes.push(c.node.text) } - return true + let test = (text, positive) => { + return positive ? regex.test(text) : !regex.test(text) + }; + if (nodes.length === 0) return !isPositive; + return matchAll ? nodes.every(text => test(text, isPositive)) : nodes.some(text => test(text, isPositive)) }); break; case "set!": @@ -2699,6 +2841,25 @@ var TreeSitter = function() { if (!properties[i]) properties[i] = {}; properties[i][steps[1].value] = steps[2] ? steps[2].value : null; break; + case "not-any-of?": + isPositive = false; + case "any-of?": + if (steps.length < 2) throw new Error(`Wrong number of arguments to \`#${operator}\` predicate. Expected at least 1. Got ${steps.length-1}.`); + if (steps[1].type !== "capture") throw new Error(`First argument of \`#${operator}\` predicate must be a capture. Got "${steps[1].value}".`); + for (let i = 2; i < steps.length; i++) { + if (steps[i].type !== "string") throw new Error(`Arguments to \`#${operator}\` predicate must be a strings.".`) + } + captureName = steps[1].name; + const values = steps.slice(2).map(s => s.value); + textPredicates[i].push(function(captures) { + const nodes = []; + for (const c of captures) { + if (c.name === captureName) nodes.push(c.node.text) + } + if (nodes.length === 0) return !isPositive; + return nodes.every(text => values.includes(text)) === isPositive + }); + break; default: predicates[i].push({ operator: operator, @@ -2749,6 +2910,49 @@ var TreeSitter = function() { }) } } + class LookaheadIterable { + constructor(internal, address, language) { + assertInternal(internal); + this[0] = address; + this.language = language + } + get currentTypeId() { + return C._ts_lookahead_iterator_current_symbol(this[0]) + } + get currentType() { + return this.language.types[this.currentTypeId] || "ERROR" + } + delete() { + C._ts_lookahead_iterator_delete(this[0]); + this[0] = 0 + } + resetState(stateId) { + return C._ts_lookahead_iterator_reset_state(this[0], stateId) + } + reset(language, stateId) { + if (C._ts_lookahead_iterator_reset(this[0], language[0], stateId)) { + this.language = language; + return true + } + return false + } [Symbol.iterator]() { + const self = this; + return { + next() { + if (C._ts_lookahead_iterator_next(self[0])) { + return { + done: false, + value: self.currentType + } + } + return { + done: true, + value: "" + } + } + } + } + } class Query { constructor(internal, address, captureNames, textPredicates, predicates, setProperties, assertedProperties, refutedProperties) { assertInternal(internal); @@ -3000,10 +3204,10 @@ var TreeSitter = function() { }) } Parser.Language = Language; - Module.onRuntimeInitialized = (() => { + Module.onRuntimeInitialized = () => { ParserImpl.init(); resolveInitPromise() - }) + } }) } } diff --git a/vendor/web-tree-sitter/tree-sitter.wasm b/vendor/web-tree-sitter/tree-sitter.wasm index 56e6db9ac9..51a7b52c2a 100755 Binary files a/vendor/web-tree-sitter/tree-sitter.wasm and b/vendor/web-tree-sitter/tree-sitter.wasm differ