Changes:
* `#define FOO 1` and `#define FOO` will _always_ scope `FOO` as `constant.other.c`, even when `FOO` is mixed-case or lower-case.
* `#define FOO()` will _always_ scope `FOO` as `entity.name.function.preprocessor.c`, even when `FOO` is mixed-case or lower-case.
* Usages of bare identifiers in other contexts in preprocessor directives should always scope them as `constant.other.c` — unless I’m made aware of any counterexamples where that shouldn’t happen. For example: in `#if TABLE_SIZE > 200`, `TABLE_SIZE` should always be `constant.other.c`, no matter its casing.
* All-caps variable declarations and assignments (`int FOO = 0`, etc.) should scope `FOO` as `variable` rather than `constant`. We should only scope an arbitrary identifier as `constant` if we think it’s been used in the context of a macro definition.
However:
* When deciding whether something outside of a directive refers to a macro constant, we have no choice but to use the `ALL_CAPS` heuristic. Ideally we’d be able to determine that from some sort of analysis of the source code files — but even if we could keep track of that sort of thing in a single buffer, it’d fall down when macro constants _defined in other files_ are used. All we can do here is make a best guess.
…in which all _value types_ are scoped under `support.storage`. The goal is to avoid drawing an arbitrary distinction between, say, `int` and `SomeCustomCType` — those things are different, but not _so_ different that they belong in separate root scope namespaces.
`storage.type` can be used for core language constructs — `var`, `class`, `function`, `struct`, `enum`, `namespace`, and so on. `support.storage.type` should be used for any _recognized_ value type — certainly core language types like `int`, but also other things if they make sense. `support.other.storage.type` can be used for user-defined types, or any other types that we don't recognize. (Using the `support.other` ordering here adheres to our new convention of reserving all of `support.other` for user-defined things.)
The point of this compromise is that both the `syntax--storage` and `syntax--support` class names are present so that many themes will still highlight these tokens as though they were in the root `storage` namespace.
This commit changes the C/C++ and TypeScript `highlights.scm` files. The results appear to be satisfactory to my eye after testing on two of the builtin themes.
I’ve updated the taxonomy document to reflect this new proposal:
https://gist.github.com/savetheclocktower/c9607b97477d4817911e4f2f8db89679#file-scope-taxonomy-md
Choosing the other side of some dilemmas I had to resolve six months ago. Highlighting between modern and legacy Tree-sitters now appears to be identical to me (with rare exception) on the One Dark theme.
Built a new `tree-sitter-cpp` parser from latest master to fix a parsing error with variable assignment. Also added/tweaked scopes for some specific scenarios.
On some default themes, scoping types as `storage.type` rather than `support.type` makes them the same color as lots of other things. Both the TM grammar and the legacy TS grammar scope them as `support.storage.type` — which isn't a thing — but `support.type` is a fine compromise.
Anything that is one of the reserved type words in C must be a type in all contexts. And any identifier that ends in `_t` is, by strong convention, a type.
I realized a few days ago that the `#is?` and `#is-not?` predicates — which
puzzled me upon first investigation back in February, and which I'd ignored ever
since — are exactly what I should've been using all along for scope tests.
They are counterparts to `#set!` in that they are two additional buckets in
which to store arbitrary data. And they remove the need to have both
`test.onlyIfFoo` and `test.onlyIfNotFoo`, since the presence of `test.onlyIfFoo`
in the `refutedProperties` bucket can behave opposite to the its presence in the
`assertedProperties` bucket.
This further means that a test called `test.onlyIfFoo` can be renamed
`test.foo`. The `onlyIf` was my way of making it clear through context that this
`#set!` predicate actually enforced a criterion — but that's implicit now that
it'll be using an `#is?` or `#is-not?` predicate.
I also took the opportunity to move `test.final` and `test.shy` to their own
namespace. `final` is an oddball in the sense that it sets criteria for _other_
captures as well as its own, and they're both oddballs in the sense that they
consider the effects of other captures on the same range. And I don't want to
introduce the idea that a predicate like `#is?` can have side effects.
So they stay on `#set!` and live at `capture.final` and `capture.shy`,
respectively.
To summarize, here's a before and after:
((string "\"" @punctuation.start)
(#set! test.onlyIfFirst true)
(#set! test.final true)
((bar) @baz
(#set! test.onlyIfNotDescendantOfType thud))
becomes
((string "\"" @punctuation.start)
(#is? test.first true)
(#set! capture.final true)
((bar) @baz
(#is-not? test.descendantOfType thud))
This PR changes all the built-in grammars. I don't know if there are any
third-party modern-Tree-sitter grammars out there except for mine, but I've
added a simple compatibility layer so that all of the old predicates should
still work for now. But I'm going to remove that code before we ship this stuff
for real.
Predicates were getting pretty chaotic. With the namespace, it's now clearer
where a predicate may be defined and what its purpose is. It also helps resolve
ambiguity — e.g., both folds and highlights can have an `endAt` predicate, so
now they're disambiguated as `fold.endAt` and `adjust.endAt`, respectively.
Namespaces:
* `highlight` for highlight-specific settings (of which there is presently only
one)
* `test` for scope tests (currently used by highlights and indents)
* `adjust` for scope adjustments (highlights)
* `indent` for indent settings
* `fold` for fold settings
Right now, only the `test` namespace will be used by more than one kind of query
file, but I could imagine that changing in the future.
For now, tests and adjustments still work without the prepended namespace, but
I imagine I'll take that out even before we ship this feature experimentally.
Much easier to make big changes like this before anyone depends on them.
This also draws a much clearer line between `#set!` predicates with special
meaning in Pulsar… and those which are being used to set arbitrary data for
later use. For instance, if you see `(#set! isOnLeftSideOfAssignment true)`, you
know it must just be arbitrary data.
…along with a temporary `core.useExperimentalModernTreeSitter` setting.
If we truly planned to keep three different language modes around indefinitely,
changing `core.useTreeSitterParsers` to an enum would make sense. But we don't,
so it'd actually just be a gigantic pain in the ass to migrate one setting to
another of a different type.
When we ship modern-tree-sitter experimentally, we'll make it opt-in via the
temporary setting. When we make it the official tree-sitter implementation and
remove the legacy node-tree-sitter version, we'll remove the temporary setting
and just change the semantics around `core.useTreeSitterParsers`.
Reverting the addition of the `core.languageParser` setting is a chore, but it
prevents a _gigantic_ future headache.
The `syntaxQuery` key in a grammar definition file is the only query whose name
differs from its canonical filename, and there's no reason why that should be
the case. Might as well change it now before we ship instead of going through
the pain of changing it later.
incorporates:
https://github.com/atom/language-c/pull/252
Note that this particular change was modified. `class public virtual : public virtual Example` is invalid I think, but I don't see a good way to prevent that because the detection must be moved into `patterns > include` because textmate is not multiline regex.
See also https://github.com/jeff-hykin/better-cpp-syntax/issues/14
(In fact that whole repostory probably has some improvements)
I changed it to include the angle brackets because types can have those
https://github.com/atom/language-c/pull/263https://github.com/atom/language-c/pull/311https://github.com/atom/language-c/pull/368
For tree-sitter, kinda fix the Discord reported issue
(In #support M1 Mac C++ Syntax highlighting)
Note that I syntax color only the last function name and not the namespace or colon. But that could easily be changed.
For future me, the relevant tree-sitter namespace identifier scopes are:
`call_expression > qualified_identifier > identifier` and
`function_declarator > qualified_identifier > identifier`
I don't know anything about template functions so I left that untouched. So this is probably an incomplete fix.
Finally, add the `static_assert` operator. It's technically a directive so it'll appear purple, not blue. Again this could easily be changed so don't hesitate about feedback, idk anything about c++