internal static async Task ChangeTypeAsync( RefactoringContext context, ForEachStatementSyntax forEachStatement) { TypeSyntax type = forEachStatement.Type; if (type?.Span.Contains(context.Span) != true) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeAnalysis analysis = CSharpTypeAnalysis.AnalyzeType(forEachStatement, semanticModel); if (analysis.IsExplicit) { if (analysis.SupportsImplicit && context.IsRefactoringEnabled(RefactoringDescriptors.UseImplicitType)) { context.RegisterRefactoring(CodeActionFactory.ChangeTypeToVar(context.Document, type, equivalenceKey: EquivalenceKey.Create(RefactoringDescriptors.UseImplicitType))); } if (!forEachStatement.ContainsDiagnostics && context.IsRefactoringEnabled(RefactoringDescriptors.ChangeTypeAccordingToExpression)) { ChangeTypeAccordingToExpression(context, forEachStatement, semanticModel); } } else if (analysis.SupportsExplicit && context.IsRefactoringEnabled(RefactoringDescriptors.UseExplicitType)) { context.RegisterRefactoring(CodeActionFactory.UseExplicitType(context.Document, type, analysis.Symbol, semanticModel, equivalenceKey: EquivalenceKey.Create(RefactoringDescriptors.UseExplicitType))); } }
private static void ChangeTypeAccordingToExpression( RefactoringContext context, ForEachStatementSyntax forEachStatement, SemanticModel semanticModel) { ForEachStatementInfo info = semanticModel.GetForEachStatementInfo(forEachStatement); ITypeSymbol elementType = info.ElementType; if (elementType?.IsErrorType() != false) { return; } Conversion conversion = info.ElementConversion; if (conversion.IsIdentity) { return; } if (!conversion.IsImplicit) { return; } context.RegisterRefactoring(CodeActionFactory.UseExplicitType(context.Document, forEachStatement.Type, elementType, semanticModel, equivalenceKey: EquivalenceKey.Create(RefactoringDescriptors.ChangeTypeAccordingToExpression))); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf( root, context.Span, out SyntaxNode node, predicate: f => f.IsKind(SyntaxKind.ForEachStatement, SyntaxKind.ForEachVariableStatement, SyntaxKind.DeclarationExpression))) { return; } Document document = context.Document; Diagnostic diagnostic = context.Diagnostics[0]; SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeSyntax type; ITypeSymbol typeSymbol; switch (node) { case ForEachStatementSyntax forEachStatement: { type = forEachStatement.Type; typeSymbol = semanticModel.GetForEachStatementInfo((CommonForEachStatementSyntax)node).ElementType; break; } case ForEachVariableStatementSyntax forEachVariableStatement: { var declarationExpression = (DeclarationExpressionSyntax)forEachVariableStatement.Variable; type = declarationExpression.Type; typeSymbol = semanticModel.GetForEachStatementInfo((CommonForEachStatementSyntax)node).ElementType; break; } case DeclarationExpressionSyntax declarationExpression: { type = declarationExpression.Type; typeSymbol = semanticModel.GetTypeSymbol(declarationExpression, context.CancellationToken); break; } default: { throw new InvalidOperationException(); } } CodeAction codeAction = CodeActionFactory.UseExplicitType(document, type, typeSymbol, semanticModel, equivalenceKey: GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); }
private void RegisterCodeFix(CodeFixContext context, TypeSyntax type, ITypeSymbol typeSymbol, SemanticModel semanticModel) { foreach (Diagnostic diagnostic in context.Diagnostics) { CodeAction codeAction = CodeActionFactory.UseExplicitType(context.Document, type, typeSymbol, semanticModel, equivalenceKey: GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); } }
private static void ChangeTypeAccordingToExpression( RefactoringContext context, VariableDeclarationSyntax variableDeclaration, ITypeSymbol typeSymbol, SemanticModel semanticModel) { foreach (VariableDeclaratorSyntax variableDeclarator in variableDeclaration.Variables) { ExpressionSyntax value = variableDeclarator.Initializer?.Value; if (value == null) { return; } Conversion conversion = semanticModel.ClassifyConversion(value, typeSymbol); if (conversion.IsIdentity) { return; } if (!conversion.IsImplicit) { return; } } ITypeSymbol newTypeSymbol = semanticModel.GetTypeSymbol(variableDeclaration.Variables[0].Initializer.Value, context.CancellationToken); if (newTypeSymbol == null) { return; } context.RegisterRefactoring(CodeActionFactory.UseExplicitType(context.Document, variableDeclaration.Type, newTypeSymbol, semanticModel, equivalenceKey: EquivalenceKey.Create(RefactoringDescriptors.ChangeTypeAccordingToExpression))); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, VariableDeclarationSyntax variableDeclaration) { TypeSyntax type = variableDeclaration.Type; if (type?.Span.Contains(context.Span) == true && context.IsAnyRefactoringEnabled( RefactoringDescriptors.UseImplicitType, RefactoringDescriptors.UseExplicitType, RefactoringDescriptors.ChangeTypeAccordingToExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeAnalysis analysis = CSharpTypeAnalysis.AnalyzeType(variableDeclaration, semanticModel, context.CancellationToken); if (analysis.IsExplicit) { if (analysis.SupportsImplicit && context.IsRefactoringEnabled(RefactoringDescriptors.UseImplicitType)) { context.RegisterRefactoring(CodeActionFactory.ChangeTypeToVar(context.Document, type, equivalenceKey: EquivalenceKey.Create(RefactoringDescriptors.UseImplicitType))); } if (!variableDeclaration.ContainsDiagnostics && context.IsRefactoringEnabled(RefactoringDescriptors.ChangeTypeAccordingToExpression)) { ChangeTypeAccordingToExpression(context, variableDeclaration, analysis.Symbol, semanticModel); } } else if (analysis.SupportsExplicit && context.IsRefactoringEnabled(RefactoringDescriptors.UseExplicitType)) { ITypeSymbol typeSymbol = analysis.Symbol; VariableDeclaratorSyntax variableDeclarator = variableDeclaration.Variables.SingleOrDefault(shouldThrow: false); if (variableDeclarator?.Initializer?.Value != null) { if (typeSymbol.OriginalDefinition.EqualsOrInheritsFromTaskOfT()) { Func <CancellationToken, Task <Document> > createChangedDocument = DocumentRefactoringFactory.ChangeTypeAndAddAwait( context.Document, variableDeclaration, variableDeclarator, typeSymbol, semanticModel, context.CancellationToken); if (createChangedDocument != null) { context.RegisterRefactoring( "Use explicit type (and add 'await')", createChangedDocument, RefactoringDescriptors.UseExplicitType, "AddAwait"); } } typeSymbol = semanticModel.GetTypeSymbol(variableDeclarator.Initializer.Value, context.CancellationToken); if (typeSymbol != null) { context.RegisterRefactoring(CodeActionFactory.UseExplicitType(context.Document, type, typeSymbol, semanticModel, equivalenceKey: EquivalenceKey.Create(RefactoringDescriptors.UseExplicitType))); } } } } }