private static void AddMemberAccessExpressionTerms(MemberAccessExpressionSyntax memberAccessExpression, IList <string> terms, ref ExpressionType expressionType)
        {
            var flags = ExpressionType.Invalid;

            // These operators always have a RHS of a name node, which we know would
            // "claim" to be a valid term, but is not valid without the LHS present.
            // So, we don't bother collecting anything from the RHS...
            AddSubExpressionTerms(memberAccessExpression.Expression, terms, ref flags);

            // If the LHS says it's a valid term, then we add it ONLY if our PARENT
            // is NOT another dot/arrow.  This allows the expression 'a.b.c.d' to
            // add both 'a.b.c.d' and 'a.b.c', but not 'a.b' and 'a'.
            if (IsValidTerm(flags) &&
                !memberAccessExpression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) &&
                !memberAccessExpression.IsParentKind(SyntaxKind.PointerMemberAccessExpression))
            {
                terms.Add(ConvertToString(memberAccessExpression.Expression));
            }

            // And this expression itself is a valid term if the LHS is a valid
            // expression, and its PARENT is not an invocation.
            if (IsValidExpression(flags) &&
                !memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression))
            {
                expressionType = ExpressionType.ValidTerm;
            }
            else
            {
                expressionType = ExpressionType.ValidExpression;
            }
        }
        public static bool CanRefactor(
            MemberAccessExpressionSyntax memberAccess,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (memberAccess == null)
            {
                throw new ArgumentNullException(nameof(memberAccess));
            }

            if (semanticModel == null)
            {
                throw new ArgumentNullException(nameof(semanticModel));
            }

            if (!memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) &&
                memberAccess.Expression != null &&
                memberAccess.Name?.Identifier.ValueText == "Empty")
            {
                var fieldSymbol = semanticModel.GetSymbol(memberAccess.Name, cancellationToken) as IFieldSymbol;

                return(fieldSymbol != null &&
                       fieldSymbol.IsPublic() &&
                       fieldSymbol.IsReadOnly &&
                       fieldSymbol.IsStatic &&
                       fieldSymbol.ContainingType?.IsString() == true);
            }

            return(false);
        }
        public static bool IsFixable(
            MemberAccessExpressionSyntax memberAccess,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default)
        {
            if (memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                return(false);
            }

            if (memberAccess.Expression == null)
            {
                return(false);
            }

            if (memberAccess.Name?.Identifier.ValueText != "Empty")
            {
                return(false);
            }

            var fieldSymbol = semanticModel.GetSymbol(memberAccess.Name, cancellationToken) as IFieldSymbol;

            return(SymbolUtility.IsPublicStaticReadOnly(fieldSymbol) &&
                   fieldSymbol.ContainingType?.SpecialType == SpecialType.System_String);
        }
        private static void AnalyzePredefinedType(
            SyntaxNodeAnalysisContext context,
            MemberAccessExpressionSyntax memberAccess)
        {
            if (!memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                ExpressionSyntax expression = memberAccess.Expression;

                if (expression?.IsKind(
                        SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxKind.IdentifierName) == true)
                {
                    var namedTypeSymbol = context.SemanticModel
                                          .GetSymbolInfo(expression, context.CancellationToken)
                                          .Symbol as INamedTypeSymbol;

                    if (namedTypeSymbol?.SupportsPredefinedType() == true)
                    {
                        IAliasSymbol aliasSymbol = context.SemanticModel.GetAliasInfo(expression, context.CancellationToken);

                        if (aliasSymbol == null)
                        {
                            context.ReportDiagnostic(
                                DiagnosticDescriptors.UsePredefinedType,
                                expression.GetLocation());
                        }
                    }
                }
            }
        }
コード例 #5
0
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberAccessExpressionSyntax memberAccess)
        {
            if (memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                return;
            }

            ExpressionSyntax expression = memberAccess.Expression;

            if (expression == null)
            {
                return;
            }

            SyntaxKind kind = expression.Kind();

            if (kind == SyntaxKind.IdentifierName)
            {
                if (!SupportsPredefinedType((IdentifierNameSyntax)expression))
                {
                    return;
                }
            }
            else if (kind == SyntaxKind.SimpleMemberAccessExpression)
            {
                memberAccess = (MemberAccessExpressionSyntax)expression;

                if (!(memberAccess.Name is IdentifierNameSyntax identifierName))
                {
                    return;
                }

                if (!SupportsPredefinedType(identifierName))
                {
                    return;
                }
            }
            else
            {
                return;
            }

            var typeSymbol = context.SemanticModel.GetSymbol(expression, context.CancellationToken) as ITypeSymbol;

            if (typeSymbol?.SupportsPredefinedType() != true)
            {
                return;
            }

            IAliasSymbol aliasSymbol = context.SemanticModel.GetAliasInfo(expression, context.CancellationToken);

            if (aliasSymbol != null)
            {
                return;
            }

            ReportDiagnostic(context, expression);
        }
コード例 #6
0
        private static MemberAccessExpressionSyntax GetTopmostMemberAccessExpression(MemberAccessExpressionSyntax memberAccess)
        {
            while (memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                memberAccess = (MemberAccessExpressionSyntax)memberAccess.Parent;
            }

            return(memberAccess);
        }
コード例 #7
0
        public static void Analyze(SyntaxNodeAnalysisContext context, MemberAccessExpressionSyntax memberAccess)
        {
            if (!memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
            {
                ExpressionSyntax expression = memberAccess.Expression;

                if (expression?.IsKind(
                        SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxKind.IdentifierName) == true)
                {
                    var typeSymbol = context.SemanticModel.GetSymbol(expression, context.CancellationToken) as ITypeSymbol;

                    if (typeSymbol?.SupportsPredefinedType() == true)
                    {
                        IAliasSymbol aliasSymbol = context.SemanticModel.GetAliasInfo(expression, context.CancellationToken);

                        if (aliasSymbol == null)
                        {
                            ReportDiagnostic(context, expression);
                        }
                    }
                }
            }
        }
コード例 #8
0
            private IEnumerable<TypeInferenceInfo> InferTypeForExpressionOfMemberAccessExpression(
                MemberAccessExpressionSyntax memberAccessExpression)
            {
                // If we're on the left side of a dot, it's possible in a few cases
                // to figure out what type we should be.  Specifically, if we have
                //
                //      await foo.ConfigureAwait()
                //
                // then we can figure out what 'foo' should be based on teh await
                // context.
                var name = memberAccessExpression.Name.Identifier.Value;
                if (name.Equals(nameof(Task<int>.ConfigureAwait)) &&
                    memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
                    memberAccessExpression.Parent.IsParentKind(SyntaxKind.AwaitExpression))
                {
                    return InferTypes((ExpressionSyntax)memberAccessExpression.Parent);
                }
                else if (name.Equals(nameof(Task<int>.ContinueWith)))
                {
                    // foo.ContinueWith(...)
                    // We want to infer Task<T>.  For now, we'll just do Task<object>,
                    // in the future it would be nice to figure out the actual result
                    // type based on the argument to ContinueWith.
                    var taskOfT = this.Compilation.TaskOfTType();
                    if (taskOfT != null)
                    {
                        return SpecializedCollections.SingletonEnumerable(
                            new TypeInferenceInfo(taskOfT.Construct(this.Compilation.ObjectType)));
                    }
                }
                else if (name.Equals(nameof(Enumerable.Select)) ||
                         name.Equals(nameof(Enumerable.Where)))
                {
                    var ienumerableType = this.Compilation.IEnumerableOfTType();

                    // foo.Select
                    // We want to infer IEnumerable<T>.  We can try to figure out what 
                    // T if we get a delegate as the first argument to Select/Where.
                    if (ienumerableType != null && memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression))
                    {
                        var invocation = (InvocationExpressionSyntax)memberAccessExpression.Parent;
                        if (invocation.ArgumentList.Arguments.Count > 0)
                        {
                            var argumentExpression = invocation.ArgumentList.Arguments[0].Expression;

                            if (argumentExpression != null)
                            {
                                var argumentTypes = GetTypes(argumentExpression);
                                var delegateType = argumentTypes.FirstOrDefault().InferredType.GetDelegateType(this.Compilation);
                                var typeArg = delegateType?.TypeArguments.Length > 0
                                    ? delegateType.TypeArguments[0]
                                    : this.Compilation.ObjectType;

                                if (IsUnusableType(typeArg) && argumentExpression is LambdaExpressionSyntax)
                                {
                                    typeArg = InferTypeForFirstParameterOfLambda((LambdaExpressionSyntax)argumentExpression) ??
                                        this.Compilation.ObjectType;
                                }

                                return SpecializedCollections.SingletonEnumerable(
                                    new TypeInferenceInfo(ienumerableType.Construct(typeArg)));
                            }
                        }
                    }
                }

                return SpecializedCollections.EmptyEnumerable<TypeInferenceInfo>();
            }
        private static void AddMemberAccessExpressionTerms(MemberAccessExpressionSyntax memberAccessExpression, IList<string> terms, ref ExpressionType expressionType)
        {
            var flags = ExpressionType.Invalid;

            // These operators always have a RHS of a name node, which we know would
            // "claim" to be a valid term, but is not valid without the LHS present.
            // So, we don't bother collecting anything from the RHS...
            AddSubExpressionTerms(memberAccessExpression.Expression, terms, ref flags);

            // If the LHS says it's a valid term, then we add it ONLY if our PARENT
            // is NOT another dot/arrow.  This allows the expression 'a.b.c.d' to
            // add both 'a.b.c.d' and 'a.b.c', but not 'a.b' and 'a'.
            if (IsValidTerm(flags) &&
                !memberAccessExpression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) &&
                !memberAccessExpression.IsParentKind(SyntaxKind.PointerMemberAccessExpression))
            {
                terms.Add(ConvertToString(memberAccessExpression.Expression));
            }

            // And this expression itself is a valid term if the LHS is a valid
            // expression, and its PARENT is not an invocation.
            if (IsValidExpression(flags) &&
                !memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression))
            {
                expressionType = ExpressionType.ValidTerm;
            }
            else
            {
                expressionType = ExpressionType.ValidExpression;
            }
        }