Gradle 的 CopySpec 过滤器方法签名与给出的示例有何关系?

Posted

技术标签:

【中文标题】Gradle 的 CopySpec 过滤器方法签名与给出的示例有何关系?【英文标题】:How does Gradle's CopySpec filter method signature relate to the example given? 【发布时间】:2020-02-18 09:18:39 【问题描述】:

我正在尝试在我的 build.gradle 文件的 xml 文件中实现替换 $pattern 的东西:

processResources 
    eachFile  FileCopyDetails fileCopyDetails ->
        if (fileCopyDetails.name.contains("blueprint.xml")) 
            project.logger.quiet "Processing: " + fileCopyDetails.path
            logger.quiet "" + project.ext.properties.entrySet()
            filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [prop1, value, prop2, value])
        
    

tokens: 似乎拿了一张地图。同样,这与函数签名有何关系?

将所有具有String值的属性转换为Map以输入到tokens:

def tokenMap = new LinkedHashMap()
def stringProps = project.ext.properties.entrySet().findAll  entry -> entry.getValue() instanceof String 
stringProps.each  entry -> tokenMap.put(entry.key, entry.value)

查看 Gradle Javadoc 会发现一个过滤器函数,其签名似乎与示例不匹配。 据我所知,Map<String,?>Class<? extends FilterReader> 与示例中的顺序不匹配。 有人可以将示例映射到函数签名以便我了解发生了什么吗?

CopySpec filter​(Map<String,​?> properties,
            Class<? extends FilterReader> filterType)

添加要在复制期间使用的内容过滤器。多次调用 过滤器,将其他过滤器添加到过滤器链中。每个过滤器应 实现 java.io.FilterReader。包括 org.apache.tools.ant.filters.* 用于访问所有标准 Ant 过滤器。

可以使用 groovy map 语法指定过滤器属性。

例子:

filter(HeadFilter, lines:25, skip:2)
filter(ReplaceTokens, tokens:[copyright:'2009', version:'2.3.1'])  

指定者

filter 在接口ContentFilterable

参数properties - 过滤器属性映射 filterType - 要添加的过滤器类别

返回: 这个


相关:

How is a token replaced in a file for a Gradle build product?


注意:

SimpleTemplateEngine 不起作用

processResources 
    filesMatching("**/features.xml") 
        // expand uses Groovy's SimpleTemplateEngine
        project.logger.quiet "Processing: " + file
        expand project.getProperties()
    

【问题讨论】:

【参考方案1】:

这实际上是底层 Groovy 语法的一个特性。当方法的第一个参数声明为Map 时,Groovy 允许您按名称(即&lt;name&gt;: &lt;value&gt;)指定方法参数。至关重要的是,命名参数可以出现在参数列表中的任何位置,即使在所谓的位置参数之后(即在方法签名中Map 之后声明的参数),它们将作为条目放入在初始 Map 参数中。有关详细信息,请参阅Groovy Language Documentation 中的混合命名参数和位置参数部分。

所以,Gradle filter 方法有签名

CopySpec filter​(Map<String,​?> properties, Class<? extends FilterReader> filterType)

第一个properties 参数是Map 类型,因此可以使用命名参数调用此方法。此外,还有一个位置参数filterType。因此,要调用此方法,您必须指定一个不带名称的参数,其类型为Class&lt;? extends FilterReader&gt;,将用于filterType,以及零个或多个命名参数,它们都将放入properties 映射中。

从文档中举一个例子:

filter(HeadFilter, lines:25, skip:2)

将意味着 filter 被调用

properties = [
  lines: 25,
  skip: 2
]
filterType = HeadFilter

以下任何调用都是等效的:

filter(lines:25, skip:2, HeadFilter)
filter(lines:25, HeadFilter, skip:2)
filter([lines:25, skip:2], HeadFilter)

此处的最后一次调用按位置传递两个参数(当第一个参数声明为 Map 时,您没有使用命名参数)。

旁注

我很好奇为什么使用 expand 不起作用 - 应该!

【讨论】:

好的,expand() 的问题与 XML 无关。它与 expand()/SimpleTemplateEngine 的错误处理有关,如果在 XML 中找不到属性,则会失败。这是愚蠢的行为。我不确定如何正确吞下异常。甚至还有一张票:issues.apache.org/jira/browse/GROOVY-5093 这是因为我正在处理所有属性,无论它们是否存在于模板中。

以上是关于Gradle 的 CopySpec 过滤器方法签名与给出的示例有何关系?的主要内容,如果未能解决你的问题,请参考以下文章

没有方法签名:com.crashlytics.tools.gradle.CrashlyticsPlugin On Mac [关闭]

安卓 自动签名 以及如何验证一个apk包是用你的签名文件签名的

Android:如何仅通过 Gradle 生成签名 APK? [复制]

Android - 签名的 APK - Gradle 执行失败

Gradle 签名的配置文件 gradle.properties

Gradle实现自动打包,签名,自定义apk文件名