SwiftSyntax seems to be labeling async
/await
as normal identifiers instead of keywords. (this also happens to override
). am i using it wrong? why doesn’t it highlight async
/await
by default?
AFAIK, for source compatibility reasons, most new "keywords" are actually contextual keywords that are lexed as identifiers that the parser inspects the contents of, instead of the lexer treating them as unique keyword kinds. If they introduced a new keyword as a keyword token, it would break source compatibility anywhere that that word was used as an identifier; for example let await = true
would fail.
I'm not sure why override
is included in that set since it's not a new keyword, but maybe they just didn't want to exclude it from being an identifier everywhere else since it's only used as a callable decl modifier.
what does this mean for tooling? for AtomicBlonde i just added an extra rule that maps .identifier("async")
to .keyword("async")
, but that also ends up catching any symbol named “async”, which is a problem for DispatchQueue.async
etc.
You won't be able to do syntax highlighting based on identifier contents alone, since the same token could be an identifier in one place and a "keyword" elsewhere.
You would need to make your highlighter syntax-tree-aware so that it only highlights certain "identifiers" as keywords when they appear in a keyword position; for example, override
when it appears in the modifier list of a function/property, async
when it appears in the result clause of a function/property accessor, await
when it appears at the head of an expression, and so forth.
Unfortunately, since it looks like you're using SourceKit's syntax map (rather than the full SwiftSyntax tree), I don't know if you have all the structure you'd need in that format to make those decisions.
For syntax highlighting you can use the "classifications" of the tree; these take into account context-specific keywords. See an example in swift-syntax/ClassifiedSyntaxTreePrinter.swift at main · apple/swift-syntax · GitHub