예제 #1
0
 public override TypeStyleResult AnalyzeTypeName(
     TypeSyntax typeName, SemanticModel semanticModel,
     OptionSet optionSet, CancellationToken cancellationToken)
 {
     if (typeName.StripRefIfNeeded().IsVar)
     {
         return(default);
        internal static void ReplaceTypeWithVar(SyntaxEditor editor, TypeSyntax type)
        {
            type = type.StripRefIfNeeded();
            var implicitType = SyntaxFactory.IdentifierName("var").WithTriviaFrom(type);

            editor.ReplaceNode(type, implicitType);
        }
예제 #3
0
        internal override bool TryAnalyzeVariableDeclaration(
            TypeSyntax typeName, SemanticModel semanticModel,
            OptionSet optionSet, CancellationToken cancellationToken)
        {
            // var (x, y) = e;
            // foreach (var (x, y) in e) ...
            if (typeName.IsParentKind(SyntaxKind.DeclarationExpression))
            {
                var parent = (DeclarationExpressionSyntax)typeName.Parent;
                if (parent.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation))
                {
                    return(true);
                }
            }

            // If it is currently not var, explicit typing exists, return.
            // this also takes care of cases where var is mapped to a named type via an alias or a class declaration.
            if (!typeName.StripRefIfNeeded().IsTypeInferred(semanticModel))
            {
                return(false);
            }

            if (typeName.Parent.IsKind(SyntaxKind.VariableDeclaration) &&
                typeName.Parent.Parent.IsKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.ForStatement, SyntaxKind.UsingStatement))
            {
                // check assignment for variable declarations.
                var variableDeclaration = (VariableDeclarationSyntax)typeName.Parent;
                var variable            = variableDeclaration.Variables.First();
                if (!AssignmentSupportsStylePreference(
                        variable.Identifier, typeName, variable.Initializer.Value,
                        semanticModel, optionSet, cancellationToken))
                {
                    return(false);
                }

                // This error case is handled by a separate code fix (UseExplicitTypeForConst).
                if ((variableDeclaration.Parent as LocalDeclarationStatementSyntax)?.IsConst == true)
                {
                    return(false);
                }
            }
            else if (typeName.Parent is ForEachStatementSyntax foreachStatement &&
                     foreachStatement.Type == typeName)
            {
                if (!AssignmentSupportsStylePreference(
                        foreachStatement.Identifier, typeName, foreachStatement.Expression,
                        semanticModel, optionSet, cancellationToken))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #4
0
        /// <summary>
        /// Analyzes the assignment expression and rejects a given declaration if it is unsuitable for explicit typing.
        /// </summary>
        /// <returns>
        /// false, if explicit typing cannot be used.
        /// true, otherwise.
        /// </returns>
        protected override bool AssignmentSupportsStylePreference(
            SyntaxToken identifier,
            TypeSyntax typeName,
            ExpressionSyntax initializer,
            SemanticModel semanticModel,
            OptionSet optionSet,
            CancellationToken cancellationToken)
        {
            // is or contains an anonymous type
            // cases :
            //        var anon = new { Num = 1 };
            //        var enumerableOfAnons = from prod in products select new { prod.Color, prod.Price };
            var declaredType = semanticModel.GetTypeInfo(typeName.StripRefIfNeeded(), cancellationToken).Type;

            if (declaredType.ContainsAnonymousType())
            {
                return(false);
            }

            // cannot find type if initializer resolves to an ErrorTypeSymbol
            var initializerTypeInfo = semanticModel.GetTypeInfo(initializer, cancellationToken);

            return(!initializerTypeInfo.Type.IsErrorType());
        }
        internal static async Task HandleDeclarationAsync(
            Document document, SyntaxEditor editor,
            SyntaxNode node, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var declarationContext = node.Parent;

            TypeSyntax typeSyntax = null;
            ParenthesizedVariableDesignationSyntax parensDesignation = null;

            if (declarationContext is RefTypeSyntax refType)
            {
                declarationContext = declarationContext.Parent;
            }

            if (declarationContext is VariableDeclarationSyntax varDecl)
            {
                typeSyntax = varDecl.Type;
            }
            else if (declarationContext is ForEachStatementSyntax forEach)
            {
                typeSyntax = forEach.Type;
            }
            else if (declarationContext is DeclarationExpressionSyntax declarationExpression)
            {
                typeSyntax = declarationExpression.Type;
                if (declarationExpression.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation))
                {
                    parensDesignation = (ParenthesizedVariableDesignationSyntax)declarationExpression.Designation;
                }
            }
            else
            {
                Contract.Fail($"unhandled kind {declarationContext.Kind().ToString()}");
            }

            if (parensDesignation is null)
            {
                var typeSymbol = semanticModel.GetTypeInfo(typeSyntax.StripRefIfNeeded()).ConvertedType;

                // We're going to be passed through the simplifier.  Tell it to not just convert
                // this back to var (as that would defeat the purpose of this refactoring entirely).
                var typeName = typeSymbol.GenerateTypeSyntax(allowVar: false)
                               .WithLeadingTrivia(node.GetLeadingTrivia())
                               .WithTrailingTrivia(node.GetTrailingTrivia());
                Debug.Assert(!typeName.ContainsDiagnostics, "Explicit type replacement likely introduced an error in code");

                editor.ReplaceNode(node, typeName);
            }
            else
            {
                var tupleTypeSymbol = semanticModel.GetTypeInfo(typeSyntax.Parent).ConvertedType;

                var leadingTrivia = node.GetLeadingTrivia()
                                    .Concat(parensDesignation.GetAllPrecedingTriviaToPreviousToken().Where(t => !t.IsWhitespace()).Select(t => t.WithoutAnnotations(SyntaxAnnotation.ElasticAnnotation)));

                var tupleDeclaration = GenerateTupleDeclaration(tupleTypeSymbol, parensDesignation).WithLeadingTrivia(leadingTrivia);

                editor.ReplaceNode(declarationContext, tupleDeclaration);
            }
        }