11import * as vscode from 'vscode' ;
22import { CancellationToken , DocumentSymbol , DocumentSymbolRequest , DocumentUri , LanguageClient , ProtocolNotificationType , ProtocolRequestType , Range , SymbolInformation , SymbolKind , TextDocumentIdentifier , TextDocumentItem , TextDocumentRegistrationOptions } from 'vscode-languageclient/node' ;
3- import { resolveVSCodeVariables } from './validator' ;
3+ import { resolveVSCodeVariables , ShaderLanguageClient } from './validator' ;
44
55interface ShaderVariantSerialized {
66 url : DocumentUri ,
@@ -121,7 +121,7 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
121121 // using vscode.Uri as key does not match well with Memento state storage...
122122 private files : Map < string , ShaderVariantFile > ;
123123 private tree : vscode . TreeView < ShaderVariantNode > ;
124- private client : LanguageClient ;
124+ private server : ShaderLanguageClient ;
125125 private decorator : vscode . TextEditorDecorationType ;
126126 private workspaceState : vscode . Memento ;
127127 private shaderEntryPointList : Map < string , ShaderEntryPoint [ ] > ;
@@ -143,12 +143,12 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
143143 this . workspaceState . update ( shaderVariantTreeKey , array ) ;
144144 }
145145
146- constructor ( context : vscode . ExtensionContext , client : LanguageClient ) {
146+ constructor ( context : vscode . ExtensionContext , server : ShaderLanguageClient ) {
147147 this . workspaceState = context . workspaceState ;
148148 this . files = new Map ;
149149 this . load ( ) ;
150150 this . shaderEntryPointList = new Map ;
151- this . client = client ;
151+ this . server = server ;
152152 this . tree = vscode . window . createTreeView < ShaderVariantNode > ( "shader-validator-variants" , {
153153 treeDataProvider : this
154154 // TODO: drag and drop for better ux.
@@ -252,6 +252,10 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
252252 this . save ( ) ;
253253 } ) ) ;
254254 context . subscriptions . push ( vscode . commands . registerCommand ( "shader-validator.gotoShaderEntryPoint" , ( uri : vscode . Uri , entryPointName : string ) => {
255+ // sometimes, its goes in random place in file...
256+ // TODO: Should use regex & read diag region instead.
257+ let diagnostic = vscode . languages . getDiagnostics ( ) . find ( ( [ diagUri , diags ] ) => diagUri === uri ) ;
258+
255259 this . goToShaderEntryPoint ( uri , entryPointName , true ) ;
256260 } ) ) ;
257261 // Prepare entry point symbol cache
@@ -268,6 +272,35 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
268272 context . subscriptions . push ( vscode . workspace . onDidCloseTextDocument ( document => {
269273 this . shaderEntryPointList . delete ( document . uri . path ) ;
270274 } ) ) ;
275+ context . subscriptions . push ( vscode . workspace . onDidRenameFiles ( document => {
276+ for ( const fileObj of document . files ) {
277+ const { oldUri, newUri } = fileObj ;
278+ // To update the key in a Map, you need to remove the old key and add the new one.
279+ const oldPath = oldUri . path ;
280+ const newPath = newUri . path ;
281+ const file = this . files . get ( oldPath ) ;
282+ if ( file ) {
283+ // Update the uri inside the file object
284+ file . uri = newUri ;
285+ // Remove the old key and set the new key
286+ this . files . delete ( oldPath ) ;
287+ this . files . set ( newPath , file ) ;
288+ }
289+ // Also update entry point and async maps
290+ const entryPoints = this . shaderEntryPointList . get ( oldPath ) ;
291+ if ( entryPoints ) {
292+ this . shaderEntryPointList . delete ( oldPath ) ;
293+ this . shaderEntryPointList . set ( newPath , entryPoints ) ;
294+ }
295+ const asyncEntryPoint = this . asyncGoToShaderEntryPoint . get ( oldUri ) ;
296+ if ( asyncEntryPoint ) {
297+ this . asyncGoToShaderEntryPoint . delete ( oldUri ) ;
298+ this . asyncGoToShaderEntryPoint . set ( newUri , asyncEntryPoint ) ;
299+ }
300+ this . shaderEntryPointList ;
301+ this . asyncGoToShaderEntryPoint ;
302+ }
303+ } ) ) ;
271304 this . updateDependencies ( ) ;
272305 }
273306 private getActiveVariant ( ) : ShaderVariant | null {
@@ -390,17 +423,17 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
390423 // Open document to get language ID.
391424 // This does not open the document in the editor, only internally.
392425 vscode . workspace . openTextDocument ( fileActiveVariant . uri ) . then ( doc => {
393- this . client . sendNotification ( didChangeShaderVariantNotification , {
426+ this . server . sendNotification ( didChangeShaderVariantNotification , {
394427 // Need this check again here because its async
395428 shaderVariant : fileActiveVariant ? shaderVariantToSerialized (
396- this . client . code2ProtocolConverter . asUri ( fileActiveVariant . uri ) ,
429+ this . server . uriAsString ( fileActiveVariant . uri ) ,
397430 capitalizeFirstLetter ( doc . languageId ) , // Server expect it with capitalized first letter.
398431 fileActiveVariant
399432 ) : null ,
400433 } ) ;
401434 } ) ;
402435 } else {
403- this . client . sendNotification ( didChangeShaderVariantNotification , {
436+ this . server . sendNotification ( didChangeShaderVariantNotification , {
404437 shaderVariant : null ,
405438 } ) ;
406439 }
@@ -421,24 +454,29 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
421454 // Dirty hack to trigger document symbol update
422455 // Ideally, it should retrigger dependencies aswell.
423456 // See https://github.com/microsoft/vscode/issues/108722 (Old one https://github.com/microsoft/vscode/issues/71454)
424- let visibleEditor = vscode . window . visibleTextEditors . find ( e => e . document . uri . path === uri . path ) ;
425- if ( visibleEditor ) {
426- let editor = visibleEditor ;
427- editor . edit ( editBuilder => {
428- for ( let iLine = 0 ; iLine < editor . document . lineCount ; iLine ++ ) {
429- // Find first non-empty line to avoid crashing on empty line with negative position.
430- let line = editor . document . lineAt ( iLine ) ;
431- if ( line . text . length > 0 ) {
432- const text = line . text ;
433- const c = line . range . end . character ;
434- // Remove last character of first line and add it back.
435- editBuilder . delete ( new vscode . Range ( iLine , c - 1 , iLine , c ) ) ;
436- editBuilder . insert ( new vscode . Position ( iLine , c ) , text [ c - 1 ] ) ;
437- break ;
457+
458+ // Only trigger it if requested by user as it may be a bit invasive.
459+ let updateSymbolsOnVariantUpdate = vscode . workspace . getConfiguration ( "shader-validator" ) . get < boolean > ( "updateSymbolsOnVariantUpdate" ) ;
460+ if ( updateSymbolsOnVariantUpdate ) {
461+ let visibleEditor = vscode . window . visibleTextEditors . find ( e => e . document . uri . path === uri . path ) ;
462+ if ( visibleEditor ) {
463+ let editor = visibleEditor ;
464+ editor . edit ( editBuilder => {
465+ for ( let iLine = 0 ; iLine < editor . document . lineCount ; iLine ++ ) {
466+ // Find first non-empty line to avoid crashing on empty line with negative position.
467+ let line = editor . document . lineAt ( iLine ) ;
468+ if ( line . text . length > 0 ) {
469+ const text = line . text ;
470+ const c = line . range . end . character ;
471+ // Remove last character of first line and add it back.
472+ editBuilder . delete ( new vscode . Range ( iLine , c - 1 , iLine , c ) ) ;
473+ editBuilder . insert ( new vscode . Position ( iLine , c ) , text [ c - 1 ] ) ;
474+ break ;
475+ }
438476 }
439- }
440- // All empty lines means no symbols !
441- } ) ;
477+ // All empty lines means no symbols !
478+ } ) ;
479+ }
442480 }
443481 }
444482 private updateDependency ( file : ShaderVariantFile ) {
@@ -568,6 +606,24 @@ export class ShaderVariantTreeDataProvider implements vscode.TreeDataProvider<Sh
568606 if ( uri . scheme !== 'file' ) {
569607 return ;
570608 }
609+ // If adding active variant, remove all currently active ones.
610+ if ( variant ) {
611+ if ( variant . isActive ) {
612+ for ( let [ url , file ] of this . files ) {
613+ let needRefresh = false ;
614+ for ( let otherVariant of file . variants ) {
615+ if ( otherVariant . isActive ) {
616+ needRefresh = true ;
617+ otherVariant . isActive = false ;
618+ }
619+ }
620+ if ( needRefresh ) {
621+ // Refresh file & all its childs
622+ this . refresh ( file , file ) ;
623+ }
624+ }
625+ }
626+ }
571627 let file = this . files . get ( uri . path ) ;
572628 if ( ! file ) {
573629 let newFile : ShaderVariantFile = {
0 commit comments