提交 ef715cf8 编写于 作者: M Martin Aeschlimann

TypeScript semantic tokens: use range provider

上级 fcca161e
......@@ -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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册