public async Task <IActionResult> FindImplementations([FromBody] Request request) { _workspace.EnsureBufferUpdated(request); var document = _workspace.GetDocument(request.FileName); var response = new QuickFixResponse(); if (document != null) { var semanticModel = await document.GetSemanticModelAsync(); var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line - 1, request.Column - 1)); var symbol = SymbolFinder.FindSymbolAtPosition(semanticModel, position, _workspace); var implementations = await SymbolFinder.FindImplementationsAsync(symbol, _workspace.CurrentSolution); var quickFixes = new List <QuickFix>(); foreach (var implementation in implementations) { foreach (var location in implementation.Locations) { AddQuickFix(quickFixes, location); } } response = new QuickFixResponse(quickFixes.OrderBy(q => q.FileName) .ThenBy(q => q.Line) .ThenBy(q => q.Column)); } return(new ObjectResult(response)); }
public async Task <QuickFixResponse> FindImplementations([FromBody] Request request) { _workspace.EnsureBufferUpdated(request); var document = _workspace.GetDocument(request.FileName); var response = new QuickFixResponse(); if (document != null) { var semanticModel = await document.GetSemanticModelAsync(); var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line - 1, request.Column - 1)); var symbol = SymbolFinder.FindSymbolAtPosition(semanticModel, position, _workspace); var quickFixes = new List <QuickFix>(); var implementations = await SymbolFinder.FindImplementationsAsync(symbol, _workspace.CurrentSolution); await AddQuickFixes(quickFixes, implementations); var overrides = await SymbolFinder.FindOverridesAsync(symbol, _workspace.CurrentSolution); await AddQuickFixes(quickFixes, overrides); var derivedTypes = await GetDerivedTypes(symbol); await AddQuickFixes(quickFixes, derivedTypes); response = new QuickFixResponse(quickFixes.OrderBy(q => q.FileName) .ThenBy(q => q.Line) .ThenBy(q => q.Column)); } return(response); }
public static QuickFixResponse OnlyThisFile(this QuickFixResponse response, string fileName) { if (response?.QuickFixes == null) { return(response); } var quickFixes = response.QuickFixes.Where(x => PathsAreEqual(x.FileName, fileName)); response.QuickFixes = quickFixes; return(response); bool PathsAreEqual(string x, string y) { if (x == null && y == null) { return(true); } if (x == null || y == null) { return(false); } var comparer = PlatformHelper.IsWindows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; return(Path.GetFullPath(x).Equals(Path.GetFullPath(y), comparer)); } }
public static QuickFixResponse OnlyThisFile(this QuickFixResponse response, string fileName) { if (response?.QuickFixes == null) { return(response); } var quickFixes = response.QuickFixes.Where(x => PathsAreEqual(x.FileName, fileName)); response.QuickFixes = quickFixes; return(response); }
public async Task <QuickFixResponse> FindUsages(FindUsagesRequest request) { var document = _workspace.GetDocument(request.FileName); var response = new QuickFixResponse(); if (document != null) { var semanticModel = await document.GetSemanticModelAsync(); var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line - 1, request.Column - 1)); var symbol = SymbolFinder.FindSymbolAtPosition(semanticModel, position, _workspace); var definition = await SymbolFinder.FindSourceDefinitionAsync(symbol, _workspace.CurrentSolution); var usages = request.OnlyThisFile ? await SymbolFinder.FindReferencesAsync(definition ?? symbol, _workspace.CurrentSolution, ImmutableHashSet.Create(document)) : await SymbolFinder.FindReferencesAsync(definition ?? symbol, _workspace.CurrentSolution); var locations = new List <Location>(); foreach (var usage in usages.Where(u => u.Definition.CanBeReferencedByName || (symbol as IMethodSymbol)?.MethodKind == MethodKind.Constructor)) { foreach (var location in usage.Locations) { locations.Add(location.Location); } if (!request.ExcludeDefinition) { var definitionLocations = usage.Definition.Locations .Where(loc => loc.IsInSource && (!request.OnlyThisFile || loc.SourceTree.FilePath == request.FileName)); foreach (var location in definitionLocations) { locations.Add(location); } } } var quickFixTasks = locations.Select(async l => await GetQuickFix(l)); var quickFixes = await Task.WhenAll(quickFixTasks); response = new QuickFixResponse(quickFixes.Distinct() .OrderBy(q => q.FileName) .ThenBy(q => q.Line) .ThenBy(q => q.Column)); } return(response); }
public static async Task <QuickFixResponse> TranslateAsync(this QuickFixResponse response, OmniSharpWorkspace workspace, Request request) { var quickFixes = new List <QuickFix>(); foreach (var quickFix in response.QuickFixes) { await quickFix.TranslateAsync(workspace, request); if (quickFix.Line >= 0) { quickFixes.Add(quickFix); } } response.QuickFixes = quickFixes; return(response); }
public async Task <QuickFixResponse> FindUsages([FromBody] Request request) { _workspace.EnsureBufferUpdated(request); var document = _workspace.GetDocument(request.FileName); var response = new QuickFixResponse(); if (document != null) { var semanticModel = await document.GetSemanticModelAsync(); var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line - 1, request.Column - 1)); var symbol = SymbolFinder.FindSymbolAtPosition(semanticModel, position, _workspace); var definition = await SymbolFinder.FindSourceDefinitionAsync(symbol, _workspace.CurrentSolution); var usages = await SymbolFinder.FindReferencesAsync(definition ?? symbol, _workspace.CurrentSolution); var locations = new HashSet <Location>(); foreach (var usage in usages.Where(u => u.Definition.CanBeReferencedByName || (symbol as IMethodSymbol)?.MethodKind == MethodKind.Constructor)) { foreach (var location in usage.Locations) { locations.Add(location.Location); } var definitionLocations = usage.Definition.Locations.Where(loc => loc.IsInSource); foreach (var location in definitionLocations) { locations.Add(location); } } var quickFixTasks = locations.Select(async l => await GetQuickFix(l)); var quickFixes = await Task.WhenAll(quickFixTasks); response = new QuickFixResponse(quickFixes.OrderBy(q => q.FileName) .ThenBy(q => q.Line) .ThenBy(q => q.Column)); } return(response); }
public async Task LoadOnDemandProjectsOneByOne() { var configData = new Dictionary <string, string> { [$"MsBuild:{nameof(MSBuildOptions.LoadProjectsOnDemand)}"] = "true" }; using (var testProject = await TestAssets.Instance.GetTestProjectAsync("TwoProjectsWithSolution")) using (var host = CreateMSBuildTestHost(testProject.Directory, configurationData: configData.ToConfiguration())) { MSBuildWorkspaceInfo workspaceInfo = await host.RequestMSBuildWorkspaceInfoAsync(); // Expect empty workspace initially since no documents have been requested yet Assert.Null(workspaceInfo.SolutionPath); Assert.NotNull(workspaceInfo.Projects); Assert.Equal(0, workspaceInfo.Projects.Count); // Requesting library document should load only that project GetCodeActionsService codeActionHandler = host.GetRequestHandler <GetCodeActionsService>(OmniSharpEndpoints.V2.GetCodeActions); GetCodeActionsResponse codeActionResponse = await codeActionHandler.Handle( new GetCodeActionsRequest { FileName = Path.Combine(testProject.Directory, "Lib", "Class1.cs") }); workspaceInfo = await host.RequestMSBuildWorkspaceInfoAsync(); Assert.NotNull(codeActionResponse); Assert.Null(workspaceInfo.SolutionPath); Assert.NotNull(workspaceInfo.Projects); Assert.Equal(1, workspaceInfo.Projects.Count); Assert.Equal("Lib.csproj", Path.GetFileName(workspaceInfo.Projects[0].Path)); // Requesting app document should load that project as well QuickFixResponse codeCheckResponse = await host.RequestCodeCheckAsync(Path.Combine(testProject.Directory, "App", "Program.cs")); workspaceInfo = await host.RequestMSBuildWorkspaceInfoAsync(); Assert.NotNull(codeCheckResponse); Assert.Null(workspaceInfo.SolutionPath); Assert.NotNull(workspaceInfo.Projects); Assert.Equal(2, workspaceInfo.Projects.Count); Assert.Equal("App.csproj", Path.GetFileName(workspaceInfo.Projects[0].Path)); Assert.Equal("Lib.csproj", Path.GetFileName(workspaceInfo.Projects[1].Path)); } }
public async Task <IActionResult> FindUsages([FromBody] Request request) { _workspace.EnsureBufferUpdated(request); var documentId = _workspace.GetDocumentId(request.FileName); var response = new QuickFixResponse(); if (documentId != null) { var document = _workspace.CurrentSolution.GetDocument(documentId); var semanticModel = await document.GetSemanticModelAsync(); var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line - 1, request.Column)); var symbol = SymbolFinder.FindSymbolAtPosition(semanticModel, position, _workspace); var definition = await SymbolFinder.FindSourceDefinitionAsync(symbol, _workspace.CurrentSolution); var usages = await SymbolFinder.FindReferencesAsync(definition, _workspace.CurrentSolution); var quickFixes = new List <QuickFix>(); foreach (var usage in usages) { foreach (var location in usage.Locations) { quickFixes.Add(GetQuickFix(location.Location)); } foreach (var location in usage.Definition.Locations) { quickFixes.Add(GetQuickFix(location)); } } response = new QuickFixResponse(quickFixes); } return(new ObjectResult(response)); }
public static async Task <QuickFixResponse> TranslateAsync(this QuickFixResponse response, OmniSharpWorkspace workspace, Request request, bool removeGenerated = false) { var quickFixes = new List <QuickFix>(); foreach (var quickFix in response.QuickFixes) { await quickFix.TranslateAsync(workspace, request); if (quickFix.Line < 0) { continue; } if (removeGenerated && quickFix.FileName.Equals(Constants.Paths.Generated)) { continue; } quickFixes.Add(quickFix); } response.QuickFixes = quickFixes; return(response); }
public async Task TestProjectWithSignedReferencedProject() { using (ITestProject testProject = await TestAssets.Instance.GetTestProjectAsync("SolutionWithSignedProject")) using (OmniSharpTestHost host = CreateOmniSharpHost(Path.Combine(testProject.Directory))) { MSBuildWorkspaceInfo workspaceInfo = await GetWorkspaceInfoAsync(host); Assert.NotNull(workspaceInfo.Projects); Assert.Equal(2, workspaceInfo.Projects.Count); // For the test to validate that assemblies representing targets of loaded projects are being skipped, // the assemblies must be present on disk. foreach (MSBuildProjectInfo loadedProject in workspaceInfo.Projects) { Assert.True(File.Exists(loadedProject.TargetPath), $"Project target assembly is not found {loadedProject.TargetPath}. " + $"Make sure to build the whole repo using the build script before running the test."); } // The callee assembly must be signed to ensure that in case of a bug the assembly is loaded // "The type 'Callee' exists in both ..." is present as a code check (which is validated below). MSBuildProjectInfo signedProject = workspaceInfo.Projects.SingleOrDefault(p => p.AssemblyName.Equals("CalleeLib", StringComparison.OrdinalIgnoreCase)); Assert.NotNull(signedProject); string token = BitConverter.ToString(AssemblyName.GetAssemblyName(signedProject.TargetPath).GetPublicKeyToken()); Assert.Equal("A5-D8-5A-5B-AA-39-A6-A6", token, ignoreCase: true); QuickFixResponse quickFixResponse = await GetCodeChecksync(host, Path.Combine(testProject.Directory, "CallerLib\\Caller.cs")); // Log result to easier debugging of the test should it fail during automated valdiation foreach (QuickFix fix in quickFixResponse.QuickFixes) { host.Logger.LogInformation($"Unexpected QuickFix returned for {fix.FileName}: {fix.Text}"); } Assert.Empty(quickFixResponse.QuickFixes); } }
public QuickFixResponse FindUsages(FindUsagesRequest request) { var result = FindUsageNodes(request) .Distinct(new NodeComparer()) .OrderBy(n => n.GetRegion().FileName.FixPath()) .ThenBy(n => n.StartLocation.Line) .ThenBy(n => n.StartLocation.Column); var res = new QuickFixResponse(); if (result.Any()) { var usages = result.Select(node => new QuickFix { FileName = node.GetRegion().FileName, Text = node.Preview(_solution.GetFile(node.GetRegion().FileName), request.MaxWidth).Replace("'", "''"), Line = node.StartLocation.Line, Column = node.StartLocation.Column, }); res.QuickFixes = usages; } return(res); }
public static Task <QuickFixResponse> TranslateAsync(this QuickFixResponse response, OmniSharpWorkspace workspace) { return(response.TranslateAsync(workspace, new Request())); }