移动项目后,Roslyn Vsix停止了工作

时间:2017-06-14 15:20:16

标签: c# roslyn code-analysis

我有一个工作的Roslyn VSIX项目,用于分析可以本地化的资源。在将项目移动到新位置之前,一切正常。

分析器似乎仍然运行并触发代码修复,但是代码操作永远不会注册到visual studio中,因此出于某种原因没有选项可用于该修复。

我的分析器:

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ConstDiagnosticAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "Viventium.Localization.Tools.ConstantToResource";

    // You can change these strings in the Resources.resx file. If you do not want your analyzer to be localize-able, you can use regular strings for Title and MessageFormat.
    // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Localizing%20Analyzers.md for more on localization
    private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.ConstAnalyzerTitle), Resources.ResourceManager, typeof(Resources));
    private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.ConstAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
    private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.ConstAnalyzerDescription), Resources.ResourceManager, typeof(Resources));
    private const string Category = "Naming";

    private static ResourceLocalizationRule localizationRule = new ResourceLocalizationRule();

    private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

    public override void Initialize(AnalysisContext context)
    {
        context.RegisterSyntaxNodeAction(AnalyzeConstDeclaration, SyntaxKind.FieldDeclaration);
    }

    public static void AnalyzeConstDeclaration(SyntaxNodeAnalysisContext context)
    {
        var fieldDeclaration = (FieldDeclarationSyntax)context.Node;

        if (false == IsValidConstDeclaration(context, fieldDeclaration))
        {
            return;
        }

        var firstVariable = fieldDeclaration.Declaration.Variables.FirstOrDefault();
        var firstSymbol = context.SemanticModel.GetDeclaredSymbol(firstVariable);

        context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation(), firstSymbol.Name));
    }

    private static bool VariableIsInResx(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax fieldDeclaration)
    {
        var solution = context.GetSolution();
        var documentPropertyMap = PropertyMapCache.GetDocumentPropertyMap(solution);

        return localizationRule.IsFieldDeclaredInResx(fieldDeclaration, documentPropertyMap);
    }

    private static bool IsValidConstDeclaration(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax fieldDeclaration)
    {
        if (false == fieldDeclaration.Modifiers.Any(SyntaxKind.ConstKeyword))
        {
            return false;
        }

        if (fieldDeclaration.Declaration.Variables.Count > 1)
        {
            return false;
        }

        var declaredVariable = fieldDeclaration.Declaration.Variables.FirstOrDefault();

        var initializer = declaredVariable.Initializer;
        if (initializer == null)
        {
            return false;
        }

        var constantValue = context.SemanticModel.GetConstantValue(initializer.Value);
        if (!constantValue.HasValue)
        {
            return false;
        }

        var variableTypeName = fieldDeclaration.Declaration.Type;
        var variableType = context.SemanticModel.GetTypeInfo(variableTypeName).ConvertedType;

        if (variableType.SpecialType != SpecialType.System_String)
        {
            return false;
        }

        return true;
    }
}

修复提供者:

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ConstantToResourceCodeFixProvider)), Shared]
public class ConstantToResourceCodeFixProvider : CodeFixProvider
{
    #region Consts

    private const string title = "Convert Constant Use Resources";

    #endregion

    #region CodeFixProvider Overrides

    public sealed override ImmutableArray<string> FixableDiagnosticIds
    {
        get { return ImmutableArray.Create(ConstDiagnosticAnalyzer.DiagnosticId); }
    }

    public sealed override FixAllProvider GetFixAllProvider()
    {
        // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers
        return WellKnownFixAllProviders.BatchFixer;
    }

    public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

        // TODO: Replace the following code with your own analysis, generating a CodeAction for each fix to suggest
        var diagnostic = context.Diagnostics.First();
        var diagnosticSpan = diagnostic.Location.SourceSpan;

        // Find the type declaration identified by the diagnostic.
        var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf<FieldDeclarationSyntax>().First();

        // Register a code action that will invoke the fix.
        context.RegisterCodeFix(
            CodeActionWithPreview.CreateStateful(
                title: title,
                createChangedDocument: (c, isPreview) => this.CheckConstForLocalization(context, declaration, isPreview, c),
                equivalenceKey: title),
            diagnostic);
    }

    #endregion

    #region Analyzer Logic

    private async Task<Document> CheckConstForLocalization(CodeFixContext context, FieldDeclarationSyntax field, bool isPreview, CancellationToken cancellationToken)
    {
        var documentPropertyMap = PropertyMapCache.GetDocumentPropertyMap(context.Document.Project.Solution);

        var localizationRule = new ResourceLocalizationRule();
        var updatedDocument = localizationRule.ConvertDocumentToUseResources(context.Document, documentPropertyMap, field, isPreview, cancellationToken);

        return await updatedDocument;
    }

    #endregion
}

有人可以给我一个关于如何解决这个问题的提示吗?

1 个答案:

答案 0 :(得分:1)

经过数小时的调试后,诊断分析仪不允许有句号...

public const string DiagnosticId = "Viventium_Localization_Tools_ConstantToResource";

修复非常简单我只是将DiagnosticId更改为使用下划线,我用Roslyn

打开了一个错误