Migrate create command to null safety (#104484)

diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index dbe6753..f506a2f 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @dart = 2.8
-
 import '../android/gradle_utils.dart' as gradle;
 import '../base/common.dart';
 import '../base/context.dart';
@@ -32,8 +30,8 @@
 
 class CreateCommand extends CreateBase {
   CreateCommand({
-    bool verboseHelp = false,
-  }) : super(verboseHelp: verboseHelp) {
+    super.verboseHelp = false,
+  }) {
     addPlatformsOptions(customHelp: kPlatformHelp);
     argParser.addOption(
       'template',
@@ -57,7 +55,6 @@
         flutterProjectTypeToString(FlutterProjectType.module): 'Generate a project to add a Flutter module to an '
             'existing Android or iOS application.',
       },
-      defaultsTo: null,
     );
     argParser.addOption(
       'sample',
@@ -66,7 +63,6 @@
         '"--template=app". The value should be the sample ID of the desired sample from the API '
         'documentation website (http://docs.flutter.dev/). An example can be found at: '
         'https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html',
-      defaultsTo: null,
       valueHelp: 'id',
     );
     argParser.addOption(
@@ -88,7 +84,7 @@
   String get category => FlutterCommandCategory.project;
 
   @override
-  String get invocation => '${runner.executableName} $name <output directory>';
+  String get invocation => '${runner?.executableName} $name <output directory>';
 
   @override
   Future<CustomDimensions> get usageValues async {
@@ -100,8 +96,7 @@
   }
 
   // Lazy-initialize the net utilities with values from the context.
-  Net _cachedNet;
-  Net get _net => _cachedNet ??= Net(
+  late final Net _net = Net(
     httpClientFactory: context.get<HttpClientFactory>(),
     logger: globals.logger,
     platform: globals.platform,
@@ -112,7 +107,7 @@
         ? 'api.flutter.dev'
         : 'master-api.flutter.dev';
 
-  Future<String> _fetchSampleFromServer(String sampleId) async {
+  Future<String?> _fetchSampleFromServer(String sampleId) async {
     // Sanity check the sampleId
     if (sampleId.contains(RegExp(r'[^-\w\.]'))) {
       throwToolExit('Sample ID "$sampleId" contains invalid characters. Check the ID in the '
@@ -120,7 +115,7 @@
     }
 
     final Uri snippetsUri = Uri.https(_snippetsHost, 'snippets/$sampleId.dart');
-    final List<int> data = await _net.fetchUrl(snippetsUri);
+    final List<int>? data = await _net.fetchUrl(snippetsUri);
     if (data == null || data.isEmpty) {
       return null;
     }
@@ -128,9 +123,9 @@
   }
 
   /// Fetches the samples index file from the Flutter docs website.
-  Future<String> _fetchSamplesIndexFromServer() async {
+  Future<String?> _fetchSamplesIndexFromServer() async {
     final Uri snippetsUri = Uri.https(_snippetsHost, 'snippets/index.json');
-    final List<int> data = await _net.fetchUrl(snippetsUri, maxAttempts: 2);
+    final List<int>? data = await _net.fetchUrl(snippetsUri, maxAttempts: 2);
     if (data == null || data.isEmpty) {
       return null;
     }
@@ -145,7 +140,7 @@
       if (outputFile.existsSync()) {
         throwToolExit('File "$outputFilePath" already exists', exitCode: 1);
       }
-      final String samplesJson = await _fetchSamplesIndexFromServer();
+      final String? samplesJson = await _fetchSamplesIndexFromServer();
       if (samplesJson == null) {
         throwToolExit('Unable to download samples', exitCode: 2);
       } else {
@@ -158,11 +153,12 @@
   }
 
   FlutterProjectType _getProjectType(Directory projectDir) {
-    FlutterProjectType template;
-    FlutterProjectType detectedProjectType;
+    FlutterProjectType? template;
+    FlutterProjectType? detectedProjectType;
     final bool metadataExists = projectDir.absolute.childFile('.metadata').existsSync();
-    if (argResults['template'] != null) {
-      template = stringToProjectType(stringArgDeprecated('template'));
+    final String? templateArgument = stringArg('template');
+    if (templateArgument != null) {
+      template = stringToProjectType(templateArgument);
     }
     // If the project directory exists and isn't empty, then try to determine the template
     // type from the project directory.
@@ -188,23 +184,25 @@
 
   @override
   Future<FlutterCommandResult> runCommand() async {
-    if (argResults['list-samples'] != null) {
+    final String? listSamples = stringArg('list-samples');
+    if (listSamples != null) {
       // _writeSamplesJson can potentially be long-lived.
-      await _writeSamplesJson(stringArgDeprecated('list-samples'));
+      await _writeSamplesJson(listSamples);
       return FlutterCommandResult.success();
     }
 
     validateOutputDirectoryArg();
 
-    String sampleCode;
-    if (argResults['sample'] != null) {
-      if (argResults['template'] != null &&
-        stringToProjectType(stringArgDeprecated('template') ?? 'app') != FlutterProjectType.app) {
+    String? sampleCode;
+    final String? sampleArgument = stringArg('sample');
+    if (sampleArgument != null) {
+      final String? templateArgument = stringArg('template');
+      if (templateArgument != null && stringToProjectType(templateArgument) != FlutterProjectType.app) {
         throwToolExit('Cannot specify --sample with a project type other than '
           '"${flutterProjectTypeToString(FlutterProjectType.app)}"');
       }
       // Fetch the sample from the server.
-      sampleCode = await _fetchSampleFromServer(stringArgDeprecated('sample'));
+      sampleCode = await _fetchSampleFromServer(sampleArgument);
     }
 
     final FlutterProjectType template = _getProjectType(projectDir);
@@ -215,7 +213,7 @@
 
     final List<String> platforms = stringsArg('platforms');
     // `--platforms` does not support module or package.
-    if (argResults.wasParsed('platforms') && (generateModule || generatePackage)) {
+    if (argResults!.wasParsed('platforms') && (generateModule || generatePackage)) {
       final String template = generateModule ? 'module' : 'package';
       throwToolExit(
         'The "--platforms" argument is not supported in $template template.',
@@ -224,18 +222,18 @@
     } else if (platforms == null || platforms.isEmpty) {
       throwToolExit('Must specify at least one platform using --platforms',
         exitCode: 2);
-    } else if (generateFfiPlugin && argResults.wasParsed('platforms') && platforms.contains('web')) {
+    } else if (generateFfiPlugin && argResults!.wasParsed('platforms') && platforms.contains('web')) {
       throwToolExit(
         'The web platform is not supported in plugin_ffi template.',
         exitCode: 2,
       );
-    } else if (generateFfiPlugin && argResults.wasParsed('ios-language')) {
+    } else if (generateFfiPlugin && argResults!.wasParsed('ios-language')) {
       throwToolExit(
         'The "ios-language" option is not supported with the plugin_ffi '
         'template: the language will always be C or C++.',
         exitCode: 2,
       );
-    } else if (generateFfiPlugin && argResults.wasParsed('android-language')) {
+    } else if (generateFfiPlugin && argResults!.wasParsed('android-language')) {
       throwToolExit(
         'The "android-language" option is not supported with the plugin_ffi '
         'template: the language will always be C or C++.',
@@ -258,7 +256,7 @@
 
     final String dartSdk = globals.cache.dartSdkBuild;
     final bool includeIos = featureFlags.isIOSEnabled && platforms.contains('ios');
-    String developmentTeam;
+    String? developmentTeam;
     if (includeIos) {
       developmentTeam = await getCodeSigningIdentityDevelopmentTeam(
         processManager: globals.processManager,
@@ -272,7 +270,7 @@
     // The dart project_name is in snake_case, this variable is the Title Case of the Project Name.
     final String titleCaseProjectName = snakeCaseToTitleCase(projectName);
 
-    final Map<String, Object> templateContext = createTemplateContext(
+    final Map<String, Object?> templateContext = createTemplateContext(
       organization: organization,
       projectName: projectName,
       titleCaseProjectName: titleCaseProjectName,
@@ -432,12 +430,12 @@
 
   Future<int> _generateModule(
     Directory directory,
-    Map<String, dynamic> templateContext, {
+    Map<String, Object?> templateContext, {
     bool overwrite = false,
     bool printStatusWhenWriting = true,
   }) async {
     int generatedCount = 0;
-    final String description = argResults.wasParsed('description')
+    final String? description = argResults!.wasParsed('description')
         ? stringArgDeprecated('description')
         : 'A new Flutter module project.';
     templateContext['description'] = description;
@@ -453,7 +451,6 @@
         context: PubContext.create,
         directory: directory.path,
         offline: boolArgDeprecated('offline'),
-        generateSyntheticPackage: false,
       );
       final FlutterProject project = FlutterProject.fromDirectory(directory);
       await project.ensureReadyForPlatformSpecificTooling(
@@ -466,12 +463,12 @@
 
   Future<int> _generatePackage(
     Directory directory,
-    Map<String, dynamic> templateContext, {
+    Map<String, Object?> templateContext, {
     bool overwrite = false,
     bool printStatusWhenWriting = true,
   }) async {
     int generatedCount = 0;
-    final String description = argResults.wasParsed('description')
+    final String? description = argResults!.wasParsed('description')
         ? stringArgDeprecated('description')
         : 'A new Flutter package project.';
     templateContext['description'] = description;
@@ -487,7 +484,6 @@
         context: PubContext.createPackage,
         directory: directory.path,
         offline: boolArgDeprecated('offline'),
-        generateSyntheticPackage: false,
       );
     }
     return generatedCount;
@@ -495,13 +491,13 @@
 
   Future<int> _generateMethodChannelPlugin(
     Directory directory,
-    Map<String, dynamic> templateContext, {
+    Map<String, Object?> templateContext, {
     bool overwrite = false,
     bool printStatusWhenWriting = true,
-    FlutterProjectType projectType,
+    required FlutterProjectType projectType,
   }) async {
     // Plugins only add a platform if it was requested explicitly by the user.
-    if (!argResults.wasParsed('platforms')) {
+    if (!argResults!.wasParsed('platforms')) {
       for (final String platform in kAllCreatePlatforms) {
         templateContext[platform] = false;
       }
@@ -517,7 +513,7 @@
     final bool willAddPlatforms = platformsToAdd.isNotEmpty;
     templateContext['no_platforms'] = !willAddPlatforms;
     int generatedCount = 0;
-    final String description = argResults.wasParsed('description')
+    final String? description = argResults!.wasParsed('description')
         ? stringArgDeprecated('description')
         : 'A new Flutter plugin project.';
     templateContext['description'] = description;
@@ -534,7 +530,6 @@
         context: PubContext.createPlugin,
         directory: directory.path,
         offline: boolArgDeprecated('offline'),
-        generateSyntheticPackage: false,
       );
     }
 
@@ -545,9 +540,9 @@
         project: project, requireAndroidSdk: false);
     }
 
-    final String projectName = templateContext['projectName'] as String;
-    final String organization = templateContext['organization'] as String;
-    final String androidPluginIdentifier = templateContext['androidIdentifier'] as String;
+    final String? projectName = templateContext['projectName'] as String?;
+    final String organization = templateContext['organization']! as String; // Required to make the context.
+    final String? androidPluginIdentifier = templateContext['androidIdentifier'] as String?;
     final String exampleProjectName = '${projectName}_example';
     templateContext['projectName'] = exampleProjectName;
     templateContext['androidIdentifier'] = CreateBase.createAndroidIdentifier(organization, exampleProjectName);
@@ -572,13 +567,13 @@
 
   Future<int> _generateFfiPlugin(
     Directory directory,
-    Map<String, dynamic> templateContext, {
+    Map<String, Object?> templateContext, {
     bool overwrite = false,
     bool printStatusWhenWriting = true,
-    FlutterProjectType projectType,
+    required FlutterProjectType projectType,
   }) async {
     // Plugins only add a platform if it was requested explicitly by the user.
-    if (!argResults.wasParsed('platforms')) {
+    if (!argResults!.wasParsed('platforms')) {
       for (final String platform in kAllCreatePlatforms) {
         templateContext[platform] = false;
       }
@@ -596,7 +591,7 @@
     final bool willAddPlatforms = platformsToAdd.isNotEmpty;
     templateContext['no_platforms'] = !willAddPlatforms;
     int generatedCount = 0;
-    final String description = argResults.wasParsed('description')
+    final String? description = argResults!.wasParsed('description')
         ? stringArgDeprecated('description')
         : 'A new Flutter FFI plugin project.';
     templateContext['description'] = description;
@@ -613,7 +608,6 @@
         context: PubContext.createPlugin,
         directory: directory.path,
         offline: boolArgDeprecated('offline'),
-        generateSyntheticPackage: false,
       );
     }
 
@@ -623,9 +617,9 @@
       gradle.updateLocalProperties(project: project, requireAndroidSdk: false);
     }
 
-    final String projectName = templateContext['projectName'] as String;
-    final String organization = templateContext['organization'] as String;
-    final String androidPluginIdentifier = templateContext['androidIdentifier'] as String;
+    final String? projectName = templateContext['projectName'] as String?;
+    final String organization = templateContext['organization']! as String; // Required to make the context.
+    final String? androidPluginIdentifier = templateContext['androidIdentifier'] as String?;
     final String exampleProjectName = '${projectName}_example';
     templateContext['projectName'] = exampleProjectName;
     templateContext['androidIdentifier'] = CreateBase.createAndroidIdentifier(organization, exampleProjectName);
@@ -662,7 +656,7 @@
     return -files.length;
   }
 
-  List<String> _getSupportedPlatformsFromTemplateContext(Map<String, dynamic> templateContext) {
+  List<String> _getSupportedPlatformsFromTemplateContext(Map<String, Object?> templateContext) {
     return <String>[
       for (String platform in kAllCreatePlatforms)
         if (templateContext[platform] == true) platform,
@@ -671,7 +665,7 @@
 
   // Returns a list of platforms that are explicitly requested by user via `--platforms`.
   List<String> _getUserRequestedPlatforms() {
-    if (!argResults.wasParsed('platforms')) {
+    if (!argResults!.wasParsed('platforms')) {
       return <String>[];
     }
     return stringsArg('platforms');
@@ -682,10 +676,11 @@
 // Determine what platforms are supported based on generated files.
 List<String> _getSupportedPlatformsInPlugin(Directory projectDir) {
   final String pubspecPath = globals.fs.path.join(projectDir.absolute.path, 'pubspec.yaml');
-  final FlutterManifest manifest = FlutterManifest.createFromPath(pubspecPath, fileSystem: globals.fs, logger: globals.logger);
-  final List<String> platforms = manifest.validSupportedPlatforms == null
+  final FlutterManifest? manifest = FlutterManifest.createFromPath(pubspecPath, fileSystem: globals.fs, logger: globals.logger);
+  final Map<String, Object?>? validSupportedPlatforms = manifest?.validSupportedPlatforms;
+  final List<String> platforms = validSupportedPlatforms == null
     ? <String>[]
-    : manifest.validSupportedPlatforms.keys.toList();
+    : validSupportedPlatforms.keys.toList();
   return platforms;
 }
 
diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart
index 93aa539..d4e2c7a 100644
--- a/packages/flutter_tools/lib/src/commands/create_base.dart
+++ b/packages/flutter_tools/lib/src/commands/create_base.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @dart = 2.8
-
 import 'package:meta/meta.dart';
 import 'package:pub_semver/pub_semver.dart';
 import 'package:uuid/uuid.dart';
@@ -54,7 +52,7 @@
 /// Common behavior for `flutter create` commands.
 abstract class CreateBase extends FlutterCommand {
   CreateBase({
-    @required bool verboseHelp,
+    required bool verboseHelp,
   }) {
     argParser.addFlag(
       'pub',
@@ -64,7 +62,6 @@
     );
     argParser.addFlag(
       'offline',
-      defaultsTo: false,
       help:
           'When "flutter pub get" is run by the create command, this indicates '
           'whether to run it in offline mode or not. In offline mode, it will need to '
@@ -72,8 +69,6 @@
     );
     argParser.addFlag(
       'with-driver-test',
-      negatable: true,
-      defaultsTo: false,
       help: '(deprecated) Historically, this added a flutter_driver dependency and generated a '
             'sample "flutter drive" test. Now it does nothing. Consider using the '
             '"integration_test" package: https://pub.dev/packages/integration_test',
@@ -81,8 +76,6 @@
     );
     argParser.addFlag(
       'overwrite',
-      negatable: true,
-      defaultsTo: false,
       help: 'When performing operations, overwrite existing files.',
     );
     argParser.addOption(
@@ -100,7 +93,6 @@
     );
     argParser.addOption(
       'project-name',
-      defaultsTo: null,
       help:
           'The project name for this new Flutter project. This must be a valid dart package name.',
     );
@@ -134,7 +126,6 @@
     );
     argParser.addOption(
       'initial-create-revision',
-      defaultsTo: null,
       help: 'The Flutter SDK git commit hash to store in .migrate_config. This parameter is used by the tool '
             'internally and should generally not be used manually.',
       hide: !verboseHelp,
@@ -144,7 +135,7 @@
   /// The output directory of the command.
   @protected
   Directory get projectDir {
-    return globals.fs.directory(argResults.rest.first);
+    return globals.fs.directory(argResults!.rest.first);
   }
 
   /// The normalized absolute path of [projectDir].
@@ -157,7 +148,7 @@
   ///
   /// The help message of the argument is replaced with `customHelp` if `customHelp` is not null.
   @protected
-  void addPlatformsOptions({String customHelp}) {
+  void addPlatformsOptions({String? customHelp}) {
     argParser.addMultiOption('platforms',
       help: customHelp ?? _kDefaultPlatformArgumentHelp,
       aliases: <String>[ 'platform' ],
@@ -173,16 +164,17 @@
   /// Throw with exit code 2 if the output directory is invalid.
   @protected
   void validateOutputDirectoryArg() {
-    if (argResults.rest.isEmpty) {
+    final List<String>? rest = argResults?.rest;
+    if (rest == null || rest.isEmpty) {
       throwToolExit(
         'No option specified for the output directory.\n$usage',
         exitCode: 2,
       );
     }
 
-    if (argResults.rest.length > 1) {
+    if (rest.length > 1) {
       String message = 'Multiple output directories specified.';
-      for (final String arg in argResults.rest) {
+      for (final String arg in rest) {
         if (arg.startsWith('-')) {
           message += '\nTry moving $arg to be immediately following $name';
           break;
@@ -194,7 +186,7 @@
 
   /// Gets the flutter root directory.
   @protected
-  String get flutterRoot => Cache.flutterRoot;
+  String get flutterRoot => Cache.flutterRoot!;
 
   /// Determines the project type in an existing flutter project.
   ///
@@ -207,14 +199,15 @@
   /// Throws assertion if [projectDir] does not exist or empty.
   /// Returns null if no project type can be determined.
   @protected
-  FlutterProjectType determineTemplateType() {
+  FlutterProjectType? determineTemplateType() {
     assert(projectDir.existsSync() && projectDir.listSync().isNotEmpty);
     final File metadataFile = globals.fs
         .file(globals.fs.path.join(projectDir.absolute.path, '.metadata'));
     final FlutterProjectMetadata projectMetadata =
         FlutterProjectMetadata(metadataFile, globals.logger);
-    if (projectMetadata.projectType != null) {
-      return projectMetadata.projectType;
+    final FlutterProjectType? projectType = projectMetadata.projectType;
+    if (projectType != null) {
+      return projectType;
     }
 
     bool exists(List<String> path) {
@@ -243,8 +236,8 @@
   /// If `--org` is not specified, returns the organization from the existing project.
   @protected
   Future<String> getOrganization() async {
-    String organization = stringArgDeprecated('org');
-    if (!argResults.wasParsed('org')) {
+    String? organization = stringArgDeprecated('org');
+    if (!argResults!.wasParsed('org')) {
       final FlutterProject project = FlutterProject.fromDirectory(projectDir);
       final Set<String> existingOrganizations = await project.organizationNames;
       if (existingOrganizations.length == 1) {
@@ -255,6 +248,9 @@
             'The --org command line argument must be specified to recreate project.');
       }
     }
+    if (organization == null) {
+      throwToolExit('The --org command line argument must be specified to create a project.');
+    }
     return organization;
   }
 
@@ -297,12 +293,10 @@
         // Do not overwrite files.
         throwToolExit("Invalid project name: '$projectDirPath' - file exists.",
             exitCode: 2);
-        break;
       case FileSystemEntityType.link:
         // Do not overwrite links.
         throwToolExit("Invalid project name: '$projectDirPath' - refers to a link.",
             exitCode: 2);
-        break;
       case FileSystemEntityType.directory:
       case FileSystemEntityType.notFound:
         break;
@@ -317,7 +311,7 @@
     final String projectName =
         stringArgDeprecated('project-name') ?? globals.fs.path.basename(projectDirPath);
     if (!boolArgDeprecated('skip-name-checks')) {
-      final String error = _validateProjectName(projectName);
+      final String? error = _validateProjectName(projectName);
       if (error != null) {
         throwToolExit(error);
       }
@@ -328,19 +322,19 @@
 
   /// Creates a template to use for [renderTemplate].
   @protected
-  Map<String, Object> createTemplateContext({
-    String organization,
-    String projectName,
-    String titleCaseProjectName,
-    String projectDescription,
-    String androidLanguage,
-    String iosDevelopmentTeam,
-    String iosLanguage,
-    String flutterRoot,
-    String dartSdkVersionBounds,
-    String agpVersion,
-    String kotlinVersion,
-    String gradleVersion,
+  Map<String, Object?> createTemplateContext({
+    required String organization,
+    required String projectName,
+    required String titleCaseProjectName,
+    String? projectDescription,
+    String? androidLanguage,
+    String? iosDevelopmentTeam,
+    String? iosLanguage,
+    required String flutterRoot,
+    required String dartSdkVersionBounds,
+    String? agpVersion,
+    String? kotlinVersion,
+    String? gradleVersion,
     bool withPlatformChannelPluginHook = false,
     bool withFfiPluginHook = false,
     bool ios = false,
@@ -376,7 +370,7 @@
         ? globals.flutterVersion.frameworkVersion
         : ffiPluginStableRelease.toString();
 
-    return <String, Object>{
+    return <String, Object?>{
       'organization': organization,
       'projectName': projectName,
       'titleCaseProjectName': titleCaseProjectName,
@@ -433,7 +427,7 @@
   Future<int> renderTemplate(
     String templateName,
     Directory directory,
-    Map<String, Object> context, {
+    Map<String, Object?> context, {
     bool overwrite = false,
     bool printStatusWhenWriting = true,
   }) async {
@@ -461,7 +455,7 @@
   Future<int> renderMerged(
     List<String> names,
     Directory directory,
-    Map<String, Object> context, {
+    Map<String, Object?> context, {
     bool overwrite = false,
     bool printStatusWhenWriting = true,
   }) async {
@@ -488,12 +482,12 @@
   Future<int> generateApp(
     List<String> templateNames,
     Directory directory,
-    Map<String, Object> templateContext, {
+    Map<String, Object?> templateContext, {
     bool overwrite = false,
     bool pluginExampleApp = false,
     bool printStatusWhenWriting = true,
     bool generateMetadata = true,
-    FlutterProjectType projectType,
+    FlutterProjectType? projectType,
   }) async {
     int generatedCount = 0;
     generatedCount += await renderMerged(
@@ -508,16 +502,16 @@
       generatedCount += _injectGradleWrapper(project);
     }
 
-    final bool androidPlatform = templateContext['android'] as bool ?? false;
-    final bool iosPlatform = templateContext['ios'] as bool ?? false;
-    final bool linuxPlatform = templateContext['linux'] as bool ?? false;
-    final bool macOSPlatform = templateContext['macos'] as bool ?? false;
-    final bool windowsPlatform = templateContext['windows'] as bool ?? false;
-    final bool webPlatform = templateContext['web'] as bool ?? false;
+    final bool androidPlatform = templateContext['android'] as bool? ?? false;
+    final bool iosPlatform = templateContext['ios'] as bool? ?? false;
+    final bool linuxPlatform = templateContext['linux'] as bool? ?? false;
+    final bool macOSPlatform = templateContext['macos'] as bool? ?? false;
+    final bool windowsPlatform = templateContext['windows'] as bool? ?? false;
+    final bool webPlatform = templateContext['web'] as bool? ?? false;
 
     if (boolArgDeprecated('pub')) {
       final Environment environment = Environment(
-        artifacts: globals.artifacts,
+        artifacts: globals.artifacts!,
         logger: globals.logger,
         cacheDir: globals.cache.getRoot(),
         engineVersion: globals.flutterVersion.engineRevision,
@@ -591,7 +585,6 @@
       metadata.populate(
         platforms: platformsForMigrateConfig,
         projectDirectory: directory,
-        create: true,
         update: false,
         currentRevision: stringArgDeprecated('initial-create-revision') ?? globals.flutterVersion.frameworkRevision,
         createRevision: globals.flutterVersion.frameworkRevision,
@@ -663,12 +656,10 @@
     return segments.join('.');
   }
 
-  Set<Uri> get _templateManifest =>
-      __templateManifest ??= _computeTemplateManifest();
-  Set<Uri> __templateManifest;
+  late final Set<Uri> _templateManifest = _computeTemplateManifest();
   Set<Uri> _computeTemplateManifest() {
     final String flutterToolsAbsolutePath = globals.fs.path.join(
-      Cache.flutterRoot,
+      Cache.flutterRoot!,
       'packages',
       'flutter_tools',
     );
@@ -681,7 +672,7 @@
       globals.fs.file(manifestPath).readAsStringSync(),
     ) as Map<String, Object>;
     return Set<Uri>.from(
-      (manifest['files'] as List<Object>).cast<String>().map<Uri>(
+      (manifest['files']! as List<Object>).cast<String>().map<Uri>(
           (String path) =>
               Uri.file(globals.fs.path.join(flutterToolsAbsolutePath, path))),
     );
@@ -793,7 +784,7 @@
 /// Whether [name] is a valid Pub package.
 @visibleForTesting
 bool isValidPackageName(String name) {
-  final Match match = _identifierRegExp.matchAsPrefix(name);
+  final Match? match = _identifierRegExp.matchAsPrefix(name);
   return match != null &&
       match.end == name.length &&
       !_keywords.contains(name);
@@ -801,7 +792,7 @@
 
 // Return null if the project name is legal. Return a validation message if
 // we should disallow the project name.
-String _validateProjectName(String projectName) {
+String? _validateProjectName(String projectName) {
   if (!isValidPackageName(projectName)) {
     return '"$projectName" is not a valid Dart package name.\n\n'
         'See https://dart.dev/tools/pub/pubspec#name for more information.';
diff --git a/packages/flutter_tools/lib/src/template.dart b/packages/flutter_tools/lib/src/template.dart
index d32fa96..0ce9942 100644
--- a/packages/flutter_tools/lib/src/template.dart
+++ b/packages/flutter_tools/lib/src/template.dart
@@ -155,7 +155,7 @@
   /// May throw a [ToolExit] if the directory is not writable.
   int render(
     Directory destination,
-    Map<String, Object> context, {
+    Map<String, Object?> context, {
     bool overwriteExisting = true,
     bool printStatusWhenWriting = true,
   }) {
diff --git a/packages/flutter_tools/test/src/test_flutter_command_runner.dart b/packages/flutter_tools/test/src/test_flutter_command_runner.dart
index b8ad91f..528a01c 100644
--- a/packages/flutter_tools/test/src/test_flutter_command_runner.dart
+++ b/packages/flutter_tools/test/src/test_flutter_command_runner.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @dart = 2.8
-
 import 'dart:async';
 
 import 'package:args/args.dart';
@@ -20,7 +18,7 @@
 
 export 'package:test_api/test_api.dart' hide test, isInstanceOf; // ignore: deprecated_member_use
 
-CommandRunner<void> createTestCommandRunner([ FlutterCommand command ]) {
+CommandRunner<void> createTestCommandRunner([ FlutterCommand? command ]) {
   final FlutterCommandRunner runner = TestFlutterCommandRunner();
   if (command != null) {
     runner.addCommand(command);
@@ -31,7 +29,7 @@
 /// Creates a flutter project in the [temp] directory using the
 /// [arguments] list if specified, or `--no-pub` if not.
 /// Returns the path to the flutter project.
-Future<String> createProject(Directory temp, { List<String> arguments }) async {
+Future<String> createProject(Directory temp, { List<String>? arguments }) async {
   arguments ??= <String>['--no-pub'];
   final String projectPath = globals.fs.path.join(temp.path, 'flutter_project');
   final CreateCommand command = CreateCommand();
@@ -61,7 +59,7 @@
           userMessages: UserMessages(),
         );
         // For compatibility with tests that set this to a relative path.
-        Cache.flutterRoot = globals.fs.path.normalize(globals.fs.path.absolute(Cache.flutterRoot));
+        Cache.flutterRoot = globals.fs.path.normalize(globals.fs.path.absolute(Cache.flutterRoot!));
         return super.runCommand(topLevelResults);
       }
     );