Beispiel #1
0
 public SymbolCompletionItem(
     CompletionListProvider completionProvider,
     string displayText,
     string insertionText,
     string filterText,
     TextSpan filterSpan,
     int position,
     List<ISymbol> symbols,
     string sortText,
     AbstractSyntaxContext context,
     Glyph glyph,
     bool preselect = false,
     SupportedPlatformData supportedPlatforms = null,
     CompletionItemRules rules = null)
 : base(completionProvider, displayText, filterSpan,
    descriptionFactory: null, glyph: glyph,
    sortText: sortText, filterText: filterText, preselect: preselect, showsWarningIcon: supportedPlatforms != null, rules: rules,
    filters: GetFilters(symbols))
 {
     this.InsertionText = insertionText;
     this.Position = position;
     this.Symbols = symbols;
     this.Context = context;
     _supportedPlatforms = supportedPlatforms;
 }
Beispiel #2
0
 public static CompletionItem Create(
     string displayText,
     TextSpan span,
     ISymbol symbol,
     int contextPosition = -1,
     int descriptionPosition = -1,
     string sortText = null,
     string insertionText = null,
     Glyph? glyph = null,
     string filterText = null,
     bool preselect = false,
     SupportedPlatformData supportedPlatforms = null,
     bool isArgumentName = false,
     ImmutableDictionary<string, string> properties = null,
     CompletionItemRules rules = null)
 {
     return Create(
         displayText: displayText,
         span: span,
         symbols: ImmutableArray.Create(symbol),
         contextPosition: contextPosition,
         descriptionPosition: descriptionPosition,
         sortText: sortText,
         insertionText: insertionText,
         glyph: glyph,
         filterText: filterText,
         preselect: preselect,
         supportedPlatforms: supportedPlatforms,
         isArgumentName: isArgumentName,
         properties: properties,
         rules: rules);
 }
 public static CompletionItem Create(
     string displayText,
     ISymbol symbol,
     int contextPosition = -1,
     string sortText = null,
     string insertionText = null,
     Glyph? glyph = null,
     string filterText = null,
     int? matchPriority = null,
     SupportedPlatformData supportedPlatforms = null,
     ImmutableDictionary<string, string> properties = null,
     CompletionItemRules rules = null)
 {
     return Create(
         displayText: displayText,
         symbols: ImmutableArray.Create(symbol),
         contextPosition: contextPosition,
         sortText: sortText,
         insertionText: insertionText,
         glyph: glyph,
         filterText: filterText,
         matchPriority: matchPriority.GetValueOrDefault(),
         supportedPlatforms: supportedPlatforms,
         properties: properties,
         rules: rules);
 }
Beispiel #4
0
        public static CompletionItem Create(
            string displayText,
            TextSpan span,
            IReadOnlyList<ISymbol> symbols,
            int contextPosition = -1,
            int descriptionPosition = -1,
            string sortText = null,
            string insertionText = null,
            Glyph? glyph = null,
            string filterText = null,
            bool preselect = false,
            SupportedPlatformData supportedPlatforms = null,
            bool isArgumentName = false,
            ImmutableDictionary<string, string> properties = null,
            ImmutableArray<string> tags = default(ImmutableArray<string>),
            CompletionItemRules rules = null)
        {
            var props = properties ?? ImmutableDictionary<string, string>.Empty;

            props = props.Add("Symbols", EncodeSymbols(symbols));

            if (insertionText != null)
            {
                props = props.Add("InsertionText", insertionText);
            }

            if (contextPosition >= 0)
            {
                props = props.Add("ContextPosition", contextPosition.ToString());
            }

            if (descriptionPosition >= 0)
            {
                props = props.Add("DescriptionPosition", descriptionPosition.ToString());
            }

            var item = CommonCompletionItem.Create(
                displayText: displayText,
                span: span,
                filterText: filterText ?? (displayText.Length > 0 && displayText[0] == '@' ? displayText : symbols[0].Name),
                sortText: sortText ?? symbols[0].Name,
                glyph: glyph ?? symbols[0].GetGlyph(),
                preselect: preselect,
                isArgumentName: isArgumentName,
                showsWarningIcon: supportedPlatforms != null,
                properties: props,
                tags: tags,
                rules: rules);

            return WithSupportedPlatforms(item, supportedPlatforms);
        }
 protected override CompletionItem CreateItem(string displayText, string insertionText, int position, List<ISymbol> symbols, AbstractSyntaxContext context, TextSpan span, bool preselect, SupportedPlatformData supportedPlatformData)
 {
     return SymbolCompletionItem.Create(
         displayText: displayText,
         insertionText: insertionText,
         filterText: GetFilterText(symbols[0], displayText, context),
         span: span,
         contextPosition: context.Position,
         descriptionPosition: position,
         symbols: symbols,
         supportedPlatforms: supportedPlatformData,
         preselect: preselect,
         tags: s_Tags,
         rules: GetCompletionItemRules(symbols, context));
 }
 protected override CompletionItem CreateItem(
     string displayText, string insertionText, List<ISymbol> symbols,
     SyntaxContext context, bool preselect,
     SupportedPlatformData supportedPlatformData)
 {
     return SymbolCompletionItem.Create(
         displayText: displayText,
         insertionText: insertionText,
         filterText: GetFilterText(symbols[0], displayText, context),
         contextPosition: context.Position,
         symbols: symbols,
         supportedPlatforms: supportedPlatformData,
         matchPriority: MatchPriority.Preselect, // Always preselect
         tags: s_Tags,
         rules: GetCompletionItemRules(symbols, context));
 }
