Formatting 为什么这个代码修复程序会破坏我的琐事?
我正在开发一个代码修复程序,使用roslyn来修复无效的抛出表达式。代码修复程序通常会执行它应该执行的操作,但是它会使我的代码变形,这将在下一个屏幕截图中显示 代码修复之前的格式 cedefix之后的格式 我尝试格式化生成语法的语法可视化 代码修复Formatting 为什么这个代码修复程序会破坏我的琐事?,formatting,roslyn,Formatting,Roslyn,我正在开发一个代码修复程序,使用roslyn来修复无效的抛出表达式。代码修复程序通常会执行它应该执行的操作,但是它会使我的代码变形,这将在下一个屏幕截图中显示 代码修复之前的格式 cedefix之后的格式 我尝试格式化生成语法的语法可视化 代码修复 有人知道我做错了什么吗?我曾尝试用DocumentEditor进行代码修复(通常不会给我带来这样的麻烦),但我也遇到了同样的问题。像下面这样更改一些代码是可行的,但我不喜欢。似乎奇怪的是,正确地保存琐事只能像这样工作 if (root.Find
有人知道我做错了什么吗?我曾尝试用DocumentEditor进行代码修复(通常不会给我带来这样的麻烦),但我也遇到了同样的问题。像下面这样更改一些代码是可行的,但我不喜欢。似乎奇怪的是,正确地保存琐事只能像这样工作
if (root.FindNode(diagnostic.Location.SourceSpan) is ThrowStatementSyntax throwSyntax)
{
var newThrowStatement = throwSyntax
.WithExpression(SyntaxFactory.ParseExpression(""));
var editor = await DocumentEditor.CreateAsync(context.Document, context.CancellationToken);
editor.ReplaceNode(throwSyntax, newThrowStatement);
return editor.GetChangedDocument();
}
1) 您是否尝试从现有的ThrowStatementSyntax
创建一个新的ThrowStatementSyntax
,而不是创建一个全新的<代码>throwSyntax..WithLeadingTrivia(throwSyntax.ThrowKeyword.LeadingTrivia)代码>2)在应用新的ThrowStatementSyntax
之后,是否尝试规范化根目录中的缩进和空白<代码>重写=重写。规范化空白(…)代码>@GeorgeAlexandria 1)这就是我的代码看起来的样子2)这正确格式化了代码,但使用空格而不是制表符,如中配置的那样IDE@GeorgeAlexandria也不行
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class DoNotRethrowAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = DiagnosticIds.DoNotRethrowAnalyzer.DoNotRethrowRule;
// 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.DoNotRethrowTitle), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.DoNotRethrowMessageFormat), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.DoNotRethrowDescription), Resources.ResourceManager, typeof(Resources));
private const string Category = "Debuggability";
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(AnalyzeThrowExpression, SyntaxKind.ThrowStatement);
}
private void AnalyzeThrowExpression(SyntaxNodeAnalysisContext context)
{
if (context.Node is ThrowStatementSyntax throwSyntax)
{
if (throwSyntax.Expression == null)
return;
if(throwSyntax.Expression is IdentifierNameSyntax throwIdentifier
&& ThrowIdentifierIsIdentifierOfParentClause(throwIdentifier))
context.ReportDiagnostic(Diagnostic.Create(DoNotRethrowAnalyzer.Rule, throwSyntax.ThrowKeyword.GetLocation()));
}
}
private bool ThrowIdentifierIsIdentifierOfParentClause(IdentifierNameSyntax throwIdentifier)
{
var parentCatch = throwIdentifier.NextParentOfType<CatchClauseSyntax>();
if (parentCatch == null || parentCatch.Declaration == null)
return false;
return parentCatch.Declaration.Identifier.ValueText == throwIdentifier.Identifier.ValueText;
}
}
[TestClass]
public class DoNotRethrowTests : CodeFixVerifier
{
//No diagnostics expected to show up
[TestMethod]
public void TestEmptyFile()
{
var test = @"";
VerifyCSharpDiagnostic(test);
}
[TestMethod]
public void InvalidRethrow()
{
var test = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class TYPENAME
{
void Offender(){
throw new Exception(""testa"");
}
void Process(Exception e){
throw new Exception(""testa"");
}
void Source()
{
try
{
Offender();
}
catch (Exception e)
{
Process(e);
throw e;
}
}
}
}";
var expected = new[]
{
new DiagnosticResult
{
Id = DoNotRethrowAnalyzer.DiagnosticId,
Message = Resources.DoNotRethrowMessageFormat,
Severity = DiagnosticSeverity.Warning,
Locations =
new[]
{
new DiagnosticResultLocation("Test0.cs", 30, 6)
}
}
};
VerifyCSharpDiagnostic(test, expected);
var expectedFix = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class TYPENAME
{
void Offender(){
throw new Exception(""testa"");
}
void Process(Exception e){
throw new Exception(""testa"");
}
void Source()
{
try
{
Offender();
}
catch (Exception e)
{
Process(e);
throw;
}
}
}
}";
VerifyCSharpFix(test, expectedFix);
}
class TYPENAME
{
void Offender()
{
throw new Exception("testa");
}
void Process(Exception e)
{
throw new Exception("testa");
}
void Source()
{
try
{
Offender();
}
catch (Exception e)
{
Process(e);
throw;
}
}
}
//Diagnostic and CodeFix both triggered and checked for
[TestMethod]
public void ValidRethrow()
{
var test = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class TYPENAME
{
void Offender(){
throw new Exception(""testa"");
}
void Source()
{
try
{
Offender();
}
catch (Exception e)
{
throw new Exception(""test"", e);
}
}
}
}";
var expected = new DiagnosticResult[0];
VerifyCSharpDiagnostic(test, expected);
}
protected override CodeFixProvider GetCSharpCodeFixProvider()
{
return new DoNotRethrowCodeFixProvider();
}
protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
{
return new DoNotRethrowAnalyzer();
}
}
if (root.FindNode(diagnostic.Location.SourceSpan) is ThrowStatementSyntax throwSyntax)
{
var newThrowStatement = throwSyntax
.WithExpression(SyntaxFactory.ParseExpression(""));
var editor = await DocumentEditor.CreateAsync(context.Document, context.CancellationToken);
editor.ReplaceNode(throwSyntax, newThrowStatement);
return editor.GetChangedDocument();
}