@@ -23,6 +23,7 @@ import org.gradle.api.DomainObjectSet
2323import org.gradle.api.Project
2424import org.gradle.api.Task
2525import org.gradle.api.specs.Specs
26+ import org.gradle.api.tasks.Copy
2627import org.gradle.util.GradleVersion
2728
2829/**
@@ -35,6 +36,9 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
3536 private static final String JACK_OPTIONS_PROPERTY_NAME = ' jackOptions'
3637 private static final String ANDROID = ' android'
3738 private static final String LINT_OPTIONS = ' lintOptions'
39+ private static final String GLOBAL_LINT_TASK_NAME = ' lint'
40+ private static final String XML = ' xml'
41+ private static final String HTML = ' html'
3842
3943 private final RemoteConfigLocator configLocator = new RemoteConfigLocator (ANDROID )
4044
@@ -45,17 +49,38 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
4549
4650 @Override
4751 void applyAndroidConfig (final Project project , final StaticCodeAnalysisExtension extension ) {
48- project. tasks. matching { Task it -> it. name == ' lint' } .all { Task t ->
52+ Class<? extends Task > lintTask = getLintTaskClass(project)
53+ project. tasks. withType(lintTask) { Task t ->
4954 setupTasks(t, project, extension)
5055
5156 configureLintTask(project, extension, t)
5257 }
5358 }
5459
60+ private static Class<? extends Task > getLintTaskClass (final Project project ) {
61+ try {
62+ // AGP 3.0+
63+ return getClass(). classLoader
64+ .loadClass(' com.android.build.gradle.tasks.LintBaseTask' ) as Class<? extends Task >
65+ } catch (ClassNotFoundException ignored) {
66+ try {
67+ // Older versions
68+ return getClass(). classLoader
69+ .loadClass(' com.android.build.gradle.tasks.Lint' ) as Class<? extends Task >
70+ } catch (ClassNotFoundException e) {
71+ // Something went wrong!
72+ warnUnexpectedException(project, ' Encountered an error trying to configure Android Lint tasks.' , e)
73+
74+ // Best effort, get the global lint task class (needs to be configured!)
75+ project. tasks. getByName(GLOBAL_LINT_TASK_NAME ). class
76+ }
77+ }
78+ }
79+
5580 private static void setupTasks (final Task lintTask , final Project project ,
5681 final StaticCodeAnalysisExtension extension ) {
57- Task resolveTask = project. tasks. create (' resolveAndroidLint' , ResolveAndroidLintTask )
58- Task cleanupTask = project. tasks. create (' cleanupAndroidLint' , CleanupAndroidLintTask )
82+ Task resolveTask = project. tasks. maybeCreate (' resolveAndroidLint' , ResolveAndroidLintTask )
83+ Task cleanupTask = project. tasks. maybeCreate (' cleanupAndroidLint' , CleanupAndroidLintTask )
5984
6085 lintTask. dependsOn resolveTask
6186 lintTask. finalizedBy cleanupTask
@@ -71,14 +96,12 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
7196 final File configSource , final Task lintTask ) {
7297 def lintOptions = project[ANDROID ][LINT_OPTIONS ]
7398
99+ // update global config
74100 lintOptions. with { it ->
75101 // TODO : This won't fail on warnings, just like Checkstyle.
76102 // See https://issues.gradle.org/browse/GRADLE-2888
77103 it[' abortOnError' ] = ! extension. ignoreErrors
78104
79- // Change output location for consistency with other plugins
80- it[' xmlOutput' ] = project. file(" ${ project.buildDir} /reports/android/lint-results.xml" )
81-
82105 // Update global config
83106 it[' lintConfig' ] = configSource
84107 }
@@ -94,6 +117,15 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
94117
95118 configureLintOptions(project, extension, config, lintTask)
96119
120+ if (lintTask. name == GLOBAL_LINT_TASK_NAME ) {
121+ // Change output location for consistency with other plugins
122+ // we copy as to not tamper with other lint tasks
123+ lintTask. finalizedBy(project. tasks. create(' copyLintReport' , Copy ) { Copy it ->
124+ it. from lintTask. outputs. files. filter { File f -> f. name. endsWith(' .xml' ) }
125+ it. into project. file(" ${ project.buildDir} /reports/android/lint-results.xml" )
126+ })
127+ }
128+
97129 try {
98130 configureLintInputsAndOutputs(project, lintTask)
99131
@@ -103,9 +135,8 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
103135 }
104136 } catch (Throwable e) {
105137 // Something went wrong!
106- project. logger. warn(' Encountered an error trying to set inputs and outputs for Android Lint ' +
107- ' tasks, it will be disabled. Please, report this incident in ' +
108- ' https://github.com/monits/static-code-analysis-plugin/issues' , e)
138+ warnUnexpectedException(project, ' Encountered an error trying to set inputs and outputs for Android Lint ' +
139+ ' tasks, it will be disabled.' , e)
109140
110141 // disable up-to-date caching
111142 lintTask. outputs. upToDateWhen {
@@ -114,6 +145,11 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
114145 }
115146 }
116147
148+ private static void warnUnexpectedException (final Project project , final String message , final Throwable e ) {
149+ project. logger. warn(message + ' Please, report this incident at ' +
150+ ' https://github.com/monits/static-code-analysis-plugin/issues' , e)
151+ }
152+
117153 private File obtainLintRules (final Project project , final StaticCodeAnalysisExtension config ,
118154 final Task lintTask ) {
119155 boolean remoteLocation = RemoteConfigLocator . isRemoteLocation(config. androidLintConfig)
@@ -150,27 +186,41 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
150186
151187 DomainObjectSet<?> variants = getVariants(project)
152188
153- String defaultReportVariant = null
154- variants. all {
155- def configuration = it. variantData. variantConfiguration
156- String variantName = it. name
157- String variantDirName = configuration. dirName
158-
159- lintTask. inputs. with {
160- dir(" ${ project.buildDir} /intermediates/classes/${ variantDirName} /" )
161- dir(" ${ project.buildDir} /intermediates/assets/${ variantDirName} /" )
162- dir(" ${ project.buildDir} /intermediates/manifests/full/${ variantDirName} /" )
163- dir(" ${ project.buildDir} /intermediates/res/merged/${ variantDirName} /" )
164- dir(" ${ project.buildDir} /intermediates/shaders/${ variantDirName} /" )
165- dir(" ${ project.buildDir} /intermediates/rs/${ variantDirName} /" )
189+ String variantName = AndroidHelper . lintTaskHasVariantInfo(project) ? lintTask. variantName
190+ : (lintTask. name. toLowerCase() - GLOBAL_LINT_TASK_NAME )
191+
192+ // Older plugins didn't setup input files, so up-to-date checks were futile
193+ if (lintTask. inputs. files. isEmpty()) {
194+ variants. matching { it. name == variantName || variantName == null || variantName. empty }. all {
195+ def configuration = it. variantData. variantConfiguration
196+ String variantDirName = configuration. dirName
197+
198+ lintTask. inputs. with {
199+ dir(" ${ project.buildDir} /intermediates/classes/${ variantDirName} /" )
200+ dir(" ${ project.buildDir} /intermediates/assets/${ variantDirName} /" )
201+ dir(" ${ project.buildDir} /intermediates/manifests/full/${ variantDirName} /" )
202+ dir(" ${ project.buildDir} /intermediates/res/merged/${ variantDirName} /" )
203+ dir(" ${ project.buildDir} /intermediates/shaders/${ variantDirName} /" )
204+ dir(" ${ project.buildDir} /intermediates/rs/${ variantDirName} /" )
205+ }
166206 }
207+ }
167208
168- if (! defaultReportVariant && configuration. buildType. isDebuggable() && ! usesJack(configuration)) {
169- defaultReportVariant = variantName
209+ // And none up to this date setup outputs for up-to-date checks and cache
210+ if ((variantName == null || variantName. empty) && AndroidHelper . globalLintIsVariant(project)) {
211+ boolean configFound = false
212+ variants. all {
213+ def configuration = it. variantData. variantConfiguration
214+ if (! configFound && configuration. buildType. isDebuggable() && ! usesJack(configuration)) {
215+ configFound = true
170216
171- addReportAsOutput(lintTask, project, xmlEnabled, xmlOutput, defaultReportVariant, ' xml' )
172- addReportAsOutput(lintTask, project, htmlEnabled, htmlOutput, defaultReportVariant, ' html' )
217+ addReportAsOutput(lintTask, project, xmlEnabled, xmlOutput, it. name, XML )
218+ addReportAsOutput(lintTask, project, htmlEnabled, htmlOutput, it. name, HTML )
219+ }
173220 }
221+ } else {
222+ addReportAsOutput(lintTask, project, xmlEnabled, xmlOutput, variantName, XML )
223+ addReportAsOutput(lintTask, project, htmlEnabled, htmlOutput, variantName, HTML )
174224 }
175225 }
176226
@@ -231,11 +281,11 @@ class AndroidLintConfigurator implements AnalysisConfigurator {
231281 File definiteOutput = output
232282 if (! output) {
233283 // Convention naming changed along the way
234- if (AndroidHelper . lintReportPerVariant(project) ) {
284+ if (variantName ) {
235285 definiteOutput = project. file(
236- " ${ project.buildDir } /outputs/ lint-results-${ variantName} .${ extension} " )
286+ AndroidHelper . getLintReportDir(project) + " lint-results-${ variantName} .${ extension} " )
237287 } else {
238- definiteOutput = project. file(" ${ project.buildDir } /outputs/ lint-results.${ extension} " )
288+ definiteOutput = project. file(AndroidHelper . getLintReportDir(project) + " lint-results.${ extension} " )
239289 }
240290 }
241291 task. outputs. file definiteOutput
0 commit comments