我编写了一个CSharpSyntaxRewriter
用于从方法中删除属性的文件,但是当我从方法中删除所有属性时,我正在努力保留属性之前的任何东西(直到前一个方法).
这适用于具有多个属性的方法,但不适用于只有一个属性.
这是一个最小的repro:
void Main()
{
var code = @"namespace P
{
class Program
{
public void NoAttributes() { }
//???
[TestCategory(""Atomic"")]
public void OneAtt1() { }
[TestCategory(""Atomic"")]
public void OneAtt2() { }
[TestMethod, TestCategory(""Atomic"")]
public void TwoAtts() { }
}
}";
var tree = CSharpSyntaxTree.ParseText(code);
var rewriter = new AttributeRemoverRewriter();
var rewrittenRoot = rewriter.Visit(tree.GetRoot());
Console.WriteLine(rewrittenRoot.GetText().ToString());
}
public class AttributeRemoverRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitAttributeList(AttributeListSyntax attributeList)
{
var nodesToRemove =
attributeList
.Attributes
.Where(att => (att.Name as IdentifierNameSyntax).Identifier.Text.StartsWith("TestCategory"))
.ToArray();
if (nodesToRemove.Length == attributeList.Attributes.Count)
{
//Remove the entire attribute
return
attributeList
.RemoveNode(attributeList, SyntaxRemoveOptions.KeepNoTrivia);
}
else
{
//Remove just the matching ones recursively
foreach (var node in nodesToRemove)
return
VisitAttributeList(attributeList.RemoveNode(node, SyntaxRemoveOptions.KeepNoTrivia));
}
return
base.VisitAttributeList(attributeList);
}
}
Run Code Online (Sandbox Code Playgroud)
完整版本在我的要点(在任何人指出任何其他问题之前).
预期产出是:
namespace P
{
class Program
{
public void NoAttributes() { }
//???
public void OneAtt1() { }
public void OneAtt2() { }
[TestMethod]
public void TwoAtts() { }
}
}
Run Code Online (Sandbox Code Playgroud)
实际输出是:
namespace P
{
class Program
{
public void NoAttributes() { }
public void OneAtt1() { }
public void OneAtt2() { }
[TestMethod]
public void TwoAtts() { }
}
}
Run Code Online (Sandbox Code Playgroud)
关于我需要做什么来保持空白(甚至评论!!)的任何想法?
我已经把Trivia
我想到的每一个组合弄乱了.更改Roslyn代码库SyntaxRemoveOptions
中NullReferenceException
s 的结果并使用*Trivia
扩展方法导致属性不再被删除 - 只是空格.
就像我在评论中所说的那样,对我来说,这看起来像是罗斯林的一个错误。如果您愿意,可以报告该问题并使用以下解决方法。
我只是尝试在方法级别而不是属性级别重写。(您可以对属性使用类似的方法)
public class AttributeRemoverRewriter : CSharpSyntaxRewriter
{
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
var newAttributes = new SyntaxList<AttributeListSyntax>();
foreach (var attributeList in node.AttributeLists)
{
var nodesToRemove =
attributeList
.Attributes
.Where(att => (att.Name as IdentifierNameSyntax).Identifier.Text.StartsWith("TestCategory"))
.ToArray();
if (nodesToRemove.Length == attributeList.Attributes.Count)
{
//Do not add the attribute to the list. It's being removed completely.
}
else
{
//We want to remove only some of the attributes
var newAttribute = (AttributeListSyntax)VisitAttributeList(attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia));
newAttributes = newAttributes.Add(newAttribute);
}
}
//Get the leading trivia (the newlines and comments)
var leadTriv = node.GetLeadingTrivia();
node = node.WithAttributeLists(newAttributes);
//Append the leading trivia to the method
node = node.WithLeadingTrivia(leadTriv);
return node;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出。leadTriv
如果您想删除评论,可以进一步过滤。
请注意,这不包括某些……不正当的情况:
[TestCategory(""Atomic"")]
#if Debug
#endif
/*Trivia in unfortunate places*/
[TestCategory("test")]
public void OneAtt2() { }
Run Code Online (Sandbox Code Playgroud)
您将失去属性之间的琐事。在构建重写器时,琐事是最难做好的事情之一。