@@ -26,6 +26,7 @@ import {
26
26
SocketMessageReader ,
27
27
MessageTransports ,
28
28
RAL ,
29
+ CancellationToken ,
29
30
} from 'vscode-languageclient/node' ;
30
31
import { PlatformInformation } from '../shared/platform' ;
31
32
import { readConfigurations } from './configurationMiddleware' ;
@@ -93,6 +94,13 @@ export class RoslynLanguageServer {
93
94
/** The project files previously opened; we hold onto this for the same reason as _solutionFile. */
94
95
private _projectFiles : vscode . Uri [ ] = new Array < vscode . Uri > ( ) ;
95
96
97
+ /** The diagnostic results from build displayed by VS Code. When live diagnostics are available for a file, these are errors that only build knows about.
98
+ * When live diagnostics aren't loaded for a file, then these are all of the diagnostics reported by the build.*/
99
+ private _diagnosticsReportedByBuild : vscode . DiagnosticCollection ;
100
+
101
+ /** All the build results sent by the DevKit extension. */
102
+ private _allBuildDiagnostics : Array < [ vscode . Uri , vscode . Diagnostic [ ] ] > = [ ] ;
103
+
96
104
constructor (
97
105
private _languageClient : RoslynLanguageClient ,
98
106
private _platformInfo : PlatformInformation ,
@@ -107,6 +115,9 @@ export class RoslynLanguageServer {
107
115
this . registerExtensionsChanged ( ) ;
108
116
this . registerTelemetryChanged ( ) ;
109
117
118
+ this . _diagnosticsReportedByBuild = vscode . languages . createDiagnosticCollection ( 'csharp-build' ) ;
119
+ this . addDiagnostics ( ) ;
120
+
110
121
// Register Razor dynamic file info handling
111
122
this . registerDynamicFileInfo ( ) ;
112
123
@@ -568,7 +579,7 @@ export class RoslynLanguageServer {
568
579
} ) ;
569
580
} ) ;
570
581
571
- // The server process will create the named pipe used for communcation . Wait for it to be created,
582
+ // The server process will create the named pipe used for communication . Wait for it to be created,
572
583
// and listen for the server to pass back the connection information via stdout.
573
584
const namedPipeConnectionPromise = new Promise < NamedPipeInformation > ( ( resolve ) => {
574
585
_channel . appendLine ( 'waiting for named pipe information from server...' ) ;
@@ -694,6 +705,70 @@ export class RoslynLanguageServer {
694
705
) ;
695
706
}
696
707
708
+ private addDiagnostics ( ) {
709
+ this . _languageClient . addDisposable (
710
+ vscode . workspace . onDidOpenTextDocument ( async ( event ) => this . _onFileOpened ( event ) )
711
+ ) ;
712
+ }
713
+
714
+ public clearDiagnostics ( ) {
715
+ this . _diagnosticsReportedByBuild . clear ( ) ;
716
+ }
717
+
718
+ public async setBuildDiagnostics ( buildDiagnostics : Array < [ vscode . Uri , vscode . Diagnostic [ ] ] > ) {
719
+ this . _allBuildDiagnostics = buildDiagnostics ;
720
+ const buildOnlyIds = await this . getBuildOnlyDiagnosticIds ( CancellationToken . None ) ;
721
+ const displayedBuildDiagnostics = new Array < [ vscode . Uri , vscode . Diagnostic [ ] ] > ( ) ;
722
+
723
+ this . _allBuildDiagnostics . forEach ( ( fileDiagnostics ) => {
724
+ const uri = fileDiagnostics [ 0 ] ;
725
+ const diagnosticList = fileDiagnostics [ 1 ] ;
726
+
727
+ // Check if we have live diagnostics shown for this document
728
+ const liveDiagnostics = vscode . languages . getDiagnostics ( uri ) ;
729
+ if ( liveDiagnostics && liveDiagnostics . length > 0 ) {
730
+ // Show the build-only diagnostics
731
+ displayedBuildDiagnostics . push ( [ uri , this . _getBuildOnlyDiagnostics ( diagnosticList , buildOnlyIds ) ] ) ;
732
+ } else {
733
+ // Document isn't shown in live diagnostics, so display everything reported by the build
734
+ displayedBuildDiagnostics . push ( fileDiagnostics ) ;
735
+ }
736
+ } ) ;
737
+
738
+ this . _diagnosticsReportedByBuild . set ( displayedBuildDiagnostics ) ;
739
+ }
740
+
741
+ private compareUri ( a : vscode . Uri , b : vscode . Uri ) : boolean {
742
+ return a . path . localeCompare ( b . path , undefined , { sensitivity : 'accent' } ) === 0 ;
743
+ }
744
+
745
+ private async _onFileOpened ( document : vscode . TextDocument ) {
746
+ const uri = document . uri ;
747
+ const buildIds = await this . getBuildOnlyDiagnosticIds ( CancellationToken . None ) ;
748
+ const currentFileBuildDiagnostics = this . _allBuildDiagnostics . find ( ( [ u ] ) => this . compareUri ( u , uri ) ) ;
749
+
750
+ // The document is now open in the editor and live diagnostics are being shown. Filter diagnostics
751
+ // reported by the build to show build-only problems.
752
+ if ( currentFileBuildDiagnostics ) {
753
+ const buildDiagnostics = this . _getBuildOnlyDiagnostics ( currentFileBuildDiagnostics [ 1 ] , buildIds ) ;
754
+ this . _diagnosticsReportedByBuild . set ( uri , buildDiagnostics ) ;
755
+ }
756
+ }
757
+
758
+ private _getBuildOnlyDiagnostics ( diagnosticList : vscode . Diagnostic [ ] , buildOnlyIds : string [ ] ) : vscode . Diagnostic [ ] {
759
+ const buildOnlyDiagnostics : vscode . Diagnostic [ ] = [ ] ;
760
+ diagnosticList . forEach ( ( d ) => {
761
+ if ( d . code ) {
762
+ // Include diagnostic in the list if it is build
763
+ if ( buildOnlyIds . find ( ( b_id ) => b_id === d . code ) ) {
764
+ buildOnlyDiagnostics . push ( d ) ;
765
+ }
766
+ }
767
+ } ) ;
768
+
769
+ return buildOnlyDiagnostics ;
770
+ }
771
+
697
772
private registerExtensionsChanged ( ) {
698
773
// subscribe to extension change events so that we can get notified if C# Dev Kit is added/removed later.
699
774
this . _languageClient . addDisposable (
0 commit comments