简体   繁体   English

如何在创建 Groovy DSL 时仅从特定闭包或 Scope 中使用 object 的方法

[英]How to make a method from an object available only from a specific Closure or Scope when creating a Groovy DSL

Lets say I have a class:假设我有一个 class:

Foo {
 always()
 onlyScopeB()
}

And I have different methods, which take different closures: scopeA , scopeB而且我有不同的方法,它们采用不同的闭包: scopeAscopeB

foo = new Foo()

scopeA{
  foo.always()     // this should COMPILE
  foo.onlyScopeB() // this should NOT COMPILE
}

scopeB{
  foo.always()     // this should COMPILE
  foo.onlyScopeB() // this should COMPILE
}

Is there anyway to achieve this at the compilation stage?无论如何在编译阶段实现这一目标? I am writing a DSL and I have scopes that correspond to stages in a process and sometimes fields are null in one scope, and then other times they are not-null and I am trying to provide the best semantic experience to find errors easily.我正在编写一个 DSL,并且我有与流程中的阶段相对应的范围,有时字段是null在一个 scope 中,然后其他时候它们not-null ,我试图提供最佳语义体验以轻松查找错误。

If you want to achieve this at the compilation stage, the only way I can think of is to write a custom AST Transformation .如果你想在编译阶段实现这一点,我能想到的唯一方法就是编写一个自定义的 AST Transformation

This is slight variation on your stated syntax.这与您声明的语法略有不同。 You can divide your Scope A and Scope B methods into interfaces and use closure delegation to provide feedback.您可以将您的 Scope A 和 Scope B 方法划分为接口,并使用闭包委托来提供反馈。 The common method(s) like always() could be moved to a common interface if there are many.如果有很多,像always()这样的通用方法可以移动到一个通用接口。 If you enable Static Type Checking on the script part of this, you will get compiler errors instead of just underlines.如果您在此脚本部分启用 Static 类型检查,您将收到编译器错误,而不仅仅是下划线。

interface Bar {
  void always()
  void onlyScopeA()
}
interface Baz {
  void always()
  void onlyScopeB()
}
@groovy.transform.AutoImplement
class Foo implements Bar, Baz {
}

void scopeA(@DelegatesTo.Target Bar bar, @DelegatesTo Closure block) {
  bar.with(block)
}
void scopeB(@DelegatesTo.Target Baz baz, @DelegatesTo Closure block) {
  baz.with(block)
}


def foo = new Foo()
scopeA(foo) {
  always()
  onlyScopeA()
  onlyScopeB()
}
scopeB(foo) {
  always()
  onlyScopeA()
  onlyScopeB()
}

IDE 反馈示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM