88 CompletionItemKind ,
99 CompletionItemProvider ,
1010 CompletionList ,
11+ Diagnostic ,
12+ DiagnosticSeverity ,
1113 Disposable ,
1214 Position ,
1315 ProviderResult ,
@@ -171,10 +173,12 @@ export class SelectorCompletionItemProvider implements CompletionItemProvider, D
171173 }
172174 }
173175
174- async findExtendedStyles ( uri : Uri , keys : Set < string > , text : string ) : Promise < void > {
176+ async findExtendedStyles ( uri : Uri , keys : Set < string > , text : string , level : number = 0 ) : Promise < void > {
175177 const extended = this . findExtended . exec ( text ) ;
176178
177- if ( extended ) {
179+ if ( extended && level < 3 ) {
180+ level ++ ;
181+
178182 const name = extended [ 2 ] ;
179183 const ext = extname ( name ) || extname ( uri . fsPath ) ;
180184 const key = this . getRelativePath ( uri , name , ext ) ;
@@ -185,7 +189,9 @@ export class SelectorCompletionItemProvider implements CompletionItemProvider, D
185189 const text = content . toString ( ) ;
186190
187191 this . findDocumentStyles ( file , keys , text ) ;
192+
188193 await this . findDocumentLinks ( file , keys , text ) ;
194+ await this . findExtendedStyles ( file , keys , text , level ) ;
189195 } catch ( error ) {
190196 }
191197 }
@@ -211,6 +217,47 @@ export class SelectorCompletionItemProvider implements CompletionItemProvider, D
211217 return { ids, classes } ;
212218 }
213219
220+ async validate ( document : TextDocument ) : Promise < Diagnostic [ ] > {
221+ const completion = await this . findAll ( document ) ;
222+ const text = document . getText ( ) ;
223+ const diagnostics : Diagnostic [ ] = [ ] ;
224+ const findAttribute = / ( i d | c l a s s | c l a s s N a m e ) \s * = \s * ( " | ' ) ( .* ?) \2/ gsi;
225+
226+ let attribute ;
227+
228+ while ( ( attribute = findAttribute . exec ( text ) ) !== null ) {
229+ const offset = findAttribute . lastIndex
230+ - attribute [ 3 ] . length
231+ + attribute [ 3 ] . indexOf ( attribute [ 2 ] ) ;
232+
233+ const findSelector = / ( [ ^ ( \[ { } \] ) \s ] + ) (? ! [ ^ ( \[ { ] * [ } \] ) ] ) / gi;
234+
235+ let value ;
236+
237+ while ( ( value = findSelector . exec ( attribute [ 3 ] ) ) !== null ) {
238+ const anchor = findSelector . lastIndex + offset ;
239+ const end = document . positionAt ( anchor ) ;
240+ const start = document . positionAt ( anchor - value [ 1 ] . length ) ;
241+
242+ if ( attribute [ 1 ] === "id" ) {
243+ if ( ! completion . ids . has ( value [ 1 ] ) ) {
244+ diagnostics . push ( new Diagnostic ( new Range ( start , end ) ,
245+ `CSS id selector '${ value [ 1 ] } ' not found.` ,
246+ DiagnosticSeverity . Information ) ) ;
247+ }
248+ } else {
249+ if ( ! completion . classes . has ( value [ 1 ] ) ) {
250+ diagnostics . push ( new Diagnostic ( new Range ( start , end ) ,
251+ `CSS class selector '${ value [ 1 ] } ' not found.` ,
252+ DiagnosticSeverity . Information ) ) ;
253+ }
254+ }
255+ }
256+ }
257+
258+ return diagnostics ;
259+ }
260+
214261 provideCompletionItems (
215262 document : TextDocument ,
216263 position : Position ,
0 commit comments