提取中文
本工具应用org.eclipse.jdt.core将java代码转换成AST
将java代码转换成AST树
def parser = new Parser()CompilationUnit result = parser.ast(content)Document document = new Document(src.text)def ast = result.getAST()
应用Vistior模式遍历所有字符串
List<StringLiteral> visitChineseText(CompilationUnit result){ var translateList = [] result.accept(new ASTVisitor(){ @Override boolean visit(StringLiteral node) { if(node.toString() =~ Config.DOUBLE_BYTE_REGEX){ translateList.add(node) } return super.visit(node) } }) return translateList}
过滤
原理:相熟AST
以下是logger.info("异样信息"+e)
的AST
如果咱们须要过滤logger.info("异样信息"+e)
,咱们须要lookup到MethodInvocation节点,而后查看MethodInvocation的expression是否为SimpleName类型,且getIdentifier() == "logger"
须要过滤的中文
kiwi中实现的过滤器反对过滤以下中文:
- 去除正文
- 过滤log中的中文
- 系统配置的中文
- 参加业务逻辑的中文比方 "中文".equsals("中文")
- 正则匹配的中文字符(只蕴含标点)
- 存在于注解中的中文
- 存在于枚举的中文
- 正文中增加了kiwi-disable-method
过滤器实现
所有的过滤器实现了Predicate<StringLiteral>
接口,用来判断中文是否过滤
罕用的过滤器有:
- 注解过滤器
boolean isInAnnotation(StringLiteral stringLiteral){ def parent = stringLiteral.parent // 以StringLiteral节点向上查找,如果找到了注解,则返回true while (parent != null && !(parent instanceof TypeDeclaration)) { if(parent instanceof Annotation){ def memberValuePair = AstUtils.lookupUntilASTNode(stringLiteral, MemberValuePair.class) if(memberValuePair.isPresent()){ return !shouldExclude(memberValuePair.get(), parent) } return true } parent = parent.parent } return false}
- 常量过滤器
- 枚举过滤器
通常Enum里的中文无需翻译,也无奈替换,因为不能在初始化的时候调用办法
public enum RpFlagEnum { /** * 应酬 */ P("P","应酬"), /** * 应收 */ R("R","应收");}
def optMethod = AstUtils.lookupUntilASTNode(stringLiteral, EnumConstantDeclaration.class) if (optMethod.isPresent()) { return true } return false
- 日志过滤
过滤 log.info("中文")
def optMethod = AstUtils.lookupUntilASTNode(stringLiteral, MethodInvocation.class) if(optMethod.isPresent()){ def methodName = optMethod.get().getExpression() // log.info(xxx) if(methodName instanceof SimpleName){ def simpleName = (SimpleName)methodName if(isLogInfo(simpleName.getIdentifier())){ return true } // this.log.info(xxx) } else if(methodName instanceof FieldAccess){ def fieldAccess = (FieldAccess)methodName def fieldName = fieldAccess.getName() if(isLogInfo(fieldName.getIdentifier())){ return true } } } return false
- Main办法过滤
- I18n办法过滤
- 正文中增加了kiwi-disable-method
某些状况下咱们须要过滤的中文属于业务逻辑,然而代码无奈判断,须要增加正文跳过
/**** kiwi-disable-method*/pubic String abc(){ return "中文";}
boolean hasMethodComment(StringLiteral stringLiteral) { def parent = stringLiteral.parent while (parent != null && !(parent instanceof TypeDeclaration)) { if(parent instanceof MethodDeclaration){ def doc = parent.getJavadoc() return doc.toString().contains(methodComment) } parent = parent.parent } return false }
- 正则过滤器(正则匹配的中文字符(只蕴含标点))
- 参加业务逻辑的中文比方 "中文".equsals("中文")
boolean hasStringEquals(StringLiteral stringLiteral){ def optMethod = AstUtils.lookupUntilASTNode(stringLiteral, MethodInvocation.class) if(optMethod.isPresent()){ def method = optMethod.get() if(method.name.identifier == "equals"){ return true } } return false }