Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tree-sitter fixes for December (including a PHP grammar!) #852

Merged
Merged
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
a8f5b17
[tree-sitter] Fold on type objects in TypeScript
savetheclocktower Dec 18, 2023
a1e9fa0
[tree-sitter] Make the shell grammar's file types match the TM grammar's
savetheclocktower Dec 19, 2023
daf0637
Do the same for the modern Tree-sitter grammar
savetheclocktower Dec 19, 2023
818d204
[tree-sitter] Add the pipe character (`|`) as an operator
savetheclocktower Dec 19, 2023
037377a
[tree-sitter] Ruby fixes…
savetheclocktower Dec 21, 2023
1ed79e2
[tree-sitter] Fix indentation hinting at the edges of injections
savetheclocktower Dec 23, 2023
fdc70fc
[tree-sitter] Highlight an obscure inheritance construct properly in C++
savetheclocktower Dec 23, 2023
20a64bd
Allow `suggestedIndentForBufferRows` to work correctly…
savetheclocktower Dec 23, 2023
be37b26
[tree-sitter] Don't highlight JS default param values like parameters
savetheclocktower Dec 24, 2023
f6bb61f
[tree-sitter] Highlight assertion function clauses in TypeScript
savetheclocktower Dec 25, 2023
da10036
[tree-sitter] Fix JSX dedent logic
savetheclocktower Dec 25, 2023
bc55c4f
[tree-sitter] Further JSX indent fixes for JS and TS alike
savetheclocktower Dec 25, 2023
7b4a50d
(oops)
savetheclocktower Dec 26, 2023
66aea45
[tree-sitter] Fixes for shell script highlighting
savetheclocktower Dec 29, 2023
294134c
[tree-sitter] Highlight private fields similarly to other JS properties
savetheclocktower Jan 2, 2024
ee54d37
[tree-sitter] Highlight TypeScript `infer` clauses properly
savetheclocktower Jan 3, 2024
d6f8a3c
Add a modern Tree-sitter PHP grammar
savetheclocktower Jan 5, 2024
00de52c
Add `parserSource` fields where appropriate
savetheclocktower Jan 5, 2024
1dc1536
Remove logging from injection callback
savetheclocktower Jan 5, 2024
0fd47f5
Skip incorrect CI behavior on changes to `web-tree-sitter` itself
savetheclocktower Jan 5, 2024
ee3f41e
Don't try to parse non-CSON files as CSON
savetheclocktower Jan 5, 2024
3a4b2dc
Handle nowdocs in PHP
savetheclocktower Jan 5, 2024
8ae599f
[tree-sitter] TS: Treat parameters with defaults like parameters…
savetheclocktower Jan 5, 2024
b6d88a5
Update `tree-sitter-php` WASM file to latest `master`
savetheclocktower Jan 5, 2024
18788c0
Address feedback on PHP syntax highlighting
savetheclocktower Jan 8, 2024
f6e1a22
Apply PHPDoc learnings to JSDoc
savetheclocktower Jan 9, 2024
5e62e20
[tree-sitter] Add TODO and hyperlink injections to Java
savetheclocktower Jan 9, 2024
0807dcf
Add TODO and hyperlink injections to Rust
savetheclocktower Jan 9, 2024
bbf4cb4
Add TODO and hyperlink injections to C/C++
savetheclocktower Jan 9, 2024
351493f
Only inject TODO and hyperlink into CSS when needed
savetheclocktower Jan 9, 2024
bf039cc
Don't add root scopes to CSS for TODO/hyperlink injections
savetheclocktower Jan 9, 2024
ebd0ae0
Add TODO and hyperlink injections to Go
savetheclocktower Jan 9, 2024
e2da555
Add hyperlink injection to JSON
savetheclocktower Jan 9, 2024
70b34cd
Add TODO and hyperlink injections to YAML comments
savetheclocktower Jan 9, 2024
a40bae4
Allow `(#set! capture.final)` as shorthand…
savetheclocktower Jan 9, 2024
30f696f
Address more PHP grammar feedback
savetheclocktower Jan 10, 2024
9db2ace
[tree-sitter] Add the pipe character (`|`) as an operator
savetheclocktower Dec 19, 2023
0e8fe9b
[tree-sitter] Fix indentation hinting at the edges of injections
savetheclocktower Dec 23, 2023
a42d0ed
Allow `suggestedIndentForBufferRows` to work correctly…
savetheclocktower Dec 23, 2023
d32bdf6
[tree-sitter] Highlight assertion function clauses in TypeScript
savetheclocktower Dec 25, 2023
d9f6946
[tree-sitter] Fix JSX dedent logic
savetheclocktower Dec 25, 2023
0b51a77
[tree-sitter] Further JSX indent fixes for JS and TS alike
savetheclocktower Dec 25, 2023
aef7c84
(oops)
savetheclocktower Dec 26, 2023
b7dc654
[tree-sitter] Fixes for shell script highlighting
savetheclocktower Dec 29, 2023
d148a73
Add a modern Tree-sitter PHP grammar
savetheclocktower Jan 5, 2024
c93bdeb
Add `parserSource` fields where appropriate
savetheclocktower Jan 5, 2024
ad8a215
Remove logging from injection callback
savetheclocktower Jan 5, 2024
58b9cc1
Handle nowdocs in PHP
savetheclocktower Jan 5, 2024
8c946a0
[tree-sitter] TS: Treat parameters with defaults like parameters…
savetheclocktower Jan 5, 2024
f2dabe5
Update `tree-sitter-php` WASM file to latest `master`
savetheclocktower Jan 5, 2024
2580642
Address feedback on PHP syntax highlighting
savetheclocktower Jan 8, 2024
8836be7
Only inject TODO and hyperlink into CSS when needed
savetheclocktower Jan 9, 2024
0b08306
Don't add root scopes to CSS for TODO/hyperlink injections
savetheclocktower Jan 9, 2024
336f609
More PHP grammar feedback
savetheclocktower Jan 10, 2024
c50b0e6
More PHP grammar feedback
savetheclocktower Jan 10, 2024
4c6b0ba
Ensure indentation decisions consult the correct layers…
savetheclocktower Jan 10, 2024
254440e
Oops
savetheclocktower Jan 11, 2024
50bfa51
Update `tree-sitter-json` WASM build to latest
savetheclocktower Jan 11, 2024
865153b
Address newly failing tests
savetheclocktower Jan 12, 2024
ddfa645
Fix issue where `symbol-provider-ctags` used the wrong package root
savetheclocktower Jan 12, 2024
9972245
[symbols-view] Allow for scope-specific overrides of preferred providers
savetheclocktower Jan 12, 2024
a34b01b
In JS/TS, correctly highlight a variable with a default value…
savetheclocktower Jan 12, 2024
e78feea
Address more PHP grammar feedback
savetheclocktower Jan 10, 2024
62bd6cc
Even more PHP grammar feedback
savetheclocktower Jan 13, 2024
f3be33b
Add `<>` and `<=>` operators in PHP
savetheclocktower Jan 13, 2024
bae3689
Add folds for PHP
savetheclocktower Jan 13, 2024
6ebdfa0
Remove unneeded file
savetheclocktower Jan 13, 2024
0111e13
PHP feedback
savetheclocktower Jan 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/language-c/grammars/tree-sitter-cpp/highlights.scm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
27 changes: 25 additions & 2 deletions packages/language-c/lib/main.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
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) {
return node.lastNamedChild;
}
});
}

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
});
}
}
};
2 changes: 1 addition & 1 deletion packages/language-c/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"license": "MIT",
"engines": {
"atom": "*",
"node": "*"
"node": ">=12"
},
"dependencies": {
"tree-sitter-c": "0.20.2",
Expand Down
32 changes: 19 additions & 13 deletions packages/language-css/lib/main.js
Original file line number Diff line number Diff line change
@@ -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/;
savetheclocktower marked this conversation as resolved.
Show resolved Hide resolved
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
//
Expand All @@ -31,7 +36,8 @@ exports.activate = () => {
if (!functionName === 'url') { return null; }

return node.descendantsOfType('plain_value');
}
},
languageScope: null
});

};
25 changes: 25 additions & 0 deletions packages/language-go/lib/main.js
Original file line number Diff line number Diff line change
@@ -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
});

};
1 change: 1 addition & 0 deletions packages/language-go/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "language-go",
"description": "Go language support in Atom",
"main": "lib/main",
"keywords": [
"tree-sitter"
],
Expand Down
4 changes: 0 additions & 4 deletions packages/language-html/grammars/tree-sitter-html/folds.scm
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@

; (element) @fold
; (style_element) @fold
; (script_element) @fold

[
(element)
(script_element)
Expand Down
77 changes: 42 additions & 35 deletions packages/language-hyperlink/spec/hyperlink-spec.js
Original file line number Diff line number Diff line change
@@ -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');
Expand All @@ -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:[email protected]');
Expand All @@ -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('<?php "/mailto:/" ?>');
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('<?php "/mailto:/" ?>');
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']});
});
});
});
});
23 changes: 22 additions & 1 deletion packages/language-java/lib/main.js
Original file line number Diff line number Diff line change
@@ -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
});
}
};
24 changes: 22 additions & 2 deletions packages/language-javascript/grammars/ts/highlights.scm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -203,7 +219,7 @@
; The "foo" in `function (foo = false) {`.
(formal_parameters
(assignment_pattern
(identifier) @variable.parameter.js))
left: (identifier) @variable.parameter.js))


; FUNCTIONS
Expand Down Expand Up @@ -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
Expand Down
Loading
Loading