Beispiel #7
0
 public SymbolCompletionItem(
     CompletionListProvider completionProvider,
     string displayText,
     string insertionText,
     string filterText,
     TextSpan filterSpan,
     int position,
     List<ISymbol> symbols,
     AbstractSyntaxContext context,
     bool preselect = false,
     SupportedPlatformData supportedPlatforms = null,
     CompletionItemRules rules = null)
 : this(completionProvider, displayText, insertionText, filterText, filterSpan, position,
       symbols, sortText: symbols[0].Name, context: context, glyph: symbols[0].GetGlyph(),
       preselect: preselect, supportedPlatforms: supportedPlatforms, rules: rules)
 {
 }
 public SymbolCompletionItem(
     CompletionListProvider completionProvider,
     string displayText,
     string insertionText,
     TextSpan filterSpan,
     int position,
     List<ISymbol> symbols,
     AbstractSyntaxContext context,
     bool preselect = false,
     SupportedPlatformData supportedPlatforms = null)
     : this(completionProvider,
           displayText,
           insertionText,
           filterText: displayText.Length > 0 && displayText[0] == '@' ? displayText : symbols[0].Name,
           filterSpan: filterSpan,
           position: position, symbols: symbols, context: context, preselect: preselect, supportedPlatforms: supportedPlatforms)
 {
 }
        protected override CompletionItem CreateItem(string displayText, string insertionText, List<ISymbol> symbols, SyntaxContext context, bool preselect, SupportedPlatformData supportedPlatformData)
        {
            var matchPriority = preselect ? ComputeSymbolMatchPriority(symbols[0]) : MatchPriority.Default;
            var rules = GetCompletionItemRules(symbols, context, preselect);
            if (preselect)
            {
                rules = rules.WithSelectionBehavior(PreselectedItemSelectionBehavior);
            }

            return SymbolCompletionItem.Create(
                displayText: displayText,
                insertionText: insertionText,
                filterText: GetFilterText(symbols[0], displayText, context),
                contextPosition: context.Position,
                symbols: symbols,
                supportedPlatforms: supportedPlatformData,
                matchPriority: matchPriority,
                rules: rules);
        }
        public static CompletionItem Create(
            string displayText,
            IReadOnlyList<ISymbol> symbols,
            int contextPosition = -1,
            string sortText = null,
            string insertionText = null,
            Glyph? glyph = null,
            string filterText = null,
            int? matchPriority = null,
            SupportedPlatformData supportedPlatforms = null,
            ImmutableDictionary<string, string> properties = null,
            ImmutableArray<string> tags = default(ImmutableArray<string>),
            CompletionItemRules rules = null)
        {
            var props = properties ?? ImmutableDictionary<string, string>.Empty;

            props = props.Add("Symbols", EncodeSymbols(symbols));

            if (insertionText != null)
            {
                props = props.Add("InsertionText", insertionText);
            }

            if (contextPosition >= 0)
            {
                props = props.Add("ContextPosition", contextPosition.ToString());
            }

            var item = CommonCompletionItem.Create(
                displayText: displayText,
                filterText: filterText ?? (displayText.Length > 0 && displayText[0] == '@' ? displayText : symbols[0].Name),
                sortText: sortText ?? symbols[0].Name,
                glyph: glyph ?? symbols[0].GetGlyph(),
                matchPriority: matchPriority.GetValueOrDefault(),
                showsWarningIcon: supportedPlatforms != null,
                properties: props,
                tags: tags,
                rules: rules);

            return WithSupportedPlatforms(item, supportedPlatforms);
        }
 public SymbolCompletionItem(
     ICompletionProvider completionProvider,
     string displayText,
     string insertionText,
     string filterText,
     TextSpan filterSpan,
     int position,
     List<ISymbol> symbols,
     AbstractSyntaxContext context,
     bool preselect = false,
     SupportedPlatformData supportedPlatforms = null)
 : base(completionProvider, displayText, filterSpan,
    descriptionFactory: null, glyph: symbols[0].GetGlyph(),
    sortText: symbols[0].Name, filterText: filterText, preselect: preselect, showsWarningIcon: supportedPlatforms != null)
 {
     this.InsertionText = insertionText;
     this.Position = position;
     this.Symbols = symbols;
     this.Context = context;
     _supportedPlatorms = supportedPlatforms;
 }
