|
5 | 5 |
|
6 | 6 | import * as serverUtils from '../omnisharp/utils'; |
7 | 7 | import { CancellationToken, DefinitionProvider, Location, Position, TextDocument, Uri } from 'vscode'; |
8 | | -import { GoToDefinitionRequest, MetadataRequest, MetadataSource } from '../omnisharp/protocol'; |
9 | | -import { createRequest, toLocation, toLocationFromUri } from '../omnisharp/typeConversion'; |
| 8 | +import { MetadataRequest, MetadataSource, V2 } from '../omnisharp/protocol'; |
| 9 | +import { createRequest, toRange3, toVscodeLocation } from '../omnisharp/typeConversion'; |
10 | 10 | import AbstractSupport from './abstractProvider'; |
11 | | -import DefinitionMetadataDocumentProvider from './definitionMetadataDocumentProvider'; |
| 11 | +import DefinitionMetadataOrSourceGeneratedDocumentProvider from './definitionMetadataDocumentProvider'; |
12 | 12 | import { OmniSharpServer } from '../omnisharp/server'; |
13 | 13 | import { LanguageMiddlewareFeature } from '../omnisharp/LanguageMiddlewareFeature'; |
| 14 | +import SourceGeneratedDocumentProvider from './sourceGeneratedDocumentProvider'; |
14 | 15 |
|
15 | 16 | export default class CSharpDefinitionProvider extends AbstractSupport implements DefinitionProvider { |
16 | | - private _definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider; |
17 | | - |
18 | | - constructor(server: OmniSharpServer, definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider, languageMiddlewareFeature: LanguageMiddlewareFeature) { |
| 17 | + constructor( |
| 18 | + server: OmniSharpServer, |
| 19 | + private definitionMetadataDocumentProvider: DefinitionMetadataOrSourceGeneratedDocumentProvider, |
| 20 | + private sourceGeneratedDocumentProvider: SourceGeneratedDocumentProvider, |
| 21 | + languageMiddlewareFeature: LanguageMiddlewareFeature) { |
19 | 22 | super(server, languageMiddlewareFeature); |
20 | | - |
21 | | - this._definitionMetadataDocumentProvider = definitionMetadataDocumentProvider; |
22 | 23 | } |
23 | 24 |
|
24 | 25 | public async provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location[]> { |
25 | 26 |
|
26 | | - let req = <GoToDefinitionRequest>createRequest(document, position); |
| 27 | + let req = <V2.GoToDefinitionRequest>createRequest(document, position); |
27 | 28 | req.WantMetadata = true; |
28 | 29 |
|
29 | | - let location: Location; |
| 30 | + const locations: Location[] = []; |
30 | 31 | try { |
31 | | - let gotoDefinitionResponse = await serverUtils.goToDefinition(this._server, req, token); |
| 32 | + const gotoDefinitionResponse = await serverUtils.goToDefinition(this._server, req, token); |
32 | 33 | // the defintion is in source |
33 | | - if (gotoDefinitionResponse && gotoDefinitionResponse.FileName) { |
| 34 | + if (gotoDefinitionResponse && gotoDefinitionResponse.Definitions) { |
34 | 35 |
|
35 | | - // if it is part of an already used metadata file, retrieve its uri instead of going to the physical file |
36 | | - if (gotoDefinitionResponse.FileName.startsWith("$metadata$")) { |
37 | | - const uri = this._definitionMetadataDocumentProvider.getExistingMetadataResponseUri(gotoDefinitionResponse.FileName); |
38 | | - location = toLocationFromUri(uri, gotoDefinitionResponse); |
39 | | - } else { |
40 | | - // if it is a normal source definition, convert the response to a location |
41 | | - location = toLocation(gotoDefinitionResponse); |
42 | | - } |
| 36 | + for (const definition of gotoDefinitionResponse.Definitions) { |
| 37 | + if (definition.Location.FileName.startsWith("$metadata$")) { |
| 38 | + // if it is part of an already used metadata file, retrieve its uri instead of going to the physical file |
| 39 | + const uri = this.definitionMetadataDocumentProvider.getExistingMetadataResponseUri(definition.Location.FileName); |
| 40 | + const vscodeRange = toRange3(definition.Location.Range); |
| 41 | + locations.push(new Location(uri, vscodeRange)); |
| 42 | + } else if (definition.MetadataSource) { |
| 43 | + // the definition is in metadata |
| 44 | + const metadataSource: MetadataSource = definition.MetadataSource; |
43 | 45 |
|
44 | | - // the definition is in metadata |
45 | | - } else if (gotoDefinitionResponse.MetadataSource) { |
46 | | - const metadataSource: MetadataSource = gotoDefinitionResponse.MetadataSource; |
| 46 | + // go to metadata endpoint for more information |
| 47 | + const metadataResponse = await serverUtils.getMetadata(this._server, <MetadataRequest>{ |
| 48 | + Timeout: 5000, |
| 49 | + AssemblyName: metadataSource.AssemblyName, |
| 50 | + VersionNumber: metadataSource.VersionNumber, |
| 51 | + ProjectName: metadataSource.ProjectName, |
| 52 | + Language: metadataSource.Language, |
| 53 | + TypeName: metadataSource.TypeName |
| 54 | + }); |
47 | 55 |
|
48 | | - // go to metadata endpoint for more information |
49 | | - const metadataResponse = await serverUtils.getMetadata(this._server, <MetadataRequest>{ |
50 | | - Timeout: 5000, |
51 | | - AssemblyName: metadataSource.AssemblyName, |
52 | | - VersionNumber: metadataSource.VersionNumber, |
53 | | - ProjectName: metadataSource.ProjectName, |
54 | | - Language: metadataSource.Language, |
55 | | - TypeName: metadataSource.TypeName |
56 | | - }); |
| 56 | + if (!metadataResponse || !metadataResponse.Source || !metadataResponse.SourceName) { |
| 57 | + continue; |
| 58 | + } |
57 | 59 |
|
58 | | - if (!metadataResponse || !metadataResponse.Source || !metadataResponse.SourceName) { |
59 | | - return; |
60 | | - } |
| 60 | + const uri: Uri = this.definitionMetadataDocumentProvider.addMetadataResponse(metadataResponse); |
| 61 | + const vscodeRange = toRange3(definition.Location.Range); |
| 62 | + locations.push(new Location(uri, vscodeRange)); |
| 63 | + } else if (definition.SourceGeneratedFileInfo) { |
| 64 | + // File is source generated |
| 65 | + let uri = this.sourceGeneratedDocumentProvider.tryGetExistingSourceGeneratedFile(definition.SourceGeneratedFileInfo); |
| 66 | + if (!uri) { |
| 67 | + const sourceGeneratedFileResponse = await serverUtils.getSourceGeneratedFile(this._server, definition.SourceGeneratedFileInfo, token); |
61 | 68 |
|
62 | | - const uri: Uri = this._definitionMetadataDocumentProvider.addMetadataResponse(metadataResponse); |
63 | | - location = new Location(uri, new Position(gotoDefinitionResponse.Line, gotoDefinitionResponse.Column)); |
| 69 | + if (!sourceGeneratedFileResponse || !sourceGeneratedFileResponse.Source || !sourceGeneratedFileResponse.SourceName) { |
| 70 | + continue; |
| 71 | + } |
| 72 | + |
| 73 | + uri = this.sourceGeneratedDocumentProvider.addSourceGeneratedFile(definition.SourceGeneratedFileInfo, sourceGeneratedFileResponse); |
| 74 | + } |
| 75 | + |
| 76 | + locations.push(new Location(uri, toRange3(definition.Location.Range))); |
| 77 | + } else { |
| 78 | + // if it is a normal source definition, convert the response to a location |
| 79 | + locations.push(toVscodeLocation(definition.Location)); |
| 80 | + } |
| 81 | + } |
64 | 82 | } |
65 | 83 |
|
66 | 84 | // Allow language middlewares to re-map its edits if necessary. |
67 | | - const result = await this._languageMiddlewareFeature.remap("remapLocations", [location], token); |
| 85 | + const result = await this._languageMiddlewareFeature.remap("remapLocations", locations, token); |
68 | 86 | return result; |
69 | 87 | } |
70 | 88 | catch (error) { |
|
0 commit comments