private bool?HasConflict(IEnumerable <ISymbol> symbols, IPropertySymbol property, Compilation compilation, CancellationToken cancellationToken)
        {
            // We're asking the rename API to update a bunch of references to an existing field to
            // the same name as an existing property.  Rename will often flag this situation as
            // an unresolvable conflict because the new name won't bind to the field anymore.
            //
            // To address this, we let rename know that there is no conflict if the new symbol it
            // resolves to is the same as the property we're trying to get the references pointing
            // to.

            foreach (var symbol in symbols)
            {
                if (symbol is IPropertySymbol otherProperty)
                {
                    var mappedProperty = otherProperty.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol as IPropertySymbol;
                    if (property.Equals(mappedProperty))
                    {
                        // No conflict.
                        return(false);
                    }
                }
            }

            // Just do the default check.
            return(null);
        }
        internal bool IsValidAutoProperty(SyntaxNode property, IPropertySymbol propertySymbol)
        {
            var fields = propertySymbol.ContainingType.GetMembers().OfType <IFieldSymbol>();
            var field  = fields.FirstOrDefault(f => propertySymbol.Equals(f.AssociatedSymbol));

            return(field != null);
        }
예제 #3
0
        private static IFieldSymbol GetBackingField(IPropertySymbol property)
        {
            var field = property.ContainingType.GetMembers()
                        .OfType <IFieldSymbol>()
                        .FirstOrDefault(f => property.Equals(f.AssociatedSymbol));

            if (field == null)
            {
                return(null);
            }

            // If the field is something can be referenced with the name it has, then just use
            // it as the backing field we'll generate.  This is the case in VB where the backing
            // field can be referenced as is.
            if (field.CanBeReferencedByName)
            {
                return(field);
            }

            // Otherwise, generate a good name for the backing field we're generating.  This is
            // the case for C# where we have mangled names for the backing field and need something
            // actually usable in code.
            var uniqueName = NameGenerator.GenerateUniqueName(
                property.Name.ToCamelCase(),
                n => !property.ContainingType.GetMembers(n).Any());

            return(CodeGenerationSymbolFactory.CreateFieldSymbol(
                       attributes: null,
                       accessibility: field.DeclaredAccessibility,
                       modifiers: DeclarationModifiers.From(field),
                       type: field.Type,
                       name: uniqueName));
        }
        private static bool IsDefaultGetProperty(IPropertySymbol propertySymbol)
        {
            // we need to search through all backing fields of the parent class
            var parentSymbol        = propertySymbol.ContainingType;
            var hasAutoBackingField = parentSymbol.GetMembers().OfType <IFieldSymbol>().Any(symbol => propertySymbol.Equals(symbol.AssociatedSymbol));
            var isImplementedMember = parentSymbol.AllInterfaces
                                      .SelectMany(iface => iface.GetMembers(propertySymbol.Name))
                                      .Any(ifaceMember => propertySymbol.Equals(parentSymbol.FindImplementationForInterfaceMember(ifaceMember)));

            var hasExplicitGetter = GetterHasExplicitBodyOrInitializer(propertySymbol);

            return(hasAutoBackingField && isImplementedMember && !hasExplicitGetter);
        }
예제 #5
0
        public static IEnumerable <IPropertySymbol> ImplementedInterfaceMembers(this IPropertySymbol @this)
        {
            if (@this == null)
            {
                throw new ArgumentNullException(nameof(@this));
            }

            return(@this
                   .ContainingType
                   .AllInterfaces
                   .SelectMany(i => i.GetMembers()
                               .OfType <IPropertySymbol>())
                   .Where(m => @this.Equals(
                              @this.ContainingType.FindImplementationForInterfaceMember(m))));
        }
            private bool PropertiesAreEquivalent(IPropertySymbol x, IPropertySymbol y, Dictionary <INamedTypeSymbol, INamedTypeSymbol> equivalentTypesWithDifferingAssemblies)
            {
                if (x.ContainingType.IsAnonymousType && y.ContainingType.IsAnonymousType)
                {
                    // We can short circuit here and just use the symbols themselves to determine
                    // equality.  This will properly handle things like the VB case where two
                    // anonymous types will be considered the same if they have properties that
                    // differ in casing.
                    if (x.Equals(y))
                    {
                        return(true);
                    }
                }

                return
                    (x.IsIndexer == y.IsIndexer &&
                     x.MetadataName == y.MetadataName &&
                     x.Parameters.Length == y.Parameters.Length &&
                     ParametersAreEquivalent(x.Parameters, y.Parameters, equivalentTypesWithDifferingAssemblies) &&
                     AreEquivalent(x.ContainingSymbol, y.ContainingSymbol, equivalentTypesWithDifferingAssemblies));
            }
        public static bool Overrides([NotNull] this IPropertySymbol propertySymbol, [NotNull] IPropertySymbol overriddenProperty)
        {
            Requires.NotNull(propertySymbol, nameof(propertySymbol));
            Requires.NotNull(overriddenProperty, nameof(overriddenProperty));

            if (propertySymbol.Equals(overriddenProperty))
            {
                return(true);
            }

            if (!propertySymbol.IsOverride)
            {
                return(false);
            }

            if (propertySymbol.OverriddenProperty.Equals(overriddenProperty))
            {
                return(true);
            }

            return(propertySymbol.OverriddenProperty.Overrides(overriddenProperty));
        }
예제 #8
0
        internal static bool IsFixable(
            IndexerDeclarationSyntax indexerDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.ElementAccessExpression) != true)
                {
                    return(false);
                }

                var elementAccess = (ElementAccessExpressionSyntax)expression;

                if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (elementAccess.ArgumentList == null)
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

                IPropertySymbol overriddenProperty = propertySymbol?.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken);

                return(overriddenProperty.Equals(symbol) &&
                       CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) &&
                       CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters));
            }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.SimpleAssignmentExpression) != true)
                {
                    return(false);
                }

                var assignment = (AssignmentExpressionSyntax)expression;

                ExpressionSyntax left = assignment.Left;

                if (left?.IsKind(SyntaxKind.ElementAccessExpression) != true)
                {
                    return(false);
                }

                var elementAccess = (ElementAccessExpressionSyntax)left;

                if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                if (elementAccess.ArgumentList == null)
                {
                    return(false);
                }

                ExpressionSyntax right = assignment.Right;

                if (right?.IsKind(SyntaxKind.IdentifierName) != true)
                {
                    return(false);
                }

                var identifierName = (IdentifierNameSyntax)right;

                if (identifierName.Identifier.ValueText != "value")
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

                IPropertySymbol overriddenProperty = propertySymbol?.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken);

                return(overriddenProperty.Equals(symbol) &&
                       CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) &&
                       CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters));
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                Debug.Fail(accessor.Kind().ToString());
                return(false);
            }
            }
        }
예제 #9
0
        internal static bool IsFixable(
            PropertyDeclarationSyntax propertyDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true)
                {
                    return(false);
                }

                var memberAccess = (MemberAccessExpressionSyntax)expression;

                if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                SimpleNameSyntax simpleName = memberAccess.Name;

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

                IPropertySymbol overriddenProperty = propertySymbol?.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken);

                return(overriddenProperty.Equals(symbol));
            }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.SimpleAssignmentExpression) != true)
                {
                    return(false);
                }

                var assignment = (AssignmentExpressionSyntax)expression;

                ExpressionSyntax left = assignment.Left;

                if (left?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true)
                {
                    return(false);
                }

                var memberAccess = (MemberAccessExpressionSyntax)left;

                if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true)
                {
                    return(false);
                }

                ExpressionSyntax right = assignment.Right;

                if (right?.IsKind(SyntaxKind.IdentifierName) != true)
                {
                    return(false);
                }

                var identifierName = (IdentifierNameSyntax)right;

                if (identifierName.Identifier.ValueText != "value")
                {
                    return(false);
                }

                SimpleNameSyntax simpleName = memberAccess.Name;

                if (simpleName == null)
                {
                    return(false);
                }

                IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

                IPropertySymbol overriddenProperty = propertySymbol?.OverriddenProperty;

                if (overriddenProperty == null)
                {
                    return(false);
                }

                ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken);

                return(overriddenProperty.Equals(symbol));
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                Debug.Fail(accessor.Kind().ToString());
                return(false);
            }
            }
        }
 public static IFieldSymbol?GetBackingFieldIfAny(this IPropertySymbol property)
 => property.ContainingType.GetMembers()
 .OfType <IFieldSymbol>()
 .FirstOrDefault(f => property.Equals(f.AssociatedSymbol));
