mirror of
https://github.com/Microsoft/vscode
synced 2024-09-18 01:58:27 +00:00
TypeScript semantic tokens: use range provider
This commit is contained in:
parent
fcca161eb8
commit
ef715cf8c5
|
@ -14,20 +14,19 @@ import { TokenType, TokenModifier, TokenEncodingConsts, VersionRequirement } fro
|
|||
|
||||
const minTypeScriptVersion = API.fromVersionString(`${VersionRequirement.major}.${VersionRequirement.minor}`);
|
||||
|
||||
// as we don't do deltas, for performance reasons, don't compute semantic tokens for documents above that limit
|
||||
const CONTENT_LENGTH_LIMIT = 100000;
|
||||
|
||||
export function register(selector: vscode.DocumentSelector, client: ITypeScriptServiceClient) {
|
||||
return new VersionDependentRegistration(client, minTypeScriptVersion, () => {
|
||||
const provider = new DocumentSemanticTokensProvider(client);
|
||||
return vscode.Disposable.from(
|
||||
vscode.languages.registerDocumentSemanticTokensProvider(selector, provider, provider.getLegend()),
|
||||
// register only as a range provider
|
||||
vscode.languages.registerDocumentRangeSemanticTokensProvider(selector, provider, provider.getLegend()),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// as we don't do deltas, for performance reasons, don't compute semantic tokens for documents above that limit
|
||||
const CONTENT_LENGTH_LIMIT = 100000;
|
||||
|
||||
/**
|
||||
* Prototype of a DocumentSemanticTokensProvider, relying on the experimental `encodedSemanticClassifications-full` request from the TypeScript server.
|
||||
* As the results retured by the TypeScript server are limited, we also add a Typescript plugin (typescript-vscode-sh-plugin) to enrich the returned token.
|
||||
|
@ -52,9 +51,10 @@ class DocumentSemanticTokensProvider implements vscode.DocumentSemanticTokensPro
|
|||
|
||||
async provideDocumentRangeSemanticTokens(document: vscode.TextDocument, range: vscode.Range, token: vscode.CancellationToken): Promise<vscode.SemanticTokens | null> {
|
||||
const file = this.client.toOpenedFilePath(document);
|
||||
if (!file || document.getText().length > CONTENT_LENGTH_LIMIT) {
|
||||
if (!file || (document.offsetAt(range.end) - document.offsetAt(range.start) > CONTENT_LENGTH_LIMIT)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const start = document.offsetAt(range.start);
|
||||
const length = document.offsetAt(range.end) - start;
|
||||
return this._provideSemanticTokens(document, { file, start, length }, token);
|
||||
|
|
|
@ -17,7 +17,7 @@ import { Position } from 'vs/editor/common/core/position';
|
|||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { FontStyle, LanguageIdentifier, StandardTokenType, TokenMetadata, DocumentSemanticTokensProviderRegistry, SemanticTokensLegend, SemanticTokens, LanguageId, ColorId } from 'vs/editor/common/modes';
|
||||
import { FontStyle, LanguageIdentifier, StandardTokenType, TokenMetadata, DocumentSemanticTokensProviderRegistry, SemanticTokensLegend, SemanticTokens, LanguageId, ColorId, DocumentRangeSemanticTokensProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { editorHoverBackground, editorHoverBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
@ -240,7 +240,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
|
|||
|
||||
private _beginCompute(position: Position): void {
|
||||
const grammar = this._textMateService.createGrammar(this._model.getLanguageIdentifier().language);
|
||||
const semanticTokens = this._computeSemanticTokens();
|
||||
const semanticTokens = this._computeSemanticTokens(position);
|
||||
|
||||
dom.clearNode(this._domNode);
|
||||
this._domNode.appendChild(document.createTextNode(nls.localize('inspectTMScopesWidget.loading', "Loading...")));
|
||||
|
@ -307,7 +307,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
|
|||
const properties: (keyof TokenStyleData)[] = ['foreground', 'bold', 'italic', 'underline'];
|
||||
const propertiesByDefValue: { [rule: string]: string[] } = {};
|
||||
const allDefValues = []; // remember the order
|
||||
// first collect to detect when the same rule is used fro multiple properties
|
||||
// first collect to detect when the same rule is used for multiple properties
|
||||
for (let property of properties) {
|
||||
if (semanticTokenInfo.metadata[property] !== undefined) {
|
||||
const definition = semanticTokenInfo.definitions[property];
|
||||
|
@ -476,7 +476,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
|
|||
return token && token.data;
|
||||
}
|
||||
|
||||
private async _computeSemanticTokens(): Promise<SemanticTokensResult | null> {
|
||||
private async _computeSemanticTokens(position: Position): Promise<SemanticTokensResult | null> {
|
||||
if (!this._isSemanticColoringEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -489,6 +489,16 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
|
|||
return { tokens, legend: provider.getLegend() };
|
||||
}
|
||||
}
|
||||
const rangeTokenProviders = DocumentRangeSemanticTokensProviderRegistry.ordered(this._model);
|
||||
if (rangeTokenProviders.length) {
|
||||
const provider = rangeTokenProviders[0];
|
||||
const lineNumber = position.lineNumber;
|
||||
const range = new Range(lineNumber, 1, lineNumber, this._model.getLineMaxColumn(lineNumber));
|
||||
const tokens = await Promise.resolve(provider.provideDocumentRangeSemanticTokens(this._model, range, this._currentRequestCancellationTokenSource.token));
|
||||
if (this.isSemanticTokens(tokens)) {
|
||||
return { tokens, legend: provider.getLegend() };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue