/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Features/CSharp/Portable/SignatureHelp/ConstructorInitializerSignatureHelpProvider.cs
152 строки
7 KB
Cyrus Najmabadi
Merge remote-tracking branch 'upstream/features/collection-expression-arguments' into portIDEFeatures2
12 дек 2025, 14:45
12 дек 2025, 14:45
8598aea
Код
Авторство
О чём код?
// 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.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.DocumentationComments; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.SignatureHelp; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp; [ExportSignatureHelpProvider("ConstructorInitializerSignatureHelpProvider", LanguageNames.CSharp), Shared] internal sealed partial class ConstructorInitializerSignatureHelpProvider : AbstractCSharpSignatureHelpProvider { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] public ConstructorInitializerSignatureHelpProvider() { } public override ImmutableArray<char> TriggerCharacters => ['(', ',']; public override ImmutableArray<char> RetriggerCharacters => [')']; private async Task<ConstructorInitializerSyntax?> TryGetConstructorInitializerAsync( Document document, int position, SignatureHelpTriggerReason triggerReason, CancellationToken cancellationToken) { var initializer = await CommonSignatureHelpUtilities.TryGetSyntaxAsync<ConstructorInitializerSyntax>( document, position, triggerReason, IsTriggerToken, IsArgumentListToken, cancellationToken).ConfigureAwait(false); return initializer?.ArgumentList is null ? null : initializer; } private bool IsTriggerToken(SyntaxToken token) => SignatureHelpUtilities.IsTriggerParenOrComma<ConstructorInitializerSyntax>(token, TriggerCharacters); private static bool IsArgumentListToken(ConstructorInitializerSyntax expression, SyntaxToken token) { return expression.ArgumentList != null && expression.ArgumentList.Span.Contains(token.SpanStart) && token != expression.ArgumentList.CloseParenToken; } protected override async Task<SignatureHelpItems?> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, MemberDisplayOptions options, CancellationToken cancellationToken) { var constructorInitializer = await TryGetConstructorInitializerAsync( document, position, triggerInfo.TriggerReason, cancellationToken).ConfigureAwait(false); if (constructorInitializer == null) return null; var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var within = semanticModel.GetEnclosingNamedType(position, cancellationToken); if (within == null) return null; if (within.TypeKind is not TypeKind.Struct and not TypeKind.Class) return null; var type = constructorInitializer.Kind() == SyntaxKind.BaseConstructorInitializer ? within.BaseType : within; if (type == null) return null; // get the candidate methods var currentConstructor = semanticModel.GetDeclaredSymbol(constructorInitializer.Parent!, cancellationToken); var constructors = type.InstanceConstructors .WhereAsArray(c => c.IsAccessibleWithin(within) && !c.Equals(currentConstructor)) .WhereAsArray(c => c.IsEditorBrowsable(options.HideAdvancedMembers, semanticModel.Compilation)) .Sort(semanticModel, constructorInitializer.SpanStart); if (!constructors.Any()) return null; var (currentSymbol, parameterIndexOverride) = new CSharpLightweightOverloadResolution(semanticModel, constructorInitializer.ArgumentList.Arguments, position) .RefineOverloadAndPickParameter(semanticModel.GetSymbolInfo(constructorInitializer, cancellationToken), constructors); // present items and select var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(constructorInitializer.ArgumentList); var structuralTypeDisplayService = document.GetRequiredLanguageService<IStructuralTypeDisplayService>(); var documentationCommentFormattingService = document.GetRequiredLanguageService<IDocumentationCommentFormattingService>(); var items = constructors.SelectAsArray(m => Convert(m, constructorInitializer.ArgumentList.OpenParenToken, semanticModel, structuralTypeDisplayService, documentationCommentFormattingService)); var selectedItem = TryGetSelectedIndex(constructors, currentSymbol); var argumentState = await GetCurrentArgumentStateAsync( document, position, textSpan, cancellationToken).ConfigureAwait(false); return CreateSignatureHelpItems(items, textSpan, argumentState, selectedItem, parameterIndexOverride); } private async Task<SignatureHelpState?> GetCurrentArgumentStateAsync( Document document, int position, TextSpan currentSpan, CancellationToken cancellationToken) { var initializer = await TryGetConstructorInitializerAsync( document, position, SignatureHelpTriggerReason.InvokeSignatureHelpCommand, cancellationToken).ConfigureAwait(false); if (initializer is { ArgumentList: not null } && currentSpan.Start == SignatureHelpUtilities.GetSignatureHelpSpan(initializer.ArgumentList).Start) { return SignatureHelpUtilities.GetSignatureHelpState(initializer.ArgumentList, position); } return null; } private static SignatureHelpItem Convert( IMethodSymbol constructor, SyntaxToken openToken, SemanticModel semanticModel, IStructuralTypeDisplayService structuralTypeDisplayService, IDocumentationCommentFormattingService documentationCommentFormattingService) { var position = openToken.SpanStart; var item = CreateItem( constructor, semanticModel, position, structuralTypeDisplayService, constructor.IsParams(), constructor.GetDocumentationPartsFactory(semanticModel, position, documentationCommentFormattingService), GetPreambleParts(constructor, semanticModel, position), GetSeparatorParts(), GetPostambleParts(), [.. constructor.Parameters.Select(p => Convert(p, semanticModel, position, documentationCommentFormattingService))]); return item; } private static IList<SymbolDisplayPart> GetPreambleParts( IMethodSymbol method, SemanticModel semanticModel, int position) { return [.. method.ContainingType.ToMinimalDisplayParts(semanticModel, position), Punctuation(SyntaxKind.OpenParenToken)]; } private static IList<SymbolDisplayPart> GetPostambleParts() => [Punctuation(SyntaxKind.CloseParenToken)]; }