Beispiel #12
0
 protected virtual CompletionItem CreateItem(string displayText, string insertionText, int position, List<ISymbol> symbols, AbstractSyntaxContext context, TextSpan span, bool preselect, SupportedPlatformData supportedPlatformData)
 {
     return SymbolCompletionItem.Create(
         displayText: displayText,
         insertionText: insertionText,
         filterText: GetFilterText(symbols[0], displayText, context),
         span: span,
         contextPosition: context.Position,
         descriptionPosition: position,
         symbols: symbols,
         supportedPlatforms: supportedPlatformData,
         matchPriority: preselect ? MatchPriority.Preselect : MatchPriority.Default,
         rules: GetCompletionItemRules(symbols, context));
 }
        protected override async Task<IDeferredQuickInfoContent> BuildContentAsync(
            Document document,
            SyntaxToken token,
            CancellationToken cancellationToken)
        {
            var linkedDocumentIds = document.GetLinkedDocumentIds();

            var modelAndSymbols = await this.BindTokenAsync(document, token, cancellationToken).ConfigureAwait(false);
            if (modelAndSymbols.Item2.Length == 0 && !linkedDocumentIds.Any())
            {
                return null;
            }

            if (!linkedDocumentIds.Any())
            {
                return await CreateContentAsync(document.Project.Solution.Workspace,
                    token,
                    modelAndSymbols.Item1,
                    modelAndSymbols.Item2,
                    supportedPlatforms: null,
                    cancellationToken: cancellationToken).ConfigureAwait(false);
            }

            // Linked files/shared projects: imagine the following when FOO is false
            // #if FOO
            // int x = 3;
            // #endif 
            // var y = x$$;
            //
            // 'x' will bind as an error type, so we'll show incorrect information.
            // Instead, we need to find the head in which we get the best binding, 
            // which in this case is the one with no errors.

            var candidateProjects = new List<ProjectId>() { document.Project.Id };
            var invalidProjects = new List<ProjectId>();

            var candidateResults = new List<Tuple<DocumentId, SemanticModel, ImmutableArray<ISymbol>>>();
            candidateResults.Add(Tuple.Create(document.Id, modelAndSymbols.Item1, modelAndSymbols.Item2));

            foreach (var link in linkedDocumentIds)
            {
                var linkedDocument = document.Project.Solution.GetDocument(link);
                var linkedToken = await FindTokenInLinkedDocument(token, linkedDocument, cancellationToken).ConfigureAwait(false);

                if (linkedToken != default(SyntaxToken))
                {
                    // Not in an inactive region, so this file is a candidate.
                    candidateProjects.Add(link.ProjectId);
                    var linkedModelAndSymbols = await this.BindTokenAsync(linkedDocument, linkedToken, cancellationToken).ConfigureAwait(false);
                    candidateResults.Add(Tuple.Create(link, linkedModelAndSymbols.Item1, linkedModelAndSymbols.Item2));
                }
            }

            // Take the first result with no errors.
            var bestBinding = candidateResults.FirstOrDefault(
                c => c.Item3.Length > 0 && !ErrorVisitor.ContainsError(c.Item3.FirstOrDefault()));

            // Every file binds with errors. Take the first candidate, which is from the current file.
            if (bestBinding == null)
            {
                bestBinding = candidateResults.First();
            }

            if (bestBinding.Item3 == null || !bestBinding.Item3.Any())
            {
                return null;
            }

            // We calculate the set of supported projects
            candidateResults.Remove(bestBinding);
            foreach (var candidate in candidateResults)
            {
                // Does the candidate have anything remotely equivalent?
                if (!candidate.Item3.Intersect(bestBinding.Item3, LinkedFilesSymbolEquivalenceComparer.Instance).Any())
                {
                    invalidProjects.Add(candidate.Item1.ProjectId);
                }
            }

            var supportedPlatforms = new SupportedPlatformData(invalidProjects, candidateProjects, document.Project.Solution.Workspace);
            return await CreateContentAsync(document.Project.Solution.Workspace, token, bestBinding.Item2, bestBinding.Item3, supportedPlatforms, cancellationToken).ConfigureAwait(false);
        }
        protected async Task<IDeferredQuickInfoContent> CreateContentAsync(
            Workspace workspace,
            SyntaxToken token,
            SemanticModel semanticModel,
            IEnumerable<ISymbol> symbols,
            SupportedPlatformData supportedPlatforms,
            CancellationToken cancellationToken)
        {
            var descriptionService = workspace.Services.GetLanguageServices(token.Language).GetService<ISymbolDisplayService>();

            var sections = await descriptionService.ToDescriptionGroupsAsync(workspace, semanticModel, token.SpanStart, symbols.AsImmutable(), cancellationToken).ConfigureAwait(false);

            var mainDescriptionBuilder = new List<TaggedText>();
            if (sections.ContainsKey(SymbolDescriptionGroups.MainDescription))
            {
                mainDescriptionBuilder.AddRange(sections[SymbolDescriptionGroups.MainDescription]);
            }

            var typeParameterMapBuilder = new List<TaggedText>();
            if (sections.ContainsKey(SymbolDescriptionGroups.TypeParameterMap))
            {
                var parts = sections[SymbolDescriptionGroups.TypeParameterMap];
                if (!parts.IsDefaultOrEmpty)
                {
                    typeParameterMapBuilder.AddLineBreak();
                    typeParameterMapBuilder.AddRange(parts);
                }
            }

            var anonymousTypesBuilder = new List<TaggedText>();
            if (sections.ContainsKey(SymbolDescriptionGroups.AnonymousTypes))
            {
                var parts = sections[SymbolDescriptionGroups.AnonymousTypes];
                if (!parts.IsDefaultOrEmpty)
                {
                    anonymousTypesBuilder.AddLineBreak();
                    anonymousTypesBuilder.AddRange(parts);
                }
            }

            var usageTextBuilder = new List<TaggedText>();
            if (sections.ContainsKey(SymbolDescriptionGroups.AwaitableUsageText))
            {
                var parts = sections[SymbolDescriptionGroups.AwaitableUsageText];
                if (!parts.IsDefaultOrEmpty)
                {
                    usageTextBuilder.AddRange(parts);
                }
            }

            if (supportedPlatforms != null)
            {
                usageTextBuilder.AddRange(supportedPlatforms.ToDisplayParts().ToTaggedText());
            }

            var exceptionsTextBuilder = new List<TaggedText>();
            if (sections.ContainsKey(SymbolDescriptionGroups.Exceptions))
            {
                var parts = sections[SymbolDescriptionGroups.Exceptions];
                if (!parts.IsDefaultOrEmpty)
                {
                    exceptionsTextBuilder.AddRange(parts);
                }
            }

            var formatter = workspace.Services.GetLanguageServices(semanticModel.Language).GetService<IDocumentationCommentFormattingService>();
            var syntaxFactsService = workspace.Services.GetLanguageServices(semanticModel.Language).GetService<ISyntaxFactsService>();
            var documentationContent = GetDocumentationContent(symbols, sections, semanticModel, token, formatter, syntaxFactsService, cancellationToken);
            var showWarningGlyph = supportedPlatforms != null && supportedPlatforms.HasValidAndInvalidProjects();
            var showSymbolGlyph = true;

            if (workspace.Services.GetLanguageServices(semanticModel.Language).GetService<ISyntaxFactsService>().IsAwaitKeyword(token) &&
                (symbols.First() as INamedTypeSymbol)?.SpecialType == SpecialType.System_Void)
            {
                documentationContent = CreateDocumentationCommentDeferredContent(null);
                showSymbolGlyph = false;
            }

            return this.CreateQuickInfoDisplayDeferredContent(
                symbol: symbols.First(),
                showWarningGlyph: showWarningGlyph,
                showSymbolGlyph: showSymbolGlyph,
                mainDescription: mainDescriptionBuilder,
                documentation: documentationContent,
                typeParameterMap: typeParameterMapBuilder,
                anonymousTypes: anonymousTypesBuilder,
                usageText: usageTextBuilder,
                exceptionText: exceptionsTextBuilder);
        }
 protected virtual CompletionItem CreateItem(ValueTuple<string, string> displayAndInsertionText, int position, List<ISymbol> symbols, AbstractSyntaxContext context, TextSpan textChangeSpan, bool preselect, SupportedPlatformData supportedPlatformData)
 {
     return new SymbolCompletionItem(
         this,
         displayAndInsertionText.Item1,
         displayAndInsertionText.Item2,
         GetFilterText(symbols[0], displayAndInsertionText.Item1, context),
         textChangeSpan,
         position,
         symbols,
         context,
         supportedPlatforms: supportedPlatformData,
         preselect: preselect);
 }
 public static Func<CancellationToken, Task<ImmutableArray<SymbolDisplayPart>>> CreateDescriptionFactory(
     Workspace workspace, SemanticModel semanticModel, int position, IList<ISymbol> symbols, SupportedPlatformData supportedPlatforms)
 {
     return c => CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms: supportedPlatforms, cancellationToken: c);
 }
        public async Task<SignatureHelpItems> GetItemsAsync(
            Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var itemsForCurrentDocument = await GetItemsWorkerAsync(document, position, triggerInfo, cancellationToken).ConfigureAwait(false);
            if (itemsForCurrentDocument == null)
            {
                return itemsForCurrentDocument;
            }

            var relatedDocuments = document.GetLinkedDocumentIds();
            if (!relatedDocuments.Any())
            {
                return itemsForCurrentDocument;
            }

            var relatedDocumentsAndItems = await GetItemsForRelatedDocuments(document, relatedDocuments, position, triggerInfo, cancellationToken).ConfigureAwait(false);
            var candidateLinkedProjectsAndSymbolSets = await ExtractSymbolsFromRelatedItems(position, relatedDocumentsAndItems, cancellationToken).ConfigureAwait(false);

            var totalProjects = candidateLinkedProjectsAndSymbolSets.Select(c => c.Item1).Concat(document.Project.Id);

            var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, 0), cancellationToken).ConfigureAwait(false);
            var compilation = semanticModel.Compilation;
            var finalItems = new List<SignatureHelpItem>();
            foreach (var item in itemsForCurrentDocument.Items)
            {
                var symbolKey = ((SymbolKeySignatureHelpItem)item).SymbolKey;
                if (symbolKey == null)
                {
                    finalItems.Add(item);
                    continue;
                }

                var expectedSymbol = symbolKey.Resolve(compilation, ignoreAssemblyKey: true, cancellationToken: cancellationToken).Symbol;

                if (expectedSymbol == null)
                {
                    finalItems.Add(item);
                    continue;
                }

                var invalidProjectsForCurrentSymbol = candidateLinkedProjectsAndSymbolSets.Where(c => !c.Item2.Contains(expectedSymbol, LinkedFilesSymbolEquivalenceComparer.IgnoreAssembliesInstance))
                                                                        .Select(c => c.Item1)
                                                                        .ToList();

                var platformData = new SupportedPlatformData(invalidProjectsForCurrentSymbol, totalProjects, document.Project.Solution.Workspace);
                finalItems.Add(UpdateItem(item, platformData, expectedSymbol));
            }

            return new SignatureHelpItems(
                finalItems, itemsForCurrentDocument.ApplicableSpan,
                itemsForCurrentDocument.ArgumentIndex,
                itemsForCurrentDocument.ArgumentCount,
                itemsForCurrentDocument.ArgumentName,
                itemsForCurrentDocument.SelectedItemIndex);
        }
        private SignatureHelpItem UpdateItem(SignatureHelpItem item, SupportedPlatformData platformData, ISymbol symbol)
        {
            var platformParts = platformData.ToDisplayParts();
            if (platformParts.Count == 0)
            {
                return item;
            }

            var startingNewLine = new List<SymbolDisplayPart>();
            startingNewLine.AddLineBreak();

            var updatedDescription = item.DescriptionParts == null
                ? item.DescriptionParts.Concat(startingNewLine.Concat(platformParts))
                : startingNewLine.Concat(platformParts);

            item.DescriptionParts = updatedDescription.ToImmutableArrayOrEmpty();
            return item;
        }
 public static Func<CancellationToken, Task<CompletionDescription>> CreateDescriptionFactory(
     Workspace workspace, SemanticModel semanticModel, int position, IReadOnlyList<ISymbol> symbols, SupportedPlatformData supportedPlatforms)
 {
     return c => CreateDescriptionAsync(workspace, semanticModel, position, symbols, supportedPlatforms: supportedPlatforms, cancellationToken: c);
 }
