| File: Completion\CompletionList.cs | Web Access |
| Project: src\roslyn\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Completion; /// <summary> /// The set of completions to present to the user. /// </summary> public sealed class CompletionList { private readonly Lazy<ImmutableArray<CompletionItem>> _lazyItems; /// <summary> /// The completion items to present to the user. /// </summary> [Obsolete($"This property is obsolete. Use {nameof(ItemsList)} instead", error: false)] [EditorBrowsable(EditorBrowsableState.Never)] public ImmutableArray<CompletionItem> Items => _lazyItems.Value; /// <summary> /// The completion items to present to the user. /// This property is preferred over `Items` because of the flexibility it provides. /// For example, the list can be backed by types like SegmentedList to avoid LOH allocations. /// </summary> public IReadOnlyList<CompletionItem> ItemsList { get; } /// <summary> /// The span of the syntax element at the caret position when the <see cref="CompletionList"/> was created. /// Individual <see cref="CompletionItem"/> spans may vary. /// </summary> [Obsolete("Not used anymore. CompletionList.Span is used instead.", error: true)] public TextSpan DefaultSpan { get; } /// <summary> /// The span of the syntax element at the caret position when the <see cref="CompletionList"/> /// was created. /// /// The span identifies the text in the document that is used to filter the initial list /// presented to the user, and typically represents the region of the document that will /// be changed if this item is committed. /// The latter is not always the case because each provider is free to make more complex changes /// to the document. If this is the case, <see cref="CompletionItem.IsComplexTextEdit"/> must be /// set to <see langword="true"/>. /// </summary> public TextSpan Span { get; } /// <summary> /// The rules used to control behavior of the completion list shown to the user during typing. /// </summary> public CompletionRules Rules { get; } /// <summary> /// An optional <see cref="CompletionItem"/> that appears selected in the list presented to the user during suggestion mode. /// Suggestion mode disables auto-selection of items in the list, giving preference to the text typed by the user unless a specific item is selected manually. /// Specifying a <see cref="SuggestionModeItem"/> is a request that the completion host operate in suggestion mode. /// The item specified determines the text displayed and the description associated with it unless a different item is manually selected. /// No text is ever inserted when this item is completed, leaving the text the user typed instead. /// </summary> public CompletionItem? SuggestionModeItem { get; } /// <summary> /// Whether the items in this list should be the only items presented to the user. /// </summary> internal bool IsExclusive { get; } private CompletionList( TextSpan defaultSpan, IReadOnlyList<CompletionItem> itemsList, CompletionRules? rules, CompletionItem? suggestionModeItem, bool isExclusive) { Span = defaultSpan; ItemsList = itemsList; _lazyItems = new(() => ItemsList.ToImmutableArrayOrEmpty(), System.Threading.LazyThreadSafetyMode.PublicationOnly); Rules = rules ?? CompletionRules.Default; SuggestionModeItem = suggestionModeItem; IsExclusive = isExclusive; foreach (var item in ItemsList) { item.Span = defaultSpan; } } /// <summary> /// Creates a new <see cref="CompletionList"/> instance. /// </summary> /// <param name="defaultSpan">The span of the syntax element at the caret position when the <see cref="CompletionList"/> was created.</param> /// <param name="items">The completion items to present to the user.</param> /// <param name="rules">The rules used to control behavior of the completion list shown to the user during typing.</param> /// <param name="suggestionModeItem">An optional <see cref="CompletionItem"/> that appears selected in the list presented to the user during suggestion mode.</param> public static CompletionList Create( TextSpan defaultSpan, ImmutableArray<CompletionItem> items, CompletionRules? rules = null, CompletionItem? suggestionModeItem = null) { return Create(defaultSpan, items, rules, suggestionModeItem, isExclusive: false); } internal static CompletionList Create( TextSpan defaultSpan, IReadOnlyList<CompletionItem> itemsList, CompletionRules? rules, CompletionItem? suggestionModeItem, bool isExclusive) { return new CompletionList(defaultSpan, itemsList, rules, suggestionModeItem, isExclusive); } private CompletionList With( Optional<TextSpan> span = default, Optional<IReadOnlyList<CompletionItem>> itemsList = default, Optional<CompletionRules> rules = default, Optional<CompletionItem> suggestionModeItem = default) { var newSpan = span.HasValue ? span.Value : Span; var newItemsList = itemsList.HasValue ? itemsList.Value : ItemsList; var newRules = rules.HasValue ? rules.Value : Rules; var newSuggestionModeItem = suggestionModeItem.HasValue ? suggestionModeItem.Value : SuggestionModeItem; if (newSpan == Span && newItemsList == ItemsList && newRules == Rules && newSuggestionModeItem == SuggestionModeItem) { return this; } else { return Create(newSpan, newItemsList, newRules, newSuggestionModeItem, IsExclusive); } } /// <summary> /// Creates a copy of this <see cref="CompletionList"/> with the <see cref="DefaultSpan"/> property changed. /// </summary> [Obsolete("Not used anymore. Use WithSpan instead.", error: true)] public CompletionList WithDefaultSpan(TextSpan span) => With(span: span); public CompletionList WithSpan(TextSpan span) => With(span: span); #pragma warning disable RS0030 // Do not used banned APIs /// <summary> /// Creates a copy of this <see cref="CompletionList"/> with the <see cref="Items"/> property changed. /// </summary> public CompletionList WithItems(ImmutableArray<CompletionItem> items) #pragma warning restore RS0030 // Do not used banned APIs => With(itemsList: items); /// <summary> /// Creates a copy of this <see cref="CompletionList"/> with the <see cref="ItemsList"/> property changed. /// </summary> internal CompletionList WithItemsList(IReadOnlyList<CompletionItem> itemsList) => With(itemsList: new(itemsList)); /// <summary> /// Creates a copy of this <see cref="CompletionList"/> with the <see cref="Rules"/> property changed. /// </summary> public CompletionList WithRules(CompletionRules rules) => With(rules: rules); /// <summary> /// Creates a copy of this <see cref="CompletionList"/> with the <see cref="SuggestionModeItem"/> property changed. /// </summary> public CompletionList WithSuggestionModeItem(CompletionItem suggestionModeItem) => With(suggestionModeItem: suggestionModeItem); /// <summary> /// The default <see cref="CompletionList"/> returned when no items are found to populate the list. /// </summary> public static readonly CompletionList Empty = new( default, [], CompletionRules.Default, suggestionModeItem: null, isExclusive: false); internal bool IsEmpty => ItemsList.Count == 0 && SuggestionModeItem is null; }