コード例 #1
0
        public static bool TryAnalyzeVariableDeclaration(
            SemanticModel semanticModel,
            VariableDeclarationSyntax variableDeclaration,
            out INamedTypeSymbol tupleType,
            out ImmutableArray <MemberAccessExpressionSyntax> memberAccessExpressions,
            CancellationToken cancellationToken)
        {
            tupleType = null;
            memberAccessExpressions = default;

            // Only support code of the form:
            //
            //      var t = ...;  or
            //      (T1 e1, ..., TN eN) t = ...
            if (!variableDeclaration.IsParentKind(SyntaxKind.LocalDeclarationStatement))
            {
                return(false);
            }

            var declarator = variableDeclaration;

            if (declarator.Initializer == null)
            {
                return(false);
            }

            var local = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declarator, cancellationToken);
            var initializerConversion = semanticModel.GetConversion(declarator.Initializer.Value, cancellationToken);

            return(TryAnalyze(
                       semanticModel, local, variableDeclaration.Type, declarator.Identifier, initializerConversion,
                       variableDeclaration.Parent.Parent, out tupleType, out memberAccessExpressions, cancellationToken));
        }
コード例 #2
0
        public static TypeAnalysisResult AnalyzeType(
            VariableDeclarationSyntax variableDeclaration,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (variableDeclaration == null)
            {
                throw new ArgumentNullException(nameof(variableDeclaration));
            }

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

            TypeSyntax type = variableDeclaration.Type;

            if (type != null)
            {
                SeparatedSyntaxList <VariableDeclaratorSyntax> variables = variableDeclaration.Variables;

                if (variables.Count > 0 &&
                    !variableDeclaration.IsParentKind(SyntaxKind.FieldDeclaration))
                {
                    ExpressionSyntax expression = variables[0].Initializer?.Value;

                    if (expression != null)
                    {
                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken);

                        if (typeSymbol?.SupportsExplicitDeclaration() == true)
                        {
                            if (variables.Count > 1 ||
                                IsLocalConstDeclaration(variableDeclaration.Parent))
                            {
                                return((type.IsVar)
                                    ? TypeAnalysisResult.ImplicitButShouldBeExplicit
                                    : TypeAnalysisResult.None);
                            }
                            else if (IsImplicitTypeAllowed(typeSymbol, expression, semanticModel, cancellationToken))
                            {
                                return((type.IsVar)
                                    ? TypeAnalysisResult.Implicit
                                    : TypeAnalysisResult.ExplicitButShouldBeImplicit);
                            }
                            else
                            {
                                return((type.IsVar)
                                    ? TypeAnalysisResult.ImplicitButShouldBeExplicit
                                    : TypeAnalysisResult.Explicit);
                            }
                        }
                    }
                }
            }

            return(TypeAnalysisResult.None);
        }
コード例 #3
0
        private static async Task RenameVariableAccordingToTypeNameAsync(
            RefactoringContext context,
            VariableDeclarationSyntax variableDeclaration)
        {
            TypeSyntax type = variableDeclaration.Type;

            if (type != null &&
                !variableDeclaration.IsParentKind(SyntaxKind.EventFieldDeclaration))
            {
                VariableDeclaratorSyntax variable = variableDeclaration.SingleVariableOrDefault();

                if (variable != null)
                {
                    SyntaxToken identifier = variable.Identifier;

                    if (identifier.Span.Contains(context.Span))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ISymbol symbol = semanticModel.GetDeclaredSymbol(variable, context.CancellationToken);

                        if (symbol != null)
                        {
                            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken);

                            if (typeSymbol?.IsErrorType() == false)
                            {
                                string newName = Identifier.CreateName(
                                    typeSymbol,
                                    FirstCharToLower(symbol));

                                if (!string.IsNullOrEmpty(newName))
                                {
                                    if (context.Settings.PrefixFieldIdentifierWithUnderscore &&
                                        symbol.IsPrivate() &&
                                        symbol.IsField() &&
                                        !((IFieldSymbol)symbol).IsConst)
                                    {
                                        newName = Identifier.ToCamelCase(newName, prefixWithUnderscore: true);
                                    }

                                    string oldName = identifier.ValueText;

                                    if (!string.Equals(oldName, newName, StringComparison.Ordinal))
                                    {
                                        newName = Identifier.EnsureUniqueLocalName(newName, variable.SpanStart, semanticModel, context.CancellationToken);

                                        context.RegisterRefactoring(
                                            $"Rename '{oldName}' to '{newName}'",
                                            cancellationToken => Renamer.RenameSymbolAsync(context.Document, symbol, newName, cancellationToken));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #4
0
        private static async Task RenameVariableAccordingToTypeNameAsync(
            RefactoringContext context,
            VariableDeclarationSyntax variableDeclaration)
        {
            TypeSyntax type = variableDeclaration.Type;

            if (type == null)
            {
                return;
            }

            if (variableDeclaration.IsParentKind(SyntaxKind.EventFieldDeclaration))
            {
                return;
            }

            VariableDeclaratorSyntax variable = variableDeclaration.Variables.SingleOrDefault(shouldThrow: false);

            if (variable == null)
            {
                return;
            }

            SyntaxToken identifier = variable.Identifier;

            if (!identifier.Span.Contains(context.Span))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            if (semanticModel.GetDeclaredSymbol(variable, context.CancellationToken) is not ILocalSymbol localSymbol)
            {
                return;
            }

            string oldName = identifier.ValueText;

            string newName = NameGenerator.Default.CreateUniqueLocalName(
                localSymbol.Type,
                oldName,
                semanticModel,
                variable.SpanStart,
                cancellationToken: context.CancellationToken);

            if (newName == null)
            {
                return;
            }

            context.RegisterRefactoring(
                $"Rename '{oldName}' to '{newName}'",
                ct => Renamer.RenameSymbolAsync(context.Solution, localSymbol, newName, default(OptionSet), ct),
                RefactoringDescriptors.RenameIdentifierAccordingToTypeName);
        }
コード例 #5
0
        private bool ShouldAnalyzeVariableDeclaration(VariableDeclarationSyntax variableDeclaration, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            // implict type is applicable only for local variables and
            // such declarations cannot have multiple declarators and
            // must have an initializer.
            var isSupportedParentKind = variableDeclaration.IsParentKind(
                SyntaxKind.LocalDeclarationStatement,
                SyntaxKind.ForStatement,
                SyntaxKind.UsingStatement);

            return(isSupportedParentKind &&
                   variableDeclaration.Variables.Count == 1 &&
                   variableDeclaration.Variables.Single().Initializer.IsKind(SyntaxKind.EqualsValueClause));
        }
コード例 #6
0
        private static async Task RenameVariableAccordingToTypeNameAsync(
            RefactoringContext context,
            VariableDeclarationSyntax variableDeclaration)
        {
            TypeSyntax type = variableDeclaration.Type;

            if (type != null &&
                !variableDeclaration.IsParentKind(SyntaxKind.EventFieldDeclaration))
            {
                VariableDeclaratorSyntax variable = variableDeclaration.Variables.SingleOrDefault(throwException: false);

                if (variable != null)
                {
                    SyntaxToken identifier = variable.Identifier;

                    if (identifier.Span.Contains(context.Span))
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ISymbol symbol = semanticModel.GetDeclaredSymbol(variable, context.CancellationToken);

                        if (symbol?.IsLocal() == true)
                        {
                            var localSymbol = (ILocalSymbol)symbol;

                            string oldName = identifier.ValueText;

                            string newName = NameGenerator.Default.CreateUniqueLocalName(
                                localSymbol.Type,
                                oldName,
                                semanticModel,
                                variable.SpanStart,
                                cancellationToken: context.CancellationToken);

                            if (newName != null)
                            {
                                context.RegisterRefactoring(
                                    $"Rename '{oldName}' to '{newName}'",
                                    cancellationToken => Renamer.RenameSymbolAsync(context.Solution, symbol, newName, default(OptionSet), cancellationToken));
                            }
                        }
                    }
                }
            }
        }
コード例 #7
0
        public static TypeAnalysisFlags AnalyzeType(
            VariableDeclarationSyntax variableDeclaration,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (variableDeclaration == null)
            {
                throw new ArgumentNullException(nameof(variableDeclaration));
            }

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

            TypeSyntax type = variableDeclaration.Type;

            if (type != null)
            {
                SeparatedSyntaxList <VariableDeclaratorSyntax> variables = variableDeclaration.Variables;

                if (variables.Count > 0 &&
                    !variableDeclaration.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration))
                {
                    ExpressionSyntax expression = variables[0].Initializer?.Value;

                    if (expression != null)
                    {
                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken);

                        if (typeSymbol?.IsErrorType() == false)
                        {
                            var flags = TypeAnalysisFlags.None;

                            if (typeSymbol.IsDynamicType())
                            {
                                flags = TypeAnalysisFlags.Dynamic;
                            }
                            else
                            {
                                flags = TypeAnalysisFlags.ValidSymbol;

                                if (type.IsVar)
                                {
                                    flags |= TypeAnalysisFlags.Implicit;

                                    if (typeSymbol.SupportsExplicitDeclaration())
                                    {
                                        flags |= TypeAnalysisFlags.SupportsExplicit;
                                    }
                                }
                                else
                                {
                                    flags |= TypeAnalysisFlags.Explicit;

                                    if (variables.Count == 1 &&
                                        !IsLocalConstDeclaration(variableDeclaration) &&
                                        !expression.IsKind(SyntaxKind.NullLiteralExpression) &&
                                        typeSymbol.Equals(semanticModel.GetTypeSymbol(expression, cancellationToken)))
                                    {
                                        flags |= TypeAnalysisFlags.SupportsImplicit;
                                    }
                                }

                                if (IsTypeObvious(expression, semanticModel, cancellationToken))
                                {
                                    flags |= TypeAnalysisFlags.TypeObvious;
                                }
                            }

                            return(flags);
                        }
                    }
                }
            }

            return(TypeAnalysisFlags.None);
        }
コード例 #8
0
 public static bool IsFixable(VariableDeclarationSyntax variableDeclaration)
 {
     return(variableDeclaration.IsParentKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration) &&
            variableDeclaration.Variables.Count > 1);
 }
コード例 #9
0
        public static TypeAnalysis AnalyzeType(
            VariableDeclarationSyntax variableDeclaration,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            TypeSyntax type = variableDeclaration.Type;

            Debug.Assert(type != null);

            if (type == null)
            {
                return(TypeAnalysisFlags.None);
            }

            SeparatedSyntaxList <VariableDeclaratorSyntax> variables = variableDeclaration.Variables;

            Debug.Assert(variables.Any());

            if (!variables.Any())
            {
                return(TypeAnalysisFlags.None);
            }

            if (variableDeclaration.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration))
            {
                return(TypeAnalysisFlags.None);
            }

            ExpressionSyntax expression = variables[0].Initializer?.Value?.WalkDownParentheses();

            if (expression == null)
            {
                return(TypeAnalysisFlags.None);
            }

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken);

            if (typeSymbol == null)
            {
                return(TypeAnalysisFlags.None);
            }

            SymbolKind kind = typeSymbol.Kind;

            if (kind == SymbolKind.ErrorType)
            {
                return(TypeAnalysisFlags.None);
            }

            if (kind == SymbolKind.DynamicType)
            {
                return(TypeAnalysisFlags.Dynamic);
            }

            var flags = TypeAnalysisFlags.None;

            if (type.IsVar)
            {
                flags |= TypeAnalysisFlags.Implicit;

                if (typeSymbol.SupportsExplicitDeclaration())
                {
                    flags |= TypeAnalysisFlags.SupportsExplicit;
                }
            }
            else
            {
                flags |= TypeAnalysisFlags.Explicit;

                if (variables.Count == 1 &&
                    (variableDeclaration.Parent as LocalDeclarationStatementSyntax)?.IsConst != true &&
                    !expression.IsKind(SyntaxKind.NullLiteralExpression, SyntaxKind.DefaultLiteralExpression))
                {
                    flags |= TypeAnalysisFlags.SupportsImplicit;
                }
            }

            switch (expression.Kind())
            {
            case SyntaxKind.ObjectCreationExpression:
            case SyntaxKind.ArrayCreationExpression:
            case SyntaxKind.CastExpression:
            case SyntaxKind.AsExpression:
            case SyntaxKind.ThisExpression:
            case SyntaxKind.DefaultExpression:
            {
                flags |= TypeAnalysisFlags.TypeObvious;
                break;
            }

            case SyntaxKind.SimpleMemberAccessExpression:
            {
                ISymbol symbol = semanticModel.GetSymbol(expression, cancellationToken);

                if (symbol?.Kind == SymbolKind.Field &&
                    symbol.ContainingType?.TypeKind == TypeKind.Enum)
                {
                    flags |= TypeAnalysisFlags.TypeObvious;
                }

                break;
            }
            }

            return(flags);
        }
