Refactor gen_defaults to support multiple generated code blocks in the same file independently. (#107278)

This commit is contained in:
Darren Austin
2022-07-10 17:17:09 -07:00
committed by GitHub
parent 7db73c0a93
commit d4061c19f4
33 changed files with 467 additions and 288 deletions

View File

@@ -15,10 +15,10 @@ dart dev/tools/gen_defaults/bin/gen_defaults.dart
There is a template file for every component that needs defaults from
the token database. These templates are implemented as subclasses of
`TokenTemplate`. This base class provides some utilities and a structure
for adding a new chunk of generated code to the bottom of a given file.
for adding a new block of generated code to the bottom of a given file.
Templates need to override the `generate` method to provide the generated
code chunk as a string. The tokens are represented as a `Map<String, dynamic>`
code block as a string. The tokens are represented as a `Map<String, dynamic>`
that is loaded from `data/material-tokens.json`. Templates can look up
whatever properties are needed in this structure to provide the properties
needed for the component.

View File

@@ -99,20 +99,20 @@ Future<void> main(List<String> args) async {
tokens['colorsLight'] = _readTokenFile('color_light.json');
tokens['colorsDark'] = _readTokenFile('color_dark.json');
AppBarTemplate('$materialLib/app_bar.dart', tokens).updateFile();
ButtonTemplate('md.comp.elevated-button', '$materialLib/elevated_button.dart', tokens).updateFile();
ButtonTemplate('md.comp.outlined-button', '$materialLib/outlined_button.dart', tokens).updateFile();
ButtonTemplate('md.comp.text-button', '$materialLib/text_button.dart', tokens).updateFile();
CardTemplate('$materialLib/card.dart', tokens).updateFile();
ChipActionTemplate('$materialLib/chip_action.dart', tokens).updateFile();
ChipFilterTemplate('$materialLib/chip_filter.dart', tokens).updateFile();
ChipFilterTemplate('$materialLib/chip_choice.dart', tokens).updateFile();
ChipInputTemplate('$materialLib/chip_input.dart', tokens).updateFile();
DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
IconButtonTemplate('$materialLib/icon_button.dart', tokens).updateFile();
NavigationBarTemplate('$materialLib/navigation_bar.dart', tokens).updateFile();
NavigationRailTemplate('$materialLib/navigation_rail.dart', tokens).updateFile();
SurfaceTintTemplate('$materialLib/elevation_overlay.dart', tokens).updateFile();
TypographyTemplate('$materialLib/typography.dart', tokens).updateFile();
AppBarTemplate('AppBar', '$materialLib/app_bar.dart', tokens).updateFile();
ButtonTemplate('md.comp.elevated-button', 'ElevatedButton', '$materialLib/elevated_button.dart', tokens).updateFile();
ButtonTemplate('md.comp.outlined-button', 'OutlinedButton', '$materialLib/outlined_button.dart', tokens).updateFile();
ButtonTemplate('md.comp.text-button', 'TextButton', '$materialLib/text_button.dart', tokens).updateFile();
CardTemplate('Card', '$materialLib/card.dart', tokens).updateFile();
ChipActionTemplate('ActionChip', '$materialLib/chip_action.dart', tokens).updateFile();
ChipFilterTemplate('FilterChip', '$materialLib/chip_filter.dart', tokens).updateFile();
ChipFilterTemplate('FilterChip', '$materialLib/chip_choice.dart', tokens).updateFile();
ChipInputTemplate('InputChip', '$materialLib/chip_input.dart', tokens).updateFile();
DialogTemplate('Dialog', '$materialLib/dialog.dart', tokens).updateFile();
FABTemplate('FAB', '$materialLib/floating_action_button.dart', tokens).updateFile();
IconButtonTemplate('IconButton', '$materialLib/icon_button.dart', tokens).updateFile();
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
TypographyTemplate('Typography', '$materialLib/typography.dart', tokens).updateFile();
}

View File

@@ -5,7 +5,7 @@
import 'template.dart';
class AppBarTemplate extends TokenTemplate {
const AppBarTemplate(super.fileName, super.tokens)
const AppBarTemplate(super.blockName, super.fileName, super.tokens)
: super(
colorSchemePrefix: '_colors.',
textThemePrefix: '_textTheme.',
@@ -13,9 +13,8 @@ class AppBarTemplate extends TokenTemplate {
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends AppBarTheme {
_TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends AppBarTheme {
_${blockName}DefaultsM3(this.context)
: super(
elevation: ${elevation('md.comp.top-app-bar.small.container')},
scrolledUnderElevation: ${elevation('md.comp.top-app-bar.small.on-scroll.container')},

View File

@@ -5,10 +5,9 @@
import 'template.dart';
class ButtonTemplate extends TokenTemplate {
const ButtonTemplate(this.tokenGroup, String fileName, Map<String, dynamic> tokens)
: super(fileName, tokens,
colorSchemePrefix: '_colors.',
);
const ButtonTemplate(this.tokenGroup, super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
});
final String tokenGroup;
@@ -55,9 +54,8 @@ class ButtonTemplate extends TokenTemplate {
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends ButtonStyle {
_TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends ButtonStyle {
_${blockName}DefaultsM3(this.context)
: super(
animationDuration: kThemeChangeDuration,
enableFeedback: true,

View File

@@ -5,13 +5,13 @@
import 'template.dart';
class CardTemplate extends TokenTemplate {
const CardTemplate(super.fileName, super.tokens);
const CardTemplate(super.blockName, super.fileName, super.tokens);
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends CardTheme {
const _TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends CardTheme {
const _${blockName}DefaultsM3(this.context)
: super(
clipBehavior: Clip.none,
elevation: ${elevation("md.comp.elevated-card.container")},

View File

@@ -6,16 +6,15 @@ import 'template.dart';
class ChipActionTemplate extends TokenTemplate {
const ChipActionTemplate(super.fileName, super.tokens);
const ChipActionTemplate(super.blockName, super.fileName, super.tokens);
static const String tokenGroup = 'md.comp.assist-chip';
static const String variant = '.flat';
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends ChipThemeData {
const _TokenDefaultsM3(this.context, this.isEnabled)
class _${blockName}DefaultsM3 extends ChipThemeData {
const _${blockName}DefaultsM3(this.context, this.isEnabled)
: super(
elevation: ${elevation("$tokenGroup$variant.container")},
shape: ${shape("$tokenGroup.container")},

View File

@@ -5,16 +5,15 @@
import 'template.dart';
class ChipFilterTemplate extends TokenTemplate {
const ChipFilterTemplate(super.fileName, super.tokens);
const ChipFilterTemplate(super.blockName, super.fileName, super.tokens);
static const String tokenGroup = 'md.comp.filter-chip';
static const String variant = '.flat';
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends ChipThemeData {
const _TokenDefaultsM3(this.context, this.isEnabled, this.isSelected)
class _${blockName}DefaultsM3 extends ChipThemeData {
const _${blockName}DefaultsM3(this.context, this.isEnabled, this.isSelected)
: super(
elevation: ${elevation("$tokenGroup$variant.container")},
shape: ${shape("$tokenGroup.container")},

View File

@@ -5,16 +5,15 @@
import 'template.dart';
class ChipInputTemplate extends TokenTemplate {
const ChipInputTemplate(super.fileName, super.tokens);
const ChipInputTemplate(super.blockName, super.fileName, super.tokens);
static const String tokenGroup = 'md.comp.input-chip';
static const String variant = '';
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends ChipThemeData {
const _TokenDefaultsM3(this.context, this.isEnabled)
class _${blockName}DefaultsM3 extends ChipThemeData {
const _${blockName}DefaultsM3(this.context, this.isEnabled)
: super(
elevation: ${elevation("$tokenGroup$variant.container")},
shape: ${shape("$tokenGroup.container")},

View File

@@ -5,16 +5,15 @@
import 'template.dart';
class DialogTemplate extends TokenTemplate {
const DialogTemplate(super.fileName, super.tokens)
: super(colorSchemePrefix: '_colors.',
textThemePrefix: '_textTheme.'
);
const DialogTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.'
});
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends DialogTheme {
_TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends DialogTheme {
_${blockName}DefaultsM3(this.context)
: super(
alignment: Alignment.center,
elevation: ${elevation("md.comp.dialog.container")},

View File

@@ -5,16 +5,15 @@
import 'template.dart';
class FABTemplate extends TokenTemplate {
const FABTemplate(super.fileName, super.tokens)
: super(colorSchemePrefix: '_colors.',
textThemePrefix: '_textTheme.',
);
const FABTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.',
});
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends FloatingActionButtonThemeData {
_TokenDefaultsM3(this.context, this.type, this.hasChild)
class _${blockName}DefaultsM3 extends FloatingActionButtonThemeData {
_${blockName}DefaultsM3(this.context, this.type, this.hasChild)
: super(
elevation: ${elevation("md.comp.fab.primary.container")},
focusElevation: ${elevation("md.comp.fab.primary.focus.container")},

View File

@@ -5,15 +5,14 @@
import 'template.dart';
class IconButtonTemplate extends TokenTemplate {
const IconButtonTemplate(super.fileName, super.tokens)
: super(colorSchemePrefix: '_colors.',
);
const IconButtonTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
});
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends ButtonStyle {
_TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends ButtonStyle {
_${blockName}DefaultsM3(this.context)
: super(
animationDuration: kThemeChangeDuration,
enableFeedback: true,

View File

@@ -5,16 +5,15 @@
import 'template.dart';
class NavigationBarTemplate extends TokenTemplate {
const NavigationBarTemplate(super.fileName, super.tokens)
: super(colorSchemePrefix: '_colors.',
textThemePrefix: '_textTheme.',
);
const NavigationBarTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.',
});
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends NavigationBarThemeData {
_TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends NavigationBarThemeData {
_${blockName}DefaultsM3(this.context)
: super(
height: ${tokens["md.comp.navigation-bar.container.height"]},
elevation: ${elevation("md.comp.navigation-bar.container")},

View File

@@ -5,16 +5,15 @@
import 'template.dart';
class NavigationRailTemplate extends TokenTemplate {
const NavigationRailTemplate(super.fileName, super.tokens)
: super(colorSchemePrefix: '_colors.',
textThemePrefix: '_textTheme.',
);
const NavigationRailTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.',
});
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends NavigationRailThemeData {
_TokenDefaultsM3(this.context)
class _${blockName}DefaultsM3 extends NavigationRailThemeData {
_${blockName}DefaultsM3(this.context)
: super(
elevation: ${elevation("md.comp.navigation-rail.container")},
groupAlignment: -1,

View File

@@ -5,12 +5,10 @@
import 'template.dart';
class SurfaceTintTemplate extends TokenTemplate {
const SurfaceTintTemplate(super.fileName, super.tokens);
const SurfaceTintTemplate(super.blockName, super.fileName, super.tokens);
@override
String generate() => '''
// Generated version ${tokens["version"]}
// Surface tint opacities based on elevations according to the
// Material Design 3 specification:
// https://m3.material.io/styles/color/the-color-system/color-roles

View File

@@ -5,50 +5,83 @@
import 'dart:io';
abstract class TokenTemplate {
const TokenTemplate(this.fileName, this.tokens, {
const TokenTemplate(this.blockName, this.fileName, this.tokens, {
this.colorSchemePrefix = 'Theme.of(context).colorScheme.',
this.textThemePrefix = 'Theme.of(context).textTheme.'
});
/// Name of the code block that this template will generate.
///
/// Used to identify an existing block when updating it.
final String blockName;
/// Name of the file that will be updated with the generated code.
final String fileName;
/// Map of token data extracted from the Material Design token database.
final Map<String, dynamic> tokens;
/// Optional prefix prepended to color definitions.
///
/// Defaults to 'Theme.of(context).colorScheme.'
final String colorSchemePrefix;
/// Optional prefix prepended to text style definitians.
///
/// Defaults to 'Theme.of(context).textTheme.'
final String textThemePrefix;
static const String beginGeneratedComment = '''
// BEGIN GENERATED TOKEN PROPERTIES
''';
// BEGIN GENERATED TOKEN PROPERTIES''';
static const String headerComment = '''
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
''';
static const String endGeneratedComment = '''
// END GENERATED TOKEN PROPERTIES
''';
final String fileName;
final Map<String, dynamic> tokens;
final String colorSchemePrefix;
final String textThemePrefix;
// END GENERATED TOKEN PROPERTIES''';
/// Replace or append the contents of the file with the text from [generate].
///
/// If the file already contains generated block at the end, it will
/// be replaced by the [generate] output. Otherwise the content will
/// just be appended to the end of the file.
/// If the file already contains a generated text block matching the
/// [blockName], it will be replaced by the [generate] output. Otherwise
/// the content will just be appended to the end of the file.
Future<void> updateFile() async {
String contents = File(fileName).readAsStringSync();
final int previousGeneratedIndex = contents.indexOf(beginGeneratedComment);
if (previousGeneratedIndex != -1) {
contents = contents.substring(0, previousGeneratedIndex);
final String contents = File(fileName).readAsStringSync();
final String beginComment = '$beginGeneratedComment - $blockName\n';
final String endComment = '$endGeneratedComment - $blockName\n';
final int beginPreviousBlock = contents.indexOf(beginComment);
final int endPreviousBlock = contents.indexOf(endComment);
late String contentBeforeBlock;
late String contentAfterBlock;
if (beginPreviousBlock != -1) {
if (endPreviousBlock < beginPreviousBlock) {
print('Unable to find block named $blockName in $fileName, skipping code generation.');
return;
}
// Found a valid block matching the name, so record the content before and after.
contentBeforeBlock = contents.substring(0, beginPreviousBlock);
contentAfterBlock = contents.substring(endPreviousBlock + endComment.length);
} else {
// Just append to the bottom.
contentBeforeBlock = contents;
contentAfterBlock = '';
}
final StringBuffer buffer = StringBuffer(contents);
buffer.write(beginGeneratedComment);
final StringBuffer buffer = StringBuffer(contentBeforeBlock);
buffer.write(beginComment);
buffer.write(headerComment);
buffer.write('// Token database version: ${tokens['version']}\n\n');
buffer.write(generate());
buffer.write(endGeneratedComment);
buffer.write(endComment);
buffer.write(contentAfterBlock);
File(fileName).writeAsStringSync(buffer.toString());
}

View File

@@ -5,11 +5,10 @@
import 'template.dart';
class TypographyTemplate extends TokenTemplate {
const TypographyTemplate(super.fileName, super.tokens);
const TypographyTemplate(super.blockName, super.fileName, super.tokens);
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _M3Typography {
_M3Typography._();

View File

@@ -23,24 +23,27 @@ void main() {
// Have a test template append new parameterized content to the end of
// the file.
final Map<String, dynamic> tokens = <String, dynamic>{'foo': 'Foobar', 'bar': 'Barfoo'};
TestTemplate(tempFile.path, tokens).updateFile();
final Map<String, dynamic> tokens = <String, dynamic>{'version': '0.0', 'foo': 'Foobar', 'bar': 'Barfoo'};
TestTemplate('Test', tempFile.path, tokens).updateFile();
expect(tempFile.readAsStringSync(), '''
// This is a file with stuff in it.
// This part shouldn't be changed by
// the template.
// BEGIN GENERATED TOKEN PROPERTIES
// BEGIN GENERATED TOKEN PROPERTIES - Test
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'Foobar';
static final String tokenBar = 'Barfoo';
// END GENERATED TOKEN PROPERTIES
// END GENERATED TOKEN PROPERTIES - Test
''');
} finally {
@@ -59,38 +62,166 @@ static final String tokenBar = 'Barfoo';
// This part shouldn't be changed by
// the template.
// BEGIN GENERATED TOKEN PROPERTIES
// BEGIN GENERATED TOKEN PROPERTIES - Test
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'Foobar';
static final String tokenBar = 'Barfoo';
// END GENERATED TOKEN PROPERTIES
// END GENERATED TOKEN PROPERTIES - Test
''');
// Have a test template append new parameterized content to the end of
// the file.
final Map<String, dynamic> tokens = <String, dynamic>{'foo': 'foo', 'bar': 'bar'};
TestTemplate(tempFile.path, tokens).updateFile();
final Map<String, dynamic> tokens = <String, dynamic>{'version': '0.0', 'foo': 'foo', 'bar': 'bar'};
TestTemplate('Test', tempFile.path, tokens).updateFile();
expect(tempFile.readAsStringSync(), '''
// This is a file with stuff in it.
// This part shouldn't be changed by
// the template.
// BEGIN GENERATED TOKEN PROPERTIES
// BEGIN GENERATED TOKEN PROPERTIES - Test
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'foo';
static final String tokenBar = 'bar';
// END GENERATED TOKEN PROPERTIES
// END GENERATED TOKEN PROPERTIES - Test
''');
} finally {
tempDir.deleteSync(recursive: true);
}
});
test('Multiple templates can modify different code blocks in the same file', () {
final Directory tempDir = Directory.systemTemp.createTempSync('gen_defaults');
try {
// Create a temporary file with some content.
final File tempFile = File(path.join(tempDir.path, 'test_template.txt'));
tempFile.createSync();
tempFile.writeAsStringSync('''
// This is a file with stuff in it.
// This part shouldn't be changed by
// the template.
''');
// Update file with a template for 'Block 1'
{
final Map<String, dynamic> tokens = <String, dynamic>{'version': '0.0', 'foo': 'foo', 'bar': 'bar'};
TestTemplate('Block 1', tempFile.path, tokens).updateFile();
}
expect(tempFile.readAsStringSync(), '''
// This is a file with stuff in it.
// This part shouldn't be changed by
// the template.
// BEGIN GENERATED TOKEN PROPERTIES - Block 1
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'foo';
static final String tokenBar = 'bar';
// END GENERATED TOKEN PROPERTIES - Block 1
''');
// Update file with a template for 'Block 2', which should append but not
// disturb the code in 'Block 1'.
{
final Map<String, dynamic> tokens = <String, dynamic>{'version': '0.0', 'foo': 'bar', 'bar': 'foo'};
TestTemplate('Block 2', tempFile.path, tokens).updateFile();
}
expect(tempFile.readAsStringSync(), '''
// This is a file with stuff in it.
// This part shouldn't be changed by
// the template.
// BEGIN GENERATED TOKEN PROPERTIES - Block 1
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'foo';
static final String tokenBar = 'bar';
// END GENERATED TOKEN PROPERTIES - Block 1
// BEGIN GENERATED TOKEN PROPERTIES - Block 2
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'bar';
static final String tokenBar = 'foo';
// END GENERATED TOKEN PROPERTIES - Block 2
''');
// Update 'Block 1' again which should just update that block,
// leaving 'Block 2' undisturbed.
{
final Map<String, dynamic> tokens = <String, dynamic>{'version': '0.0', 'foo': 'FOO', 'bar': 'BAR'};
TestTemplate('Block 1', tempFile.path, tokens).updateFile();
}
expect(tempFile.readAsStringSync(), '''
// This is a file with stuff in it.
// This part shouldn't be changed by
// the template.
// BEGIN GENERATED TOKEN PROPERTIES - Block 1
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'FOO';
static final String tokenBar = 'BAR';
// END GENERATED TOKEN PROPERTIES - Block 1
// BEGIN GENERATED TOKEN PROPERTIES - Block 2
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: 0.0
static final String tokenFoo = 'bar';
static final String tokenBar = 'foo';
// END GENERATED TOKEN PROPERTIES - Block 2
''');
} finally {
@@ -113,14 +244,14 @@ static final String tokenBar = 'bar';
'family': 'SHAPE_FAMILY_CIRCULAR',
},
};
final TestTemplate template = TestTemplate('foobar.dart', tokens);
final TestTemplate template = TestTemplate('Test', 'foobar.dart', tokens);
expect(template.shape('foo'), 'const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(1.0), topRight: Radius.circular(2.0), bottomLeft: Radius.circular(3.0), bottomRight: Radius.circular(4.0)))');
expect(template.shape('bar'), 'const StadiumBorder()');
});
}
class TestTemplate extends TokenTemplate {
TestTemplate(super.fileName, super.tokens);
TestTemplate(super.blockName, super.fileName, super.tokens);
@override
String generate() => '''