Beispiel #20
0
 private static CompletionItem WithSupportedPlatforms(CompletionItem completionItem, SupportedPlatformData supportedPlatforms)
 {
     if (supportedPlatforms != null)
     {
         return completionItem
             .AddProperty("InvalidProjects", string.Join(";", supportedPlatforms.InvalidProjects.Select(id => id.Id)))
             .AddProperty("CandidateProjects", string.Join(";", supportedPlatforms.CandidateProjects.Select(id => id.Id)));
     }
     else
     {
         return completionItem;
     }
 }
        public static async Task<CompletionDescription> CreateDescriptionAsync(
            Workspace workspace, SemanticModel semanticModel, int position, IReadOnlyList<ISymbol> symbols, SupportedPlatformData supportedPlatforms, CancellationToken cancellationToken)
        {
            var symbolDisplayService = workspace.Services.GetLanguageServices(semanticModel.Language).GetService<ISymbolDisplayService>();
            var formatter = workspace.Services.GetLanguageServices(semanticModel.Language).GetService<IDocumentationCommentFormattingService>();

            // TODO(cyrusn): Figure out a way to cancel this.
            var symbol = symbols[0];
            var sections = await symbolDisplayService.ToDescriptionGroupsAsync(workspace, semanticModel, position, ImmutableArray.Create(symbol), cancellationToken).ConfigureAwait(false);

            if (!sections.ContainsKey(SymbolDescriptionGroups.MainDescription))
            {
                return CompletionDescription.Empty;
            }

            var textContentBuilder = new List<SymbolDisplayPart>();
            textContentBuilder.AddRange(sections[SymbolDescriptionGroups.MainDescription]);

            switch (symbol.Kind)
            {
                case SymbolKind.Method:
                case SymbolKind.NamedType:
                    if (symbols.Count > 1)
                    {
                        var overloadCount = symbols.Count - 1;
                        var isGeneric = symbol.GetArity() > 0;

                        textContentBuilder.AddSpace();
                        textContentBuilder.AddPunctuation("(");
                        textContentBuilder.AddPunctuation("+");
                        textContentBuilder.AddText(NonBreakingSpaceString + overloadCount.ToString());

                        AddOverloadPart(textContentBuilder, overloadCount, isGeneric);

                        textContentBuilder.AddPunctuation(")");
                    }

                    break;
            }

            AddDocumentationPart(textContentBuilder, symbol, semanticModel, position, formatter, cancellationToken);

            if (sections.ContainsKey(SymbolDescriptionGroups.AwaitableUsageText))
            {
                textContentBuilder.AddRange(sections[SymbolDescriptionGroups.AwaitableUsageText]);
            }

            if (sections.ContainsKey(SymbolDescriptionGroups.AnonymousTypes))
            {
                var parts = sections[SymbolDescriptionGroups.AnonymousTypes];
                if (!parts.IsDefaultOrEmpty)
                {
                    textContentBuilder.AddLineBreak();
                    textContentBuilder.AddLineBreak();
                    textContentBuilder.AddRange(parts);
                }
            }

            if (supportedPlatforms != null)
            {
                textContentBuilder.AddLineBreak();
                textContentBuilder.AddRange(supportedPlatforms.ToDisplayParts());
            }

            return CompletionDescription.Create(textContentBuilder.Select(p => new TaggedText(SymbolDisplayPartKindTags.GetTag(p.Kind), p.ToString())).ToImmutableArray());
        }
        /// <summary>
        /// Given a Symbol, creates the completion item for it.
        /// </summary>
        private CompletionItem CreateItem(
            string displayText,
            string insertionText,
            List<ISymbol> symbols,
            SyntaxContext context,
            Dictionary<ISymbol, List<ProjectId>> invalidProjectMap,
            List<ProjectId> totalProjects,
            bool preselect)
        {
            Contract.ThrowIfNull(symbols);

            SupportedPlatformData supportedPlatformData = null;
            if (invalidProjectMap != null)
            {
                List<ProjectId> invalidProjects = null;
                foreach (var symbol in symbols)
                {
                    if (invalidProjectMap.TryGetValue(symbol, out invalidProjects))
                    {
                        break;
                    }
                }

                if (invalidProjects != null)
                {
                    supportedPlatformData = new SupportedPlatformData(invalidProjects, totalProjects, context.Workspace);
                }
            }

            return CreateItem(displayText, insertionText, symbols, context, preselect, supportedPlatformData);
        }
 protected virtual CompletionItem CreateItem(
     string displayText, string insertionText,
     List<ISymbol> symbols,
     SyntaxContext context, bool preselect,
     SupportedPlatformData supportedPlatformData)
 {
     return SymbolCompletionItem.Create(
         displayText: displayText,
         insertionText: insertionText,
         filterText: GetFilterText(symbols[0], displayText, context),
         contextPosition: context.Position,
         symbols: symbols,
         supportedPlatforms: supportedPlatformData,
         matchPriority: preselect ? MatchPriority.Preselect : MatchPriority.Default,
         rules: GetCompletionItemRules(symbols, context),
         properties: GetInitialProperties(symbols[0], context));
 }
        /// <summary>
        /// Given a Symbol, creates the completion item for it.
        /// </summary>
        private CompletionItem CreateItem(
            ValueTuple<string, string> displayAndInsertionText,
            int position,
            List<ISymbol> symbols,
            AbstractSyntaxContext context,
            TextSpan textChangeSpan,
            Dictionary<ISymbol, List<ProjectId>> invalidProjectMap,
            List<ProjectId> totalProjects,
            bool preselect,
            CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(symbols);

            SupportedPlatformData supportedPlatformData = null;
            if (invalidProjectMap != null)
            {
                List<ProjectId> invalidProjects = null;
                foreach (var symbol in symbols)
                {
                    if (invalidProjectMap.TryGetValue(symbol, out invalidProjects))
                    {
                        break;
                    }
                }

                if (invalidProjects != null)
                {
                    supportedPlatformData = new SupportedPlatformData(invalidProjects, totalProjects, context.Workspace);
                }
            }

            return CreateItem(displayAndInsertionText, position, symbols, context, textChangeSpan, preselect, supportedPlatformData);
        }
        private SignatureHelpItem UpdateItem(SignatureHelpItem item, SupportedPlatformData platformData, ISymbol symbol)
        {
            var platformParts = platformData.ToDisplayParts().ToTaggedText();
            if (platformParts.Length == 0)
            {
                return item;
            }

            var startingNewLine = new List<TaggedText>();
            startingNewLine.AddLineBreak();

            var concatted = startingNewLine.Concat(platformParts);
            var updatedDescription = item.DescriptionParts.IsDefault
                ? concatted
                : item.DescriptionParts.Concat(concatted);

            item.DescriptionParts = updatedDescription.ToImmutableArrayOrEmpty();
            return item;
        }