| File: Completion\Providers\AbstractOverrideCompletionProvider.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.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Text; namespace Microsoft.CodeAnalysis.Completion.Providers; internal abstract partial class AbstractOverrideCompletionProvider() : AbstractMemberInsertingCompletionProvider { public abstract SyntaxToken FindStartingToken(SyntaxTree tree, int position, CancellationToken cancellationToken); public abstract ImmutableArray<ISymbol> FilterOverrides(ImmutableArray<ISymbol> members, ITypeSymbol? returnType); public abstract bool TryDetermineModifiers(SyntaxToken startToken, SourceText text, int startLine, out Accessibility seenAccessibility, out DeclarationModifiers modifiers); public override async Task ProvideCompletionsAsync(CompletionContext context) { var state = await ItemGetter.CreateAsync(this, context.Document, context.Position, context.CancellationToken).ConfigureAwait(false); var items = await state.GetItemsAsync().ConfigureAwait(false); if (!items.IsDefaultOrEmpty) { context.IsExclusive = true; context.AddItems(items); } } protected override Task<ISymbol> GenerateMemberAsync( Document document, CompletionItem completionItem, Compilation compilation, ISymbol overriddenMember, INamedTypeSymbol containingType, CancellationToken cancellationToken) { // Special case: if you are overriding object.ToString(), we will make the return value as non-nullable. The // return was made nullable because are implementations out there that will return null, but that's not // something we really want new implementations doing. We may need to consider expanding this behavior to other // methods in the future; if that is the case then we would want there to be an attribute on the return type // rather than updating this list, but for now there is no such attribute until we find more cases for it. See // https://github.com/dotnet/roslyn/issues/30317 for some additional conversation about this design decision. // // We don't check if methodSymbol.ContainingType is object, in case you're overriding something that is itself an override if (overriddenMember is IMethodSymbol methodSymbol && methodSymbol.Name == "ToString" && methodSymbol.Parameters.Length == 0) { overriddenMember = CodeGenerationSymbolFactory.CreateMethodSymbol(methodSymbol, returnType: methodSymbol.ReturnType.WithNullableAnnotation(NullableAnnotation.NotAnnotated)); } // Figure out what to insert, and do it. Throw if we've somehow managed to get this far and can't. var syntaxFactory = document.GetRequiredLanguageService<SyntaxGenerator>(); var itemModifiers = MemberInsertionCompletionItem.GetModifiers(completionItem); var modifiers = itemModifiers.WithIsUnsafe(itemModifiers.IsUnsafe | overriddenMember.RequiresUnsafeModifier()); return syntaxFactory.OverrideAsync( overriddenMember, containingType, document, modifiers, cancellationToken); } public abstract bool TryDetermineReturnType( SyntaxToken startToken, SemanticModel semanticModel, CancellationToken cancellationToken, out ITypeSymbol? returnType, out SyntaxToken nextToken); protected static bool IsOnStartLine(int position, SourceText text, int startLine) => text.Lines.IndexOf(position) == startLine; protected static ITypeSymbol GetReturnType(ISymbol symbol) => symbol.Kind switch { SymbolKind.Event => ((IEventSymbol)symbol).Type, SymbolKind.Method => ((IMethodSymbol)symbol).ReturnType, SymbolKind.Property => ((IPropertySymbol)symbol).Type, _ => throw ExceptionUtilities.UnexpectedValue(symbol.Kind), }; }