-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[material_ui] Set up gen_defaults sub-directory
#11762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ environment: | |
|
|
||
| workspace: | ||
| - example | ||
| - tool/gen_defaults | ||
|
|
||
| dependencies: | ||
| cupertino_ui: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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/gen_defaults/bin/gen_defaults.dart [-v] | ||
| ``` | ||
|
|
||
| This updates generated component theming files under | ||
| `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 either `M3TokenTemplate` or `M3ETokenTemplate`. | ||
|
|
||
| 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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| include: ../../../../analysis_options.yaml | ||
|
|
||
| formatter: | ||
| page_width: 100 |
28 changes: 28 additions & 0 deletions
28
packages/material_ui/tool/gen_defaults/bin/gen_defaults.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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/gen_defaults/bin/gen_defaults.dart [-v] | ||
| // ``` | ||
|
|
||
| import 'package:args/args.dart'; | ||
|
|
||
| // TODO(elliette): Import template files. | ||
| // import '../templates/x_template.dart'; | ||
|
|
||
| Future<void> main(List<String> 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); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| 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: | ||
| sdk: ^3.10.0-0 | ||
|
elliette marked this conversation as resolved.
|
||
|
|
||
| resolution: workspace | ||
|
elliette marked this conversation as resolved.
|
||
|
|
||
| dependencies: | ||
| args: any | ||
| meta: any | ||
|
|
||
| dev_dependencies: | ||
| path: any | ||
| test: any | ||
111 changes: 111 additions & 0 deletions
111
packages/material_ui/tool/gen_defaults/templates/template.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| // 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:meta/meta.dart'; | ||
|
|
||
| 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 | ||
| // 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/gen_defaults/bin/gen_defaults.dart. | ||
| '''; | ||
|
|
||
| /// 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(); | ||
|
|
||
| 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(recursive: true); | ||
| } | ||
|
|
||
| final parentName = '$name.dart'; | ||
|
|
||
| if (verbose) { | ||
| stdout.writeln('Generating contents...'); | ||
| } | ||
| final buffer = StringBuffer(); | ||
| buffer.write(copyrightHeader); | ||
| buffer.write(headerComment); | ||
| final String partOfPath = switch (_version) { | ||
| _MaterialVersion.material3 => '../$parentName', | ||
| _MaterialVersion.material3Expressive => '../../material_3_expressive/$parentName', | ||
| }; | ||
| buffer.write("part of '$partOfPath';\n\n"); | ||
| buffer.write(generateContents()); | ||
|
|
||
| if (verbose) { | ||
| stdout.writeln('Writing generated contents to $fileName...'); | ||
| } | ||
| file.writeAsStringSync(buffer.toString()); | ||
| if (verbose) { | ||
| stdout.writeln('Formatting $fileName...'); | ||
| } | ||
| final ProcessResult result = Process.runSync(Platform.resolvedExecutable, <String>[ | ||
| 'format', | ||
| fileName, | ||
| ]); | ||
| if (result.exitCode != 0) { | ||
| stderr.writeln('Failed to format $fileName: ${result.stderr}'); | ||
| } | ||
| if (verbose) { | ||
| stdout.writeln('Done generating $fileName.'); | ||
| } | ||
| } | ||
| } |
112 changes: 112 additions & 0 deletions
112
packages/material_ui/tool/gen_defaults/test/gen_defaults_test.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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'; | ||
| } | ||
| '''; |
8 changes: 8 additions & 0 deletions
8
packages/material_ui/tool/gen_defaults/test/test_fixtures/button_token_data.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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. | ||
|
|
||
| class TokenButton { | ||
| static const double height = 40.0; | ||
| static const double borderRadius = 8.0; | ||
| } |
66 changes: 66 additions & 0 deletions
66
packages/material_ui/tool/gen_defaults/test/test_fixtures/test_templates.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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() => ''; | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.