@@ -167,6 +167,9 @@ Future<void> run(List<String> arguments) async {
167167 printProgress ('Lint Kotlin files...' );
168168 await lintKotlinFiles (flutterRoot);
169169
170+ printProgress ('Lint generated Kotlin files from templates...' );
171+ await lintKotlinTemplatedFiles (flutterRoot);
172+
170173 // Ensure that all package dependencies are in sync.
171174 printProgress ('Package dependencies...' );
172175 await runCommand (flutter, < String > [
@@ -2460,6 +2463,66 @@ Future<void> verifyTabooDocumentation(String workingDirectory, {int minimumMatch
24602463 }
24612464}
24622465
2466+ final Map <String , String > _kKotlinTemplateKeys = < String , String > {
2467+ 'androidIdentifier' : 'dummyPackage' ,
2468+ 'pluginClass' : 'PluginClass' ,
2469+ 'projectName' : 'dummy' ,
2470+ 'agpVersion' : '0.0.0.1' ,
2471+ 'kotlinVersion' : '0.0.0.1' ,
2472+ };
2473+
2474+ final String _kKotlinTemplateRelativePath = path.join ('packages' , 'flutter_tools' , 'templates' );
2475+
2476+ const List <String > _kKotlinExtList = < String > ['.kt.tmpl' , '.kts.tmpl' ];
2477+ const String _kKotlinTmplExt = '.tmpl' ;
2478+ final RegExp _kKotlinTemplatePattern = RegExp (r'{{(.*?)}}' );
2479+
2480+ /// Copy kotlin template files from [_kKotlinTemplateRelativePath] into a system tmp folder
2481+ /// then replace template values with values from [_kKotlinTemplateKeys] or "'dummy'" if an
2482+ /// unknown key is found. Then run ktlint on the tmp folder to check for lint errors in the
2483+ /// generated Kotlin files.
2484+ Future <void > lintKotlinTemplatedFiles (String workingDirectory) async {
2485+ final String templatePath = path.join (workingDirectory, _kKotlinTemplateRelativePath);
2486+ final Iterable <File > files = Directory (templatePath)
2487+ .listSync (recursive: true )
2488+ .toList ()
2489+ .whereType <File >()
2490+ .where ((File file) => _kKotlinExtList.contains (path.extension (file.path, 2 )));
2491+
2492+ if (files.isEmpty) {
2493+ foundError (< String > ['No Kotlin template files found' ]);
2494+ return ;
2495+ }
2496+
2497+ final Directory tempDir = Directory .systemTemp.createTempSync ('template_output' );
2498+ for (final File templateFile in files) {
2499+ final String inputContent = await templateFile.readAsString ();
2500+ final String modifiedContent = inputContent.replaceAllMapped (
2501+ _kKotlinTemplatePattern,
2502+ (Match match) => _kKotlinTemplateKeys[match[1 ]] ?? 'dummy' ,
2503+ );
2504+
2505+ String outputFilename = path.basename (templateFile.path);
2506+ outputFilename = outputFilename.substring (
2507+ 0 ,
2508+ outputFilename.length - _kKotlinTmplExt.length,
2509+ ); // Remove '.tmpl' from file path
2510+
2511+ // Ensure the first letter of the generated class is uppercase (instead of pluginClass)
2512+ outputFilename = outputFilename.substring (0 , 1 ).toUpperCase () + outputFilename.substring (1 );
2513+
2514+ final String relativePath = path.dirname (path.relative (templateFile.path, from: templatePath));
2515+ final String outputDir = path.join (tempDir.path, relativePath);
2516+ await Directory (outputDir).create (recursive: true );
2517+ final String outputFile = path.join (outputDir, outputFilename);
2518+ final File output = File (outputFile);
2519+ await output.writeAsString (modifiedContent);
2520+ }
2521+ return lintKotlinFiles (tempDir.path).whenComplete (() {
2522+ tempDir.deleteSync (recursive: true );
2523+ });
2524+ }
2525+
24632526Future <void > lintKotlinFiles (String workingDirectory) async {
24642527 const String baselineRelativePath = 'dev/bots/test/analyze-test-input/ktlint-baseline.xml' ;
24652528 const String editorConfigRelativePath = 'dev/bots/test/analyze-test-input/.editorconfig' ;
0 commit comments