Skip to content
This repository was archived by the owner on Nov 6, 2018. It is now read-only.

Commit c9dcf86

Browse files
committed
feat: add method to get locations with provider name
add TextDocumentLocationProviderRegistry.getLocationsWithProviderName method
1 parent d445230 commit c9dcf86

File tree

10 files changed

+88
-9
lines changed

10 files changed

+88
-9
lines changed

src/client/client.ts

+1
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ export class Client implements Unsubscribable {
468468
if (!options.documentSelector && this.options.documentSelector) {
469469
options.documentSelector = this.options.documentSelector
470470
}
471+
options.providerName = this.name
471472
const data: RegistrationData<any> = {
472473
id: registration.id,
473474
registerOptions: options,

src/client/features/common.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class TextDocumentFeature extends AbstractTextDocumentFeature<TextDocumentRegist
2828
}
2929
}
3030

31-
const FIXTURE_REGISTER_OPTIONS: TextDocumentRegistrationOptions = { documentSelector: ['*'] }
31+
const FIXTURE_REGISTER_OPTIONS: TextDocumentRegistrationOptions = { documentSelector: ['*'], providerName: 'test' }
3232

3333
describe('TextDocumentFeature', () => {
3434
describe('dynamic registration', () => {

src/client/features/hover.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ export class TextDocumentHoverFeature extends Feature<TextDocumentRegistrationOp
4242
}
4343
this.register(this.messages, {
4444
id: uuidv4(),
45-
registerOptions: { documentSelector },
45+
registerOptions: {
46+
documentSelector,
47+
providerName: this.client.name,
48+
},
4649
})
4750
}
4851

src/client/features/location.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ export abstract class TextDocumentLocationFeature<
5858
}
5959
this.register(this.messages, {
6060
id: uuidv4(),
61-
registerOptions: { documentSelector },
61+
registerOptions: {
62+
documentSelector,
63+
providerName: this.client.name,
64+
},
6265
})
6366
}
6467

src/client/features/textDocument.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe('TextDocumentNotificationFeature', () => {
4646
}
4747
}
4848

49-
const FIXTURE_REGISTER_OPTIONS: TextDocumentRegistrationOptions = { documentSelector: ['*'] }
49+
const FIXTURE_REGISTER_OPTIONS: TextDocumentRegistrationOptions = { documentSelector: ['*'], providerName: 'test' }
5050

5151
describe('registration', () => {
5252
it('supports dynamic registration and unregistration', () => {

src/client/features/textDocument.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ export class TextDocumentDidOpenFeature extends TextDocumentNotificationFeature<
124124
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) {
125125
this.register(this.messages, {
126126
id: uuidv4(),
127-
registerOptions: { documentSelector },
127+
registerOptions: {
128+
documentSelector,
129+
providerName: this.client.name,
130+
},
128131
})
129132
}
130133
}
@@ -171,7 +174,10 @@ export class TextDocumentDidCloseFeature extends TextDocumentNotificationFeature
171174
if (documentSelector && textDocumentSyncOptions && textDocumentSyncOptions.openClose) {
172175
this.register(this.messages, {
173176
id: uuidv4(),
174-
registerOptions: { documentSelector },
177+
registerOptions: {
178+
documentSelector,
179+
providerName: this.client.name,
180+
},
175181
})
176182
}
177183
}

src/environment/providers/location.ts

+58-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { combineLatest, from, Observable } from 'rxjs'
1+
import { combineLatest, from, Observable, Unsubscribable } from 'rxjs'
22
import { map, switchMap } from 'rxjs/operators'
33
import { Location } from 'vscode-languageserver-types'
44
import { ReferenceParams, TextDocumentPositionParams, TextDocumentRegistrationOptions } from '../../protocol'
55
import { FeatureProviderRegistry } from './registry'
6-
import { flattenAndCompact } from './util'
6+
import { flattenAndCompact, flattenAndCompactNonNull } from './util'
77

88
/**
99
* Function signature for retrieving related locations given a location (e.g., definition, implementation, and type
@@ -22,6 +22,33 @@ export class TextDocumentLocationProviderRegistry<
2222
public getLocation(params: P): Observable<L | L[] | null> {
2323
return getLocation<P, L>(this.providers, params)
2424
}
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+
}
2552
}
2653

2754
/**
@@ -62,6 +89,35 @@ export function getLocations<
6289
)
6390
}
6491

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+
65121
/**
66122
* Provides reference results from all extensions.
67123
*

src/environment/providers/registry.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface Entry<O, P> {
99

1010
/** Base class for provider registries for features. */
1111
export abstract class FeatureProviderRegistry<O, P> {
12-
private entries = new BehaviorSubject<Entry<O, P>[]>([])
12+
protected entries = new BehaviorSubject<Entry<O, P>[]>([])
1313

1414
public constructor(initialEntries?: Entry<O, P>[]) {
1515
if (initialEntries) {

src/environment/providers/util.ts

+5
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ export function flattenAndCompact<T>(value: (T | T[] | null)[] | null): T[] | nu
88
const merged = flatten(compact(value))
99
return merged.length === 0 ? null : merged
1010
}
11+
12+
/** Flattens and compacts the argument. If it is null or if the result is empty, it returns null. */
13+
export function flattenAndCompactNonNull<T>(value: (T | T[] | null)[] | null): T[] {
14+
return value ? flatten(compact(value)) : []
15+
}

src/protocol/textDocument.ts

+5
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,11 @@ export interface TextDocumentRegistrationOptions {
358358
* the document selector provided on the client side will be used.
359359
*/
360360
documentSelector: DocumentSelector | null
361+
362+
/**
363+
* User-visible name of the of the provider being registered.
364+
*/
365+
providerName: string
361366
}
362367

363368
/**

0 commit comments

Comments
 (0)