Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 41 additions & 16 deletions lib/src/commands/create/commands/create_subcommand.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ const _defaultDescription = 'A Very Good Project created by Very Good CLI.';
/// A method which returns a [Future<MasonGenerator>] given a [MasonBundle].
typedef MasonGeneratorFromBundle = Future<MasonGenerator> Function(MasonBundle);

/// Lazy resolvers for template vars, keyed by the brick var name.
typedef TemplateVarResolvers = Map<String, Object? Function()>;

/// {@template create_subcommand}
/// Generic class for sub commands of [CreateCommand].
/// {@endtemplate}
Expand Down Expand Up @@ -259,35 +262,45 @@ abstract class CreateSubCommand({
return ExitCode.success.code;
}

/// Responsible for returns the template parameters to be passed to the
/// template brick.
/// The template vars this command handles, keyed by the brick var name.
///
/// Each resolver is only invoked by [getTemplateVars], so the keys can be
/// read without parsing any arguments.
///
/// Override if the create sub command requires additional template
/// parameters.
/// Override to handle additional template vars, spreading
/// `super.templateVarResolvers` into the returned map.
///
/// For subcommands that mix with [OrgName], it includes 'org_name'.
/// For subcommands that mix with [Publishable], it includes 'publishable'.
/// For subcommands that mix with [Workspace], it includes 'workspace'.
@mustCallSuper
Map<String, dynamic> getTemplateVars() {
final projectName = this.projectName;
final projectDescription = this.projectDescription;

return <String, dynamic>{
'project_name': projectName,
'description': projectDescription,
if (this is OrgName) 'org_name': (this as OrgName).orgName,
if (this is Publishable) 'publishable': (this as Publishable).publishable,
if (this is Workspace) 'workspace': (this as Workspace).workspace,
};
}
TemplateVarResolvers get templateVarResolvers => {
'project_name': () => projectName,
'description': () => projectDescription,
};

/// Returns the template parameters to be passed to the template brick.
///
/// Computed from [templateVarResolvers]. Vars that resolve to `null` are
/// omitted so the template falls back to its default value.
@nonVirtual
Map<String, dynamic> getTemplateVars() => <String, dynamic>{
for (final MapEntry(:key, value: resolve) in templateVarResolvers.entries)
key: ?resolve(),
};
}

/// Mixin for [CreateSubCommand] subclasses that receives the org name
/// parameter.
///
/// Takes care of parsing from [argResults] and validating the org name.
mixin OrgName on CreateSubCommand {
@override
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'org_name': () => orgName,
};

/// Gets the organization name.
String get orgName {
final orgName = argResults.resolve<String>(
Expand Down Expand Up @@ -365,6 +378,12 @@ mixin MultiTemplates on CreateSubCommand {
/// Takes care of parsing it from [argResults] and pass it
/// to the brick generator.
mixin Publishable on CreateSubCommand {
@override
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'publishable': () => publishable,
};

/// Gets the publishable flag.
bool get publishable => argResults.resolve<bool>(
'publishable',
Expand All @@ -378,6 +397,12 @@ mixin Publishable on CreateSubCommand {
/// Takes care of parsing it from [argResults] and pass it
/// to the brick generator.
mixin Workspace on CreateSubCommand {
@override
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'workspace': () => workspace,
};

/// Gets the workspace flag.
bool get workspace => argResults.resolve<bool>(
'workspace',
Expand Down
15 changes: 5 additions & 10 deletions lib/src/commands/create/commands/dart_cli.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,9 @@ class CreateDartCLI({required super.logger, required super.generatorFromBundle})
Template get template => VeryGoodDartCLITemplate();

@override
Map<String, dynamic> getTemplateVars() {
final vars = super.getTemplateVars();

final executableName =
argResults['executable-name'] as String? ?? projectName;

vars['executable_name'] = executableName;

return vars;
}
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'executable_name': () =>
argResults['executable-name'] as String? ?? projectName,
};
}
18 changes: 8 additions & 10 deletions lib/src/commands/create/commands/docs_site.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,14 @@ class CreateDocsSite({
String get description => 'Generate a Very Good documentation site.';

@override
Map<String, dynamic> getTemplateVars() {
return <String, dynamic>{
...super.getTemplateVars(),
'org_name': argResults.resolve<String>(
'org-name',
createConfig.orgName,
fallbackValue: _defaultOrgName,
),
};
}
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'org_name': () => argResults.resolve<String>(
'org-name',
createConfig.orgName,
fallbackValue: _defaultOrgName,
),
};

@override
Template get template => VeryGoodDocsSiteTemplate();
Expand Down
10 changes: 4 additions & 6 deletions lib/src/commands/create/commands/flame_game.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ class CreateFlameGame({
Template get template => VeryGoodFlameGameTemplate();

@override
Map<String, dynamic> getTemplateVars() {
final vars = super.getTemplateVars();
final platforms = argResults['platforms'] as List<String>;
vars['platforms'] = platforms;
return vars;
}
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'platforms': () => argResults['platforms'] as List<String>,
};
}
18 changes: 5 additions & 13 deletions lib/src/commands/create/commands/flutter_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,11 @@ class CreateFlutterApp({
String get description => 'Generate a Very Good Flutter application.';

@override
Map<String, dynamic> getTemplateVars() {
final vars = super.getTemplateVars();

final applicationId = argResults['application-id'] as String?;
if (applicationId != null) {
vars['application_id'] = applicationId;
}

final platforms = argResults['platforms'] as List<String>;
vars['platforms'] = platforms;

return vars;
}
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'application_id': () => argResults['application-id'] as String?,
'platforms': () => argResults['platforms'] as List<String>,
};

@override
final List<Template> templates = [VeryGoodCoreTemplate()];
Expand Down
13 changes: 4 additions & 9 deletions lib/src/commands/create/commands/flutter_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,8 @@ class CreateFlutterPlugin({
Template get template => FlutterPluginTemplate();

@override
Map<String, dynamic> getTemplateVars() {
final vars = super.getTemplateVars();

final platforms = argResults['platforms'] as List<String>;

vars['platforms'] = platforms;

return vars;
}
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'platforms': () => argResults['platforms'] as List<String>,
};
}
56 changes: 56 additions & 0 deletions test/src/commands/create/create_subcommand_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ class _TestCreateSubCommandWithWorkspace({
required super.generatorFromBundle,
}) extends _TestCreateSubCommand with Workspace;

class _TestCreateSubCommandWithNullableVar({
required super.template,
required super.logger,
required super.generatorFromBundle,
}) extends _TestCreateSubCommand {
@override
TemplateVarResolvers get templateVarResolvers => {
...super.templateVarResolvers,
'nullable': () => null,
'present': () => 'value',
};
}

class _TestCreateSubCommandMultiTemplate({
@override required final List<Template> templates,
required super.logger,
Expand Down Expand Up @@ -159,6 +172,34 @@ Run "runner help" to see global options.''';
.having((o) => o.mandatory, 'mandatory', false),
});
expect(command.argParser.commands, isEmpty);
expect(command.templateVarResolvers.keys, [
'project_name',
'description',
]);
});
});

group('templateVarResolvers', () {
test('getTemplateVars omits vars that resolve to null', () {
final argResults = _MockArgResults();
when(() => argResults.rest).thenReturn(['test_project']);
when(() => argResults['description']).thenReturn('description');
when(() => argResults.wasParsed(any())).thenReturn(true);

final command = _TestCreateSubCommandWithNullableVar(
template: template,
logger: logger,
generatorFromBundle: null,
)..argResultOverrides = argResults;

expect(
command.getTemplateVars(),
equals({
'project_name': 'test_project',
'description': 'description',
'present': 'value',
}),
);
});
});

Expand Down Expand Up @@ -611,6 +652,11 @@ Run "runner help" to see global options.''';
.having((o) => o.aliases, 'aliases', ['org']),
);
expect(command.argParser.commands, isEmpty);
expect(command.templateVarResolvers.keys, [
'project_name',
'description',
'org_name',
]);
});
});

Expand Down Expand Up @@ -1391,6 +1437,11 @@ Run "runner help" to see global options.''';
.having((o) => o.aliases, 'aliases', <String>[]),
);
expect(command.argParser.commands, isEmpty);
expect(command.templateVarResolvers.keys, [
'project_name',
'description',
'publishable',
]);
});
});

Expand Down Expand Up @@ -1585,6 +1636,11 @@ Run "runner help" to see global options.''';
.having((o) => o.aliases, 'aliases', ['ws']),
);
expect(command.argParser.commands, isEmpty);
expect(command.templateVarResolvers.keys, [
'project_name',
'description',
'workspace',
]);
});
});

Expand Down
Loading