You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java适配Groovy Parrot解析器时,如何在启用类型检查的同时允许指定未定义变量?

Java适配Groovy Parrot解析器时,如何在启用类型检查的同时允许指定未定义变量?

我正在升级一个Java代码库,它需要解析用户提供的Groovy脚本,目标是兼容Groovy的Parrot解析器,但目前遇到了不小的麻烦。

旧版解析器的语法错误捕获逻辑

在使用Antlr2解析器(Parrot之前的版本)时,我们可以像这样轻松捕获语法错误:

@Test(expected = MultipleCompilationErrorsException.class)
public void testFailingOldWay() {
    CompilerConfiguration config = new CompilerConfiguration();
    config.setPluginFactory(ParserPluginFactory.antlr2());
    new GroovyShell(config).parse("this is not valid");
}

这种方式会正常抛出MultipleCompilationErrorsException,完全符合预期。

切换到Parrot解析器后的问题

但换成Parrot解析器(基于Antlr4实现)后,原本明显无效的代码居然不会触发任何解析错误。我一开始以为是Groovy的bug,后来才搞明白:Groovy的动态特性允许传入动态方法和变量,所以这类代码在理论上存在合法的可能性,因此解析器不会直接报错:

@Test
public void testFailingNewWayDoesNotWork() {
    CompilerConfiguration config = new CompilerConfiguration();
    // 原本期望下面这行抛出编译错误,但实际并没有
    new GroovyShell(config).parse("this is not valid");
}

尝试用类型检查解决问题

因为我明确知道脚本可以使用的变量列表,所以想到启用静态类型检查来捕获非法代码,于是写了这样的测试:

@Test(expected = MultipleCompilationErrorsException.class)
public void testNewIdea() {
    CompilerConfiguration config = new CompilerConfiguration();
    config.addCompilationCustomizers(new ASTTransformationCustomizer(TypeChecked.class));
    new GroovyShell(config).parse("this is not valid");
}

这个方法确实能抛出预期的编译错误,但新问题来了:我找不到办法告诉类型检查器,允许某些特定的变量处于未定义状态。

我查了Groovy的官方文档,还看了一篇Stack Overflow的相关帖子,但文档只覆盖了Java实现的部分内容,而帖子全是基于Groovy代码的实现方案,和我的Java场景完全不匹配。

自定义扩展的思路(但遇到空指针)

我自己琢磨出一个方案:写一个自定义注解和类型检查扩展类,来控制哪些未定义变量可以被允许。

首先是自定义注解类:

import org.codehaus.groovy.transform.GroovyASTTransformationClass;

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@GroovyASTTransformationClass("flexagon.fd.model.script.AllowUnresolvedVariables")
public @interface NoUnresolvedVariablesAnnotation
{
}

然后是继承自AbstractTypeCheckingExtension的扩展类:

public class AllowUnresolvedVariables
  extends AbstractTypeCheckingExtension
{

  public AllowUnresolvedVariables(final StaticTypeCheckingVisitor typeCheckingVisitor)
  {
    super(typeCheckingVisitor);
  }

  @Override
  public boolean handleUnresolvedVariableExpression(final VariableExpression vexp)
  {
    return true;
  }

}

但在配置中引用这些类时,出现了空指针异常。我还专门做了一个简单的项目来复现这个问题。

真心希望能得到大家的帮助!

备注:内容来源于stack exchange,提问作者Karl Henselin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:18:03