@@ -6,6 +6,7 @@ import 'package:file/file.dart';
6
6
7
7
import 'common/core.dart' ;
8
8
import 'common/package_looping_command.dart' ;
9
+ import 'common/plugin_utils.dart' ;
9
10
import 'common/repository_package.dart' ;
10
11
11
12
/// A command to enforce gradle file conventions and best practices.
@@ -84,6 +85,8 @@ class GradleCheckCommand extends PackageLoopingCommand {
84
85
.childFile ('AndroidManifest.xml' );
85
86
}
86
87
88
+ bool _isCommented (String line) => line.trim ().startsWith ('//' );
89
+
87
90
/// Validates the build.gradle file for a plugin
88
91
/// (some_plugin/android/build.gradle).
89
92
bool _validatePluginBuildGradle (RepositoryPackage package, File gradleFile) {
@@ -101,6 +104,9 @@ class GradleCheckCommand extends PackageLoopingCommand {
101
104
if (! _validateSourceCompatibilityVersion (lines)) {
102
105
succeeded = false ;
103
106
}
107
+ if (! _validateGradleDrivenLintConfig (package, lines)) {
108
+ succeeded = false ;
109
+ }
104
110
return succeeded;
105
111
}
106
112
@@ -110,9 +116,16 @@ class GradleCheckCommand extends PackageLoopingCommand {
110
116
RepositoryPackage package, File gradleFile) {
111
117
print ('${indentation }Validating '
112
118
'${getRelativePosixPath (gradleFile , from : package .directory )}.' );
113
- // TODO(stuartmorgan): Move the -Xlint validation from lint_android_command
114
- // to here.
115
- return true ;
119
+ final String contents = gradleFile.readAsStringSync ();
120
+ final List <String > lines = contents.split ('\n ' );
121
+
122
+ // This is tracked as a variable rather than a sequence of &&s so that all
123
+ // failures are reported at once, not just the first one.
124
+ bool succeeded = true ;
125
+ if (! _validateJavacLintConfig (package, lines)) {
126
+ succeeded = false ;
127
+ }
128
+ return succeeded;
116
129
}
117
130
118
131
/// Validates the app-level build.gradle for an example app (e.g.,
@@ -193,11 +206,9 @@ build.gradle "namespace" must match the "package" attribute in AndroidManifest.x
193
206
/// lead to compile errors that show up for clients, but not in CI).
194
207
bool _validateSourceCompatibilityVersion (List <String > gradleLines) {
195
208
if (! gradleLines.any ((String line) =>
196
- line.contains ('languageVersion' ) &&
197
- ! line.trim ().startsWith ('//' )) &&
209
+ line.contains ('languageVersion' ) && ! _isCommented (line)) &&
198
210
! gradleLines.any ((String line) =>
199
- line.contains ('sourceCompatibility' ) &&
200
- ! line.trim ().startsWith ('//' ))) {
211
+ line.contains ('sourceCompatibility' ) && ! _isCommented (line))) {
201
212
const String errorMessage = '''
202
213
build.gradle must set an explicit Java compatibility version.
203
214
@@ -225,4 +236,75 @@ for more details.''';
225
236
}
226
237
return true ;
227
238
}
239
+
240
+ /// Returns whether the given gradle content is configured to enable all
241
+ /// Gradle-driven lints (those checked by ./gradlew lint) and treat them as
242
+ /// errors.
243
+ bool _validateGradleDrivenLintConfig (
244
+ RepositoryPackage package, List <String > gradleLines) {
245
+ final List <String > gradleBuildContents = package
246
+ .platformDirectory (FlutterPlatform .android)
247
+ .childFile ('build.gradle' )
248
+ .readAsLinesSync ();
249
+ if (! gradleBuildContents.any ((String line) =>
250
+ line.contains ('checkAllWarnings true' ) && ! _isCommented (line)) ||
251
+ ! gradleBuildContents.any ((String line) =>
252
+ line.contains ('warningsAsErrors true' ) && ! _isCommented (line))) {
253
+ printError ('${indentation }This package is not configured to enable all '
254
+ 'Gradle-driven lint warnings and treat them as errors. '
255
+ 'Please add the following to the lintOptions section of '
256
+ 'android/build.gradle:' );
257
+ print ('''
258
+ checkAllWarnings true
259
+ warningsAsErrors true
260
+ ''' );
261
+ return false ;
262
+ }
263
+ return true ;
264
+ }
265
+
266
+ /// Validates whether the given [example] 's gradle content is configured to
267
+ /// build its plugin target with javac lints enabled and treated as errors,
268
+ /// if the enclosing package is a plugin.
269
+ ///
270
+ /// This can only be called on example packages. (Plugin packages should not
271
+ /// be configured this way, since it would affect clients.)
272
+ ///
273
+ /// If [example] 's enclosing package is not a plugin package, this just
274
+ /// returns true.
275
+ bool _validateJavacLintConfig (
276
+ RepositoryPackage example, List <String > gradleLines) {
277
+ final RepositoryPackage enclosingPackage = example.getEnclosingPackage ()! ;
278
+ if (! pluginSupportsPlatform (platformAndroid, enclosingPackage,
279
+ requiredMode: PlatformSupport .inline)) {
280
+ return true ;
281
+ }
282
+ final String enclosingPackageName = enclosingPackage.directory.basename;
283
+
284
+ // The check here is intentionally somewhat loose, to allow for the
285
+ // possibility of variations (e.g., not using Xlint:all in some cases, or
286
+ // passing other arguments).
287
+ if (! (gradleLines.any ((String line) =>
288
+ line.contains ('project(":$enclosingPackageName ")' )) &&
289
+ gradleLines.any ((String line) =>
290
+ line.contains ('options.compilerArgs' ) &&
291
+ line.contains ('-Xlint' ) &&
292
+ line.contains ('-Werror' )))) {
293
+ printError ('The example '
294
+ '"${getRelativePosixPath (example .directory , from : enclosingPackage .directory )}" '
295
+ 'is not configured to treat javac lints and warnings as errors. '
296
+ 'Please add the following to its build.gradle:' );
297
+ print ('''
298
+ gradle.projectsEvaluated {
299
+ project(":$enclosingPackageName ") {
300
+ tasks.withType(JavaCompile) {
301
+ options.compilerArgs << "-Xlint:all" << "-Werror"
302
+ }
303
+ }
304
+ }
305
+ ''' );
306
+ return false ;
307
+ }
308
+ return true ;
309
+ }
228
310
}
0 commit comments