有时,咱们须要删除Java源代码中的注释。目前有很多方法,好比:html
实现状态机。该方式较为通用,适用于多种语言(取决于状态机支持的注释符号)。java
正则匹配。该方式容易误判,尤为是容易误删字符串。git
本文针对Java语言,介绍一种利用第三方库的方式,能够方便快速地移除代码中的注释。github
原理所以核心思路即为:maven
JavaParser解析源码并获得AST。编辑器
识别出注释类型的节点并将其删掉。ide
LineComment 单行注释。性能
BlockComent 块注释。测试
JavadocComment Java文档注释。ui
import java.util.ArrayList; import java.util.stream.Collectors; /** * @author xiaoxi666 * @date 2021-02-15 17:13 * 我是 Javadoc 注释 */ public class Input { /** * 我是 Javadoc 注释 * * @param param1 * @param param2 */ public static void someMethod(String param1, // 我是单行注释 String param2 // 我是单行注释 String param3, /* 我是块注释 String param4, String param5, String param6 */ /* 我是块注释 String param4 */) { // 我是单行注释 int a = 1; /* 我是块注释,注意我和Javadoc注释的区别,我只有一个星号 */ int b = 2; /* * 我是块注释 */ int c = 3; String s1 = "// 我是字符串中的内容,不是注释"; String s2 = "/* 我是字符串中的内容,不是注释 */"; String s3 = "/** 我是字符串中的内容,不是注释 */"; } }
<dependencies> <dependency> <groupId>com.github.javaparser</groupId> <artifactId>javaparser-symbol-solver-core</artifactId> <version>3.18.0</version> </dependency> </dependencies>
package core;
import com.github.javaparser.JavaParser; import com.github.javaparser.ParseResult; import com.github.javaparser.ParserConfiguration; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.comments.BlockComment; import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.comments.LineComment; import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; /** * @author xiaoxi666 * @date 2021-02-15 20:09 * 几个注释的概念: * LineComment * BlockComment * JavadocComment */ public final class CommentsRemover { private CommentsRemover() {} public static String doAction(String content) { JavaParser javaParser = createJavaParser(); ParseResult<CompilationUnit> result = javaParser.parse(content); Optional<CompilationUnit> optionalCompilationUnit = result.getResult(); if (!optionalCompilationUnit.isPresent()) { return ""; } CompilationUnit compilationUnit = optionalCompilationUnit.get(); removeComments(compilationUnit); return LexicalPreservingPrinter.print(compilationUnit); } private static void removeComments(CompilationUnit compilationUnit) { List<Comment> comments = compilationUnit.getAllContainedComments(); List<Comment> unwantedComments = comments .stream() .filter(CommentsRemover::isValidCommentType) .collect(Collectors.toList()); unwantedComments.forEach(Node::remove); } /** * 建立源码解析器。咱们设置LexicalPreservationEnabled为true,保留源码中的全部语法。 * * @return JavaParser */ private static JavaParser createJavaParser() { ParserConfiguration parserConfiguration = new ParserConfiguration(); parserConfiguration.setLexicalPreservationEnabled(true); return new JavaParser(parserConfiguration); } /** * 咱们只识别单行注释和块注释 * * @param comment * @return true if meet the correct type */ private static boolean isValidCommentType(Comment comment) { return comment instanceof LineComment || comment instanceof BlockComment; } }
IDEA插件的原理基本都是事件驱动,以下图所示,咱们建立了一个事件监听器,当检测到编辑器中点击右键后,便可弹出菜单,咱们的插件在菜单中的第一个位置。
接下来,实现事件处理器:
删除源码注释。首先读取当前文件内容也即源码,而后交给前面已经介绍过的CommentsRemover.doAction处理,就拿到了删除注释后的源码。
格式化代码。删除注释后,可能会引入多余的空格,所以咱们自动格式化,这样用户就不用再手动格式化一次了。
/** * 移除代码中的注释 * * @param editor * @return true if remove comments successfully */ private boolean removeComments(Editor editor) { String src = editor.getDocument().getText(); if (Strings.isNullOrEmpty(src)) { return false; } String dst = CommentsRemover.doAction(checkEndLineAndModifyIfNeed(src)); if (Strings.isNullOrEmpty(dst)) { return false; } editor.getDocument().setText(dst); return true; } /** * 因为咱们保留了源码格式,移除注释以后会引入没必要要的空格,所以须要再格式化一下 * * @param editor * @param project */ private void reformat(Editor editor, Project project) { PsiDocumentManager.getInstance(project).commitAllDocuments(); PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); if (file == null) { return; } LastRunReformatCodeOptionsProvider provider = new LastRunReformatCodeOptionsProvider(PropertiesComponent.getInstance()); ReformatCodeRunOptions currentRunOptions = provider.getLastRunOptions(file); TextRangeType processingScope = TextRangeType.WHOLE_FILE; currentRunOptions.setProcessingScope(processingScope); (new FileInEditorProcessor(file, editor, currentRunOptions)).processCode(); }
在弹出的目录树中,选中remove.comments.zip安装包,肯定便可。
重启IDEA后,能够看到插件已安装成功:
此时咱们就能够使用该插件,一键删除代码中的注释了。演示一下效果:
不严格性能测试(响应时间包括插件处理时间和IDEA界面更新时间):
对于500行左右的文件,响应时间约200ms,几乎瞬间完成。
对于1000行左右的文件,响应时间约为1s。
对于3000行左右的文件,响应时间约需2s。
总之,平常使用毫无压力。
总结
另外,因为本人对JavaParser的认知不是特别深刻,不免存在未考虑到的场景。若你们在使用过程当中发现bug,欢迎到github提issue甚至pr。
资源
源码均已放在github:https://github.com/xiaoxi666/remove.comments。
插件也已经上传至github,可点击下载。或者关注公众号「xiaoxi666」,后台回复「删除注释」,便可收到插件下载地址。
Go to "Discover" > "Top Stories" > "Wow"