Ejemplo n.º 1
0
        /// <summary>
        /// Given a symbol, finds the symbol that actually defines the name that we're using.
        /// </summary>
        public static async Task <ISymbol> FindDefinitionSymbolAsync(
            ISymbol symbol, Solution solution, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(symbol);
            Contract.ThrowIfNull(solution);

            // Make sure we're on the original source definition if we can be
            var foundSymbol = await SymbolFinder.FindSourceDefinitionAsync(
                symbol, solution, cancellationToken).ConfigureAwait(false);

            var bestSymbol = foundSymbol ?? symbol;

            symbol = bestSymbol;

            // If we're renaming a property, it might be a synthesized property for a method
            // backing field.
            if (symbol.Kind == SymbolKind.Parameter)
            {
                if (symbol.ContainingSymbol.Kind == SymbolKind.Method)
                {
                    var containingMethod = (IMethodSymbol)symbol.ContainingSymbol;
                    if (containingMethod.AssociatedSymbol is IPropertySymbol)
                    {
                        var associatedPropertyOrEvent = (IPropertySymbol)containingMethod.AssociatedSymbol;
                        var ordinal = containingMethod.Parameters.IndexOf((IParameterSymbol)symbol);
                        if (ordinal < associatedPropertyOrEvent.Parameters.Length)
                        {
                            return(associatedPropertyOrEvent.Parameters[ordinal]);
                        }
                    }
                }
            }

            // if we are renaming a compiler generated delegate for an event, cascade to the event
            if (symbol.Kind == SymbolKind.NamedType)
            {
                var typeSymbol = (INamedTypeSymbol)symbol;
                if (typeSymbol.IsImplicitlyDeclared && typeSymbol.IsDelegateType() && typeSymbol.AssociatedSymbol != null)
                {
                    return(typeSymbol.AssociatedSymbol);
                }
            }

            // If we are renaming a constructor or destructor, we wish to rename the whole type
            if (symbol.Kind == SymbolKind.Method)
            {
                var methodSymbol = (IMethodSymbol)symbol;
                if (methodSymbol.MethodKind is MethodKind.Constructor or
                    MethodKind.StaticConstructor or
                    MethodKind.Destructor)
                {
                    return(methodSymbol.ContainingType);
                }
            }

            // If we are renaming a backing field for a property, cascade to the property
            if (symbol.Kind == SymbolKind.Field)
            {
                var fieldSymbol = (IFieldSymbol)symbol;
                if (fieldSymbol.IsImplicitlyDeclared &&
                    fieldSymbol.AssociatedSymbol.IsKind(SymbolKind.Property))
                {
                    return(fieldSymbol.AssociatedSymbol);
                }
            }

            // in case this is e.g. an overridden property accessor, we'll treat the property itself as the definition symbol
            var property = await RenameUtilities.TryGetPropertyFromAccessorOrAnOverrideAsync(bestSymbol, solution, cancellationToken).ConfigureAwait(false);

            return(property ?? bestSymbol);
        }