[dartdevc] Migrate DevCompilerTarget and dependencies to null safety

Change-Id: I75ebd85b745f55bc4ca4111e97a0ec2d787098a2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207135
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index d5b538f..87df7e3 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -2,8 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
+import 'package:collection/collection.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/target/targets.dart';
 
@@ -21,7 +20,7 @@
   /// failed, or if the constant was unavailable.
   ///
   /// Returns [NullConstant] to represent the `null` value.
-  Constant evaluate(Expression e) {
+  Constant? evaluate(Expression e) {
     return e is ConstantExpression ? e.constant : null;
   }
 
@@ -43,13 +42,12 @@
   ///     main() { ... }
   ///
   /// Given the node for `@MyAnnotation('FooBar')` this will return `'FooBar'`.
-  Object getFieldValueFromAnnotation(Expression node, String name) {
+  Object? getFieldValueFromAnnotation(Expression node, String name) {
     if (node is ConstantExpression) {
       var constant = node.constant;
       if (constant is InstanceConstant) {
         var value = constant.fieldValues.entries
-            .firstWhere((e) => e.key.asField.name.text == name,
-                orElse: () => null)
+            .firstWhereOrNull((e) => e.key.asField.name.text == name)
             ?.value;
         if (value is PrimitiveConstant) return value.value;
         if (value is UnevaluatedConstant) {
@@ -64,11 +62,10 @@
     //
     // We may need to address this in the kernel outline files.
     if (node is ConstructorInvocation) {
-      Expression first;
+      Expression? first;
       var named = node.arguments.named;
       if (named.isNotEmpty) {
-        first =
-            named.firstWhere((n) => n.name == name, orElse: () => null)?.value;
+        first = named.firstWhereOrNull((n) => n.name == name)?.value;
       }
       var positional = node.arguments.positional;
       if (positional.isNotEmpty) first ??= positional[0];
@@ -79,7 +76,7 @@
     return null;
   }
 
-  Object _evaluateAnnotationArgument(Expression node) {
+  Object? _evaluateAnnotationArgument(Expression node) {
     if (node is ConstantExpression) {
       var constant = node.constant;
       if (constant is PrimitiveConstant) return constant.value;
@@ -87,7 +84,7 @@
     if (node is StaticGet) {
       var target = node.target;
       if (target is Field) {
-        return _evaluateAnnotationArgument(target.initializer);
+        return _evaluateAnnotationArgument(target.initializer!);
       }
     }
     return node is BasicLiteral ? node.value : null;
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 0c4e313..0e4ae0e 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -2,19 +2,18 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:collection';
+import 'package:collection/collection.dart';
 import 'package:front_end/src/api_unstable/ddc.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
 
-Constructor unnamedConstructor(Class c) =>
-    c.constructors.firstWhere((c) => c.name.text == '', orElse: () => null);
+Constructor? unnamedConstructor(Class c) =>
+    c.constructors.firstWhereOrNull((c) => c.name.text == '');
 
 /// Returns the enclosing library for reference [node].
-Library getLibrary(NamedNode node) {
-  for (TreeNode n = node; n != null; n = n.parent) {
+Library? getLibrary(NamedNode node) {
+  for (TreeNode? n = node; n != null; n = n.parent) {
     if (n is Library) return n;
   }
   return null;
@@ -22,14 +21,14 @@
 
 final Pattern _syntheticTypeCharacters = RegExp('[&^#.|]');
 
-String escapeIdentifier(String identifier) {
+String? escapeIdentifier(String? identifier) {
   // Remove the special characters used to encode mixin application class names
   // and extension method / parameter names which are legal in Kernel, but not
   // in JavaScript.
   //
   // Note, there is an implicit assumption here that we won't have
   // collisions since everything is mapped to \$.  That may work out fine given
-  // how these are sythesized, but may need to revisit.
+  // how these are synthesized, but may need to revisit.
   return identifier?.replaceAll(_syntheticTypeCharacters, r'$');
 }
 
@@ -40,15 +39,15 @@
 ///
 /// In the current encoding, generic classes are generated in a function scope
 /// which avoids name clashes of the escaped class name.
-String getLocalClassName(Class node) => escapeIdentifier(node.name);
+String getLocalClassName(Class node) => escapeIdentifier(node.name)!;
 
 /// Returns the escaped name for the type parameter [node].
 ///
 /// In the current encoding, generic classes are generated in a function scope
 /// which avoids name clashes of the escaped parameter name.
-String getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
+String? getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
 
-String getTopLevelName(NamedNode n) {
+String? getTopLevelName(NamedNode n) {
   if (n is Procedure) return n.name.text;
   if (n is Class) return n.name;
   if (n is Typedef) return n.name;
@@ -69,7 +68,7 @@
 ///
 ///    (v) => v.type.name == 'Deprecated' && v.type.element.library.isDartCore
 ///
-Expression findAnnotation(TreeNode node, bool Function(Expression) test) {
+Expression? findAnnotation(TreeNode node, bool Function(Expression) test) {
   List<Expression> annotations;
   if (node is Class) {
     annotations = node.annotations;
@@ -84,7 +83,7 @@
   } else {
     return null;
   }
-  return annotations.firstWhere(test, orElse: () => null);
+  return annotations.firstWhereOrNull(test);
 }
 
 /// Returns true if [value] represents an annotation for class [className] in
@@ -108,7 +107,7 @@
 ///
 /// This function works regardless of whether the CFE is evaluating constants,
 /// or whether the constant is a field reference (such as "anonymous" above).
-Class getAnnotationClass(Expression node) {
+Class? getAnnotationClass(Expression node) {
   if (node is ConstantExpression) {
     var constant = node.constant;
     if (constant is InstanceConstant) return constant.classNode;
@@ -165,9 +164,9 @@
 /// A mixin alias class is a mixin application, that can also be itself used as
 /// a mixin.
 bool isMixinAliasClass(Class c) =>
-    c.isMixinApplication && c.superclass.superclass == null;
+    c.isMixinApplication && c.superclass!.superclass == null;
 
-List<Class> getSuperclasses(Class c) {
+List<Class> getSuperclasses(Class? c) {
   var result = <Class>[];
   var visited = HashSet<Class>();
   while (c != null && visited.add(c)) {
@@ -191,7 +190,7 @@
   return result;
 }
 
-Expression getInvocationReceiver(InvocationExpression node) {
+Expression? getInvocationReceiver(InvocationExpression node) {
   if (node is MethodInvocation) {
     return node.receiver;
   } else if (node is InstanceInvocation) {
@@ -251,7 +250,7 @@
 
 /// Returns the redirecting factory constructors for the enclosing class,
 /// if the field [f] is storing that information, otherwise returns `null`.
-Iterable<Member> getRedirectingFactories(Field f) {
+Iterable<Member>? getRedirectingFactories(Field f) {
   // TODO(jmesserly): this relies on implementation details in Kernel
   if (isRedirectingFactoryField(f)) {
     assert(f.isStatic);
@@ -269,14 +268,15 @@
 // TODO(jmesserly): consider replacing this with Kernel's mixin unrolling
 Class getSuperclassAndMixins(Class c, List<Class> mixins) {
   assert(mixins.isEmpty);
+  assert(c.superclass != null);
 
   var mixedInClass = c.mixedInClass;
   if (mixedInClass != null) mixins.add(mixedInClass);
 
-  var sc = c.superclass;
-  for (; sc.isAnonymousMixin; sc = sc.superclass) {
+  var sc = c.superclass!;
+  for (; sc.isAnonymousMixin; sc = sc.superclass!) {
     mixedInClass = sc.mixedInClass;
-    if (mixedInClass != null) mixins.add(sc.mixedInClass);
+    if (mixedInClass != null) mixins.add(sc.mixedInClass!);
   }
   return sc;
 }
@@ -291,7 +291,7 @@
 class LabelContinueFinder extends StatementVisitor<void> {
   var found = false;
 
-  void visit(Statement s) {
+  void visit(Statement? s) {
     if (!found && s != null) s.accept(this);
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index b6020ee..5bc10c1 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:collection';
 
 import 'package:_fe_analyzer_shared/src/messages/codes.dart'
@@ -28,9 +26,9 @@
   @override
   final TargetFlags flags;
 
-  WidgetCreatorTracker _widgetTracker;
+  WidgetCreatorTracker? _widgetTracker;
 
-  Map<String, Class> _nativeClasses;
+  Map<String, Class>? _nativeClasses;
 
   @override
   bool get enableSuperMixins => true;
@@ -156,11 +154,11 @@
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<Library> libraries,
-      Map<String, String> environmentDefines,
+      Map<String, String>? environmentDefines,
       DiagnosticReporter diagnosticReporter,
-      ReferenceFromIndex referenceFromIndex,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      ReferenceFromIndex? referenceFromIndex,
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
     var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
     for (var library in libraries) {
@@ -169,7 +167,7 @@
       JsInteropChecks(
               coreTypes,
               diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
-              _nativeClasses)
+              _nativeClasses!)
           .visitLibrary(library);
     }
   }
@@ -180,11 +178,11 @@
       CoreTypes coreTypes,
       List<Library> libraries,
       DiagnosticReporter diagnosticReporter,
-      {void Function(String msg) logger,
-      ChangedStructureNotifier changedStructureNotifier}) {
+      {void Function(String msg)? logger,
+      ChangedStructureNotifier? changedStructureNotifier}) {
     if (flags.trackWidgetCreation) {
       _widgetTracker ??= WidgetCreatorTracker();
-      _widgetTracker.transform(component, libraries, changedStructureNotifier);
+      _widgetTracker!.transform(component, libraries, changedStructureNotifier);
     }
   }
 
@@ -352,7 +350,7 @@
   /// If the member needs a check it will be stored in [_checkedMembers].
   ///
   /// See [transform] for more information.
-  void _checkTarget(Expression receiver, Member target) {
+  void _checkTarget(Expression receiver, Member? target) {
     if (target != null &&
         target.name.isPrivate &&
         target.isInstanceMember &&
@@ -370,7 +368,7 @@
   /// escape, and it also has a different runtime type.
   ///
   /// See [transform] for more information.
-  void _checkTearoff(Member target) {
+  void _checkTearoff(Member? target) {
     if (target != null &&
         target.name.isPrivate &&
         target.isInstanceMember &&
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index 41826b5..e0271f3 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -16,6 +16,7 @@
   build_integration:
     path: ../build_integration
   cli_util: any
+  collection: ^1.15.0
   front_end:
     path: ../front_end
   kernel: