我正在用C#编写程序,用于从代码中提取注释。我正在使用Roslyn编译器来做到这一点。这很棒,因为我只是访问整个抽象语法树并从解决方案中的文件中获取SingleLineComment trivia,MultiLineComment trivia和DocumentationComment trivia语法。但是有一个问题,因为程序员经常写这样的评论:
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
您可以看到这些是三行单行注释,但我希望它们可以作为一条注释从代码中获取。我能用Roslyn实现这个目标吗?或者还有其他办法吗?因为当程序员使用单行注释语法编写多行通知时,这是常见的情况。
我提取评论的代码如下所示:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
namespace RoslynPlay
{
public class CommentStore
{
public List<Comment> Comments { get; } = new List<Comment>();
public void AddCommentTrivia(SyntaxTrivia trivia,
LocationStore commentLocationstore, string fileName)
{
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia)
{
Comments.Add(new SingleLineComment(trivia.ToString(),
trivia.GetLocation().GetLineSpan().EndLinePosition.Line + 1, commentLocationstore)
{
FileName = fileName,
});
}
else if (trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
{
Comments.Add(new MultiLineComment(trivia.ToString(),
trivia.GetLocation().GetLineSpan().StartLinePosition.Line + 1,
trivia.GetLocation().GetLineSpan().EndLinePosition.Line + 1, commentLocationstore)
{
FileName = fileName,
});
}
}
public void AddCommentNode(DocumentationCommentTriviaSyntax node,
LocationStore commentLocationstore, string fileName)
{
Comments.Add(new DocComment(node.ToString(),
node.GetLocation().GetLineSpan().StartLinePosition.Line + 1,
node.GetLocation().GetLineSpan().EndLinePosition.Line,
commentLocationstore)
{
FileName = fileName,
});
}
}
}
并在主主文件(Program.cs)中我从这样的代码中启动注释提取:
string fileContent;
SyntaxTree tree;
SyntaxNode root;
CommentsWalker commentWalker;
MethodsAndClassesWalker methodWalker;
string[] files = Directory.GetFiles(projectPath, $"*.cs", SearchOption.AllDirectories);
var commentStore = new CommentStore();
Console.WriteLine("Reading files...");
ProgressBar progressBar = new ProgressBar(files.Length);
foreach (var file in files)
{
fileContent = File.ReadAllText(file);
string filePath = new Regex($@"{projectPath}\\(.*)$").Match(file).Groups[1].ToString();
tree = CSharpSyntaxTree.ParseText(fileContent);
root = tree.GetRoot();
commentWalker = new CommentsWalker(filePath, commentStore);
commentWalker.Visit(root);
progressBar.UpdateAndDisplay();
}
这里也是评论沃克:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace RoslynPlay
{
public class CommentsWalker : CSharpSyntaxWalker
{
private string _fileName;
private CommentStore _commentStore;
public CommentsWalker(string fileName,
CommentStore commentStore)
: base(SyntaxWalkerDepth.StructuredTrivia)
{
_fileName = fileName;
_commentStore = commentStore;
}
public override void VisitTrivia(SyntaxTrivia trivia)
{
if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia
|| trivia.Kind() == SyntaxKind.MultiLineCommentTrivia)
{
_commentStore.AddCommentTrivia(trivia, _commentLocationStore, _fileName);
}
base.VisitTrivia(trivia);
}
public override void VisitDocumentationCommentTrivia(DocumentationCommentTriviaSyntax node)
{
_commentStore.AddCommentNode(node, _commentLocationStore, _fileName);
base.VisitDocumentationCommentTrivia(node);
}
}
}
问题是因为trivia.Kind()== SyntaxKind.SingleLineCommentTrivia只提取单行注释,但我想将单行注释块提取为一条注释。