microsoft / microsoft/TypeScript

[Bug] PrivateIdentifier nodes are omitted from 2020 semantic classifications

Open Beginner friendly
#64,322 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

# Bug Report

### 🔎 Search Terms

semantic highlighting, semantic token, PrivateIdentifier, private field, private method, encodedSemanticClassifications

### 🕗 Version & Regression Information

- TypeScript 6.0.3 (bundled with VS Code)
- Also present in the v5.9 classifier implementation
- This is not a theme-specific issue

### 💻 Code

```ts
class Foo {
field = 1;
#privateField = 1;

method() {}
#privateMethod() {}

test() {
this.field;
this.#privateField;

this.method();
this.#privateMethod();
}
}
```

### 🙁 Actual behavior

In VS Code's **Developer: Inspect Editor Tokens and Scopes**:

- `field` and `method` receive semantic token types.
- `#privateField` and `#privateMethod` receive no semantic token and fall back to TextMate scopes.
- As a result, `editor.semanticTokenColorCustomizations` rules for `property` and `method` do not apply to ECMAScript private members.

Image

Image

### 🙂 Expected behavior

- `#privateField` should be classified as `property`.
- `#privateMethod` should be classified as `method`.
- Declarations should also receive the `declaration` modifier.

### Root cause

VS Code requests `encodedSemanticClassifications-full` with format `"2020"`.

In `src/services/classifier2020.ts`, `collectTokens` only enters the semantic-classification path for `isIdentifier(node)`:

```ts
if (isIdentifier(node) && ...) {
let symbol = typeChecker.getSymbolAtLocation(node);
// ...
}
```

ECMAScript private names are separate `SyntaxKind.PrivateIdentifier` nodes, so they are skipped before `getSymbolAtLocation` is called.

Relevant source:
https://github.com/microsoft/TypeScript/blob/050880ce59e30b356b686bd3144efe24f875ebc8/src/services/classifier2020.ts#L121-L203

### Proposed fix

```diff
+ isPrivateIdentifier,
isPropertyAccessExpression,
```

```diff
- if (isIdentifier(node) && ...) {
+ if ((isIdentifier(node) || isPrivateIdentifier(node)) && ...) {
```

The existing declaration-kind mapping already classifies private fields and methods correctly once these nodes reach the symbol-classification path.

I tested the equivalent change against TypeScript 6.0.3:

- `#privateField` declaration/reference → `property`
- `#privateMethod` declaration/reference → `member` internally, mapped by VS Code to `method`
- declaration occurrences receive the `declaration` modifier
- added fourslash regression test passes

### Related issue

https://github.com/microsoft/TypeScript/issues/44483 requests new `private`/`protected` semantic modifiers. This report is different: ECMAScript `PrivateIdentifier` nodes currently receive no semantic classification at all.

Contributor guide

Open the contributing guide

Research direction

Start in src/services/classifier2020.ts at collectTokens and review the existing declaration-kind mapping for identifier nodes. Add the relevant fourslash regression test covering private field and method declarations and references, then verify that the nodes receive property or method classifications and declaration modifiers.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, vscode
Domain
compilers, developer-experience
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.