From b028d2f641eb0401090a8aff96914695030f8d5f Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 22 May 2026 10:11:28 -0700 Subject: [PATCH 1/4] Set up gen_defaults package --- .../tool/m3e_gen_defaults/README.md | 24 ++++++ .../m3e_gen_defaults/analysis_options.yaml | 4 + .../m3e_gen_defaults/bin/gen_defaults.dart | 28 +++++++ .../tool/m3e_gen_defaults/pubspec.yaml | 15 ++++ .../m3e_gen_defaults/templates/template.dart | 77 +++++++++++++++++++ .../test/gen_defaults_test.dart | 77 +++++++++++++++++++ .../test/test_fixtures/button_template.dart | 28 +++++++ .../test/test_fixtures/button_token_data.dart | 8 ++ 8 files changed, 261 insertions(+) create mode 100644 packages/material_ui/tool/m3e_gen_defaults/README.md create mode 100644 packages/material_ui/tool/m3e_gen_defaults/analysis_options.yaml create mode 100644 packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart create mode 100644 packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml create mode 100644 packages/material_ui/tool/m3e_gen_defaults/templates/template.dart create mode 100644 packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart create mode 100644 packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart create mode 100644 packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart diff --git a/packages/material_ui/tool/m3e_gen_defaults/README.md b/packages/material_ui/tool/m3e_gen_defaults/README.md new file mode 100644 index 000000000000..f0d300074fe4 --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/README.md @@ -0,0 +1,24 @@ +## Token Defaults Generator + +Script that generates component theme data defaults based on token data. + +## Usage +Run this program from the root of the git repository: +```sh +dart packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart [-v] +``` + +This updates generated component theming files under +`packages/material_ui/lib/src/m3e/generated`. + +## Templates + +There is a template file for every component that needs defaults from the token +database. These templates are implemented as subclasses of `TokenTemplate`. + +Templates need to override the `generateContents` method to provide the +generated code block as a string. + +## Tokens + +Tokens are stored in `data/`, and are sourced from an internal Google database. \ No newline at end of file diff --git a/packages/material_ui/tool/m3e_gen_defaults/analysis_options.yaml b/packages/material_ui/tool/m3e_gen_defaults/analysis_options.yaml new file mode 100644 index 000000000000..1fb98de01a0b --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/analysis_options.yaml @@ -0,0 +1,4 @@ +include: ../../../../analysis_options.yaml + +formatter: + page_width: 100 diff --git a/packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart b/packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart new file mode 100644 index 000000000000..42e66881f10a --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart @@ -0,0 +1,28 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ## Usage +// +// Run from the root of flutter/packages: +// +// ``` +// dart packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart [-v] +// ``` + +import 'package:args/args.dart'; + +// TODO(elliette): Import template files. +// import '../templates/x_template.dart'; + +Future main(List args) async { + // Parse arguments + final parser = ArgParser(); + parser.addFlag('verbose', abbr: 'v', help: 'Enable verbose output', negatable: false); + final ArgResults argResults = parser.parse(args); + // TODO(elliette): Add token logger when verbose flag is used. + // ignore: unused_local_variable + final verbose = argResults['verbose'] as bool; + // TODO(elliette): Invoke template generators. + // const XTemplate().generateFile(verbose: verbose); +} diff --git a/packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml b/packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml new file mode 100644 index 000000000000..2fdde7945bad --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml @@ -0,0 +1,15 @@ +name: gen_defaults +description: A command line script to generate Material component defaults from the token database. +version: 1.0.0 + +environment: + sdk: ^3.10.0-0 + +resolution: workspace + +dependencies: + args: any + +dev_dependencies: + path: any + test: any diff --git a/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart b/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart new file mode 100644 index 000000000000..e0c8a71865e8 --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart @@ -0,0 +1,77 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +abstract class TokenTemplate { + const TokenTemplate(); + + /// The name of the template, which corresponds to the target file name. + /// E.g., 'typography' for generating 'typography_defaults.g.dart'. + String get name; + + static const String copyrightHeader = ''' +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +'''; + + static const String headerComment = ''' + +// Do not edit by hand. The code is generated from data in the Material +// Design token database by the script: +// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart. + +// dart format off +'''; + + static const String footerComment = ''' +// dart format on +'''; + + String generateContents(); + + void generateFile({bool verbose = false}) { + final fileName = '$materialLib/${name}_defaults.g.dart'; + if (verbose) { + stdout.writeln('Generating file: $fileName'); + stdout.writeln('Target parent file name: $name.dart'); + } + final file = File(fileName); + if (!file.existsSync()) { + if (verbose) { + stdout.writeln('File does not exist, creating it.'); + } + file.createSync(); + } + + final parentName = '$name.dart'; + + if (verbose) { + stdout.writeln('Generating contents...'); + } + final buffer = StringBuffer(); + buffer.write(copyrightHeader); + buffer.write(headerComment); + buffer.write("part of '../$parentName';\n\n"); + buffer.write(generateContents()); + buffer.write(footerComment); + + if (verbose) { + stdout.writeln('Writing generated contents to $fileName...'); + } + file.writeAsStringSync(buffer.toString()); + if (verbose) { + stdout.writeln('Done generating $fileName.'); + } + } + + String get materialLib { + const repoPath = 'packages/material_ui/lib/src/generated'; + if (Directory(repoPath).existsSync()) { + return repoPath; + } + return 'lib/src/generated'; + } +} diff --git a/packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart b/packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart new file mode 100644 index 000000000000..7451c5e1c4b2 --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart @@ -0,0 +1,77 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:test/test.dart'; +import 'test_fixtures/button_template.dart'; + +void main() { + group('TokenTemplate', () { + test( + 'Templates will generate a part file ending in _defaults.g.dart with correct parent reference', + () { + final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults'); + try { + final template = ButtonTemplate(tempDir.path); + template.generateFile(); + + final file = File('${tempDir.path}/button_defaults.g.dart'); + expect(file.readAsStringSync(), ''' +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Do not edit by hand. The code is generated from data in the Material +// Design token database by the script: +// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart. + +// dart format off +part of '../button.dart'; + +abstract final class _ButtonDefaults { + static const double height = 40.0; + static const double borderRadius = 8.0; +} +// dart format on +'''); + } finally { + tempDir.deleteSync(recursive: true); + } + }, + ); + + test('Templates will completely overwrite any previous code', () { + final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults'); + try { + // Seed the file with pre-existing random text. + final file = File('${tempDir.path}/button_defaults.g.dart'); + file.writeAsStringSync('Pre-existing random text.'); + + final templateNew = ButtonTemplate(tempDir.path); + templateNew.generateFile(); + expect(file.readAsStringSync(), ''' +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Do not edit by hand. The code is generated from data in the Material +// Design token database by the script: +// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart. + +// dart format off +part of '../button.dart'; + +abstract final class _ButtonDefaults { + static const double height = 40.0; + static const double borderRadius = 8.0; +} +// dart format on +'''); + } finally { + tempDir.deleteSync(recursive: true); + } + }); + }); +} diff --git a/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart b/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart new file mode 100644 index 000000000000..ed5742162c94 --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart @@ -0,0 +1,28 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../../templates/template.dart'; +import 'button_token_data.dart'; + +class ButtonTemplate extends TokenTemplate { + ButtonTemplate(this.customMaterialLib); + + final String customMaterialLib; + + @override + String get name => 'button'; + + @override + String get materialLib => customMaterialLib; + + @override + String generateContents() { + return ''' +abstract final class _ButtonDefaults { + static const double height = ${TokenButton.height}; + static const double borderRadius = ${TokenButton.borderRadius}; +} +'''; + } +} diff --git a/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart b/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart new file mode 100644 index 000000000000..539da016e907 --- /dev/null +++ b/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart @@ -0,0 +1,8 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +abstract final class TokenButton { + static const double height = 40.0; + static const double borderRadius = 8.0; +} From 4bf8b1a28a47f5c2a8878225761a04c96aa44d4f Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 22 May 2026 10:27:34 -0700 Subject: [PATCH 2/4] Updates based on code assist review --- packages/material_ui/pubspec.yaml | 1 + .../tool/m3e_gen_defaults/templates/template.dart | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/material_ui/pubspec.yaml b/packages/material_ui/pubspec.yaml index 70489e1f2f61..fab783e33bd1 100644 --- a/packages/material_ui/pubspec.yaml +++ b/packages/material_ui/pubspec.yaml @@ -11,6 +11,7 @@ environment: workspace: - example + - tool/m3e_gen_defaults dependencies: cupertino_ui: diff --git a/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart b/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart index e0c8a71865e8..8d4e1fc12df1 100644 --- a/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart +++ b/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart @@ -43,7 +43,7 @@ abstract class TokenTemplate { if (verbose) { stdout.writeln('File does not exist, creating it.'); } - file.createSync(); + file.createSync(recursive: true); } final parentName = '$name.dart'; @@ -68,10 +68,11 @@ abstract class TokenTemplate { } String get materialLib { - const repoPath = 'packages/material_ui/lib/src/generated'; - if (Directory(repoPath).existsSync()) { - return repoPath; + const packagePath = 'packages/material_ui'; + const relativeOutputPath = 'lib/src/m3e/generated'; + if (Directory(packagePath).existsSync()) { + return '$packagePath/$relativeOutputPath'; } - return 'lib/src/generated'; + return relativeOutputPath; } } From 58f34c369def1c5687975e7b565477d84871f4b7 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 26 May 2026 14:56:39 -0700 Subject: [PATCH 3/4] Respond to PR comments --- packages/material_ui/pubspec.yaml | 2 +- .../README.md | 6 +- .../analysis_options.yaml | 0 .../bin/gen_defaults.dart | 2 +- .../pubspec.yaml | 1 + .../templates/template.dart | 77 ++++++++---- .../gen_defaults/test/gen_defaults_test.dart | 112 ++++++++++++++++++ .../test/test_fixtures/button_token_data.dart | 2 +- .../test/test_fixtures/test_templates.dart | 66 +++++++++++ .../test/gen_defaults_test.dart | 77 ------------ .../test/test_fixtures/button_template.dart | 28 ----- 11 files changed, 240 insertions(+), 133 deletions(-) rename packages/material_ui/tool/{m3e_gen_defaults => gen_defaults}/README.md (70%) rename packages/material_ui/tool/{m3e_gen_defaults => gen_defaults}/analysis_options.yaml (100%) rename packages/material_ui/tool/{m3e_gen_defaults => gen_defaults}/bin/gen_defaults.dart (91%) rename packages/material_ui/tool/{m3e_gen_defaults => gen_defaults}/pubspec.yaml (95%) rename packages/material_ui/tool/{m3e_gen_defaults => gen_defaults}/templates/template.dart (55%) create mode 100644 packages/material_ui/tool/gen_defaults/test/gen_defaults_test.dart rename packages/material_ui/tool/{m3e_gen_defaults => gen_defaults}/test/test_fixtures/button_token_data.dart (86%) create mode 100644 packages/material_ui/tool/gen_defaults/test/test_fixtures/test_templates.dart delete mode 100644 packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart delete mode 100644 packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart diff --git a/packages/material_ui/pubspec.yaml b/packages/material_ui/pubspec.yaml index fab783e33bd1..e3a8b6073409 100644 --- a/packages/material_ui/pubspec.yaml +++ b/packages/material_ui/pubspec.yaml @@ -11,7 +11,7 @@ environment: workspace: - example - - tool/m3e_gen_defaults + - tool/gen_defaults dependencies: cupertino_ui: diff --git a/packages/material_ui/tool/m3e_gen_defaults/README.md b/packages/material_ui/tool/gen_defaults/README.md similarity index 70% rename from packages/material_ui/tool/m3e_gen_defaults/README.md rename to packages/material_ui/tool/gen_defaults/README.md index f0d300074fe4..56581126a8ca 100644 --- a/packages/material_ui/tool/m3e_gen_defaults/README.md +++ b/packages/material_ui/tool/gen_defaults/README.md @@ -5,16 +5,16 @@ Script that generates component theme data defaults based on token data. ## Usage Run this program from the root of the git repository: ```sh -dart packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart [-v] +dart packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart [-v] ``` This updates generated component theming files under -`packages/material_ui/lib/src/m3e/generated`. +`packages/material_ui/lib/src/generated`. ## Templates There is a template file for every component that needs defaults from the token -database. These templates are implemented as subclasses of `TokenTemplate`. +database. These templates are implemented as subclasses of either `M3TokenTemplate` or `M3ETokenTemplate`. Templates need to override the `generateContents` method to provide the generated code block as a string. diff --git a/packages/material_ui/tool/m3e_gen_defaults/analysis_options.yaml b/packages/material_ui/tool/gen_defaults/analysis_options.yaml similarity index 100% rename from packages/material_ui/tool/m3e_gen_defaults/analysis_options.yaml rename to packages/material_ui/tool/gen_defaults/analysis_options.yaml diff --git a/packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart b/packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart similarity index 91% rename from packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart rename to packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart index 42e66881f10a..2da295bc4e99 100644 --- a/packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart +++ b/packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart @@ -7,7 +7,7 @@ // Run from the root of flutter/packages: // // ``` -// dart packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart [-v] +// dart packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart [-v] // ``` import 'package:args/args.dart'; diff --git a/packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml b/packages/material_ui/tool/gen_defaults/pubspec.yaml similarity index 95% rename from packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml rename to packages/material_ui/tool/gen_defaults/pubspec.yaml index 2fdde7945bad..ab49cbfc4384 100644 --- a/packages/material_ui/tool/m3e_gen_defaults/pubspec.yaml +++ b/packages/material_ui/tool/gen_defaults/pubspec.yaml @@ -9,6 +9,7 @@ resolution: workspace dependencies: args: any + meta: any dev_dependencies: path: any diff --git a/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart b/packages/material_ui/tool/gen_defaults/templates/template.dart similarity index 55% rename from packages/material_ui/tool/m3e_gen_defaults/templates/template.dart rename to packages/material_ui/tool/gen_defaults/templates/template.dart index 8d4e1fc12df1..e10ffca26693 100644 --- a/packages/material_ui/tool/m3e_gen_defaults/templates/template.dart +++ b/packages/material_ui/tool/gen_defaults/templates/template.dart @@ -4,12 +4,26 @@ import 'dart:io'; -abstract class TokenTemplate { - const TokenTemplate(); +import 'package:meta/meta.dart'; - /// The name of the template, which corresponds to the target file name. - /// E.g., 'typography' for generating 'typography_defaults.g.dart'. - String get name; +enum _MaterialVersion { material3, material3Expressive } + +abstract class M3TokenTemplate extends _TokenTemplate { + const M3TokenTemplate(); + + @override + _MaterialVersion get _version => _MaterialVersion.material3; +} + +abstract class M3ETokenTemplate extends _TokenTemplate { + const M3ETokenTemplate(); + + @override + _MaterialVersion get _version => _MaterialVersion.material3Expressive; +} + +abstract class _TokenTemplate { + const _TokenTemplate(); static const String copyrightHeader = ''' // Copyright 2013 The Flutter Authors @@ -21,14 +35,29 @@ abstract class TokenTemplate { // Do not edit by hand. The code is generated from data in the Material // Design token database by the script: -// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart. - -// dart format off +// packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart. '''; - static const String footerComment = ''' -// dart format on -'''; + /// The Material version this template is for. + _MaterialVersion get _version; + + /// The name of the template, which corresponds to the target file name. + /// E.g., 'typography' for generating 'typography_defaults.g.dart'. + String get name; + + @visibleForTesting + String get materialLib { + const packagePath = 'packages/material_ui'; + const generatedDirectory = 'lib/src/generated'; + final String relativeOutputPath = switch (_version) { + _MaterialVersion.material3 => generatedDirectory, + _MaterialVersion.material3Expressive => '$generatedDirectory/material_3_expressive', + }; + if (Directory(packagePath).existsSync()) { + return '$packagePath/$relativeOutputPath'; + } + return relativeOutputPath; + } String generateContents(); @@ -54,25 +83,29 @@ abstract class TokenTemplate { final buffer = StringBuffer(); buffer.write(copyrightHeader); buffer.write(headerComment); - buffer.write("part of '../$parentName';\n\n"); + final String partOfPath = switch (_version) { + _MaterialVersion.material3 => '../$parentName', + _MaterialVersion.material3Expressive => '../../material_3_expressive/$parentName', + }; + buffer.write("part of '$partOfPath';\n\n"); buffer.write(generateContents()); - buffer.write(footerComment); if (verbose) { stdout.writeln('Writing generated contents to $fileName...'); } file.writeAsStringSync(buffer.toString()); if (verbose) { - stdout.writeln('Done generating $fileName.'); + stdout.writeln('Formatting $fileName...'); } - } - - String get materialLib { - const packagePath = 'packages/material_ui'; - const relativeOutputPath = 'lib/src/m3e/generated'; - if (Directory(packagePath).existsSync()) { - return '$packagePath/$relativeOutputPath'; + final ProcessResult result = Process.runSync(Platform.resolvedExecutable, [ + 'format', + fileName, + ]); + if (result.exitCode != 0) { + stderr.writeln('Failed to format $fileName: ${result.stderr}'); + } + if (verbose) { + stdout.writeln('Done generating $fileName.'); } - return relativeOutputPath; } } diff --git a/packages/material_ui/tool/gen_defaults/test/gen_defaults_test.dart b/packages/material_ui/tool/gen_defaults/test/gen_defaults_test.dart new file mode 100644 index 000000000000..91053fcd959d --- /dev/null +++ b/packages/material_ui/tool/gen_defaults/test/gen_defaults_test.dart @@ -0,0 +1,112 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:test/test.dart'; +import 'test_fixtures/test_templates.dart'; + +void main() { + Directory? tempDir; + String testPath() => tempDir!.path; + + group('gen_defaults templates', () { + setUp(() { + tempDir = Directory.systemTemp.createTempSync('gen_defaults'); + }); + + tearDown(() { + tempDir!.deleteSync(recursive: true); + }); + + test('will generate a part file ending in _defaults.g.dart', () { + final template = ButtonTemplate(testPath()); + template.generateFile(verbose: true); + + final file = File('${testPath()}/button_defaults.g.dart'); + expect(file.existsSync(), isTrue); + }); + + test('will generate a file with the correct header text', () { + final template = ButtonTemplate(testPath()); + template.generateFile(); + + final file = File('${testPath()}/button_defaults.g.dart'); + final String fileContents = file.readAsStringSync(); + expect(fileContents, contains(_fileHeader)); + }); + + test('will generate a file with the expected contents', () { + final template = ButtonTemplate(testPath()); + template.generateFile(); + + final file = File('${testPath()}/button_defaults.g.dart'); + final String fileContents = file.readAsStringSync(); + expect(fileContents, contains(_buttonDefaultsClass)); + }); + + test('will completely overwrite any previous code', () { + final file = File('${testPath()}/button_defaults.g.dart'); + const randomText = 'Pre-existing random text.'; + file.writeAsStringSync(randomText); + + final template = ButtonTemplate(testPath()); + template.generateFile(); + final String fileContents = file.readAsStringSync(); + expect(fileContents, isNot(contains(randomText))); + expect(fileContents, contains(_buttonDefaultsClass)); + }); + + test('will run dart format over the generated file', () { + final template = UnformattedTemplate(testPath()); + template.generateFile(); + + final file = File('${testPath()}/unformatted_defaults.g.dart'); + expect(file.readAsStringSync(), contains(formattedClass)); + }); + + test('materialLib path resolves correctly based on MaterialVersion', () { + final m3Template = TestM3Template(); + final m3ExpressiveTemplate = TestM3ExpressiveTemplate(); + const materialUiDir = 'packages/material_ui'; + const generatedDir = 'lib/src/generated'; + + final bool hasPackageDir = Directory(materialUiDir).existsSync(); + if (hasPackageDir) { + expect(m3Template.materialLib, '$materialUiDir/$generatedDir'); + expect( + m3ExpressiveTemplate.materialLib, + '$materialUiDir/$generatedDir/material_3_expressive', + ); + } else { + expect(m3Template.materialLib, generatedDir); + expect(m3ExpressiveTemplate.materialLib, '$generatedDir/material_3_expressive'); + } + }); + }); +} + +const _fileHeader = ''' +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Do not edit by hand. The code is generated from data in the Material +// Design token database by the script: +// packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart. +'''; + +const _buttonDefaultsClass = ''' +class _ButtonDefaults { + static const double height = 40.0; + static const double borderRadius = 8.0; +} +'''; + +const formattedClass = ''' +class UnformattedClass { + final int x = 1; + final String y = 'hello'; +} +'''; diff --git a/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart b/packages/material_ui/tool/gen_defaults/test/test_fixtures/button_token_data.dart similarity index 86% rename from packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart rename to packages/material_ui/tool/gen_defaults/test/test_fixtures/button_token_data.dart index 539da016e907..dbebb961a1e7 100644 --- a/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_token_data.dart +++ b/packages/material_ui/tool/gen_defaults/test/test_fixtures/button_token_data.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -abstract final class TokenButton { +class TokenButton { static const double height = 40.0; static const double borderRadius = 8.0; } diff --git a/packages/material_ui/tool/gen_defaults/test/test_fixtures/test_templates.dart b/packages/material_ui/tool/gen_defaults/test/test_fixtures/test_templates.dart new file mode 100644 index 000000000000..e56d0c8ef85d --- /dev/null +++ b/packages/material_ui/tool/gen_defaults/test/test_fixtures/test_templates.dart @@ -0,0 +1,66 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../../templates/template.dart'; +import 'button_token_data.dart'; + +class ButtonTemplate extends M3ETokenTemplate { + ButtonTemplate(this.customMaterialLib); + + final String customMaterialLib; + + @override + String get name => 'button'; + + @override + String get materialLib => customMaterialLib; + + @override + String generateContents() { + return ''' +class _ButtonDefaults { + static const double height = ${TokenButton.height}; + static const double borderRadius = ${TokenButton.borderRadius}; +} +'''; + } +} + +class UnformattedTemplate extends M3TokenTemplate { + UnformattedTemplate(this.customMaterialLib); + + final String customMaterialLib; + + @override + String get name => 'unformatted'; + + @override + String get materialLib => customMaterialLib; + + @override + String generateContents() { + return ''' +class UnformattedClass { +final int x = 1 ; + final String y = 'hello' ; +} +'''; + } +} + +class TestM3Template extends M3TokenTemplate { + @override + String get name => 'm3'; + + @override + String generateContents() => ''; +} + +class TestM3ExpressiveTemplate extends M3ETokenTemplate { + @override + String get name => 'm3e'; + + @override + String generateContents() => ''; +} diff --git a/packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart b/packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart deleted file mode 100644 index 7451c5e1c4b2..000000000000 --- a/packages/material_ui/tool/m3e_gen_defaults/test/gen_defaults_test.dart +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:test/test.dart'; -import 'test_fixtures/button_template.dart'; - -void main() { - group('TokenTemplate', () { - test( - 'Templates will generate a part file ending in _defaults.g.dart with correct parent reference', - () { - final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults'); - try { - final template = ButtonTemplate(tempDir.path); - template.generateFile(); - - final file = File('${tempDir.path}/button_defaults.g.dart'); - expect(file.readAsStringSync(), ''' -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Do not edit by hand. The code is generated from data in the Material -// Design token database by the script: -// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart. - -// dart format off -part of '../button.dart'; - -abstract final class _ButtonDefaults { - static const double height = 40.0; - static const double borderRadius = 8.0; -} -// dart format on -'''); - } finally { - tempDir.deleteSync(recursive: true); - } - }, - ); - - test('Templates will completely overwrite any previous code', () { - final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults'); - try { - // Seed the file with pre-existing random text. - final file = File('${tempDir.path}/button_defaults.g.dart'); - file.writeAsStringSync('Pre-existing random text.'); - - final templateNew = ButtonTemplate(tempDir.path); - templateNew.generateFile(); - expect(file.readAsStringSync(), ''' -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Do not edit by hand. The code is generated from data in the Material -// Design token database by the script: -// packages/material_ui/tool/m3e_gen_defaults/bin/gen_defaults.dart. - -// dart format off -part of '../button.dart'; - -abstract final class _ButtonDefaults { - static const double height = 40.0; - static const double borderRadius = 8.0; -} -// dart format on -'''); - } finally { - tempDir.deleteSync(recursive: true); - } - }); - }); -} diff --git a/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart b/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart deleted file mode 100644 index ed5742162c94..000000000000 --- a/packages/material_ui/tool/m3e_gen_defaults/test/test_fixtures/button_template.dart +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import '../../templates/template.dart'; -import 'button_token_data.dart'; - -class ButtonTemplate extends TokenTemplate { - ButtonTemplate(this.customMaterialLib); - - final String customMaterialLib; - - @override - String get name => 'button'; - - @override - String get materialLib => customMaterialLib; - - @override - String generateContents() { - return ''' -abstract final class _ButtonDefaults { - static const double height = ${TokenButton.height}; - static const double borderRadius = ${TokenButton.borderRadius}; -} -'''; - } -} From 5514450bb6eada99b0fe79ac7f9c0dd8b02d6399 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 26 May 2026 14:58:27 -0700 Subject: [PATCH 4/4] Set publish_to: none --- packages/material_ui/tool/gen_defaults/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/material_ui/tool/gen_defaults/pubspec.yaml b/packages/material_ui/tool/gen_defaults/pubspec.yaml index ab49cbfc4384..6ab022d87c3d 100644 --- a/packages/material_ui/tool/gen_defaults/pubspec.yaml +++ b/packages/material_ui/tool/gen_defaults/pubspec.yaml @@ -1,5 +1,6 @@ name: gen_defaults description: A command line script to generate Material component defaults from the token database. +publish_to: none version: 1.0.0 environment: