如何解决重写CompilationUnit时保留类型,字段和方法注释
TL; DR:在基于给定类型创建新的java类型时,如何保留Javadoc,行注释和块注释?
长:
我正在使用JDT使用无头蚀应用程序将基于有害基类的无限数量的类型(java类)批量转换为Java枚举类型。我的方法是根据类型信息创建一个新的EnumDeclaration
,并基于初始类类型的EnumConstantDeclaration
(排除FieldDeclaration
)添加serialVersionUID
。之后,我通过简单地将原始MethodDeclaration
的克隆添加到新创建的MethodDeclaration
的{{1}}中来添加BodyDelcaration
(不包括构造函数)。一旦完成此操作,由于使用了出色的API,这非常简单,我将执行以下操作...
EnumDeclaration
...用新的// create the EnumDeclaration from the given UnwantedClass compilationunit
final EnumDeclaration enumTypeDeclaration = createEnumDeclaration(cu,astRoot,methodDeclarations,ast);
// Find the original UnwantedClass TypeDeclaration and replace it with the new EnumDeclaration
astRoot.accept(new ASTVisitor() {
@Override
public boolean visit(final TypeDeclaration node) {
rewriter.replace(node,enumTypeDeclaration,null);
return false;
}
});
替换原始java类Type
。这几乎完美地工作。唯一缺少的是原始java类型的所有EnumDeclaration
-,Line
-和Block
元素。我发现您至少可以通过以下方式检索所有JavadocComment
实例:
Comment
这给了我所有评论,但是我还没有弄清楚如何将List<Comment> comments = cu.getCommentList();
if (comments != null) {
for (Comment comment : comments) {
comment.accept(visitor);
}
}
实例映射到Comment
,因为这些BodyDeclaration
实例基本上是自由浮动的。 Comment
文件,并且只能通过Source
文件中的startPosition进行链接。
问题是:如何保留原始类型的getAlternateRoot
实例并将其放置在新类型的正确位置?
解决方法
似乎没有直接解决此问题的方法,因为Java文件中的javadoc(或一般来说只是注释)与要注释的实际代码没有直接关系。对于开发人员来说,这只是常识,通常我们会将注释放在要注释的代码之上。因此,我采取了以下途径来解决这个问题:
- 创建一个基于起始位置的索引,该索引将一个Integer(起始位置)映射到所谓的CommentEntry实例,该实例基本上是一个由org.eclipse.jdt.core.dom.Comment和实际文本组成的元组只需通过子字符串提取编译单元的源字符串即可。
- 我访问原始的CompilationUnit并检索所有相关的ASTNode(在我的情况下分别是Type-,Field-和MethodDeclaration实例)并将其映射到它们的起始位置。
- 现在,我从1.迭代所有映射的CommentEntry位置,并将它们与ASTNode实例相关联,该实例被映射到同一位置(来自2的映射)。然后,结果是带有ASTNode-> CommentEntry的地图。
- 在构建新的EnumDeclaration时,我通过使用实际的ASTNode类型(TypeDeclaration仅存在一次),ASTNode的实际实例(我使用原始FieldDeclarations的属性来创建EnumConstants)从3中查询地图。使用ASTMatcher来识别正确的MethodDeclaration,因为我必须克隆它们才能将它们“复制”到新的EnumDeclaration Body部分。
添加注释并不像我想的那么直接,因为在较新的JSL中,您不能简单地在javadoc中设置注释String(仅在JSL2中受支持,但是在此版本中我们没有枚举)。因此,我使用了以下代码:
[HttpPut]
[Route("{primaryKey}")]
public async Task<ActionResult<ResponseSingleX<ClassA>>> Update(Guid primaryKey,[FromBody] ClassA classA)
{
// Update database
}
如您所见,即使使用TextElement,即使包含标签,也可以简单地添加实际注释文本。为了使其完美,您可能需要对先前从源文件中提取的注释文本进行子字符串化,因为它将包含/ **和* /。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。