@@ -10,6 +10,7 @@ import { SvelteCheck } from 'svelte-language-server';
1010import { Diagnostic , DiagnosticSeverity } from 'vscode-languageserver-protocol' ;
1111import { URI } from 'vscode-uri' ;
1212import { HumanFriendlyWriter , MachineFriendlyWriter , Writer } from './writers' ;
13+ import { watch } from 'chokidar' ;
1314
1415const outputFormats = [ 'human' , 'human-verbose' , 'machine' ] as const ;
1516type OutputFormat = typeof outputFormats [ number ] ;
@@ -20,58 +21,105 @@ type Result = {
2021 warningCount : number ;
2122} ;
2223
23- async function getDiagnostics ( workspaceUri : URI , writer : Writer ) : Promise < Result | null > {
24- writer . start ( workspaceUri . fsPath ) ;
25-
26- const svelteCheck = new SvelteCheck ( workspaceUri . fsPath ) ;
27-
24+ function openAllDocuments (
25+ workspaceUri : URI ,
26+ filePathsToIgnore : string [ ] ,
27+ svelteCheck : SvelteCheck ,
28+ ) {
2829 const files = glob . sync ( '**/*.svelte' , {
2930 cwd : workspaceUri . fsPath ,
30- ignore : [ 'node_modules/**' ] ,
31+ ignore : [ 'node_modules/**' ] . concat ( filePathsToIgnore . map ( ( ignore ) => ` ${ ignore } /**` ) ) ,
3132 } ) ;
3233
3334 const absFilePaths = files . map ( ( f ) => path . resolve ( workspaceUri . fsPath , f ) ) ;
3435
35- const result = {
36- fileCount : absFilePaths . length ,
37- errorCount : 0 ,
38- warningCount : 0 ,
39- } ;
40-
4136 for ( const absFilePath of absFilePaths ) {
4237 const text = fs . readFileSync ( absFilePath , 'utf-8' ) ;
38+ svelteCheck . upsertDocument ( {
39+ uri : URI . file ( absFilePath ) . toString ( ) ,
40+ text,
41+ } ) ;
42+ }
43+ }
4344
44- let res : Diagnostic [ ] = [ ] ;
45+ async function getDiagnostics (
46+ workspaceUri : URI ,
47+ writer : Writer ,
48+ svelteCheck : SvelteCheck ,
49+ ) : Promise < Result | null > {
50+ writer . start ( workspaceUri . fsPath ) ;
4551
46- try {
47- res = await svelteCheck . getDiagnostics ( {
48- uri : URI . file ( absFilePath ) . toString ( ) ,
49- text,
52+ try {
53+ const diagnostics = await svelteCheck . getDiagnostics ( ) ;
54+
55+ const result : Result = {
56+ fileCount : diagnostics . length ,
57+ errorCount : 0 ,
58+ warningCount : 0 ,
59+ } ;
60+
61+ for ( const diagnostic of diagnostics ) {
62+ writer . file (
63+ diagnostic . diagnostics ,
64+ workspaceUri . fsPath ,
65+ path . relative ( workspaceUri . fsPath , diagnostic . filePath ) ,
66+ diagnostic . text ,
67+ ) ;
68+
69+ diagnostic . diagnostics . forEach ( ( d : Diagnostic ) => {
70+ if ( d . severity === DiagnosticSeverity . Error ) {
71+ result . errorCount += 1 ;
72+ } else if ( d . severity === DiagnosticSeverity . Warning ) {
73+ result . warningCount += 1 ;
74+ }
5075 } ) ;
51- } catch ( err ) {
52- writer . failure ( err ) ;
53- return null ;
5476 }
5577
56- writer . file (
57- res ,
58- workspaceUri . fsPath ,
59- path . relative ( workspaceUri . fsPath , absFilePath ) ,
60- text ,
61- ) ;
78+ writer . completion ( result . fileCount , result . errorCount , result . warningCount ) ;
79+ return result ;
80+ } catch ( err ) {
81+ writer . failure ( err ) ;
82+ return null ;
83+ }
84+ }
6285
63- res . forEach ( ( d : Diagnostic ) => {
64- if ( d . severity === DiagnosticSeverity . Error ) {
65- result . errorCount += 1 ;
66- } else if ( d . severity === DiagnosticSeverity . Warning ) {
67- result . warningCount += 1 ;
68- }
69- } ) ;
86+ class DiagnosticsWatcher {
87+ private updateDiagnostics : any ;
88+
89+ constructor (
90+ private workspaceUri : URI ,
91+ private svelteCheck : SvelteCheck ,
92+ private writer : Writer ,
93+ filePathsToIgnore : string [ ] ,
94+ ) {
95+ watch ( `${ workspaceUri . fsPath } /**/*.svelte` , {
96+ ignored : [ 'node_modules' ]
97+ . concat ( filePathsToIgnore )
98+ . map ( ( ignore ) => path . join ( workspaceUri . fsPath , ignore ) ) ,
99+ } )
100+ . on ( 'add' , ( path ) => this . updateDocument ( path ) )
101+ . on ( 'unlink' , ( path ) => this . removeDocument ( path ) )
102+ . on ( 'change' , ( path ) => this . updateDocument ( path ) ) ;
70103 }
71104
72- writer . completion ( result . fileCount , result . errorCount , result . warningCount ) ;
105+ private updateDocument ( path : string ) {
106+ const text = fs . readFileSync ( path , 'utf-8' ) ;
107+ this . svelteCheck . upsertDocument ( { text, uri : URI . file ( path ) . toString ( ) } ) ;
108+ this . scheduleDiagnostics ( ) ;
109+ }
73110
74- return result ;
111+ private removeDocument ( path : string ) {
112+ this . svelteCheck . removeDocument ( URI . file ( path ) . toString ( ) ) ;
113+ this . scheduleDiagnostics ( ) ;
114+ }
115+
116+ private scheduleDiagnostics ( ) {
117+ clearTimeout ( this . updateDiagnostics ) ;
118+ this . updateDiagnostics = setTimeout (
119+ ( ) => getDiagnostics ( this . workspaceUri , this . writer , this . svelteCheck ) ,
120+ 1000 ,
121+ ) ;
122+ }
75123}
76124
77125( async ( ) => {
@@ -99,12 +147,23 @@ async function getDiagnostics(workspaceUri: URI, writer: Writer): Promise<Result
99147 writer = new MachineFriendlyWriter ( process . stdout ) ;
100148 }
101149
102- const result = await getDiagnostics ( workspaceUri , writer ) ;
150+ const svelteCheck = new SvelteCheck ( workspaceUri . fsPath ) ;
151+ const filePathsToIgnore = myArgs [ 'ignore' ] . split ( ' ' ) || [ ] ;
103152
104- if ( result && ( result as Result ) . errorCount === 0 ) {
105- process . exit ( 0 ) ;
153+ if ( myArgs [ 'watch' ] ) {
154+ new DiagnosticsWatcher ( workspaceUri , svelteCheck , writer , filePathsToIgnore ) ;
106155 } else {
107- process . exit ( 1 ) ;
156+ openAllDocuments ( workspaceUri , filePathsToIgnore , svelteCheck ) ;
157+ const result = await getDiagnostics ( workspaceUri , writer , svelteCheck ) ;
158+ if (
159+ result &&
160+ result . errorCount === 0 &&
161+ ( ! myArgs [ 'fail-on-warnings' ] || result . warningCount === 0 )
162+ ) {
163+ process . exit ( 0 ) ;
164+ } else {
165+ process . exit ( 1 ) ;
166+ }
108167 }
109168} ) ( ) . catch ( ( _err ) => {
110169 console . error ( _err ) ;
0 commit comments