【问题标题】:Source code of current file in GroovyGroovy 中当前文件的源代码
【发布时间】:2018-08-17 22:20:22
【问题描述】:

我需要在 Groovy(定义当前运行的方法的文件)中将当前文件的源代码加载为字符串。我该怎么做?

我找到的大多数答案都与获取当前文件的父目录或获取 Groovy 脚本的源代码有关。但我的代码不是脚本,它只是一个类。

【问题讨论】:

  • “当前文件”是什么意思?定义当前运行的方法的文件?
  • 类文件没有(人类可读的)源。也许尝试在更高级别捕获问题,覆盖 GroovyClassLoader 或 GroovyShell GroovyScriptEngine groovy-lang.org/integrating.html
  • @ErnestKiwele 是的,定义当前运行的方法的文件
  • 您是否熟悉没有thrownew Exception(),以及在直播节目中获得StackTrace 的其他一些技术?
  • "在这个测试中,我需要获取测试的源代码来验证是否做出了所有必要的断言。" - 你想测试一个单元测试吗?这不是过于复杂的测试设计的一个例子吗?

标签: groovy


【解决方案1】:

虽然我不知道“使用 Groovy 来实现这一点的简单单行”(您的评论),但可以使用 AST 转换来做到这一点。

最简单的方法是使用注释进行本地 AST 转换。你注释你的测试类。然后,您有不同的选项可以在运行时检索源代码。我会将其添加为新注释的值,然后您可以通过反射获得。

项目

我在github 上创建了一个展示库。

你应该可以通过 gradle / maven 直接使用它:

repositories {
   maven { url 'https://jitpack.io' }
}
dependencies {
   compile 'com.github.MeneDev:groovy-get-source:96746d39f3'
}

用法:

@SaveSource
class AClass {

    def getCode() {
        SourceCode sourceCode = this.class.getAnnotation(SourceCode)
        return sourceCode.value()
    }
}

所需步骤

注释:

import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target

@Target([ElementType.TYPE])
@Retention(RetentionPolicy.CLASS)
@GroovyASTTransformationClass(classes = [SaveSourceASTTransformation])
public @interface SaveSource {

}

转换:

import groovy.transform.CompileStatic
import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.expr.ConstantExpression
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.ASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation

@CompileStatic
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
class SaveSourceASTTransformation implements ASTTransformation {

    @Override
    void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
        if (nodes.length < 2) {
            return
        }
        if (!(nodes[0] instanceof AnnotationNode)) {
            return
        }
        if (!(nodes[1] instanceof ClassNode)) {
            return
        }
        def classNode = nodes[1] as ClassNode

        def annotationNode = new AnnotationNode(new ClassNode(SourceCode))
        def sourceCode = sourceUnit.source.reader.text
        annotationNode.addMember("value", new ConstantExpression(sourceCode))
        classNode.addAnnotation(annotationNode)
    }
}

用于存储源代码的注释(注意RetentionPolicy.RUNTIME,以便您可以在运行时读取该值):

@Retention(RetentionPolicy.RUNTIME)
@interface SourceCode {
    String value()
}

【讨论】:

    猜你喜欢
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 2015-12-26
    • 2015-01-28
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    相关资源
    最近更新 更多