@@ -15,9 +15,10 @@ export interface CsharpierDiff {
1515}
1616
1717export class DiagnosticsService implements vscode . CodeActionProvider , vscode . Disposable {
18- public static readonly quickFixCodeActionKind =
18+ private static readonly quickFixCodeActionKind =
1919 vscode . CodeActionKind . QuickFix . append ( DIAGNOSTICS_ID ) ;
20- public static metadata : vscode . CodeActionProviderMetadata = {
20+
21+ private static metadata : vscode . CodeActionProviderMetadata = {
2122 providedCodeActionKinds : [ DiagnosticsService . quickFixCodeActionKind ] ,
2223 } ;
2324
@@ -48,87 +49,100 @@ export class DiagnosticsService implements vscode.CodeActionProvider, vscode.Dis
4849 this . codeActionsProvider . dispose ( ) ;
4950 }
5051
51- private handleChangeTextDocument ( document : vscode . TextDocument ) : void {
52- void this . runDiagnostics ( document ) ;
53- }
54-
55- public async runDiagnostics ( document : vscode . TextDocument ) : Promise < void > {
56- const shouldRunDiagnostics =
57- this . documentSelector . some ( selector => selector . language === document . languageId ) &&
58- ! ! vscode . workspace . getWorkspaceFolder ( document . uri ) &&
59- ( workspace . getConfiguration ( "csharpier" ) . get < boolean > ( "enableDiagnostics" ) ?? true ) ;
60- if ( shouldRunDiagnostics ) {
61- try {
62- const diff = await this . getDiff ( document ) ;
63- this . updateDiagnostics ( document , diff ) ;
64- } catch ( e ) {
65- this . logger . error ( `Unable to provide diagnostics: ${ ( e as Error ) . message } ` ) ;
66- }
67- }
68- }
69-
70- public updateDiagnostics ( document : vscode . TextDocument , diff : CsharpierDiff ) : void {
71- const diagnostics = this . getDiagnostics ( document , diff ) ;
72- this . diagnosticCollection . set ( document . uri , diagnostics ) ;
73- }
74-
7552 private registerEditorEvents ( ) : void {
7653 const activeDocument = vscode . window . activeTextEditor ?. document ;
7754 if ( activeDocument ) {
7855 void this . runDiagnostics ( activeDocument ) ;
7956 }
8057
81- const onDidChangeTextDocument = vscode . workspace . onDidChangeTextDocument (
82- ( e : vscode . TextDocumentChangeEvent ) => {
83- if (
84- e . contentChanges . length &&
85- vscode . window . activeTextEditor ?. document === e . document
86- ) {
87- this . handleChangeTextDocument ( e . document ) ;
88- }
89- } ,
90- ) ;
58+ const onDidChangeTextDocument = vscode . workspace . onDidChangeTextDocument ( e => {
59+ if (
60+ e . contentChanges . length &&
61+ vscode . window . activeTextEditor ?. document === e . document
62+ ) {
63+ // when editing don't pop up any new diagnostics, but if someone cleans up one then allow that update
64+ void this . runDiagnostics ( e . document , true ) ;
65+ }
66+ } ) ;
9167
92- const onDidChangeActiveTextEditor = vscode . window . onDidChangeActiveTextEditor (
93- ( editor ?: vscode . TextEditor ) => {
94- if ( editor ) {
95- void this . runDiagnostics ( editor . document ) ;
96- }
97- } ,
98- ) ;
68+ const onDidSaveTextDocument = vscode . workspace . onDidSaveTextDocument ( document => {
69+ if ( vscode . window . activeTextEditor ?. document === document ) {
70+ void this . runDiagnostics ( document ) ;
71+ }
72+ } ) ;
73+
74+ const onDidChangeActiveTextEditor = vscode . window . onDidChangeActiveTextEditor ( editor => {
75+ if ( editor ) {
76+ void this . runDiagnostics ( editor . document ) ;
77+ }
78+ } ) ;
9979
10080 this . disposables . push (
10181 onDidChangeTextDocument ,
82+ onDidSaveTextDocument ,
10283 onDidChangeActiveTextEditor ,
10384 this . diagnosticCollection ,
10485 ) ;
10586 }
10687
88+ public async runDiagnostics (
89+ document : vscode . TextDocument ,
90+ onlyAllowLessDiagnostics = false ,
91+ ) : Promise < void > {
92+ const shouldRunDiagnostics =
93+ this . documentSelector . some ( selector => selector . language === document . languageId ) &&
94+ ! ! vscode . workspace . getWorkspaceFolder ( document . uri ) &&
95+ ( workspace . getConfiguration ( "csharpier" ) . get < boolean > ( "enableDiagnostics" ) ?? true ) ;
96+ if ( ! shouldRunDiagnostics ) {
97+ this . diagnosticCollection . set ( document . uri , [ ] ) ;
98+ return ;
99+ }
100+
101+ try {
102+ const source = document . getText ( ) ;
103+ const formattedSource =
104+ ( await this . formatDocumentProvider . formatDocument ( document ) ) ?? source ;
105+ const differences = generateDifferences ( source , formattedSource ) ;
106+ const diff = {
107+ source,
108+ formattedSource,
109+ differences,
110+ } ;
111+ const diagnostics = this . getDiagnostics ( document , diff ) ;
112+ if ( onlyAllowLessDiagnostics ) {
113+ let currentDiagnostics = this . diagnosticCollection . get ( document . uri ) ;
114+ let currentCount = ! currentDiagnostics ? 0 : currentDiagnostics . length ;
115+ if ( diagnostics . length >= currentCount ) {
116+ return ;
117+ }
118+ }
119+ this . diagnosticCollection . set ( document . uri , diagnostics ) ;
120+ } catch ( e ) {
121+ this . logger . error ( `Unable to provide diagnostics: ${ ( e as Error ) . message } ` ) ;
122+ }
123+ }
124+
107125 private getDiagnostics (
108126 document : vscode . TextDocument ,
109127 diff : CsharpierDiff ,
110128 ) : vscode . Diagnostic [ ] {
111129 const diagnostics : vscode . Diagnostic [ ] = [ ] ;
112130 for ( const difference of diff . differences ) {
113- const diagnostic = this . getDiagnostic ( document , difference ) ;
131+ let range = this . getRange ( document , difference ) ;
132+ let message = this . getMessage ( difference ) ;
133+ let diagnostic = new vscode . Diagnostic ( range , message ) ;
134+ diagnostic . source = DIAGNOSTICS_ID ;
135+ diagnostic . code = DIAGNOSTICS_SOURCE_ID ;
136+ diagnostic . severity = parseInt (
137+ workspace . getConfiguration ( "csharpier" ) . get < string > ( "diagnosticsLevel" ) ?? "1" ,
138+ 10 ,
139+ ) ;
114140 this . diagnosticDifferenceMap . set ( diagnostic , difference ) ;
115141 diagnostics . push ( diagnostic ) ;
116142 }
117143 return diagnostics ;
118144 }
119145
120- private getDiagnostic (
121- document : vscode . TextDocument ,
122- difference : Difference ,
123- ) : vscode . Diagnostic {
124- const range = this . getRange ( document , difference ) ;
125- const message = this . getMessage ( difference ) ;
126- const diagnostic = new vscode . Diagnostic ( range , message ) ;
127- diagnostic . source = DIAGNOSTICS_ID ;
128- diagnostic . code = DIAGNOSTICS_SOURCE_ID ;
129- return diagnostic ;
130- }
131-
132146 private getMessage ( difference : Difference ) : string {
133147 switch ( difference . operation ) {
134148 case generateDifferences . INSERT :
@@ -154,18 +168,6 @@ export class DiagnosticsService implements vscode.CodeActionProvider, vscode.Dis
154168 return new vscode . Range ( start . line , start . character , end . line , end . character ) ;
155169 }
156170
157- private async getDiff ( document : vscode . TextDocument ) : Promise < CsharpierDiff > {
158- const source = document . getText ( ) ;
159- const formattedSource =
160- ( await this . formatDocumentProvider . formatDocument ( document ) ) ?? source ;
161- const differences = generateDifferences ( source , formattedSource ) ;
162- return {
163- source,
164- formattedSource,
165- differences,
166- } ;
167- }
168-
169171 public provideCodeActions (
170172 document : vscode . TextDocument ,
171173 range : vscode . Range | vscode . Selection ,
0 commit comments