예제 #11
0
        private static bool IsAutoGetterPropertyAssigned(SymbolAnalysisContext context, IPropertySymbol property)
        {
            Debug.Assert(!property.IsImplicitlyDeclared);
            var propertySyntax = (PropertyDeclarationSyntax)property.DeclaringSyntaxReferences.First().GetSyntax();

            if (propertySyntax.Initializer != null)
            {
                return(true);
            }


            if (// A null accessor list indicates an expression-bodied property
                propertySyntax.AccessorList == null ||
                // If accessor body is non-null, this is a computed property, not an auto property
                propertySyntax.AccessorList.Accessors.Any(a => a.Body != null))
            {
                return(true);
            }

            // if any constructor exists which does not assign the property (including implicit constructor), return false
            foreach (var ctorSymbol in property.ContainingType.InstanceConstructors)
            {
                Debug.Assert(ctorSymbol.DeclaringSyntaxReferences.Length <= 1);
                var ctorSyntax = ctorSymbol.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as ConstructorDeclarationSyntax;
                if (ctorSyntax == null)
                {
                    // implicit constructor
                    return(false);
                }

                var bodyOpt = (SyntaxNode)ctorSyntax.Body ?? ctorSyntax.ExpressionBody;
                if (bodyOpt == null)
                {
                    // don't check extern constructors
                    continue;
                }

                if (ctorSyntax.Initializer != null && ctorSyntax.Initializer.ThisOrBaseKeyword.Kind() == SyntaxKind.ThisKeyword)
                {
                    // If the constructor calls out to another constructor in the same class, rely on the other constructor to initialize
                    // (if the other constructor doesn't initialize, we'll warn anyway)
                    return(true);
                }

                var isAssigned  = false;
                var assignments = bodyOpt.DescendantNodes().OfType <AssignmentExpressionSyntax>();
                foreach (var assignment in assignments)
                {
                    var symbol = context.Compilation.GetSemanticModel(ctorSyntax.SyntaxTree).GetSymbolInfo(assignment.Left, context.CancellationToken);
                    if (property.Equals(symbol.Symbol))
                    {
                        isAssigned = true;
                        break;
                    }
                }

                if (!isAssigned)
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #12
0
 static bool IsInterfaceImplementation(IPropertySymbol method)
 {
     return(method.ContainingType.AllInterfaces.SelectMany(@interface => @interface.GetMembers().OfType <IPropertySymbol>()).Any(interfaceMethod => method.Equals(method.ContainingType.FindImplementationForInterfaceMember(interfaceMethod))));
 }
예제 #13
0
 /// <summary>
 /// Check if a property is an auto-property.
 /// TODO: Remove this helper when https://github.com/dotnet/roslyn/issues/46682 is handled.
 /// </summary>
 public static bool IsAutoProperty(this IPropertySymbol propertySymbol)
 => propertySymbol.ContainingType.GetMembers().OfType <IFieldSymbol>().Any(f => f.IsImplicitlyDeclared && propertySymbol.Equals(f.AssociatedSymbol));
            private bool PropertiesAreEquivalent(IPropertySymbol x, IPropertySymbol y, Dictionary<INamedTypeSymbol, INamedTypeSymbol> equivalentTypesWithDifferingAssemblies)
            {
                if (x.ContainingType.IsAnonymousType && y.ContainingType.IsAnonymousType)
                {
                    // We can short circuit here and just use the symbols themselves to determine
                    // equality.  This will properly handle things like the VB case where two
                    // anonymous types will be considered the same if they have properties that
                    // differ in casing.
                    if (x.Equals(y))
                    {
                        return true;
                    }
                }

                return
                    x.IsIndexer == y.IsIndexer &&
                    x.MetadataName == y.MetadataName &&
                    x.Parameters.Length == y.Parameters.Length &&
                    ParametersAreEquivalent(x.Parameters, y.Parameters, equivalentTypesWithDifferingAssemblies) &&
                    AreEquivalent(x.ContainingSymbol, y.ContainingSymbol, equivalentTypesWithDifferingAssemblies);
            }
예제 #15
0
        internal static bool CanRefactor(
            IndexerDeclarationSyntax indexerDeclaration,
            AccessorDeclarationSyntax accessor,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            switch (accessor.Kind())
            {
            case SyntaxKind.GetAccessorDeclaration:
                {
                    ExpressionSyntax expression = GetGetAccessorExpression(accessor);

                    if (expression?.IsKind(SyntaxKind.ElementAccessExpression) == true)
                    {
                        var elementAccess = (ElementAccessExpressionSyntax)expression;

                        if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) == true &&
                            elementAccess.ArgumentList != null)
                        {
                            IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

                            if (propertySymbol != null)
                            {
                                IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

                                if (overriddenProperty != null)
                                {
                                    ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken);

                                    if (overriddenProperty.Equals(symbol))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }

                    return(false);
                }

            case SyntaxKind.SetAccessorDeclaration:
            {
                ExpressionSyntax expression = GetSetAccessorExpression(accessor);

                if (expression?.IsKind(SyntaxKind.SimpleAssignmentExpression) == true)
                {
                    var assignment = (AssignmentExpressionSyntax)expression;

                    ExpressionSyntax left = assignment.Left;

                    if (left?.IsKind(SyntaxKind.ElementAccessExpression) == true)
                    {
                        var elementAccess = (ElementAccessExpressionSyntax)left;

                        if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) == true &&
                            elementAccess.ArgumentList != null)
                        {
                            ExpressionSyntax right = assignment.Right;

                            if (right?.IsKind(SyntaxKind.IdentifierName) == true)
                            {
                                var identifierName = (IdentifierNameSyntax)right;

                                if (identifierName.Identifier.ValueText == "value")
                                {
                                    IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken);

                                    if (propertySymbol != null)
                                    {
                                        IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty;

                                        if (overriddenProperty != null)
                                        {
                                            ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken);

                                            if (overriddenProperty.Equals(symbol))
                                            {
                                                return(true);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                return(false);
            }

            case SyntaxKind.UnknownAccessorDeclaration:
            {
                return(false);
            }

            default:
            {
                Debug.Assert(false, accessor.Kind().ToString());
                return(false);
            }
            }
        }