@@ -786,94 +786,92 @@ class DefaultClient implements Client {
786786 }
787787
788788 public async provideCustomConfiguration ( document : vscode . TextDocument ) : Promise < void > {
789- let tokenSource : CancellationTokenSource = new CancellationTokenSource ( ) ;
790- let providers : CustomConfigurationProviderCollection = getCustomConfigProviders ( ) ;
791- if ( providers . size === 0 ) {
792- return Promise . resolve ( ) ;
793- }
794- console . log ( "provideCustomConfiguration" ) ;
795- let providerId : string | undefined = await this . getCustomConfigurationProviderId ( ) ;
796- if ( ! providerId ) {
797- return Promise . resolve ( ) ;
798- }
789+ return this . queueBlockingTask ( async ( ) => {
790+ let tokenSource : CancellationTokenSource = new CancellationTokenSource ( ) ;
791+ let providers : CustomConfigurationProviderCollection = getCustomConfigProviders ( ) ;
792+ if ( providers . size === 0 ) {
793+ return Promise . resolve ( ) ;
794+ }
795+ console . log ( "provideCustomConfiguration" ) ;
796+ let providerId : string | undefined = this . configuration . CurrentConfigurationProvider ;
797+ if ( ! providerId ) {
798+ return Promise . resolve ( ) ;
799+ }
799800
800- let providerName : string = providerId ;
801- let params : QueryTranslationUnitSourceParams = {
802- uri : document . uri . toString ( )
803- } ;
804- let response : QueryTranslationUnitSourceResult = await this . requestWhenReady ( ( ) => this . languageClient . sendRequest ( QueryTranslationUnitSourceRequest , params ) ) ;
805- if ( response . configDisposition === QueryTranslationUnitSourceConfigDisposition . ConfigNotNeeded ) {
806- return Promise . resolve ( ) ;
807- }
801+ let providerName : string = providerId ;
802+ let params : QueryTranslationUnitSourceParams = {
803+ uri : document . uri . toString ( )
804+ } ;
805+ let response : QueryTranslationUnitSourceResult = await this . languageClient . sendRequest ( QueryTranslationUnitSourceRequest , params ) ;
806+ if ( response . configDisposition === QueryTranslationUnitSourceConfigDisposition . ConfigNotNeeded ) {
807+ return Promise . resolve ( ) ;
808+ }
808809
809- let tuUri : vscode . Uri = vscode . Uri . parse ( response . uri ) ;
810- let configName : string = await this . getCurrentConfigName ( ) ;
811- const notReadyMessage : string = `${ providerName } is not ready` ;
812- let provideConfigurationAsync : ( ) => Thenable < SourceFileConfigurationItem [ ] > = async ( ) => {
813- // The config requests that we use a provider, try to get IntelliSense configuration info from that provider.
814- try {
815- let provider : CustomConfigurationProvider1 | null = providers . get ( providerId ) ;
816- if ( provider ) {
817- if ( ! provider . isReady ) {
818- return Promise . reject ( notReadyMessage ) ;
819- }
810+ let tuUri : vscode . Uri = vscode . Uri . parse ( response . uri ) ;
811+ let configName : string = this . configuration . CurrentConfiguration . name ;
812+ const notReadyMessage : string = `${ providerName } is not ready` ;
813+ let provideConfigurationAsync : ( ) => Thenable < SourceFileConfigurationItem [ ] > = async ( ) => {
814+ // The config requests that we use a provider, try to get IntelliSense configuration info from that provider.
815+ try {
816+ let provider : CustomConfigurationProvider1 | null = providers . get ( providerId ) ;
817+ if ( provider ) {
818+ if ( ! provider . isReady ) {
819+ return Promise . reject ( notReadyMessage ) ;
820+ }
820821
821- providerName = provider . name ;
822- if ( await provider . canProvideConfiguration ( tuUri , tokenSource . token ) ) {
823- return provider . provideConfigurations ( [ tuUri ] , tokenSource . token ) ;
822+ providerName = provider . name ;
823+ if ( await provider . canProvideConfiguration ( tuUri , tokenSource . token ) ) {
824+ return provider . provideConfigurations ( [ tuUri ] , tokenSource . token ) ;
825+ }
824826 }
827+ } catch ( err ) {
825828 }
826- } catch ( err ) {
827- }
828- console . warn ( "failed to provide configuration" ) ;
829- return Promise . reject ( "" ) ;
830- } ;
829+ console . warn ( "failed to provide configuration" ) ;
830+ return Promise . reject ( "" ) ;
831+ } ;
831832
832- return this . queueTaskWithTimeout ( provideConfigurationAsync , configProviderTimeout , tokenSource ) . then (
833- ( configs : SourceFileConfigurationItem [ ] ) => {
834- if ( configs && configs . length > 0 ) {
835- this . sendCustomConfigurations ( configs , true ) ;
836- if ( response . configDisposition === QueryTranslationUnitSourceConfigDisposition . AncestorConfigNeeded ) {
837- // replacing uri with original uri
838- let newConfig : SourceFileConfigurationItem = { uri : document . uri , configuration : configs [ 0 ] . configuration } ;
839- this . sendCustomConfigurations ( [ newConfig ] , true ) ;
833+ return this . callTaskWithTimeout ( provideConfigurationAsync , configProviderTimeout , tokenSource ) . then (
834+ ( configs : SourceFileConfigurationItem [ ] ) => {
835+ if ( configs && configs . length > 0 ) {
836+ this . sendCustomConfigurations ( configs , false ) ;
837+ if ( response . configDisposition === QueryTranslationUnitSourceConfigDisposition . AncestorConfigNeeded ) {
838+ // replacing uri with original uri
839+ let newConfig : SourceFileConfigurationItem = { uri : document . uri , configuration : configs [ 0 ] . configuration } ;
840+ this . sendCustomConfigurations ( [ newConfig ] , false ) ;
841+ }
840842 }
841- }
842- } ,
843- ( err ) => {
844- if ( err === notReadyMessage ) {
845- return ;
846- }
847- let settings : CppSettings = new CppSettings ( this . RootUri ) ;
848- if ( settings . configurationWarnings === "Enabled" && ! this . isExternalHeader ( document . uri ) && ! vscode . debug . activeDebugSession ) {
849- const dismiss : string = "Dismiss" ;
850- const disable : string = "Disable Warnings" ;
851- let message : string = `'${ providerName } ' is unable to provide IntelliSense configuration information for '${ document . uri . fsPath } '. ` +
852- `Settings from the '${ configName } ' configuration will be used instead.` ;
853- if ( err ) {
854- message += ` (${ err } )` ;
843+ } ,
844+ ( err ) => {
845+ if ( err === notReadyMessage ) {
846+ return ;
855847 }
848+ let settings : CppSettings = new CppSettings ( this . RootUri ) ;
849+ if ( settings . configurationWarnings === "Enabled" && ! this . isExternalHeader ( document . uri ) && ! vscode . debug . activeDebugSession ) {
850+ const dismiss : string = "Dismiss" ;
851+ const disable : string = "Disable Warnings" ;
852+ let message : string = `'${ providerName } ' is unable to provide IntelliSense configuration information for '${ document . uri . fsPath } '. ` +
853+ `Settings from the '${ configName } ' configuration will be used instead.` ;
854+ if ( err ) {
855+ message += ` (${ err } )` ;
856+ }
856857
857- vscode . window . showInformationMessage ( message , dismiss , disable ) . then ( response => {
858+ vscode . window . showInformationMessage ( message , dismiss , disable ) . then ( response => {
858859 switch ( response ) {
859860 case disable : {
860861 settings . toggleSetting ( "configurationWarnings" , "Enabled" , "Disabled" ) ;
861862 break ;
862863 }
863864 }
864865 } ) ;
865- }
866- } ) ;
866+ }
867+ } ) ;
868+ } ) ;
867869 }
868870
869871 private isExternalHeader ( uri : vscode . Uri ) : boolean {
870872 return util . isHeader ( uri ) && ! uri . toString ( ) . startsWith ( this . RootUri . toString ( ) ) ;
871873 }
872874
873- private getCustomConfigurationProviderId ( ) : Thenable < string | undefined > {
874- return this . queueTask ( ( ) => Promise . resolve ( this . configuration . CurrentConfigurationProvider ) ) ;
875- }
876-
877875 public getCurrentConfigName ( ) : Thenable < string > {
878876 return this . queueTask ( ( ) => Promise . resolve ( this . configuration . CurrentConfiguration . name ) ) ;
879877 }
@@ -923,7 +921,7 @@ class DefaultClient implements Client {
923921
924922 if ( this . pendingTask && ! this . pendingTask . Done ) {
925923 // We don't want the queue to stall because of a rejected promise.
926- return this . pendingTask . then ( nextTask , nextTask ) ;
924+ return this . pendingTask . getPromise ( ) . then ( nextTask , nextTask ) ;
927925 } else {
928926 this . pendingTask = undefined ;
929927 return nextTask ( ) ;
@@ -941,6 +939,7 @@ class DefaultClient implements Client {
941939 private queueBlockingTask ( task : ( ) => Thenable < void > ) : Thenable < void > {
942940 if ( this . isSupported ) {
943941 this . pendingTask = new util . BlockingTask < void > ( task , this . pendingTask ) ;
942+ return this . pendingTask . getPromise ( ) ;
944943 } else {
945944 return Promise . reject ( "Unsupported client" ) ;
946945 }
@@ -973,6 +972,31 @@ class DefaultClient implements Client {
973972 } ) ;
974973 }
975974
975+ private callTaskWithTimeout ( task : ( ) => Thenable < any > , ms : number , cancelToken ?: CancellationTokenSource ) : Thenable < any > {
976+ let timer : NodeJS . Timer ;
977+ // Create a promise that rejects in <ms> milliseconds
978+ let timeout : ( ) => Promise < any > = ( ) => new Promise ( ( resolve , reject ) => {
979+ timer = setTimeout ( ( ) => {
980+ clearTimeout ( timer ) ;
981+ if ( cancelToken ) {
982+ cancelToken . cancel ( ) ;
983+ }
984+ reject ( "Timed out in " + ms + "ms." ) ;
985+ } , ms ) ;
986+ } ) ;
987+
988+ // Returns a race between our timeout and the passed in promise
989+ return Promise . race ( [ task ( ) , timeout ( ) ] ) . then (
990+ ( result : any ) => {
991+ clearTimeout ( timer ) ;
992+ return result ;
993+ } ,
994+ ( error : any ) => {
995+ clearTimeout ( timer ) ;
996+ throw error ;
997+ } ) ;
998+ }
999+
9761000 public requestWhenReady ( request : ( ) => Thenable < any > ) : Thenable < any > {
9771001 return this . queueTask ( request ) ;
9781002 }
0 commit comments