Add DiagnosticsOptions.onlyVisible to limit computing diagnostics to only the visible text models

This commit is contained in:
Alex Dima 2021-05-11 14:27:47 +02:00
parent e9fb83dcb1
commit 22e7676a8c
No known key found for this signature in database
GPG key ID: 6E58D7B045760DA0
3 changed files with 51 additions and 9 deletions

5
monaco.d.ts vendored
View file

@ -143,6 +143,11 @@ declare namespace monaco.languages.typescript {
noSemanticValidation?: boolean;
noSyntaxValidation?: boolean;
noSuggestionDiagnostics?: boolean;
/**
* Limit diagnostic computation to only visible files.
* Defaults to false.
*/
onlyVisible?: boolean;
diagnosticCodesToIgnore?: number[];
}
export interface WorkerOptions {

View file

@ -163,6 +163,15 @@ enum DiagnosticCategory {
Message = 3
}
/**
* temporary interface until the editor API exposes
* `IModel.isAttachedToEditor` and `IModel.onDidChangeAttached`
*/
interface IInternalEditorModel extends editor.IModel {
onDidChangeAttached(listener: () => void): IDisposable;
isAttachedToEditor(): boolean;
}
export class DiagnosticsAdapter extends Adapter {
private _disposables: IDisposable[] = [];
private _listener: { [uri: string]: IDisposable } = Object.create(null);
@ -175,25 +184,52 @@ export class DiagnosticsAdapter extends Adapter {
) {
super(worker);
const onModelAdd = (model: editor.IModel): void => {
const onModelAdd = (model: IInternalEditorModel): void => {
if (model.getModeId() !== _selector) {
return;
}
const maybeValidate = () => {
const { onlyVisible } = this._defaults.getDiagnosticsOptions();
if (onlyVisible) {
if (model.isAttachedToEditor()) {
this._doValidate(model);
}
} else {
this._doValidate(model);
}
};
let handle: number;
const changeSubscription = model.onDidChangeContent(() => {
clearTimeout(handle);
handle = setTimeout(() => this._doValidate(model), 500);
handle = setTimeout(maybeValidate, 500);
});
const visibleSubscription = model.onDidChangeAttached(() => {
const { onlyVisible } = this._defaults.getDiagnosticsOptions();
if (onlyVisible) {
if (model.isAttachedToEditor()) {
// this model is now attached to an editor
// => compute diagnostics
maybeValidate();
} else {
// this model is no longer attached to an editor
// => clear existing diagnostics
editor.setModelMarkers(model, this._selector, []);
}
}
});
this._listener[model.uri.toString()] = {
dispose() {
changeSubscription.dispose();
visibleSubscription.dispose();
clearTimeout(handle);
}
};
this._doValidate(model);
maybeValidate();
};
const onModelRemoved = (model: editor.IModel): void => {
@ -205,12 +241,12 @@ export class DiagnosticsAdapter extends Adapter {
}
};
this._disposables.push(editor.onDidCreateModel(onModelAdd));
this._disposables.push(editor.onDidCreateModel((model) => onModelAdd(<IInternalEditorModel>model)));
this._disposables.push(editor.onWillDisposeModel(onModelRemoved));
this._disposables.push(
editor.onDidChangeModelLanguage((event) => {
onModelRemoved(event.model);
onModelAdd(event.model);
onModelAdd(<IInternalEditorModel>event.model);
})
);
@ -226,13 +262,13 @@ export class DiagnosticsAdapter extends Adapter {
// redo diagnostics when options change
for (const model of editor.getModels()) {
onModelRemoved(model);
onModelAdd(model);
onModelAdd(<IInternalEditorModel>model);
}
};
this._disposables.push(this._defaults.onDidChange(recomputeDiagostics));
this._disposables.push(this._defaults.onDidExtraLibsChange(recomputeDiagostics));
editor.getModels().forEach(onModelAdd);
editor.getModels().forEach((model) => onModelAdd(<IInternalEditorModel>model));
}
public dispose(): void {

View file

@ -156,6 +156,7 @@ export interface DiagnosticsOptions {
noSemanticValidation?: boolean;
noSyntaxValidation?: boolean;
noSuggestionDiagnostics?: boolean;
onlyVisible?: boolean;
diagnosticCodesToIgnore?: number[];
}
@ -616,13 +617,13 @@ export const typescriptVersion: string = tsversion;
export const typescriptDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, target: ScriptTarget.Latest },
{ noSemanticValidation: false, noSyntaxValidation: false },
{ noSemanticValidation: false, noSyntaxValidation: false, onlyVisible: false },
{}
);
export const javascriptDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl(
{ allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest },
{ noSemanticValidation: true, noSyntaxValidation: false },
{ noSemanticValidation: true, noSyntaxValidation: false, onlyVisible: false },
{}
);