public void UpdateBufferFindsProjectBasedOnNearestPath() { var workspace = new OmnisharpWorkspace(); TestHelpers.AddProjectToWorkspace(workspace, Path.Combine("src", "root", "foo.csproj"), new[] { "" }, new Dictionary<string, string>() { { Path.Combine("src", "root", "foo.cs"), "class C1 {}" } }); TestHelpers.AddProjectToWorkspace(workspace, Path.Combine("src", "root", "foo", "bar", "insane.csproj"), new[] { "" }, new Dictionary<string, string>() { { Path.Combine("src", "root", "foo", "bar", "nested", "code.cs"), "class C2 {}" } }); workspace.BufferManager.UpdateBuffer(new Request() { FileName = Path.Combine("src", "root", "bar.cs"), Buffer = "enum E {}" }); var documents = workspace.GetDocuments(Path.Combine("src", "root", "bar.cs")); Assert.Equal(1, documents.Count()); Assert.Equal(Path.Combine("src", "root", "foo.csproj"), documents.ElementAt(0).Project.FilePath); Assert.Equal(2, documents.ElementAt(0).Project.Documents.Count()); workspace.BufferManager.UpdateBuffer(new Request() { FileName = Path.Combine("src", "root", "foo", "bar", "nested", "paths", "dance.cs"), Buffer = "enum E {}" }); documents = workspace.GetDocuments(Path.Combine("src", "root", "foo", "bar", "nested", "paths", "dance.cs")); Assert.Equal(1, documents.Count()); Assert.Equal(Path.Combine("src", "root", "foo", "bar", "insane.csproj"), documents.ElementAt(0).Project.FilePath); Assert.Equal(2, documents.ElementAt(0).Project.Documents.Count()); }
public async Task UpdateBufferFindsProjectBasedOnNearestPath() { var workspace = new OmnisharpWorkspace( new HostServicesAggregator( Enumerable.Empty <IHostServicesProvider>())); await TestHelpers.AddProjectToWorkspace(workspace, Path.Combine("src", "root", "foo.csproj"), new[] { "" }, new Dictionary <string, string>() { { Path.Combine("src", "root", "foo.cs"), "class C1 {}" } }); await TestHelpers.AddProjectToWorkspace(workspace, Path.Combine("src", "root", "foo", "bar", "insane.csproj"), new[] { "" }, new Dictionary <string, string>() { { Path.Combine("src", "root", "foo", "bar", "nested", "code.cs"), "class C2 {}" } }); await workspace.BufferManager.UpdateBuffer(new Request() { FileName = Path.Combine("src", "root", "bar.cs"), Buffer = "enum E {}" }); var documents = workspace.GetDocuments(Path.Combine("src", "root", "bar.cs")); Assert.Equal(1, documents.Count()); Assert.Equal(Path.Combine("src", "root", "foo.csproj"), documents.ElementAt(0).Project.FilePath); Assert.Equal(2, documents.ElementAt(0).Project.Documents.Count()); await workspace.BufferManager.UpdateBuffer(new Request() { FileName = Path.Combine("src", "root", "foo", "bar", "nested", "paths", "dance.cs"), Buffer = "enum E {}" }); documents = workspace.GetDocuments(Path.Combine("src", "root", "foo", "bar", "nested", "paths", "dance.cs")); Assert.Equal(1, documents.Count()); Assert.Equal(Path.Combine("src", "root", "foo", "bar", "insane.csproj"), documents.ElementAt(0).Project.FilePath); Assert.Equal(2, documents.ElementAt(0).Project.Documents.Count()); }
public static async Task <QuickFix> GetQuickFix(OmnisharpWorkspace workspace, Location location) { if (!location.IsInSource) { throw new Exception("Location is not in the source tree"); } var lineSpan = location.GetLineSpan(); var path = lineSpan.Path; var documents = workspace.GetDocuments(path); var line = lineSpan.StartLinePosition.Line; var syntaxTree = await documents.First().GetSyntaxTreeAsync(); var text = syntaxTree.GetText().Lines[line].ToString(); return(new QuickFix { Text = text.Trim(), FileName = path, Line = line + 1, Column = lineSpan.StartLinePosition.Character + 1, EndLine = lineSpan.EndLinePosition.Line + 1, EndColumn = lineSpan.EndLinePosition.Character + 1, Projects = documents.Select(document => document.Project.Name).ToArray() }); }
public async Task <FileMemberTree> Handle(MembersTreeRequest request) { return(new FileMemberTree() { TopLevelTypeDefinitions = await StructureComputer.Compute(_workspace.GetDocuments(request.FileName), _discovers) }); }
private QuickFix ConvertSymbol(ISymbol symbol, Location location) { var lineSpan = location.GetLineSpan(); var path = lineSpan.Path; var documents = _workspace.GetDocuments(path); var format = SymbolDisplayFormat.MinimallyQualifiedFormat; format = format.WithMemberOptions(format.MemberOptions ^ SymbolDisplayMemberOptions.IncludeContainingType ^ SymbolDisplayMemberOptions.IncludeType); format = format.WithKindOptions(SymbolDisplayKindOptions.None); return(new SymbolLocation { Text = symbol.ToDisplayString(format), Kind = symbol.GetKind(), FileName = path, Line = lineSpan.StartLinePosition.Line + 1, Column = lineSpan.StartLinePosition.Character + 1, EndLine = lineSpan.EndLinePosition.Line + 1, EndColumn = lineSpan.EndLinePosition.Character + 1, Projects = documents.Select(document => document.Project.Name).ToArray() }); }
public Task <FileCloseResponse> Handle(FileCloseRequest request) { var documents = _workspace.GetDocuments(request.FileName); foreach (var document in documents) { _workspace.CloseDocument(document.Id); } return(Task.FromResult(new FileCloseResponse())); }
public async Task <IEnumerable <QuickFix> > Handle(MembersFlatRequest request) { var stack = new List <FileMemberElement>(await StructureComputer.Compute(_workspace.GetDocuments(request.FileName))); var ret = new List <QuickFix>(); while (stack.Count > 0) { var node = stack[0]; stack.Remove(node); ret.Add(node.Location); stack.AddRange(node.ChildNodes); } return(ret); }
private async Task <DiagnosticResult> ProcessNextItem(string filePath) { var documents = _workspace.GetDocuments(filePath); var items = new List <DiagnosticLocation>(); if (documents.Any()) { foreach (var document in documents) { var semanticModel = await document.GetSemanticModelAsync(); IEnumerable <Diagnostic> diagnostics = semanticModel.GetDiagnostics(); //script files can have custom directives such as #load which will be deemed invalid by Roslyn //we suppress the CS1024 diagnostic for script files for this reason. Roslyn will fix it later too, so this is temporary. if (document.SourceCodeKind != SourceCodeKind.Regular) { diagnostics = diagnostics.Where(diagnostic => diagnostic.Id != "CS1024"); } foreach (var quickFix in diagnostics.Select(MakeQuickFix)) { var existingQuickFix = items.FirstOrDefault(q => q.Equals(quickFix)); if (existingQuickFix == null) { quickFix.Projects.Add(document.Project.Name); items.Add(quickFix); } else { existingQuickFix.Projects.Add(document.Project.Name); } } } } return(new DiagnosticResult() { FileName = filePath, QuickFixes = items }); }
public static async Task<NavigateResponse> Navigate(OmnisharpWorkspace workspace, Request request, Func<FileMemberElement, FileMemberElement, Request, bool> IsCloserNode) { var stack = new List<FileMemberElement>(await StructureComputer.Compute(workspace.GetDocuments(request.FileName))); var response = new NavigateResponse(); //Retain current line in case we dont need to navigate. response.Line = request.Line; response.Column = request.Column; FileMemberElement closestNode = null; FileMemberElement thisNode = null; while (stack.Count > 0) { var node = stack[0]; stack.Remove(node); var isCloserNode = IsCloserNode(node, closestNode, request); if (isCloserNode) { closestNode = node; } if (node.Location.Line == request.Line) { thisNode = node; } stack.AddRange(node.ChildNodes); } //If there is a closest node, use its line and column. //or if we are on the last node, adjust column. //if we are above the first or below the last node, do nothing. if (closestNode != null) { response.Line = closestNode.Location.Line; response.Column = closestNode.Location.Column; } else if (thisNode != null) { response.Column = thisNode.Location.Column; } return response; }
public async Task <IEnumerable <AutoCompleteResponse> > Handle(AutoCompleteRequest request) { var documents = _workspace.GetDocuments(request.FileName); var wordToComplete = request.WordToComplete; var completions = new HashSet <AutoCompleteResponse>(); foreach (var document in documents) { var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line - 1, request.Column - 1)); var model = await document.GetSemanticModelAsync(); AddKeywords(completions, model, position, request.WantKind, wordToComplete); var symbols = Recommender.GetRecommendedSymbolsAtPosition(model, position, _workspace); foreach (var symbol in symbols.Where(s => s.Name.IsValidCompletionFor(wordToComplete))) { if (request.WantSnippet) { foreach (var completion in MakeSnippetedResponses(request, symbol)) { completions.Add(completion); } } else { completions.Add(MakeAutoCompleteResponse(request, symbol)); } } } return(completions .OrderByDescending(c => c.CompletionText.IsValidCompletionStartsWithExactCase(wordToComplete)) .ThenByDescending(c => c.CompletionText.IsValidCompletionStartsWithIgnoreCase(wordToComplete)) .ThenByDescending(c => c.CompletionText.IsCamelCaseMatch(wordToComplete)) .ThenByDescending(c => c.CompletionText.IsSubsequenceMatch(wordToComplete)) .ThenBy(c => c.CompletionText)); }
public async Task <QuickFixResponse> Handle(CodeCheckRequest request) { var quickFixes = new List <QuickFix>(); var documents = request.FileName != null ? _workspace.GetDocuments(request.FileName) : _workspace.CurrentSolution.Projects.SelectMany(project => project.Documents); foreach (var document in documents) { var semanticModel = await document.GetSemanticModelAsync(); IEnumerable <Diagnostic> diagnostics = semanticModel.GetDiagnostics(); //script files can have custom directives such as #load which will be deemed invalid by Roslyn //we suppress the CS1024 diagnostic for script files for this reason. Roslyn will fix it later too, so this is temporary. if (document.SourceCodeKind != SourceCodeKind.Regular) { diagnostics = diagnostics.Where(diagnostic => diagnostic.Id != "CS1024"); } foreach (var quickFix in diagnostics.Select(MakeQuickFix)) { var existingQuickFix = quickFixes.FirstOrDefault(q => q.Equals(quickFix)); if (existingQuickFix == null) { quickFix.Projects.Add(document.Project.Name); quickFixes.Add(quickFix); } else { existingQuickFix.Projects.Add(document.Project.Name); } } } return(new QuickFixResponse(quickFixes)); }
public static async Task<QuickFix> GetQuickFix(OmnisharpWorkspace workspace, Location location) { if (!location.IsInSource) throw new Exception("Location is not in the source tree"); var lineSpan = location.GetLineSpan(); var path = lineSpan.Path; var documents = workspace.GetDocuments(path); var line = lineSpan.StartLinePosition.Line; var syntaxTree = await documents.First().GetSyntaxTreeAsync(); var text = syntaxTree.GetText().Lines[line].ToString(); return new QuickFix { Text = text.Trim(), FileName = path, Line = line + 1, Column = lineSpan.StartLinePosition.Character + 1, EndLine = lineSpan.EndLinePosition.Line + 1, EndColumn = lineSpan.EndLinePosition.Character + 1, Projects = documents.Select(document => document.Project.Name).ToArray() }; }
public async Task <IEnumerable <AutoCompleteResponse> > Handle(AutoCompleteRequest request) { var documents = _workspace.GetDocuments(request.FileName); var wordToComplete = request.WordToComplete; var completions = new HashSet <AutoCompleteResponse>(); foreach (var document in documents) { var sourceText = await document.GetTextAsync(); var position = sourceText.Lines.GetPosition(new LinePosition(request.Line, request.Column)); var service = CompletionService.GetService(document); var completionList = await service.GetCompletionsAsync(document, position); // Add keywords from the completion list. We'll use the recommender service to get symbols // to create snippets from. foreach (var item in completionList.Items) { if (item.Tags.Contains(CompletionTags.Keyword)) { // Note: For keywords, we'll just assume that the completion text is the same // as the display text. var keyword = item.DisplayText; if (keyword.IsValidCompletionFor(wordToComplete)) { var response = new AutoCompleteResponse() { CompletionText = item.DisplayText, DisplayText = item.DisplayText, Snippet = item.DisplayText, Kind = request.WantKind ? "Keyword" : null }; completions.Add(response); } } } var model = await document.GetSemanticModelAsync(); var symbols = await Recommender.GetRecommendedSymbolsAtPositionAsync(model, position, _workspace); foreach (var symbol in symbols.Where(s => s.Name.IsValidCompletionFor(wordToComplete))) { if (request.WantSnippet) { foreach (var completion in MakeSnippetedResponses(request, symbol)) { completions.Add(completion); } } else { completions.Add(MakeAutoCompleteResponse(request, symbol)); } } } return(completions .OrderByDescending(c => c.CompletionText.IsValidCompletionStartsWithExactCase(wordToComplete)) .ThenByDescending(c => c.CompletionText.IsValidCompletionStartsWithIgnoreCase(wordToComplete)) .ThenByDescending(c => c.CompletionText.IsCamelCaseMatch(wordToComplete)) .ThenByDescending(c => c.CompletionText.IsSubsequenceMatch(wordToComplete)) .ThenBy(c => c.CompletionText)); }
public async Task <SignatureHelp> Handle(SignatureHelpRequest request) { var invocations = new List <InvocationContext>(); foreach (var document in _workspace.GetDocuments(request.FileName)) { var invocation = await GetInvocation(document, request); if (invocation != null) { invocations.Add(invocation); } } if (invocations.Count == 0) { return(null); } var response = new SignatureHelp(); // define active parameter by position foreach (var comma in invocations.First().ArgumentList.Arguments.GetSeparators()) { if (comma.Span.Start > invocations.First().Position) { break; } response.ActiveParameter += 1; } // process all signatures, define active signature by types var signaturesSet = new HashSet <SignatureHelpItem>(); var bestScore = int.MinValue; SignatureHelpItem bestScoredItem = null; foreach (var invocation in invocations) { var types = invocation.ArgumentList.Arguments .Select(argument => invocation.SemanticModel.GetTypeInfo(argument.Expression)); foreach (var methodOverload in GetMethodOverloads(invocation.SemanticModel, invocation.Receiver)) { var signature = BuildSignature(methodOverload); signaturesSet.Add(signature); var score = InvocationScore(methodOverload, types); if (score > bestScore) { bestScore = score; bestScoredItem = signature; } } } var signaturesList = signaturesSet.ToList(); response.Signatures = signaturesList; response.ActiveSignature = signaturesList.IndexOf(bestScoredItem); return(response); }
public static async Task <NavigateResponse> Navigate(OmnisharpWorkspace workspace, Request request, Func <FileMemberElement, FileMemberElement, Request, bool> IsCloserNode) { var stack = new List <FileMemberElement>(await StructureComputer.Compute(workspace.GetDocuments(request.FileName))); var response = new NavigateResponse(); //Retain current line in case we dont need to navigate. response.Line = request.Line; response.Column = request.Column; FileMemberElement closestNode = null; FileMemberElement thisNode = null; while (stack.Count > 0) { var node = stack[0]; stack.Remove(node); var isCloserNode = IsCloserNode(node, closestNode, request); if (isCloserNode) { closestNode = node; } if (node.Location.Line == request.Line) { thisNode = node; } stack.AddRange(node.ChildNodes); } //If there is a closest node, use its line and column. //or if we are on the last node, adjust column. //if we are above the first or below the last node, do nothing. if (closestNode != null) { response.Line = closestNode.Location.Line; response.Column = closestNode.Location.Column; } else if (thisNode != null) { response.Column = thisNode.Location.Column; } return(response); }