Skip to content

Commit 7208ce4

Browse files
Eskibearfbricon
authored andcommitted
Support semantic highlighting
Signed-off-by: Yan Zhang <yanzh@microsoft.com>
1 parent 8b73af6 commit 7208ce4

6 files changed

Lines changed: 113 additions & 39 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,10 @@ The following settings are supported:
155155

156156
Default launch mode is `Hybrid`. Legacy mode is `Standard`
157157

158-
New in 0.60.0:
158+
New in 0.60.0:
159159
* `java.sources.organizeImports.starThreshold`: Specifies the number of imports added before a star-import declaration is used, default is 99.
160160
* `java.sources.organizeImports.staticStarThreshold`: Specifies the number of static imports added before a star-import declaration is used, default is 99.
161+
* `java.semanticHighlighting.enabled`: Enable/disable the [semantic highlighting](https://github.com/microsoft/vscode/wiki/Semantic-Highlighting-Overview). Defaults to `true`.
161162

162163
Troubleshooting
163164
===============

package-lock.json

Lines changed: 34 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"preview": true,
1212
"enableProposedApi": false,
1313
"engines": {
14-
"vscode": "^1.41.0"
14+
"vscode": "^1.44.0"
1515
},
1616
"repository": {
1717
"type": "git",
@@ -526,7 +526,12 @@
526526
"java.sources.organizeImports.staticStarThreshold": {
527527
"type": "integer",
528528
"description": "Specifies the number of static imports added before a star-import declaration is used.",
529-
"default": 99,
529+
"default": 99
530+
},
531+
"java.semanticHighlighting.enabled": {
532+
"type": "boolean",
533+
"default": true,
534+
"description": "Enable/disable the semantic highlighting.",
530535
"scope": "window"
531536
}
532537
}
@@ -693,7 +698,7 @@
693698
"@types/lodash.findindex": "^4.6.6",
694699
"@types/mocha": "^5.2.5",
695700
"@types/node": "^8.10.51",
696-
"@types/vscode": "^1.41.0",
701+
"@types/vscode": "^1.44.0",
697702
"@types/winston": "^2.4.4",
698703
"gulp": "^4.0.0",
699704
"gulp-decompress": "2.0.1",

src/commands.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,12 @@ export namespace Commands {
184184
* Check the input file is a test file or not
185185
*/
186186
export const IS_TEST_FILE = 'java.project.isTestFile';
187+
/**
188+
* Temporary command for Semantic Highlighting. To remove when LSP v3.16 is ready.
189+
*/
190+
export const PROVIDE_SEMANTIC_TOKENS = 'java.project.provideSemanticTokens';
191+
/**
192+
* Temporary command to fetch Semantic Tokens Legend. To remove when LSP v3.16 is ready.
193+
*/
194+
export const GET_SEMANTIC_TOKENS_LEGEND = 'java.project.getSemanticTokensLegend';
187195
}

src/extension.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { serverStatus, ServerStatusKind } from './serverStatus';
3232
import { SyntaxLanguageClient } from './syntaxLanguageClient';
3333
import { registerClientProviders, ClientHoverProvider } from './providerDispatcher';
3434
import * as fileEventHandler from './fileEventHandler';
35+
import { registerSemanticTokensProvider } from './semanticTokenProvider';
3536

3637
let languageClient: LanguageClient;
3738
const syntaxClient: SyntaxLanguageClient = new SyntaxLanguageClient();
@@ -517,6 +518,9 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
517518
context.subscriptions.push(commands.registerCommand(Commands.CLEAN_WORKSPACE, () => cleanWorkspace(workspacePath)));
518519

519520
context.subscriptions.push(onConfigurationChange(languageClient, context));
521+
522+
// temporary implementation Semantic Highlighting before it is part of LSP
523+
registerSemanticTokensProvider(context);
520524
});
521525
});
522526
}

src/semanticTokenProvider.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as vscode from 'vscode';
2+
import { Commands } from './commands';
3+
import { getJavaConfiguration } from './utils';
4+
5+
export function registerSemanticTokensProvider(context: vscode.ExtensionContext) {
6+
if (isSemanticHTokensEnabled()) {
7+
getSemanticTokensLegend().then(legend => {
8+
const semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider({ scheme: 'file', language: 'java' }, semanticTokensProvider, legend);
9+
context.subscriptions.push(semanticTokensProviderDisposable);
10+
onceSemanticTokenEnabledChange(context, semanticTokensProviderDisposable);
11+
});
12+
} else {
13+
onceSemanticTokenEnabledChange(context, undefined);
14+
}
15+
}
16+
17+
class SemanticTokensProvider implements vscode.DocumentSemanticTokensProvider {
18+
async provideDocumentSemanticTokens(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.SemanticTokens> {
19+
const response = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.PROVIDE_SEMANTIC_TOKENS, document.uri.toString());
20+
if (token.isCancellationRequested) {
21+
return undefined;
22+
}
23+
return response as vscode.SemanticTokens;
24+
}
25+
}
26+
27+
const semanticTokensProvider = new SemanticTokensProvider();
28+
29+
async function getSemanticTokensLegend(): Promise<vscode.SemanticTokensLegend | undefined> {
30+
const response = await vscode.commands.executeCommand(Commands.EXECUTE_WORKSPACE_COMMAND, Commands.GET_SEMANTIC_TOKENS_LEGEND) as vscode.SemanticTokensLegend;
31+
if (response && response.tokenModifiers !== undefined && response.tokenTypes !== undefined) {
32+
return new vscode.SemanticTokensLegend(response.tokenTypes, response.tokenModifiers);
33+
}
34+
return undefined;
35+
}
36+
37+
function onceSemanticTokenEnabledChange(context: vscode.ExtensionContext, registeredDisposable?: vscode.Disposable) {
38+
const configChangeListener = vscode.workspace.onDidChangeConfiguration(e => {
39+
configChangeListener.dispose();
40+
if (e.affectsConfiguration('java.semanticHighlighting.enabled')) {
41+
if (isSemanticHTokensEnabled()) {
42+
// turn on
43+
registerSemanticTokensProvider(context);
44+
} else if (registeredDisposable) {
45+
// turn off
46+
registeredDisposable.dispose();
47+
}
48+
onceSemanticTokenEnabledChange(context);
49+
}
50+
});
51+
}
52+
53+
function isSemanticHTokensEnabled(): boolean {
54+
const config = getJavaConfiguration();
55+
const section = 'semanticHighlighting.enabled';
56+
return config.get(section);
57+
}

0 commit comments

Comments
 (0)