Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(language-service): add semantic tokens for templates #60260

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

JannikLassahn
Copy link

@JannikLassahn JannikLassahn commented Mar 7, 2025

Adds support for getEncodedSemanticClassifications to the language service. The service now classifies components in a template as the class type.

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

The language service does not provide semantic tokens.

Issue Number: #60262

What is the new behavior?

The Angular language service now implements the getEncodedSemanticClassifications call, which in turn is needed on the language server/client side to provide the desired contextual syntax highlighting in the editor.

For now, the service only tries to highlight component tags by classifying them as classes (similiar to TSX highlighting done by TypeScript). To this extent the token types are the same as in the TypeScript language service to ensure this service keeps working as a strict superset.

For details about semantic tokens see the LSP protocol.

Does this PR introduce a breaking change?

  • Yes
  • No

@angular-robot angular-robot bot added detected: feature PR contains a feature commit area: language-service Issues related to Angular's VS Code language service labels Mar 7, 2025
@ngbot ngbot bot added this to the Backlog milestone Mar 7, 2025
@JannikLassahn
Copy link
Author

Since this feature requires changes in vscode-ng-language-service, I prepared a fork feature/semantic-tokens to test this PR in an actual editor.

This is a screenshot from VSCode with semantic tokens enabled:
screenshot

Copy link
Contributor

@atscott atscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! I was waiting for this to move from draft to ready for review but maybe the fact that it was created in draft mode wasn't noticed.

@JannikLassahn JannikLassahn force-pushed the feature/semantic-tokens branch from 5d1775c to 74904fa Compare June 11, 2025 19:19
@angular-robot angular-robot bot requested a review from atscott June 11, 2025 19:19
@JannikLassahn JannikLassahn marked this pull request as ready for review June 11, 2025 19:20
@JannikLassahn
Copy link
Author

Thanks for your review and kind words!
(I kept the draft because I wasn't quite sure myself whether functionality/code were sufficient)

Adds support for `getEncodedSemanticClassifications` to the language service.
The service now classifies components in a template as the `class` type.
@JannikLassahn JannikLassahn force-pushed the feature/semantic-tokens branch from 74904fa to 564c1b5 Compare June 12, 2025 17:31
visitElement(element: TmplAstElement) {
const tag = element.name;
const potentialDirective = this.tags.get(tag);
const isComponent = potentialDirective && potentialDirective.isComponent;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind adding a comment about why this was done? e.g. to prevent the classifications for directives from applying to the element.

BTW, the way we attempt to determine if an attribute is what causes the directive to be a match for the element is by removing the attribute and checking to see if the directive still matches:

const allAttrs = attributes.map(toAttributeCssSelector);
const allDirectiveMatches = getDirectiveMatchesForSelector(
directives,
getNodeName(hostNode) + allAttrs.join(''),
);
const attrsExcludingName = attributes.filter((a) => a.name !== name).map(toAttributeCssSelector);
const matchesWithoutAttr = getDirectiveMatchesForSelector(
directives,
getNodeName(hostNode) + attrsExcludingName.join(''),
);
return difference(allDirectiveMatches, matchesWithoutAttr);
.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my PR can wait for this to be merged. We all need to visit the template node and get the component node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: language-service Issues related to Angular's VS Code language service detected: feature PR contains a feature commit
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants