gradle - 在 Gradle 中定义嵌套的扩展容器

标签 gradle

我正在实现我的第一个 Gradle 插件,我需要在其中定义嵌套扩展对象。用户指南尚未涵盖此内容。在过去一年左右的时间里有几个关于这个的问题,但我无法从我所读到的内容中组装出一个解决方案。
这就是我相信我希望用户能够做到的事情:

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
        }
这是我的扩展类:
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 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属性(property)。一个常见的例子是 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 的新实例。目的。这里的问题是因为 如果没有 Gradle 会做的所有花哨的装饰(例如 setter 方法),则正在实例化生成器。如果你想要能力,你必须在 Generator 上手动定义这些方法。类(class)。
更新:
为了利用 Project.container()并创建一个 NamedDomainObjectContainer ,容器类型必须有一个名为 name 的属性和一个公共(public)构造函数,它采用 String名称的参数。此属性的值是我最初配置对象时使用的任何名称。例如:
sourceSets {
    integTest {
        srcDir 'src/integTest'
    }
}
上面的代码创建 配置一个新的SourceSet名称为“integTest”并将其添加到容器中。您可以通过简单地添加该属性来利用您的“生成器”。您还需要修改您的扩展类以使 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
    }
}
更新 2:
如果在你的 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 - 在 Gradle 中定义嵌套的扩展容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28999106/

相关文章:

gradle - 将文件复制到 Gradle 中的 rootDir

android - Build.gradle : Failed to resolve: com. android.support

node.js - 通过 Gradle 将文件复制到构建目录

java - 有没有办法以编程方式检索 gradle 中的依赖项

java - 如何确保doLast甚至任务被跳过

spring-boot - 关于将Clojure集成到springboot框架中

android - Android Studio无法无故完成Gradle执行

angularjs - 在 Weblogic Server 上无法访问 Webjar

android - 由于OneSignal无法解决依赖关系

Gradle processResources 损坏 .jks