在 Gradle 中定义嵌套扩展容器
Define nested extension containers in Gradle
我正要实现我的第一个 Gradle 插件,我需要在其中定义嵌套的扩展对象。用户指南还没有涵盖这一点。在过去一年左右的时间里,有几个关于这个的问题,但我无法 assemble 从我读到的内容中找到解决方案。
这是我认为我希望用户能够做到的:
yang {
yangFilesRootDir "src/main/resources/yang"
inspectDependencies true
generators {
generator { // line 25
generatorClassName "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir "build/gen1"
}
generator {
generatorClassName "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir "build/gen2"
}
}
}
我的第一个随机尝试看起来像这样,我敢肯定这还没有结束:
public void apply(Project project) {
project.plugins.apply(JavaPlugin)
YangExtension yang = project.extensions.create(YANG_EXT, YangExtension)
project.yang.extensions.generators =
project.container(CodeGeneratorsContainer) {
println it
}
这是我的分机 classes:
class YangExtension {
CodeGeneratorsContainer generators
String yangFilesRootDir
String[] excludeFiles
boolean inspectDependencies
String yangFilesConfiguration
String generatorsConfiguration
}
public class CodeGeneratorsContainer {
Collection<CodeGenerator> generators
}
class CodeGenerator {
String generatorClassName
File outputBaseDir
Map additionalConfiguration
}
当我现在 运行 这样做时,它失败了:
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object
at org.gradle.api.internal.DynamicPropertyNamer.determineName(DynamicPropertyNamer.groovy:36)
at org.gradle.api.internal.DefaultNamedDomainObjectCollection.add(DefaultNamedDomainObjectCollection.java:70)
at org.gradle.api.internal.AbstractNamedDomainObjectContainer.create(AbstractNamedDomainObjectContainer.java:58)
at org.gradle.api.internal.AbstractNamedDomainObjectContainer.create(AbstractNamedDomainObjectContainer.java:52)
at org.gradle.api.internal.NamedDomainObjectContainerConfigureDelegate._configure(NamedDomainObjectContainerConfigureDelegate.java:39)
at org.gradle.api.internal.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:73)
at build_2a353qtggi869feteaqu2qgc3$_run_closure1_closure3.doCall(....\workspace2\YangUsingProject\build.gradle:25)
如果重要的话,我已经在构建脚本中标记了第 25 行。
更新:
集成解决方案后,这是所需设置的摘要。
“build.gradle”文件中的示例结构:
yang {
yangFilesRootDir "src/main/resources/yang"
//excludeFiles "target.yang"
inspectDependencies true
generator {
generatorClassName = "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir = "build/gen1"
}
generator {
generatorClassName = "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir = "build/gen2"
}
}
插件“应用”方法:
public void apply(Project project) {
project.plugins.apply(JavaPlugin)
YangExtension yang = project.extensions.create(YANG_EXT, YangExtension, project)
YangGenerateTask task = project.task(YANG_GENERATE_TASK, type: YangGenerateTask)
project.afterEvaluate {
task.init(project, yang)
}
}
分机 class:
class YangExtension {
private Project project
Collection<CodeGenerator> generators
String yangFilesRootDir
String[] excludeFiles
boolean inspectDependencies
String yangFilesConfiguration
String generatorsConfiguration
YangExtension(Project project) {
this.project = project
}
CodeGenerator generator(Closure closure) {
def generator = project.configure(new CodeGenerator(), closure)
generators.add(generator)
return generator
}
}
最后,CodeGenerator POGO:
class CodeGenerator {
String generatorClassName
String outputDir
Map additionalConfiguration
}
错误是由于 Project.container()
试图创建 NamedDomainObjectContainer
。这种特殊的集合类型要求集合类型指定一个name
属性。一个常见的例子是 sourceSets
,其中每个项目都有一个唯一的名称(main、test 等)。 DSL 将如下所示:
generators {
codeGenerator {
generatorClassName "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir "build/gen1"
}
docGenerator {
generatorClassName "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir "build/gen2"
}
}
如果给每个生成器命名没有意义,那么最好的办法就是在扩展上定义一个方法来配置 Generator
对象的新实例。这里的问题是,因为 you 正在实例化生成器 if 不会拥有 Gradle 会做的所有精美装饰(例如 setter 方法)。如果您想要功能,则必须在 Generator
class.
上手动定义这些方法
更新:
为了利用 Project.container()
并创建一个 NamedDomainObjectContainer
,容器类型必须有一个名为 name
的 属性 和一个 public 构造函数名称的 String
参数。 属性 的值是我最初配置对象时使用的任何名称。例如:
sourceSets {
integTest {
srcDir 'src/integTest'
}
}
上面的代码创建并配置一个名为“integTest”的新SourceSet
并将其添加到容器中.您可以通过简单地添加 属性 来利用您的“生成器”。你还想修改你的扩展 class 以及使 generators
属性 类型 NamedDomainObjectContainer<CodeGenerator>
并且不需要额外的 CodeGeneratorsContainer
class.
class YangExtension {
NamedDomainObjectContainer<CodeGenerator> generators
String yangFilesRootDir
String[] excludeFiles
boolean inspectDependencies
String yangFilesConfiguration
String generatorsConfiguration
YangExtension(Project project) {
this.generators = project.container(CodeGenerator)
}
}
class CodeGenerator {
String generatorClassName
File outputBaseDir
Map additionalConfiguration
private String name
CodeGenerator(String name) {
this.name = name
}
String getName() {
return this.name
}
}
更新二:
如果在你的 DSL 中命名对象没有意义,你可以简单地在你的扩展中提供一个方法来配置一个新的 CodeGenerator
并将它添加到一个集合中。
class YangExtension {
Collection<CodeGenerator> generators = new ArrayList<>()
private Project project
YangExtension(Project project) {
this.project = project
}
CodeGenerator generator(Closure closure) {
def generator = project.configure(new CodeGenerator(), closure)
generators.add(generator)
return generator
}
}
您的新 DSL 将不会有 generators
块。它看起来像这样:
yang {
generator {
generatorClassName = "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir = "build/gen1"
}
generator {
generatorClassName = "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir = "build/gen2"
}
}
我正要实现我的第一个 Gradle 插件,我需要在其中定义嵌套的扩展对象。用户指南还没有涵盖这一点。在过去一年左右的时间里,有几个关于这个的问题,但我无法 assemble 从我读到的内容中找到解决方案。
这是我认为我希望用户能够做到的:
yang {
yangFilesRootDir "src/main/resources/yang"
inspectDependencies true
generators {
generator { // line 25
generatorClassName "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir "build/gen1"
}
generator {
generatorClassName "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir "build/gen2"
}
}
}
我的第一个随机尝试看起来像这样,我敢肯定这还没有结束:
public void apply(Project project) {
project.plugins.apply(JavaPlugin)
YangExtension yang = project.extensions.create(YANG_EXT, YangExtension)
project.yang.extensions.generators =
project.container(CodeGeneratorsContainer) {
println it
}
这是我的分机 classes:
class YangExtension {
CodeGeneratorsContainer generators
String yangFilesRootDir
String[] excludeFiles
boolean inspectDependencies
String yangFilesConfiguration
String generatorsConfiguration
}
public class CodeGeneratorsContainer {
Collection<CodeGenerator> generators
}
class CodeGenerator {
String generatorClassName
File outputBaseDir
Map additionalConfiguration
}
当我现在 运行 这样做时,它失败了:
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object
at org.gradle.api.internal.DynamicPropertyNamer.determineName(DynamicPropertyNamer.groovy:36)
at org.gradle.api.internal.DefaultNamedDomainObjectCollection.add(DefaultNamedDomainObjectCollection.java:70)
at org.gradle.api.internal.AbstractNamedDomainObjectContainer.create(AbstractNamedDomainObjectContainer.java:58)
at org.gradle.api.internal.AbstractNamedDomainObjectContainer.create(AbstractNamedDomainObjectContainer.java:52)
at org.gradle.api.internal.NamedDomainObjectContainerConfigureDelegate._configure(NamedDomainObjectContainerConfigureDelegate.java:39)
at org.gradle.api.internal.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:73)
at build_2a353qtggi869feteaqu2qgc3$_run_closure1_closure3.doCall(....\workspace2\YangUsingProject\build.gradle:25)
如果重要的话,我已经在构建脚本中标记了第 25 行。
更新:
集成解决方案后,这是所需设置的摘要。
“build.gradle”文件中的示例结构:
yang {
yangFilesRootDir "src/main/resources/yang"
//excludeFiles "target.yang"
inspectDependencies true
generator {
generatorClassName = "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir = "build/gen1"
}
generator {
generatorClassName = "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir = "build/gen2"
}
}
插件“应用”方法:
public void apply(Project project) {
project.plugins.apply(JavaPlugin)
YangExtension yang = project.extensions.create(YANG_EXT, YangExtension, project)
YangGenerateTask task = project.task(YANG_GENERATE_TASK, type: YangGenerateTask)
project.afterEvaluate {
task.init(project, yang)
}
}
分机 class:
class YangExtension {
private Project project
Collection<CodeGenerator> generators
String yangFilesRootDir
String[] excludeFiles
boolean inspectDependencies
String yangFilesConfiguration
String generatorsConfiguration
YangExtension(Project project) {
this.project = project
}
CodeGenerator generator(Closure closure) {
def generator = project.configure(new CodeGenerator(), closure)
generators.add(generator)
return generator
}
}
最后,CodeGenerator POGO:
class CodeGenerator {
String generatorClassName
String outputDir
Map additionalConfiguration
}
错误是由于 Project.container()
试图创建 NamedDomainObjectContainer
。这种特殊的集合类型要求集合类型指定一个name
属性。一个常见的例子是 sourceSets
,其中每个项目都有一个唯一的名称(main、test 等)。 DSL 将如下所示:
generators {
codeGenerator {
generatorClassName "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir "build/gen1"
}
docGenerator {
generatorClassName "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir "build/gen2"
}
}
如果给每个生成器命名没有意义,那么最好的办法就是在扩展上定义一个方法来配置 Generator
对象的新实例。这里的问题是,因为 you 正在实例化生成器 if 不会拥有 Gradle 会做的所有精美装饰(例如 setter 方法)。如果您想要功能,则必须在 Generator
class.
更新:
为了利用 Project.container()
并创建一个 NamedDomainObjectContainer
,容器类型必须有一个名为 name
的 属性 和一个 public 构造函数名称的 String
参数。 属性 的值是我最初配置对象时使用的任何名称。例如:
sourceSets {
integTest {
srcDir 'src/integTest'
}
}
上面的代码创建并配置一个名为“integTest”的新SourceSet
并将其添加到容器中.您可以通过简单地添加 属性 来利用您的“生成器”。你还想修改你的扩展 class 以及使 generators
属性 类型 NamedDomainObjectContainer<CodeGenerator>
并且不需要额外的 CodeGeneratorsContainer
class.
class YangExtension {
NamedDomainObjectContainer<CodeGenerator> generators
String yangFilesRootDir
String[] excludeFiles
boolean inspectDependencies
String yangFilesConfiguration
String generatorsConfiguration
YangExtension(Project project) {
this.generators = project.container(CodeGenerator)
}
}
class CodeGenerator {
String generatorClassName
File outputBaseDir
Map additionalConfiguration
private String name
CodeGenerator(String name) {
this.name = name
}
String getName() {
return this.name
}
}
更新二:
如果在你的 DSL 中命名对象没有意义,你可以简单地在你的扩展中提供一个方法来配置一个新的 CodeGenerator
并将它添加到一个集合中。
class YangExtension {
Collection<CodeGenerator> generators = new ArrayList<>()
private Project project
YangExtension(Project project) {
this.project = project
}
CodeGenerator generator(Closure closure) {
def generator = project.configure(new CodeGenerator(), closure)
generators.add(generator)
return generator
}
}
您的新 DSL 将不会有 generators
块。它看起来像这样:
yang {
generator {
generatorClassName = "org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl"
outputDir = "build/gen1"
}
generator {
generatorClassName = "org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl"
outputDir = "build/gen2"
}
}