Skip to content

Commit 45c3cec

Browse files
authored
Implement reportStyleChecksAsWarnings (#2132)
1 parent c6c346e commit 45c3cec

File tree

6 files changed

+70
-17
lines changed

6 files changed

+70
-17
lines changed

internal/fourslash/fourslash.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,8 +2588,7 @@ func (f *FourslashTest) getDiagnostics(t *testing.T, fileName string) []*lsproto
25882588
}
25892589

25902590
func isSuggestionDiagnostic(diag *lsproto.Diagnostic) bool {
2591-
return diag.Tags != nil && len(*diag.Tags) > 0 ||
2592-
(diag.Severity != nil && *diag.Severity == lsproto.DiagnosticSeverityHint)
2591+
return diag.Severity != nil && *diag.Severity == lsproto.DiagnosticSeverityHint
25932592
}
25942593

25952594
func (f *FourslashTest) VerifyBaselineNonSuggestionDiagnostics(t *testing.T) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package fourslash_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/microsoft/typescript-go/internal/fourslash"
7+
"github.com/microsoft/typescript-go/internal/testutil"
8+
)
9+
10+
func TestUnreachableCodeDiagnostics(t *testing.T) {
11+
t.Parallel()
12+
13+
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
14+
const content = `// @allowUnreachableCode: false
15+
throw new Error();
16+
17+
(() => {})();
18+
`
19+
f := fourslash.NewFourslash(t, nil /*capabilities*/, content)
20+
f.VerifyBaselineNonSuggestionDiagnostics(t)
21+
}

internal/ls/diagnostics.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ func (l *LanguageService) ProvideDiagnostics(ctx context.Context, uri lsproto.Do
1616
diagnostics = append(diagnostics, program.GetSemanticDiagnostics(ctx, file))
1717
// !!! user preference for suggestion diagnostics; keep only unnecessary/deprecated?
1818
// See: https://github.com/microsoft/vscode/blob/3dbc74129aaae102e5cb485b958fa5360e8d3e7a/extensions/typescript-language-features/src/languageFeatures/diagnostics.ts#L114
19-
// TODO: also implement reportStyleCheckAsWarnings to rewrite diags with Warning severity
2019
diagnostics = append(diagnostics, program.GetSuggestionDiagnostics(ctx, file))
2120
if program.Options().GetEmitDeclarations() {
2221
diagnostics = append(diagnostics, program.GetDeclarationDiagnostics(ctx, file))
@@ -37,7 +36,7 @@ func (l *LanguageService) toLSPDiagnostics(ctx context.Context, diagnostics ...[
3736
lspDiagnostics := make([]*lsproto.Diagnostic, 0, size)
3837
for _, diagSlice := range diagnostics {
3938
for _, diag := range diagSlice {
40-
lspDiagnostics = append(lspDiagnostics, lsconv.DiagnosticToLSPPull(ctx, l.converters, diag))
39+
lspDiagnostics = append(lspDiagnostics, lsconv.DiagnosticToLSPPull(ctx, l.converters, diag, l.UserPreferences().ReportStyleChecksAsWarnings))
4140
}
4241
}
4342
return lspDiagnostics

internal/ls/lsconv/converters.go

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"unicode/utf8"
1111

1212
"github.com/microsoft/typescript-go/internal/ast"
13+
"github.com/microsoft/typescript-go/internal/collections"
1314
"github.com/microsoft/typescript-go/internal/core"
1415
"github.com/microsoft/typescript-go/internal/diagnostics"
1516
"github.com/microsoft/typescript-go/internal/diagnosticwriter"
@@ -204,30 +205,44 @@ func ptrTo[T any](v T) *T {
204205
return &v
205206
}
206207

207-
type diagnosticCapabilities struct {
208-
relatedInformation bool
209-
tagValueSet []lsproto.DiagnosticTag
208+
type diagnosticOptions struct {
209+
reportStyleChecksAsWarnings bool
210+
relatedInformation bool
211+
tagValueSet []lsproto.DiagnosticTag
210212
}
211213

212214
// DiagnosticToLSPPull converts a diagnostic for pull diagnostics (textDocument/diagnostic)
213-
func DiagnosticToLSPPull(ctx context.Context, converters *Converters, diagnostic *ast.Diagnostic) *lsproto.Diagnostic {
215+
func DiagnosticToLSPPull(ctx context.Context, converters *Converters, diagnostic *ast.Diagnostic, reportStyleChecksAsWarnings bool) *lsproto.Diagnostic {
214216
clientCaps := lsproto.GetClientCapabilities(ctx).TextDocument.Diagnostic
215-
return diagnosticToLSP(converters, diagnostic, diagnosticCapabilities{
216-
relatedInformation: clientCaps.RelatedInformation,
217-
tagValueSet: clientCaps.TagSupport.ValueSet,
217+
return diagnosticToLSP(converters, diagnostic, diagnosticOptions{
218+
reportStyleChecksAsWarnings: reportStyleChecksAsWarnings, // !!! get through context UserPreferences
219+
relatedInformation: clientCaps.RelatedInformation,
220+
tagValueSet: clientCaps.TagSupport.ValueSet,
218221
})
219222
}
220223

221224
// DiagnosticToLSPPush converts a diagnostic for push diagnostics (textDocument/publishDiagnostics)
222225
func DiagnosticToLSPPush(ctx context.Context, converters *Converters, diagnostic *ast.Diagnostic) *lsproto.Diagnostic {
223226
clientCaps := lsproto.GetClientCapabilities(ctx).TextDocument.PublishDiagnostics
224-
return diagnosticToLSP(converters, diagnostic, diagnosticCapabilities{
227+
return diagnosticToLSP(converters, diagnostic, diagnosticOptions{
225228
relatedInformation: clientCaps.RelatedInformation,
226229
tagValueSet: clientCaps.TagSupport.ValueSet,
227230
})
228231
}
229232

230-
func diagnosticToLSP(converters *Converters, diagnostic *ast.Diagnostic, caps diagnosticCapabilities) *lsproto.Diagnostic {
233+
// https://github.com/microsoft/vscode/blob/93e08afe0469712706ca4e268f778cfadf1a43ef/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts#L40C7-L40C29
234+
var styleCheckDiagnostics = collections.NewSetFromItems(
235+
diagnostics.X_0_is_declared_but_never_used.Code(),
236+
diagnostics.X_0_is_declared_but_its_value_is_never_read.Code(),
237+
diagnostics.Property_0_is_declared_but_its_value_is_never_read.Code(),
238+
diagnostics.All_imports_in_import_declaration_are_unused.Code(),
239+
diagnostics.Unreachable_code_detected.Code(),
240+
diagnostics.Unused_label.Code(),
241+
diagnostics.Fallthrough_case_in_switch.Code(),
242+
diagnostics.Not_all_code_paths_return_a_value.Code(),
243+
)
244+
245+
func diagnosticToLSP(converters *Converters, diagnostic *ast.Diagnostic, opts diagnosticOptions) *lsproto.Diagnostic {
231246
var severity lsproto.DiagnosticSeverity
232247
switch diagnostic.Category() {
233248
case diagnostics.CategorySuggestion:
@@ -240,8 +255,12 @@ func diagnosticToLSP(converters *Converters, diagnostic *ast.Diagnostic, caps di
240255
severity = lsproto.DiagnosticSeverityError
241256
}
242257

258+
if opts.reportStyleChecksAsWarnings && severity == lsproto.DiagnosticSeverityError && styleCheckDiagnostics.Has(diagnostic.Code()) {
259+
severity = lsproto.DiagnosticSeverityWarning
260+
}
261+
243262
var relatedInformation []*lsproto.DiagnosticRelatedInformation
244-
if caps.relatedInformation {
263+
if opts.relatedInformation {
245264
relatedInformation = make([]*lsproto.DiagnosticRelatedInformation, 0, len(diagnostic.RelatedInformation()))
246265
for _, related := range diagnostic.RelatedInformation() {
247266
relatedInformation = append(relatedInformation, &lsproto.DiagnosticRelatedInformation{
@@ -255,12 +274,12 @@ func diagnosticToLSP(converters *Converters, diagnostic *ast.Diagnostic, caps di
255274
}
256275

257276
var tags []lsproto.DiagnosticTag
258-
if len(caps.tagValueSet) > 0 && (diagnostic.ReportsUnnecessary() || diagnostic.ReportsDeprecated()) {
277+
if len(opts.tagValueSet) > 0 && (diagnostic.ReportsUnnecessary() || diagnostic.ReportsDeprecated()) {
259278
tags = make([]lsproto.DiagnosticTag, 0, 2)
260-
if diagnostic.ReportsUnnecessary() && slices.Contains(caps.tagValueSet, lsproto.DiagnosticTagUnnecessary) {
279+
if diagnostic.ReportsUnnecessary() && slices.Contains(opts.tagValueSet, lsproto.DiagnosticTagUnnecessary) {
261280
tags = append(tags, lsproto.DiagnosticTagUnnecessary)
262281
}
263-
if diagnostic.ReportsDeprecated() && slices.Contains(caps.tagValueSet, lsproto.DiagnosticTagDeprecated) {
282+
if diagnostic.ReportsDeprecated() && slices.Contains(opts.tagValueSet, lsproto.DiagnosticTagDeprecated) {
264283
tags = append(tags, lsproto.DiagnosticTagDeprecated)
265284
}
266285
}

internal/ls/lsutil/userpreferences.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func NewDefaultUserPreferences() *UserPreferences {
1919
IncludeCompletionsWithSnippetText: core.TSTrue,
2020
DisplayPartsForJSDoc: true,
2121
DisableLineTextInReferences: true,
22+
ReportStyleChecksAsWarnings: true,
2223
}
2324
}
2425

@@ -148,6 +149,7 @@ type UserPreferences struct {
148149
DisableSuggestions bool // !!!
149150
DisableLineTextInReferences bool // !!!
150151
DisplayPartsForJSDoc bool // !!!
152+
ReportStyleChecksAsWarnings bool // !!! If this changes, we need to ask the client to recompute diagnostics
151153
}
152154

153155
type JsxAttributeCompletionStyle string
@@ -628,5 +630,7 @@ func (p *UserPreferences) set(name string, value any) {
628630
p.DisableLineTextInReferences = parseBoolWithDefault(value, true)
629631
case "displaypartsforjsdoc":
630632
p.DisplayPartsForJSDoc = parseBoolWithDefault(value, true)
633+
case "reportstylechecksaswarnings":
634+
p.ReportStyleChecksAsWarnings = parseBoolWithDefault(value, true)
631635
}
632636
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// === Syntax and Semantic Diagnostics ===
2+
/unreachableCodeDiagnostics.ts(3,1): warning TS7027: Unreachable code detected.
3+
4+
5+
==== /unreachableCodeDiagnostics.ts (1 errors) ====
6+
throw new Error();
7+
8+
(() => {})();
9+
~~~~~~~~~~~~~
10+
!!! warning TS7027: Unreachable code detected.
11+

0 commit comments

Comments
 (0)