private static void AddCodeFixWithNewPublicConstructor(CodeFixContext context, SyntaxNode root,
      Diagnostic diagnostic, ClassDeclarationSyntax classNode)
    {
      // Generated from http://roslynquoter.azurewebsites.net/
      var constructor = SyntaxFactory.ConstructorDeclaration(classNode.Identifier)
        .WithModifiers(
          SyntaxFactory.TokenList(
            SyntaxFactory.Token(SyntaxKind.PublicKeyword)))
        .WithParameterList(SyntaxFactory.ParameterList()
          .WithOpenParenToken(
            SyntaxFactory.Token(SyntaxKind.OpenParenToken))
          .WithCloseParenToken(
            SyntaxFactory.Token(
              SyntaxKind.CloseParenToken)))
        .WithBody(SyntaxFactory.Block()
          .WithOpenBraceToken(
            SyntaxFactory.Token(
              SyntaxKind.OpenBraceToken))
          .WithCloseBraceToken(
            SyntaxFactory.Token(
              SyntaxKind.CloseBraceToken))).NormalizeWhitespace().WithAdditionalAnnotations(Formatter.Annotation);
      var newClassNode = classNode.AddMembers(constructor);
      var newRoot = root.ReplaceNode(classNode, newClassNode);

      context.RegisterCodeFix(
        CodeAction.Create(
          CheckConstructorsAnalyzerPublicConstructorCodeFixConstants.AddPublicConstructorDescription,
          _ => Task.FromResult(context.Document.WithSyntaxRoot(newRoot)),
          CheckConstructorsAnalyzerPublicConstructorCodeFixConstants.AddPublicConstructorDescription), diagnostic);
    }
 public override Task RegisterCodeFixesAsync(CodeFixContext context)
 {
     context.RegisterCodeFix(new MyCodeAction(
         c => FixAsync(context.Document, context.Diagnostics.First(), c)),
         context.Diagnostics);
     return SpecializedTasks.EmptyTask;
 }
    private static void AddCodeFix(CodeFixContext context, SyntaxNode root,
      Diagnostic diagnostic, ClassDeclarationSyntax classNode)
    {
      var newRoot = IsBusinessObjectSerializableMakeSerializableCodeFix.AddAttribute(
        root, classNode, IsBusinessObjectSerializableMakeSerializableCodeFixConstants.SerializableName);

      if (!root.HasUsing(IsBusinessObjectSerializableMakeSerializableCodeFixConstants.SystemNamespace))
      {
        newRoot = (newRoot as CompilationUnitSyntax).AddUsings(
          SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(
            IsBusinessObjectSerializableMakeSerializableCodeFixConstants.SystemNamespace)));
      }

      if (!root.HasUsing(IsBusinessObjectSerializableMakeSerializableCodeFixConstants.CslaSerializationNamespace))
      {
        newRoot = (newRoot as CompilationUnitSyntax).AddUsings(
          SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(
            IsBusinessObjectSerializableMakeSerializableCodeFixConstants.CslaSerializationNamespace)));
      }

      context.RegisterCodeFix(
        CodeAction.Create(
          IsBusinessObjectSerializableMakeSerializableCodeFixConstants.AddSerializableAndUsingDescription,
          _ => Task.FromResult<Document>(context.Document.WithSyntaxRoot(newRoot))), diagnostic);
    }
        /// <inheritdoc/>
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (var diagnostic in context.Diagnostics)
            {
                var documentRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
                SyntaxNode syntax = documentRoot.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true, getInnermostNodeForTie: true);
                if (syntax == null)
                {
                    continue;
                }

                XmlElementSyntax xmlElementSyntax = syntax as XmlElementSyntax;
                if (xmlElementSyntax == null)
                {
                    // We continue even for placeholders if they are empty elements (XmlEmptyElementSyntax)
                    continue;
                }

                if (string.IsNullOrWhiteSpace(xmlElementSyntax.Content.ToString()))
                {
                    // The placeholder hasn't been updated yet.
                    continue;
                }

                context.RegisterCodeFix(
                    CodeAction.Create(
                        DocumentationResources.SA1651CodeFix,
                        cancellationToken => this.GetTransformedDocumentAsync(context.Document, xmlElementSyntax, cancellationToken),
                        nameof(SA1651CodeFixProvider)),
                    diagnostic);
            }
        }
        public async override Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document = context.Document;
            var cancellationToken = context.CancellationToken;
            var span = context.Span;
            var diagnostics = context.Diagnostics;
            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            if (model.IsFromGeneratedCode(cancellationToken))
                return;
            var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            var diagnostic = diagnostics.First();
            var node = root.FindNode(context.Span);
            context.RegisterCodeFix(CodeActionFactory.Create(
                node.Span,
                diagnostic.Severity,
                GettextCatalog.GetString("Add 'new' modifier"),
                token =>
                {
                    SyntaxNode newRoot;
                    if (node.Kind() != SyntaxKind.VariableDeclarator)
                        newRoot = root.ReplaceNode(node, AddNewModifier(node));
                    else //this one wants to be awkward - you can't add modifiers to a variable declarator
                    {
                        SyntaxNode declaringNode = node.Parent.Parent;
                        if (declaringNode is FieldDeclarationSyntax)
                            newRoot = root.ReplaceNode(node.Parent.Parent, (node.Parent.Parent as FieldDeclarationSyntax).AddModifiers(SyntaxFactory.Token(SyntaxKind.NewKeyword)));
                        else //it's an event declaration
                            newRoot = root.ReplaceNode(node.Parent.Parent, (node.Parent.Parent as EventFieldDeclarationSyntax).AddModifiers(SyntaxFactory.Token(SyntaxKind.NewKeyword)));
                    }
                    return Task.FromResult(document.WithSyntaxRoot(newRoot.WithAdditionalAnnotations(Formatter.Annotation)));
                }), diagnostic);
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            var declaration = root.FindNode(context.Span);
            if (declaration == null)
            {
                return;
            }

            // find a Dispose method
            var iDisposableType = model.Compilation.GetSpecialType(SpecialType.System_IDisposable);
            var iDisposable_Dispose = (iDisposableType?.GetMembers(DisposableFieldsShouldBeDisposedAnalyzer.Dispose))?.Single();
            if (iDisposableType == null || iDisposable_Dispose == null)
            {
                return;
            }

            var fieldSymbol = model.GetDeclaredSymbol(declaration, context.CancellationToken) as IFieldSymbol;
            var disposeMethod = fieldSymbol?.ContainingType?.FindImplementationForInterfaceMember(iDisposable_Dispose) as IMethodSymbol;
            if (disposeMethod == null)
            {
                return;
            }

            // We cannot have multiple overlapping diagnostics of this id.
            var diagnostic = context.Diagnostics.Single();

            context.RegisterCodeFix(new MyCodeAction(SystemRuntimeAnalyzersResources.DisposableFieldsShouldBeDisposedMessage,
                                                     async ct => await AddDisposeCall(context.Document, declaration, fieldSymbol, disposeMethod, iDisposableType, iDisposable_Dispose, ct).ConfigureAwait(false)),
                                    diagnostic);
        }
        /// <inheritdoc/>
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            foreach (var diagnostic in context.Diagnostics)
            {
                SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
                if (node == null || node.IsMissing)
                {
                    continue;
                }

                SyntaxNode declarationNode = FindParentDeclarationNode(node);
                if (declarationNode == null)
                {
                    continue;
                }

                context.RegisterCodeFix(
                    CodeAction.Create(
                        MaintainabilityResources.SA1400CodeFix,
                        cancellationToken => GetTransformedDocumentAsync(context.Document, root, declarationNode),
                        nameof(SA1400CodeFixProvider)),
                    diagnostic);
            }
        }
        /// <inheritdoc/>
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            foreach (var diagnostic in context.Diagnostics)
            {
                if (!this.FixableDiagnosticIds.Contains(diagnostic.Id))
                {
                    continue;
                }

                SyntaxNode node = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);
                if (node.IsMissing)
                {
                    continue;
                }

                // Check if we are interested in this node
                node = (SyntaxNode)(node as ParameterListSyntax) ?? node as AttributeArgumentListSyntax;

                if (node != null)
                {
                    context.RegisterCodeFix(CodeAction.Create(MaintainabilityResources.SA1410SA1411CodeFix, token => GetTransformedDocumentAsync(context.Document, root, node), equivalenceKey: nameof(SA1410SA1411CodeFixProvider)), diagnostic);
                }
            }
        }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            var node = root.FindNode(context.Span);
            var fieldNode = GetFieldDeclarationNode(node);
            if(fieldNode == null)
            {
                return;
            }

            var diagnostic = context.Diagnostics.Single();

            // Fix 1: Add a NonSerialized attribute to the field
            context.RegisterCodeFix(new MyCodeAction(AnalyzerPowerPackFixersResources.AddNonSerializedAttribute,
                                        async ct => await AddNonSerializedAttribute(context.Document, fieldNode, ct).ConfigureAwait(false)),
                                    diagnostic);


            // Fix 2: If the type of the field is defined in source, then add the serializable attribute to the type.
            var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
            var fieldSymbol = model.GetDeclaredSymbol(node, context.CancellationToken) as IFieldSymbol;
            var type = fieldSymbol?.Type;
            if (type != null && type.Locations.Any(l => l.IsInSource))
            {
                context.RegisterCodeFix(new MyCodeAction(AnalyzerPowerPackFixersResources.AddSerializableAttribute,
                            async ct => await AddSerializableAttributeToType(context.Document, type, ct).ConfigureAwait(false)),
                        diagnostic);
            }
        }
		public async override Task RegisterCodeFixesAsync(CodeFixContext context)
		{
			var document = context.Document;
			var cancellationToken = context.CancellationToken;
			var diagnostics = context.Diagnostics;
			var root = await document.GetSyntaxRootAsync(cancellationToken);
			var diagnostic = diagnostics.First();
			var node = root.FindNode(context.Span) as BinaryExpressionSyntax;
			if (node == null)
				return;
			StatementSyntax expression = null;
			var ifStatement = node.Parent as IfStatementSyntax;
			if (ifStatement == null)
				return;
            var statement = ifStatement.Statement;
			if (statement is BlockSyntax)
				expression = ((BlockSyntax)statement).Statements[0];
			else
				expression = statement;

			if (expression == null)
				return;

			context.RegisterCodeFix(CodeAction.Create("Remove redundant check", async token => {
				var editor = await DocumentEditor.CreateAsync(document, cancellationToken);
				expression = expression
					.WithOrderedTriviaFromSubTree(ifStatement)
					.WithAdditionalAnnotations(Formatter.Annotation);
                editor.ReplaceNode(ifStatement, expression);
				return editor.GetChangedDocument();
			}, string.Empty), diagnostic);
		}
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var syntaxFactoryService = SyntaxGenerator.GetGenerator(context.Document);
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            var node = root.FindNode(context.Span);

            // We cannot have multiple overlapping diagnostics of this id.
            var diagnostic = context.Diagnostics.Single();

            if (IsInArgumentContext(node))
            {
                // StringComparison.CurrentCulture => StringComparison.Ordinal
                // StringComparison.CurrentCultureIgnoreCase => StringComparison.OrdinalIgnoreCase
                context.RegisterCodeFix(new MyCodeAction(SystemRuntimeAnalyzersResources.UseOrdinalStringComparisonTitle,
                                                         async ct => await FixArgument(context.Document, syntaxFactoryService, root, node).ConfigureAwait(false)),
                                                    diagnostic);
            }
            else if (IsInIdentifierNameContext(node))
            {
                // string.Equals(a, b) => string.Equals(a, b, StringComparison.Ordinal)
                // string.Compare(a, b) => string.Compare(a, b, StringComparison.Ordinal)
                context.RegisterCodeFix(new MyCodeAction(SystemRuntimeAnalyzersResources.UseOrdinalStringComparisonTitle,
                                                         async ct => await FixIdentifierName(context.Document, syntaxFactoryService, root, node, context.CancellationToken).ConfigureAwait(false)),
                                                    diagnostic);
            }
            else if (IsInEqualsContext(node))
            {
                // "a == b" => "string.Equals(a, b, StringComparison.Ordinal)"
                // "a != b" => "!string.Equals(a, b, StringComparison.Ordinal)"
                context.RegisterCodeFix(new MyCodeAction(SystemRuntimeAnalyzersResources.UseOrdinalStringComparisonTitle,
                                async ct => await FixEquals(context.Document, syntaxFactoryService, root, node, context.CancellationToken).ConfigureAwait(false)),
                        diagnostic);
            }
        }
 public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
 {
     var diagnostic = context.Diagnostics.First();
     context.RegisterCodeFix(
         CodeAction.Create("Use ?.Invoke operator and method to fire an event.", ct => UseInvokeAsync(context.Document, diagnostic, ct)), diagnostic);
     return Task.FromResult(0);
 }
 /// <summary>
 /// Register the property fix for property documentation.
 /// </summary>
 /// <param name="root">the syntax root node.</param>
 /// <param name="context">the code fix context, containing the location of the fix.</param>
 /// <param name="diagnostic">the diagnostic, where the invalid code was located.</param>
 private void RegisterMethodDocumentationCodeFix(SyntaxNode root, CodeFixContext context, Diagnostic diagnostic)
 {
     var startNode = root.FindNode(diagnostic.Location.SourceSpan);
     var constructorDeclaration = startNode as ConstructorDeclarationSyntax;
     if (constructorDeclaration != null)
         this.RegisterConstructorCodeFix(constructorDeclaration, root, context, diagnostic);
 }
        /// <inheritdoc/>
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document = context.Document;
            var root = await document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            foreach (var diagnostic in context.Diagnostics)
            {
                if (!diagnostic.Id.Equals(SA1309FieldNamesMustNotBeginWithUnderscore.DiagnosticId))
                {
                    continue;
                }

                var token = root.FindToken(diagnostic.Location.SourceSpan.Start);
                if (token.IsMissing)
                {
                    continue;
                }

                if (!string.IsNullOrEmpty(token.ValueText))
                {
                    var newName = token.ValueText.TrimStart(new[] { '_' });

                    if (string.IsNullOrEmpty(newName))
                    {
                        // The variable consisted of only underscores. In this case we cannot
                        // generate a valid variable name and thus will not offer a code fix.
                        continue;
                    }

                    context.RegisterCodeFix(CodeAction.Create(string.Format(NamingResources.SA1309CodeFix, newName), cancellationToken => RenameHelper.RenameSymbolAsync(document, root, token, newName, cancellationToken), equivalenceKey: nameof(SA1309CodeFixProvider)), diagnostic);
                }
            }
        }
 public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
 {
     var diagnostic = context.Diagnostics.First();
     context.RegisterCodeFix(
         CodeAction.Create("Call GC.SuppressFinalize", ct => AddSuppressFinalizeAsync(context.Document, diagnostic, ct), nameof(DisposablesShouldCallSuppressFinalizeCodeFixProvider)), diagnostic);
     return Task.FromResult(0);
 }
    public async Task VerifyGetFixesWhenUsingSystemDoesNotExist()
    {
      var code = File.ReadAllText(
        $@"Targets\{nameof(IsBusinessObjectSerializableMakeSerializableCodeFixTests)}.{(nameof(this.VerifyGetFixesWhenUsingSystemDoesNotExist))}.cs");
      var document = TestHelpers.Create(code);
      var tree = await document.GetSyntaxTreeAsync();
      var diagnostics = await TestHelpers.GetDiagnosticsAsync(code, new IsBusinessObjectSerializableAnalyzer());
      var sourceSpan = diagnostics[0].Location.SourceSpan;

      var actions = new List<CodeAction>();
      var codeActionRegistration = new Action<CodeAction, ImmutableArray<Diagnostic>>(
        (a, _) => { actions.Add(a); });

      var fix = new IsBusinessObjectSerializableMakeSerializableCodeFix();
      var codeFixContext = new CodeFixContext(document, diagnostics[0],
        codeActionRegistration, new CancellationToken(false));
      await fix.RegisterCodeFixesAsync(codeFixContext);

      Assert.AreEqual(2, actions.Count, nameof(actions.Count));

      await TestHelpers.VerifyActionAsync(actions,
        IsBusinessObjectSerializableMakeSerializableCodeFixConstants.AddSystemSerializableDescription, document,
        tree, $"{Environment.NewLine}[System.Serializable]");
      await TestHelpers.VerifyActionAsync(actions,
        IsBusinessObjectSerializableMakeSerializableCodeFixConstants.AddSerializableAndUsingDescription, document,
        tree, $"using System;{Environment.NewLine}{Environment.NewLine}[Serializable]");
    }
    public override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
      var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

      if (context.CancellationToken.IsCancellationRequested)
      {
        return;
      }

      var diagnostic = context.Diagnostics.First();
      var classNode = root.FindNode(diagnostic.Location.SourceSpan) as ClassDeclarationSyntax;

      if (context.CancellationToken.IsCancellationRequested)
      {
        return;
      }

      var hasNonPublicNoArgumentConstructor = bool.Parse(diagnostic.Properties[PublicNoArgumentConstructorIsMissingConstants.HasNonPublicNoArgumentConstructor]);

      if(hasNonPublicNoArgumentConstructor)
      {
        CheckConstructorsAnalyzerPublicConstructorCodeFix.AddCodeFixWithUpdatingNonPublicConstructor(
          context, root, diagnostic, classNode);
      }
      else
      {
        CheckConstructorsAnalyzerPublicConstructorCodeFix.AddCodeFixWithNewPublicConstructor(
          context, root, diagnostic, classNode);
      }
    }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            var token = root.FindToken(context.Span.Start);
            if (!token.Span.IntersectsWith(context.Span))
            {
                return;
            }

            var generator = SyntaxGenerator.GetGenerator(context.Document);
            var classDecl = generator.GetDeclaration(token.Parent);
            if (classDecl == null)
            {
                return;
            }

            // Register fixes.

            // 1) Apply C# DiagnosticAnalyzerAttribute.
            var title = string.Format(CodeAnalysisDiagnosticsResources.ApplyDiagnosticAnalyzerAttribute_1, LanguageNames.CSharp);
            AddFix(title, context, root, classDecl, generator, LanguageNames.CSharp);

            // 2) Apply VB DiagnosticAnalyzerAttribute.
            title = string.Format(CodeAnalysisDiagnosticsResources.ApplyDiagnosticAnalyzerAttribute_1, LanguageNames.VisualBasic);
            AddFix(title, context, root, classDecl, generator, LanguageNames.VisualBasic);

            // 3) Apply both C# and VB DiagnosticAnalyzerAttributes.
            title = string.Format(CodeAnalysisDiagnosticsResources.ApplyDiagnosticAnalyzerAttribute_2, LanguageNames.CSharp, LanguageNames.VisualBasic);
            AddFix(title, context, root, classDecl, generator, LanguageNames.CSharp, LanguageNames.VisualBasic);
        }
		public async Task GetFixes()
		{
			var code =
@"using System.ServiceModel;

public class AClass
{
	[OperationContract(IsOneWay = true)]
	public string AMethod() { return string.Empty; }
}";

			var document = TestHelpers.Create(code);
			var tree = await document.GetSyntaxTreeAsync();
			var diagnostics = await TestHelpers.GetDiagnosticsAsync(
				code, new IsOneWayOperationAnalyzer());
			var sourceSpan = diagnostics[0].Location.SourceSpan;

			var actions = new List<CodeAction>();
			var codeActionRegistration = new Action<CodeAction, ImmutableArray<Diagnostic>>(
			  (a, _) => { actions.Add(a); });

			var fix = new IsOneWayOperationMakeIsOneWayFalseCodeFix();
			var codeFixContext = new CodeFixContext(document, diagnostics[0],
			  codeActionRegistration, new CancellationToken(false));
			await fix.RegisterCodeFixesAsync(codeFixContext);

			Assert.Equal(1, actions.Count);

			await TestHelpers.VerifyActionAsync(actions,
			  IsOneWayOperationMakeIsOneWayFalseCodeFixConstants.Description, document,
			  tree, new[] { "fals" });
		}
 private void AddFix(string codeFixTitle, CodeFixContext context, SyntaxNode root, SyntaxNode classDecl, SyntaxGenerator generator, params string[] languages)
 {
     var fix = new MyCodeAction(
         codeFixTitle,
         c => GetFix(context.Document, root, classDecl, generator, languages));
     context.RegisterCodeFix(fix, context.Diagnostics);
 }
		public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
		{
			var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

			if (context.CancellationToken.IsCancellationRequested)
			{
				return;
			}

			var diagnostic = context.Diagnostics.First();
			var diagnosticSpan = diagnostic.Location.SourceSpan;

			var nowToken = root.FindToken(diagnosticSpan.Start)
				.Parent.AncestorsAndSelf().OfType<IdentifierNameSyntax>().First().GetFirstToken();

			var utcNowToken = SyntaxFactory.Identifier(nowToken.LeadingTrivia,
				"UtcNow", nowToken.TrailingTrivia);

			var newRoot = root.ReplaceToken(nowToken, utcNowToken);

			context.RegisterCodeFix(
				CodeAction.Create(
					FindingDateTimeNowConstants.Title,
					_ => Task.FromResult<Document>(context.Document.WithSyntaxRoot(newRoot))), diagnostic);
		}
 public override sealed Task RegisterCodeFixesAsync(CodeFixContext context)
 {
     var diagnostic = context.Diagnostics.First();
     if (diagnostic.Properties["kind"] == "missingDoc")
         context.RegisterCodeFix(CodeAction.Create(Resources.XmlDocumentationCreateMissingParametersCodeFixProvider_Title, c => FixParametersAsync(context.Document, diagnostic, c)), diagnostic);
     return Task.FromResult(0);
 }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var generator = SyntaxGenerator.GetGenerator(context.Document);
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var declaration = root.FindNode(context.Span);
            declaration = generator.GetDeclaration(declaration);
            if (declaration == null)
            {
                return;
            }

            var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
            var typeSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
            if (typeSymbol?.TypeKind != TypeKind.Class &&
                typeSymbol?.TypeKind != TypeKind.Struct)
            {
                return;
            }

            // We cannot have multiple overlapping diagnostics of this id.
            var diagnostic = context.Diagnostics.Single();

            context.RegisterCodeFix(new MyCodeAction(MicrosoftApiDesignGuidelinesAnalyzersResources.ImplementComparable,
                                                     async ct => await ImplementComparable(context.Document, declaration, typeSymbol, ct).ConfigureAwait(false)),
                                    diagnostic);
        }
        public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var initializer = root.FindNode(diagnosticSpan) as ConstructorInitializerSyntax;
            if (initializer == null)
            {
                return;
            }

            var constructor = initializer.Parent as ConstructorDeclarationSyntax;
            if (constructor == null)
            {
                return;
            }

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
                    {
                        var newRoot = RemoveInitializer(root, constructor);
                        return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                    }),
                context.Diagnostics);
        }
        public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            //  var syntaxNode = root.FindNode(diagnosticSpan);
            //var declaration = root.FindToken(diagnosticSpan.Start);
            // var firstToken = declaration.GetFirstToken();
            // var leadingTrivia = firstToken.LeadingTrivia;
            // var trimmedLocal = declaration.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(SyntaxTriviaList.Empty));
            var cw = new AdhocWorkspace();
            OptionSet options = cw.Options;
            options = options.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, false);
            options = options.WithChangedOption(CSharpFormattingOptions.IndentBlock, false);
            context.RegisterCodeFix(
     CodeAction.Create(
         Title,
        async c =>
         {
             var oldNode = root.FindTrivia(diagnosticSpan.Start);
             var newRoot = root.ReplaceTrivia(oldNode, SyntaxTriviaList.Empty);
             newRoot = newRoot.WithAdditionalAnnotations(Formatter.Annotation);
             newRoot = Formatter.Format(newRoot, new AdhocWorkspace(),options);
             //TODO:Need to remove empty line if it followed by a comment(Formatting).
             return await Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
         }),
     context.Diagnostics);
        }
 public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
 {
     var diagnostic = context.Diagnostics.First();
     context.RegisterCodeFix(CodeAction.Create(
         "Removes redundant comparision", c => RemoveRedundantComparisonAsync(context.Document, diagnostic, c), nameof(SimplifyRedundantBooleanComparisonsCodeFixProvider)), diagnostic);
     return Task.FromResult(0);
 }
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var generator = SyntaxGenerator.GetGenerator(context.Document);
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var declaration = root.FindNode(context.Span);
            declaration = generator.GetDeclaration(declaration);
            if (declaration == null)
            {
                return;
            }

            var model = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);
            var typeSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
            if (typeSymbol == null)
            {
                return;
            }

            // We cannot have multiple overlapping diagnostics of this id.
            var diagnostic = context.Diagnostics.Single();

            context.RegisterCodeFix(new MyCodeAction(SystemRuntimeAnalyzersResources.OverloadOperatorEqualsOnOverridingValueTypeEquals,
                                                     async ct => await ImplementOperatorEquals(context.Document, declaration, typeSymbol, ct).ConfigureAwait(false)),
                                    diagnostic);
        }
        public override sealed async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var diagnostic = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntaxNode = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true);

            var statement = syntaxNode as StatementSyntax;
            var assignment = syntaxNode as AssignmentExpressionSyntax;
            var binary = syntaxNode as BinaryExpressionSyntax;
            if (statement != null ||
                assignment != null ||
                binary != null)
            {
                context.RegisterCodeFix(
                    CodeAction.Create(
                        Title,
                        c =>
                        {
                            var newRoot = CalculateNewRoot(root, diagnostic, statement, assignment, binary);
                            return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
                        }),
                    context.Diagnostics);
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var document = context.Document;
            var span = context.Span;
            var cancellationToken = context.CancellationToken;

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(span.Start);
            if (!token.Span.IntersectsWith(span))
            {
                return;
            }

            var service = document.GetLanguageService<IImplementInterfaceService>();
            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var actions = token.Parent.GetAncestorsOrThis<TypeSyntax>()
                                      .Where(_interfaceName)
                                      .Select(n => service.GetCodeActions(document, model, n, cancellationToken))
                                      .FirstOrDefault(_codeActionAvailable);

            if (_codeActionAvailable(actions))
            {
                context.RegisterFixes(actions, context.Diagnostics);
            }
        }
    public override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
      var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

      context.CancellationToken.ThrowIfCancellationRequested();

      var diagnostic = context.Diagnostics.First();
      var invocationNode = root.FindNode(diagnostic.Location.SourceSpan) as InvocationExpressionSyntax;

      var invocationIdentifier = ((invocationNode.Expression as MemberAccessExpressionSyntax)
        .Expression as IdentifierNameSyntax).Identifier;
      var leadingTrivia = invocationIdentifier.HasLeadingTrivia ? 
        invocationIdentifier.LeadingTrivia : new SyntaxTriviaList();

      var newInvocationIdentifier = invocationIdentifier.WithLeadingTrivia(new SyntaxTriviaList());
      var newInvocationNode = invocationNode.ReplaceToken(invocationIdentifier, newInvocationIdentifier);

      context.CancellationToken.ThrowIfCancellationRequested();

      var simpleAssignmentExpressionNode = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression,
        SyntaxFactory.IdentifierName(newInvocationIdentifier), newInvocationNode)
        .WithLeadingTrivia(leadingTrivia);

      var newRoot = root.ReplaceNode(invocationNode, simpleAssignmentExpressionNode);

      context.RegisterCodeFix(
        CodeAction.Create(
          FindSaveAssignmentIssueAnalyzerAddAssignmentCodeFixConstants.AddAssignmentDescription,
          _ => Task.FromResult(context.Document.WithSyntaxRoot(newRoot)),
          FindSaveAssignmentIssueAnalyzerAddAssignmentCodeFixConstants.AddAssignmentDescription), diagnostic);
    }
Example #31
0
        /// <summary>
        /// General verifier for codefixes.
        /// Creates a Document from the source string, then gets diagnostics on it and applies the relevant codefixes.
        /// Then gets the string after the codefix is applied and compares it with the expected result.
        /// Note: If any codefix causes new diagnostics to show up, the test fails unless allowNewCompilerDiagnostics is set to true.
        /// </summary>
        /// <param name="language">The language the source code is in</param>
        /// <param name="analyzer">The analyzer to be applied to the source code</param>
        /// <param name="codeFixProvider">The codefix to be applied to the code wherever the relevant Diagnostic is found</param>
        /// <param name="oldSource">A class in the form of a string before the CodeFix was applied to it</param>
        /// <param name="newSource">A class in the form of a string after the CodeFix was applied to it</param>
        /// <param name="codeFixIndex">Index determining which codefix to apply if there are multiple</param>
        /// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the CodeFix introduces other warnings after being applied</param>
        private void VerifyFix(string language, DiagnosticAnalyzer analyzer, CodeFixProvider codeFixProvider, string oldSource, string newSource, int?codeFixIndex, bool allowNewCompilerDiagnostics)
        {
            var document            = CreateDocument(oldSource, language);
            var analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document });
            var compilerDiagnostics = GetCompilerDiagnostics(document);
            var attempts            = analyzerDiagnostics.Length;

            for (int i = 0; i < attempts; ++i)
            {
                var actions = new List <CodeAction>();
                var context = new Microsoft.CodeAnalysis.CodeFixes.CodeFixContext(document, analyzerDiagnostics[0], (a, d) => actions.Add(a), CancellationToken.None);
                codeFixProvider.RegisterCodeFixesAsync(context).Wait();

                if (!actions.Any())
                {
                    break;
                }

                if (codeFixIndex != null)
                {
                    document = ApplyFix(document, actions.ElementAt((int)codeFixIndex));
                    break;
                }

                document            = ApplyFix(document, actions.ElementAt(0));
                analyzerDiagnostics = GetSortedDiagnosticsFromDocuments(analyzer, new[] { document });

                var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));

                //check if applying the code fix introduced any new compiler diagnostics
                if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any())
                {
                    // Format and get the compiler diagnostics again so that the locations make sense in the output
                    document = document.WithSyntaxRoot(Formatter.Format(document.GetSyntaxRootAsync().Result, Formatter.Annotation, document.Project.Solution.Workspace));
                    newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, GetCompilerDiagnostics(document));

                    var newCode = GetStringFromDocument(document);

                    Assert.IsTrue(false,
                                  string.Format("Fix introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n",
                                                string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())),
                                                document.GetSyntaxRootAsync().Result.ToFullString()));
                }

                //check if there are analyzer diagnostics left after the code fix
                if (!analyzerDiagnostics.Any())
                {
                    break;
                }
            }

            //after applying all of the code fixes, compare the resulting string to the inputted one
            var actual = GetStringFromDocument(document);

            Assert.AreEqual(newSource, actual);
        }
