support for --strong option (#13859)

* Plumb a --strong option through to the front end server and the engine
so that we can run flutter apps in preview-dart-2 and strong mode

* - Address analyzer lint issues
*- correctly set up strong mode option in the case of AOT builds
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle
index 3cbd6fa..98748d6 100644
--- a/packages/flutter_tools/gradle/flutter.gradle
+++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -255,6 +255,11 @@
         if (project.hasProperty('preview-dart-2')) {
             previewDart2Value = project.property('preview-dart-2')
         }
+	
+        Boolean strongModeValue = false
+        if (project.hasProperty('strong')) {
+            strongModeValue = project.property('strong')
+        }
 
         String extraFrontEndOptionsValue = null
         if (project.hasProperty('extra-front-end-options')) {
@@ -290,6 +295,7 @@
                 localEngineSrcPath this.localEngineSrcPath
                 targetPath target
                 previewDart2 previewDart2Value
+                strongMode strongModeValue	
                 preferSharedLibrary preferSharedLibraryValue
                 sourceDir project.file(project.flutter.source)
                 intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}")
@@ -304,6 +310,7 @@
                 localEngineSrcPath this.localEngineSrcPath
                 targetPath target
                 previewDart2 previewDart2Value
+                strongMode strongModeValue	
                 preferSharedLibrary preferSharedLibraryValue
                 sourceDir project.file(project.flutter.source)
                 intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}")
@@ -338,6 +345,8 @@
     @Optional @Input
     Boolean previewDart2
     @Optional @Input
+    Boolean strongMode
+    @Optional @Input
     Boolean preferSharedLibrary
     File sourceDir
     File intermediateDir
@@ -378,6 +387,9 @@
                 if (previewDart2) {
                     args "--preview-dart-2"
                 }
+		if (strongMode) {
+                    args "--strong"
+                }
                 if (extraFrontEndOptions != null) {
                     args "--extra-front-end-options", "${extraFrontEndOptions}"
                 }
@@ -404,6 +416,10 @@
             if (previewDart2) {
                 args "--preview-dart-2"
             }
+            if (strongMode) {
+                args "--strong"
+            }
+
             args "--output-file", "${intermediateDir}/app.flx"
             if (buildMode != "debug") {
                 args "--precompiled"
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index b6e5890..a0a19c0 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -378,6 +378,7 @@
       return new LaunchResult.failed();
 
     final bool traceStartup = platformArgs['trace-startup'] ?? false;
+    final bool strongMode = platformArgs['strong'] ?? false;
     final AndroidApk apk = package;
     printTrace('$this startApp');
 
@@ -406,6 +407,9 @@
 
     if (traceStartup)
       cmd.addAll(<String>['--ez', 'trace-startup', 'true']);
+    if (strongMode) {
+      cmd.addAll(<String>['--ez', 'strong', 'true']);
+    }
     if (route != null)
       cmd.addAll(<String>['--es', 'route', route]);
     if (debuggingOptions.enableSoftwareRendering)
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index 0a7083e..8d8957a 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -291,6 +291,8 @@
   }
   if (buildInfo.previewDart2) {
     command.add('-Ppreview-dart-2=true');
+  if (buildInfo.strongMode)
+    command.add('-Pstrong=true');
   if (buildInfo.extraFrontEndOptions != null)
     command.add('-Pextra-front-end-options=${buildInfo.extraFrontEndOptions}');
   if (buildInfo.extraGenSnapshotOptions != null)
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
index e3d12c3..3c4bfa3 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -21,6 +21,7 @@
   vmSnapshotData,
   isolateSnapshotData,
   platformKernelDill,
+  platformKernelStrongDill,
   platformLibrariesJson,
   flutterPatchedSdkPath,
   frontendServerSnapshotForEngineDartSdk,
@@ -47,6 +48,8 @@
       return 'isolate_snapshot.bin';
     case Artifact.platformKernelDill:
       return 'platform.dill';
+    case Artifact.platformKernelStrongDill:
+      return 'platform_strong.dill';
     case Artifact.platformLibrariesJson:
       return 'libraries.json';
     case Artifact.flutterPatchedSdkPath:
@@ -168,6 +171,7 @@
         final String platformDirName = getNameForTargetPlatform(platform);
         return fs.path.join(engineArtifactsPath, platformDirName, _artifactToFileName(artifact));
       case Artifact.platformKernelDill:
+      case Artifact.platformKernelStrongDill:
         return fs.path.join(_getFlutterPatchedSdkPath(), _artifactToFileName(artifact));
       case Artifact.platformLibrariesJson:
         return fs.path.join(_getFlutterPatchedSdkPath(), 'lib', _artifactToFileName(artifact));
@@ -237,6 +241,7 @@
       case Artifact.vmSnapshotData:
         return fs.path.join(engineOutPath, 'gen', 'flutter', 'lib', 'snapshot', _artifactToFileName(artifact));
       case Artifact.platformKernelDill:
+      case Artifact.platformKernelStrongDill:
         return fs.path.join(_getFlutterPatchedSdkPath(), _artifactToFileName(artifact));
       case Artifact.platformLibrariesJson:
         return fs.path.join(_getFlutterPatchedSdkPath(), 'lib', _artifactToFileName(artifact));
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index 5f3aef2..63bf145 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -12,6 +12,7 @@
 class BuildInfo {
   const BuildInfo(this.mode, this.flavor,
       {this.previewDart2,
+      this.strongMode,
       this.extraFrontEndOptions,
       this.extraGenSnapshotOptions,
       this.preferSharedLibrary});
@@ -27,6 +28,9 @@
 
   // Whether build should be done using Dart2 Frontend parser.
   final bool previewDart2;
+  
+  // Whether build should use strong mode semantics.
+  final bool strongMode;
 
   /// Extra command-line options for front-end.
   final String extraFrontEndOptions;
diff --git a/packages/flutter_tools/lib/src/commands/build_aot.dart b/packages/flutter_tools/lib/src/commands/build_aot.dart
index af455f7..f132f0c 100644
--- a/packages/flutter_tools/lib/src/commands/build_aot.dart
+++ b/packages/flutter_tools/lib/src/commands/build_aot.dart
@@ -40,6 +40,7 @@
       ..addFlag('interpreter')
       ..addFlag('quiet', defaultsTo: false)
       ..addFlag('preview-dart-2', negatable: false, hide: !verboseHelp)
+      ..addFlag('strong', negatable: false, hide: !verboseHelp)
       ..addOption(FlutterOptions.kExtraFrontEndOptions,
         allowMultiple: true,
         splitCommas: true,
@@ -81,6 +82,7 @@
       outputPath: argResults['output-dir'],
       interpreter: argResults['interpreter'],
       previewDart2: argResults['preview-dart-2'],
+      strongMode: argResults['strong'],
       extraFrontEndOptions: argResults[FlutterOptions.kExtraFrontEndOptions],
       extraGenSnapshotOptions: argResults[FlutterOptions.kExtraGenSnapshotOptions],
       preferSharedLibrary: argResults['prefer-shared-library'],
@@ -112,6 +114,7 @@
   String outputPath,
   bool interpreter: false,
   bool previewDart2: false,
+  bool strongMode: false,
   List<String> extraFrontEndOptions,
   List<String> extraGenSnapshotOptions,
   bool preferSharedLibrary: false,
@@ -125,6 +128,7 @@
       outputPath: outputPath,
       interpreter: interpreter,
       previewDart2: previewDart2,
+      strongMode: strongMode,
       extraFrontEndOptions: extraFrontEndOptions,
       extraGenSnapshotOptions: extraGenSnapshotOptions,
       preferSharedLibrary: preferSharedLibrary,
@@ -144,6 +148,7 @@
   String outputPath,
   bool interpreter: false,
   bool previewDart2: false,
+  bool strongMode: false,
   List<String> extraFrontEndOptions,
   List<String> extraGenSnapshotOptions,
   bool preferSharedLibrary: false,
@@ -335,6 +340,7 @@
       extraFrontEndOptions: extraFrontEndOptions,
       linkPlatformKernelIn : true,
       aot : true,
+      strongMode: strongMode,
     );
   }
 
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart
index 0c1811d..4636e48 100644
--- a/packages/flutter_tools/lib/src/commands/build_apk.dart
+++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -16,6 +16,7 @@
 
     argParser
       ..addFlag('preview-dart-2', negatable: false,  hide: !verboseHelp)
+      ..addFlag('strong', negatable: false,  hide: !verboseHelp)
       ..addFlag('prefer-shared-library', negatable: false,
           help: 'Whether to prefer compiling to a *.so file (android only).');
   }
diff --git a/packages/flutter_tools/lib/src/commands/build_flx.dart b/packages/flutter_tools/lib/src/commands/build_flx.dart
index be66079..73c1a08 100644
--- a/packages/flutter_tools/lib/src/commands/build_flx.dart
+++ b/packages/flutter_tools/lib/src/commands/build_flx.dart
@@ -21,6 +21,7 @@
     argParser.addOption('snapshot', defaultsTo: defaultSnapshotPath);
     argParser.addOption('depfile', defaultsTo: defaultDepfilePath);
     argParser.addFlag('preview-dart-2', negatable: false, hide: !verboseHelp);
+    argParser.addFlag('strong', negatable: false, hide: !verboseHelp);
     argParser.addOption('working-dir', defaultsTo: getAssetBuildDirectory());
     argParser.addFlag('report-licensed-packages', help: 'Whether to report the names of all the packages that are included in the application\'s LICENSE file.', defaultsTo: false);
     usesPubOption();
@@ -50,6 +51,7 @@
       privateKeyPath: argResults['private-key'],
       workingDirPath: argResults['working-dir'],
       previewDart2: argResults['preview-dart-2'],
+      strongMode: argResults['strong'],
       precompiledSnapshot: argResults['precompiled'],
       reportLicensedPackages: argResults['report-licensed-packages']
     );
diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart
index ee0c312..d1d7580 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios.dart
@@ -31,6 +31,8 @@
         help: 'Codesign the application bundle (only available on device builds).');
     argParser.addFlag('preview-dart-2', negatable: false,
         hide: !verboseHelp);
+    argParser.addFlag('strong', negatable: false,
+        hide: !verboseHelp);
   }
 
   @override
diff --git a/packages/flutter_tools/lib/src/commands/create.dart b/packages/flutter_tools/lib/src/commands/create.dart
index 2247079..056d0b5 100644
--- a/packages/flutter_tools/lib/src/commands/create.dart
+++ b/packages/flutter_tools/lib/src/commands/create.dart
@@ -229,6 +229,7 @@
       target: flx.defaultMainPath,
       hasPlugins: generatePlugin,
       previewDart2: false,
+      strongMode: false,
     );
 
     if (argResults['pub']) {
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index 52e27bd..beb0c61 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -105,6 +105,10 @@
     argParser.addFlag('preview-dart-2',
         hide: !verboseHelp,
         help: 'Preview Dart 2.0 functionality.');
+    argParser.addFlag('strong',
+        hide: !verboseHelp,
+        help: 'Turn on strong mode semantics.\n'
+              'Valid only when --preview-dart-2 is also specified');
     argParser.addOption('packages',
         hide: !verboseHelp,
         valueHelp: 'path',
@@ -290,7 +294,9 @@
     }
 
     final List<FlutterDevice> flutterDevices = devices.map((Device device) {
-      return new FlutterDevice(device, previewDart2: argResults['preview-dart-2']);
+      return new FlutterDevice(device,
+                               previewDart2: argResults['preview-dart-2'],
+                               strongMode : argResults['strong']);
     }).toList();
 
     ResidentRunner runner;
@@ -302,6 +308,7 @@
         benchmarkMode: argResults['benchmark'],
         applicationBinary: argResults['use-application-binary'],
         previewDart2: argResults['preview-dart-2'],
+        strongMode: argResults['strong'],
         projectRootPath: argResults['project-root'],
         packagesFilePath: argResults['packages'],
         projectAssets: argResults['project-assets'],
@@ -316,6 +323,7 @@
         traceStartup: traceStartup,
         applicationBinary: argResults['use-application-binary'],
         previewDart2: argResults['preview-dart-2'],
+        strongMode: argResults['strong'],
         stayResident: stayResident,
         ipv6: ipv6,
       );
diff --git a/packages/flutter_tools/lib/src/compile.dart b/packages/flutter_tools/lib/src/compile.dart
index 998ff67..be35217 100644
--- a/packages/flutter_tools/lib/src/compile.dart
+++ b/packages/flutter_tools/lib/src/compile.dart
@@ -61,6 +61,7 @@
     String mainPath,
     bool linkPlatformKernelIn : false,
     bool aot : false,
+    bool strongMode : false,
     List<String> extraFrontEndOptions,
     String incrementalCompilerByteStorePath}) async {
   final String frontendServer = artifacts.getArtifactPath(
@@ -81,6 +82,9 @@
   if (aot) {
     command.add('--aot');
   }
+  if (strongMode) {
+    command.add('--strong');
+  }
   if (incrementalCompilerByteStorePath != null) {
     command.addAll(<String>[
       '--incremental',
diff --git a/packages/flutter_tools/lib/src/flx.dart b/packages/flutter_tools/lib/src/flx.dart
index ff4c501..d54ac1b 100644
--- a/packages/flutter_tools/lib/src/flx.dart
+++ b/packages/flutter_tools/lib/src/flx.dart
@@ -39,6 +39,7 @@
   String workingDirPath,
   String packagesPath,
   bool previewDart2 : false,
+  bool strongMode : false,
   bool precompiledSnapshot: false,
   bool reportLicensedPackages: false
 }) async {
@@ -72,7 +73,8 @@
     final String kernelBinaryFilename = await compile(
       sdkRoot: artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath),
       incrementalCompilerByteStorePath: fs.path.absolute(getIncrementalCompilerByteStoreDirectory()),
-      mainPath: fs.file(mainPath).absolute.path
+      mainPath: fs.file(mainPath).absolute.path,
+      strongMode: strongMode
     );
     kernelContent = new DevFSFileContent(fs.file(kernelBinaryFilename));
   }
@@ -85,6 +87,7 @@
     privateKeyPath: privateKeyPath,
     workingDirPath: workingDirPath,
     packagesPath: packagesPath,
+    strongMode: strongMode,
     reportLicensedPackages: reportLicensedPackages
   ).then((_) => null);
 }
@@ -98,6 +101,7 @@
   String privateKeyPath: defaultPrivateKeyPath,
   String workingDirPath,
   String packagesPath,
+  bool strongMode : false,
   bool includeDefaultFonts: true,
   bool reportLicensedPackages: false
 }) async {
@@ -128,7 +132,9 @@
       .toList();
 
   if (kernelContent != null) {
-    final String platformKernelDill = artifacts.getArtifactPath(Artifact.platformKernelDill);
+    final String platformKernelDill = strongMode ?
+        artifacts.getArtifactPath(Artifact.platformKernelStrongDill) :
+        artifacts.getArtifactPath(Artifact.platformKernelDill);
     zipBuilder.entries[_kKernelKey] = kernelContent;
     zipBuilder.entries[_kPlatformKernelKey] = new DevFSFileContent(fs.file(platformKernelDill));
   }
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
index 2ca8109..14fa5a3 100644
--- a/packages/flutter_tools/lib/src/ios/mac.dart
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -264,6 +264,7 @@
     target: target,
     hasPlugins: hasFlutterPlugins,
     previewDart2: buildInfo.previewDart2,
+    strongMode: buildInfo.strongMode,
   );
 
   if (hasFlutterPlugins) {
diff --git a/packages/flutter_tools/lib/src/ios/xcodeproj.dart b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
index 7dbeca7..c70c997 100644
--- a/packages/flutter_tools/lib/src/ios/xcodeproj.dart
+++ b/packages/flutter_tools/lib/src/ios/xcodeproj.dart
@@ -25,6 +25,7 @@
   @required String target,
   @required bool hasPlugins,
   @required bool previewDart2,
+  @required bool strongMode,
 }) {
   final StringBuffer localsBuffer = new StringBuffer();
 
@@ -57,6 +58,9 @@
   if (previewDart2) {
     localsBuffer.writeln('PREVIEW_DART_2=true');
   }
+  if (strongMode) {
+    localsBuffer.writeln('STRONG=true');
+  }
 
   // Add dependency to CocoaPods' generated project only if plugins are used.
   if (hasPlugins)
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index c284dce..22a62fd 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -38,7 +38,8 @@
 
   StreamSubscription<String> _loggingSubscription;
 
-  FlutterDevice(this.device, { bool previewDart2 : false }) {
+  FlutterDevice(this.device,
+                { bool previewDart2 : false, bool strongMode : false }) {
     if (previewDart2)
       generator = new ResidentCompiler(
         artifacts.getArtifactPath(Artifact.flutterPatchedSdkPath));
@@ -259,6 +260,8 @@
     }
 
     final Map<String, dynamic> platformArgs = <String, dynamic>{};
+    if (hotRunner.strongMode != null)
+      platformArgs['strong'] = hotRunner.strongMode;
 
     startEchoingDeviceLog();
 
@@ -320,6 +323,8 @@
     final Map<String, dynamic> platformArgs = <String, dynamic>{};
     if (coldRunner.traceStartup != null)
       platformArgs['trace-startup'] = coldRunner.traceStartup;
+    if (coldRunner.strongMode != null)
+      platformArgs['strong'] = coldRunner.strongMode;
 
     startEchoingDeviceLog();
 
diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart
index 7a004f2..9d41ce8 100644
--- a/packages/flutter_tools/lib/src/run_cold.dart
+++ b/packages/flutter_tools/lib/src/run_cold.dart
@@ -21,6 +21,7 @@
     this.traceStartup: false,
     this.applicationBinary,
     this.previewDart2 : false,
+    this.strongMode : false,
     bool stayResident: true,
     bool ipv6: false,
   }) : super(devices,
@@ -33,6 +34,7 @@
   final bool traceStartup;
   final String applicationBinary;
   final bool previewDart2;
+  final bool strongMode;
 
   @override
   Future<int> run({
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index b7a6f38..4a20f91 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -40,6 +40,7 @@
     this.benchmarkMode: false,
     this.applicationBinary,
     this.previewDart2: false,
+    this.strongMode: false,
     this.hostIsIde: false,
     String projectRootPath,
     String packagesFilePath,
@@ -65,6 +66,7 @@
   // The initial launch is from a snapshot.
   bool _runningFromSnapshot = true;
   bool previewDart2 = false;
+  bool strongMode = false;
 
   void _addBenchmarkData(String name, int value) {
     benchmarkData[name] ??= <int>[];
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index 5d673b6..33d3e54 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -149,13 +149,23 @@
   }
 
   BuildInfo getBuildInfo() {
+    final bool previewDart2 = argParser.options.containsKey('preview-dart-2')
+        ? argResults['preview-dart-2']
+        : false;
+    final bool strongMode =  argParser.options.containsKey('strong')
+        ? argResults['strong']
+        : false;
+    if (strongMode == true && previewDart2 == false) {
+      throw new UsageException(
+          '--strong is valid only when --preview-dart-2 is specified.', null);
+    }
+
     return new BuildInfo(getBuildMode(),
       argParser.options.containsKey('flavor')
         ? argResults['flavor']
         : null,
-      previewDart2: argParser.options.containsKey('preview-dart-2')
-        ? argResults['preview-dart-2']
-        : false,
+      previewDart2: previewDart2,
+      strongMode: strongMode,
       extraFrontEndOptions: argParser.options.containsKey(FlutterOptions.kExtraFrontEndOptions)
           ? argResults[FlutterOptions.kExtraFrontEndOptions]
           : null,
@@ -374,6 +384,16 @@
       if (!fs.isFileSync(targetPath))
         throw new ToolExit('Target file "$targetPath" not found.');
     }
+
+    final bool previewDart2 = argParser.options.containsKey('preview-dart-2')
+        ? argResults['preview-dart-2']
+        : false;
+    final bool strongMode =  argParser.options.containsKey('strong')
+        ? argResults['strong']
+        : false;
+    if (strongMode == true && previewDart2 == false) {
+      throw new ToolExit('--strong is valid only with --preview-dart-2 option.');
+    }
   }
 
   ApplicationPackageStore applicationPackages;