static async Task <CompletionModel> ComputeModelAsync( RoslynCompilationWorkspace compilationWorkspace, SourceText text, int position, CancellationToken ct) { ct.ThrowIfCancellationRequested(); var completions = await compilationWorkspace.CompletionService.GetCompletionsAsync( compilationWorkspace.GetSubmissionDocument(text.Container), position, options : compilationWorkspace.Options, cancellationToken : ct).ConfigureAwait(false); if (completions == null) { return(null); } // TODO: Default tracking span //var trackingSpan = await _completionService.GetDefaultTrackingSpanAsync(_documentOpt, _subjectBufferCaretPosition, cancellationToken).ConfigureAwait(false); return(CompletionModel.CreateModel( text, default(TextSpan), completions.Items)); }
public async Task <SignatureHelpViewModel> ComputeSignatureHelpAsync( SourceText sourceText, LinePosition linePosition, CancellationToken cancellationToken) { var signatureHelp = new SignatureHelpViewModel(); var position = sourceText.Lines.GetPosition(linePosition); if (position <= 0) { return(signatureHelp); } var document = compilationWorkspace.GetSubmissionDocument(sourceText.Container); var root = await document.GetSyntaxRootAsync(cancellationToken); var syntaxToken = root.FindToken(position); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var currentNode = syntaxToken.Parent; do { var creationExpression = currentNode as ObjectCreationExpressionSyntax; if (creationExpression != null && creationExpression.ArgumentList.Span.Contains(position)) { return(CreateMethodGroupSignatureHelp( creationExpression, creationExpression.ArgumentList, position, semanticModel)); } var invocationExpression = currentNode as InvocationExpressionSyntax; if (invocationExpression != null && invocationExpression.ArgumentList.Span.Contains(position)) { return(CreateMethodGroupSignatureHelp( invocationExpression.Expression, invocationExpression.ArgumentList, position, semanticModel)); } currentNode = currentNode.Parent; } while (currentNode != null); return(signatureHelp); }
/// <summary> /// Start a new ModelComputation. Completion computations and filtering tasks will be chained to this /// ModelComputation, and when the chain is complete the view will be notified via the /// OnCompletionModelUpdated handler. /// /// The latest immutable CompletionModel can be accessed at any time. Some parts of the code may choose /// to wait on it to arrive synchronously. /// /// Inspired by similar method in Completion/Controller.cs in Roslyn. /// </summary> void StartNewComputation( int position, CompletionRules rules, bool filterItems) { computation = new ModelComputation <CompletionModel> ( OnCompletionModelUpdated, Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion.PrioritizedTaskScheduler.AboveNormalInstance); ComputeModel(position); if (filterItems) { var document = compilationWorkspace.GetSubmissionDocument(sourceTextContent.Container); FilterModel(CompletionHelper.GetHelper(document)); } }
public async Task <HoverViewModel> ProvideHoverAsync( SourceText sourceText, LinePosition linePosition, CancellationToken cancellationToken) { var hover = new HoverViewModel(); var position = sourceText.Lines.GetPosition(linePosition); if (position <= 0) { return(hover); } var document = compilationWorkspace.GetSubmissionDocument(sourceText.Container); var root = await document.GetSyntaxRootAsync(cancellationToken); var syntaxToken = root.FindToken(position); var expression = syntaxToken.Parent as ExpressionSyntax; if (expression == null) { return(hover); } var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var symbolInfo = semanticModel.GetSymbolInfo(expression); if (symbolInfo.Symbol == null) { return(hover); } hover.Contents = new [] { symbolInfo.Symbol.ToDisplayString(Constants.SymbolDisplayFormat) }; hover.Range = syntaxToken.GetLocation().GetLineSpan().Span; return(hover); }
/// <summary> /// Filter currentCompletionList according to the current filter text. Roslyn's completion does not /// handle this automatically. /// </summary> static async Task <CompletionModel> FilterModelAsync( RoslynCompilationWorkspace compilationWorkspace, SourceText sourceText, CompletionModel model, CompletionHelper helper, CancellationToken ct) { if (model == null) { return(null); } CompletionItem bestFilterMatch = null; var bestFilterMatchIndex = 0; var document = compilationWorkspace.GetSubmissionDocument(sourceText.Container); var newFilteredCompletions = new List <CompletionItem> (); foreach (var item in model.TotalItems) { var completion = item; // TODO: Better range checking on delete before queuing up filtering (see TODO in HandleChange) if (completion.Span.Start > sourceText.Length) { continue; } var filterText = GetFilterText(sourceText, completion); // CompletionRules.MatchesFilterText seems to always return false when filterText is // empty. if (filterText != String.Empty && !helper.MatchesPattern( completion.FilterText, filterText, CultureInfo.CurrentCulture)) { continue; } var itemDetail = String.Empty; var symbols = await SymbolCompletionItem.GetSymbolsAsync(completion, document, ct) .ConfigureAwait(false); var overloads = symbols.OfType <IMethodSymbol> ().ToArray(); if (overloads.Length > 0) { itemDetail = overloads [0].ToMonacoSignatureString(); if (overloads.Length > 1) { itemDetail += $" (+ {overloads.Length - 1} overload(s))"; } } completion = completion.AddProperty(itemDetailPropertyName, itemDetail); newFilteredCompletions.Add(completion); if (bestFilterMatch == null || helper.CompareItems( completion, bestFilterMatch, filterText, CultureInfo.CurrentCulture) > 0) { bestFilterMatch = completion; bestFilterMatchIndex = newFilteredCompletions.Count - 1; } } if (newFilteredCompletions.Count == 0) { return(null); } return(model .WithFilteredItems(newFilteredCompletions) .WithSelectedItem(bestFilterMatch, bestFilterMatchIndex) .WithText(sourceText)); }