我有一个工作的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
}
有人可以给我一个关于如何解决这个问题的提示吗?
答案 0 :(得分:1)
经过数小时的调试后,诊断分析仪不允许有句号...
public const string DiagnosticId = "Viventium_Localization_Tools_ConstantToResource";
修复非常简单我只是将DiagnosticId更改为使用下划线,我用Roslyn
打开了一个错误