| File: Completion\Providers\AbstractObjectCreationCompletionProvider.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.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Completion.Providers; internal abstract class AbstractObjectCreationCompletionProvider<TSyntaxContext> : AbstractSymbolCompletionProvider<TSyntaxContext> where TSyntaxContext : SyntaxContext { /// <summary> /// Return null if not in object creation type context. /// </summary> protected abstract SyntaxNode? GetObjectCreationNewExpression(SyntaxTree tree, int position, CancellationToken cancellationToken); protected abstract CompletionItemRules GetCompletionItemRules(ImmutableArray<SymbolAndSelectionInfo> symbols); protected override CompletionItem CreateItem( CompletionContext completionContext, string displayText, string displayTextSuffix, string insertionText, ImmutableArray<SymbolAndSelectionInfo> symbols, TSyntaxContext context, SupportedPlatformData? supportedPlatformData) { return SymbolCompletionItem.CreateWithSymbolId( displayText: displayText, displayTextSuffix: displayTextSuffix, symbols: symbols.SelectAsArray(t => t.Symbol), // Always preselect rules: GetCompletionItemRules(symbols).WithMatchPriority(MatchPriority.Preselect), contextPosition: context.Position, insertionText: insertionText, filterText: GetFilterTextDefault(symbols[0].Symbol, displayText, context), supportedPlatforms: supportedPlatformData); } protected override Task<ImmutableArray<SymbolAndSelectionInfo>> GetSymbolsAsync( CompletionContext? completionContext, TSyntaxContext context, int position, CompletionOptions options, CancellationToken cancellationToken) { var newExpression = GetObjectCreationNewExpression(context.SyntaxTree, position, cancellationToken); if (newExpression == null) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); var typeInferenceService = context.GetRequiredLanguageService<ITypeInferenceService>(); var type = typeInferenceService.InferType( context.SemanticModel, position, objectAsDefault: false, cancellationToken: cancellationToken); // Unwrap an array type fully. We only want to offer the underlying element type in the // list of completion items. var isArray = type is IArrayTypeSymbol; while (type is IArrayTypeSymbol arrayType) type = arrayType.ElementType; if (type == null) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); // Unwrap nullable if (type.OriginalDefinition.SpecialType == SpecialType.System_Nullable_T) type = type.GetTypeArguments().Single(); if (type.SpecialType == SpecialType.System_Void) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); if (type.ContainsAnonymousType()) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); if (!type.CanBeReferencedByName) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); // Normally the user can't say things like "new IList". Except for "IList[] x = new |". // In this case we do want to allow them to preselect certain types in the completion // list even if they can't new them directly. if (!isArray) { if (type.TypeKind is TypeKind.Interface or TypeKind.Pointer or TypeKind.Dynamic || type.IsAbstract) { return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); } if (type is ITypeParameterSymbol typeParameter && !typeParameter.HasConstructorConstraint) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); } if (!type.IsEditorBrowsable(options.MemberDisplayOptions.HideAdvancedMembers, context.SemanticModel.Compilation)) return SpecializedTasks.EmptyImmutableArray<SymbolAndSelectionInfo>(); // In the case of array creation, we don't offer a preselected/hard-selected item because // the user may want an implicitly-typed array creation return Task.FromResult(ImmutableArray.Create(new SymbolAndSelectionInfo(Symbol: type, Preselect: !isArray))); } }