@@ -22,6 +22,8 @@ export class ScriptCompletion implements vscode.CompletionItemProvider {
2222 [ 'value' , vscode . CompletionItemKind . Value ] ,
2323 ] ) ;
2424
25+ private static readonly breakSymbols : string [ ] = [ ' ' , '.' , '[' , ']' , '{' , '}' , '(' , ')' , "'" , '"' , '=' , ':' , ';' , ',' , '&' , '|' , '/' , '!' , '*' , '+' , '-' , '?' , '%' , '^' , '~' , '`' ] ;
26+
2527 private xsdReference : XsdReference ;
2628 private xmlTracker : XmlStructureTracker ;
2729 private scriptProperties : ScriptProperties ;
@@ -166,6 +168,16 @@ export class ScriptCompletion implements vscode.CompletionItemProvider {
166168 return this . emptyCompletion ;
167169 }
168170
171+ private static getNearestBreakSymbolIndex ( text : string , before : boolean , exceptDot : boolean = false ) : number {
172+ const searchRange = before ? text . length - 1 : 0 ;
173+ for ( let i = searchRange ; i >= 0 && i < text . length ; i += before ? - 1 : 1 ) {
174+ if ( this . breakSymbols . includes ( text [ i ] ) && ( ! exceptDot || text [ i ] !== '.' ) ) {
175+ return i ;
176+ }
177+ }
178+ return - 1 ;
179+ }
180+
169181 public prepareCompletion ( document : vscode . TextDocument , position : vscode . Position , checkOnly : boolean , token ?: vscode . CancellationToken , context ?: vscode . CompletionContext ) : vscode . CompletionItem [ ] | vscode . CompletionList | undefined {
170182 const schema = getDocumentScriptType ( document ) ;
171183 if ( schema == '' ) {
@@ -233,6 +245,8 @@ export class ScriptCompletion implements vscode.CompletionItemProvider {
233245 return [ ] ; // Return empty list if only checking
234246 }
235247
248+ const attributeInfo = elementAttributes . find ( attr => attr . name === attribute . name ) ;
249+
236250 const attributeValue = document . getText ( attribute . valueRange ) ;
237251
238252 // If we're in an attribute value, we need to check for possible values
@@ -307,30 +321,31 @@ export class ScriptCompletion implements vscode.CompletionItemProvider {
307321 }
308322 textToProcessBefore = textToProcessBefore . substring ( 0 , position . character ) ;
309323 }
324+
325+ let lastBreakIndex = ScriptCompletion . getNearestBreakSymbolIndex ( textToProcessBefore , true ) ;
326+ let firstBreakIndex = ScriptCompletion . getNearestBreakSymbolIndex ( textToProcessAfter , false ) ;
327+
310328 const lastDollarIndex = textToProcessBefore . lastIndexOf ( '$' ) ;
311- if ( lastDollarIndex >= 0 ) {
312- const prefix = lastDollarIndex < textToProcessBefore . length ? textToProcessBefore . substring ( lastDollarIndex + 1 ) : '' ;
313- if ( prefix === '' || / ^ [ a - z A - Z 0 - 9 _ ] * $ / . test ( prefix ) ) {
314- let suffixLength = textToProcessAfter . length ;
315- for ( const breakSymbol of [ ' ' , '.' , '[' , ']' , '{' , '}' , '(' , ')' ] ) {
316- const breakIndex = textToProcessAfter . indexOf ( breakSymbol ) ;
317- if ( breakIndex >= 0 && breakIndex < suffixLength ) {
318- suffixLength = breakIndex ;
319- break ;
320- }
321- }
322- const variableRange = new vscode . Range (
323- position . translate ( 0 , - textToProcessBefore . length + lastDollarIndex + 1 ) ,
324- position . translate ( 0 , suffixLength )
325- ) ;
326- const variableCompletion = this . variablesTracker . getAllVariablesForDocumentMap ( document , position , prefix ) ;
327- for ( const [ variableName , info ] of variableCompletion . entries ( ) ) {
328- ScriptCompletion . addItem ( items , 'variable' , variableName , info , variableRange ) ;
329- }
330- return ScriptCompletion . makeCompletionList ( items , prefix ) ;
329+ const prefix = lastDollarIndex < textToProcessBefore . length ? textToProcessBefore . substring ( lastDollarIndex + 1 ) : '' ;
330+ if ( lastDollarIndex >= 0 && lastDollarIndex > lastBreakIndex && ( prefix === '' || / ^ [ a - z A - Z 0 - 9 _ ] * $ / . test ( prefix ) ) ) {
331+ if ( firstBreakIndex >= 0 ) {
332+ textToProcessAfter = textToProcessAfter . substring ( 0 , firstBreakIndex ) ;
331333 }
334+ const variableRange = new vscode . Range (
335+ position . translate ( 0 , - textToProcessBefore . length + lastDollarIndex + 1 ) ,
336+ position . translate ( 0 , textToProcessAfter . length )
337+ ) ;
338+ const variableCompletion = this . variablesTracker . getAllVariablesForDocumentMap ( document , position , prefix ) ;
339+ for ( const [ variableName , info ] of variableCompletion . entries ( ) ) {
340+ ScriptCompletion . addItem ( items , 'variable' , variableName , info , variableRange ) ;
341+ }
342+ return ScriptCompletion . makeCompletionList ( items , prefix ) ;
343+ } else {
344+ lastBreakIndex = ScriptCompletion . getNearestBreakSymbolIndex ( textToProcessBefore , true , true ) ;
345+ firstBreakIndex = ScriptCompletion . getNearestBreakSymbolIndex ( textToProcessAfter , false , true ) ;
346+ return this . scriptProperties . processText ( textToProcessBefore , textToProcessAfter , attributeInfo ?. type || 'undefined' ) || ScriptCompletion . emptyCompletion ;
332347 }
333- return this . scriptProperties . processText ( textToProcessBefore ) ;
348+ return ScriptCompletion . emptyCompletion ; // Skip if no valid prefix found
334349 } else {
335350 if ( checkOnly ) {
336351 return undefined ; // Return empty list if only checking
0 commit comments