コード例 #10
0
        public static bool IsImplicitThatCanBeExplicit(
            VariableDeclarationSyntax variableDeclaration,
            SemanticModel semanticModel,
            TypeAppearance typeAppearance,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            TypeSyntax type = variableDeclaration.Type;

            Debug.Assert(type != null);

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

            if (!type.IsVar)
            {
                return(false);
            }

            if (variableDeclaration.IsParentKind(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration))
            {
                return(false);
            }

            Debug.Assert(variableDeclaration.Variables.Any());

            ExpressionSyntax expression = variableDeclaration
                                          .Variables
                                          .FirstOrDefault()?
                                          .Initializer?
                                          .Value?
                                          .WalkDownParentheses();

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

            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, cancellationToken);

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

            if (typeSymbol.IsKind(SymbolKind.ErrorType, SymbolKind.DynamicType))
            {
                return(false);
            }

            if (!typeSymbol.SupportsExplicitDeclaration())
            {
                return(false);
            }

            switch (typeAppearance)
            {
            case TypeAppearance.Obvious:
                return(IsObvious(expression, semanticModel, cancellationToken));

            case TypeAppearance.NotObvious:
                return(!IsObvious(expression, semanticModel, cancellationToken));
            }

            Debug.Assert(typeAppearance == TypeAppearance.None, typeAppearance.ToString());

            return(true);
        }