| File: SignatureHelp\SignatureHelpItems.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.Diagnostics; using System.Linq; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.SignatureHelp; internal sealed class SignatureHelpItems { /// <summary> /// The list of items to present to the user. /// </summary> public IList<SignatureHelpItem> Items { get; } /// <summary> /// The span this session applies to. /// /// Navigation outside this span will cause signature help to be dismissed. /// </summary> public TextSpan ApplicableSpan { get; } /// <summary> /// Returns the specified <em>parameter</em> index that the provided position is at in the current document. This /// index may be greater than the number of actual syntactic arguments in the selected <see cref="SignatureHelpItem"/>. /// </summary> /// <remarks> /// This relates to the original semantic symbol that was used to create a particular item. In other words, /// it may be using /// </remarks> public int SemanticParameterIndex { get; } /// <summary> /// Returns the total number of arguments that have been typed in the current document. This may be /// greater than the ArgumentIndex if there are additional arguments after the provided position. /// </summary> public int SyntacticArgumentCount { get; } /// <summary> /// Returns the name of specified argument at the current position in the document. /// This only applies to languages that allow the user to provide named arguments. /// If no named argument exists at the current position, then null should be returned. /// /// This value is used to determine which documentation comment should be provided for the current /// parameter. Normally this is determined simply by determining the parameter by index. /// </summary> public string? ArgumentName { get; } /// <summary> /// The item to select by default. If this is <see langword="null"/> then the controller will /// pick the first item that has enough arguments to be viable based on what argument /// position the user is currently inside of. /// </summary> public int? SelectedItemIndex { get; } public SignatureHelpItems( IList<SignatureHelpItem> items, TextSpan applicableSpan, int semanticParameterIndex, int syntacticArgumentCount, string? argumentName, int? selectedItem = null) { Contract.ThrowIfNull(items); Contract.ThrowIfTrue(items.IsEmpty()); Contract.ThrowIfTrue(selectedItem.HasValue && selectedItem.Value >= items.Count); if (semanticParameterIndex < 0) throw new ArgumentException($"{nameof(semanticParameterIndex)} < 0. {semanticParameterIndex} < 0", nameof(semanticParameterIndex)); // Adjust the `selectedItem` index if duplicates are able to be removed. var distinctItems = items.Distinct().ToList(); if (selectedItem.HasValue && items.Count != distinctItems.Count) { // `selectedItem` index has already been determined to be valid, it now needs to be adjusted to point // to the equivalent item in the reduced list to account for duplicates being removed // E.g., // items = {A, A, B, B, C, D} // selectedItem = 4 (index for item C) // ergo // distinctItems = {A, B, C, D} // actualItem = C // selectedItem = 2 (index for item C) var actualItem = items[selectedItem.Value]; selectedItem = distinctItems.IndexOf(actualItem); Debug.Assert(selectedItem.Value >= 0, "actual item was not part of the final list"); } Items = distinctItems; ApplicableSpan = applicableSpan; SemanticParameterIndex = semanticParameterIndex; SyntacticArgumentCount = syntacticArgumentCount; SelectedItemIndex = selectedItem; ArgumentName = argumentName; } }