Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

README.md #1

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

README.md #1

wants to merge 1 commit into from

Conversation

Create-For-Fun
Copy link
Owner

From

8473b1e6da41e023320b5d426c3dbb77385cd9e5
Mon Sep 17 00:00:00 2001 From: Jackson Schuster [email protected] Date: Sun, 6 Mar 2022 00:27:02 -0800 Subject: [PATCH 1/2] Add GoToTypeDefinition provider PR OmniSharp/omnisharp-roslyn#2315 add a gototypedefinition endpoint. This PR adds a provider that utilizes the endpoint. --- src/features/typeDefinitionProvider.ts
| 98 ++++++++++++++++++++++++++ src/omnisharp/extension.ts
| 4 ++ src/omnisharp/prioritization.ts
| 3 +- src/omnisharp/protocol.ts
| 16 +++++ src/omnisharp/utils.ts
| 4 ++ 5 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/features/typeDefinitionProvider.ts
diff --git a/src/features/typeDefinitionProvider.ts b/src/features/typeDefinitionProvider.ts
new file mode 100644 index 000000000..6d00024a8
--- /dev/null +++ b/src/features/typeDefinitionProvider.ts @@ -0,0 +1,98 @@ +/--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + --------------------------------------------------------------------------------------------/ + +import * as serverUtils from '../omnisharp/utils'; +import { CancellationToken, TypeDefinitionProvider, Location, Position, TextDocument, Uri } from 'vscode'; +import { MetadataRequest, MetadataSource, GoToTypeDefinitionRequest, } from '../omnisharp/protocol'; +import { createRequest, toRange3, toVscodeLocation } from '../omnisharp/typeConversion'; +import AbstractSupport from './abstractProvider'; +import DefinitionMetadataOrSourceGeneratedDocumentProvider from './definitionMetadataDocumentProvider'; +import { OmniSharpServer } from '../omnisharp/server'; +import { LanguageMiddlewareFeature } from '../omnisharp/LanguageMiddlewareFeature'; +import SourceGeneratedDocumentProvider from './sourceGeneratedDocumentProvider'; + +export default class CSharpTypeDefinitionProvider extends AbstractSupport implements TypeDefinitionProvider { + constructor( + server: OmniSharpServer, + private definitionMetadataDocumentProvider: DefinitionMetadataOrSourceGeneratedDocumentProvider, + private sourceGeneratedDocumentProvider: SourceGeneratedDocumentProvider, + languageMiddlewareFeature: LanguageMiddlewareFeature) { + super(server, languageMiddlewareFeature); + } + + public async provideTypeDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location[]> { + + let req = createRequest(document, position); + req.WantMetadata = true; + + const locations: Location[] = []; + try { + const goToTypeDefinitionResponse = await serverUtils.goToTypeDefinition(this._server, req, token); + // the defintion is in source + if (goToTypeDefinitionResponse && goToTypeDefinitionResponse.Definitions) { + + for (const definition of goToTypeDefinitionResponse.Definitions) { + if (definition.MetadataSource) { + // the definition is in metadata + const metadataSource: MetadataSource = definition.MetadataSource; + + // Do we already have a document for this metadata reference? + if (definition.Location.FileName.startsWith("$metadata$") && + this.definitionMetadataDocumentProvider.hasMetadataDocument(definition.Location.FileName)) { + + // if it is part of an already used metadata file, retrieve its uri instead of going to the physical file + const uri = this.definitionMetadataDocumentProvider.getExistingMetadataResponseUri(definition.Location.FileName); + const vscodeRange = toRange3(definition.Location.Range); + locations.push(new Location(uri, vscodeRange)); + continue; + } + + // We need to go to the metadata endpoint for more information + const metadataResponse = await serverUtils.getMetadata(this._server, { + Timeout: 5000, + AssemblyName: metadataSource.AssemblyName, + VersionNumber: metadataSource.VersionNumber, + ProjectName: metadataSource.ProjectName, + Language: metadataSource.Language, + TypeName: metadataSource.TypeName + }); + + if (!metadataResponse || !metadataResponse.Source || !metadataResponse.SourceName) { + continue; + } + + const uri: Uri = this.definitionMetadataDocumentProvider.addMetadataResponse(metadataResponse); + const vscodeRange = toRange3(definition.Location.Range); + locations.push(new Location(uri, vscodeRange)); + } else if (definition.SourceGeneratedFileInfo) { + // File is source generated + let uri = this.sourceGeneratedDocumentProvider.tryGetExistingSourceGeneratedFile(definition.SourceGeneratedFileInfo); + if (!uri) { + const sourceGeneratedFileResponse = await serverUtils.getSourceGeneratedFile(this._server, definition.SourceGeneratedFileInfo, token); + + if (!sourceGeneratedFileResponse || !sourceGeneratedFileResponse.Source || !sourceGeneratedFileResponse.SourceName) { + continue; + } + + uri = this.sourceGeneratedDocumentProvider.addSourceGeneratedFile(definition.SourceGeneratedFileInfo, sourceGeneratedFileResponse); + } + + locations.push(new Location(uri, toRange3(definition.Location.Range))); + } else { + // if it is a normal source definition, convert the response to a location + locations.push(toVscodeLocation(definition.Location)); + } + } + } + + // Allow language middlewares to re-map its edits if necessary. + const result = await this._languageMiddlewareFeature.remap("remapLocations", locations, token); + return result; + } + catch (error) { + return []; + } + } +} diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 97505e497..f584ca5e4 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -14,6 +14,7 @@ import CodeLensProvider from '../features/codeLensProvider'; import CompletionProvider, { CompletionAfterInsertCommand } from '../features/completionProvider'; import DefinitionMetadataDocumentProvider from '../features/definitionMetadataDocumentProvider'; import DefinitionProvider from '../features/definitionProvider'; +import TypeDefinitionProvider from '../features/typeDefinitionProvider'; import DocumentHighlightProvider from '../features/documentHighlightProvider'; import DocumentSymbolProvider from '../features/documentSymbolProvider'; import FormatProvider from '../features/formattingEditProvider'; @@ -80,8 +81,11 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an sourceGeneratedDocumentProvider.register(); localDisposables.add(sourceGeneratedDocumentProvider); const definitionProvider = new DefinitionProvider(server, definitionMetadataDocumentProvider, sourceGeneratedDocumentProvider, languageMiddlewareFeature); + const typeDefinitionProvider = new TypeDefinitionProvider(server, definitionMetadataDocumentProvider, sourceGeneratedDocumentProvider, languageMiddlewareFeature); localDisposables.add(vscode.languages.registerDefinitionProvider(documentSelector, definitionProvider)); localDisposables.add(vscode.languages.registerDefinitionProvider({ scheme: definitionMetadataDocumentProvider.scheme }, definitionProvider)); + localDisposables.add(vscode.languages.registerTypeDefinitionProvider(documentSelector, typeDefinitionProvider)); + localDisposables.add(vscode.languages.registerTypeDefinitionProvider({ scheme: definitionMetadataDocumentProvider.scheme }, typeDefinitionProvider)); localDisposables.add(vscode.languages.registerImplementationProvider(documentSelector, new ImplementationProvider(server, languageMiddlewareFeature))); localDisposables.add(vscode.languages.registerCodeLensProvider(documentSelector, new CodeLensProvider(server, testManager, optionProvider, languageMiddlewareFeature))); localDisposables.add(vscode.languages.registerDocumentHighlightProvider(documentSelector, new DocumentHighlightProvider(server, languageMiddlewareFeature))); diff --git a/src/omnisharp/prioritization.ts b/src/omnisharp/prioritization.ts index 1484947bf..775e17336 100644 --- a/src/omnisharp/prioritization.ts +++ b/src/omnisharp/prioritization.ts @@ -22,7 +22,8 @@ const normalCommands = [ protocol.V2.Requests.GoToDefinition, protocol.Requests.RunCodeAction, protocol.Requests.SignatureHelp, - protocol.Requests.TypeLookup + protocol.Requests.TypeLookup, + protocol.Requests.GoToTypeDefinition ]; const prioritySet = new Set(priorityCommands); diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index d95c31ea1..098e5d303 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -17,6 +17,7 @@ export module Requests { export const FormatAfterKeystroke = '/formatAfterKeystroke'; export const FormatRange = '/formatRange'; export const GetCodeActions = '/getcodeactions'; + export const GoToTypeDefinition = '/gototypedefinition'; export const FindImplementations = '/findimplementations'; export const Project = '/project'; export const Projects = '/projects'; @@ -578,6 +579,21 @@ export enum UpdateType { export interface SourceGeneratedFileClosedRequest extends SourceGeneratedFileInfo { } +export interface Definition { + Location: V2.Location; + MetadataSource?: MetadataSource; + SourceGeneratedFileInfo?: SourceGeneratedFileInfo; +} + +export interface GoToTypeDefinitionRequest extends Request { + WantMetadata?: boolean; +} + +export interface GoToTypeDefinitionResponse { + Definitions?: Definition[]; +} + + export namespace V2 { export module Requests { diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 8a5186f6b..6a57bcfb0 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -67,6 +67,10 @@ export async function goToDefinition(server: OmniSharpServer, request: protocol. return server.makeRequest<protocol.V2.GoToDefinitionResponse>(protocol.V2.Requests.GoToDefinition, request, token); } +export async function goToTypeDefinition(server: OmniSharpServer, request: protocol.GoToTypeDefinitionRequest, token: vscode.CancellationToken) { + return server.makeRequest<protocol.GoToTypeDefinitionResponse>(protocol.Requests.GoToTypeDefinition, request, token); +} + export async function getSourceGeneratedFile(server: OmniSharpServer, request: protocol.SourceGeneratedFileRequest, token: vscode.CancellationToken) { return server.makeRequest<protocol.SourceGeneratedFileResponse>(protocol.Requests.SourceGeneratedFile, request, token); } From 6504e9dd57707beafd0d2caa64096fe0e5716d0a Mon Sep 17 00:00:00 2001 From: Jackson Schuster [email protected] Date: Sun, 6 Mar 2022 13:58:16 -0800 Subject: [PATCH 2/2] Add tests for GoToTypeDefinition --- .../testAssets/singleCsproj/typeDefinition.cs | 24 +++++++ .../typeDefinitionProvider.test.ts | 68 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 test/integrationTests/testAssets/singleCsproj/typeDefinition.cs create mode 100644 test/integrationTests/typeDefinitionProvider.test.ts diff --git a/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs b/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs new file mode 100644 index 000000000..addee4fde --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs @@ -0,0 +1,24 @@ + +using System; + +namespace Test +{ + public class LinkedList + { + public void MyMethod() + { + var linked = new LinkedList(); + var str = "test string"; + var part = new PartialClass(); + Console.WriteLine(str); + } + } + + public partial class PartialClass { + public string Foo {get; set;}; + } + + public partial class PartialClass { + public int Bar {get; set;} + } +} diff --git a/test/integrationTests/typeDefinitionProvider.test.ts b/test/integrationTests/typeDefinitionProvider.test.ts new file mode 100644 index 000000000..7da58011a --- /dev/null +++ b/test/integrationTests/typeDefinitionProvider.test.ts @@ -0,0 +1,68 @@ +/--------------------------------------------------------------------------------------------- +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +--------------------------------------------------------------------------------------------/ + +import * as vscode from "vscode"; +import CSharpDefinitionProvider from "../../src/features/typeDefinitionProvider"; +import * as path from "path"; +import testAssetWorkspace from "./testAssets/testAssetWorkspace"; +import { expect, should } from "chai"; +import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator, restartOmniSharpServer } from './integrationHelpers'; + +suite(${CSharpDefinitionProvider.name}: ${testAssetWorkspace.description}, () => { + let fileUri: vscode.Uri; + + suiteSetup(async function () { + should(); + + if (isRazorWorkspace(vscode.workspace) || isSlnWithGenerator(vscode.workspace)) { + this.skip(); + } + + const activation = await activateCSharpExtension(); + await testAssetWorkspace.restore(); + + const fileName = 'typeDefinition.cs'; + const projectDirectory = testAssetWorkspace.projects[0].projectDirectoryPath; + fileUri = vscode.Uri.file(path.join(projectDirectory, fileName)); + await vscode.commands.executeCommand("vscode.open", fileUri); + + await testAssetWorkspace.waitForIdle(activation.eventStream); + }); + + suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); + + test("Returns the type definition", async () => { + const definitionList = <vscode.Location[]>(await vscode.commands.executeCommand("vscode.executeTypeDefinitionProvider", fileUri, new vscode.Position(9, 18))); + expect(definitionList.length).to.be.equal(1); + expect(definitionList[0]).to.exist; + expect(definitionList[0].uri.path).to.contain("typeDefinition.cs"); + }); + + test("Returns the definition from Metadata", async () => { + const omnisharpConfig = vscode.workspace.getConfiguration('omnisharp'); + await omnisharpConfig.update('enableDecompilationSupport', false, vscode.ConfigurationTarget.Global); + await restartOmniSharpServer(); + + const definitionList = <vscode.Location[]>(await vscode.commands.executeCommand("vscode.executeTypeDefinitionProvider", fileUri, new vscode.Position(10, 18))); + expect(definitionList.length).to.be.equal(1); + expect(definitionList[0]).to.exist; + expect(definitionList[0].uri.path).to.contain("[metadata] String.cs"); + }); + + test("Returns multiple definitions for partial types", async () => { + const definitionList = <vscode.Location[]>(await vscode.commands.executeCommand("vscode.executeTypeDefinitionProvider", fileUri, new vscode.Position(11, 18))); + expect(definitionList.length).eq(2); + expect(definitionList[0]).to.exist; + expect(definitionList[0].uri.path).to.contain("typeDefinition.cs"); + expect(definitionList[1]).to.exist; + expect(definitionList[1].uri.path).to.contain("typeDefinition.cs"); + }); + + suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); +});

@Create-For-Fun
Copy link
Owner Author

diff --git a/src/features/typeDefinitionProvider.ts b/src/features/typeDefinitionProvider.ts new file mode 100644 index 000000000..6d00024a8 --- /dev/null +++ b/src/features/typeDefinitionProvider.ts @@ -0,0 +1,98 @@ +/--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + --------------------------------------------------------------------------------------------/ + +import * as serverUtils from '../omnisharp/utils'; +import { CancellationToken, TypeDefinitionProvider, Location, Position, TextDocument, Uri } from 'vscode'; +import { MetadataRequest, MetadataSource, GoToTypeDefinitionRequest, } from '../omnisharp/protocol'; +import { createRequest, toRange3, toVscodeLocation } from '../omnisharp/typeConversion'; +import AbstractSupport from './abstractProvider'; +import DefinitionMetadataOrSourceGeneratedDocumentProvider from './definitionMetadataDocumentProvider'; +import { OmniSharpServer } from '../omnisharp/server'; +import { LanguageMiddlewareFeature } from '../omnisharp/LanguageMiddlewareFeature'; +import SourceGeneratedDocumentProvider from './sourceGeneratedDocumentProvider'; + +export default class CSharpTypeDefinitionProvider extends AbstractSupport implements TypeDefinitionProvider { + constructor( + server: OmniSharpServer, + private definitionMetadataDocumentProvider: DefinitionMetadataOrSourceGeneratedDocumentProvider, + private sourceGeneratedDocumentProvider: SourceGeneratedDocumentProvider, + languageMiddlewareFeature: LanguageMiddlewareFeature) { + super(server, languageMiddlewareFeature); + } + + public async provideTypeDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location[]> { + + let req = createRequest(document, position); + req.WantMetadata = true; + + const locations: Location[] = []; + try { + const goToTypeDefinitionResponse = await serverUtils.goToTypeDefinition(this._server, req, token); + // the defintion is in source + if (goToTypeDefinitionResponse && goToTypeDefinitionResponse.Definitions) { + + for (const definition of goToTypeDefinitionResponse.Definitions) { + if (definition.MetadataSource) { + // the definition is in metadata + const metadataSource: MetadataSource = definition.MetadataSource; + + // Do we already have a document for this metadata reference? + if (definition.Location.FileName.startsWith("$metadata$") && + this.definitionMetadataDocumentProvider.hasMetadataDocument(definition.Location.FileName)) { + + // if it is part of an already used metadata file, retrieve its uri instead of going to the physical file + const uri = this.definitionMetadataDocumentProvider.getExistingMetadataResponseUri(definition.Location.FileName); + const vscodeRange = toRange3(definition.Location.Range); + locations.push(new Location(uri, vscodeRange)); + continue; + } + + // We need to go to the metadata endpoint for more information + const metadataResponse = await serverUtils.getMetadata(this._server, { + Timeout: 5000, + AssemblyName: metadataSource.AssemblyName, + VersionNumber: metadataSource.VersionNumber, + ProjectName: metadataSource.ProjectName, + Language: metadataSource.Language, + TypeName: metadataSource.TypeName + }); + + if (!metadataResponse || !metadataResponse.Source || !metadataResponse.SourceName) { + continue; + } + + const uri: Uri = this.definitionMetadataDocumentProvider.addMetadataResponse(metadataResponse); + const vscodeRange = toRange3(definition.Location.Range); + locations.push(new Location(uri, vscodeRange)); + } else if (definition.SourceGeneratedFileInfo) { + // File is source generated + let uri = this.sourceGeneratedDocumentProvider.tryGetExistingSourceGeneratedFile(definition.SourceGeneratedFileInfo); + if (!uri) { + const sourceGeneratedFileResponse = await serverUtils.getSourceGeneratedFile(this._server, definition.SourceGeneratedFileInfo, token); + + if (!sourceGeneratedFileResponse || !sourceGeneratedFileResponse.Source || !sourceGeneratedFileResponse.SourceName) { + continue; + } + + uri = this.sourceGeneratedDocumentProvider.addSourceGeneratedFile(definition.SourceGeneratedFileInfo, sourceGeneratedFileResponse); + } + + locations.push(new Location(uri, toRange3(definition.Location.Range))); + } else { + // if it is a normal source definition, convert the response to a location + locations.push(toVscodeLocation(definition.Location)); + } + } + } + + // Allow language middlewares to re-map its edits if necessary. + const result = await this._languageMiddlewareFeature.remap("remapLocations", locations, token); + return result; + } + catch (error) { + return []; + } + } +} diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 97505e497..f584ca5e4 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -14,6 +14,7 @@ import CodeLensProvider from '../features/codeLensProvider'; import CompletionProvider, { CompletionAfterInsertCommand } from '../features/completionProvider'; import DefinitionMetadataDocumentProvider from '../features/definitionMetadataDocumentProvider'; import DefinitionProvider from '../features/definitionProvider'; +import TypeDefinitionProvider from '../features/typeDefinitionProvider'; import DocumentHighlightProvider from '../features/documentHighlightProvider'; import DocumentSymbolProvider from '../features/documentSymbolProvider'; import FormatProvider from '../features/formattingEditProvider'; @@ -80,8 +81,11 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an sourceGeneratedDocumentProvider.register(); localDisposables.add(sourceGeneratedDocumentProvider); const definitionProvider = new DefinitionProvider(server, definitionMetadataDocumentProvider, sourceGeneratedDocumentProvider, languageMiddlewareFeature); + const typeDefinitionProvider = new TypeDefinitionProvider(server, definitionMetadataDocumentProvider, sourceGeneratedDocumentProvider, languageMiddlewareFeature); localDisposables.add(vscode.languages.registerDefinitionProvider(documentSelector, definitionProvider)); localDisposables.add(vscode.languages.registerDefinitionProvider({ scheme: definitionMetadataDocumentProvider.scheme }, definitionProvider)); + localDisposables.add(vscode.languages.registerTypeDefinitionProvider(documentSelector, typeDefinitionProvider)); + localDisposables.add(vscode.languages.registerTypeDefinitionProvider({ scheme: definitionMetadataDocumentProvider.scheme }, typeDefinitionProvider)); localDisposables.add(vscode.languages.registerImplementationProvider(documentSelector, new ImplementationProvider(server, languageMiddlewareFeature))); localDisposables.add(vscode.languages.registerCodeLensProvider(documentSelector, new CodeLensProvider(server, testManager, optionProvider, languageMiddlewareFeature))); localDisposables.add(vscode.languages.registerDocumentHighlightProvider(documentSelector, new DocumentHighlightProvider(server, languageMiddlewareFeature))); diff --git a/src/omnisharp/prioritization.ts b/src/omnisharp/prioritization.ts index 1484947bf..775e17336 100644 --- a/src/omnisharp/prioritization.ts +++ b/src/omnisharp/prioritization.ts @@ -22,7 +22,8 @@ const normalCommands = [ protocol.V2.Requests.GoToDefinition, protocol.Requests.RunCodeAction, protocol.Requests.SignatureHelp, - protocol.Requests.TypeLookup + protocol.Requests.TypeLookup, + protocol.Requests.GoToTypeDefinition ]; const prioritySet = new Set(priorityCommands); diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index d95c31ea1..098e5d303 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -17,6 +17,7 @@ export module Requests { export const FormatAfterKeystroke = '/formatAfterKeystroke'; export const FormatRange = '/formatRange'; export const GetCodeActions = '/getcodeactions'; + export const GoToTypeDefinition = '/gototypedefinition'; export const FindImplementations = '/findimplementations'; export const Project = '/project'; export const Projects = '/projects'; @@ -578,6 +579,21 @@ export enum UpdateType { export interface SourceGeneratedFileClosedRequest extends SourceGeneratedFileInfo { } +export interface Definition { + Location: V2.Location; + MetadataSource?: MetadataSource; + SourceGeneratedFileInfo?: SourceGeneratedFileInfo; +} + +export interface GoToTypeDefinitionRequest extends Request { + WantMetadata?: boolean; +} + +export interface GoToTypeDefinitionResponse { + Definitions?: Definition[]; +} + + export namespace V2 { export module Requests { diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 8a5186f6b..6a57bcfb0 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -67,6 +67,10 @@ export async function goToDefinition(server: OmniSharpServer, request: protocol. return server.makeRequest<protocol.V2.GoToDefinitionResponse>(protocol.V2.Requests.GoToDefinition, request, token); } +export async function goToTypeDefinition(server: OmniSharpServer, request: protocol.GoToTypeDefinitionRequest, token: vscode.CancellationToken) { + return server.makeRequest<protocol.GoToTypeDefinitionResponse>(protocol.Requests.GoToTypeDefinition, request, token); +} + export async function getSourceGeneratedFile(server: OmniSharpServer, request: protocol.SourceGeneratedFileRequest, token: vscode.CancellationToken) { return server.makeRequest<protocol.SourceGeneratedFileResponse>(protocol.Requests.SourceGeneratedFile, request, token); } diff --git a/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs b/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs new file mode 100644 index 000000000..addee4fde --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs @@ -0,0 +1,24 @@ + +using System; + +namespace Test +{ + public class LinkedList + { + public void MyMethod() + { + var linked = new LinkedList(); + var str = "test string"; + var part = new PartialClass(); + Console.WriteLine(str); + } + } + + public partial class PartialClass { + public string Foo {get; set;}; + } + + public partial class PartialClass { + public int Bar {get; set;} + } +} diff --git a/test/integrationTests/typeDefinitionProvider.test.ts b/test/integrationTests/typeDefinitionProvider.test.ts new file mode 100644 index 000000000..7da58011a --- /dev/null +++ b/test/integrationTests/typeDefinitionProvider.test.ts @@ -0,0 +1,68 @@ +/--------------------------------------------------------------------------------------------- +* Copyright (c) Microsoft Corporation. All rights reserved. +* Licensed under the MIT License. See License.txt in the project root for license information. +--------------------------------------------------------------------------------------------/ + +import * as vscode from "vscode"; +import CSharpDefinitionProvider from "../../src/features/typeDefinitionProvider"; +import * as path from "path"; +import testAssetWorkspace from "./testAssets/testAssetWorkspace"; +import { expect, should } from "chai"; +import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator, restartOmniSharpServer } from './integrationHelpers'; + +suite(${CSharpDefinitionProvider.name}: ${testAssetWorkspace.description}, () => { + let fileUri: vscode.Uri; + + suiteSetup(async function () { + should(); + + if (isRazorWorkspace(vscode.workspace) || isSlnWithGenerator(vscode.workspace)) { + this.skip(); + } + + const activation = await activateCSharpExtension(); + await testAssetWorkspace.restore(); + + const fileName = 'typeDefinition.cs'; + const projectDirectory = testAssetWorkspace.projects[0].projectDirectoryPath; + fileUri = vscode.Uri.file(path.join(projectDirectory, fileName)); + await vscode.commands.executeCommand("vscode.open", fileUri); + + await testAssetWorkspace.waitForIdle(activation.eventStream); + }); + + suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); + + test("Returns the type definition", async () => { + const definitionList = <vscode.Location[]>(await vscode.commands.executeCommand("vscode.executeTypeDefinitionProvider", fileUri, new vscode.Position(9, 18))); + expect(definitionList.length).to.be.equal(1); + expect(definitionList[0]).to.exist; + expect(definitionList[0].uri.path).to.contain("typeDefinition.cs"); + }); + + test("Returns the definition from Metadata", async () => { + const omnisharpConfig = vscode.workspace.getConfiguration('omnisharp'); + await omnisharpConfig.update('enableDecompilationSupport', false, vscode.ConfigurationTarget.Global); + await restartOmniSharpServer(); + + const definitionList = <vscode.Location[]>(await vscode.commands.executeCommand("vscode.executeTypeDefinitionProvider", fileUri, new vscode.Position(10, 18))); + expect(definitionList.length).to.be.equal(1); + expect(definitionList[0]).to.exist; + expect(definitionList[0].uri.path).to.contain("[metadata] String.cs"); + }); + + test("Returns multiple definitions for partial types", async () => { + const definitionList = <vscode.Location[]>(await vscode.commands.executeCommand("vscode.executeTypeDefinitionProvider", fileUri, new vscode.Position(11, 18))); + expect(definitionList.length).eq(2); + expect(definitionList[0]).to.exist; + expect(definitionList[0].uri.path).to.contain("typeDefinition.cs"); + expect(definitionList[1]).to.exist; + expect(definitionList[1].uri.path).to.contain("typeDefinition.cs"); + }); + + suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); +});

@Create-For-Fun Create-For-Fun mentioned this pull request Mar 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant