Exemple #1
0
            public State(
                SyntaxNode declaration,
                SemanticModel semanticModel,
                OptionSet optionSet,
                CancellationToken cancellationToken
                )
            {
                TypeStylePreference      = default;
                IsInIntrinsicTypeContext = default;
                IsTypeApparentInContext  = default;

                var styleForIntrinsicTypes = optionSet.GetOption(
                    CSharpCodeStyleOptions.VarForBuiltInTypes
                    );
                var styleForApparent = optionSet.GetOption(
                    CSharpCodeStyleOptions.VarWhenTypeIsApparent
                    );
                var styleForElsewhere = optionSet.GetOption(CSharpCodeStyleOptions.VarElsewhere);

                _forBuiltInTypes    = styleForIntrinsicTypes.Notification.Severity;
                _whenTypeIsApparent = styleForApparent.Notification.Severity;
                _elsewhere          = styleForElsewhere.Notification.Severity;

                var stylePreferences = UseVarPreference.None;

                if (styleForIntrinsicTypes.Value)
                {
                    stylePreferences |= UseVarPreference.ForBuiltInTypes;
                }

                if (styleForApparent.Value)
                {
                    stylePreferences |= UseVarPreference.WhenTypeIsApparent;
                }

                if (styleForElsewhere.Value)
                {
                    stylePreferences |= UseVarPreference.Elsewhere;
                }

                this.TypeStylePreference = stylePreferences;

                IsTypeApparentInContext =
                    declaration.IsKind(
                        SyntaxKind.VariableDeclaration,
                        out VariableDeclarationSyntax? varDecl
                        ) &&
                    IsTypeApparentInDeclaration(
                        varDecl,
                        semanticModel,
                        TypeStylePreference,
                        cancellationToken
                        );

                IsInIntrinsicTypeContext =
                    IsPredefinedTypeInDeclaration(declaration, semanticModel) ||
                    IsInferredPredefinedType(declaration, semanticModel);
            }
Exemple #2
0
 private static bool IsImplicitStylePreferred(
     UseVarPreference stylePreferences, bool isBuiltInTypeContext, bool isTypeApparentContext)
 {
     return(isBuiltInTypeContext
             ? stylePreferences.HasFlag(UseVarPreference.ForBuiltInTypes)
             : isTypeApparentContext
                 ? stylePreferences.HasFlag(UseVarPreference.WhenTypeIsApparent)
                 : stylePreferences.HasFlag(UseVarPreference.Elsewhere));
 }
Exemple #3
0
            /// <summary>
            /// Returns true if type information could be gleaned by simply looking at the given statement.
            /// This typically means that the type name occurs in right hand side of an assignment.
            /// </summary>
            private static bool IsTypeApparentInDeclaration(
                VariableDeclarationSyntax variableDeclaration,
                SemanticModel semanticModel,
                UseVarPreference stylePreferences,
                CancellationToken cancellationToken
                )
            {
                if (variableDeclaration.Variables.Count != 1)
                {
                    return(false);
                }

                var initializer = variableDeclaration.Variables[0].Initializer;

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

                var initializerExpression = CSharpUseImplicitTypeHelper.GetInitializerExpression(
                    initializer.Value
                    );
                var declaredTypeSymbol =
                    semanticModel.GetTypeInfo(
                        variableDeclaration.Type.StripRefIfNeeded(),
                        cancellationToken
                        ).Type;

                return(TypeStyleHelper.IsTypeApparentInAssignmentExpression(
                           stylePreferences,
                           initializerExpression,
                           semanticModel,
                           declaredTypeSymbol,
                           cancellationToken
                           ));
            }
Exemple #4
0
        /// <summary>
        /// Analyzes if type information is obvious to the reader by simply looking at the assignment expression.
        /// </summary>
        /// <remarks>
        /// <paramref name="typeInDeclaration"/> accepts null, to be able to cater to codegen features
        /// that are about to generate a local declaration and do not have this information to pass in.
        /// Things (like analyzers) that do have a local declaration already, should pass this in.
        /// </remarks>
        public static bool IsTypeApparentInAssignmentExpression(
            UseVarPreference stylePreferences,
            ExpressionSyntax initializerExpression,
            SemanticModel semanticModel,
            ITypeSymbol typeInDeclaration,
            CancellationToken cancellationToken)
        {
            // tuple literals
            if (initializerExpression.IsKind(SyntaxKind.TupleExpression, out TupleExpressionSyntax tuple))
            {
                if (typeInDeclaration == null || !typeInDeclaration.IsTupleType)
                {
                    return(false);
                }

                var tupleType = (INamedTypeSymbol)typeInDeclaration;
                if (tupleType.TupleElements.Length != tuple.Arguments.Count)
                {
                    return(false);
                }

                for (int i = 0, n = tuple.Arguments.Count; i < n; i++)
                {
                    var argument         = tuple.Arguments[i];
                    var tupleElementType = tupleType.TupleElements[i].Type;

                    if (!IsTypeApparentInAssignmentExpression(
                            stylePreferences, argument.Expression, semanticModel, tupleElementType, cancellationToken))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            // default(type)
            if (initializerExpression.IsKind(SyntaxKind.DefaultExpression))
            {
                return(true);
            }

            // literals, use var if options allow usage here.
            if (initializerExpression.IsAnyLiteralExpression())
            {
                return(stylePreferences.HasFlag(UseVarPreference.ForBuiltInTypes));
            }

            // constructor invocations cases:
            //      = new type();
            if (initializerExpression.IsKind(SyntaxKind.ObjectCreationExpression, SyntaxKind.ArrayCreationExpression) &&
                !initializerExpression.IsKind(SyntaxKind.AnonymousObjectCreationExpression))
            {
                return(true);
            }

            // explicit conversion cases:
            //      (type)expr, expr is type, expr as type
            if (initializerExpression.IsKind(SyntaxKind.CastExpression) ||
                initializerExpression.IsKind(SyntaxKind.IsExpression) ||
                initializerExpression.IsKind(SyntaxKind.AsExpression))
            {
                return(true);
            }

            // other Conversion cases:
            //      a. conversion with helpers like: int.Parse methods
            //      b. types that implement IConvertible and then invoking .ToType()
            //      c. System.Convert.ToType()
            var memberName = GetRightmostInvocationExpression(initializerExpression).GetRightmostName();

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

            if (!(semanticModel.GetSymbolInfo(memberName, cancellationToken).Symbol is IMethodSymbol methodSymbol))
            {
                return(false);
            }

            if (memberName.IsRightSideOfDot())
            {
                var containingTypeName = memberName.GetLeftSideOfDot();
                return(IsPossibleCreationOrConversionMethod(methodSymbol, typeInDeclaration, semanticModel, containingTypeName, cancellationToken));
            }

            return(false);
        }