1
- import { combineLatest , from , Observable } from 'rxjs'
1
+ import { combineLatest , from , Observable , Unsubscribable } from 'rxjs'
2
2
import { map , switchMap } from 'rxjs/operators'
3
3
import { Location } from 'vscode-languageserver-types'
4
4
import { ReferenceParams , TextDocumentPositionParams , TextDocumentRegistrationOptions } from '../../protocol'
5
5
import { FeatureProviderRegistry } from './registry'
6
- import { flattenAndCompact } from './util'
6
+ import { flattenAndCompact , flattenAndCompactNonNull } from './util'
7
7
8
8
/**
9
9
* Function signature for retrieving related locations given a location (e.g., definition, implementation, and type
@@ -22,6 +22,33 @@ export class TextDocumentLocationProviderRegistry<
22
22
public getLocation ( params : P ) : Observable < L | L [ ] | null > {
23
23
return getLocation < P , L > ( this . providers , params )
24
24
}
25
+
26
+ public getLocationsWithProviderName ( params : P ) : Observable < { providerName : string ; location : L } [ ] | null > {
27
+ return getLocationsWithProviderName < P , L > ( this . providersWithName , params )
28
+ }
29
+
30
+ public readonly providersWithName : Observable <
31
+ { name : string ; provider : ProvideTextDocumentLocationSignature < P , L > } [ ]
32
+ > = this . entries . pipe (
33
+ map ( providers =>
34
+ providers . map ( ( { provider, registrationOptions } ) => ( {
35
+ name : registrationOptions . providerName ,
36
+ provider,
37
+ } ) )
38
+ )
39
+ )
40
+
41
+ public registerProvider (
42
+ registrationOptions : TextDocumentRegistrationOptions ,
43
+ provider : ProvideTextDocumentLocationSignature < P , L >
44
+ ) : Unsubscribable {
45
+ if ( ! registrationOptions . providerName ) {
46
+ // Input validation is necessary here, because registrationOptions is deserialized from
47
+ // the registration request and this is the first place where where we have the provider type.
48
+ throw new Error ( 'registered provider must have name' )
49
+ }
50
+ return super . registerProvider ( registrationOptions , provider )
51
+ }
25
52
}
26
53
27
54
/**
@@ -62,6 +89,35 @@ export function getLocations<
62
89
)
63
90
}
64
91
92
+ export function getLocationsWithProviderName <
93
+ P extends TextDocumentPositionParams = TextDocumentPositionParams ,
94
+ L extends Location = Location
95
+ > (
96
+ providersWithName : Observable < { name : string ; provider : ProvideTextDocumentLocationSignature < P , L > } [ ] > ,
97
+ params : P
98
+ ) : Observable < { providerName : string ; location : L } [ ] > {
99
+ return providersWithName . pipe (
100
+ switchMap ( async providersWithName => {
101
+ const resultsByProvider = await Promise . all (
102
+ providersWithName . map ( async ( { provider, name } ) => {
103
+ const providerRes = await provider ( params ) . toPromise ( )
104
+ return flattenAndCompactNonNull ( [ providerRes ] ) . map ( loc => ( {
105
+ providerName : name ,
106
+ location : loc ,
107
+ } ) )
108
+ } )
109
+ )
110
+ const flattenedResults : { providerName : string ; location : L } [ ] = [ ]
111
+ for ( const providerResults of resultsByProvider ) {
112
+ for ( const res of providerResults ) {
113
+ flattenedResults . push ( res )
114
+ }
115
+ }
116
+ return flattenedResults
117
+ } )
118
+ )
119
+ }
120
+
65
121
/**
66
122
* Provides reference results from all extensions.
67
123
*
0 commit comments