diff --git a/extensions/typescript-language-features/src/features/diagnostics.ts b/extensions/typescript-language-features/src/features/diagnostics.ts index fc42e0518b7..ffa9d75e81d 100644 --- a/extensions/typescript-language-features/src/features/diagnostics.ts +++ b/extensions/typescript-language-features/src/features/diagnostics.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; -class DiagnosticSet { +export class DiagnosticSet { private _map: ObjectMap = Object.create(null); public set( diff --git a/extensions/typescript-language-features/src/features/unusedHighlighter.ts b/extensions/typescript-language-features/src/features/unusedHighlighter.ts new file mode 100644 index 00000000000..f5c34a91ec8 --- /dev/null +++ b/extensions/typescript-language-features/src/features/unusedHighlighter.ts @@ -0,0 +1,73 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { DiagnosticSet } from './diagnostics'; + + +export class UnusedHighlighter { + + private readonly _decorationType: vscode.TextEditorDecorationType; + + private readonly _diagnostics = new DiagnosticSet(); + private _validate: boolean = true; + + constructor( + ) { + this._decorationType = vscode.window.createTextEditorDecorationType({ + opacity: '0.7' + }); + } + + public dispose() { + this._decorationType.dispose(); + } + + public reInitialize(): void { + this._diagnostics.clear(); + + for (const editor of vscode.window.visibleTextEditors) { + editor.setDecorations(this._decorationType, []); + } + } + + public set validate(value: boolean) { + if (this._validate === value) { + return; + } + + this._validate = value; + if (!value) { + for (const editor of vscode.window.visibleTextEditors) { + editor.setDecorations(this._decorationType, []); + } + } + } + + public diagnosticsReceived( + file: vscode.Uri, + diagnostics: vscode.Diagnostic[] + ): void { + // Undocumented flag to enable + if (!vscode.workspace.getConfiguration('typescript').get('showUnused.experimentalFade')) { + return; + } + this._diagnostics.set(file, diagnostics); + this._updateCurrentHighlights(file); + } + + private _updateCurrentHighlights(file: vscode.Uri) { + for (const editor of vscode.window.visibleTextEditors) { + if (editor.document.uri.fsPath !== file.fsPath) { + continue; + } + + const diagnostics = this._diagnostics.get(editor.document.uri); + if (diagnostics) { + editor.setDecorations(this._decorationType, diagnostics.map(x => x.range)); + } + } + } +} \ No newline at end of file diff --git a/extensions/typescript-language-features/src/languageProvider.ts b/extensions/typescript-language-features/src/languageProvider.ts index 2c0679e13a1..f40be249b37 100644 --- a/extensions/typescript-language-features/src/languageProvider.ts +++ b/extensions/typescript-language-features/src/languageProvider.ts @@ -21,6 +21,7 @@ import { CachedNavTreeResponse } from './features/baseCodeLensProvider'; import { memoize } from './utils/memoize'; import { disposeAll } from './utils/dipose'; import TelemetryReporter from './utils/telemetry'; +import { UnusedHighlighter } from './features/unusedHighlighter'; const validateSetting = 'validate.enable'; const suggestionSetting = 'suggestionActions.enabled'; @@ -29,6 +30,7 @@ const foldingSetting = 'typescript.experimental.syntaxFolding'; export default class LanguageProvider { private readonly diagnosticsManager: DiagnosticsManager; private readonly bufferSyncSupport: BufferSyncSupport; + private readonly ununsedHighlighter: UnusedHighlighter; private readonly fileConfigurationManager: FileConfigurationManager; private readonly toUpdateOnConfigurationChanged: ({ updateConfiguration: () => void })[] = []; @@ -56,6 +58,7 @@ export default class LanguageProvider { }, this._validate); this.diagnosticsManager = new DiagnosticsManager(description.diagnosticOwner); + this.ununsedHighlighter = new UnusedHighlighter(); workspace.onDidChangeConfiguration(this.configurationChanged, this, this.disposables); this.configurationChanged(); @@ -226,6 +229,7 @@ export default class LanguageProvider { public reInitialize(): void { this.diagnosticsManager.reInitialize(); + this.ununsedHighlighter.reInitialize(); this.bufferSyncSupport.reOpenDocuments(); this.bufferSyncSupport.requestAllDiagnostics(); this.fileConfigurationManager.reset(); @@ -261,6 +265,9 @@ export default class LanguageProvider { public diagnosticsReceived(diagnosticsKind: DiagnosticKind, file: Uri, diagnostics: (Diagnostic & { reportUnnecessary: any })[]): void { const config = workspace.getConfiguration(this.id); const reportUnnecessary = config.get('showUnused.enabled', true); + if (diagnosticsKind === DiagnosticKind.Suggestion) { + this.ununsedHighlighter.diagnosticsReceived(file, diagnostics.filter(diag => diag.reportUnnecessary)); + } this.diagnosticsManager.diagnosticsReceived(diagnosticsKind, file, diagnostics.filter(diag => diag.reportUnnecessary ? reportUnnecessary : true)); }