解析 – 获取有关Groovy函数的信息(名称,签名,正文代码)
发布时间:2020-12-14 16:23:58 所属栏目:大数据 来源:网络整理
导读:我有一个Groovy文件包含一堆简单的函数,如下所示: // useful functionsdef myFunc1(String arg) { println("Hello " + arg)}def myFunc2(String arg) { println("Goodbye " + arg)} 我想从中得到: 方法名称 论点 函数的正文代码 (所有这些都是简单的字符串
我有一个Groovy文件包含一堆简单的函数,如下所示:
// useful functions def myFunc1(String arg) { println("Hello " + arg) } def myFunc2(String arg) { println("Goodbye " + arg) } 我想从中得到: >方法名称 (所有这些都是简单的字符串,我不需要运行任何东西.) 我正准备使用一些Regexing,但由于我使用的是JVM语言(Scala),我想我可以使用一些Groovy编译器的东西来做这个“更好”的方式. 似乎有很多关于动态加载Groovy代码并运行它的信息,但在内省源代码方面却没有那么多.有任何想法吗? (以“不错”的方式失败,我也会接受一些Scala-foo以简洁的方式解析信息.) 解决方法
这有效,并演示了在AST中查找每个重要节点所需的令牌类型.希望它有意义……通过使用大量的Groovy动态,我希望我没有让Scala的端口太难:-(
import org.codehaus.groovy.antlr.* import org.codehaus.groovy.antlr.parser.* import static org.codehaus.groovy.antlr.parser.GroovyTokenTypes.* def code = ''' // useful functions def myFunc1(String arg) { println("Hello " + arg) } def myFunc2(arg,int arg2) { println("Goodbye " + arg) } public String stringify( int a ) { "$a" } ''' def lines = code.split( 'n' ) // Generate a GroovyRecognizer,compile an AST and assign it to 'ast' def ast = new SourceBuffer().with { buff -> new UnicodeEscapingReader( new StringReader( code ),buff ).with { read -> read.lexer = new GroovyLexer( read ) GroovyRecognizer.make( read.lexer ).with { parser -> parser.sourceBuffer = buff parser.compilationUnit() parser.AST } } } // Walks the ast looking for types def findByPath( ast,types,multiple=false ) { [types.take( 1 )[ 0 ],types.drop(1)].with { head,tail -> if( tail ) { findByPath( ast*.childrenOfType( head ).flatten(),tail,multiple ) } else { ast*.childrenOfType( head ).with { ret -> multiple ? ret[ 0 ] : ret.head()[0] } } } } // Walk through the returned ast while( ast ) { def methodModifier = findByPath( ast,[ MODIFIERS ] ).firstChild?.toStringTree() ?: 'public' def returnType = findByPath( ast,[ TYPE,IDENT ] ) ?: 'Object' def methodName = findByPath( ast,[ IDENT ] ) def body = findByPath( ast,[ SLIST ] ) def parameters = findByPath( ast,[ PARAMETERS,PARAMETER_DEF ],true ).collect { param -> [ type: findByPath( param,[ TYPE ] ).firstChild?.toStringTree() ?: 'Object',name: findByPath( param,[ IDENT ] ) ] } def (y1,y2,x1,x2) = [ body.line - 1,body.lineLast - 1,body.column - 1,body.columnLast ] // Grab the text from the original string def snip = [ lines[ y1 ].drop( x1 ),// First line prefix stripped *lines[ (y1+1)..<y2 ],// Mid lines lines[ y2 ].take( x2 ) ].join( 'n' ) // End line suffix stripped println '------------------------------' println "modifier: $methodModifier" println "returns: $returnType" println "name: $methodName" println "params: $parameters" println "$snipn" // Step to next branch and repeat ast = ast.nextSibling } 打印出来: ------------------------------ modifier: public returns: Object name: myFunc1 params: [[type:String,name:arg]] { println("Hello " + arg) } ------------------------------ modifier: public returns: Object name: myFunc2 params: [[type:Object,name:arg],[type:int,name:arg2]] { println("Goodbye " + arg) } ------------------------------ modifier: public returns: String name: stringify params: [[type:int,name:a]] { "$a" } 希望它有所帮助,或指出你正确的方向:-) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |