import * as vscode from 'vscode' ; import { DefaultClient , workspaceReferences , FindAllReferencesParams , ReferencesCancellationState , RequestReferencesNotification , CancelReferencesNotification } from '../client' ; import { Position } from 'vscode-languageclient' ; import * as refs from '../references' ; export class FindAllReferencesProvider implements vscode . ReferenceProvider { private client : DefaultClient ; constructor ( client ) { this . client = client ; } public async provideReferences ( document , position , context , token ) { return new Promise < vscode . Location [ ] > ( ( resolve , reject ) => { const callback = async ( ) => { const params = { position : Position . create ( position . line , position . character ) , textDocument : this . client . languageClient . code2ProtocolConverter . asTextDocumentIdentifier ( document ) } ; DefaultClient . referencesParams = params ; await this . client . awaitUntilLanguageClientReady ( ) ; if ( params !== DefaultClient . referencesParams ) { const locations = [ ] ; resolve ( locations ) ; return ; } DefaultClient . referencesRequestPending = true ; const resultCallback = ( result , doResolve ) => { DefaultClient . referencesRequestPending = false ; const locations = [ ] ; if ( result ) { result . referenceInfos . forEach ( ( referenceInfo ) => { if ( referenceInfo . type === refs . ReferenceType . Confirmed ) { const uri = vscode . Uri . file ( referenceInfo . file ) ; const range = new vscode . Range ( referenceInfo . position . line , referenceInfo . position . character , referenceInfo . position . line , referenceInfo . position . character + result . text . length ) ; locations . push ( new vscode . Location ( uri , range ) ) ; } } ) ; } if ( doResolve ) { resolve ( locations ) ; } if ( DefaultClient . referencesPendingCancellations . length > 0 ) { while ( DefaultClient . referencesPendingCancellations . length > 1 ) { const pendingCancel = DefaultClient . referencesPendingCancellations [ 0 ] ; DefaultClient . referencesPendingCancellations . pop ( ) ; pendingCancel . reject ( ) ; } const pendingCancel = DefaultClient . referencesPendingCancellations [ 0 ] ; DefaultClient . referencesPendingCancellations . pop ( ) ; pendingCancel . callback ( ) ; } } ; if ( ! workspaceReferences . referencesRefreshPending ) { workspaceReferences . setResultsCallback ( resultCallback ) ; workspaceReferences . startFindAllReferences ( params ) ; } else { workspaceReferences . referencesRefreshPending = false ; if ( workspaceReferences . lastResults ) { const lastResults = workspaceReferences . lastResults ; workspaceReferences . lastResults = null ; resultCallback ( lastResults , true ) ; } else { workspaceReferences . referencesRequestPending = true ; workspaceReferences . setResultsCallback ( resultCallback ) ; this . client . languageClient . sendNotification ( RequestReferencesNotification , false ) ; } } token . onCancellationRequested ( e => { if ( params === DefaultClient . referencesParams ) { this . client . cancelReferences ( ) ; } } ) ; } ; if ( DefaultClient . referencesRequestPending || ( workspaceReferences . symbolSearchInProgress && ! workspaceReferences . referencesRefreshPending ) ) { const cancelling = DefaultClient . referencesPendingCancellations . length > 0 ; DefaultClient . referencesPendingCancellations . push ( { reject : ( ) => { const locations = [ ] ; resolve ( locations ) ; } , callback } ) ; if ( ! cancelling ) { DefaultClient . renamePending = false ; workspaceReferences . referencesCanceled = true ; if ( ! DefaultClient . referencesRequestPending ) { workspaceReferences . referencesCanceledWhilePreviewing = true ; } this . client . languageClient . sendNotification ( CancelReferencesNotification ) ; } } else { callback ( ) ; } } ) ; } }