Skip to content

Commit 8bb27cd

Browse files
authored
Add unused diagnostic subtype (microsoft#49646)
* Add unused diagnostic subtype Fixes microsoft#15710 Adds a new `DiagnosticTag` class that provide additional information about a diagnostic. Introduce `DiagnosticTag.Unnecessary` to mark when a diagnostic is for unused / unnecessary code The design comes from Rosyln's diagnostic object and allows us to modify how a diagnostic is rendered without changing its serverity. Hooks up JS and TS to use this new tag. This is controlled by the `javascript.showUnused.enabled` setting which is enabled by default - Introduce a new diagnostic severity for unused. However, using this approach, if a user sets `noUnusedLocals` in their `tsconfig.json`, the resulting diagnostic could only show the squiggly OR be grayed out. Using `customTags` allows us to support both graying out and showing the squiggly - Custom JS/TS implementation using decorators Not themable. We want a standard experience across languages. * - Move to proposed - Use numeric enum
1 parent 0f7ac44 commit 8bb27cd

17 files changed

Lines changed: 92 additions & 90 deletions

File tree

build/monaco/monaco.d.ts.recipe

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ declare namespace monaco {
3232
Error = 3,
3333
}
3434

35+
export enum MarkerTag {
36+
Unnecessary = 1,
37+
}
38+
3539
export enum MarkerSeverity {
3640
Hint = 1,
3741
Info = 2,

extensions/typescript-language-features/src/features/unusedHighlighter.ts

Lines changed: 0 additions & 73 deletions
This file was deleted.

extensions/typescript-language-features/src/languageProvider.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { CachedNavTreeResponse } from './features/baseCodeLensProvider';
2121
import { memoize } from './utils/memoize';
2222
import { disposeAll } from './utils/dispose';
2323
import TelemetryReporter from './utils/telemetry';
24-
import { UnusedHighlighter } from './features/unusedHighlighter';
2524

2625
const validateSetting = 'validate.enable';
2726
const suggestionSetting = 'suggestionActions.enabled';
@@ -30,7 +29,6 @@ const foldingSetting = 'typescript.experimental.syntaxFolding';
3029
export default class LanguageProvider {
3130
private readonly diagnosticsManager: DiagnosticsManager;
3231
private readonly bufferSyncSupport: BufferSyncSupport;
33-
private readonly ununsedHighlighter: UnusedHighlighter;
3432
private readonly fileConfigurationManager: FileConfigurationManager;
3533

3634
private readonly toUpdateOnConfigurationChanged: ({ updateConfiguration: () => void })[] = [];
@@ -58,7 +56,6 @@ export default class LanguageProvider {
5856
}, this._validate);
5957

6058
this.diagnosticsManager = new DiagnosticsManager(description.diagnosticOwner);
61-
this.ununsedHighlighter = new UnusedHighlighter();
6259

6360
workspace.onDidChangeConfiguration(this.configurationChanged, this, this.disposables);
6461
this.configurationChanged();
@@ -229,7 +226,6 @@ export default class LanguageProvider {
229226

230227
public reInitialize(): void {
231228
this.diagnosticsManager.reInitialize();
232-
this.ununsedHighlighter.reInitialize();
233229
this.bufferSyncSupport.reOpenDocuments();
234230
this.bufferSyncSupport.requestAllDiagnostics();
235231
this.fileConfigurationManager.reset();
@@ -265,9 +261,6 @@ export default class LanguageProvider {
265261
public diagnosticsReceived(diagnosticsKind: DiagnosticKind, file: Uri, diagnostics: (Diagnostic & { reportUnnecessary: any })[]): void {
266262
const config = workspace.getConfiguration(this.id, file);
267263
const reportUnnecessary = config.get<boolean>('showUnused.enabled', true);
268-
if (diagnosticsKind === DiagnosticKind.Suggestion) {
269-
this.ununsedHighlighter.diagnosticsReceived(file, diagnostics.filter(diag => diag.reportUnnecessary));
270-
}
271264
this.diagnosticsManager.diagnosticsReceived(diagnosticsKind, file, diagnostics.filter(diag => diag.reportUnnecessary ? reportUnnecessary : true));
272265
}
273266

extensions/typescript-language-features/src/typeScriptServiceClientHost.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* https://github.com/Microsoft/TypeScript-Sublime-Plugin/blob/master/TypeScript%20Indent.tmPreferences
99
* ------------------------------------------------------------------------------------------ */
1010

11-
import { workspace, Memento, Diagnostic, Range, Disposable, Uri, DiagnosticSeverity } from 'vscode';
11+
import { workspace, Memento, Diagnostic, Range, Disposable, Uri, DiagnosticSeverity, DiagnosticTag } from 'vscode';
1212

1313
import * as Proto from './protocol';
1414
import * as PConst from './protocol.const';
@@ -256,6 +256,9 @@ export default class TypeScriptServiceClientHost {
256256
if (diagnostic.code) {
257257
converted.code = diagnostic.code;
258258
}
259+
if (diagnostic.reportsUnnecessary) {
260+
converted.customTags = [DiagnosticTag.Unnecessary];
261+
}
259262
(converted as Diagnostic & { reportUnnecessary: any }).reportUnnecessary = diagnostic.reportsUnnecessary;
260263
return converted as Diagnostic & { reportUnnecessary: any };
261264
}

src/vs/editor/browser/widget/codeEditorWidget.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import { IMouseEvent } from 'vs/base/browser/mouseEvent';
4646
import { InternalEditorAction } from 'vs/editor/common/editorAction';
4747
import { ICommandDelegate } from 'vs/editor/browser/view/viewController';
4848
import { CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
49-
import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoBorder, editorInfoForeground, editorHintForeground, editorHintBorder } from 'vs/editor/common/view/editorColorRegistry';
49+
import { editorErrorForeground, editorErrorBorder, editorWarningForeground, editorWarningBorder, editorInfoBorder, editorInfoForeground, editorHintForeground, editorHintBorder, editorUnnecessaryForeground } from 'vs/editor/common/view/editorColorRegistry';
5050
import { Color } from 'vs/base/common/color';
5151
import { ClassName } from 'vs/editor/common/model/intervalTree';
5252

@@ -1795,4 +1795,9 @@ registerThemingParticipant((theme, collector) => {
17951795
if (hintForeground) {
17961796
collector.addRule(`.monaco-editor .${ClassName.EditorHintDecoration} { background: url("data:image/svg+xml,${getDotDotDotSVGData(hintForeground)}") no-repeat bottom left; }`);
17971797
}
1798+
1799+
const unnecessaryForeground = theme.getColor(editorUnnecessaryForeground);
1800+
if (unnecessaryForeground) {
1801+
collector.addRule(`.monaco-editor .${ClassName.EditorUnnecessaryDecoration} { color: ${unnecessaryForeground}; }`);
1802+
}
17981803
});

src/vs/editor/common/model/intervalTree.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export const ClassName = {
1616
EditorHintDecoration: 'squiggly-hint',
1717
EditorInfoDecoration: 'squiggly-info',
1818
EditorWarningDecoration: 'squiggly-warning',
19-
EditorErrorDecoration: 'squiggly-error'
19+
EditorErrorDecoration: 'squiggly-error',
20+
EditorUnnecessaryDecoration: 'squiggly-overlay-unnecessary'
2021
};
2122

2223
/**

src/vs/editor/common/services/modelServiceImpl.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { MarkdownString } from 'vs/base/common/htmlContent';
1111
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
1212
import URI from 'vs/base/common/uri';
1313
import { TPromise } from 'vs/base/common/winjs.base';
14-
import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers';
14+
import { IMarker, IMarkerService, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
1515
import { Range } from 'vs/editor/common/core/range';
1616
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
1717
import { IMode, LanguageIdentifier } from 'vs/editor/common/modes';
@@ -127,10 +127,13 @@ class ModelMarkerHandler {
127127
let color: ThemeColor;
128128
let darkColor: ThemeColor;
129129
let zIndex: number;
130+
let inlineClassName: string;
130131

131132
switch (marker.severity) {
132133
case MarkerSeverity.Hint:
133-
className = ClassName.EditorHintDecoration;
134+
if (!marker.customTags || marker.customTags.indexOf(MarkerTag.Unnecessary) === -1) {
135+
className = ClassName.EditorHintDecoration;
136+
}
134137
zIndex = 0;
135138
break;
136139
case MarkerSeverity.Warning:
@@ -154,6 +157,12 @@ class ModelMarkerHandler {
154157
break;
155158
}
156159

160+
if (marker.customTags) {
161+
if (marker.customTags.indexOf(MarkerTag.Unnecessary) !== -1) {
162+
inlineClassName = ClassName.EditorUnnecessaryDecoration;
163+
}
164+
}
165+
157166
let hoverMessage: MarkdownString = null;
158167
let { message, source, relatedInformation } = marker;
159168

@@ -193,7 +202,8 @@ class ModelMarkerHandler {
193202
darkColor,
194203
position: OverviewRulerLane.Right
195204
},
196-
zIndex
205+
zIndex,
206+
inlineClassName,
197207
};
198208
}
199209
}

src/vs/editor/common/standalone/standaloneBase.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export enum Severity {
2525
Error = 3,
2626
}
2727

28+
export enum MarkerTag {
29+
Unnecessary = 1,
30+
}
31+
2832
export enum MarkerSeverity {
2933
Hint = 1,
3034
Info = 2,
@@ -246,6 +250,7 @@ export function createMonacoBaseAPI(): typeof monaco {
246250
SelectionDirection: SelectionDirection,
247251
Severity: Severity,
248252
MarkerSeverity: MarkerSeverity,
253+
MarkerTag: MarkerTag,
249254
Promise: TPromise,
250255
Uri: <any>URI,
251256
Token: Token

src/vs/editor/common/view/editorColorRegistry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export const editorInfoBorder = registerColor('editorInfo.border', { dark: null,
4949
export const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('hintForeground', 'Foreground color of hint squigglies in the editor.'));
5050
export const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hc: Color.fromHex('#eeeeee').transparent(0.8) }, nls.localize('hintBorder', 'Border color of hint squigglies in the editor.'));
5151

52+
export const editorUnnecessaryForeground = registerColor('editorUnnecessary.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('unnecessaryForeground', 'Foreground color of unnecessary code in the editor.'));
53+
5254
const rulerRangeDefault = new Color(new RGBA(0, 122, 204, 0.6));
5355
export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque to not hide underlying decorations.'), true);
5456
export const overviewRulerError = registerColor('editorOverviewRuler.errorForeground', { dark: new Color(new RGBA(255, 18, 18, 0.7)), light: new Color(new RGBA(255, 18, 18, 0.7)), hc: new Color(new RGBA(255, 50, 50, 1)) }, nls.localize('overviewRuleError', 'Overview ruler marker color for errors.'));

src/vs/editor/editor.api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const Selection = api.Selection;
3737
export const SelectionDirection = api.SelectionDirection;
3838
export const Severity = api.Severity;
3939
export const MarkerSeverity = api.MarkerSeverity;
40+
export const MarkerTag = api.MarkerTag;
4041
export const Promise = api.Promise;
4142
export const Uri = api.Uri;
4243
export const Token = api.Token;

0 commit comments

Comments
 (0)