У меня есть строгий скрипт, который определяет метод, который генерирует исключение. Используя AST Transformations, я генерирую во время компиляции новый класс. Затем я копирую этот метод из сценария в этот новый класс и делаю класс доступным во время выполнения. Когда во время выполнения я создаю новый объект нового класса и вызываю метод в трассировке стека, я могу видеть ссылки на класс Script1
вместо нового сгенерированного класса.Неправильная трассировка стека из исключения в методе, скопированном из скрипта строчной оболочки
Exception in thread "main" java.lang.RuntimeException
at MyGeneratedClass.myMethod(Script1.groovy:4)
at MyGeneratedClass$myMethod.call(Unknown Source)
at scripttest.ExTest.main(ExTest.groovy:35)
Что я могу сделать, чтобы изменить его, так что я не вижу этот Script1.groovy
класс в трассировки стека, но новый класс и номер строки внутри него?
Мой код:
class ExTest {
public static void main(String[] a) {
String script = '''
def myMethod() {
throw new RuntimeException()
}
'''
def config = new CompilerConfiguration()
config.addCompilationCustomizers(new MyCompilerConfiguration())
ClassLoader classLoaderToUse = new GroovyClassLoader()
GroovyShell shell = new GroovyShell(classLoaderToUse, new Binding(), config)
Script parsedScript = shell.parse(script)
def generatedClass = parsedScript.class.fields.find {it.name == 'myGeneratedClassField'}.type
def generated = generatedClass.newInstance()
generated.myMethod()
}
}
class MyCompilerConfiguration extends CompilationCustomizer {
MyCompilerConfiguration() {
super(CompilePhase.CONVERSION)
}
@Override
void call(SourceUnit source, GeneratorContext context, ClassNode currentClassNode) throws CompilationFailedException {
def newClassAst = new AstBuilder().buildFromSpec {
classNode('MyGeneratedClass', ClassNode.ACC_PUBLIC) {
classNode java.lang.Object
interfaces { classNode GroovyObject }
mixins { }
}
}
ClassNode myGeneratedClassNode = newClassAst[0]
source.getAST().addClass(myGeneratedClassNode)
currentClassNode.addField('myGeneratedClassField', Opcodes.ACC_PUBLIC, myGeneratedClassNode, new EmptyExpression())
MethodNode myMethodNode = source.getAST().methods.find {it.name == 'myMethod'}
myGeneratedClassNode.addMethod(myMethodNode.name, Opcodes.ACC_PUBLIC, myMethodNode.returnType, myMethodNode.parameters, myMethodNode.exceptions, myMethodNode.code)
}
}