动态类型推断,或自定义VariableScope。它是如何正确完成的?

时间:2018-04-15 17:14:54

标签: groovy

我有一个脚本系统,根据脚本的执行位置,您可以访问不同的变量。我还希望为脚本编辑器提供一种自动完成类型的推断类型。

但是当在编译阶段推断出类型时,我无法给出一个Binding,它向编译阶段解释了这些动态变量的类型。

我目前通过以下方式解决了这个问题:

不使用@TypeChecked@CompileStatic编译代码,但稍后在动态类型代码库上手动运行子类StaticCompilationVisitor并手动填写StaticTypesMarker.INFERRED_TYPE内{{1}对于我所知道的动态变量。

然而,这似乎是错误的方法,我真的想与visitVariableExpression()合作。但它似乎在VariableScope内部处于粗略锁定状态,因此很难弹出动态执行查找的VariableScopeVisitor。我已设法通过反射执行此操作,替换CustomVariableScope内的VariableScopeVisitorCompilationUnit内部currentScope。它有效,但我不喜欢使用硬编码的私有字段名称。

这可能是一种冗长的问题:是否有正式的方法来处理动态变量的静态类型?我无法通过设置VaribleScopeVisitor来解决此问题,原因太复杂,无法在此解释。

如果问题不清楚,请告诉我,我会尝试编辑更好的解释。

1 个答案:

答案 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;
    }

}