mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
turn language status API proposal into push model, https://github.com/microsoft/vscode/issues/129037
This commit is contained in:
parent
ee4740005e
commit
e30d70f9f5
|
@ -4,8 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
@ -17,6 +16,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
|||
|
||||
|
||||
export interface ILanguageStatus {
|
||||
selector: LanguageSelector,
|
||||
severity: Severity;
|
||||
text: string;
|
||||
message: string | IMarkdownString;
|
||||
|
@ -34,41 +34,26 @@ export interface ILanguageStatusService {
|
|||
|
||||
onDidChange: Event<void>;
|
||||
|
||||
registerLanguageStatusProvider(selector: LanguageSelector, provider: ILanguageStatusProvider): IDisposable;
|
||||
addStatus(status: ILanguageStatus): IDisposable;
|
||||
|
||||
getLanguageStatus(model: ITextModel): Promise<ILanguageStatus[]>;
|
||||
}
|
||||
|
||||
|
||||
class LanguageStatusServiceImpl implements ILanguageStatusService {
|
||||
|
||||
declare _serviceBrand: undefined;
|
||||
|
||||
private readonly _provider = new LanguageFeatureRegistry<ILanguageStatusProvider>();
|
||||
private readonly _provider = new LanguageFeatureRegistry<ILanguageStatus>();
|
||||
|
||||
private readonly _onDidChange = new Emitter<void>();
|
||||
readonly onDidChange: Event<void> = Event.any(this._onDidChange.event, this._provider.onDidChange);
|
||||
readonly onDidChange: Event<any> = this._provider.onDidChange;
|
||||
|
||||
dispose() {
|
||||
this._onDidChange.dispose();
|
||||
}
|
||||
|
||||
registerLanguageStatusProvider(selector: LanguageSelector, provider: ILanguageStatusProvider): IDisposable {
|
||||
return this._provider.register(selector, provider);
|
||||
addStatus(status: ILanguageStatus): IDisposable {
|
||||
return this._provider.register(status.selector, status);
|
||||
}
|
||||
|
||||
async getLanguageStatus(model: ITextModel): Promise<ILanguageStatus[]> {
|
||||
const all: ILanguageStatus[] = [];
|
||||
for (const provider of this._provider.ordered(model)) {
|
||||
try {
|
||||
const status = await provider.provideLanguageStatus(model.getLanguageIdentifier().language, CancellationToken.None);
|
||||
if (status) {
|
||||
all.push(status);
|
||||
}
|
||||
} catch (err) {
|
||||
onUnexpectedExternalError(err);
|
||||
}
|
||||
}
|
||||
return all.sort((a, b) => b.severity - a.severity);
|
||||
return this._provider.ordered(model).sort((a, b) => b.severity - a.severity);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
src/vs/vscode.proposed.d.ts
vendored
13
src/vs/vscode.proposed.d.ts
vendored
|
@ -3166,19 +3166,16 @@ declare module 'vscode' {
|
|||
Error = 2
|
||||
}
|
||||
|
||||
class LanguageStatus {
|
||||
interface LanguageStatusItem {
|
||||
selector: DocumentSelector;
|
||||
text: string;
|
||||
detail: string | MarkdownString;
|
||||
detail: string | MarkdownString
|
||||
severity: LanguageStatusSeverity;
|
||||
constructor(text: string);
|
||||
}
|
||||
|
||||
export interface LanguageStatusProvider {
|
||||
provideLanguageStatus(token: CancellationToken): ProviderResult<LanguageStatus>;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
namespace languages {
|
||||
export function registerLanguageStatusProvider(selector: DocumentSelector, provider: LanguageStatusProvider): Disposable;
|
||||
export function createLanguageStatusItem(selector: DocumentSelector): LanguageStatusItem;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
|
|
@ -23,7 +23,6 @@ import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'
|
|||
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { decodeSemanticTokensDto } from 'vs/editor/common/services/semanticTokensDto';
|
||||
import { ILanguageStatus, ILanguageStatusService } from 'vs/editor/common/services/languageStatusService';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
|
||||
export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape {
|
||||
|
@ -35,7 +34,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IModeService modeService: IModeService,
|
||||
@ILanguageStatusService private readonly _languageStatusService: ILanguageStatusService
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostLanguageFeatures);
|
||||
this._modeService = modeService;
|
||||
|
@ -159,16 +157,6 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||
|
||||
//#endregion
|
||||
|
||||
// --- language status
|
||||
|
||||
$registerLanguageStatusProvider(handle: number, selector: IDocumentFilterDto[]): void {
|
||||
this._registrations.set(handle, this._languageStatusService.registerLanguageStatusProvider(selector, {
|
||||
provideLanguageStatus: (_langId: string, token: CancellationToken): Promise<ILanguageStatus | undefined> => {
|
||||
return this._proxy.$provideLanguageStatus(handle, token);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// --- outline
|
||||
|
||||
$registerDocumentSymbolProvider(handle: number, selector: IDocumentFilterDto[], displayName: string): void {
|
||||
|
|
|
@ -12,6 +12,8 @@ import { IPosition } from 'vs/editor/common/core/position';
|
|||
import { IRange, Range } from 'vs/editor/common/core/range';
|
||||
import { StandardTokenType } from 'vs/editor/common/modes';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ILanguageStatus, ILanguageStatusService } from 'vs/editor/common/services/languageStatusService';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadLanguages)
|
||||
export class MainThreadLanguages implements MainThreadLanguagesShape {
|
||||
|
@ -21,8 +23,8 @@ export class MainThreadLanguages implements MainThreadLanguagesShape {
|
|||
@IModeService private readonly _modeService: IModeService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
@ITextModelService private _resolverService: ITextModelService,
|
||||
) {
|
||||
}
|
||||
@ILanguageStatusService private readonly _languageStatusService: ILanguageStatusService,
|
||||
) { }
|
||||
|
||||
dispose(): void {
|
||||
// nothing
|
||||
|
@ -62,4 +64,17 @@ export class MainThreadLanguages implements MainThreadLanguagesShape {
|
|||
range: new Range(position.lineNumber, 1 + tokens.getStartOffset(idx), position.lineNumber, 1 + tokens.getEndOffset(idx))
|
||||
};
|
||||
}
|
||||
|
||||
// --- language status
|
||||
|
||||
private readonly _status = new Map<number, IDisposable>();
|
||||
|
||||
$setLanguageStatus(handle: number, status: ILanguageStatus): void {
|
||||
this._status.get(handle)?.dispose();
|
||||
this._status.set(handle, this._languageStatusService.addStatus(status));
|
||||
}
|
||||
|
||||
$removeLanguageStatus(handle: number): void {
|
||||
this._status.get(handle)?.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -507,9 +507,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguageFeatures.registerTypeHierarchyProvider(extension, selector, provider);
|
||||
},
|
||||
registerLanguageStatusProvider(selector: vscode.DocumentSelector, provider: vscode.LanguageStatusProvider): vscode.Disposable {
|
||||
createLanguageStatusItem(selector: vscode.DocumentSelector): vscode.LanguageStatusItem {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostLanguageFeatures.registerLanguageStatusProvider(extension, selector, provider);
|
||||
return extHostLanguages.createLanguageStatusItem(selector);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1284,7 +1284,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
BranchCoverage: extHostTypes.BranchCoverage,
|
||||
FunctionCoverage: extHostTypes.FunctionCoverage,
|
||||
WorkspaceTrustState: extHostTypes.WorkspaceTrustState,
|
||||
LanguageStatus: extHostTypes.LanguageStatus,
|
||||
LanguageStatusSeverity: extHostTypes.LanguageStatusSeverity,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -383,7 +383,6 @@ export interface IdentifiableInlineCompletion extends modes.InlineCompletion {
|
|||
|
||||
export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$unregister(handle: number): void;
|
||||
$registerLanguageStatusProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||
$registerDocumentSymbolProvider(handle: number, selector: IDocumentFilterDto[], label: string): void;
|
||||
$registerCodeLensSupport(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void;
|
||||
$emitCodeLensEvent(eventHandle: number, event?: any): void;
|
||||
|
@ -426,6 +425,8 @@ export interface MainThreadLanguagesShape extends IDisposable {
|
|||
$getLanguages(): Promise<string[]>;
|
||||
$changeLanguage(resource: UriComponents, languageId: string): Promise<void>;
|
||||
$tokensAtPosition(resource: UriComponents, position: IPosition): Promise<undefined | { type: modes.StandardTokenType, range: IRange }>;
|
||||
$setLanguageStatus(handle: number, status: ILanguageStatus): void;
|
||||
$removeLanguageStatus(handle: number): void;
|
||||
}
|
||||
|
||||
export interface MainThreadMessageOptions {
|
||||
|
@ -1641,7 +1642,6 @@ export interface IInlineValueContextDto {
|
|||
export type ITypeHierarchyItemDto = Dto<TypeHierarchyItem>;
|
||||
|
||||
export interface ExtHostLanguageFeaturesShape {
|
||||
$provideLanguageStatus(handle: number, token: CancellationToken): Promise<ILanguageStatus | undefined>;
|
||||
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined>;
|
||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
|
||||
$resolveCodeLens(handle: number, symbol: ICodeLensDto, token: CancellationToken): Promise<ICodeLensDto | undefined>;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
|||
import { mixin } from 'vs/base/common/objects';
|
||||
import type * as vscode from 'vscode';
|
||||
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, LanguageStatusSeverity } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
|
@ -33,37 +33,9 @@ import { Cache } from './cache';
|
|||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
import { CancellationError } from 'vs/base/common/errors';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { ILanguageStatus } from 'vs/editor/common/services/languageStatusService';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
// --- adapter
|
||||
|
||||
class LanguageStatusAdapter {
|
||||
|
||||
constructor(private readonly _provider: vscode.LanguageStatusProvider) { }
|
||||
|
||||
async provideLanguageStatus(token: CancellationToken): Promise<ILanguageStatus | undefined> {
|
||||
|
||||
const value = await this._provider.provideLanguageStatus(token);
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
let severity = Severity.Info;
|
||||
if (value.severity === LanguageStatusSeverity.Error) {
|
||||
severity = Severity.Error;
|
||||
} else if (value.severity === LanguageStatusSeverity.Warning) {
|
||||
severity = Severity.Warning;
|
||||
}
|
||||
|
||||
return {
|
||||
text: value.text,
|
||||
message: typeConvert.MarkdownString.from(value.detail),
|
||||
severity
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentSymbolAdapter {
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
|
@ -1520,7 +1492,7 @@ class TypeHierarchyAdapter {
|
|||
return map?.get(itemId);
|
||||
}
|
||||
}
|
||||
type Adapter = LanguageStatusAdapter | DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
|
||||
type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
|
||||
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
|
||||
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
|
||||
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter
|
||||
|
@ -1652,18 +1624,6 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
|||
return ext.displayName || ext.name;
|
||||
}
|
||||
|
||||
// --- language status
|
||||
|
||||
registerLanguageStatusProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.LanguageStatusProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new LanguageStatusAdapter(provider), extension);
|
||||
this._proxy.$registerLanguageStatusProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideLanguageStatus(handle: number, token: CancellationToken): Promise<ILanguageStatus | undefined> {
|
||||
return this._withAdapter(handle, LanguageStatusAdapter, adapter => adapter.provideLanguageStatus(token), undefined);
|
||||
}
|
||||
|
||||
// --- outline
|
||||
|
||||
registerDocumentSymbolProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, metadata?: vscode.DocumentSymbolProviderMetadata): vscode.Disposable {
|
||||
|
|
|
@ -7,7 +7,10 @@ import { MainContext, MainThreadLanguagesShape, IMainContext } from './extHost.p
|
|||
import type * as vscode from 'vscode';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { StandardTokenType, Range, Position } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { StandardTokenType, Range, Position, LanguageStatusSeverity } from 'vs/workbench/api/common/extHostTypes';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { disposableTimeout } from 'vs/base/common/async';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export class ExtHostLanguages {
|
||||
|
||||
|
@ -61,4 +64,69 @@ export class ExtHostLanguages {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private _handlePool: number = 0;
|
||||
|
||||
createLanguageStatusItem(selector: vscode.DocumentSelector): vscode.LanguageStatusItem {
|
||||
|
||||
const handle = this._handlePool++;
|
||||
const proxy = this._proxy;
|
||||
|
||||
const data: { selector: any, text: string, detail: string | vscode.MarkdownString, severity: vscode.LanguageStatusSeverity } = {
|
||||
selector,
|
||||
text: '',
|
||||
detail: '',
|
||||
severity: LanguageStatusSeverity.Information,
|
||||
};
|
||||
|
||||
let soonHandle: IDisposable | undefined;
|
||||
const updateAsync = () => {
|
||||
soonHandle?.dispose();
|
||||
soonHandle = disposableTimeout(() => {
|
||||
this._proxy.$setLanguageStatus(handle, {
|
||||
selector: data.selector,
|
||||
text: data.text,
|
||||
message: typeof data.detail === 'string' ? data.detail : typeConvert.MarkdownString.from(data.detail),
|
||||
severity: data.severity === LanguageStatusSeverity.Error ? Severity.Error : data.severity === LanguageStatusSeverity.Warning ? Severity.Warning : Severity.Info
|
||||
});
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const result: vscode.LanguageStatusItem = {
|
||||
get selector() {
|
||||
return data.selector;
|
||||
},
|
||||
set selector(value) {
|
||||
data.selector = value;
|
||||
updateAsync();
|
||||
},
|
||||
get text() {
|
||||
return data.text;
|
||||
},
|
||||
set text(value) {
|
||||
data.text = value;
|
||||
updateAsync();
|
||||
},
|
||||
get detail() {
|
||||
return data.detail;
|
||||
},
|
||||
set detail(value) {
|
||||
data.detail = value;
|
||||
updateAsync();
|
||||
},
|
||||
get severity() {
|
||||
return data.severity;
|
||||
},
|
||||
set severity(value) {
|
||||
data.severity = value;
|
||||
updateAsync();
|
||||
},
|
||||
dispose() {
|
||||
soonHandle?.dispose();
|
||||
proxy.$removeLanguageStatus(handle);
|
||||
}
|
||||
};
|
||||
updateAsync();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1286,18 +1286,7 @@ export enum LanguageStatusSeverity {
|
|||
Error = 2
|
||||
}
|
||||
|
||||
export class LanguageStatus {
|
||||
|
||||
text: string;
|
||||
detail: string | MarkdownString;
|
||||
severity: LanguageStatusSeverity;
|
||||
|
||||
constructor(text: string) {
|
||||
this.text = text;
|
||||
this.detail = '';
|
||||
this.severity = LanguageStatusSeverity.Information;
|
||||
}
|
||||
}
|
||||
@es5ClassCompat
|
||||
export class CodeLens {
|
||||
|
||||
|
|
Loading…
Reference in a new issue