| File: FindSymbols\FindReferences\Finders\ImplicitConstructorInitializerSymbolReferenceFinder.cs | Web Access |
| Project: src\roslyn\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces) |
// 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.Linq; using System.Threading; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.FindSymbols.Finders; /// <summary> /// For finding references to implicit constructor initializers (i.e. the implicit "base()" call when non is /// explicitly supplied). /// </summary> internal sealed class ImplicitConstructorInitializerSymbolReferenceFinder : ExplicitOrImplicitConstructorInitializerSymbolReferenceFinder { public static readonly ImplicitConstructorInitializerSymbolReferenceFinder Instance = new(); private ImplicitConstructorInitializerSymbolReferenceFinder() { } /// <summary> /// Only use this finder if the constructor is one that can be called without parameters (and thus a base class /// could be calling it implicitly). /// </summary> protected override bool CanFind(IMethodSymbol symbol) => base.CanFind(symbol) && symbol.Parameters.All(p => p.IsOptional || p.IsParams); protected override bool CheckIndex(Document document, string name, SyntaxTreeIndex index) { if (index.ContainsImplicitBaseConstructorInitializer) { // if we have `partial class C { public C() { } }` we have to assume it might be a match, as the base // type reference might be in a another part of the partial in another file. if (index.ContainsPartialClass) return true; // Otherwise, if it doesn't have any partial types, ensure that the base type name is referenced in the // same file. e.g. `class C : B { public C() { } }`. This allows us to greatly filter down the // number of matches, presuming that most inheriting types in a project are not themselves partial. if (index.ProbablyContainsIdentifier(name)) return true; } return false; } protected sealed override void FindReferencesInDocument<TData>( IMethodSymbol methodSymbol, FindReferencesDocumentState state, Action<FinderLocation, TData> processResult, TData processResultData, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var syntaxFacts = state.SyntaxFacts; var constructorNodes = state.Cache.GetConstructorDeclarations(cancellationToken); foreach (var constructorNode in constructorNodes) { if (!syntaxFacts.HasImplicitBaseConstructorInitializer(constructorNode)) continue; // Looks like a suitable match. A constructor with an implicit base constructor initializer. See if the // constructor's base type is the type that contains the constructor we're looking for. if (state.SemanticModel.GetDeclaredSymbol(constructorNode, cancellationToken) is IMethodSymbol constructor && SymbolFinder.OriginalSymbolsMatch(state.Solution, methodSymbol.ContainingType, constructor.ContainingType.BaseType)) { processResult(new(constructorNode, new( state.Document, alias: null, constructor.Locations.First(loc => loc.SourceTree == constructorNode.SyntaxTree && constructorNode.Span.IntersectsWith(loc.SourceSpan)), isImplicit: true, new(valueUsageInfoOpt: null, TypeOrNamespaceUsageInfo.ObjectCreation), additionalProperties: [], CandidateReason.None)), processResultData); } } } }