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)); }
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); }
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)); } } } } } } } }
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); }
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)); }
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)); } } } } } }
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); }
public static bool IsFixable(VariableDeclarationSyntax variableDeclaration) { return(variableDeclaration.IsParentKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration) && variableDeclaration.Variables.Count > 1); }
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); }
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); }