public void IntroduceFieldRefactoring_DisplaysInvalidSelectionAndDoesNothingForInvalidSelection() { //Input const string inputCode = @"Private fizz As Boolean Private Sub Foo() End Sub"; var selection = new Selection(3, 16, 3, 16); IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var state = MockParser.CreateAndParse(vbe.Object); var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var messageBox = new Mock <IMessageBox>(); messageBox.Setup(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>())).Returns(DialogResult.OK); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, messageBox.Object); refactoring.Refactor(qualifiedSelection); messageBox.Verify(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>()), Times.Once); var actual = state.GetRewriter(component).GetText(); Assert.AreEqual(inputCode, actual); }
public void IntroduceFieldRefactoring_MultipleFieldsOnMultipleLines() { //Input const string inputCode = @"Public fizz As Integer Public buzz As Integer Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean End Sub"; var selection = new Selection(5, 8, 5, 20); //Expectation const string expectedCode = @"Public fizz As Integer Public buzz As Integer Private bar As Boolean Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var state = MockParser.CreateAndParse(vbe.Object); var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, null); refactoring.Refactor(qualifiedSelection); Assert.AreEqual(expectedCode, component.CodeModule.Content()); }
public void IntroduceFieldRefactoring_OneFieldInList_MultipleLines() { //Input const string inputCode = @"Public fizz As Integer Private Sub Foo(ByVal buz As Integer) Dim _ bar _ As _ Boolean End Sub"; var selection = new Selection(3, 10, 3, 13); //Expectation const string expectedCode = @"Public fizz As Integer Private bar As Boolean Private Sub Foo(ByVal buz As Integer) End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var state = MockParser.CreateAndParse(vbe.Object); var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, null); refactoring.Refactor(qualifiedSelection); var actual = state.GetRewriter(component).GetText(); Assert.AreEqual(expectedCode, actual); }
public void IntroduceFieldRefactoring_MultipleVariablesInStatement_OnOneLine_MoveFirst() { //Input const string inputCode = @"Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean, bat As Date, bap As Integer End Sub"; var selection = new Selection(3, 10, 3, 13); //Expectation const string expectedCode = @"Private bar As Boolean Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bat As Date, bap As Integer End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var state = MockParser.CreateAndParse(vbe.Object); var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, null); refactoring.Refactor(qualifiedSelection); var actual = state.GetRewriter(component).GetText(); Assert.AreEqual(expectedCode, actual); }
public void IntroduceFieldRefactoring_MultipleVariablesInStatement_MoveSecond() { //Input const string inputCode = @" Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean, _ bat As Date, _ bap As Integer End Sub"; //Expectation const string expectedCode = @" Private bat As Date Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean, _ bap As Integer End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component); var(state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); using (state) { var target = state.AllUserDeclarations.SingleOrDefault(e => e.IdentifierName == "bat"); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, new Mock <IMessageBox>().Object, rewritingManager); refactoring.Refactor(target); var actualCode = component.CodeModule.Content(); Assert.AreEqual(expectedCode, actualCode); } }
public void IntroduceFieldRefactoring_DisplaysInvalidSelectionAndDoesNothingForInvalidSelection() { //Input const string inputCode = @"Private fizz As Boolean Private Sub Foo() End Sub"; var selection = new Selection(3, 16, 3, 16); IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var(state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); using (state) { var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var messageBox = new Mock <IMessageBox>(); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, messageBox.Object, rewritingManager); refactoring.Refactor(qualifiedSelection); messageBox.Verify(m => m.NotifyWarn(It.IsAny <string>(), It.IsAny <string>()), Times.Once); const string expectedCode = inputCode; var actualCode = component.CodeModule.Content(); Assert.AreEqual(expectedCode, actualCode); } }
public void IntroduceFieldRefactoring_PassInTarget_Nonvariable() { //Input const string inputCode = @"Private Sub Foo() Dim bar As Boolean End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component); var(state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); using (state) { var messageBox = new Mock <IMessageBox>(); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, messageBox.Object, rewritingManager); try { refactoring.Refactor(state.AllUserDeclarations.First(d => d.DeclarationType != DeclarationType.Variable)); } catch (ArgumentException e) { messageBox.Verify(m => m.NotifyWarn(It.IsAny <string>(), It.IsAny <string>()), Times.Once); Assert.AreEqual("target", e.ParamName); var actual = component.CodeModule.Content(); Assert.AreEqual(inputCode, actual); return; } Assert.Fail(); } }
public void IntroduceFieldRefactoring_PassInTarget() { //Input const string inputCode = @"Private Sub Foo() Dim bar As Boolean End Sub"; var selection = new Selection(2, 10, 2, 13); //Expectation const string expectedCode = @"Private bar As Boolean Private Sub Foo() End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var(state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); using (state) { var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring((vbe.Object), state, null, rewritingManager); refactoring.Refactor(state.AllUserDeclarations.FindVariable(qualifiedSelection)); var actualCode = component.CodeModule.Content(); Assert.AreEqual(expectedCode, actualCode); } }
public void IntroduceFieldRefactoring_OneFieldInList() { //Input const string inputCode = @"Public fizz As Integer Private Sub Foo(ByVal buz As Integer) Dim bar As Boolean End Sub"; var selection = new Selection(3, 10, 3, 13); //Expectation const string expectedCode = @"Public fizz As Integer Private bar As Boolean Private Sub Foo(ByVal buz As Integer) End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var(state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); using (state) { var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, null, rewritingManager); refactoring.Refactor(qualifiedSelection); var actualCode = component.CodeModule.Content(); Assert.AreEqual(expectedCode, actualCode); } }
public void IntroduceFieldRefactoring_NoFieldsInClass_Sub() { //Input const string inputCode = @"Private Sub Foo() Dim bar As Boolean End Sub"; var selection = new Selection(2, 10, 2, 13); //Expectation const string expectedCode = @"Private bar As Boolean Private Sub Foo() End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var state = MockParser.CreateAndParse(vbe.Object); var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, null); refactoring.Refactor(qualifiedSelection); Assert.AreEqual(expectedCode, component.CodeModule.Content()); }
public void IntroduceFieldRefactoring_NoFieldsInList_Function() { //Input const string inputCode = @"Private Function Foo() As Boolean Dim bar As Boolean Foo = True End Function"; var selection = new Selection(2, 10, 2, 13); //Expectation const string expectedCode = @"Private bar As Boolean Private Function Foo() As Boolean Foo = True End Function"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component, selection); var state = MockParser.CreateAndParse(vbe.Object); var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, null); refactoring.Refactor(qualifiedSelection); var actual = state.GetRewriter(component).GetText(); Assert.AreEqual(expectedCode, actual); }
protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state, IRewritingManager rewritingManager, ISelectionService selectionService) { var msgBox = new Mock <IMessageBox>().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var refactoring = new IntroduceFieldRefactoring(state, rewritingManager, selectionService, selectedDeclarationProvider); var notifier = new IntroduceFieldFailedNotifier(msgBox); return(new RefactorIntroduceFieldCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider)); }
public void IntroduceFieldRefactoring_PassInTarget_Nonvariable() { //Input const string inputCode = @"Private Sub Foo() Dim bar As Boolean End Sub"; //Arrange var builder = new MockVbeBuilder(); VBComponent component; var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); var project = vbe.Object.VBProjects.Item(0); var module = project.VBComponents.Item(0).CodeModule; var codePaneFactory = new CodePaneWrapperFactory(); var mockHost = new Mock <IHostApplication>(); mockHost.SetupAllProperties(); var parser = MockParser.Create(vbe.Object, new RubberduckParserState()); parser.Parse(); if (parser.State.Status == ParserState.Error) { Assert.Inconclusive("Parser Error"); } var messageBox = new Mock <IMessageBox>(); messageBox.Setup(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>())) .Returns(DialogResult.OK); //Act var refactoring = new IntroduceFieldRefactoring(parser.State, new ActiveCodePaneEditor(vbe.Object, codePaneFactory), messageBox.Object); //Assert try { refactoring.Refactor(parser.State.AllUserDeclarations.First(d => d.DeclarationType != DeclarationType.Variable)); } catch (ArgumentException e) { messageBox.Verify(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>()), Times.Once); Assert.AreEqual("Invalid declaration type\r\nParameter name: target", e.Message); Assert.AreEqual(inputCode, module.Lines()); return; } Assert.Fail(); }
public override void Execute(object parameter) { var selection = Vbe.ActiveCodePane.GetQualifiedSelection(); if (!selection.HasValue) { return; } var refactoring = new IntroduceFieldRefactoring(Vbe, _state, new MessageBox()); refactoring.Refactor(selection.Value); }
public override void Execute(object parameter) { if (Vbe.ActiveCodePane == null) { return; } var codePane = _wrapperWrapperFactory.Create(Vbe.ActiveCodePane); var selection = new QualifiedSelection(new QualifiedModuleName(codePane.CodeModule.Parent), codePane.Selection); var refactoring = new IntroduceFieldRefactoring(_state, Editor, new MessageBox()); refactoring.Refactor(selection); }
public RefactorIntroduceFieldCommand( IntroduceFieldRefactoring refactoring, IntroduceFieldFailedNotifier introduceFieldFailedNotifier, RubberduckParserState state, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) : base(refactoring, introduceFieldFailedNotifier, selectionProvider, state) { _state = state; _selectedDeclarationProvider = selectedDeclarationProvider; AddToCanExecuteEvaluation(SpecializedEvaluateCanExecute); }
protected override void OnExecute(object parameter) { var selection = Vbe.GetActiveSelection(); if (!selection.HasValue) { return; } var refactoring = new IntroduceFieldRefactoring(Vbe, _state, _messageBox, _rewritingManager); refactoring.Refactor(selection.Value); }
protected override void OnExecute(object parameter) { var activeSelection = SelectionService.ActiveSelection(); if (!activeSelection.HasValue) { return; } var refactoring = new IntroduceFieldRefactoring(_state, _messageBox, RewritingManager, SelectionService); refactoring.Refactor(activeSelection.Value); }
public void IntroduceFieldRefactoring_MultipleVariablesInStatement_MoveLast() { //Input const string inputCode = @"Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean, _ bat As Date, _ bap As Integer End Sub"; var selection = new Selection(5, 10, 5, 13); //Expectation const string expectedCode = @"Private bap As Integer Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean, _ bat As Date End Sub"; //Arrange var builder = new MockVbeBuilder(); VBComponent component; var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); var project = vbe.Object.VBProjects.Item(0); var module = project.VBComponents.Item(0).CodeModule; var codePaneFactory = new CodePaneWrapperFactory(); var mockHost = new Mock <IHostApplication>(); mockHost.SetupAllProperties(); var parser = MockParser.Create(vbe.Object, new RubberduckParserState()); parser.Parse(); if (parser.State.Status == ParserState.Error) { Assert.Inconclusive("Parser Error"); } var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); //Act var refactoring = new IntroduceFieldRefactoring(parser.State, new ActiveCodePaneEditor(vbe.Object, codePaneFactory), null); refactoring.Refactor(qualifiedSelection); //Assert Assert.AreEqual(expectedCode, module.Lines()); }
public void IntroduceFieldRefactoring_MultipleFieldsOnMultipleLines() { //Input const string inputCode = @"Public fizz As Integer Public buzz As Integer Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) Dim bar As Boolean End Sub"; var selection = new Selection(5, 8, 5, 20); //Expectation const string expectedCode = @"Public fizz As Integer Public buzz As Integer Private bar As Boolean Private Sub Foo(ByVal buz As Integer, _ ByRef baz As Date) End Sub"; //Arrange var builder = new MockVbeBuilder(); VBComponent component; var vbe = builder.BuildFromSingleStandardModule(inputCode, out component, selection); var project = vbe.Object.VBProjects.Item(0); var module = project.VBComponents.Item(0).CodeModule; var mockHost = new Mock <IHostApplication>(); mockHost.SetupAllProperties(); var parser = MockParser.Create(vbe.Object, new RubberduckParserState()); parser.Parse(); if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); } var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); //Act var refactoring = new IntroduceFieldRefactoring(vbe.Object, parser.State, null); refactoring.Refactor(qualifiedSelection); //Assert Assert.AreEqual(expectedCode, module.Lines()); }
public void IntroduceFieldRefactoring_DisplaysInvalidSelectionAndDoesNothingForInvalidSelection() { //Input const string inputCode = @"Private fizz As Boolean Private Sub Foo() End Sub"; var selection = new Selection(3, 16, 3, 16); //Arrange var builder = new MockVbeBuilder(); VBComponent component; var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); var project = vbe.Object.VBProjects.Item(0); var module = project.VBComponents.Item(0).CodeModule; var codePaneFactory = new CodePaneWrapperFactory(); var mockHost = new Mock <IHostApplication>(); mockHost.SetupAllProperties(); var parser = MockParser.Create(vbe.Object, new RubberduckParserState()); parser.Parse(); if (parser.State.Status == ParserState.Error) { Assert.Inconclusive("Parser Error"); } var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); var messageBox = new Mock <IMessageBox>(); messageBox.Setup(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>())).Returns(DialogResult.OK); //Act var refactoring = new IntroduceFieldRefactoring(parser.State, new ActiveCodePaneEditor(vbe.Object, codePaneFactory), messageBox.Object); refactoring.Refactor(qualifiedSelection); //Assert messageBox.Verify(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>()), Times.Once); Assert.AreEqual(inputCode, module.Lines()); }
public void IntroduceFieldRefactoring_NoFieldsInList_Function() { //Input const string inputCode = @"Private Function Foo() As Boolean Dim bar As Boolean Foo = True End Function"; var selection = new Selection(2, 10, 2, 13); //Expectation const string expectedCode = @"Private bar As Boolean Private Function Foo() As Boolean Foo = True End Function"; //Arrange var builder = new MockVbeBuilder(); VBComponent component; var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); var project = vbe.Object.VBProjects.Item(0); var module = project.VBComponents.Item(0).CodeModule; var codePaneFactory = new CodePaneWrapperFactory(); var mockHost = new Mock <IHostApplication>(); mockHost.SetupAllProperties(); var parser = MockParser.Create(vbe.Object, new RubberduckParserState()); parser.Parse(); if (parser.State.Status == ParserState.Error) { Assert.Inconclusive("Parser Error"); } var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); //Act var refactoring = new IntroduceFieldRefactoring(parser.State, new ActiveCodePaneEditor(vbe.Object, codePaneFactory), null); refactoring.Refactor(qualifiedSelection); //Assert Assert.AreEqual(expectedCode, module.Lines()); }
protected override void ExecuteImpl(object parameter) { var pane = Vbe.ActiveCodePane; { if (pane.IsWrappingNullReference) { return; } var selection = pane.GetQualifiedSelection(); if (!selection.HasValue) { return; } var refactoring = new IntroduceFieldRefactoring(Vbe, _state, _messageBox); refactoring.Refactor(selection.Value); } }
public void IntroduceFieldRefactoring_PassInTarget() { //Input const string inputCode = @"Private Sub Foo() Dim bar As Boolean End Sub"; var selection = new Selection(2, 10, 2, 13); //Expectation const string expectedCode = @"Private bar As Boolean Private Sub Foo() End Sub"; //Arrange var builder = new MockVbeBuilder(); VBComponent component; var vbe = builder.BuildFromSingleStandardModule(inputCode, out component, selection); var project = vbe.Object.VBProjects.Item(0); var module = project.VBComponents.Item(0).CodeModule; var mockHost = new Mock <IHostApplication>(); mockHost.SetupAllProperties(); var parser = MockParser.Create(vbe.Object, new RubberduckParserState()); parser.Parse(); if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); } var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); //Act var refactoring = new IntroduceFieldRefactoring(vbe.Object, parser.State, null); refactoring.Refactor(parser.State.AllUserDeclarations.FindVariable(qualifiedSelection)); //Assert Assert.AreEqual(expectedCode, module.Lines()); }
public void IntroduceFieldRefactoring_PassInTarget_Nonvariable() { //Input const string inputCode = @"Private Sub Foo() Dim bar As Boolean End Sub"; IVBComponent component; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out component); using (var state = MockParser.CreateAndParse(vbe.Object)) { var messageBox = new Mock <IMessageBox>(); messageBox.Setup(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>())) .Returns(DialogResult.OK); var refactoring = new IntroduceFieldRefactoring(vbe.Object, state, messageBox.Object); try { refactoring.Refactor(state.AllUserDeclarations.First(d => d.DeclarationType != DeclarationType.Variable)); } catch (ArgumentException e) { messageBox.Verify(m => m.Show(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <MessageBoxButtons>(), It.IsAny <MessageBoxIcon>()), Times.Once); Assert.AreEqual("target", e.ParamName); var actual = state.GetRewriter(component).GetText(); Assert.AreEqual(inputCode, actual); return; } Assert.Fail(); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.RemoveEmptySwitchStatement, CodeFixIdentifiers.IntroduceLocalVariable, CodeFixIdentifiers.RemoveJumpStatement)) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindFirstAncestorOrSelf(root, context.Span, out StatementSyntax statement)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.EmptySwitchBlock: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveEmptySwitchStatement)) { break; } if (!statement.IsKind(SyntaxKind.SwitchStatement)) { break; } var switchStatement = (SwitchStatementSyntax)statement; CodeAction codeAction = CodeAction.Create( "Remove switch statement", cancellationToken => context.Document.RemoveStatementAsync(switchStatement, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.OnlyAssignmentCallIncrementDecrementAndNewObjectExpressionsCanBeUsedAsStatement: { if (Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.IntroduceLocalVariable, CodeFixIdentifiers.IntroduceField)) { if (!(statement is ExpressionStatementSyntax expressionStatement)) { break; } ExpressionSyntax expression = expressionStatement.Expression; SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetSymbol(expression, context.CancellationToken)?.IsErrorType() != false) { break; } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken); if (typeSymbol?.IsErrorType() != false) { break; } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceLocalVariable) && !statement.IsEmbedded()) { bool addAwait = typeSymbol.IsConstructedFromTaskOfT(semanticModel) && semanticModel.GetEnclosingSymbol(expressionStatement.SpanStart, context.CancellationToken).IsAsyncMethod(); CodeAction codeAction = CodeAction.Create( IntroduceLocalVariableRefactoring.GetTitle(expression), cancellationToken => IntroduceLocalVariableRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, addAwait, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceLocalVariable)); context.RegisterCodeFix(codeAction, diagnostic); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceField)) { CodeAction codeAction = CodeAction.Create( $"Introduce field for '{expression}'", cancellationToken => IntroduceFieldRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceField)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.NoEnclosingLoopOutOfWhichToBreakOrContinue: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveJumpStatement)) { break; } CodeAction codeAction = CodeAction.Create( $"Remove {statement.GetTitle()}", cancellationToken => context.Document.RemoveStatementAsync(statement, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } } } }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindNode(root, context.Span, out ExpressionSyntax expression)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertTypeExplicitConversionExists: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken); ITypeSymbol type = typeInfo.Type; ITypeSymbol convertedType = typeInfo.ConvertedType; if ((type is INamedTypeSymbol namedType) && namedType.IsNullableType()) { if (convertedType?.SpecialType == SpecialType.System_Boolean || AddComparisonWithBooleanLiteralRefactoring.IsCondition(expression)) { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddComparisonWithBooleanLiteral)) { CodeAction codeAction = CodeAction.Create( AddComparisonWithBooleanLiteralRefactoring.GetTitle(expression), cancellationToken => AddComparisonWithBooleanLiteralRefactoring.RefactorAsync(context.Document, expression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddComparisonWithBooleanLiteral)); context.RegisterCodeFix(codeAction, diagnostic); } } else if (SymbolEqualityComparer.Default.Equals(namedType.TypeArguments[0], convertedType)) { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseCoalesceExpression)) { CodeAction codeAction = CodeAction.Create( "Use coalesce expression", cancellationToken => { ExpressionSyntax defaultValue = convertedType.GetDefaultValueSyntax(context.Document.GetDefaultSyntaxOptions()); ExpressionSyntax newNode = CoalesceExpression(expression.WithoutTrivia(), defaultValue) .WithTriviaFrom(expression) .Parenthesize() .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseCoalesceExpression)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) && expression.IsParentKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement)) { ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddCastExpression)) { CodeFixRegistrator.AddCastExpression(context, diagnostic, expression, convertedType, semanticModel); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeTypeAccordingToInitializer)) { ChangeTypeAccordingToInitializerRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.CreateSingletonArray) && type?.IsErrorType() == false && !SymbolEqualityComparer.Default.Equals(type, convertedType) && (convertedType is IArrayTypeSymbol arrayType) && semanticModel.IsImplicitConversion(expression, arrayType.ElementType)) { CodeAction codeAction = CodeAction.Create( "Create singleton array", cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.CreateSingletonArray)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.ConstantValueCannotBeConverted: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseUncheckedExpression)) { break; } CodeAction codeAction = CodeAction.Create( "Use 'unchecked'", cancellationToken => { CheckedExpressionSyntax newNode = CSharpFactory.UncheckedExpression(expression.WithoutTrivia()); newNode = newNode.WithTriviaFrom(expression); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExpressionBeingAssignedMustBeConstant: { SyntaxNode parent = expression.Parent; if (parent?.IsKind(SyntaxKind.EqualsValueClause) != true) { break; } parent = parent.Parent; if (parent?.IsKind(SyntaxKind.VariableDeclarator) != true) { break; } parent = parent.Parent; if (!(parent is VariableDeclarationSyntax variableDeclaration)) { break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstModifier) && variableDeclaration.Parent is LocalDeclarationStatementSyntax localDeclarationStatement) { SyntaxTokenList modifiers = localDeclarationStatement.Modifiers; if (!modifiers.Contains(SyntaxKind.ConstKeyword)) { break; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, localDeclarationStatement, SyntaxKind.ConstKeyword); } else if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceConstantWithField) && variableDeclaration.Variables.Count == 1 && (variableDeclaration.Parent is FieldDeclarationSyntax fieldDeclaration) && fieldDeclaration.Modifiers.Contains(SyntaxKind.ConstKeyword)) { CodeAction codeAction = CodeAction.Create( ReplaceConstantWithFieldRefactoring.Title, cancellationToken => ReplaceConstantWithFieldRefactoring.RefactorAsync(context.Document, fieldDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } break; } case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeBecauseItIsNonNullableValueType: case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeParameterBecauseItCouldBeNonNullableValueType: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, expression, semanticModel); break; } case CompilerDiagnosticIdentifiers.ResultOfExpressionIsAlwaysConstantSinceValueIsNeverEqualToNull: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConditionThatIsAlwaysEqualToTrueOrFalse)) { break; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(expression, allowedStyles: NullCheckStyles.ComparisonToNull); if (!nullCheck.Success) { break; } CodeAction codeAction = CodeAction.Create( "Remove condition", cancellationToken => { cancellationToken.ThrowIfCancellationRequested(); SyntaxNode newRoot = RemoveCondition(root, expression, nullCheck.Style == NullCheckStyles.NotEqualsToNull); cancellationToken.ThrowIfCancellationRequested(); return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot))); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.OnlyAssignmentCallIncrementDecrementAndNewObjectExpressionsCanBeUsedAsStatement: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveParentheses) && expression is ParenthesizedExpressionSyntax parenthesizedExpression && parenthesizedExpression?.IsMissing == false) { CodeAction codeAction = CodeActionFactory.RemoveParentheses(context.Document, parenthesizedExpression, equivalenceKey: GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (expression.Parent is ArrowExpressionClauseSyntax arrowExpresssionClause) { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression)) { break; } ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } else if (expression.Parent is ExpressionStatementSyntax expressionStatement) { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList) && expression.IsKind( SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { SyntaxNode invocationExpression = InvocationExpression(expression); if (semanticModel.GetSpeculativeMethodSymbol(expression.SpanStart, invocationExpression) != null) { CodeAction codeAction = CodeAction.Create( "Add argument list", cancellationToken => context.Document.ReplaceNodeAsync(expression, invocationExpression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddArgumentList)); context.RegisterCodeFix(codeAction, diagnostic); } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceComparisonWithAssignment) && expression.IsKind(SyntaxKind.EqualsExpression)) { BinaryExpressionInfo info = SyntaxInfo.BinaryExpressionInfo(expression); if (!info.Success) { break; } ITypeSymbol leftTypeSymbol = semanticModel.GetTypeSymbol(info.Left, context.CancellationToken); if (leftTypeSymbol?.IsErrorType() != false) { break; } if (!semanticModel.IsImplicitConversion(info.Right, leftTypeSymbol)) { break; } CodeAction codeAction = CodeAction.Create( "Replace comparison with assignment", cancellationToken => { AssignmentExpressionSyntax simpleAssignment = SimpleAssignmentExpression(info.Left, info.Right).WithTriviaFrom(expression); return(context.Document.ReplaceNodeAsync(expression, simpleAssignment, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceComparisonWithAssignment)); context.RegisterCodeFix(codeAction, diagnostic); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceConditionalExpressionWithIfElse) && (expression is ConditionalExpressionSyntax conditionalExpression) && conditionalExpression.Condition != null) { ExpressionSyntax whenTrue = conditionalExpression.WhenTrue; ExpressionSyntax whenFalse = conditionalExpression.WhenFalse; if (whenTrue != null && whenFalse != null && semanticModel.GetTypeSymbol(whenTrue, context.CancellationToken)?.SpecialType == SpecialType.System_Void && semanticModel.GetTypeSymbol(whenFalse, context.CancellationToken)?.SpecialType == SpecialType.System_Void) { CodeAction codeAction = CodeAction.Create( "Replace ?: with if-else", cancellationToken => { IfStatementSyntax newNode = IfStatement( conditionalExpression.Condition.WalkDownParentheses(), Block(ExpressionStatement(whenTrue)), ElseClause(Block(ExpressionStatement(whenFalse)))); newNode = newNode .WithTriviaFrom(expressionStatement) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(expressionStatement, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceConditionalExpressionWithIfElse)); context.RegisterCodeFix(codeAction, diagnostic); } } if (semanticModel.GetSymbol(expression, context.CancellationToken)?.IsErrorType() != false) { break; } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken); if (typeSymbol?.IsErrorType() != false) { break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.IntroduceLocalVariable) && !expressionStatement.IsEmbedded()) { bool addAwait = typeSymbol.OriginalDefinition.EqualsOrInheritsFromTaskOfT() && semanticModel.GetEnclosingSymbol(expressionStatement.SpanStart, context.CancellationToken).IsAsyncMethod(); CodeAction codeAction = CodeAction.Create( IntroduceLocalVariableRefactoring.GetTitle(expression), cancellationToken => IntroduceLocalVariableRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, addAwait, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceLocalVariable)); context.RegisterCodeFix(codeAction, diagnostic); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.IntroduceField)) { CodeAction codeAction = CodeAction.Create( $"Introduce field for '{expression}'", cancellationToken => IntroduceFieldRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceField)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertType: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceYieldReturnWithForEach) && expression.IsParentKind(SyntaxKind.YieldReturnStatement)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ReplaceYieldReturnWithForEachRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) && expression.IsParentKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement, SyntaxKind.ArrowExpressionClause)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeTypeAccordingToInitializer)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); CodeFixRegistrationResult result = ChangeTypeAccordingToInitializerRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); if (!result.Success) { RemoveAssignmentOfVoidExpression(context, diagnostic, expression, semanticModel); } break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral) && expression?.Kind() == SyntaxKind.StringLiteralExpression) { var literalExpression = (LiteralExpressionSyntax)expression; if (literalExpression.Token.ValueText.Length == 1) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetTypeInfo(expression, context.CancellationToken).ConvertedType?.SpecialType == SpecialType.System_Char) { CodeAction codeAction = CodeAction.Create( "Replace string literal with character literal", cancellationToken => ReplaceStringLiteralWithCharacterLiteralRefactoring.RefactorAsync(context.Document, literalExpression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseYieldReturnInsteadOfReturn) && expression.IsParentKind(SyntaxKind.ReturnStatement)) { var returnStatement = (ReturnStatementSyntax)expression.Parent; SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol containingSymbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken); if (containingSymbol?.Kind == SymbolKind.Method && ((IMethodSymbol)containingSymbol).ReturnType.OriginalDefinition.IsIEnumerableOrIEnumerableOfT()) { CodeAction codeAction = CodeAction.Create( "Use yield return instead of return", cancellationToken => UseYieldReturnInsteadOfReturnRefactoring.RefactorAsync(context.Document, returnStatement, SyntaxKind.YieldReturnStatement, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseYieldReturnInsteadOfReturn)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.LeftHandSideOfAssignmentMustBeVariablePropertyOrIndexer: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstModifier)) { return; } if (!expression.IsKind(SyntaxKind.IdentifierName)) { return; } if (!expression.IsParentKind(SyntaxKind.SimpleAssignmentExpression)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(expression, context.CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.NotAVariable) { return; } if (!(symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is ILocalSymbol localSymbol)) { return; } if (!localSymbol.IsConst) { return; } SyntaxNode node = localSymbol.GetSyntaxOrDefault(context.CancellationToken); if (!node.IsKind(SyntaxKind.VariableDeclarator)) { return; } node = node.Parent; if (!node.IsKind(SyntaxKind.VariableDeclaration)) { return; } node = node.Parent; if (!(node is LocalDeclarationStatementSyntax localDeclaration)) { return; } SyntaxToken constModifier = localDeclaration.Modifiers.Find(SyntaxKind.ConstKeyword); if (!constModifier.IsKind(SyntaxKind.ConstKeyword)) { return; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, localDeclaration, constModifier); break; } case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBeAssignedTo: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeFieldWritable)) { break; } SimpleAssignmentExpressionInfo simpleAssignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression.Parent); if (!simpleAssignment.Success) { return; } if (simpleAssignment.Left != expression) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(expression, context.CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.NotAVariable) { return; } if (!(symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is IFieldSymbol fieldSymbol)) { return; } if (fieldSymbol.DeclaredAccessibility != Accessibility.Private) { return; } if (!(fieldSymbol.GetSyntax().Parent.Parent is FieldDeclarationSyntax fieldDeclaration)) { return; } TypeDeclarationSyntax containingTypeDeclaration = fieldDeclaration.FirstAncestor <TypeDeclarationSyntax>(); if (!expression.Ancestors().Any(f => f == containingTypeDeclaration)) { return; } ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, title: $"Make '{fieldSymbol.Name}' writable"); break; } } } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddComparisonWithBooleanLiteral) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.CreateSingletonArray) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseUncheckedExpression) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstModifier) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseCoalesceExpression) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionThatIsAlwaysEqualToTrueOrFalse) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceLocalVariable) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceField) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseYieldReturnInsteadOfReturn) && !Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) ) { return; } SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindNode(root, context.Span, out ExpressionSyntax expression)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertTypeExplicitConversionExists: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken); ITypeSymbol type = typeInfo.Type; ITypeSymbol convertedType = typeInfo.ConvertedType; if ((type is INamedTypeSymbol namedType) && namedType.ConstructedFrom.SpecialType == SpecialType.System_Nullable_T) { if (convertedType?.IsBoolean() == true || AddComparisonWithBooleanLiteralRefactoring.IsCondition(expression)) { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddComparisonWithBooleanLiteral)) { CodeAction codeAction = CodeAction.Create( AddComparisonWithBooleanLiteralRefactoring.GetTitle(expression), cancellationToken => AddComparisonWithBooleanLiteralRefactoring.RefactorAsync(context.Document, expression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddComparisonWithBooleanLiteral)); context.RegisterCodeFix(codeAction, diagnostic); } } else if (namedType.TypeArguments[0].Equals(convertedType)) { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseCoalesceExpression)) { CodeAction codeAction = CodeAction.Create( "Use coalesce expression", cancellationToken => { ExpressionSyntax defaultValue = convertedType.ToDefaultValueSyntax(semanticModel, expression.SpanStart); ExpressionSyntax newNode = CoalesceExpression(expression.WithoutTrivia(), defaultValue) .WithTriviaFrom(expression) .Parenthesize() .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseCoalesceExpression)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression)) { ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.AddCastExpression)) { CodeFixRegistrator.AddCastExpression(context, diagnostic, expression, convertedType, semanticModel); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.CreateSingletonArray) && type?.IsErrorType() == false && !type.Equals(convertedType) && (convertedType is IArrayTypeSymbol arrayType) && semanticModel.IsImplicitConversion(expression, arrayType.ElementType)) { CodeAction codeAction = CodeAction.Create( "Create singleton array", cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.CreateSingletonArray)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.ConstantValueCannotBeConverted: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseUncheckedExpression)) { break; } CodeAction codeAction = CodeAction.Create( "Use 'unchecked'", cancellationToken => { CheckedExpressionSyntax newNode = CSharpFactory.UncheckedExpression(expression.WithoutTrivia()); newNode = newNode.WithTriviaFrom(expression); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExpressionBeingAssignedMustBeConstant: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConstModifier)) { break; } LocalDeclarationStatementSyntax localDeclarationStatement = GetLocalDeclarationStatement(expression); if (localDeclarationStatement == null) { break; } SyntaxTokenList modifiers = localDeclarationStatement.Modifiers; if (!modifiers.Contains(SyntaxKind.ConstKeyword)) { break; } ModifiersCodeFixes.RemoveModifier(context, diagnostic, localDeclarationStatement, SyntaxKind.ConstKeyword); break; } case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeBecauseItIsNonNullableValueType: case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeParameterBecauseItCouldBeNonNullableValueType: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeInfo(expression, context.CancellationToken).ConvertedType; if (typeSymbol?.SupportsExplicitDeclaration() != true) { break; } CodeAction codeAction = CodeAction.Create( "Replace 'null' with default value", cancellationToken => { ExpressionSyntax newNode = typeSymbol.ToDefaultValueSyntax(semanticModel, expression.SpanStart); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ResultOfExpressionIsAlwaysConstantSinceValueIsNeverEqualToNull: { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.RemoveConditionThatIsAlwaysEqualToTrueOrFalse)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (!NullCheckExpression.TryCreate(expression, semanticModel, out NullCheckExpression nullCheck, context.CancellationToken)) { break; } if (nullCheck.Kind != NullCheckKind.EqualsToNull && nullCheck.Kind != NullCheckKind.NotEqualsToNull) { break; } CodeAction codeAction = CodeAction.Create( "Remove condition", cancellationToken => { SyntaxNode newRoot = RemoveHelper.RemoveCondition(root, expression, nullCheck.Kind == NullCheckKind.NotEqualsToNull); return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot))); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.OnlyAssignmentCallIncrementDecrementAndNewObjectExpressionsCanBeUsedAsStatement: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (expression.Parent is ArrowExpressionClauseSyntax arrowExpresssionClause) { if (!Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression)) { break; } ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } else if (expression.Parent is ExpressionStatementSyntax expressionStatement) { if (!Settings.IsAnyCodeFixEnabled( CodeFixIdentifiers.IntroduceLocalVariable, CodeFixIdentifiers.IntroduceField)) { break; } if (semanticModel.GetSymbol(expression, context.CancellationToken)?.IsErrorType() != false) { break; } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken); if (typeSymbol?.IsErrorType() != false) { break; } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceLocalVariable) && !expressionStatement.IsEmbedded()) { bool addAwait = typeSymbol.IsConstructedFromTaskOfT(semanticModel) && semanticModel.GetEnclosingSymbol(expressionStatement.SpanStart, context.CancellationToken).IsAsyncMethod(); CodeAction codeAction = CodeAction.Create( IntroduceLocalVariableRefactoring.GetTitle(expression), cancellationToken => IntroduceLocalVariableRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, addAwait, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceLocalVariable)); context.RegisterCodeFix(codeAction, diagnostic); } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.IntroduceField)) { CodeAction codeAction = CodeAction.Create( $"Introduce field for '{expression}'", cancellationToken => IntroduceFieldRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceField)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertType: { if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); break; } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral) && expression?.IsKind(SyntaxKind.StringLiteralExpression) == true) { var literalExpression = (LiteralExpressionSyntax)expression; if (literalExpression.Token.ValueText.Length == 1) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetTypeInfo(expression, context.CancellationToken).ConvertedType?.IsChar() == true) { CodeAction codeAction = CodeAction.Create( "Replace string literal with character literal", cancellationToken => ReplaceStringLiteralWithCharacterLiteralRefactoring.RefactorAsync(context.Document, literalExpression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsCodeFixEnabled(CodeFixIdentifiers.UseYieldReturnInsteadOfReturn) && expression.IsParentKind(SyntaxKind.ReturnStatement)) { var returnStatement = (ReturnStatementSyntax)expression.Parent; SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol containingSymbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken); if (containingSymbol?.IsKind(SymbolKind.Method) == true && ((IMethodSymbol)containingSymbol).ReturnType?.IsIEnumerableOrConstructedFromIEnumerableOfT() == true) { CodeAction codeAction = CodeAction.Create( "Use yield return instead of return", cancellationToken => UseYieldReturnInsteadOfReturnRefactoring.RefactorAsync(context.Document, returnStatement, SyntaxKind.YieldReturnStatement, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseYieldReturnInsteadOfReturn)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } } } }