private static async Task <CompletionList> GetCompletionListAsync( CompletionListProvider provider, Document documentOpt, SourceText text, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { if (provider is TextCompletionProvider) { return(((TextCompletionProvider)provider).GetCompletionList(text, position, triggerInfo, cancellationToken)); } if (documentOpt != null) { var context = new CompletionListContext(documentOpt, position, triggerInfo, cancellationToken); await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); return(new CompletionList(context.GetItems(), context.Builder, context.IsExclusive)); } Contract.Fail("Should never get here."); return(null); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // first try to get the #r string literal token. If we couldn't, then we're not in a #r // reference directive and we immediately bail. SyntaxToken stringLiteral; if (!TryGetStringLiteralToken(tree, position, out stringLiteral, cancellationToken)) { return; } var documentPath = document.Project.IsSubmission ? null : document.FilePath; var textChangeSpan = this.GetTextChangeSpan(stringLiteral, position); var gacHelper = new GlobalAssemblyCacheCompletionHelper(this, textChangeSpan, itemRules: ItemRules.Instance); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var snapshot = text.FindCorrespondingEditorTextSnapshot(); if (snapshot == null) { // Passing null to GetFileSystemDiscoveryService raises an exception. // Instead, return here since there is no longer snapshot for this document. return; } var referenceResolver = document.Project.CompilationOptions.MetadataReferenceResolver; // TODO: https://github.com/dotnet/roslyn/issues/5263 // Avoid dependency on a specific resolvers. // The search paths should be provided by specialized workspaces: // - InteractiveWorkspace for interactive window // - ScriptWorkspace for loose .csx files (we don't have such workspace today) var pathResolver = (referenceResolver as RuntimeMetadataReferenceResolver)?.PathResolver ?? (referenceResolver as WorkspaceMetadataFileReferenceResolver)?.PathResolver; if (pathResolver == null) { return; } var fileSystemHelper = new FileSystemCompletionHelper( this, textChangeSpan, GetFileSystemDiscoveryService(snapshot), Glyph.OpenFolder, Glyph.Assembly, searchPaths: pathResolver.SearchPaths, allowableExtensions: new[] { ".dll", ".exe" }, exclude: path => path.Contains(","), itemRules: ItemRules.Instance); var pathThroughLastSlash = this.GetPathThroughLastSlash(stringLiteral, position); context.AddItems(gacHelper.GetItems(pathThroughLastSlash, documentPath)); context.AddItems(fileSystemHelper.GetItems(pathThroughLastSlash, documentPath)); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; using (Logger.LogBlock(FunctionId.Completion_SnippetCompletionProvider_GetItemsWorker_CSharp, cancellationToken)) { // TODO (https://github.com/dotnet/roslyn/issues/5107): Enable in Interactive. var workspace = document.Project.Solution.Workspace; if (!workspace.CanApplyChange(ApplyChangesKind.ChangeDocument) || workspace.Kind == WorkspaceKind.Debugger || workspace.Kind == WorkspaceKind.Interactive) { return; } if (!options.GetOption(CSharpCompletionOptions.IncludeSnippets)) { return; } var snippetCompletionItems = await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync( UnionCompletionItemComparer.Instance, (d, c) => GetSnippetsForDocumentAsync(d, position, workspace, c), cancellationToken).ConfigureAwait(false); context.AddItems(snippetCompletionItems); } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); // first try to get the #r string literal token. If we couldn't, then we're not in a #r // reference directive and we immediately bail. SyntaxToken stringLiteral; if (!TryGetStringLiteralToken(tree, position, out stringLiteral, cancellationToken)) { return; } var textChangeSpan = GetTextChangeSpan(stringLiteral, position); var gacHelper = new GlobalAssemblyCacheCompletionHelper(this, textChangeSpan, ItemRules.Instance); var referenceResolver = document.Project.CompilationOptions.MetadataReferenceResolver; // TODO: https://github.com/dotnet/roslyn/issues/5263 // Avoid dependency on a specific resolvers. // The search paths should be provided by specialized workspaces: // - InteractiveWorkspace for interactive window // - ScriptWorkspace for loose .csx files (we don't have such workspace today) ImmutableArray<string> searchPaths; RuntimeMetadataReferenceResolver rtResolver; WorkspaceMetadataFileReferenceResolver workspaceResolver; if ((rtResolver = referenceResolver as RuntimeMetadataReferenceResolver) != null) { searchPaths = rtResolver.PathResolver.SearchPaths; } else if ((workspaceResolver = referenceResolver as WorkspaceMetadataFileReferenceResolver) != null) { searchPaths = workspaceResolver.PathResolver.SearchPaths; } else { return; } var fileSystemHelper = new FileSystemCompletionHelper( this, textChangeSpan, new CurrentWorkingDirectoryDiscoveryService(Directory.GetCurrentDirectory()), Microsoft.CodeAnalysis.Glyph.OpenFolder, Microsoft.CodeAnalysis.Glyph.Assembly, searchPaths, new[] { ".dll", ".exe" }, path => path.Contains(","), ItemRules.Instance); var pathThroughLastSlash = GetPathThroughLastSlash(stringLiteral, position); var documentPath = document.Project.IsSubmission ? null : document.FilePath; context.AddItems(gacHelper.GetItems(pathThroughLastSlash, documentPath)); context.AddItems(fileSystemHelper.GetItems(pathThroughLastSlash, documentPath)); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var state = new ItemGetter(this, context.Document, context.Position, context.CancellationToken); var items = await state.GetItemsAsync().ConfigureAwait(false); if (items?.Any() == true) { context.MakeExclusive(true); context.AddItems(items); } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (syntaxTree.IsInNonUserCode(position, cancellationToken)) { return; } var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); token = token.GetPreviousTokenIfTouchingWord(position); if (!token.IsKind(SyntaxKind.OpenParenToken, SyntaxKind.CommaToken)) { return; } var attributeArgumentList = token.Parent as AttributeArgumentListSyntax; var attributeSyntax = token.Parent.Parent as AttributeSyntax; if (attributeSyntax == null || attributeArgumentList == null) { return; } if (IsAfterNameColonArgument(token) || IsAfterNameEqualsArgument(token)) { context.MakeExclusive(true); } // We actually want to collect two sets of named parameters to present the user. The // normal named parameters that come from the attribute constructors. These will be // presented like "foo:". And also the named parameters that come from the writable // fields/properties in the attribute. These will be presented like "bar =". var existingNamedParameters = GetExistingNamedParameters(attributeArgumentList, position); var workspace = document.Project.Solution.Workspace; var semanticModel = await document.GetSemanticModelForNodeAsync(attributeSyntax, cancellationToken).ConfigureAwait(false); var nameColonItems = await GetNameColonItemsAsync(workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false); var nameEqualsItems = await GetNameEqualsItemsAsync(workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false); context.AddItems(nameEqualsItems); // If we're after a name= parameter, then we only want to show name= parameters. // Otherwise, show name: parameters too. if (!IsAfterNameEqualsArgument(token)) { context.AddItems(nameColonItems); } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var triggerInfo = context.TriggerInfo; var cancellationToken = context.CancellationToken; var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var items = GetItems(text, position, triggerInfo, cancellationToken); context.AddItems(items); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { if (!context.Options.GetOption(CompletionOptions.ShowXmlDocCommentCompletion)) { return; } var items = await GetItemsWorkerAsync(context.Document, context.Position, context.TriggerInfo, context.CancellationToken).ConfigureAwait(false); if (items != null) { context.AddItems(items); } }
private static async Task <CompletionList> GetCompletionListAsync( CompletionListProvider provider, Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { var context = new CompletionListContext(document, position, triggerInfo, cancellationToken); await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); return(new CompletionList(context.GetItems(), context.Builder, context.IsExclusive)); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (!tree.IsEntirelyWithinCrefSyntax(position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDocumentationComments: true) .GetPreviousTokenIfTouchingWord(position); // To get a Speculative SemanticModel (which is much faster), we need to // walk up to the node the DocumentationTrivia is attached to. var parentNode = token.Parent.FirstAncestorOrSelf<DocumentationCommentTriviaSyntax>()?.ParentTrivia.Token.Parent; if (parentNode == null) { return; } var semanticModel = await document.GetSemanticModelForNodeAsync(parentNode, cancellationToken).ConfigureAwait(false); var symbols = GetSymbols(token, semanticModel, cancellationToken); symbols = symbols.FilterToVisibleAndBrowsableSymbols(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation); if (!symbols.Any()) { return; } context.MakeExclusive(true); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var filterSpan = GetTextChangeSpan(text, position); var items = CreateCompletionItems(document.Project.Solution.Workspace, semanticModel, symbols, token, filterSpan); context.AddItems(items); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var showSpeculativeT = await document.IsValidContextForDocumentOrLinkedDocumentsAsync( (doc, ct) => ShouldShowSpeculativeTCompletionItemAsync(doc, position, ct), cancellationToken).ConfigureAwait(false); if (showSpeculativeT) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var filterSpan = this.GetTextChangeSpan(text, position); const string T = nameof(T); context.AddItem(new CompletionItem(this, T, filterSpan, descriptionFactory: null, glyph: Glyph.TypeParameter)); } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var targetToken = tree .FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position); if (targetToken.IsKind(SyntaxKind.AliasKeyword) && targetToken.Parent.IsKind(SyntaxKind.ExternAliasDirective)) { var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var aliases = compilation.ExternalReferences.SelectMany(r => r.Properties.Aliases).ToSet(); if (aliases.Any()) { var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var usedAliases = root.ChildNodes().OfType<ExternAliasDirectiveSyntax>() .Where(e => !e.Identifier.IsMissing) .Select(e => e.Identifier.ValueText); aliases.RemoveRange(usedAliases); aliases.Remove(MetadataReferenceProperties.GlobalAlias); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var filterSpan = CompletionUtilities.GetTextChangeSpan(text, position); foreach (var alias in aliases) { context.AddItem(new CompletionItem(this, alias, filterSpan, glyph: Glyph.Namespace)); } } } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; if (document != null && document.SourceCodeKind == SourceCodeKind.Interactive) { // the provider might be invoked in non-interactive context: Workspace ws; if (Workspace.TryGetWorkspace(document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).Container, out ws)) { var workspace = ws as InteractiveWorkspace; if (workspace != null) { var window = workspace.Engine.CurrentWindow; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsBeforeFirstToken(position, cancellationToken) && tree.IsPreProcessorKeywordContext(position, cancellationToken)) { var filterSpan = await this.GetTextChangeSpanAsync(document, position, cancellationToken).ConfigureAwait(false); IInteractiveWindowCommands commands = window.GetInteractiveCommands(); if (commands != null) { foreach (var command in commands.GetCommands()) { foreach (var commandName in command.Names) { context.AddItem(new CompletionItem( this, commandName, filterSpan, c => Task.FromResult(command.Description.ToSymbolDisplayParts()), glyph: Glyph.Intrinsic)); } } } } } } } }
private static async Task <CompletionList> GetCompletionListAsync( CompletionListProvider provider, Document document, int position, CompletionTriggerInfo triggerInfo, OptionSet options, CancellationToken cancellationToken) { var context = new CompletionListContext(document, position, triggerInfo, options, cancellationToken); if (document.SupportsSyntaxTree) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (!root.FullSpan.IntersectsWith(position)) { try { // Trying to track down source of https://github.com/dotnet/roslyn/issues/9325 var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); ReportException(position, root, sourceText); } catch (Exception e) when(FatalError.ReportWithoutCrash(e)) { } } else { await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); } } else { await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); } return(new CompletionList(context.GetItems(), context.Builder, context.IsExclusive)); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; // the provider might be invoked in non-interactive context: Workspace ws; SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (Workspace.TryGetWorkspace(sourceText.Container, out ws)) { var workspace = ws as InteractiveWorkspace; if (workspace != null) { var window = workspace.Engine.CurrentWindow; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (ShouldDisplayCommandCompletions(tree, position, cancellationToken)) { var filterSpan = await this.GetTextChangeSpanAsync(document, position, cancellationToken).ConfigureAwait(false); IInteractiveWindowCommands commands = window.GetInteractiveCommands(); if (commands != null) { foreach (var command in commands.GetCommands()) { foreach (var commandName in command.Names) { string completion = GetCompletionString(commandName); context.AddItem(new CompletionItem( this, completion, filterSpan, c => Task.FromResult(command.Description.ToSymbolDisplayParts()), glyph: Glyph.Intrinsic)); } } } } } } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); DeclarationModifiers modifiers; SyntaxToken token; if (!IsPartialCompletionContext(tree, position, cancellationToken, out modifiers, out token)) { return; } var items = await CreatePartialItemsAsync(document, position, modifiers, token, cancellationToken).ConfigureAwait(false); if (items?.Any() == true) { context.MakeExclusive(true); context.AddItems(items); } }
/// <summary> /// Implement to register the items and other details for a <see cref="CompletionList"/> /// </summary> public abstract Task ProduceCompletionListAsync(CompletionListContext context);
private static async Task<CompletionList> GetCompletionListAsync( CompletionListProvider provider, Document documentOpt, SourceText text, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken) { if (provider is TextCompletionProvider) { return ((TextCompletionProvider)provider).GetCompletionList(text, position, triggerInfo, cancellationToken); } if (documentOpt != null) { var context = new CompletionListContext(documentOpt, position, triggerInfo, cancellationToken); await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); return new CompletionList(context.GetItems(), context.Builder, context.IsExclusive); } Contract.Fail("Should never get here."); return null; }
private static async Task<CompletionList> GetCompletionListAsync( CompletionListProvider provider, Document document, int position, CompletionTriggerInfo triggerInfo, OptionSet options, CancellationToken cancellationToken) { var context = new CompletionListContext(document, position, triggerInfo, options, cancellationToken); if (document.SupportsSyntaxTree) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (!root.FullSpan.IntersectsWith(position)) { try { // Trying to track down source of https://github.com/dotnet/roslyn/issues/9325 var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); ReportException(position, root, sourceText); } catch (Exception e) when (FatalError.ReportWithoutCrash(e)) { } } else { await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); } } else { await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); } return new CompletionList(context.GetItems(), context.Builder, context.IsExclusive); }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var span = new TextSpan(position, length: 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var syntaxTree = semanticModel.SyntaxTree; var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); var semanticFacts = document.GetLanguageService<ISemanticFactsService>(); if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || semanticFacts.IsPreProcessorDirectiveContext(semanticModel, position, cancellationToken)) { return; } if (!syntaxTree.IsRightOfDotOrArrowOrColonColon(position, cancellationToken)) { return; } var node = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) .GetPreviousTokenIfTouchingWord(position) .Parent; if (node.Kind() != SyntaxKind.ExplicitInterfaceSpecifier) { return; } // Bind the interface name which is to the left of the dot var name = ((ExplicitInterfaceSpecifierSyntax)node).Name; var symbol = semanticModel.GetSymbolInfo(name, cancellationToken).Symbol as ITypeSymbol; if (symbol?.TypeKind != TypeKind.Interface) { return; } var members = semanticModel.LookupSymbols( position: name.SpanStart, container: symbol) .Where(s => !s.IsStatic) .FilterToVisibleAndBrowsableSymbols(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation); // We're going to create a entry for each one, including the signature var namePosition = name.SpanStart; var text = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); foreach (var member in members) { var displayText = member.ToMinimalDisplayString(semanticModel, namePosition, s_signatureDisplayFormat); var insertionText = displayText; context.AddItem(new SymbolCompletionItem( this, displayText, insertionText: insertionText, filterSpan: textChangeSpan, position: position, symbols: new List<ISymbol> { member }, context: CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken), rules: ItemRules.Instance)); } }
public override async Task ProduceCompletionListAsync(CompletionListContext context) { try { var document = context.Document; var position = context.Position; var options = context.Options; var cancellationToken = context.CancellationToken; var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (tree.IsInNonUserCode(position, cancellationToken)) { return; } var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken); if (token.IsMandatoryNamedParameterPosition()) { return; } var typeInferenceService = document.GetLanguageService<ITypeInferenceService>(); var span = new TextSpan(position, 0); var semanticModel = await document.GetSemanticModelForSpanAsync(span, cancellationToken).ConfigureAwait(false); var type = typeInferenceService.InferType(semanticModel, position, objectAsDefault: true, cancellationToken: cancellationToken); // If we have a Nullable<T>, unwrap it. if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) { type = type.GetTypeArguments().FirstOrDefault(); if (type == null) { return; } } if (type.TypeKind != TypeKind.Enum) { type = GetCompletionListType(type, semanticModel.GetEnclosingNamedType(position, cancellationToken), semanticModel.Compilation); if (type == null) { return; } } if (!type.IsEditorBrowsable(options.GetOption(CompletionOptions.HideAdvancedMembers, semanticModel.Language), semanticModel.Compilation)) { return; } // Does type have any aliases? ISymbol alias = await type.FindApplicableAlias(position, semanticModel, cancellationToken).ConfigureAwait(false); var displayService = document.GetLanguageService<ISymbolDisplayService>(); var displayText = alias != null ? alias.Name : displayService.ToMinimalDisplayString(semanticModel, position, type); var workspace = document.Project.Solution.Workspace; var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); var textChangeSpan = CompletionUtilities.GetTextChangeSpan(text, position); var item = new CompletionItem( this, displayText: displayText, filterSpan: textChangeSpan, descriptionFactory: CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, position, alias ?? type), glyph: (alias ?? type).GetGlyph(), preselect: true, rules: ItemRules.Instance); context.AddItem(item); } catch (Exception e) when (FatalError.ReportUnlessCanceled(e)) { throw ExceptionUtilities.Unreachable; } }
private static async Task<CompletionList> GetCompletionListAsync( CompletionListProvider provider, Document document, int position, CompletionTriggerInfo triggerInfo, OptionSet options, CancellationToken cancellationToken) { var context = new CompletionListContext(document, position, triggerInfo, options, cancellationToken); await provider.ProduceCompletionListAsync(context).ConfigureAwait(false); return new CompletionList(context.GetItems(), context.Builder, context.IsExclusive); }