我有一个脚本系统,根据脚本的执行位置,您可以访问不同的变量。我还希望为脚本编辑器提供一种自动完成类型的推断类型。
但是当在编译阶段推断出类型时,我无法给出一个Binding,它向编译阶段解释了这些动态变量的类型。
我目前通过以下方式解决了这个问题:
不使用@TypeChecked
或@CompileStatic
编译代码,但稍后在动态类型代码库上手动运行子类StaticCompilationVisitor
并手动填写StaticTypesMarker.INFERRED_TYPE
内{{1}对于我所知道的动态变量。
然而,这似乎是错误的方法,我真的想与visitVariableExpression()
合作。但它似乎在VariableScope
内部处于粗略锁定状态,因此很难弹出动态执行查找的VariableScopeVisitor
。我已设法通过反射执行此操作,替换CustomVariableScope
内的VariableScopeVisitor
和CompilationUnit
内部currentScope
。它有效,但我不喜欢使用硬编码的私有字段名称。
这可能是一种冗长的问题:是否有正式的方法来处理动态变量的静态类型?我无法通过设置VaribleScopeVisitor
来解决此问题,原因太复杂,无法在此解释。
如果问题不清楚,请告诉我,我会尝试编辑更好的解释。
答案 0 :(得分:0)
答案是将GroovyTypeCheckingExtensionSupport
添加到StaticTypeCheckingVisitor
,然后在visitClass
的第一个ClassNode
上使用CompilationUnit
。
final ClassNode classNode = this.compilationUnit.getFirstClassNode();
final StaticCompilationVisitor visitor = new StaticCompilationVisitor(this.sourceUnit, classNode);
visitor.addTypeCheckingExtension(new MyGroovyTypeCheckingExtensionSupport(visitor, this.compilationUnit));
visitor.visitClass(classNode);
visitor.performSecondPass();
并创建类似于以下类的内容:
private static class MyGroovyTypeCheckingExtensionSupport extends GroovyTypeCheckingExtensionSupport {
private static final ClassNode CLASSNODE_OBJECT = ClassHelper.make(Object.class);
public MyGroovyTypeCheckingExtensionSupport(StaticTypeCheckingVisitor typeCheckingVisitor, CompilationUnit compilationUnit) {
super(typeCheckingVisitor, "", compilationUnit);
}
@Override
public boolean handleUnresolvedVariableExpression(VariableExpression vexp) {
final ClassNode type = this.getType(vexp);
if (type == null || type.equals(CLASSNODE_OBJECT)) {
if (vextp.getName().equals("something")) {
this.storeType(vexp, ClassHelper.make(SomeClass.class));
return true;
}
}
return false;
}
}