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)); }
/// <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); }