Example #32
0
        public sealed override async Task RegisterCodeFixesAsync(Microsoft.CodeAnalysis.CodeFixes.CodeFixContext context)
        {
            var diagnostic = context.Diagnostics.First();

            if (!HasValidProperties(diagnostic))
            {
                return;
            }

            var success = Enum.TryParse(diagnostic.Properties[ObsoleteFixerAnalyzer.SyntaxKindKey], false, out SyntaxKind syntaxKind);

            if (!success)
            {
                return;
            }

            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var root           = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            // Find the type declaration identified by the diagnostic.
            var syntax = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().FirstOrDefault(s => s.IsKind(syntaxKind));

            if (!IsSupported(syntax))
            {
                return;
            }

            var replaceWith = diagnostic.Properties[ObsoleteFixerAnalyzer.ReplaceWithKey];

            if (!bool.TryParse(diagnostic.Properties[ObsoleteFixerAnalyzer.IsObsoleteTypeKey], out var isObsoleteTypeKey))
            {
                return;
            }

            // Register a code action that will invoke the fix.
            var title = $"Replace method call with `{replaceWith}`";

            context.RegisterCodeFix(
                CodeAction.Create(
                    title,
                    // todo change to createChangedSolution?
                    c => ReplaceMethodCallsAsync(context.Document, syntax, c, replaceWith, isObsoleteTypeKey),
                    title),
                diagnostic);
        }
Example #33
0
        private async Task<bool> ContainsAnyFixAsync(
            Document document, DiagnosticData diagnostic, CancellationToken cancellationToken)
        {
            var workspaceFixers = ImmutableArray<CodeFixProvider>.Empty;
            var hasAnySharedFixer = _workspaceFixersMap.TryGetValue(document.Project.Language, out var fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers);
            var hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out var projectFixers);

            // TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive
            if (hasAnySharedFixer && document.Project.Solution.Workspace.Kind == WorkspaceKind.Interactive)
            {
                workspaceFixers = workspaceFixers.WhereAsArray(IsInteractiveCodeFixProvider);
                hasAnySharedFixer = workspaceFixers.Any();
            }

            var hasConfigurationFixer =
                _configurationProvidersMap.TryGetValue(document.Project.Language, out var lazyConfigurationProviders) &&
                !lazyConfigurationProviders.Value.IsDefaultOrEmpty;

            if (!hasAnySharedFixer && !hasAnyProjectFixer && !hasConfigurationFixer)
            {
                return false;
            }

            var allFixers = ImmutableArray<CodeFixProvider>.Empty;
            if (hasAnySharedFixer)
            {
                allFixers = workspaceFixers;
            }

            if (hasAnyProjectFixer)
            {
                allFixers = allFixers.AddRange(projectFixers);
            }

            var dx = await diagnostic.ToDiagnosticAsync(document.Project, cancellationToken).ConfigureAwait(false);

            if (hasConfigurationFixer)
            {
                foreach (var lazyConfigurationProvider in lazyConfigurationProviders.Value)
                {
                    if (lazyConfigurationProvider.IsFixableDiagnostic(dx))
                    {
                        return true;
                    }
                }
            }

            var fixes = new List<CodeFix>();
            var context = new CodeFixContext(document, dx,

                // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                (action, applicableDiagnostics) =>
                {
                    // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                    lock (fixes)
                    {
                        fixes.Add(new CodeFix(document.Project, action, applicableDiagnostics));
                    }
                },
                verifyArguments: false,
                cancellationToken: cancellationToken);

            var extensionManager = document.Project.Solution.Workspace.Services.GetRequiredService<IExtensionManager>();

            // we do have fixer. now let's see whether it actually can fix it
            foreach (var fixer in allFixers)
            {
                await extensionManager.PerformActionAsync(fixer, () => fixer.RegisterCodeFixesAsync(context) ?? Task.CompletedTask).ConfigureAwait(false);
                foreach (var fix in fixes)
                {
                    if (!fix.Action.PerformFinalApplicabilityCheck)
                    {
                        return true;
                    }

                    // Have to see if this fix is still applicable.  Jump to the foreground thread
                    // to make that check.
                    await ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true, cancellationToken);
                    cancellationToken.ThrowIfCancellationRequested();

                    var applicable = fix.Action.IsApplicable(document.Project.Solution.Workspace);

                    await TaskScheduler.Default;

                    if (applicable)
                    {
                        return true;
                    }
                }
            }

            return false;
        }
Example #34
0
        private async Task <bool> ContainsAnyFix(Document document, DiagnosticData diagnostic, bool considerSuppressionFixes, CancellationToken cancellationToken)
        {
            ImmutableArray <CodeFixProvider> workspaceFixers = ImmutableArray <CodeFixProvider> .Empty;
            List <CodeFixProvider>           projectFixers   = null;

            Lazy <ImmutableDictionary <DiagnosticId, ImmutableArray <CodeFixProvider> > > fixerMap;
            bool hasAnySharedFixer  = _workspaceFixersMap.TryGetValue(document.Project.Language, out fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers);
            var  hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out projectFixers);

            Lazy <ISuppressionFixProvider> lazySuppressionProvider = null;
            var hasSuppressionFixer =
                considerSuppressionFixes &&
                _suppressionProvidersMap.TryGetValue(document.Project.Language, out lazySuppressionProvider) &&
                lazySuppressionProvider.Value != null;

            if (!hasAnySharedFixer && !hasAnyProjectFixer && !hasSuppressionFixer)
            {
                return(false);
            }

            var allFixers = ImmutableArray <CodeFixProvider> .Empty;

            if (hasAnySharedFixer)
            {
                allFixers = workspaceFixers;
            }

            if (hasAnyProjectFixer)
            {
                allFixers = allFixers.AddRange(projectFixers);
            }

            var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var dx = diagnostic.ToDiagnostic(tree);

            if (hasSuppressionFixer && lazySuppressionProvider.Value.CanBeSuppressed(dx))
            {
                return(true);
            }

            var fixes   = new List <CodeFix>();
            var context = new CodeFixContext(document, dx,

                                             // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                                             (a, d) =>
            {
                // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                lock (fixes)
                {
                    fixes.Add(new CodeFix(a, d));
                }
            },
                                             verifyArguments: false,
                                             cancellationToken: cancellationToken);

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();

            // we do have fixer. now let's see whether it actually can fix it
            foreach (var fixer in allFixers)
            {
                await extensionManager.PerformActionAsync(fixer, () => fixer.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask).ConfigureAwait(false);

                if (!fixes.Any())
                {
                    continue;
                }

                return(true);
            }

            return(false);
        }
Example #35
0
        private async Task <List <CodeFixCollection> > AppendFixesAsync(
            Document document,
            TextSpan span,
            IEnumerable <DiagnosticData> diagnosticDataCollection,
            List <CodeFixCollection> result,
            CancellationToken cancellationToken)
        {
            Lazy <ImmutableDictionary <DiagnosticId, ImmutableArray <CodeFixProvider> > > fixerMap;
            bool hasAnySharedFixer = _workspaceFixersMap.TryGetValue(document.Project.Language, out fixerMap);

            var projectFixersMap   = GetProjectFixers(document.Project);
            var hasAnyProjectFixer = projectFixersMap.Any();

            if (!hasAnySharedFixer && !hasAnyProjectFixer)
            {
                return(result);
            }

            ImmutableArray <CodeFixProvider> workspaceFixers;
            List <CodeFixProvider>           projectFixers;
            var allFixers = new List <CodeFixProvider>();

            foreach (var diagnosticId in diagnosticDataCollection.Select(d => d.Id).Distinct())
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (hasAnySharedFixer && fixerMap.Value.TryGetValue(diagnosticId, out workspaceFixers))
                {
                    allFixers.AddRange(workspaceFixers);
                }

                if (hasAnyProjectFixer && projectFixersMap.TryGetValue(diagnosticId, out projectFixers))
                {
                    allFixers.AddRange(projectFixers);
                }
            }

            var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();
            var diagnostics      = diagnosticDataCollection.Select(data => data.ToDiagnostic(tree)).ToImmutableArray();

            foreach (var fixer in allFixers.Distinct())
            {
                cancellationToken.ThrowIfCancellationRequested();

                Func <Diagnostic, bool> hasFix = (d) => this.GetFixableDiagnosticIds(fixer).Contains(d.Id);
                Func <ImmutableArray <Diagnostic>, Task <IEnumerable <CodeFix> > > getFixes =
                    async(dxs) =>
                {
                    var fixes   = new List <CodeFix>();
                    var context = new CodeFixContext(document, span, dxs,

                                                     // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                                                     (a, d) =>
                    {
                        // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                        lock (fixes)
                        {
                            fixes.Add(new CodeFix(a, d));
                        }
                    },
                                                     verifyArguments: false,
                                                     cancellationToken: cancellationToken);

                    var task = fixer.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask;
                    await task.ConfigureAwait(false);

                    return(fixes);
                };
                await AppendFixesOrSuppressionsAsync(document, span, diagnostics, result, fixer,
                                                     extensionManager, hasFix, getFixes, cancellationToken).ConfigureAwait(false);
            }

            return(result);
        }
Example #36
0
        private async Task <bool> ContainsAnyFix(Document document, DiagnosticData diagnostic, CancellationToken cancellationToken)
        {
            // TODO: We don't return true here if the only available fixes are suppressions.
            // This is to avoid the problem where lightbulb would show up for every green warning
            // squiggle in the editor thereby diluting the promise of the light bulb from
            // "I have a fix" to "I have some action". This is temporary until the editor team exposes
            // some mechanism (e.g. a faded out lightbulb) that would allow us to say "I have an action
            // but not a fix".

            ImmutableArray <CodeFixProvider> workspaceFixers = ImmutableArray <CodeFixProvider> .Empty;
            List <CodeFixProvider>           projectFixers   = null;

            Lazy <ImmutableDictionary <DiagnosticId, ImmutableArray <CodeFixProvider> > > fixerMap;
            bool hasAnySharedFixer  = _workspaceFixersMap.TryGetValue(document.Project.Language, out fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers);
            var  hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out projectFixers);

            if (!hasAnySharedFixer && !hasAnyProjectFixer)
            {
                return(false);
            }

            var allFixers = ImmutableArray <CodeFixProvider> .Empty;

            if (hasAnySharedFixer)
            {
                allFixers = workspaceFixers;
            }

            if (hasAnyProjectFixer)
            {
                allFixers = allFixers.AddRange(projectFixers);
            }

            var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var dx = diagnostic.ToDiagnostic(tree);

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();

            var fixes   = new List <CodeFix>();
            var context = new CodeFixContext(document, dx,

                                             // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                                             (a, d) =>
            {
                // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                lock (fixes)
                {
                    fixes.Add(new CodeFix(a, d));
                }
            },
                                             verifyArguments: false,
                                             cancellationToken: cancellationToken);

            // we do have fixer. now let's see whether it actually can fix it
            foreach (var fixer in allFixers)
            {
                await extensionManager.PerformActionAsync(fixer, () => fixer.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask).ConfigureAwait(false);

                if (!fixes.Any())
                {
                    continue;
                }

                return(true);
            }

            return(false);
        }
Example #37
0
 /// <summary>
 /// Computes one or more fixes for the specified <see cref="CodeFixContext"/>.
 /// </summary>
 public abstract Task RegisterCodeFixesAsync(CodeFixContext context);
Example #38
0
        private async Task <bool> ContainsAnyFix(Document document, DiagnosticData diagnostic, bool considerSuppressionFixes, CancellationToken cancellationToken)
        {
            ImmutableArray <CodeFixProvider> workspaceFixers = ImmutableArray <CodeFixProvider> .Empty;
            List <CodeFixProvider>           projectFixers   = null;

            Lazy <ImmutableDictionary <DiagnosticId, ImmutableArray <CodeFixProvider> > > fixerMap;
            bool hasAnySharedFixer  = _workspaceFixersMap.TryGetValue(document.Project.Language, out fixerMap) && fixerMap.Value.TryGetValue(diagnostic.Id, out workspaceFixers);
            var  hasAnyProjectFixer = GetProjectFixers(document.Project).TryGetValue(diagnostic.Id, out projectFixers);

            // TODO (https://github.com/dotnet/roslyn/issues/4932): Don't restrict CodeFixes in Interactive
            if (hasAnySharedFixer && document.Project.Solution.Workspace.Kind == WorkspaceKind.Interactive)
            {
                workspaceFixers   = workspaceFixers.WhereAsArray(IsInteractiveCodeFixProvider);
                hasAnySharedFixer = workspaceFixers.Any();
            }

            Lazy <ISuppressionFixProvider> lazySuppressionProvider = null;
            var hasSuppressionFixer =
                considerSuppressionFixes &&
                _suppressionProvidersMap.TryGetValue(document.Project.Language, out lazySuppressionProvider) &&
                lazySuppressionProvider.Value != null;

            if (!hasAnySharedFixer && !hasAnyProjectFixer && !hasSuppressionFixer)
            {
                return(false);
            }

            var allFixers = ImmutableArray <CodeFixProvider> .Empty;

            if (hasAnySharedFixer)
            {
                allFixers = workspaceFixers;
            }

            if (hasAnyProjectFixer)
            {
                allFixers = allFixers.AddRange(projectFixers);
            }

            var dx = await diagnostic.ToDiagnosticAsync(document.Project, cancellationToken).ConfigureAwait(false);

            if (hasSuppressionFixer && lazySuppressionProvider.Value.CanBeSuppressedOrUnsuppressed(dx))
            {
                return(true);
            }

            var fixes   = new List <CodeFix>();
            var context = new CodeFixContext(document, dx,

                                             // TODO: Can we share code between similar lambdas that we pass to this API in BatchFixAllProvider.cs, CodeFixService.cs and CodeRefactoringService.cs?
                                             (action, applicableDiagnostics) =>
            {
                // Serialize access for thread safety - we don't know what thread the fix provider will call this delegate from.
                lock (fixes)
                {
                    fixes.Add(new CodeFix(document.Project, action, applicableDiagnostics));
                }
            },
                                             verifyArguments: false,
                                             cancellationToken: cancellationToken);

            var extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>();

            // we do have fixer. now let's see whether it actually can fix it
            foreach (var fixer in allFixers)
            {
                await extensionManager.PerformActionAsync(fixer, () => fixer.RegisterCodeFixesAsync(context) ?? SpecializedTasks.EmptyTask).ConfigureAwait(false);

                foreach (var fix in fixes)
                {
                    if (!fix.Action.PerformFinalApplicabilityCheck)
                    {
                        return(true);
                    }

                    // Have to see if this fix is still applicable.  Jump to the foreground thread
                    // to make that check.
                    var applicable = await Task.Factory.StartNew(() =>
                    {
                        this.AssertIsForeground();
                        return(fix.Action.IsApplicable(document.Project.Solution.Workspace));
                    },
                                                                 cancellationToken, TaskCreationOptions.None, this.ForegroundTaskScheduler).ConfigureAwait(false);

                    this.AssertIsBackground();

                    if (applicable)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }