我如何调试从未加载过的CodeFixProvider

问题描述 投票:0回答:1

我创建了一个新的“带有代码修复(.NET标准)的分析器”项目,并更新了分析器以检查我想要的内容,并且效果很好。现在,我已经修改了CodeFixProvider,但是在调试时它从未显示。

我已经在FixableDiagnosticIdsGetFixAllProvider()RegisterCodeFixesAsync(CodeFixContext context)的吸气剂中设置了断点,但是当我单击分析仪正确标记的行上的“灯泡”时,都不会调用任何断点。

关于如何弄清为什么它没有被调用的任何想法?

在“带有代码修复(.NET标准)的分析器创建的默认项目中,正确调用了这3个地方的断点。

我的分析器代码

using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace InAnalyzer
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class InAnalyzerAnalyzer : DiagnosticAnalyzer
    {
        public const string CanBeInvokedWithInDiagnosticId = "IN3001";
        public const string DoNotUseInWithParameterDiagnosticId = "IN3002";
        public const string UseInWithParameterDiagnosticId = "IN3003";
        private const string CanBeInvokedWithInCategory = "Performance";
        private const string DoNotUseInWithParameterCategory = "Performance";
        private const string UseInWithParameterCategory = "Performance";

        private static readonly LocalizableString CanBeInvokedWithInTitle = new LocalizableResourceString(nameof(Resources.CanBeInvokedWithInAnalyzerTitle), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString DoNotUseInWithParameterTitle = new LocalizableResourceString( nameof(Resources.DoNotUseInWithParameterAnalyzerTitle), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString UseInWithParameterTitle = new LocalizableResourceString( nameof(Resources.UseInWithParameterAnalyzerTitle), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString CanBeInvokedWithInMessageFormat = new LocalizableResourceString(nameof(Resources.CanBeInvokedWithInAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString DoNotUseInWithParameterMessageFormat = new LocalizableResourceString(nameof(Resources.DoNotUseInWithParameterAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString UseInWithParameterMessageFormat = new LocalizableResourceString(nameof(Resources.UseInWithParameterAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString CanBeInvokedWithInDescription = new LocalizableResourceString(nameof(Resources.CanBeInvokedWithInAnalyzerDescription), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString DoNotUseInWithParameterDescription = new LocalizableResourceString(nameof(Resources.DoNotUseInWithParameterAnalyzerDescription), Resources.ResourceManager, typeof(Resources));
        private static readonly LocalizableString UseInWithParameterDescription = new LocalizableResourceString(nameof(Resources.UseInWithParameterAnalyzerDescription), Resources.ResourceManager, typeof(Resources));

        private static readonly DiagnosticDescriptor CanBeInvokedWithInRule = new DiagnosticDescriptor(
            CanBeInvokedWithInDiagnosticId,
            CanBeInvokedWithInTitle,
            CanBeInvokedWithInMessageFormat,
            CanBeInvokedWithInCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true,
            CanBeInvokedWithInDescription);

        private static readonly DiagnosticDescriptor DoNotUseInWithParameterRule = new DiagnosticDescriptor(
            DoNotUseInWithParameterDiagnosticId,
            DoNotUseInWithParameterTitle,
            DoNotUseInWithParameterMessageFormat,
            DoNotUseInWithParameterCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true,
            DoNotUseInWithParameterDescription);

        private static readonly DiagnosticDescriptor UseInWithParameterRule = new DiagnosticDescriptor(
            UseInWithParameterDiagnosticId,
            UseInWithParameterTitle,
            UseInWithParameterMessageFormat,
            UseInWithParameterCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true,
            UseInWithParameterDescription);

        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(CanBeInvokedWithInRule, DoNotUseInWithParameterRule, UseInWithParameterRule);

        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
            context.EnableConcurrentExecution();

            context.RegisterSyntaxNodeAction(AnalyzeInvocationExpressionSyntaxNode, SyntaxKind.InvocationExpression);
            context.RegisterSyntaxNodeAction(AnalyzeMethodDeclarationSyntaxNode, SyntaxKind.MethodDeclaration);
        }

        private static void AnalyzeInvocationExpressionSyntaxNode(SyntaxNodeAnalysisContext context)
        {
            var node = (InvocationExpressionSyntax) context.Node;
            var symbol = context.SemanticModel.GetSymbolInfo(node).Symbol ??
                context.SemanticModel.GetDeclaredSymbol(node);
            if (symbol is IMethodSymbol methodSymbol)
            {
                var parametersSymbol = methodSymbol.Parameters;
                var argumentSyntaxList = node?.ArgumentList.Arguments;
                if (argumentSyntaxList != null)
                {
                    var argumentSyntaxes = argumentSyntaxList.Value;
                    for (var index = 0; index < parametersSymbol.Length; index++)
                    {
                        var parameterSymbol = parametersSymbol[index];
                        if (parameterSymbol.RefKind == RefKind.In &&
                            parameterSymbol.Type.IsReadOnly &&
                            parameterSymbol.Type.IsValueType &&
                            index < argumentSyntaxes.Count)
                        {
                            var argumentSyntax = argumentSyntaxes[index];
                            if (argumentSyntax?.RefKindKeyword.IsKind(SyntaxKind.InKeyword) == false)
                            {
                                var diagnostic = Diagnostic.Create(
                                    CanBeInvokedWithInRule,
                                    argumentSyntax.Expression.GetLocation(),
                                    parameterSymbol.Name,
                                    parameterSymbol.Type);

                                context.ReportDiagnostic(diagnostic);
                            }
                        }
                    }
                }
            }
        }

        private static void AnalyzeMethodDeclarationSyntaxNode(SyntaxNodeAnalysisContext context)
        {
            var node = (MethodDeclarationSyntax) context.Node;

            var parameterSyntaxList = node?.ParameterList.Parameters;
            if (parameterSyntaxList != null)
            {
                var parameterSyntaxes = parameterSyntaxList.Value;
                for (var index = 0; index < parameterSyntaxes.Count; index++)
                {
                    var parameterSyntax = parameterSyntaxes[index];
                    if (parameterSyntax != null)
                    {
                        var symbol = context.SemanticModel.GetSymbolInfo(parameterSyntax.Type).Symbol;

                        if (symbol is ITypeSymbol typeSymbol)
                        {
                            if (typeSymbol.IsReadOnly &&
                                typeSymbol.IsValueType)
                            {
                                if (!parameterSyntax.Modifiers.Any(SyntaxKind.InKeyword))
                                {
                                    var diagnostic = Diagnostic.Create(
                                        UseInWithParameterRule,
                                        parameterSyntax.Identifier.GetLocation(),
                                        parameterSyntax.Identifier,
                                        typeSymbol);
                                    context.ReportDiagnostic(diagnostic);
                                }
                            }
                            else
                            {
                                foreach (var modifier in parameterSyntax.Modifiers)
                                {
                                    if (modifier.Kind() == SyntaxKind.InKeyword)
                                    {
                                        var diagnostic = Diagnostic.Create(
                                            DoNotUseInWithParameterRule,
                                            modifier.GetLocation(),
                                            parameterSyntax.Identifier,
                                            typeSymbol);
                                        context.ReportDiagnostic(diagnostic);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

我的CodeFixProvider(可能不完整和正确;我想调试并使其正常运行,但甚至无法尝试运行它:):

using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;

namespace InAnalyzer
{
    [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(InAnalyzerCodeFixProvider)), Shared]
    public class InAnalyzerCodeFixProvider : CodeFixProvider
    {
        private const string AddInModifierTitle = "Add 'in' modifier";
        private const string RemoveInModifierTitle = "Remove 'in' modifier";

        public sealed override ImmutableArray<string> FixableDiagnosticIds
            => ImmutableArray.Create(
                InAnalyzerAnalyzer.CanBeInvokedWithInDiagnosticId,
                InAnalyzerAnalyzer.DoNotUseInWithParameterDiagnosticId,
                InAnalyzerAnalyzer.UseInWithParameterDiagnosticId);

        public sealed override FixAllProvider GetFixAllProvider()
        {
            return WellKnownFixAllProviders.BatchFixer;
        }

        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 node = generator.GetDeclaration(token.Parent);
            if (node == null)
            {
                return;
            }

            foreach (var diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                    case InAnalyzerAnalyzer.CanBeInvokedWithInDiagnosticId:
                    case InAnalyzerAnalyzer.UseInWithParameterDiagnosticId:
                        context.RegisterCodeFix(
                            CodeAction.Create(
                                AddInModifierTitle,
                                c => AddInModifierAsync(context.Document, node, c),
                                AddInModifierTitle),
                            diagnostic);
                        break;
                    case InAnalyzerAnalyzer.DoNotUseInWithParameterDiagnosticId:
                        context.RegisterCodeFix(
                            CodeAction.Create(
                                RemoveInModifierTitle,
                                c => RemoveInModifierAsync(context.Document, node, c),
                                RemoveInModifierTitle),
                            diagnostic);
                        break;
                }
            }
        }

        private async Task<Document> AddInModifierAsync(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken)
        {
            var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            switch (node.Parent)
            {
                case ArgumentSyntax argumentSyntax:
                    editor.ReplaceNode(
                        argumentSyntax,
                        argumentSyntax.WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.InKeyword)));
                    break;
                case ParameterSyntax parameterSyntax:
                    editor.ReplaceNode(
                        parameterSyntax,
                        parameterSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.InKeyword)));
                    break;
            }

            return editor.GetChangedDocument();
        }

        private async Task<Document> RemoveInModifierAsync(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken)
        {
            var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false);

            ////switch (node.Parent)
            ////{
            ////    case ArgumentSyntax argumentSyntax:
            ////        editor.ReplaceNode(
            ////            argumentSyntax,
            ////            argumentSyntax.WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.InKeyword)));
            ////        break;
            ////    case ParameterSyntax parameterSyntax:
            ////        editor.ReplaceNode(
            ////            parameterSyntax,
            ////            parameterSyntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.InKeyword)));
            ////        break;
            ////}

            return editor.GetChangedDocument();
        }
    }
}
c# roslyn-code-analysis codefixprovider
1个回答
0
投票

[找到指向thisthe CreateExpInstance tool之后,我尝试重置后缀为“ Roslyn”的实验实例。那并不能解决我的问题,但是后来我删除了带有“ Roslyn”后缀的实验实例,然后尝试再次调试VSIX。这次,调试我的VSIX正常工作并显示了我的CodeFixProvider。

rd / s / q“%LOCALAPPDATA%\ Microsoft \ VisualStudio \ 16.0_0f71fe5bRoslyn”

© www.soinside.com 2019 - 2024. All rights reserved.