gpt4 book ai didi

c# - 用 Roslyn 中的节点替换琐事

转载 作者:太空狗 更新时间:2023-10-29 20:30:03 26 4
gpt4 key购买 nike

例如,我的 C# 代码文件中有以下文档注释:

/// add k+5

我想用节点REPLACE

_tst.AddElement(k+5);

如何使用 C#/Roslyn 来实现?我找到了如何添加这一行,但没有找到如何替换。我添加节点的代码:

public static MethodDeclarationSyntax getChangedNode(MethodDeclarationSyntax method)
{
var newmethod = method;
var TestEntryArgName = "_tst";

/* Adding _tst.AddElement(i); */
foreach (var s in newmethod.Body.DescendantNodes())
{
SyntaxTrivia st = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " ");
bool fl = false;
bool before = true;
var lt = s.GetLeadingTrivia();

foreach (var triviaEntry in lt)
{
if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia)
{
fl = true;
st = triviaEntry;
break;
}
}

if (!fl)
{
lt = s.GetTrailingTrivia();
before = false;
foreach (var triviaEntry in lt)
{
if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia)
{
fl = true;
st = triviaEntry;
break;
}
}
if (!fl) continue;
}

var commentContents = st.ToString();
char[] delim = { ' ', '\n', '\t', '\r' };
var ar = commentContents.Split(delim, StringSplitOptions.RemoveEmptyEntries);
if (ar.Length != 2 || ar[0] != "add") continue;

var lineToAdd = TestEntryArgName + ".AddElement(" + ar[1] + ")";
var linelist = new List<ExpressionStatementSyntax>();
linelist.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(lineToAdd)));

var childlist = s.Parent.ChildNodes();

foreach (var si in childlist)
{
if (s != si) continue;
if (before) newmethod = newmethod.InsertNodesBefore(si, linelist);
else newmethod = newmethod.InsertNodesAfter(si, linelist);
break;
}

break;
}

return newmethod;
}

我需要替换我的方法中的所有此类注释。该函数只插入节点,并且只插入一次。

编辑。此刻,我得到了以下解决方案,但它似乎过于复杂且不明显......

   public static MethodDeclarationSyntax getChangedNode(MethodDeclarationSyntax method)
{
var TestEntryArgName = "__tst";
/* Adding last param */
var parlist = method.ChildNodes().OfType<ParameterListSyntax>().First();
var newparlist = parlist.AddParameters(SyntaxFactory.Parameter(
SyntaxFactory.Identifier(TestEntryArgName))
.WithType(SyntaxFactory.ParseTypeName("Heap ")));
var newmethod = method.ReplaceNode(parlist, newparlist);

/* Adding __tst.AddElement(i); */
while (true) {
IEnumerable<SyntaxNode> desc;
bool triviaFound;
desc = newmethod.Body.DescendantNodes();
triviaFound = false;
foreach (var s in desc)
{
SyntaxTrivia st = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " ");
bool fl = false;
bool before = true;
var lt = s.GetLeadingTrivia();

foreach (var triviaEntry in lt)
{
if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia)
{
fl = true;
st = triviaEntry;
break;
}
}

if (!fl)
{
lt = s.GetTrailingTrivia();
before = false;
foreach (var triviaEntry in lt)
{
if (triviaEntry.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia)
{
fl = true;
st = triviaEntry;
break;
}
}
if (!fl) continue;
}

var commentContents = st.ToString();
char[] delim = { ' ', '\n', '\t', '\r' };
var ar = commentContents.Split(delim, StringSplitOptions.RemoveEmptyEntries);
if (ar.Length != 2 || ar[0] != "add") continue;

var lineToAdd = TestEntryArgName + ".AddElement(" + ar[1] + ")";
var linelist = new List<ExpressionStatementSyntax>();
linelist.Add(SyntaxFactory.ExpressionStatement(SyntaxFactory.ParseExpression(lineToAdd)));

var childlist = s.Parent.ChildNodes();

foreach (var si in childlist)
{
if (s != si) continue;
if (before) newmethod = newmethod.InsertNodesBefore(si, linelist);
else newmethod = newmethod.InsertNodesAfter(si, linelist);
break;
}

var newTrvias = newmethod.DescendantTrivia().Where((t) =>
{
if (t.Kind() != SyntaxKind.SingleLineDocumentationCommentTrivia)
return false;
var arr = t.ToString().Split(delim, StringSplitOptions.RemoveEmptyEntries);
return arr.Length == 2 && arr[0] == "add";
});

newmethod = newmethod.ReplaceTrivia(newTrvias.First(), SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " "));
triviaFound = true;
break;
}
if (!triviaFound) break;
}
return newmethod;
}

最佳答案

您正在寻找的可能是 CSharpSyntaxRewriter。这是 roslyn 中的一个类,它访问您代码的句法模型中的每个节点、标记和琐事。您可以制作自己的重写器,它会覆盖 VisitTrivia 并返回您想要获取的表达式。例如:

    public class MyRewriter : CSharpSyntaxRewriter
{
public MyRewriter(): base(true)
{
}
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
{
if(trivia.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia)
{
string xml = trivia.ToFullString();

var TestEntryArgName = "__tst";

char[] delim = { ' ', '\n', '\t', '\r' };
var ar = xml.Split(delim, StringSplitOptions.RemoveEmptyEntries);
if (ar.Length != 3 || ar[1] != "add")
{
return base.VisitTrivia(trivia);
}
var lineToAdd = TestEntryArgName + ".AddElement(" + ar[2] + ")";

var expression = SyntaxFactory.SyntaxTrivia(SyntaxKind.SingleLineCommentTrivia, lineToAdd);

return expression;
}
return base.VisitTrivia(trivia);
}
}

示例使用:

    var myRewriter = new MyRewriter();

string code = "";

using (StreamReader sr = new StreamReader("Program.cs"))
{
code = sr.ReadToEnd();
}
var tree = CSharpSyntaxTree.ParseText(code);
var node = tree.GetRoot();


using(StreamWriter sw = new StreamWriter("Program.cs"))
{
sw.Write(myRewriter.Visit(node));
}

关于c# - 用 Roslyn 中的节点替换琐事,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38425441/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com