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);
        }
Exemplo n.º 11
0
        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));
                    }
                }
            }
        }
Exemplo n.º 13
0
        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));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 14
0
        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;
        }
Exemplo n.º 19
0
        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;
            }
        }
 /// <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 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);
        }