IDEA-155548 gradle: classpath does not include generated resources
[idea/community.git] / plugins / gradle / tooling-extension-impl / src / org / jetbrains / plugins / gradle / tooling / builder / ExternalProjectBuilderImpl.groovy
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.plugins.gradle.tooling.builder
17
18 import com.google.gson.GsonBuilder
19 import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
20 import org.gradle.api.Action
21 import org.gradle.api.JavaVersion
22 import org.gradle.api.Project
23 import org.gradle.api.Task
24 import org.gradle.api.artifacts.Configuration
25 import org.gradle.api.file.ContentFilterable
26 import org.gradle.api.file.FileCopyDetails
27 import org.gradle.api.tasks.SourceSet
28 import org.gradle.api.tasks.SourceSetContainer
29 import org.gradle.api.tasks.bundling.Jar
30 import org.gradle.api.tasks.compile.JavaCompile
31 import org.gradle.api.tasks.util.PatternFilterable
32 import org.gradle.plugins.ide.idea.IdeaPlugin
33 import org.jetbrains.annotations.NotNull
34 import org.jetbrains.annotations.Nullable
35 import org.jetbrains.plugins.gradle.model.*
36 import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
37 import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
38 import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl
39 import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder
40
41 import java.util.concurrent.ConcurrentHashMap
42
43 /**
44  * @author Vladislav.Soroka
45  * @since 12/20/13
46  */
47 class ExternalProjectBuilderImpl implements ModelBuilderService {
48
49   private final cache = new ConcurrentHashMap<String, ExternalProject>()
50   private final myTasksFactory = new TasksFactory()
51   private SourceSetCachedFinder mySourceSetFinder
52
53   @Override
54   public boolean canBuild(String modelName) {
55     return ExternalProject.name == modelName || ExternalProjectPreview.name == modelName
56   }
57
58   @Nullable
59   @Override
60   public Object buildAll(final String modelName, final Project project) {
61     ExternalProject externalProject = cache[project.path]
62     if (externalProject != null) return externalProject
63
64     if(!mySourceSetFinder) mySourceSetFinder = new SourceSetCachedFinder(project)
65
66     def resolveSourceSetDependencies = System.properties.'idea.resolveSourceSetDependencies' as boolean
67     def isPreview = ExternalProjectPreview.name == modelName
68     DefaultExternalProject defaultExternalProject = new DefaultExternalProject()
69     defaultExternalProject.externalSystemId = "GRADLE"
70     defaultExternalProject.name = project.name
71     defaultExternalProject.QName = ":" == project.path ? project.name : project.path
72     defaultExternalProject.version = wrap(project.version)
73     defaultExternalProject.description = project.description
74     defaultExternalProject.buildDir = project.buildDir
75     defaultExternalProject.buildFile = project.buildFile
76     defaultExternalProject.group = wrap(project.group)
77     defaultExternalProject.projectDir = project.projectDir
78     defaultExternalProject.sourceSets = getSourceSets(project, isPreview, resolveSourceSetDependencies)
79     defaultExternalProject.tasks = getTasks(project)
80
81     defaultExternalProject.plugins = getPlugins(project)
82     //defaultExternalProject.setProperties(project.getProperties())
83
84     addArtifactsData(project, defaultExternalProject)
85
86     final Map<String, ExternalProject> childProjects = new HashMap<String, ExternalProject>(project.getChildProjects().size())
87     for (Map.Entry<String, Project> projectEntry : project.getChildProjects().entrySet()) {
88       final Object externalProjectChild = buildAll(modelName, projectEntry.getValue())
89       if (externalProjectChild instanceof ExternalProject) {
90         childProjects.put(projectEntry.getKey(), (ExternalProject)externalProjectChild)
91       }
92     }
93     defaultExternalProject.setChildProjects(childProjects)
94     cache.put(project.getPath(), defaultExternalProject)
95
96     defaultExternalProject
97   }
98
99   static void addArtifactsData(final Project project, DefaultExternalProject externalProject) {
100     final List<File> artifacts = new ArrayList<File>();
101     for (Task task : project.getTasks()) {
102       if (task instanceof Jar) {
103         Jar jar = (Jar)task;
104         artifacts.add(jar.getArchivePath());
105       }
106     }
107     externalProject.setArtifacts(artifacts);
108
109     def configurationsByName = project.getConfigurations().getAsMap();
110     Map<String, Set<File>> artifactsByConfiguration = new HashMap<String, Set<File>>();
111     for (Map.Entry<String, Configuration> configurationEntry : configurationsByName.entrySet()) {
112       Set<File> files = configurationEntry.getValue().getAllArtifacts().getFiles().getFiles();
113       artifactsByConfiguration.put(configurationEntry.getKey(), files);
114     }
115     externalProject.setArtifactsByConfiguration(artifactsByConfiguration);
116   }
117
118   static Map<String, ExternalPlugin> getPlugins(Project project) {
119     def result = [:] as Map<String, ExternalPlugin>
120     project.convention.plugins.each { key, value ->
121       ExternalPlugin externalPlugin = new DefaultExternalPlugin()
122       externalPlugin.id = key
123       result.put(key, externalPlugin)
124     }
125
126     result
127   }
128
129   Map<String, ExternalTask> getTasks(Project project) {
130     def result = [:] as Map<String, DefaultExternalTask>
131
132     myTasksFactory.getTasks(project).each { Task task ->
133       DefaultExternalTask externalTask = result.get(task.name)
134       if (externalTask == null) {
135         externalTask = new DefaultExternalTask()
136         externalTask.name = task.name
137         externalTask.QName = task.name
138         externalTask.description = task.description
139         externalTask.group = task.group ?: "other"
140
141         def clazzName = task.class.canonicalName
142         def prefixIndex = clazzName.lastIndexOf('_Decorated')
143         externalTask.type = prefixIndex == -1 ? clazzName : clazzName.substring(0, prefixIndex)
144         result.put(externalTask.name, externalTask)
145       }
146
147       def projectTaskPath = (project.path == ':' ? ':' : project.path + ':') + task.name
148       if (projectTaskPath.equals(task.path)) {
149         externalTask.QName = task.path
150       }
151     }
152     result
153   }
154
155   private Map<String, ExternalSourceSet> getSourceSets(Project project, boolean isPreview, boolean resolveSourceSetDependencies) {
156     final IdeaPlugin ideaPlugin = project.getPlugins().findPlugin(IdeaPlugin.class);
157     def ideaPluginModule = ideaPlugin?.model?.module
158     boolean inheritOutputDirs = ideaPluginModule?.inheritOutputDirs ?: false
159     def ideaOutDir = ideaPluginModule?.outputDir
160     def ideaTestOutDir = ideaPluginModule?.testOutputDir
161     def generatedSourceDirs
162     def ideaSourceDirs
163     def ideaTestSourceDirs
164     def downloadJavadoc = false
165     def downloadSources = true
166     if(ideaPluginModule) {
167       generatedSourceDirs = ideaPluginModule.hasProperty("generatedSourceDirs") ? new LinkedHashSet<>(ideaPluginModule.generatedSourceDirs): null
168       ideaSourceDirs = new LinkedHashSet<>(ideaPluginModule.sourceDirs)
169       ideaTestSourceDirs = new LinkedHashSet<>(ideaPluginModule.testSourceDirs)
170       downloadJavadoc = ideaPluginModule.downloadJavadoc
171       downloadSources = ideaPluginModule.downloadSources
172     } else {
173       generatedSourceDirs = null
174       ideaSourceDirs = null
175       ideaTestSourceDirs = null
176     }
177
178     def projectSourceCompatibility
179     def projectTargetCompatibility
180
181     //noinspection GrUnresolvedAccess
182     if(project.hasProperty('sourceCompatibility') && project.sourceCompatibility instanceof JavaVersion) {
183       //noinspection GrUnresolvedAccess
184       projectSourceCompatibility = project.sourceCompatibility.name;
185     }
186     //noinspection GrUnresolvedAccess
187     if(project.hasProperty('targetCompatibility') && project.targetCompatibility instanceof JavaVersion) {
188       //noinspection GrUnresolvedAccess
189       projectTargetCompatibility = project.targetCompatibility.name;
190     }
191
192     def result = [:] as Map<String, ExternalSourceSet>
193     //noinspection GrUnresolvedAccess
194     if (!project.hasProperty("sourceSets") || !(project.sourceSets instanceof SourceSetContainer)) {
195       return result
196     }
197     //noinspection GrUnresolvedAccess
198     def sourceSets = project.sourceSets as SourceSetContainer
199
200     // ignore inherited source sets from parent project
201     def parentProject = project.parent
202     if (parentProject && parentProject.hasProperty("sourceSets") && parentProject.sourceSets instanceof SourceSetContainer) {
203       if(sourceSets.is(parentProject.sourceSets)){
204         return result
205       }
206     }
207
208     def (resourcesIncludes, resourcesExcludes, filterReaders) = getFilters(project, 'processResources')
209     def (testResourcesIncludes, testResourcesExcludes, testFilterReaders) = getFilters(project, 'processTestResources')
210     //def (javaIncludes,javaExcludes) = getFilters(project,'compileJava')
211
212     def additionalIdeaGenDirs = [] as Collection<File>
213     if(generatedSourceDirs && !generatedSourceDirs.isEmpty()) {
214       additionalIdeaGenDirs.addAll(generatedSourceDirs)
215     }
216     sourceSets.all { SourceSet sourceSet ->
217       ExternalSourceSet externalSourceSet = new DefaultExternalSourceSet()
218       externalSourceSet.name = sourceSet.name
219
220       def javaCompileTask = project.tasks.findByName(sourceSet.compileJavaTaskName)
221       if(javaCompileTask instanceof JavaCompile) {
222         externalSourceSet.sourceCompatibility = javaCompileTask.sourceCompatibility ?: projectSourceCompatibility
223         externalSourceSet.targetCompatibility = javaCompileTask.targetCompatibility ?: projectTargetCompatibility
224       } else {
225         externalSourceSet.sourceCompatibility = projectSourceCompatibility
226         externalSourceSet.targetCompatibility = projectTargetCompatibility
227       }
228
229       def sources = [:] as Map<ExternalSystemSourceType, ExternalSourceDirectorySet>
230       ExternalSourceDirectorySet resourcesDirectorySet = new DefaultExternalSourceDirectorySet()
231       resourcesDirectorySet.name = sourceSet.resources.name
232       resourcesDirectorySet.srcDirs = sourceSet.resources.srcDirs
233       resourcesDirectorySet.outputDir = chooseNotNull(sourceSet.output.resourcesDir, sourceSet.output.classesDir, project.buildDir)
234       resourcesDirectorySet.inheritedCompilerOutput = inheritOutputDirs
235
236       ExternalSourceDirectorySet javaDirectorySet = new DefaultExternalSourceDirectorySet()
237       javaDirectorySet.name = sourceSet.allJava.name
238       javaDirectorySet.srcDirs = sourceSet.allJava.srcDirs
239       javaDirectorySet.outputDir = chooseNotNull(sourceSet.output.classesDir, project.buildDir);
240       javaDirectorySet.inheritedCompilerOutput = inheritOutputDirs
241 //      javaDirectorySet.excludes = javaExcludes + sourceSet.java.excludes;
242 //      javaDirectorySet.includes = javaIncludes + sourceSet.java.includes;
243
244       ExternalSourceDirectorySet generatedDirectorySet = null
245       if(generatedSourceDirs && !generatedSourceDirs.isEmpty()) {
246         def files = new HashSet<File>()
247         for(File file : generatedSourceDirs) {
248           if(javaDirectorySet.srcDirs.contains(file)) {
249             files.add(file)
250           }
251         }
252         if(!files.isEmpty()) {
253           javaDirectorySet.srcDirs.removeAll(files)
254           generatedDirectorySet = new DefaultExternalSourceDirectorySet()
255           generatedDirectorySet.name = "generated " + javaDirectorySet.name
256           generatedDirectorySet.srcDirs = files
257           generatedDirectorySet.outputDir = javaDirectorySet.outputDir
258           generatedDirectorySet.inheritedCompilerOutput = javaDirectorySet.isCompilerOutputPathInherited()
259         }
260         additionalIdeaGenDirs.removeAll(files)
261       }
262
263       if (SourceSet.TEST_SOURCE_SET_NAME == sourceSet.name) {
264         if (!inheritOutputDirs && ideaTestOutDir != null) {
265           javaDirectorySet.outputDir = ideaTestOutDir
266           resourcesDirectorySet.outputDir = ideaTestOutDir
267         }
268         resourcesDirectorySet.excludes = testResourcesExcludes + sourceSet.resources.excludes;
269         resourcesDirectorySet.includes = testResourcesIncludes + sourceSet.resources.includes;
270         resourcesDirectorySet.filters = testFilterReaders
271         sources.put(ExternalSystemSourceType.TEST, javaDirectorySet)
272         sources.put(ExternalSystemSourceType.TEST_RESOURCE, resourcesDirectorySet)
273         if(generatedDirectorySet) {
274           sources.put(ExternalSystemSourceType.TEST_GENERATED, generatedDirectorySet)
275         }
276       }
277       else {
278         if (!inheritOutputDirs && SourceSet.MAIN_SOURCE_SET_NAME == sourceSet.name && ideaOutDir != null) {
279           javaDirectorySet.outputDir = ideaOutDir
280           resourcesDirectorySet.outputDir = ideaOutDir
281         }
282         resourcesDirectorySet.excludes = resourcesExcludes + sourceSet.resources.excludes;
283         resourcesDirectorySet.includes = resourcesIncludes + sourceSet.resources.includes;
284         resourcesDirectorySet.filters = filterReaders
285         sources.put(ExternalSystemSourceType.SOURCE, javaDirectorySet)
286         sources.put(ExternalSystemSourceType.RESOURCE, resourcesDirectorySet)
287
288         if(!resolveSourceSetDependencies && ideaTestSourceDirs) {
289           def testDirs = javaDirectorySet.srcDirs.intersect(ideaTestSourceDirs as Collection)
290           if(!testDirs.isEmpty()) {
291             javaDirectorySet.srcDirs.removeAll(ideaTestSourceDirs)
292
293             def testDirectorySet = new DefaultExternalSourceDirectorySet()
294             testDirectorySet.name = javaDirectorySet.name
295             testDirectorySet.srcDirs = testDirs
296             testDirectorySet.outputDir = javaDirectorySet.outputDir
297             testDirectorySet.inheritedCompilerOutput = javaDirectorySet.isCompilerOutputPathInherited()
298             sources.put(ExternalSystemSourceType.TEST, testDirectorySet)
299           }
300
301           def testResourcesDirs = resourcesDirectorySet.srcDirs.intersect(ideaTestSourceDirs as Collection)
302           if(!testResourcesDirs.isEmpty()) {
303             resourcesDirectorySet.srcDirs.removeAll(ideaTestSourceDirs)
304
305             def testResourcesDirectorySet = new DefaultExternalSourceDirectorySet()
306             testResourcesDirectorySet.name = resourcesDirectorySet.name
307             testResourcesDirectorySet.srcDirs = testResourcesDirs
308             testResourcesDirectorySet.outputDir = resourcesDirectorySet.outputDir
309             testResourcesDirectorySet.inheritedCompilerOutput = resourcesDirectorySet.isCompilerOutputPathInherited()
310             sources.put(ExternalSystemSourceType.TEST_RESOURCE, testResourcesDirectorySet)
311           }
312         }
313
314         if (generatedDirectorySet) {
315           sources.put(ExternalSystemSourceType.SOURCE_GENERATED, generatedDirectorySet)
316           if(!resolveSourceSetDependencies && ideaTestSourceDirs) {
317             def testGeneratedDirs = generatedDirectorySet.srcDirs.intersect(ideaTestSourceDirs as Collection)
318             if(!testGeneratedDirs.isEmpty()) {
319               generatedDirectorySet.srcDirs.removeAll(ideaTestSourceDirs)
320
321               def testGeneratedDirectorySet = new DefaultExternalSourceDirectorySet()
322               testGeneratedDirectorySet.name = generatedDirectorySet.name
323               testGeneratedDirectorySet.srcDirs = testGeneratedDirs
324               testGeneratedDirectorySet.outputDir = generatedDirectorySet.outputDir
325               testGeneratedDirectorySet.inheritedCompilerOutput = generatedDirectorySet.isCompilerOutputPathInherited()
326
327               sources.put(ExternalSystemSourceType.TEST_GENERATED, testGeneratedDirectorySet)
328             }
329           }
330         }
331
332         if (ideaPluginModule && SourceSet.MAIN_SOURCE_SET_NAME != sourceSet.name && SourceSet.TEST_SOURCE_SET_NAME != sourceSet.name) {
333           sources.values().each {
334             ideaSourceDirs.removeAll(it.srcDirs)
335             ideaTestSourceDirs.removeAll(it.srcDirs)
336           }
337         }
338       }
339
340       if(resolveSourceSetDependencies) {
341         def dependencies = new DependencyResolverImpl(project, isPreview, downloadJavadoc, downloadSources, mySourceSetFinder).resolveDependencies(sourceSet)
342         externalSourceSet.dependencies.addAll(dependencies)
343       }
344
345       externalSourceSet.sources = sources
346       result[sourceSet.name] = externalSourceSet
347     }
348
349     def mainSourceSet = result[SourceSet.MAIN_SOURCE_SET_NAME]
350     if(ideaPluginModule && mainSourceSet && ideaSourceDirs && !ideaSourceDirs.isEmpty()) {
351       def mainGradleSourceSet = sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)
352       if(mainGradleSourceSet) {
353         def mainSourceDirectorySet = mainSourceSet.sources[ExternalSystemSourceType.SOURCE]
354         if(mainSourceDirectorySet) {
355           mainSourceDirectorySet.srcDirs.addAll(ideaSourceDirs - (mainGradleSourceSet.resources.srcDirs + generatedSourceDirs))
356         }
357
358         if (!additionalIdeaGenDirs.isEmpty()) {
359           def mainAdditionalGenDirs = additionalIdeaGenDirs.intersect(ideaSourceDirs)
360           def mainGenSourceDirectorySet = mainSourceSet.sources[ExternalSystemSourceType.SOURCE_GENERATED]
361           if (mainGenSourceDirectorySet) {
362             mainGenSourceDirectorySet.srcDirs.addAll(mainAdditionalGenDirs)
363           }
364           else {
365             def generatedDirectorySet = new DefaultExternalSourceDirectorySet()
366             generatedDirectorySet.name = "generated " + mainSourceSet.name
367             generatedDirectorySet.srcDirs.addAll(mainAdditionalGenDirs)
368             generatedDirectorySet.outputDir = mainSourceDirectorySet.outputDir
369             generatedDirectorySet.inheritedCompilerOutput = mainSourceDirectorySet.isCompilerOutputPathInherited()
370             mainSourceSet.sources.put(ExternalSystemSourceType.SOURCE_GENERATED, generatedDirectorySet)
371           }
372         }
373       }
374     }
375
376     def testSourceSet = result[SourceSet.TEST_SOURCE_SET_NAME]
377     if(ideaPluginModule && testSourceSet && ideaTestSourceDirs && !ideaTestSourceDirs.isEmpty()) {
378       def testGradleSourceSet = sourceSets.findByName(SourceSet.TEST_SOURCE_SET_NAME)
379       if(testGradleSourceSet) {
380         def testSourceDirectorySet = testSourceSet.sources[ExternalSystemSourceType.TEST]
381         if(testSourceDirectorySet) {
382           testSourceDirectorySet.srcDirs.addAll(ideaTestSourceDirs - (testGradleSourceSet.resources.srcDirs + generatedSourceDirs))
383         }
384
385         if (!additionalIdeaGenDirs.isEmpty()) {
386           def testAdditionalGenDirs = additionalIdeaGenDirs.intersect(ideaTestSourceDirs)
387           def testGenSourceDirectorySet = testSourceSet.sources[ExternalSystemSourceType.TEST_GENERATED]
388           if (testGenSourceDirectorySet) {
389             testGenSourceDirectorySet.srcDirs.addAll(testAdditionalGenDirs)
390           }
391           else {
392             def generatedDirectorySet = new DefaultExternalSourceDirectorySet()
393             generatedDirectorySet.name = "generated " + testSourceSet.name
394             generatedDirectorySet.srcDirs.addAll(testAdditionalGenDirs)
395             generatedDirectorySet.outputDir = testSourceDirectorySet.outputDir
396             generatedDirectorySet.inheritedCompilerOutput = testSourceDirectorySet.isCompilerOutputPathInherited()
397             testSourceSet.sources.put(ExternalSystemSourceType.TEST_GENERATED, generatedDirectorySet)
398           }
399         }
400       }
401     }
402
403     cleanupSharedSourceFolders(result)
404
405     result
406   }
407
408   private static void cleanupSharedSourceFolders(Map<String, ExternalSourceSet> map) {
409     def mainSourceSet = map[SourceSet.MAIN_SOURCE_SET_NAME]
410     cleanupSharedSourceFolders(map, mainSourceSet, null)
411     cleanupSharedSourceFolders(map, map[SourceSet.TEST_SOURCE_SET_NAME], mainSourceSet)
412   }
413
414   private static void cleanupSharedSourceFolders(Map<String, ExternalSourceSet> result, ExternalSourceSet sourceSet, ExternalSourceSet toIgnore) {
415     if(!sourceSet) return
416
417     result.entrySet().each {
418       if (!it.value.is(sourceSet) && !it.value.is(toIgnore)) {
419         def customSourceSet = it.value
420         ExternalSystemSourceType.values().each {
421           def customSourceDirectorySet = customSourceSet.sources[it] as ExternalSourceDirectorySet
422           if (customSourceDirectorySet) {
423             def mainSourcesMap = sourceSet.sources
424             mainSourcesMap.values().each {
425               customSourceDirectorySet.srcDirs.removeAll(it.srcDirs)
426             }
427           }
428         }
429       }
430     }
431   }
432
433   static <T> T chooseNotNull(T ... params) {
434     //noinspection GrUnresolvedAccess
435     params.findResult("", { it })
436   }
437
438   static getFilters(Project project, String taskName) {
439     def includes = []
440     def excludes = []
441     def filterReaders = [] as List<ExternalFilter>
442     def filterableTask = project.tasks.findByName(taskName)
443     if (filterableTask instanceof PatternFilterable) {
444       includes += filterableTask.includes
445       excludes += filterableTask.excludes
446     }
447
448     if(System.getProperty('idea.disable.gradle.resource.filtering', 'false').toBoolean()) {
449       return [includes, excludes, filterReaders]
450     }
451
452     try {
453       if (filterableTask instanceof ContentFilterable && filterableTask.metaClass.respondsTo(filterableTask, "getMainSpec")) {
454         //noinspection GrUnresolvedAccess
455         def properties = filterableTask.getMainSpec().properties
456         def copyActions = properties?.allCopyActions ?: properties?.copyActions
457
458         if(copyActions) {
459           copyActions.each { Action<? super FileCopyDetails> action ->
460             if (action.hasProperty('val$filterType') && action.hasProperty('val$properties')) {
461               //noinspection GrUnresolvedAccess
462               def filterType = (action?.val$filterType as Class).name
463               def filter = [filterType: filterType] as DefaultExternalFilter
464               //noinspection GrUnresolvedAccess
465               def props = action?.val$properties
466               if (props) {
467                 if ('org.apache.tools.ant.filters.ExpandProperties'.equals(filterType) && props['project']) {
468                   if (props['project']) filter.propertiesAsJsonMap = new GsonBuilder().create().toJson(props['project'].properties);
469                 }
470                 else {
471                   filter.propertiesAsJsonMap = new GsonBuilder().create().toJson(props);
472                 }
473               }
474               filterReaders << filter
475             }
476             else if (action.class.simpleName.equals('RenamingCopyAction') && action.hasProperty('transformer')) {
477               //noinspection GrUnresolvedAccess
478               if (action.transformer.hasProperty('matcher') && action?.transformer?.hasProperty('replacement')) {
479                 //noinspection GrUnresolvedAccess
480                 String pattern = action?.transformer?.matcher?.pattern()?.pattern
481                 //noinspection GrUnresolvedAccess
482                 String replacement = action?.transformer?.replacement
483                 def filter = [filterType: 'RenamingCopyFilter'] as DefaultExternalFilter
484                 if(pattern && replacement){
485                   filter.propertiesAsJsonMap = new GsonBuilder().create().toJson([pattern: pattern, replacement: replacement]);
486                   filterReaders << filter
487                 }
488               }
489             }
490 //          else {
491 //            project.logger.error(
492 //              ErrorMessageBuilder.create(project, "Resource configuration errors")
493 //                .withDescription("Unsupported copy action found: " + action.class.name).build())
494 //          }
495           }
496         }
497       }
498     }
499     catch (Exception ignore) {
500 //      project.logger.error(
501 //        ErrorMessageBuilder.create(project, e, "Resource configuration errors")
502 //          .withDescription("Unable to resolve resources filtering configuration").build())
503     }
504
505     return [includes, excludes, filterReaders]
506   }
507
508
509   private static String wrap(Object o) {
510     return o instanceof CharSequence ? o.toString() : ""
511   }
512
513   @NotNull
514   @Override
515   public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
516     return ErrorMessageBuilder.create(
517       project, e, "Project resolve errors"
518     ).withDescription("Unable to resolve additional project configuration.")
519   }
520 }