Version 2.19.0-52.0.dev

Merge commit '546d0f5fe2c28b92d87fbb3dc3b3ed331c803510' into 'dev'
diff --git a/pkg/_js_interop_checks/lib/src/transformations/static_interop_class_eraser.dart b/pkg/_js_interop_checks/lib/src/transformations/static_interop_class_eraser.dart
index a907d2c..565faa5 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/static_interop_class_eraser.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/static_interop_class_eraser.dart
@@ -60,11 +60,7 @@
         .where((procedure) => procedure.name.text == stubName);
     if (stubs.isEmpty) {
       // We should only create the stub if we're processing the component in
-      // which the stub should exist. Any static invocation of the factory that
-      // doesn't exist in the same component as the factory should be processed
-      // after the component in which the factory exists. In modular
-      // compilation, the outline of that component should already contain the
-      // needed stub.
+      // which the stub should exist.
       if (currentComponent != null) {
         assert(factoryTarget.enclosingComponent == currentComponent);
       }
@@ -241,23 +237,3 @@
   @override
   TreeNode visitTreeNode(TreeNode node) => node.accept(_eraser);
 }
-
-/// Used to create stubs for factories when computing outlines.
-///
-/// These stubs can then be used in downstream dependencies in modular
-/// compilation.
-class StaticInteropStubCreator extends RecursiveVisitor {
-  final StaticInteropClassEraser _eraser;
-  StaticInteropStubCreator(this._eraser);
-
-  @override
-  void visitLibrary(Library node) {
-    _eraser.currentComponent = node.enclosingComponent;
-    super.visitLibrary(node);
-  }
-
-  @override
-  void visitProcedure(Procedure node) {
-    _eraser.visitProcedure(node);
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index cf79edf..70ccf2f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -391,8 +391,8 @@
           }
         }
       } else if (node is CatchClause) {
-        if (node.exceptionParameter?.staticElement == variable ||
-            node.stackTraceParameter?.staticElement == variable) {
+        if (node.exceptionParameter2?.declaredElement == variable ||
+            node.stackTraceParameter2?.declaredElement == variable) {
           return distance;
         }
       }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index c6be580..4d000d9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
@@ -362,11 +363,10 @@
   }
 
   @override
-  void declaredParam(SimpleIdentifier name, TypeAnnotation? type) {
-    var element = name.staticElement;
+  void declaredParam(Token name, Element? element, TypeAnnotation? type) {
     if (visibilityTracker._isVisible(element) &&
         opType.includeReturnValueSuggestions) {
-      if (_isUnused(name.name)) {
+      if (_isUnused(name.lexeme)) {
         return;
       }
       if (element is ParameterElement) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index ef27adf..1caf787 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer_plugin/src/utilities/visitors/local_declaration_visitor.dart';
@@ -205,8 +206,8 @@
   }
 
   @override
-  void declaredParam(SimpleIdentifier name, TypeAnnotation? type) {
-    if (name.name == targetName) {
+  void declaredParam(Token name, Element? element, TypeAnnotation? type) {
+    if (name.lexeme == targetName) {
       // Type provided by the element in computeFull above.
       finished();
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 076cc4f..8c0782b 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -1013,7 +1013,7 @@
           var struct = _KeywordConditionBlockStructure(
               catchKeyword,
               catchNode.leftParenthesis!,
-              catchNode.exceptionParameter!,
+              catchNode.exceptionParameter2!,
               catchNode.rightParenthesis!,
               catchNode.body);
           if (sb != null) {
@@ -1126,7 +1126,7 @@
         p?.parent?.parent is! Statement;
   }
 
-  bool _isSyntheticExpression(Expression? expr) {
+  bool _isSyntheticExpression(AstNode? expr) {
     return expr is SimpleIdentifier && expr.isSynthetic;
   }
 
@@ -1229,7 +1229,7 @@
 class _KeywordConditionBlockStructure {
   final Token keyword;
   final Token leftParenthesis, rightParenthesis;
-  final Expression condition;
+  final AstNode condition;
   final Statement? block;
 
   _KeywordConditionBlockStructure(this.keyword, this.leftParenthesis,
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart b/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart
index 90aacb1..a6875dd 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/assign_to_local_variable.dart
@@ -57,7 +57,7 @@
     var excluded = <String>{};
     var scopedNameFinder = ScopedNameFinder(offset);
     expression.accept(scopedNameFinder);
-    excluded.addAll(scopedNameFinder.locals.keys.toSet());
+    excluded.addAll(scopedNameFinder.locals);
     var suggestions =
         getVariableNameSuggestionsForExpression(type, expression, excluded);
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_on_type.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_on_type.dart
index 8c48362..0fc2c61 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_on_type.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_on_type.dart
@@ -20,18 +20,18 @@
   Future<void> compute(ChangeBuilder builder) async {
     var exceptionParameter = node;
     if (exceptionParameter is SimpleIdentifier) {
-      var catchClause = exceptionParameter.parent;
+      var catchClause = exceptionParameter.parent?.parent;
       if (catchClause is CatchClause) {
         var catchKeyword = catchClause.catchKeyword;
         var rightParenthesis = catchClause.rightParenthesis;
         if (catchKeyword != null &&
             catchClause.exceptionType == null &&
-            catchClause.exceptionParameter == exceptionParameter &&
+            catchClause.exceptionParameter2?.name == exceptionParameter.token &&
             rightParenthesis != null) {
           var exceptionTypeName = exceptionParameter.name;
           fixArguments.add(exceptionTypeName);
           await builder.addDartFileEdit(file, (builder) {
-            var stackTraceParameter = catchClause.stackTraceParameter;
+            var stackTraceParameter = catchClause.stackTraceParameter2;
             if (stackTraceParameter != null) {
               builder.addSimpleReplacement(
                 range.startStart(catchKeyword, stackTraceParameter),
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart b/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart
index 359e946..d180777 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart
@@ -42,7 +42,7 @@
     var excluded = <String>{};
     var scopedNameFinder = ScopedNameFinder(offset);
     isExpression.accept(scopedNameFinder);
-    excluded.addAll(scopedNameFinder.locals.keys.toSet());
+    excluded.addAll(scopedNameFinder.locals);
     // name(s)
     var suggestions =
         getVariableNameSuggestionsForExpression(castType, null, excluded);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_clause.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_clause.dart
index 15eb4ef..6fc350e 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_clause.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_clause.dart
@@ -24,7 +24,12 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var catchClause = node.parent;
+    final exceptionParameter = node.parent;
+    if (exceptionParameter is! CatchClauseParameter) {
+      return;
+    }
+
+    final catchClause = exceptionParameter.parent;
     if (catchClause is! CatchClause) {
       return;
     }
@@ -34,7 +39,7 @@
       return;
     }
 
-    if (catchClause.exceptionParameter == node) {
+    if (catchClause.exceptionParameter2 == exceptionParameter) {
       await builder.addDartFileEdit(file, (builder) {
         builder.addDeletion(range.startStart(catchKeyword, catchClause.body));
       });
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_stack.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_stack.dart
index 7efccd8..8a7f342 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_stack.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_catch_stack.dart
@@ -24,19 +24,26 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var catchClause = node.parent;
+    final stackTraceParameter = node.parent;
+    if (stackTraceParameter is! CatchClauseParameter) {
+      return;
+    }
+
+    final catchClause = stackTraceParameter.parent;
     if (catchClause is! CatchClause) {
       return;
     }
 
-    var exceptionParameter = catchClause.exceptionParameter;
+    final exceptionParameter = catchClause.exceptionParameter2;
     if (exceptionParameter == null) {
       return;
     }
 
-    if (catchClause.stackTraceParameter == node) {
+    if (catchClause.stackTraceParameter2 == stackTraceParameter) {
       await builder.addDartFileEdit(file, (builder) {
-        builder.addDeletion(range.endEnd(exceptionParameter, node));
+        builder.addDeletion(
+          range.endEnd(exceptionParameter, stackTraceParameter),
+        );
       });
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index 59d04bd..293ec6c 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -157,7 +157,7 @@
         for (var catchClause in catchClauses) {
           if (firstSelectedNode == catchClause ||
               firstSelectedNode == catchClause.body ||
-              firstSelectedNode == catchClause.exceptionParameter) {
+              firstSelectedNode == catchClause.exceptionParameter2) {
             invalidSelection(
                 'Selection must either cover whole try statement or parts of try, catch, or finally block.');
           }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index fcfcab8..6a74379 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -930,6 +930,14 @@
   }
 
   @override
+  void visitCatchClauseParameter(CatchClauseParameter node) {
+    super.visitCatchClauseParameter(node);
+    if (_isFirstSelectedNode(node)) {
+      invalidSelection('Cannot extract the name part of a declaration.');
+    }
+  }
+
+  @override
   void visitConstructorInitializer(ConstructorInitializer node) {
     super.visitConstructorInitializer(node);
     if (_isFirstSelectedNode(node)) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/visible_ranges_computer.dart b/pkg/analysis_server/lib/src/services/refactoring/visible_ranges_computer.dart
index 72101d6..6e8b38e 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/visible_ranges_computer.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/visible_ranges_computer.dart
@@ -14,8 +14,8 @@
 
   @override
   void visitCatchClause(CatchClause node) {
-    _addLocalVariable(node, node.exceptionParameter?.staticElement);
-    _addLocalVariable(node, node.stackTraceParameter?.staticElement);
+    _addLocalVariable(node, node.exceptionParameter2?.declaredElement);
+    _addLocalVariable(node, node.stackTraceParameter2?.declaredElement);
     node.body.accept(this);
   }
 
diff --git a/pkg/analysis_server/lib/src/status/ast_writer.dart b/pkg/analysis_server/lib/src/status/ast_writer.dart
index 42460ba..af7730c 100644
--- a/pkg/analysis_server/lib/src/status/ast_writer.dart
+++ b/pkg/analysis_server/lib/src/status/ast_writer.dart
@@ -51,7 +51,7 @@
     } else if (node is CompilationUnit) {
       properties['declaredElement'] = node.declaredElement;
     } else if (node is Configuration) {
-      properties['uriSource'] = node.uriSource;
+      properties['uriSource'] = node.resolvedUri;
     } else if (node is ConstructorName) {
       properties['static element'] = node.staticElement;
     } else if (node is DeclaredIdentifier) {
diff --git a/pkg/analysis_server/lib/src/status/tree_writer.dart b/pkg/analysis_server/lib/src/status/tree_writer.dart
index 01543e1..a1fe248 100644
--- a/pkg/analysis_server/lib/src/status/tree_writer.dart
+++ b/pkg/analysis_server/lib/src/status/tree_writer.dart
@@ -4,6 +4,7 @@
 
 import 'dart:convert';
 
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -54,7 +55,13 @@
 
   String? _toString(Object? value) {
     try {
-      if (value is Source) {
+      if (value is DirectiveUri) {
+        if (value is DirectiveUriWithSource) {
+          final sourceStr = _toString(value.source);
+          return 'DirectiveUriWithSource (source=$sourceStr)';
+        }
+        return value.toString();
+      } else if (value is Source) {
         return 'Source (uri="${value.uri}", path="${value.fullName}")';
       } else if (value is ElementAnnotationImpl) {
         var buffer = StringBuffer();
diff --git a/pkg/analysis_server/tool/code_completion/code_metrics.dart b/pkg/analysis_server/tool/code_completion/code_metrics.dart
index cdfd1df..051f919 100644
--- a/pkg/analysis_server/tool/code_completion/code_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/code_metrics.dart
@@ -294,8 +294,8 @@
   void visitCatchClause(CatchClause node) {
     _visitChildren(node, {
       'exceptionType': node.exceptionType,
-      'exceptionParameter': node.exceptionParameter,
-      'stackTraceParameter': node.stackTraceParameter,
+      'exceptionParameter': node.exceptionParameter2,
+      'stackTraceParameter': node.stackTraceParameter2,
       'body': node.body,
     });
     super.visitCatchClause(node);
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 4bf1253..b3d3e24 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -8,8 +8,11 @@
 * Deprecated `ClassElement.hasStaticMember`, it is not useful for clients.
 * Deprecated `NamespaceDirective.uriElement`, use `element2.uri` with `DirectiveUriWithLibrary` instead.
 * Deprecated `UriBasedDirective.uriContent`, `UriBasedDirective.uriElement`, `UriBasedDirective.uriSource`.
-  Use `Directive.element2.uri` instead. 
+  Use `Directive.element2.uri` instead.
 * Deprecated `NamespaceDirective.selectedSource`, use `element2.uri` with `DirectiveUriWithSource` instead.
+* Deprecated `Configuration.uriSource`, use `resolvedUri` instead.
+* Deprecated `CatchClause.exceptionParameter` and `CatchClause.stackTraceParameter`.
+  Use `exceptionParameter2` and `stackTraceParameter2` instead.
 
 ## 4.3.1
 * Fix `identifier` for `LibraryExportElement` and `LibraryImportElement`.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index f4f40f7..38f2281 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -383,6 +383,8 @@
 
   R? visitCatchClause(CatchClause node);
 
+  R? visitCatchClauseParameter(CatchClauseParameter node);
+
   R? visitClassDeclaration(ClassDeclaration node);
 
   R? visitClassTypeAlias(ClassTypeAlias node);
@@ -804,8 +806,13 @@
 
   /// Return the parameter whose value will be the exception that was thrown, or
   /// `null` if there is no 'catch' keyword.
+  @Deprecated('Use exceptionParameter2 instead')
   SimpleIdentifier? get exceptionParameter;
 
+  /// Return the parameter whose value will be the exception that was thrown, or
+  /// `null` if there is no 'catch' keyword.
+  CatchClauseParameter? get exceptionParameter2;
+
   /// Return the type of exceptions caught by this catch clause, or `null` if
   /// this catch clause catches every type of exception.
   TypeAnnotation? get exceptionType;
@@ -822,7 +829,23 @@
 
   /// Return the parameter whose value will be the stack trace associated with
   /// the exception, or `null` if there is no stack trace parameter.
+  @Deprecated('Use stackTraceParameter2 instead')
   SimpleIdentifier? get stackTraceParameter;
+
+  /// Return the parameter whose value will be the stack trace associated with
+  /// the exception, or `null` if there is no stack trace parameter.
+  CatchClauseParameter? get stackTraceParameter2;
+}
+
+/// The 'exception' or 'stackTrace' parameter in [CatchClause].
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CatchClauseParameter extends AstNode {
+  /// The declared element, or `null` if the AST has not been resolved.
+  LocalVariableElement? get declaredElement;
+
+  /// The name of the parameter.
+  Token get name;
 }
 
 /// The declaration of a class.
@@ -1237,6 +1260,9 @@
   /// condition.
   DottedName get name;
 
+  /// The result of resolving [uri].
+  DirectiveUri? get resolvedUri;
+
   /// Return the token for the right parenthesis.
   Token get rightParenthesis;
 
@@ -1245,7 +1271,7 @@
   StringLiteral get uri;
 
   /// Return the source to which the [uri] was resolved.
-  /// TODO(scheglov) Deprecate and remove.
+  @Deprecated('Use resolvedUri and check for DirectiveUriWithSource instead')
   Source? get uriSource;
 
   /// Return the value to which the value of the declared variable will be
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index 2c43bc6..a82ad8e 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -182,6 +182,9 @@
   R? visitCatchClause(CatchClause node) => visitNode(node);
 
   @override
+  R? visitCatchClauseParameter(CatchClauseParameter node) => visitNode(node);
+
+  @override
   R? visitClassDeclaration(ClassDeclaration node) =>
       visitNamedCompilationUnitMember(node);
 
@@ -756,6 +759,12 @@
   }
 
   @override
+  R? visitCatchClauseParameter(CatchClauseParameter node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R? visitClassDeclaration(ClassDeclaration node) {
     node.visitChildren(this);
     return null;
@@ -1518,6 +1527,9 @@
   R? visitCatchClause(CatchClause node) => null;
 
   @override
+  R? visitCatchClauseParameter(CatchClauseParameter node) => null;
+
+  @override
   R? visitClassDeclaration(ClassDeclaration node) => null;
 
   @override
@@ -1938,6 +1950,9 @@
   R? visitCatchClause(CatchClause node) => _throw(node);
 
   @override
+  R? visitCatchClauseParameter(CatchClauseParameter node) => _throw(node);
+
+  @override
   R? visitClassDeclaration(ClassDeclaration node) => _throw(node);
 
   @override
@@ -2452,6 +2467,14 @@
   }
 
   @override
+  T? visitCatchClauseParameter(CatchClauseParameter node) {
+    stopwatch.start();
+    T? result = _baseVisitor.visitCatchClauseParameter(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T? visitClassDeclaration(ClassDeclaration node) {
     stopwatch.start();
     T? result = _baseVisitor.visitClassDeclaration(node);
@@ -3454,6 +3477,9 @@
   R? visitCatchClause(CatchClause node) => visitNode(node);
 
   @override
+  R? visitCatchClauseParameter(CatchClauseParameter node) => visitNode(node);
+
+  @override
   R? visitClassDeclaration(ClassDeclaration node) => visitNode(node);
 
   @override
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index ac9dc6c..a6b2d79 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -78,7 +78,7 @@
 /// The result of applying augmentations to a [ClassElement].
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class AugmentedClassElement implements AugmentedClassOrEnumElement {
+abstract class AugmentedClassElement implements AugmentedInterfaceElement {
   /// Returns mixins applied by this class or in its augmentations.
   ///
   /// This is a union of mixins applied by the class declaration and all its
@@ -86,28 +86,10 @@
   List<InterfaceType> get mixins;
 }
 
-/// The result of applying augmentations to a [ClassElement] or [EnumElement].
-///
-/// Clients may not extend, implement or mix-in this class.
-abstract class AugmentedClassOrEnumElement
-    implements AugmentedInterfaceElement {
-  /// Returns constructors declared in this element.
-  ///
-  /// [ConstructorAugmentationElement]s replace corresponding elements,
-  /// other [ConstructorElement]s are appended.
-  List<ConstructorElement> get constructors;
-
-  /// Returns the unnamed constructor from [constructors].
-  ConstructorElement? get unnamedConstructor;
-
-  /// Returns the constructor from [constructors] that has the given [name].
-  ConstructorElement? getNamedConstructor(String name);
-}
-
 /// The result of applying augmentations to a [EnumElement].
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class AugmentedEnumElement implements AugmentedClassOrEnumElement {
+abstract class AugmentedEnumElement implements AugmentedInterfaceElement {
   /// Returns mixins applied by this class or in its augmentations.
   ///
   /// This is a union of mixins applied by the class declaration and all its
@@ -125,6 +107,12 @@
   /// other [PropertyAccessorElement]s are appended.
   List<PropertyAccessorElement> get accessors;
 
+  /// Returns constructors declared in this element.
+  ///
+  /// [ConstructorAugmentationElement]s replace corresponding elements,
+  /// other [ConstructorElement]s are appended.
+  List<ConstructorElement> get constructors;
+
   /// Returns fields declared in this element.
   ///
   /// [FieldAugmentationElement]s replace corresponding elements, other
@@ -149,6 +137,9 @@
   /// [MethodElement]s are appended.
   List<MethodElement> get methods;
 
+  /// Returns the unnamed constructor from [constructors].
+  ConstructorElement? get unnamedConstructor;
+
   /// Returns the field from [fields] that has the given [name].
   FieldElement? getField(String name);
 
@@ -158,6 +149,9 @@
   /// Returns the method from [methods] that has the given [name].
   MethodElement? getMethod(String name);
 
+  /// Returns the constructor from [constructors] that has the given [name].
+  ConstructorElement? getNamedConstructor(String name);
+
   /// Returns the setter from [accessors] that has the given [name].
   PropertyAccessorElement? getSetter(String name);
 }
@@ -1454,7 +1448,7 @@
 abstract class LibraryAugmentationElement
     implements LibraryOrAugmentationElement, _ExistingElement {
   /// Returns the library that is augmented by this augmentation.
-  LibraryOrAugmentationElement get augmented;
+  LibraryOrAugmentationElement get augmentationTarget;
 }
 
 /// A library.
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index b7ec2f5..3b3f088 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -560,7 +560,6 @@
       directive.uriSource = uriState.source;
     }
 
-    // TODO(scheglov) Similarly restructure imports/exports.
     final AugmentationFileKind? importedAugmentationKind;
     if (state is AugmentationImportWithFile) {
       importedAugmentationKind = state.importedAugmentation;
@@ -869,10 +868,8 @@
     required List<file_state.DirectiveUri> configurationUris,
   }) {
     for (var i = 0; i < configurationNodes.length; i++) {
-      final configurationNode = configurationNodes[i];
-      configurationNode as ConfigurationImpl;
-      // TODO(scheglov) Use `DirectiveUri` here instead.
-      configurationNode.uriSource = configurationUris[i].source;
+      final node = configurationNodes[i] as ConfigurationImpl;
+      node.resolvedUri = configurationUris[i].asDirectiveUri;
     }
 
     if (primaryUriState is DirectiveUriWithString) {
@@ -883,7 +880,9 @@
     }
 
     if (selectedUriState is DirectiveUriWithString) {
+      // ignore: deprecated_member_use_from_same_package
       directive.selectedUriContent = selectedUriState.relativeUriStr;
+      // ignore: deprecated_member_use_from_same_package
       directive.selectedSource = selectedUriState.source;
     }
   }
@@ -1025,3 +1024,26 @@
 
   UnitAnalysisResult(this.file, this.unit, this.errors);
 }
+
+extension on file_state.DirectiveUri {
+  DirectiveUriImpl get asDirectiveUri {
+    final self = this;
+    if (self is file_state.DirectiveUriWithSource) {
+      return DirectiveUriWithSourceImpl(
+        relativeUriString: self.relativeUriStr,
+        relativeUri: self.relativeUri,
+        source: self.source,
+      );
+    } else if (self is file_state.DirectiveUriWithUri) {
+      return DirectiveUriWithRelativeUriImpl(
+        relativeUriString: self.relativeUriStr,
+        relativeUri: self.relativeUri,
+      );
+    } else if (self is file_state.DirectiveUriWithString) {
+      return DirectiveUriWithRelativeUriStringImpl(
+        relativeUriString: self.relativeUriStr,
+      );
+    }
+    return DirectiveUriImpl();
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index c36c045..4e04433 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -21,6 +21,7 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/utilities/extensions/object.dart';
 import 'package:meta/meta.dart';
 
 /// Two or more string literals that are implicitly concatenated because of
@@ -1410,7 +1411,7 @@
 
   /// The parameter whose value will be the exception that was thrown, or `null`
   /// if there is no 'catch' keyword.
-  SimpleIdentifierImpl? _exceptionParameter;
+  CatchClauseParameterImpl? _exceptionParameter;
 
   /// The comma separating the exception parameter from the stack trace
   /// parameter, or `null` if there is no stack trace parameter.
@@ -1419,7 +1420,7 @@
 
   /// The parameter whose value will be the stack trace associated with the
   /// exception, or `null` if there is no stack trace parameter.
-  SimpleIdentifierImpl? _stackTraceParameter;
+  CatchClauseParameterImpl? _stackTraceParameter;
 
   /// The right parenthesis, or `null` if there is no 'catch' keyword.
   @override
@@ -1430,7 +1431,7 @@
 
   /// Initialize a newly created catch clause. The [onKeyword] and
   /// [exceptionType] can be `null` if the clause will catch all exceptions. The
-  /// [comma] and [stackTraceParameter] can be `null` if the stack trace
+  /// [comma] and [_stackTraceParameter] can be `null` if the stack trace
   /// parameter is not defined.
   CatchClauseImpl(
       this.onKeyword,
@@ -1467,11 +1468,20 @@
   @override
   Token get endToken => _body.endToken;
 
+  @Deprecated('Use exceptionParameter2 instead')
   @override
-  SimpleIdentifierImpl? get exceptionParameter => _exceptionParameter;
+  SimpleIdentifierImpl? get exceptionParameter {
+    return _exceptionParameter?.nameNode;
+  }
 
-  set exceptionParameter(SimpleIdentifier? parameter) {
-    _exceptionParameter = _becomeParentOf(parameter as SimpleIdentifierImpl?);
+  @override
+  CatchClauseParameterImpl? get exceptionParameter2 {
+    return _exceptionParameter;
+  }
+
+  set exceptionParameter2(CatchClauseParameterImpl? parameter) {
+    _exceptionParameter = parameter;
+    _becomeParentOf(parameter);
   }
 
   @override
@@ -1481,11 +1491,20 @@
     _exceptionType = _becomeParentOf(exceptionType as TypeAnnotationImpl?);
   }
 
+  @Deprecated('Use stackTraceParameter2 instead')
   @override
-  SimpleIdentifierImpl? get stackTraceParameter => _stackTraceParameter;
+  SimpleIdentifierImpl? get stackTraceParameter {
+    return _stackTraceParameter?.nameNode;
+  }
 
-  set stackTraceParameter(SimpleIdentifier? parameter) {
-    _stackTraceParameter = _becomeParentOf(parameter as SimpleIdentifierImpl?);
+  @override
+  CatchClauseParameterImpl? get stackTraceParameter2 {
+    return _stackTraceParameter;
+  }
+
+  set stackTraceParameter2(CatchClauseParameterImpl? parameter) {
+    _stackTraceParameter = parameter;
+    _becomeParentOf(parameter);
   }
 
   @override
@@ -1494,9 +1513,9 @@
     ..addNode('exceptionType', exceptionType)
     ..addToken('catchKeyword', catchKeyword)
     ..addToken('leftParenthesis', leftParenthesis)
-    ..addNode('exceptionParameter', exceptionParameter)
+    ..addNode('exceptionParameter', exceptionParameter2)
     ..addToken('comma', comma)
-    ..addNode('stackTraceParameter', stackTraceParameter)
+    ..addNode('stackTraceParameter', stackTraceParameter2)
     ..addToken('rightParenthesis', rightParenthesis)
     ..addNode('body', body);
 
@@ -1512,6 +1531,40 @@
   }
 }
 
+class CatchClauseParameterImpl extends AstNodeImpl
+    implements CatchClauseParameter {
+  /// TODO(scheglov) Eventually replace with [Token].
+  final SimpleIdentifierImpl nameNode;
+
+  @override
+  LocalVariableElement? declaredElement;
+
+  CatchClauseParameterImpl({
+    required this.nameNode,
+  }) {
+    _becomeParentOf(nameNode);
+  }
+
+  @override
+  Token get beginToken => name;
+
+  @override
+  Token get endToken => name;
+
+  @override
+  Token get name => nameNode.token;
+
+  @override
+  E? accept<E>(AstVisitor<E> visitor) {
+    return visitor.visitCatchClauseParameter(this);
+  }
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    nameNode.accept(visitor);
+  }
+}
+
 /// Helper class to allow iteration of child entities of an AST node.
 class ChildEntities {
   /// The list of child entities to be iterated over.
@@ -2489,7 +2542,7 @@
   StringLiteralImpl _uri;
 
   @override
-  Source? uriSource;
+  DirectiveUri? resolvedUri;
 
   ConfigurationImpl(this.ifKeyword, this.leftParenthesis, this._name,
       this.equalToken, this._value, this.rightParenthesis, this._uri) {
@@ -2518,6 +2571,12 @@
     _uri = _becomeParentOf(uri as StringLiteralImpl);
   }
 
+  @Deprecated('Use resolvedUri instead')
+  @override
+  Source? get uriSource {
+    return resolvedUri?.ifTypeOrNull<DirectiveUriWithSource>()?.source;
+  }
+
   @override
   StringLiteralImpl? get value => _value;
 
@@ -8246,9 +8305,11 @@
   @override
   Token semicolon;
 
+  @Deprecated('Use element2.uri instead')
   @override
   String? selectedUriContent;
 
+  @Deprecated('Use element2.uri instead')
   @override
   Source? selectedSource;
 
@@ -9949,6 +10010,9 @@
         return false;
       }
     }
+    if (parent is CatchClauseParameterImpl && parent.nameNode == this) {
+      return false;
+    }
     if (parent is ConstructorFieldInitializer &&
         identical(parent.fieldName, target)) {
       return false;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 0e45fe4..d0fffa1 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -53,27 +53,6 @@
           Expression target, List<Expression> cascadeSections) =>
       CascadeExpressionImpl(target as ExpressionImpl, cascadeSections);
 
-  CatchClauseImpl catchClause(
-          Token? onKeyword,
-          TypeAnnotation? exceptionType,
-          Token? catchKeyword,
-          Token? leftParenthesis,
-          SimpleIdentifier? exceptionParameter,
-          Token? comma,
-          SimpleIdentifier? stackTraceParameter,
-          Token? rightParenthesis,
-          Block body) =>
-      CatchClauseImpl(
-          onKeyword,
-          exceptionType as TypeAnnotationImpl?,
-          catchKeyword,
-          leftParenthesis,
-          exceptionParameter as SimpleIdentifierImpl?,
-          comma,
-          stackTraceParameter as SimpleIdentifierImpl?,
-          rightParenthesis,
-          body as BlockImpl);
-
   ClassDeclarationImpl classDeclaration(
           Comment? comment,
           List<Annotation>? metadata,
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index 5a83d20..f344609 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -146,8 +146,8 @@
         sink.write(' ');
       }
       sink.write('catch (');
-      _visitNode(node.exceptionParameter);
-      _visitNode(node.stackTraceParameter, prefix: ', ');
+      _visitNode(node.exceptionParameter2);
+      _visitNode(node.stackTraceParameter2, prefix: ', ');
       sink.write(') ');
     } else {
       sink.write(' ');
@@ -156,6 +156,11 @@
   }
 
   @override
+  void visitCatchClauseParameter(CatchClauseParameter node) {
+    _visitToken(node.name);
+  }
+
+  @override
   void visitClassDeclaration(covariant ClassDeclarationImpl node) {
     _visitNodeList(node.metadata, separator: ' ', suffix: ' ');
     _visitToken(node.abstractKeyword, suffix: ' ');
@@ -1184,8 +1189,9 @@
   }
 
   /// Print the given [token].
-  void _visitToken(Token? token, {String suffix = ''}) {
+  void _visitToken(Token? token, {String prefix = '', String suffix = ''}) {
     if (token != null) {
+      sink.write(prefix);
       sink.write(token.lexeme);
       sink.write(suffix);
     }
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index f1eb7bf..251454c 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.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.
 
-import 'dart:collection';
-
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -230,14 +228,20 @@
         isEqualNodes(node.exceptionType, other.exceptionType) &&
         isEqualTokens(node.catchKeyword, other.catchKeyword) &&
         isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.exceptionParameter, other.exceptionParameter) &&
+        isEqualNodes(node.exceptionParameter2, other.exceptionParameter2) &&
         isEqualTokens(node.comma, other.comma) &&
-        isEqualNodes(node.stackTraceParameter, other.stackTraceParameter) &&
+        isEqualNodes(node.stackTraceParameter2, other.stackTraceParameter2) &&
         isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
         isEqualNodes(node.body, other.body);
   }
 
   @override
+  bool visitCatchClauseParameter(CatchClauseParameter node) {
+    CatchClauseParameter other = _other as CatchClauseParameter;
+    return isEqualTokens(node.name, other.name);
+  }
+
+  @override
   bool visitClassDeclaration(ClassDeclaration node) {
     ClassDeclaration other = _other as ClassDeclaration;
     return isEqualNodes(
@@ -1781,11 +1785,11 @@
     if (identical(node.exceptionType, _oldNode)) {
       node.exceptionType = _newNode as TypeAnnotation;
       return true;
-    } else if (identical(node.exceptionParameter, _oldNode)) {
-      node.exceptionParameter = _newNode as SimpleIdentifier;
+    } else if (identical(node.exceptionParameter2, _oldNode)) {
+      node.exceptionParameter2 = _newNode as CatchClauseParameterImpl;
       return true;
-    } else if (identical(node.stackTraceParameter, _oldNode)) {
-      node.stackTraceParameter = _newNode as SimpleIdentifier;
+    } else if (identical(node.stackTraceParameter2, _oldNode)) {
+      node.stackTraceParameter2 = _newNode as CatchClauseParameterImpl;
       return true;
     } else if (identical(node.body, _oldNode)) {
       node.body = _newNode as Block;
@@ -1795,6 +1799,11 @@
   }
 
   @override
+  bool? visitCatchClauseParameter(CatchClauseParameter node) {
+    return visitNode(node);
+  }
+
+  @override
   bool visitClassDeclaration(covariant ClassDeclarationImpl node) {
     if (identical(node.name, _oldNode)) {
       node.name = _newNode as SimpleIdentifier;
@@ -3144,8 +3153,7 @@
 
   AstNode? _immediateChild;
 
-  final Map<String, SimpleIdentifier> _locals =
-      HashMap<String, SimpleIdentifier>();
+  final Set<String> _locals = {};
 
   final int _position;
 
@@ -3155,7 +3163,7 @@
 
   Declaration? get declaration => _declarationNode;
 
-  Map<String, SimpleIdentifier> get locals => _locals;
+  Set<String> get locals => _locals;
 
   @override
   void visitBlock(Block node) {
@@ -3165,8 +3173,8 @@
 
   @override
   void visitCatchClause(CatchClause node) {
-    _addToScope(node.exceptionParameter);
-    _addToScope(node.stackTraceParameter);
+    _addToScope2(node.exceptionParameter2?.name);
+    _addToScope2(node.stackTraceParameter2?.name);
     super.visitCatchClause(node);
   }
 
@@ -3258,10 +3266,16 @@
 
   void _addToScope(SimpleIdentifier? identifier) {
     if (identifier != null && _isInRange(identifier)) {
-      String name = identifier.name;
-      if (!_locals.containsKey(name)) {
-        _locals[name] = identifier;
-      }
+      _locals.add(identifier.name);
+    }
+  }
+
+  /// TODO(scheglov) If we still have [_addToScope] after:
+  /// https://dart-review.googlesource.com/c/sdk/+/252566,
+  /// rename to `_addNodeToScope` and `_addTokenToScope`.
+  void _addToScope2(Token? identifier) {
+    if (identifier != null && _isInRange2(identifier)) {
+      _locals.add(identifier.lexeme);
     }
   }
 
@@ -3296,4 +3310,13 @@
     }
     return node.end < _position;
   }
+
+  bool _isInRange2(Token token) {
+    if (_position < 0) {
+      // if source position is not set then all nodes are in range
+      return true;
+      // not reached
+    }
+    return token.end < _position;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index d734a09..b9ef02c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1763,7 +1763,7 @@
   });
 }
 
-class DirectiveUriWithRelativeUriStringImpl
+class DirectiveUriWithRelativeUriStringImpl extends DirectiveUriImpl
     implements DirectiveUriWithRelativeUriString {
   @override
   final String relativeUriString;
@@ -3895,12 +3895,12 @@
 class LibraryAugmentationElementImpl extends LibraryOrAugmentationElementImpl
     implements LibraryAugmentationElement {
   @override
-  final LibraryOrAugmentationElementImpl augmented;
+  final LibraryOrAugmentationElementImpl augmentationTarget;
 
   LibraryAugmentationElementLinkedData? linkedData;
 
   LibraryAugmentationElementImpl({
-    required this.augmented,
+    required this.augmentationTarget,
     required super.nameOffset,
   }) : super(name: null);
 
@@ -3915,19 +3915,21 @@
   }
 
   @override
-  FeatureSet get featureSet => augmented.featureSet;
+  FeatureSet get featureSet => augmentationTarget.featureSet;
 
   @override
-  bool get isNonNullableByDefault => augmented.isNonNullableByDefault;
+  bool get isNonNullableByDefault => augmentationTarget.isNonNullableByDefault;
 
   @override
   ElementKind get kind => ElementKind.LIBRARY_AUGMENTATION;
 
   @override
-  LibraryLanguageVersion get languageVersion => augmented.languageVersion;
+  LibraryLanguageVersion get languageVersion {
+    return augmentationTarget.languageVersion;
+  }
 
   @override
-  LibraryElementImpl get library => augmented.library;
+  LibraryElementImpl get library => augmentationTarget.library;
 
   @override
   List<LibraryExportElement> get libraryExports {
@@ -3944,13 +3946,13 @@
   Source get librarySource => library.source;
 
   @override
-  AnalysisSessionImpl get session => augmented.session;
+  AnalysisSessionImpl get session => augmentationTarget.session;
 
   @override
-  TypeProvider get typeProvider => augmented.typeProvider;
+  TypeProvider get typeProvider => augmentationTarget.typeProvider;
 
   @override
-  TypeSystem get typeSystem => augmented.typeSystem;
+  TypeSystem get typeSystem => augmentationTarget.typeSystem;
 
   @override
   T? accept<T>(ElementVisitor<T> visitor) {
@@ -3959,7 +3961,7 @@
 
   @override
   void _readLinkedData() {
-    augmented._readLinkedData();
+    augmentationTarget._readLinkedData();
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 7b8101e..43ad2d4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -466,12 +466,11 @@
   @override
   void visitCatchClause(CatchClause node) {
     for (var identifier in [
-      node.exceptionParameter,
-      node.stackTraceParameter
+      node.exceptionParameter2,
+      node.stackTraceParameter2,
     ]) {
       if (identifier != null) {
-        assignedVariables
-            .declare(identifier.staticElement as PromotableElement);
+        assignedVariables.declare(identifier.declaredElement!);
       }
     }
     super.visitCatchClause(node);
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index ed87486..a528110 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -181,16 +181,17 @@
     exceptionTypeNode?.accept(this);
 
     _withNameScope(() {
-      var exceptionNode = node.exceptionParameter;
+      var exceptionNode = node.exceptionParameter2;
       if (exceptionNode != null) {
         var element = LocalVariableElementImpl(
-          exceptionNode.name,
-          exceptionNode.offset,
+          exceptionNode.name.lexeme,
+          exceptionNode.name.offset,
         );
         _elementHolder.enclose(element);
         _define(element);
 
-        exceptionNode.staticElement = element;
+        exceptionNode.declaredElement = element;
+        exceptionNode.nameNode.staticElement = element;
 
         element.isFinal = true;
         if (exceptionTypeNode == null) {
@@ -198,31 +199,38 @@
           var type =
               _isNonNullableByDefault ? _typeProvider.objectType : _dynamicType;
           element.type = type;
-          exceptionNode.staticType = type;
+          exceptionNode.nameNode.staticType = type;
         } else {
           element.type = exceptionTypeNode.typeOrThrow;
-          exceptionNode.staticType = exceptionTypeNode.type;
+          exceptionNode.nameNode.staticType = exceptionTypeNode.type;
         }
 
-        _setCodeRange(element, exceptionNode);
+        element.setCodeRange(
+          exceptionNode.name.offset,
+          exceptionNode.name.length,
+        );
       }
 
-      var stackTraceNode = node.stackTraceParameter;
+      var stackTraceNode = node.stackTraceParameter2;
       if (stackTraceNode != null) {
         var element = LocalVariableElementImpl(
-          stackTraceNode.name,
-          stackTraceNode.offset,
+          stackTraceNode.name.lexeme,
+          stackTraceNode.name.offset,
         );
         _elementHolder.enclose(element);
         _define(element);
 
-        stackTraceNode.staticElement = element;
+        stackTraceNode.declaredElement = element;
+        stackTraceNode.nameNode.staticElement = element;
 
         element.isFinal = true;
         element.type = _typeProvider.stackTraceType;
-        stackTraceNode.staticType = _typeProvider.stackTraceType;
+        stackTraceNode.nameNode.staticType = _typeProvider.stackTraceType;
 
-        _setCodeRange(element, stackTraceNode);
+        element.setCodeRange(
+          stackTraceNode.name.offset,
+          stackTraceNode.name.length,
+        );
       }
 
       node.body.accept(this);
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 9687d8c..58db0cd 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -25,11 +25,11 @@
 
   /// Check that the exception and stack trace parameters have different names.
   void checkCatchClause(CatchClause node) {
-    var exceptionParameter = node.exceptionParameter;
-    var stackTraceParameter = node.stackTraceParameter;
+    var exceptionParameter = node.exceptionParameter2;
+    var stackTraceParameter = node.stackTraceParameter2;
     if (exceptionParameter != null && stackTraceParameter != null) {
-      String exceptionName = exceptionParameter.name;
-      if (exceptionName == stackTraceParameter.name) {
+      String exceptionName = exceptionParameter.name.lexeme;
+      if (exceptionName == stackTraceParameter.name.lexeme) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.DUPLICATE_DEFINITION,
             stackTraceParameter,
diff --git a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
index aab0059..66a2b0f 100644
--- a/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
+++ b/pkg/analyzer/lib/src/error/unused_local_elements_verifier.dart
@@ -52,17 +52,17 @@
 
   @override
   void visitCatchClause(CatchClause node) {
-    var exceptionParameter = node.exceptionParameter;
-    var stackTraceParameter = node.stackTraceParameter;
+    var exceptionParameter = node.exceptionParameter2;
+    var stackTraceParameter = node.stackTraceParameter2;
     if (exceptionParameter != null) {
-      var element = exceptionParameter.staticElement;
+      var element = exceptionParameter.declaredElement;
       usedElements.addCatchException(element);
       if (stackTraceParameter != null || node.onKeyword == null) {
         usedElements.addElement(element);
       }
     }
     if (stackTraceParameter != null) {
-      var element = stackTraceParameter.staticElement;
+      var element = stackTraceParameter.declaredElement;
       usedElements.addCatchStackTrace(element);
     }
     super.visitCatchClause(node);
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index b40172c..ee1e932 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2745,16 +2745,27 @@
         stackTrace = catchParameters[1].identifier;
       }
     }
-    push(ast.catchClause(
+    push(
+      CatchClauseImpl(
         onKeyword,
-        type,
+        type as TypeAnnotationImpl?,
         catchKeyword,
         catchParameterList?.leftParenthesis,
-        exception,
+        exception != null
+            ? CatchClauseParameterImpl(
+                nameNode: exception as SimpleIdentifierImpl,
+              )
+            : null,
         comma,
-        stackTrace,
+        stackTrace != null
+            ? CatchClauseParameterImpl(
+                nameNode: stackTrace as SimpleIdentifierImpl,
+              )
+            : null,
         catchParameterList?.rightParenthesis,
-        body));
+        body as BlockImpl,
+      ),
+    );
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 9a01970..9123552 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1131,6 +1131,11 @@
   }
 
   @override
+  void visitCatchClauseParameter(CatchClauseParameter node) {
+    node.visitChildren(this);
+  }
+
+  @override
   void visitClassDeclaration(ClassDeclaration node) {
     //
     // Continue the class resolution.
@@ -2440,8 +2445,8 @@
         var catchClause = catchClauses[i];
         nullSafetyDeadCodeVerifier.verifyCatchClause(catchClause);
         flow.tryCatchStatement_catchBegin(
-          catchClause.exceptionParameter?.staticElement as PromotableElement?,
-          catchClause.stackTraceParameter?.staticElement as PromotableElement?,
+          catchClause.exceptionParameter2?.declaredElement,
+          catchClause.stackTraceParameter2?.declaredElement,
         );
         catchClause.accept(this);
         flow.tryCatchStatement_catchEnd();
@@ -2990,15 +2995,15 @@
 
   @override
   void visitCatchClause(CatchClause node) {
-    var exception = node.exceptionParameter;
+    var exception = node.exceptionParameter2;
     if (exception != null) {
       Scope outerScope = nameScope;
       try {
         nameScope = LocalScope(nameScope);
-        _define(exception.staticElement!);
-        var stackTrace = node.stackTraceParameter;
+        _define(exception.declaredElement!);
+        var stackTrace = node.stackTraceParameter2;
         if (stackTrace != null) {
-          _define(stackTrace.staticElement!);
+          _define(stackTrace.declaredElement!);
         }
         super.visitCatchClause(node);
       } finally {
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index e8b0fa6..a5ee15d 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -159,48 +159,6 @@
     return cascade;
   }
 
-  static CatchClauseImpl catchClause(String exceptionParameter,
-          [List<Statement> statements = const []]) =>
-      catchClause5(null, exceptionParameter, null, statements);
-
-  static CatchClauseImpl catchClause2(
-          String exceptionParameter, String stackTraceParameter,
-          [List<Statement> statements = const []]) =>
-      catchClause5(null, exceptionParameter, stackTraceParameter, statements);
-
-  static CatchClauseImpl catchClause3(TypeAnnotation exceptionType,
-          [List<Statement> statements = const []]) =>
-      catchClause5(exceptionType, null, null, statements);
-
-  static CatchClauseImpl catchClause4(
-          TypeAnnotation exceptionType, String exceptionParameter,
-          [List<Statement> statements = const []]) =>
-      catchClause5(exceptionType, exceptionParameter, null, statements);
-
-  static CatchClauseImpl catchClause5(TypeAnnotation? exceptionType,
-          String? exceptionParameter, String? stackTraceParameter,
-          [List<Statement> statements = const []]) =>
-      astFactory.catchClause(
-          exceptionType == null
-              ? null
-              : TokenFactory.tokenFromTypeAndString(TokenType.IDENTIFIER, "on"),
-          exceptionType,
-          exceptionParameter == null
-              ? null
-              : TokenFactory.tokenFromKeyword(Keyword.CATCH),
-          exceptionParameter == null
-              ? null
-              : TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-          exceptionParameter == null ? null : identifier3(exceptionParameter),
-          stackTraceParameter == null
-              ? null
-              : TokenFactory.tokenFromType(TokenType.COMMA),
-          stackTraceParameter == null ? null : identifier3(stackTraceParameter),
-          exceptionParameter == null
-              ? null
-              : TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-          block(statements));
-
   static ClassDeclarationImpl classDeclaration(
           Keyword? abstractKeyword,
           String name,
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index 22d52eb..73d60a8 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -134,14 +134,19 @@
     node.exceptionType?.accept(this);
     _token(node.catchKeyword);
     _token(node.leftParenthesis);
-    node.exceptionParameter?.accept(this);
+    node.exceptionParameter2?.accept(this);
     _token(node.comma);
-    node.stackTraceParameter?.accept(this);
+    node.stackTraceParameter2?.accept(this);
     _token(node.rightParenthesis);
     node.body.accept(this);
   }
 
   @override
+  void visitCatchClauseParameter(CatchClauseParameter node) {
+    _token(node.name);
+  }
+
+  @override
   void visitClassDeclaration(covariant ClassDeclarationImpl node) {
     _compilationUnitMember(node);
     _token(node.abstractKeyword);
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 27c7070..626dd40 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -545,7 +545,7 @@
   }
 
   LibraryAugmentationElementImpl _readAugmentationElement({
-    required LibraryOrAugmentationElementImpl augmented,
+    required LibraryOrAugmentationElementImpl augmentationTarget,
     required Source unitSource,
   }) {
     final definingUnit = _readUnitElement(
@@ -555,7 +555,7 @@
     );
 
     final augmentation = LibraryAugmentationElementImpl(
-      augmented: augmented,
+      augmentationTarget: augmentationTarget,
       nameOffset: -1, // TODO(scheglov) implement, test
     );
     augmentation.definingCompilationUnit = definingUnit;
@@ -716,7 +716,7 @@
       case DirectiveUriKind.withAugmentation:
         final parent = readWithSource();
         final augmentation = _readAugmentationElement(
-          augmented: container,
+          augmentationTarget: container,
           unitSource: parent.source,
         );
         return DirectiveUriWithAugmentationImpl(
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index e1511dd..b472f5a 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -440,7 +440,7 @@
   }
 
   AugmentationImportElementImpl _buildAugmentationImport(
-    LibraryOrAugmentationElementImpl augmentedElement,
+    LibraryOrAugmentationElementImpl augmentationTarget,
     AugmentationImportState state,
   ) {
     final DirectiveUri uri;
@@ -463,7 +463,7 @@
         _bindReference(unitReference, unitElement);
 
         final augmentation = LibraryAugmentationElementImpl(
-          augmented: augmentedElement,
+          augmentationTarget: augmentationTarget,
           nameOffset: importedAugmentation.unlinked.libraryKeywordOffset,
         );
         augmentation.definingCompilationUnit = unitElement;
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index c19ca5e..31801f0 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -133,13 +133,11 @@
     }
 
     unit.accept(FunctionAstVisitor(
-      declaredIdentifier: (node) {
+      catchClauseParameter: (node) {
         updateResult(node.declaredElement!);
       },
-      simpleIdentifier: (node) {
-        if (node.parent is CatchClause) {
-          updateResult(node.staticElement!);
-        }
+      declaredIdentifier: (node) {
+        updateResult(node.declaredElement!);
       },
       variableDeclaration: (node) {
         updateResult(node.declaredElement!);
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index e933186..5ffa874 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -91,6 +91,10 @@
     return _node(search, (n) => n is CatchClause);
   }
 
+  CatchClauseParameter catchClauseParameter(String search) {
+    return _node(search, (n) => n is CatchClauseParameter);
+  }
+
   ClassDeclaration classDeclaration(String search) {
     return _node(search, (n) => n is ClassDeclaration);
   }
@@ -115,6 +119,10 @@
     return _node(search, (n) => n is ConditionalExpression);
   }
 
+  Configuration configuration(String search) {
+    return _node(search, (n) => n is Configuration);
+  }
+
   ConstructorDeclaration constructor(String search) {
     return _node(search, (n) => n is ConstructorDeclaration);
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
index bb1476c..c8956e5 100644
--- a/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
+++ b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
@@ -7,6 +7,7 @@
 
 /// [RecursiveAstVisitor] that delegates visit methods to functions.
 class FunctionAstVisitor extends RecursiveAstVisitor<void> {
+  final void Function(CatchClauseParameter)? catchClauseParameter;
   final void Function(DeclaredIdentifier)? declaredIdentifier;
   final void Function(FunctionDeclarationStatement)?
       functionDeclarationStatement;
@@ -17,6 +18,7 @@
   final void Function(VariableDeclaration)? variableDeclaration;
 
   FunctionAstVisitor({
+    this.catchClauseParameter,
     this.declaredIdentifier,
     this.functionDeclarationStatement,
     this.functionExpression,
@@ -27,6 +29,12 @@
   });
 
   @override
+  void visitCatchClauseParameter(CatchClauseParameter node) {
+    catchClauseParameter?.call(node);
+    super.visitCatchClauseParameter(node);
+  }
+
+  @override
   void visitDeclaredIdentifier(DeclaredIdentifier node) {
     if (declaredIdentifier != null) {
       declaredIdentifier!(node);
diff --git a/pkg/analyzer/test/generated/statement_parser_test.dart b/pkg/analyzer/test/generated/statement_parser_test.dart
index 702d950..ec1236b 100644
--- a/pkg/analyzer/test/generated/statement_parser_test.dart
+++ b/pkg/analyzer/test/generated/statement_parser_test.dart
@@ -1407,9 +1407,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
+    expect(clause.stackTraceParameter2, isNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1430,9 +1430,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter!.name, 'int');
+    expect(clause.exceptionParameter2!.name.lexeme, 'int');
     expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter!.name, 'e');
+    expect(clause.stackTraceParameter2!.name.lexeme, 'e');
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1449,9 +1449,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
+    expect(clause.stackTraceParameter2, isNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1468,9 +1468,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
+    expect(clause.stackTraceParameter2, isNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1487,9 +1487,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.stackTraceParameter2, isNotNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1507,9 +1507,9 @@
     expect(clause.onKeyword, isNull);
     expect(clause.exceptionType, isNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.stackTraceParameter2, isNotNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNotNull);
     expect(statement.finallyBlock, isNotNull);
@@ -1548,9 +1548,9 @@
     expect(clause.onKeyword, isNotNull);
     expect(clause.exceptionType, isNotNull);
     expect(clause.catchKeyword, isNull);
-    expect(clause.exceptionParameter, isNull);
+    expect(clause.exceptionParameter2, isNull);
     expect(clause.comma, isNull);
-    expect(clause.stackTraceParameter, isNull);
+    expect(clause.stackTraceParameter2, isNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1568,9 +1568,9 @@
     expect(clause.onKeyword, isNotNull);
     expect(clause.exceptionType, isNotNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.stackTraceParameter2, isNotNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNull);
     expect(statement.finallyBlock, isNull);
@@ -1588,9 +1588,9 @@
     expect(clause.onKeyword, isNotNull);
     expect(clause.exceptionType, isNotNull);
     expect(clause.catchKeyword, isNotNull);
-    expect(clause.exceptionParameter, isNotNull);
+    expect(clause.exceptionParameter2, isNotNull);
     expect(clause.comma, isNotNull);
-    expect(clause.stackTraceParameter, isNotNull);
+    expect(clause.stackTraceParameter2, isNotNull);
     expect(clause.body, isNotNull);
     expect(statement.finallyKeyword, isNotNull);
     expect(statement.finallyBlock, isNotNull);
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 711e8e8..183e638 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -416,8 +416,8 @@
       source: findNode.catchClause('(e2,'),
       childAccessors: [
         (node) => node.exceptionType!,
-        (node) => node.exceptionParameter!,
-        (node) => node.stackTraceParameter!,
+        (node) => node.exceptionParameter2!,
+        (node) => node.stackTraceParameter2!,
         (node) => node.body,
       ],
     );
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 94928cc..4a00cd4 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -7653,13 +7653,12 @@
       CatchClause catchClause = statement.catchClauses[0];
       expect(catchClause.exceptionType, isNull);
 
-      var exceptionNode = catchClause.exceptionParameter as SimpleIdentifier;
-      var exceptionElement =
-          exceptionNode.staticElement as LocalVariableElement;
+      var exceptionNode = catchClause.exceptionParameter2!;
+      var exceptionElement = exceptionNode.declaredElement!;
       expect(exceptionElement.type, typeProvider.objectType);
 
-      var stackNode = catchClause.stackTraceParameter as SimpleIdentifier;
-      var stackElement = stackNode.staticElement as LocalVariableElement;
+      var stackNode = catchClause.stackTraceParameter2!;
+      var stackElement = stackNode.declaredElement!;
       expect(stackElement.type, typeProvider.stackTraceType);
 
       List<Statement> catchStatements = catchClause.body.statements;
@@ -7683,13 +7682,12 @@
       _assertNamedTypeSimple(
           catchClause.exceptionType as NamedType, typeProvider.intType);
 
-      var exceptionNode = catchClause.exceptionParameter as SimpleIdentifier;
-      var exceptionElement =
-          exceptionNode.staticElement as LocalVariableElement;
+      var exceptionNode = catchClause.exceptionParameter2!;
+      var exceptionElement = exceptionNode.declaredElement!;
       expect(exceptionElement.type, typeProvider.intType);
 
-      var stackNode = catchClause.stackTraceParameter as SimpleIdentifier;
-      var stackElement = stackNode.staticElement as LocalVariableElement;
+      var stackNode = catchClause.stackTraceParameter2!;
+      var stackElement = stackNode.declaredElement!;
       expect(stackElement.type, typeProvider.stackTraceType);
 
       List<Statement> catchStatements = catchClause.body.statements;
@@ -7711,11 +7709,10 @@
       var statement = statements[2] as TryStatement;
       CatchClause catchClause = statement.catchClauses[0];
       expect(catchClause.exceptionType, isNull);
-      expect(catchClause.stackTraceParameter, isNull);
+      expect(catchClause.stackTraceParameter2, isNull);
 
-      var exceptionNode = catchClause.exceptionParameter as SimpleIdentifier;
-      var exceptionElement =
-          exceptionNode.staticElement as LocalVariableElement;
+      var exceptionNode = catchClause.exceptionParameter2!;
+      var exceptionElement = exceptionNode.declaredElement!;
       expect(exceptionElement.type, typeProvider.objectType);
     }
 
@@ -7724,11 +7721,10 @@
       var statement = statements[3] as TryStatement;
       CatchClause catchClause = statement.catchClauses[0];
       _assertNamedTypeSimple(catchClause.exceptionType!, typeProvider.intType);
-      expect(catchClause.stackTraceParameter, isNull);
+      expect(catchClause.stackTraceParameter2, isNull);
 
-      var exceptionNode = catchClause.exceptionParameter as SimpleIdentifier;
-      var exceptionElement =
-          exceptionNode.staticElement as LocalVariableElement;
+      var exceptionNode = catchClause.exceptionParameter2!;
+      var exceptionElement = exceptionNode.declaredElement!;
       expect(exceptionElement.type, typeProvider.intType);
     }
 
@@ -7738,8 +7734,8 @@
       CatchClause catchClause = statement.catchClauses[0];
       _assertNamedTypeSimple(
           catchClause.exceptionType as NamedType, typeProvider.intType);
-      expect(catchClause.exceptionParameter, isNull);
-      expect(catchClause.stackTraceParameter, isNull);
+      expect(catchClause.exceptionParameter2, isNull);
+      expect(catchClause.stackTraceParameter2, isNull);
     }
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 1abdd39..ec86bb6 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -1846,43 +1845,12 @@
   }
 
   test_newFile_library_exports_inSummary_library() async {
-    // Prepare a bundle where `package:foo/foo.dart` is a library.
-    final librarySummaryFiles = <File>[];
-    {
-      final fooRoot = getFolder('$workspaceRootPath/foo');
-      final foo = newFile('${fooRoot.path}/lib/foo.dart', 'class F {}');
-
-      final fooPackageConfigFile = getFile(
-        '${fooRoot.path}/.dart_tool/package_config.json',
-      );
-
-      writePackageConfig(
-        fooPackageConfigFile.path,
-        PackageConfigFileBuilder()..add(name: 'foo', rootPath: fooRoot.path),
-      );
-
-      final analysisDriver = driverFor(foo);
-      final bundleBytes = await analysisDriver.buildPackageBundle(
-        uriList: [
-          Uri.parse('package:foo/foo.dart'),
-        ],
-      );
-
-      final bundleFile = getFile('/home/summaries/packages.sum');
-      bundleFile.writeAsBytesSync(bundleBytes);
-
-      librarySummaryFiles.add(bundleFile);
-
-      // Delete, so it is not available as a file.
-      // We don't have a package config for it anyway, but just to be sure.
-      fooRoot.delete();
-    }
-
-    // Prepare for recreating the collection, with summaries.
-    sdkSummaryFile = await _writeSdkSummary();
-    this.librarySummaryFiles = librarySummaryFiles;
-
-    await disposeAnalysisContextCollection();
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': 'class F {}',
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 export 'dart:async';
@@ -1932,50 +1900,13 @@
   }
 
   test_newFile_library_exports_inSummary_part() async {
-    // Prepare a bundle where `package:foo/foo2.dart` is a part.
-    final librarySummaryFiles = <File>[];
-    {
-      final fooRoot = getFolder('$workspaceRootPath/foo');
-
-      final foo = newFile('${fooRoot.path}/lib/foo.dart', r'''
-part 'foo2.dart';
-''');
-
-      newFile('${fooRoot.path}/lib/foo2.dart', r'''
-part of 'foo.dart';
-''');
-
-      final fooPackageConfigFile = getFile(
-        '${fooRoot.path}/.dart_tool/package_config.json',
-      );
-
-      writePackageConfig(
-        fooPackageConfigFile.path,
-        PackageConfigFileBuilder()..add(name: 'foo', rootPath: fooRoot.path),
-      );
-
-      final analysisDriver = driverFor(foo);
-      final bundleBytes = await analysisDriver.buildPackageBundle(
-        uriList: [
-          Uri.parse('package:foo/foo.dart'),
-        ],
-      );
-
-      final bundleFile = getFile('/home/summaries/packages.sum');
-      bundleFile.writeAsBytesSync(bundleBytes);
-
-      librarySummaryFiles.add(bundleFile);
-
-      // Delete, so it is not available as a file.
-      // We don't have a package config for it anyway, but just to be sure.
-      fooRoot.delete();
-    }
-
-    // Prepare for recreating the collection, with summaries.
-    sdkSummaryFile = await _writeSdkSummary();
-    this.librarySummaryFiles = librarySummaryFiles;
-
-    await disposeAnalysisContextCollection();
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': "part 'foo2.dart';",
+        'lib/foo2.dart': "part of 'foo.dart';",
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 export 'package:foo/foo2.dart';
@@ -2343,44 +2274,12 @@
   }
 
   test_newFile_library_imports_library_inSummary_library() async {
-    // Prepare a bundle where `package:foo/foo.dart` is a library.
-    final librarySummaryFiles = <File>[];
-    {
-      final fooRoot = getFolder('$workspaceRootPath/foo');
-
-      final foo = newFile('${fooRoot.path}/lib/foo.dart', 'class F {}');
-
-      final fooPackageConfigFile = getFile(
-        '${fooRoot.path}/.dart_tool/package_config.json',
-      );
-
-      writePackageConfig(
-        fooPackageConfigFile.path,
-        PackageConfigFileBuilder()..add(name: 'foo', rootPath: fooRoot.path),
-      );
-
-      final analysisDriver = driverFor(foo);
-      final bundleBytes = await analysisDriver.buildPackageBundle(
-        uriList: [
-          Uri.parse('package:foo/foo.dart'),
-        ],
-      );
-
-      final bundleFile = getFile('/home/summaries/packages.sum');
-      bundleFile.writeAsBytesSync(bundleBytes);
-
-      librarySummaryFiles.add(bundleFile);
-
-      // Delete, so it is not available as a file.
-      // We don't have a package config for it anyway, but just to be sure.
-      fooRoot.delete();
-    }
-
-    // Prepare for recreating the collection, with summaries.
-    sdkSummaryFile = await _writeSdkSummary();
-    this.librarySummaryFiles = librarySummaryFiles;
-
-    await disposeAnalysisContextCollection();
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': 'class F {}',
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 import 'dart:async';
@@ -2429,50 +2328,13 @@
   }
 
   test_newFile_library_imports_library_inSummary_part() async {
-    // Prepare a bundle where `package:foo/foo2.dart` is a part.
-    final librarySummaryFiles = <File>[];
-    {
-      final fooRoot = getFolder('$workspaceRootPath/foo');
-
-      final foo = newFile('${fooRoot.path}/lib/foo.dart', r'''
-part 'foo2.dart';
-''');
-
-      newFile('${fooRoot.path}/lib/foo2.dart', r'''
-part of 'foo.dart';
-''');
-
-      final fooPackageConfigFile = getFile(
-        '${fooRoot.path}/.dart_tool/package_config.json',
-      );
-
-      writePackageConfig(
-        fooPackageConfigFile.path,
-        PackageConfigFileBuilder()..add(name: 'foo', rootPath: fooRoot.path),
-      );
-
-      final analysisDriver = driverFor(foo);
-      final bundleBytes = await analysisDriver.buildPackageBundle(
-        uriList: [
-          Uri.parse('package:foo/foo.dart'),
-        ],
-      );
-
-      final bundleFile = getFile('/home/summaries/packages.sum');
-      bundleFile.writeAsBytesSync(bundleBytes);
-
-      librarySummaryFiles.add(bundleFile);
-
-      // Delete, so it is not available as a file.
-      // We don't have a package config for it anyway, but just to be sure.
-      fooRoot.delete();
-    }
-
-    // Prepare for recreating the collection, with summaries.
-    sdkSummaryFile = await _writeSdkSummary();
-    this.librarySummaryFiles = librarySummaryFiles;
-
-    await disposeAnalysisContextCollection();
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': "part 'foo2.dart';",
+        'lib/foo2.dart': "part of 'foo.dart';",
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
 
     final a = newFile('$testPackageLibPath/a.dart', r'''
 import 'package:foo/foo2.dart';
@@ -5776,16 +5638,6 @@
 elementFactory
 ''');
   }
-
-  Future<File> _writeSdkSummary() async {
-    final file = getFile('/home/summaries/sdk.sum');
-    final bytes = await buildSdkSummary2(
-      resourceProvider: resourceProvider,
-      sdkPath: sdkRoot.path,
-    );
-    file.writeAsBytesSync(bytes);
-    return file;
-  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
index 9fd743c..ccfc496 100644
--- a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -223,21 +223,47 @@
   }
 
   void test_visitCatchClause_catch_noStack() {
-    _assertSource("catch (e) {}", AstTestFactory.catchClause("e"));
+    final code = 'catch (e) {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  try {}
+  $code
+}
+''');
+    _assertSource(code, findNode.catchClause(code));
   }
 
   void test_visitCatchClause_catch_stack() {
-    _assertSource("catch (e, s) {}", AstTestFactory.catchClause2("e", "s"));
+    final code = 'catch (e, s) {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  try {}
+  $code
+}
+''');
+    _assertSource(code, findNode.catchClause(code));
   }
 
   void test_visitCatchClause_on() {
-    _assertSource(
-        "on E {}", AstTestFactory.catchClause3(AstTestFactory.namedType4("E")));
+    final code = 'on E {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  try {}
+  $code
+}
+''');
+    _assertSource(code, findNode.catchClause(code));
   }
 
   void test_visitCatchClause_on_catch() {
-    _assertSource("on E catch (e) {}",
-        AstTestFactory.catchClause4(AstTestFactory.namedType4("E"), "e"));
+    final code = 'on E catch (e) {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  try {}
+  $code
+}
+''');
+    _assertSource(code, findNode.catchClause(code));
   }
 
   void test_visitClassDeclaration_abstract() {
@@ -3333,28 +3359,33 @@
   }
 
   void test_visitTryStatement_catch() {
-    _assertSource(
-        "try {} on E {}",
-        AstTestFactory.tryStatement2(AstTestFactory.block(),
-            [AstTestFactory.catchClause3(AstTestFactory.namedType4("E"))]));
+    final code = 'try {} on E {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  $code
+}
+''');
+    _assertSource(code, findNode.tryStatement(code));
   }
 
   void test_visitTryStatement_catches() {
-    _assertSource(
-        "try {} on E {} on F {}",
-        AstTestFactory.tryStatement2(AstTestFactory.block(), [
-          AstTestFactory.catchClause3(AstTestFactory.namedType4("E")),
-          AstTestFactory.catchClause3(AstTestFactory.namedType4("F"))
-        ]));
+    final code = 'try {} on E {} on F {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  $code
+}
+''');
+    _assertSource(code, findNode.tryStatement(code));
   }
 
   void test_visitTryStatement_catchFinally() {
-    _assertSource(
-        "try {} on E {} finally {}",
-        AstTestFactory.tryStatement3(
-            AstTestFactory.block(),
-            [AstTestFactory.catchClause3(AstTestFactory.namedType4("E"))],
-            AstTestFactory.block()));
+    final code = 'try {} on E {} finally {}';
+    final findNode = _parseStringToFindNode('''
+void f() {
+  $code
+}
+''');
+    _assertSource(code, findNode.tryStatement(code));
   }
 
   void test_visitTryStatement_finally() {
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index da175f8..28777a2 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -343,6 +344,45 @@
 
   String get workspaceRootPath => '/home';
 
+  /// Build summary bundle for a single URI `package:foo/foo.dart`.
+  Future<File> buildPackageFooSummary({
+    required Map<String, String> files,
+  }) async {
+    final rootFolder = getFolder('$workspaceRootPath/foo');
+
+    final packageConfigFile = getFile(
+      '${rootFolder.path}/.dart_tool/package_config.json',
+    );
+
+    writePackageConfig(
+      packageConfigFile.path,
+      PackageConfigFileBuilder()..add(name: 'foo', rootPath: rootFolder.path),
+    );
+
+    for (final entry in files.entries) {
+      newFile('${rootFolder.path}/${entry.key}', entry.value);
+    }
+
+    final targetFile = getFile(rootFolder.path);
+    final analysisDriver = driverFor(targetFile);
+    final bundleBytes = await analysisDriver.buildPackageBundle(
+      uriList: [
+        Uri.parse('package:foo/foo.dart'),
+      ],
+    );
+
+    final bundleFile = getFile('/home/summaries/packages.sum');
+    bundleFile.writeAsBytesSync(bundleBytes);
+
+    // Delete, so it is not available as a file.
+    // We don't have a package config for it anyway, but just to be sure.
+    rootFolder.delete();
+
+    await disposeAnalysisContextCollection();
+
+    return bundleFile;
+  }
+
   @override
   void setUp() {
     super.setUp();
@@ -365,6 +405,16 @@
     );
   }
 
+  Future<File> writeSdkSummary() async {
+    final file = getFile('/home/summaries/sdk.sum');
+    final bytes = await buildSdkSummary2(
+      resourceProvider: resourceProvider,
+      sdkPath: sdkRoot.path,
+    );
+    file.writeAsBytesSync(bytes);
+    return file;
+  }
+
   void writeTestPackageAnalysisOptionsFile(AnalysisOptionsFileConfig config) {
     newAnalysisOptionsYamlFile(
       testPackageRootPath,
diff --git a/pkg/analyzer/test/src/dart/resolution/library_export_test.dart b/pkg/analyzer/test/src/dart/resolution/library_export_test.dart
index b4f6a2f..149ce7b 100644
--- a/pkg/analyzer/test/src/dart/resolution/library_export_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/library_export_test.dart
@@ -305,6 +305,8 @@
       rightParenthesis: )
       uri: SimpleStringLiteral
         literal: 'a_html.dart'
+      resolvedUri: DirectiveUriWithSource
+        source: package:test/a_html.dart
     Configuration
       ifKeyword: if
       leftParenthesis: (
@@ -325,6 +327,8 @@
       rightParenthesis: )
       uri: SimpleStringLiteral
         literal: 'a_io.dart'
+      resolvedUri: DirectiveUriWithSource
+        source: package:test/a_io.dart
   semicolon: ;
   element: LibraryExportElement
     uri: DirectiveUriWithLibrary
@@ -375,6 +379,8 @@
       rightParenthesis: )
       uri: SimpleStringLiteral
         literal: 'a_html.dart'
+      resolvedUri: DirectiveUriWithSource
+        source: package:test/a_html.dart
     Configuration
       ifKeyword: if
       leftParenthesis: (
@@ -395,6 +401,8 @@
       rightParenthesis: )
       uri: SimpleStringLiteral
         literal: 'a_io.dart'
+      resolvedUri: DirectiveUriWithSource
+        source: package:test/a_io.dart
   semicolon: ;
   element: LibraryExportElement
     uri: DirectiveUriWithLibrary
@@ -445,6 +453,8 @@
       rightParenthesis: )
       uri: SimpleStringLiteral
         literal: 'a_html.dart'
+      resolvedUri: DirectiveUriWithSource
+        source: package:test/a_html.dart
     Configuration
       ifKeyword: if
       leftParenthesis: (
@@ -465,6 +475,8 @@
       rightParenthesis: )
       uri: SimpleStringLiteral
         literal: 'a_io.dart'
+      resolvedUri: DirectiveUriWithSource
+        source: package:test/a_io.dart
   semicolon: ;
   element: LibraryExportElement
     uri: DirectiveUriWithLibrary
@@ -512,6 +524,31 @@
 ''');
   }
 
+  test_inLibrary_library_inSummary() async {
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': 'class F {}',
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
+
+    await assertNoErrorsInCode(r'''
+export 'package:foo/foo.dart';
+''');
+
+    final node = findNode.export('package:foo');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'package:foo/foo.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:foo/foo.dart
+''');
+  }
+
   /// Test that both getter and setter are in the export namespace.
   test_inLibrary_namespace_getter_setter() async {
     newFile('$testPackageLibPath/a.dart', r'''
@@ -667,4 +704,32 @@
       source: package:test/a.dart
 ''');
   }
+
+  test_inLibrary_notLibrary_partOfUri_inSummary() async {
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': "part 'foo2.dart';",
+        'lib/foo2.dart': "part of 'foo.dart';",
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
+
+    await assertErrorsInCode(r'''
+export 'package:foo/foo2.dart';
+''', [
+      error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 7, 23),
+    ]);
+
+    final node = findNode.export('package:foo');
+    assertResolvedNodeText(node, r'''
+ExportDirective
+  exportKeyword: export
+  uri: SimpleStringLiteral
+    literal: 'package:foo/foo2.dart'
+  semicolon: ;
+  element: LibraryExportElement
+    uri: DirectiveUriWithSource
+      source: package:foo/foo2.dart
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/library_import_test.dart b/pkg/analyzer/test/src/dart/resolution/library_import_test.dart
index 1cc0030..0402d00 100644
--- a/pkg/analyzer/test/src/dart/resolution/library_import_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/library_import_test.dart
@@ -310,6 +310,8 @@
           rightParenthesis: )
           uri: SimpleStringLiteral
             literal: 'a_html.dart'
+          resolvedUri: DirectiveUriWithSource
+            source: package:test/a_html.dart
         Configuration
           ifKeyword: if
           leftParenthesis: (
@@ -330,6 +332,8 @@
           rightParenthesis: )
           uri: SimpleStringLiteral
             literal: 'a_io.dart'
+          resolvedUri: DirectiveUriWithSource
+            source: package:test/a_io.dart
       semicolon: ;
       element: LibraryImportElement
         uri: DirectiveUriWithLibrary
@@ -411,6 +415,8 @@
           rightParenthesis: )
           uri: SimpleStringLiteral
             literal: 'a_html.dart'
+          resolvedUri: DirectiveUriWithSource
+            source: package:test/a_html.dart
         Configuration
           ifKeyword: if
           leftParenthesis: (
@@ -431,6 +437,8 @@
           rightParenthesis: )
           uri: SimpleStringLiteral
             literal: 'a_io.dart'
+          resolvedUri: DirectiveUriWithSource
+            source: package:test/a_io.dart
       semicolon: ;
       element: LibraryImportElement
         uri: DirectiveUriWithLibrary
@@ -465,6 +473,128 @@
 ''');
   }
 
+  test_inLibrary_configurations_noRelativeUri() async {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    await assertNoErrorsInCode(r'''
+// ignore:unused_import
+import 'a.dart'
+  if (x) ':net';
+''');
+
+    final node = findNode.configuration('if (');
+    assertResolvedNodeText(node, r'''
+Configuration
+  ifKeyword: if
+  leftParenthesis: (
+  name: DottedName
+    components
+      SimpleIdentifier
+        token: x
+        staticElement: <null>
+        staticType: null
+  rightParenthesis: )
+  uri: SimpleStringLiteral
+    literal: ':net'
+  resolvedUri: DirectiveUriWithRelativeUriString
+    relativeUriString: :net
+''');
+  }
+
+  test_inLibrary_configurations_noRelativeUriStr() async {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    await assertNoErrorsInCode(r'''
+// ignore:unused_import
+import 'a.dart'
+  if (x) '${'foo'}.dart';
+''');
+
+    final node = findNode.configuration('if (');
+    assertResolvedNodeText(node, r'''
+Configuration
+  ifKeyword: if
+  leftParenthesis: (
+  name: DottedName
+    components
+      SimpleIdentifier
+        token: x
+        staticElement: <null>
+        staticType: null
+  rightParenthesis: )
+  uri: StringInterpolation
+    elements
+      InterpolationString
+        contents: '
+      InterpolationExpression
+        leftBracket: ${
+        expression: SimpleStringLiteral
+          literal: 'foo'
+        rightBracket: }
+      InterpolationString
+        contents: .dart'
+    staticType: null
+    stringValue: null
+  resolvedUri: DirectiveUri
+''');
+  }
+
+  test_inLibrary_configurations_noSource() async {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    await assertNoErrorsInCode(r'''
+// ignore:unused_import
+import 'a.dart'
+  if (x) 'foo:bar';
+''');
+
+    final node = findNode.configuration('if (');
+    assertResolvedNodeText(node, r'''
+Configuration
+  ifKeyword: if
+  leftParenthesis: (
+  name: DottedName
+    components
+      SimpleIdentifier
+        token: x
+        staticElement: <null>
+        staticType: null
+  rightParenthesis: )
+  uri: SimpleStringLiteral
+    literal: 'foo:bar'
+  resolvedUri: DirectiveUriWithRelativeUri
+    relativeUri: foo:bar
+''');
+  }
+
+  test_inLibrary_configurations_onlySource_notLibrary() async {
+    newFile('$testPackageLibPath/a.dart', '');
+
+    await assertNoErrorsInCode(r'''
+// ignore:unused_import
+import 'a.dart'
+  if (x) 'a.dart';
+''');
+
+    final node = findNode.configuration('if (');
+    assertResolvedNodeText(node, r'''
+Configuration
+  ifKeyword: if
+  leftParenthesis: (
+  name: DottedName
+    components
+      SimpleIdentifier
+        token: x
+        staticElement: <null>
+        staticType: null
+  rightParenthesis: )
+  uri: SimpleStringLiteral
+    literal: 'a.dart'
+  resolvedUri: DirectiveUriWithSource
+    source: package:test/a.dart
+''');
+  }
+
   test_inLibrary_configurations_second() async {
     newFile('$testPackageLibPath/a.dart', 'class A {}');
     newFile('$testPackageLibPath/a_html.dart', 'class A {}');
@@ -512,6 +642,8 @@
           rightParenthesis: )
           uri: SimpleStringLiteral
             literal: 'a_html.dart'
+          resolvedUri: DirectiveUriWithSource
+            source: package:test/a_html.dart
         Configuration
           ifKeyword: if
           leftParenthesis: (
@@ -532,6 +664,8 @@
           rightParenthesis: )
           uri: SimpleStringLiteral
             literal: 'a_io.dart'
+          resolvedUri: DirectiveUriWithSource
+            source: package:test/a_io.dart
       semicolon: ;
       element: LibraryImportElement
         uri: DirectiveUriWithLibrary
@@ -607,6 +741,32 @@
 ''');
   }
 
+  test_inLibrary_library_inSummary() async {
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': 'class F {}',
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
+
+    await assertNoErrorsInCode(r'''
+// ignore: unused_import
+import 'package:foo/foo.dart';
+''');
+
+    final node = findNode.import('package:foo');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'package:foo/foo.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithLibrary
+      uri: package:foo/foo.dart
+''');
+  }
+
   test_inLibrary_noRelativeUri() async {
     await assertErrorsInCode(r'''
 import ':net';
@@ -748,4 +908,32 @@
       source: package:test/a.dart
 ''');
   }
+
+  test_inLibrary_notLibrary_partOfUri_inSummary() async {
+    librarySummaryFiles = [
+      await buildPackageFooSummary(files: {
+        'lib/foo.dart': "part 'foo2.dart';",
+        'lib/foo2.dart': "part of 'foo.dart';",
+      }),
+    ];
+    sdkSummaryFile = await writeSdkSummary();
+
+    await assertErrorsInCode(r'''
+import 'package:foo/foo2.dart';
+''', [
+      error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 7, 23),
+    ]);
+
+    final node = findNode.import('package:foo');
+    assertResolvedNodeText(node, r'''
+ImportDirective
+  importKeyword: import
+  uri: SimpleStringLiteral
+    literal: 'package:foo/foo2.dart'
+  semicolon: ;
+  element: LibraryImportElement
+    uri: DirectiveUriWithSource
+      source: package:foo/foo2.dart
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/try_statement_test.dart b/pkg/analyzer/test/src/dart/resolution/try_statement_test.dart
index 75c7e3c..b8f160a 100644
--- a/pkg/analyzer/test/src/dart/resolution/try_statement_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/try_statement_test.dart
@@ -36,8 +36,8 @@
     assertType(st.type, 'StackTrace');
 
     var node = findNode.catchClause('catch');
-    expect(node.exceptionParameter!.staticElement, e);
-    expect(node.stackTraceParameter!.staticElement, st);
+    expect(node.exceptionParameter2!.declaredElement, e);
+    expect(node.stackTraceParameter2!.declaredElement, st);
   }
 
   test_catch_withType() async {
@@ -58,7 +58,7 @@
     assertType(st.type, 'StackTrace');
 
     var node = findNode.catchClause('catch');
-    expect(node.exceptionParameter!.staticElement, e);
-    expect(node.stackTraceParameter!.staticElement, st);
+    expect(node.exceptionParameter2!.declaredElement, e);
+    expect(node.stackTraceParameter2!.declaredElement, st);
   }
 }
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 521477e..f838869 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -269,6 +269,11 @@
     _withIndent(() {
       _writeNamedChildEntities(node);
     });
+    _withIndent(() {
+      _sink.write(_indent);
+      _sink.write('resolvedUri: ');
+      _writeDirectiveUri(node.resolvedUri);
+    });
   }
 
   @override
@@ -1369,8 +1374,10 @@
     });
   }
 
-  void _writeDirectiveUri(DirectiveUri uri) {
-    if (uri is DirectiveUriWithAugmentation) {
+  void _writeDirectiveUri(DirectiveUri? uri) {
+    if (uri == null) {
+      _writeln('<null>');
+    } else if (uri is DirectiveUriWithAugmentation) {
       _writeln('DirectiveUriWithAugmentation');
       _withIndent(() {
         final uriStr = _stringOfSource(uri.augmentation.source);
diff --git a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
index 2dfb787..996d339 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
 
 /// A visitor that visits an [AstNode] and its parent recursively along with any
 /// declarations in those nodes. Consumers typically call [visit] which catches
@@ -39,7 +41,7 @@
 
   void declaredMixin(MixinDeclaration declaration) {}
 
-  void declaredParam(SimpleIdentifier name, TypeAnnotation? type) {}
+  void declaredParam(Token name, Element? element, TypeAnnotation? type) {}
 
   void declaredTopLevelVar(
       VariableDeclarationList varList, VariableDeclaration varDecl) {}
@@ -72,14 +74,22 @@
 
   @override
   void visitCatchClause(CatchClause node) {
-    var exceptionParameter = node.exceptionParameter;
+    var exceptionParameter = node.exceptionParameter2;
     if (exceptionParameter != null) {
-      declaredParam(exceptionParameter, node.exceptionType);
+      declaredParam(
+        exceptionParameter.name,
+        exceptionParameter.declaredElement,
+        node.exceptionType,
+      );
     }
 
-    var stackTraceParameter = node.stackTraceParameter;
+    var stackTraceParameter = node.stackTraceParameter2;
     if (stackTraceParameter != null) {
-      declaredParam(stackTraceParameter, null);
+      declaredParam(
+        stackTraceParameter.name,
+        stackTraceParameter.declaredElement,
+        null,
+      );
     }
 
     visitNode(node);
@@ -292,8 +302,7 @@
         } else if (normalParam is SimpleFormalParameter) {
           type = normalParam.type;
         }
-        var name = param.identifier;
-        declaredParam(name!, type);
+        declaredParam(param.identifier!.token, param.declaredElement, type);
       }
     }
   }
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
index d88f47a..d356221 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -226,8 +227,8 @@
   }
 
   @override
-  void declaredParam(SimpleIdentifier name, TypeAnnotation? type) {
-    if (name.name == targetName) {
+  void declaredParam(Token name, Element? element, TypeAnnotation? type) {
+    if (name.lexeme == targetName) {
       // Type provided by the element in computeFull above
       finished();
     }
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index d0b8b44..be4d391 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -247,8 +247,9 @@
 
   @override
   void visitConfiguration(Configuration node) {
-    var source = node.uriSource;
-    if (source != null) {
+    final resolvedUri = node.resolvedUri;
+    if (resolvedUri is DirectiveUriWithSource) {
+      final source = resolvedUri.source;
       if (resourceProvider.getResource(source.fullName).exists) {
         // TODO(brianwilkerson) If the analyzer ever resolves the URI to a
         //  library, use that library element to create the region.
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 00f0fb4..18b1d8e 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -138,13 +138,6 @@
   bool get errorOnUnexactWebIntLiterals => true;
 
   @override
-  void performOutlineTransformations(ir.Component component,
-      CoreTypes coreTypes, ReferenceFromIndex? referenceFromIndex) {
-    component.accept(StaticInteropStubCreator(
-        StaticInteropClassEraser(coreTypes, referenceFromIndex)));
-  }
-
-  @override
   void performModularTransformationsOnLibraries(
       ir.Component component,
       CoreTypes coreTypes,
@@ -168,12 +161,14 @@
       // TODO (rileyporter): Merge js_util optimizations with other lowerings
       // in the single pass in `transformations/lowering.dart`.
       jsUtilOptimizer.visitLibrary(library);
-      staticInteropClassEraser.visitLibrary(library);
     }
     lowering.transformLibraries(libraries, coreTypes, hierarchy, options);
     logger?.call("Lowering transformations performed");
     if (canPerformGlobalTransforms) {
       transformMixins.transformLibraries(libraries);
+      for (var library in libraries) {
+        staticInteropClassEraser.visitLibrary(library);
+      }
       logger?.call("Mixin transformations performed");
     }
   }
diff --git a/pkg/compiler/lib/src/phase/load_kernel.dart b/pkg/compiler/lib/src/phase/load_kernel.dart
index 6145d84..676afba 100644
--- a/pkg/compiler/lib/src/phase/load_kernel.dart
+++ b/pkg/compiler/lib/src/phase/load_kernel.dart
@@ -7,12 +7,15 @@
 import 'package:collection/collection.dart';
 import 'package:front_end/src/fasta/kernel/utils.dart';
 import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
 import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
 import 'package:kernel/target/targets.dart' hide DiagnosticReporter;
 
+import 'package:_js_interop_checks/src/transformations/static_interop_class_eraser.dart';
+
 import '../../compiler_api.dart' as api;
 import '../commandline_options.dart';
 import '../common.dart';
@@ -130,6 +133,12 @@
 
 void _doGlobalTransforms(Component component) {
   transformMixins.transformLibraries(component.libraries);
+  // referenceFromIndex is only necessary in the case where a module containing
+  // a stub definition is invalidated, and then reloaded, because we need to
+  // keep existing references to that stub valid. Here, we have the whole
+  // program, and therefore do not need it.
+  StaticInteropClassEraser(ir.CoreTypes(component), null)
+      .visitComponent(component);
 }
 
 Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options,
diff --git a/pkg/dart2js_info/bin/src/to_devtools_format.dart b/pkg/dart2js_info/bin/src/to_devtools_format.dart
index adb4f50..9d8e756 100644
--- a/pkg/dart2js_info/bin/src/to_devtools_format.dart
+++ b/pkg/dart2js_info/bin/src/to_devtools_format.dart
@@ -6,7 +6,7 @@
 import 'package:dart2js_info/info.dart';
 import 'package:dart2js_info/src/io.dart';
 import 'package:vm_snapshot_analysis/treemap.dart';
-import 'package:dart2js_info/src/util.dart' show libraryGroupName;
+import 'package:dart2js_info/src/util.dart';
 import 'package:vm_snapshot_analysis/program_info.dart' as vm;
 
 /// Command that converts a `--dump-info` JSON output into a format ingested by Devtools.
@@ -72,6 +72,10 @@
   /// objects of [vm.NodeType.packageNode].
   final Map<String, vm.ProgramInfoNode> packageInfoNodes = {};
 
+  /// Mapping between an <unnamed> [LibraryInfo] object and the name of the
+  /// corresponding [vm.ProgramInfoNode] object.
+  final Map<Info, String> unnamedLibraries = {};
+
   ProgramInfoBuilder(this.info);
 
   @override
@@ -111,7 +115,8 @@
     info.classTypes.forEach(visitClassType);
     info.typedefs.forEach(makeTypedef);
     info.typedefs.forEach(visitTypedef);
-    return infoNodesByName[info.name]!;
+    return infoNodesByName[info.name] ??
+        infoNodesByName[unnamedLibraries[info]]!;
   }
 
   @override
@@ -151,7 +156,7 @@
 
   @override
   vm.ProgramInfoNode visitConstant(ConstantInfo info) {
-    return infoNodesByName[info.name]!;
+    return infoNodesByName[info.code.first.text!]!;
   }
 
   @override
@@ -182,6 +187,8 @@
       packageInfoNodes[packageName] = newPackage;
       program.root.children[packageName] = newPackage;
       outputInfo.add(newPackage);
+      var packageNode = infoNodesByName[newPackage.name];
+      assert(packageNode == null, "encountered package with duplicated name");
       infoNodesByName[newPackage.name] = newPackage;
     } else {
       packageInfoNode.size = (packageInfoNode.size ?? 0) + libraryInfo.size;
@@ -190,13 +197,18 @@
 
   void makeLibrary(LibraryInfo libraryInfo) {
     String packageName = libraryGroupName(libraryInfo) ?? libraryInfo.name;
-    vm.ProgramInfoNode? parentNode = infoNodesByName[packageName];
+    vm.ProgramInfoNode parentNode = infoNodesByName[packageName]!;
+    String libraryName = libraryInfo.name;
+    if (libraryName == '<unnamed>') {
+      libraryName = longName(libraryInfo, useLibraryUri: true, forId: true);
+      unnamedLibraries[libraryInfo] = libraryName;
+    }
     vm.ProgramInfoNode newLibrary = program.makeNode(
-        name: libraryInfo.name,
-        parent: parentNode!,
-        type: vm.NodeType.libraryNode);
+        name: libraryName, parent: parentNode, type: vm.NodeType.libraryNode);
     newLibrary.size = libraryInfo.size;
     parentNode.children[newLibrary.name] = newLibrary;
+    vm.ProgramInfoNode? libraryNode = infoNodesByName[newLibrary.name];
+    assert(libraryNode == null, "encountered library with duplicated name");
     infoNodesByName[newLibrary.name] = newLibrary;
     outputInfo.add(newLibrary);
   }
@@ -204,13 +216,21 @@
   void makeFunction(FunctionInfo functionInfo) {
     Info? parent = functionInfo.parent;
     if (parent != null) {
-      vm.ProgramInfoNode? parentNode = infoNodesByName[parent.name];
+      vm.ProgramInfoNode parentNode;
+      if (parent.name == "<unnamed>" &&
+          parent.kind == kindFromString('library')) {
+        parentNode = infoNodesByName[unnamedLibraries[parent]]!;
+      } else {
+        parentNode = infoNodesByName[parent.name]!;
+      }
       vm.ProgramInfoNode newFunction = program.makeNode(
           name: functionInfo.name,
-          parent: parentNode!,
+          parent: parentNode,
           type: vm.NodeType.functionNode);
       newFunction.size = functionInfo.size;
       parentNode.children[newFunction.name] = newFunction;
+      vm.ProgramInfoNode? functionNode = infoNodesByName[newFunction.name];
+      assert(functionNode == null, "encountered function with duplicated name");
       infoNodesByName[newFunction.name] = newFunction;
       outputInfo.add(newFunction);
     }
@@ -219,13 +239,21 @@
   void makeClass(ClassInfo classInfo) {
     Info? parent = classInfo.parent;
     if (parent != null) {
-      vm.ProgramInfoNode? parentNode = infoNodesByName[parent.name];
+      vm.ProgramInfoNode parentNode;
+      if (parent.name == "<unnamed>" &&
+          parent.kind == kindFromString('library')) {
+        parentNode = infoNodesByName[unnamedLibraries[parent]]!;
+      } else {
+        parentNode = infoNodesByName[parent.name]!;
+      }
       vm.ProgramInfoNode newClass = program.makeNode(
           name: classInfo.name,
-          parent: parentNode!,
+          parent: parentNode,
           type: vm.NodeType.classNode);
       newClass.size = classInfo.size;
       parentNode.children[newClass.name] = newClass;
+      vm.ProgramInfoNode? classNode = infoNodesByName[newClass.name];
+      assert(classNode == null, "encountered class with duplicated name");
       infoNodesByName[newClass.name] = newClass;
       outputInfo.add(newClass);
     }
@@ -239,21 +267,32 @@
   void makeField(FieldInfo fieldInfo) {
     Info? parent = fieldInfo.parent;
     if (parent != null) {
-      vm.ProgramInfoNode? parentNode = infoNodesByName[parent.name];
+      vm.ProgramInfoNode parentNode;
+      if (parent.name == "<unnamed>" &&
+          parent.kind == kindFromString('library')) {
+        parentNode = infoNodesByName[unnamedLibraries[parent]]!;
+      } else {
+        parentNode = infoNodesByName[parent.name]!;
+      }
       vm.ProgramInfoNode newField = program.makeNode(
-          name: fieldInfo.name, parent: parentNode!, type: vm.NodeType.other);
+          name: fieldInfo.name, parent: parentNode, type: vm.NodeType.other);
       newField.size = fieldInfo.size;
       parentNode.children[newField.name] = newField;
+      vm.ProgramInfoNode? fieldNode = infoNodesByName[newField.name];
+      assert(fieldNode == null, "encountered field with duplicated name");
       infoNodesByName[newField.name] = newField;
       outputInfo.add(newField);
     }
   }
 
   void makeConstant(ConstantInfo constantInfo) {
+    String constantName = constantInfo.code.first.text!;
     vm.ProgramInfoNode newConstant = program.makeNode(
-        name: constantInfo.name, parent: program.root, type: vm.NodeType.other);
+        name: constantName, parent: program.root, type: vm.NodeType.other);
     newConstant.size = constantInfo.size;
     program.root.children[newConstant.name] = newConstant;
+    vm.ProgramInfoNode? constantNode = infoNodesByName[newConstant.name];
+    assert(constantNode == null, "encountered constant with duplicated name");
     infoNodesByName[newConstant.name] = newConstant;
     outputInfo.add(newConstant);
   }
@@ -269,12 +308,21 @@
   void makeClassType(ClassTypeInfo classTypeInfo) {
     Info? parent = classTypeInfo.parent;
     if (parent != null) {
-      vm.ProgramInfoNode? parentNode = infoNodesByName[parent.name];
+      vm.ProgramInfoNode parentNode;
+      if (parent.name == "<unnamed>" &&
+          parent.kind == kindFromString('library')) {
+        parentNode = infoNodesByName[unnamedLibraries[parent]]!;
+      } else {
+        parentNode = infoNodesByName[parent.name]!;
+      }
       vm.ProgramInfoNode newClassType = program.makeNode(
           name: classTypeInfo.name,
-          parent: parentNode!,
+          parent: parentNode,
           type: vm.NodeType.other);
       newClassType.size = classTypeInfo.size;
+      vm.ProgramInfoNode? classTypeNode = infoNodesByName[newClassType.name];
+      assert(
+          classTypeNode == null, "encountered classType with duplicated name");
       infoNodesByName[newClassType.name] = newClassType;
       outputInfo.add(newClassType);
     }
@@ -283,14 +331,22 @@
   void makeClosure(ClosureInfo closureInfo) {
     Info? parent = closureInfo.parent;
     if (parent != null) {
-      vm.ProgramInfoNode? parentNode = infoNodesByName[parent.name];
+      vm.ProgramInfoNode parentNode;
+      if (parent.name == "<unnamed>" &&
+          parent.kind == kindFromString('library')) {
+        parentNode = infoNodesByName[unnamedLibraries[parent]]!;
+      } else {
+        parentNode = infoNodesByName[parent.name]!;
+      }
       vm.ProgramInfoNode newClosure = program.makeNode(
           name: closureInfo.name,
-          parent: parentNode!,
+          parent: parentNode,
           // ProgramInfo trees consider closures and functions to both be of the functionNode type.
           type: vm.NodeType.functionNode);
       newClosure.size = closureInfo.size;
       parentNode.children[newClosure.name] = newClosure;
+      vm.ProgramInfoNode? closureNode = infoNodesByName[newClosure.name];
+      assert(closureNode == null, "encountered closure with duplicated name");
       infoNodesByName[newClosure.name] = newClosure;
       outputInfo.add(newClosure);
     }
diff --git a/pkg/dart2wasm/lib/target.dart b/pkg/dart2wasm/lib/target.dart
index 604072e..871f07a 100644
--- a/pkg/dart2wasm/lib/target.dart
+++ b/pkg/dart2wasm/lib/target.dart
@@ -86,20 +86,16 @@
       ..parent = host;
   }
 
-  StaticInteropClassEraser _staticInteropClassEraser(
-          CoreTypes coreTypes, ReferenceFromIndex? referenceFromIndex) =>
-      StaticInteropClassEraser(coreTypes, referenceFromIndex,
-          libraryForJavaScriptObject: 'dart:_js_helper',
-          classNameOfJavaScriptObject: 'JSValue');
-
   void _performJSInteropTransformations(
       CoreTypes coreTypes,
       ClassHierarchy hierarchy,
       List<Library> interopDependentLibraries,
       ReferenceFromIndex? referenceFromIndex) {
     final jsUtilOptimizer = JsUtilWasmOptimizer(coreTypes, hierarchy);
-    final staticInteropClassEraser =
-        _staticInteropClassEraser(coreTypes, referenceFromIndex);
+    final staticInteropClassEraser = StaticInteropClassEraser(
+        coreTypes, referenceFromIndex,
+        libraryForJavaScriptObject: 'dart:_js_helper',
+        classNameOfJavaScriptObject: 'JSValue');
     for (Library library in interopDependentLibraries) {
       jsUtilOptimizer.visitLibrary(library);
       staticInteropClassEraser.visitLibrary(library);
@@ -118,13 +114,6 @@
   }
 
   @override
-  void performOutlineTransformations(Component component, CoreTypes coreTypes,
-      ReferenceFromIndex? referenceFromIndex) {
-    component.accept(StaticInteropStubCreator(
-        _staticInteropClassEraser(coreTypes, referenceFromIndex)));
-  }
-
-  @override
   void performModularTransformationsOnLibraries(
       Component component,
       CoreTypes coreTypes,
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 795d503..3d5e682 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -153,13 +153,6 @@
   bool get enableNoSuchMethodForwarders => true;
 
   @override
-  void performOutlineTransformations(Component component, CoreTypes coreTypes,
-      ReferenceFromIndex? referenceFromIndex) {
-    component.accept(StaticInteropStubCreator(
-        StaticInteropClassEraser(coreTypes, referenceFromIndex)));
-  }
-
-  @override
   void performModularTransformationsOnLibraries(
       Component component,
       CoreTypes coreTypes,
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 8f0f4f3..880d764 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -12,8 +12,6 @@
 import 'package:kernel/kernel.dart'
     show Component, Library, Procedure, DartType, TypeParameter;
 
-import 'package:kernel/reference_from_index.dart';
-
 import '../base/processed_options.dart' show ProcessedOptions;
 
 import '../fasta/compiler_context.dart' show CompilerContext;
@@ -154,11 +152,7 @@
   final ClassHierarchy? classHierarchy;
   final CoreTypes? coreTypes;
   final Set<Library>? neededDillLibraries;
-  final ReferenceFromIndex? referenceFromIndex;
 
   IncrementalCompilerResult(this.component,
-      {this.classHierarchy,
-      this.coreTypes,
-      this.neededDillLibraries,
-      this.referenceFromIndex});
+      {this.classHierarchy, this.coreTypes, this.neededDillLibraries});
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index b8c8a58..d23a14f 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -268,7 +268,9 @@
             bodyBuilder.transformCollections,
             library.library);
         initializerWasInferred = true;
-        bodyBuilder.performBacklogComputations(delayedActionPerformers);
+        bodyBuilder.performBacklogComputations(
+            delayedActionPerformers: delayedActionPerformers,
+            allowFurtherDelays: false);
       } else if (kind != FormalParameterKind.requiredPositional) {
         // As done by BodyBuilder.endFormalParameter.
         variable!.initializer = new NullLiteral()..parent = variable;
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index 80ed54d..2e76574 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -30,7 +30,8 @@
       SourceLibraryBuilder library,
       DeclarationBuilder? classOrExtensionBuilder,
       MemberBuilder? member,
-      Uri fileUri, Scope scope) {
+      Uri fileUri,
+      Scope scope) {
     if (metadata == null) return;
     BodyBuilder bodyBuilder = library.loader
         .createBodyBuilderForOutlineExpression(library, classOrExtensionBuilder,
@@ -41,6 +42,6 @@
           bodyBuilder.parseAnnotation(annotationBuilder.beginToken));
     }
     bodyBuilder.inferAnnotations(parent, parent.annotations);
-    bodyBuilder.performBacklogComputations();
+    bodyBuilder.performBacklogComputations(allowFurtherDelays: false);
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index d6687f9..489a220 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -529,8 +529,7 @@
       return new IncrementalCompilerResult(result,
           classHierarchy: currentKernelTarget.loader.hierarchy,
           coreTypes: currentKernelTarget.loader.coreTypes,
-          neededDillLibraries: neededDillLibraries,
-          referenceFromIndex: currentKernelTarget.loader.referenceFromIndex);
+          neededDillLibraries: neededDillLibraries);
     });
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 5d15880..8a79564 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1016,7 +1016,7 @@
     }
     pop(); // Annotations.
 
-    performBacklogComputations();
+    performBacklogComputations(allowFurtherDelays: false);
     assert(stack.length == 0);
   }
 
@@ -1025,12 +1025,22 @@
   ///
   /// Back logged computations include resolution of redirecting factory
   /// invocations and checking of typedef types.
+  ///
+  /// If the parameter [allowFurtherDelays] is set to `true`, the backlog
+  /// computations are allowed to be delayed one more time if they can't be
+  /// completed in the current invocation of [performBacklogComputations] and
+  /// have a chance to be completed during the next invocation. If
+  /// [allowFurtherDelays] is set to `false`, the backlog computations are
+  /// assumed to be final and the function throws an internal exception in case
+  /// if any of the computations can't be completed.
   void performBacklogComputations(
-      [List<DelayedActionPerformer>? delayedActionPerformers]) {
+      {List<DelayedActionPerformer>? delayedActionPerformers,
+      required bool allowFurtherDelays}) {
     _finishVariableMetadata();
     _unaliasTypeAliasedConstructorInvocations();
     _unaliasTypeAliasedFactoryInvocations(typeAliasedFactoryInvocations);
-    _resolveRedirectingFactoryTargets(redirectingFactoryInvocations);
+    _resolveRedirectingFactoryTargets(redirectingFactoryInvocations,
+        allowFurtherDelays: allowFurtherDelays);
     libraryBuilder.checkPendingBoundsChecks(typeEnvironment);
     if (hasDelayedActions) {
       assert(
@@ -1042,7 +1052,7 @@
   }
 
   void finishRedirectingFactoryBody() {
-    performBacklogComputations();
+    performBacklogComputations(allowFurtherDelays: false);
   }
 
   @override
@@ -1369,7 +1379,7 @@
       }
     }
 
-    performBacklogComputations();
+    performBacklogComputations(allowFurtherDelays: false);
   }
 
   void checkAsyncReturnType(AsyncMarker asyncModifier, DartType returnType,
@@ -1517,8 +1527,17 @@
     return replacementNode;
   }
 
+  /// If the parameter [allowFurtherDelays] is set to `true`, the resolution of
+  /// redirecting factories is allowed to be delayed one more time if it can't
+  /// be completed in the current invocation of
+  /// [_resolveRedirectingFactoryTargets] and has a chance to be completed
+  /// during the next invocation. If [allowFurtherDelays] is set to `false`,
+  /// the resolution of redirecting factories is assumed to be final and the
+  /// function throws an internal exception in case if any of the resolutions
+  /// can't be completed.
   void _resolveRedirectingFactoryTargets(
-      List<FactoryConstructorInvocation> redirectingFactoryInvocations) {
+      List<FactoryConstructorInvocation> redirectingFactoryInvocations,
+      {required bool allowFurtherDelays}) {
     List<FactoryConstructorInvocation> invocations =
         redirectingFactoryInvocations.toList();
     redirectingFactoryInvocations.clear();
@@ -1533,6 +1552,9 @@
       // ignore: unnecessary_null_comparison
       if (typeInferrer != null) {
         if (!invocation.hasBeenInferred) {
+          if (allowFurtherDelays) {
+            delayedRedirectingFactoryInvocations.add(invocation);
+          }
           continue;
         }
       } else {
@@ -1637,9 +1659,10 @@
   /// redirecting factory invocation depends on the type inference in the
   /// redirecting factory.
   @override
-  void performDelayedActions() {
+  void performDelayedActions({required bool allowFurtherDelays}) {
     if (delayedRedirectingFactoryInvocations.isNotEmpty) {
-      _resolveRedirectingFactoryTargets(delayedRedirectingFactoryInvocations);
+      _resolveRedirectingFactoryTargets(delayedRedirectingFactoryInvocations,
+          allowFurtherDelays: allowFurtherDelays);
       if (delayedRedirectingFactoryInvocations.isNotEmpty) {
         for (StaticInvocation invocation
             in delayedRedirectingFactoryInvocations) {
@@ -1722,7 +1745,7 @@
     } else {
       temporaryParent = new ListLiteral(expressions);
     }
-    performBacklogComputations();
+    performBacklogComputations(allowFurtherDelays: false);
     return temporaryParent != null ? temporaryParent.expressions : expressions;
   }
 
@@ -1793,7 +1816,7 @@
         "Previously implicit assumption about inferFunctionBody "
         "not returning anything different.");
 
-    performBacklogComputations();
+    performBacklogComputations(allowFurtherDelays: false);
     libraryBuilder.loader.transformPostInference(fakeReturn,
         transformSetLiterals, transformCollections, libraryBuilder.library);
 
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index be790e8..20146e7 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -513,7 +513,9 @@
       }
       bodyBuilder.parseInitializers(beginInitializers!,
           doFinishConstructor: isConst);
-      bodyBuilder.performBacklogComputations(delayedActionPerformers);
+      bodyBuilder.performBacklogComputations(
+          delayedActionPerformers: delayedActionPerformers,
+          allowFurtherDelays: false);
     }
     beginInitializers = null;
     addSuperParameterDefaultValueCloners(delayedDefaultValueCloners);
diff --git a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index 8b8f7b2..a73f8f5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -694,7 +694,14 @@
       if (enumConstantInfo.argumentsBeginToken != null) {
         arguments =
             bodyBuilder.parseArguments(enumConstantInfo.argumentsBeginToken!);
-        bodyBuilder.performBacklogComputations(_delayedActionPerformers);
+        // We pass `true` for [allowFurtherDelays] here because the members of
+        // the enums are built before the inference, and the resolution of the
+        // redirecting factories can't be completed at this moment and
+        // therefore should be delayed to another invocation of
+        // [BodyBuilder.performBacklogComputations].
+        bodyBuilder.performBacklogComputations(
+            delayedActionPerformers: _delayedActionPerformers,
+            allowFurtherDelays: true);
 
         arguments.positional.insertAll(0, enumSyntheticArguments);
         arguments.argumentsOriginalOrder?.insertAll(0, enumSyntheticArguments);
diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
index 1fccff2..5547064 100644
--- a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
@@ -433,7 +433,9 @@
         initializer = wrapper.operand;
       }
       buildBody(classHierarchy.coreTypes, initializer);
-      bodyBuilder.performBacklogComputations(delayedActionPerformers);
+      bodyBuilder.performBacklogComputations(
+          delayedActionPerformers: delayedActionPerformers,
+          allowFurtherDelays: false);
     }
     _constInitializerToken = null;
   }
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index c039e08..3de16c3 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -2314,7 +2314,7 @@
         ?.beginSubdivide(BenchmarkSubdivides.delayedActionPerformer);
     for (DelayedActionPerformer delayedActionPerformer
         in delayedActionPerformers) {
-      delayedActionPerformer.performDelayedActions();
+      delayedActionPerformer.performDelayedActions(allowFurtherDelays: false);
     }
     target.benchmarker?.endSubdivide();
     ticker.logMs("Build outline expressions");
diff --git a/pkg/front_end/lib/src/fasta/util/helpers.dart b/pkg/front_end/lib/src/fasta/util/helpers.dart
index 0e41efc..bf6fbce 100644
--- a/pkg/front_end/lib/src/fasta/util/helpers.dart
+++ b/pkg/front_end/lib/src/fasta/util/helpers.dart
@@ -4,5 +4,5 @@
 
 abstract class DelayedActionPerformer {
   bool get hasDelayedActions;
-  void performDelayedActions();
+  void performDelayedActions({required bool allowFurtherDelays});
 }
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 1d35c50..b8eb49e 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -188,10 +188,7 @@
     // summaries without building a full component (at this time, that's
     // the only need we have for these transformations).
     if (!buildComponent) {
-      options.target.performOutlineTransformations(
-          trimmedSummaryComponent,
-          kernelTarget.loader.coreTypes,
-          kernelTarget.loader.referenceFromIndex);
+      options.target.performOutlineTransformations(trimmedSummaryComponent);
       options.ticker.logMs("Transformed outline");
     }
     // Don't include source (but do add it above to include importUris).
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index fe79f6e..46bb0f7 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -780,6 +780,7 @@
 degrade
 delay
 delayed
+delays
 delegate
 delegates
 delegation
@@ -2563,6 +2564,7 @@
 reset
 resets
 resolution
+resolutions
 resolve
 resolved
 resolver
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart b/pkg/front_end/testcases/enhanced_enums/issue49429.dart
new file mode 100644
index 0000000..e445561
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart
@@ -0,0 +1,12 @@
+class A {
+  const A();
+  const factory A.redir() = A;
+}
+
+enum E {
+  element(A.redir());
+
+  const E(A a);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.strong.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.strong.expect
new file mode 100644
index 0000000..8567ebc
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.strong.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    return new self::A::•();
+}
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C5;
+  static const field self::E element = #C4;
+  const constructor •(core::int #index, core::String #name, self::A a) → self::E
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = 0
+  #C3 = "element"
+  #C4 = self::E {index:#C2, _name:#C3}
+  #C5 = <self::E>[#C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49429.dart:
+- A. (from org-dartlang-testcase:///issue49429.dart:2:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+- E. (from org-dartlang-testcase:///issue49429.dart:9:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.strong.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.strong.transformed.expect
new file mode 100644
index 0000000..8567ebc
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.strong.transformed.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    return new self::A::•();
+}
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C5;
+  static const field self::E element = #C4;
+  const constructor •(core::int #index, core::String #name, self::A a) → self::E
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = 0
+  #C3 = "element"
+  #C4 = self::E {index:#C2, _name:#C3}
+  #C5 = <self::E>[#C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49429.dart:
+- A. (from org-dartlang-testcase:///issue49429.dart:2:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+- E. (from org-dartlang-testcase:///issue49429.dart:9:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.textual_outline.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.textual_outline.expect
new file mode 100644
index 0000000..e445561
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+class A {
+  const A();
+  const factory A.redir() = A;
+}
+
+enum E {
+  element(A.redir());
+
+  const E(A a);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e445561
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A {
+  const A();
+  const factory A.redir() = A;
+}
+
+enum E {
+  element(A.redir());
+
+  const E(A a);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.expect
new file mode 100644
index 0000000..2eb1193
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    return new self::A::•();
+}
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C5;
+  static const field self::E element = #C4;
+  const constructor •(core::int #index, core::String #name, self::A a) → self::E
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = 0
+  #C3 = "element"
+  #C4 = self::E {index:#C2, _name:#C3}
+  #C5 = <self::E*>[#C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49429.dart:
+- A. (from org-dartlang-testcase:///issue49429.dart:2:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+- E. (from org-dartlang-testcase:///issue49429.dart:9:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.modular.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.modular.expect
new file mode 100644
index 0000000..2eb1193
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.modular.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    return new self::A::•();
+}
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C5;
+  static const field self::E element = #C4;
+  const constructor •(core::int #index, core::String #name, self::A a) → self::E
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = 0
+  #C3 = "element"
+  #C4 = self::E {index:#C2, _name:#C3}
+  #C5 = <self::E*>[#C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49429.dart:
+- A. (from org-dartlang-testcase:///issue49429.dart:2:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+- E. (from org-dartlang-testcase:///issue49429.dart:9:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.outline.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.outline.expect
new file mode 100644
index 0000000..7b600b0
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[self::A::redir]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    return new self::A::•();
+}
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = const <self::E>[self::E::element];
+  static const field self::E element = const self::E::•(0, "element", const self::A::•());
+  const constructor •(core::int #index, core::String #name, self::A a) → self::E
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///issue49429.dart:1:7 -> ConstructorTearOffConstant(A.redir)
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue49429.dart:6:6 -> ListConstant(const <E*>[const E{_Enum.index: 0, _Enum._name: "element"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue49429.dart:7:3 -> InstanceConstant(const E{_Enum.index: 0, _Enum._name: "element"})
+Extra constant evaluation: evaluated: 10, effectively constant: 3
diff --git a/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.transformed.expect b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.transformed.expect
new file mode 100644
index 0000000..2eb1193
--- /dev/null
+++ b/pkg/front_end/testcases/enhanced_enums/issue49429.dart.weak.transformed.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  static final field dynamic _redirecting# = <dynamic>[#C1]/*isLegacy*/;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  static factory redir() → self::A
+    return new self::A::•();
+}
+class E extends core::_Enum /*isEnum*/  {
+  static const field core::List<self::E> values = #C5;
+  static const field self::E element = #C4;
+  const constructor •(core::int #index, core::String #name, self::A a) → self::E
+    : super core::_Enum::•(#index, #name)
+    ;
+  method toString() → core::String
+    return "E.${this.{core::_Enum::_name}{core::String}}";
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = constructor-tearoff self::A::redir
+  #C2 = 0
+  #C3 = "element"
+  #C4 = self::E {index:#C2, _name:#C3}
+  #C5 = <self::E*>[#C4]
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue49429.dart:
+- A. (from org-dartlang-testcase:///issue49429.dart:2:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
+- E. (from org-dartlang-testcase:///issue49429.dart:9:9)
+- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart)
diff --git a/pkg/frontend_server/lib/compute_kernel.dart b/pkg/frontend_server/lib/compute_kernel.dart
index 24a0fa4..918c891 100644
--- a/pkg/frontend_server/lib/compute_kernel.dart
+++ b/pkg/frontend_server/lib/compute_kernel.dart
@@ -396,10 +396,7 @@
         incrementalComponent.problemsAsJson = null;
         incrementalComponent.setMainMethodAndMode(
             null, true, incrementalComponent.mode);
-        target.performOutlineTransformations(
-            incrementalComponent,
-            incrementalCompilerResult.coreTypes!,
-            incrementalCompilerResult.referenceFromIndex);
+        target.performOutlineTransformations(incrementalComponent);
         makeStable(incrementalComponent);
         return Future.value(fe.serializeComponent(incrementalComponent,
             includeSources: false, includeOffsets: false));
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 477f255..0c594a5 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -314,8 +314,7 @@
   /// transformation is not applied when compiling full kernel programs to
   /// prevent affecting the internal invariants of the compiler and accidentally
   /// slowing down compilation.
-  void performOutlineTransformations(Component component, CoreTypes coreTypes,
-      ReferenceFromIndex? referenceFromIndex) {}
+  void performOutlineTransformations(Component component) {}
 
   /// Perform target-specific transformations on the given libraries that must
   /// run before constant evaluation.
@@ -1008,10 +1007,8 @@
   }
 
   @override
-  void performOutlineTransformations(Component component, CoreTypes coreTypes,
-      ReferenceFromIndex? referenceFromIndex) {
-    _target.performOutlineTransformations(
-        component, coreTypes, referenceFromIndex);
+  void performOutlineTransformations(Component component) {
+    _target.performOutlineTransformations(component);
   }
 
   @override
@@ -1076,10 +1073,8 @@
   bool get excludeNonSources;
 
   @override
-  void performOutlineTransformations(Component component, CoreTypes coreTypes,
-      ReferenceFromIndex? referenceFromIndex) {
-    super.performOutlineTransformations(
-        component, coreTypes, referenceFromIndex);
+  void performOutlineTransformations(Component component) {
+    super.performOutlineTransformations(component);
     if (!excludeNonSources) return;
 
     List<Library> libraries = new List.of(component.libraries);
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index d992ce5..6ce51d2 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -642,8 +642,8 @@
   @override
   DecoratedType? visitCatchClause(CatchClause node) {
     _flowAnalysis!.tryCatchStatement_catchBegin(
-        node.exceptionParameter?.staticElement as PromotableElement?,
-        node.stackTraceParameter?.staticElement as PromotableElement?);
+        node.exceptionParameter2?.declaredElement,
+        node.stackTraceParameter2?.declaredElement);
     _dispatch(node.exceptionType);
     // The catch clause may not execute, so create a new scope for
     // post-dominators.
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 7ac2f62..78e0b70 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -90,37 +90,37 @@
 
   @override
   DecoratedType? visitCatchClause(CatchClause node) {
-    var exceptionElement = node.exceptionParameter?.staticElement;
+    var exceptionElement = node.exceptionParameter2?.declaredElement;
     var target = exceptionElement == null
         ? NullabilityNodeTarget.text('exception type')
         : NullabilityNodeTarget.element(exceptionElement);
     DecoratedType? exceptionType = _pushNullabilityNodeTarget(
         target, () => node.exceptionType?.accept(this));
-    if (node.exceptionParameter != null) {
+    if (node.exceptionParameter2 != null) {
       // If there is no `on Type` part of the catch clause, the type is dynamic.
       if (exceptionType == null) {
         exceptionType = DecoratedType.forImplicitType(_typeProvider,
             _typeProvider.dynamicType, _graph, target.withCodeRef(node));
         instrumentation?.implicitType(
-            source, node.exceptionParameter, exceptionType);
+            source, node.exceptionParameter2, exceptionType);
       }
       _variables!.recordDecoratedElementType(
-          node.exceptionParameter!.staticElement, exceptionType);
+          node.exceptionParameter2?.declaredElement, exceptionType);
     }
-    if (node.stackTraceParameter != null) {
+    if (node.stackTraceParameter2 != null) {
       // The type of stack traces is always StackTrace (non-nullable).
       var target = NullabilityNodeTarget.text('stack trace').withCodeRef(node);
       var nullabilityNode = NullabilityNode.forInferredType(target);
       _graph.makeNonNullableUnion(nullabilityNode,
-          StackTraceTypeOrigin(source, node.stackTraceParameter));
+          StackTraceTypeOrigin(source, node.stackTraceParameter2));
       var stackTraceType =
           DecoratedType(_typeProvider.stackTraceType, nullabilityNode);
       _variables!.recordDecoratedElementType(
-          node.stackTraceParameter!.staticElement, stackTraceType);
+          node.stackTraceParameter2?.declaredElement, stackTraceType);
       instrumentation?.implicitType(
-          source, node.stackTraceParameter, stackTraceType);
+          source, node.stackTraceParameter2, stackTraceType);
     }
-    node.stackTraceParameter?.accept(this);
+    node.stackTraceParameter2?.accept(this);
     node.body.accept(this);
     return null;
   }
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index ed7e265..578dca2 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -868,7 +868,7 @@
 }
 ''');
     var oNode = explicitTypeNullability[findNode.typeAnnotation('Object')];
-    var eNode = implicitType[findNode.simple('e)')]!.node;
+    var eNode = implicitType[findNode.catchClauseParameter('e)')]!.node;
     expect(
         edges.where((e) => e.sourceNode == eNode && e.destinationNode == oNode),
         hasLength(1));
@@ -883,7 +883,7 @@
 }
 ''');
     var oNode = explicitTypeNullability[findNode.typeAnnotation('Object')];
-    var stNode = implicitType[findNode.simple('st)')]!.node;
+    var stNode = implicitType[findNode.catchClauseParameter('st)')]!.node;
     expect(
         edges
             .where((e) => e.sourceNode == stNode && e.destinationNode == oNode),
diff --git a/pkg/vm/lib/transformations/ffi/common.dart b/pkg/vm/lib/transformations/ffi/common.dart
index a34a828..71fc2b5 100644
--- a/pkg/vm/lib/transformations/ffi/common.dart
+++ b/pkg/vm/lib/transformations/ffi/common.dart
@@ -1120,7 +1120,14 @@
     if (dartType == correspondingDartType) return;
     if (env.isSubtypeOf(correspondingDartType, dartType,
         SubtypeCheckMode.ignoringNullabilities)) {
-      return;
+      // If subtype, manually check the return type is not void.
+      if (dartType is! FunctionType || correspondingDartType is! FunctionType) {
+        return;
+      } else if ((dartType.returnType is VoidType) ==
+          (correspondingDartType.returnType is VoidType)) {
+        return;
+      }
+      // One of the return types is void, the other isn't, report error.
     }
     diagnosticReporter.report(
         templateFfiTypeMismatch.withArguments(dartType, correspondingDartType,
diff --git a/pkg/vm/lib/transformations/ffi/native.dart b/pkg/vm/lib/transformations/ffi/native.dart
index feaa323..837792e 100644
--- a/pkg/vm/lib/transformations/ffi/native.dart
+++ b/pkg/vm/lib/transformations/ffi/native.dart
@@ -117,9 +117,10 @@
   // Replaces return type with Object if it is Handle.
   DartType _wrapReturnType(DartType dartReturnType, DartType ffiReturnType) {
     if (env.isSubtypeOf(
-        ffiReturnType,
-        handleClass.getThisType(coreTypes, Nullability.nonNullable),
-        SubtypeCheckMode.ignoringNullabilities)) {
+            ffiReturnType,
+            handleClass.getThisType(coreTypes, Nullability.nonNullable),
+            SubtypeCheckMode.ignoringNullabilities) &&
+        dartReturnType is! VoidType) {
       return objectClass.getThisType(coreTypes, dartReturnType.nullability);
     }
     return dartReturnType;
@@ -411,7 +412,8 @@
         nativeFunctionClass, Nullability.legacy, [ffiFunctionType]);
     try {
       ensureNativeTypeValid(nativeType, node);
-      ensureNativeTypeToDartType(nativeType, wrappedDartFunctionType, node);
+      ensureNativeTypeToDartType(nativeType, wrappedDartFunctionType, node,
+          allowHandle: true);
       ensureLeafCallDoesNotUseHandles(nativeType, isLeaf, node);
     } on FfiStaticTypeError {
       // It's OK to swallow the exception because the diagnostics issued will
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 44f2547..a12f853 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -1133,17 +1133,30 @@
                              FLAG_branch_coverage);
     }
 
-    // Generated code must match the host architecture and ABI. We check the
-    // strong condition of matching on operating system so that
-    // Platform.isAndroid etc can be compile-time constants.
-#if defined(TARGET_ARCH_IA32)
+// Generated code must match the host architecture and ABI.
+#if defined(TARGET_ARCH_ARM)
+#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
+    buffer.AddString(" arm-ios");
+#else
+    buffer.AddString(" arm-eabi");
+#endif
+    buffer.AddString(TargetCPUFeatures::hardfp_supported() ? " hardfp"
+                                                           : " softfp");
+#elif defined(TARGET_ARCH_ARM64)
+#if defined(DART_TARGET_OS_FUCHSIA)
+    // See signal handler cheat in Assembler::EnterFrame.
+    buffer.AddString(" arm64-fuchsia");
+#else
+    buffer.AddString(" arm64-sysv");
+#endif
+#elif defined(TARGET_ARCH_IA32)
     buffer.AddString(" ia32");
 #elif defined(TARGET_ARCH_X64)
-    buffer.AddString(" x64");
-#elif defined(TARGET_ARCH_ARM)
-    buffer.AddString(" arm");
-#elif defined(TARGET_ARCH_ARM64)
-    buffer.AddString(" arm64");
+#if defined(DART_TARGET_OS_WINDOWS)
+    buffer.AddString(" x64-win");
+#else
+    buffer.AddString(" x64-sysv");
+#endif
 #elif defined(TARGET_ARCH_RISCV32)
     buffer.AddString(" riscv32");
 #elif defined(TARGET_ARCH_RISCV64)
@@ -1151,25 +1164,6 @@
 #else
 #error What architecture?
 #endif
-
-#if defined(DART_TARGET_OS_ANDROID)
-    buffer.AddString(" android");
-#elif defined(DART_TARGET_OS_FUCHSIA)
-    buffer.AddString(" fuchsia");
-#elif defined(DART_TARGET_OS_MACOS)
-#if defined(DART_TARGET_OS_MACOS_IOS)
-    buffer.AddString(" ios");
-#else
-    buffer.AddString(" macos");
-#endif
-#elif defined(DART_TARGET_OS_LINUX)
-    buffer.AddString(" linux");
-#elif defined(DART_TARGET_OS_WINDOWS)
-    buffer.AddString(" windows");
-#else
-#error What operating system?
-#endif
-
 #if defined(DART_COMPRESSED_POINTERS)
     buffer.AddString(" compressed-pointers");
 #else
diff --git a/samples-dev/swarm/App.dart b/samples-dev/swarm/App.dart
index fc51ec9..b03e814 100644
--- a/samples-dev/swarm/App.dart
+++ b/samples-dev/swarm/App.dart
@@ -6,18 +6,16 @@
 
 part of swarmlib;
 
-/**
- * The base class that should be extended by all HTML applications.
- *
- * It should both be easy to use for users coming over from JavaScript, but
- * also offer a clear notion of OO encapsulation.
- *
- * This class or something similar belongs in the standard DOM library.
- */
+/// The base class that should be extended by all HTML applications.
+///
+/// It should both be easy to use for users coming over from JavaScript, but
+/// also offer a clear notion of OO encapsulation.
+///
+/// This class or something similar belongs in the standard DOM library.
 class App {
-  App() {}
+  App();
 
-  /** Begins executing code in this [App]. */
+  /// Begins executing code in this [App]. */
   void run() {
     // If the script is async, by the time we get here the DOM content may
     // already be loaded, so waiting on the DOMContentLoaded event is a no-op.
@@ -40,12 +38,10 @@
     }
   }
 
-  /**
-   * Called when the DOM is fully loaded but potentially before resources.
-   *
-   * For most apps, any startup code should be in this method. Be sure to call
-   * the superclass implementation.
-   */
+  /// Called when the DOM is fully loaded but potentially before resources.
+  ///
+  /// For most apps, any startup code should be in this method. Be sure to call
+  /// the superclass implementation.
   void onLoad() {
     // Prevent the default browser behavior of scrolling the window.
     document.onTouchMove.listen((Event event) => event.preventDefault());
@@ -57,11 +53,9 @@
     }
   }
 
-  /**
-   * Erase the static splash screen.
-   *
-   * Assumption: if a splash screen exists, an element #appSplash contains it.
-   */
+  /// Erase the static splash screen.
+  ///
+  /// Assumption: if a splash screen exists, an element #appSplash contains it.
   void eraseSplashScreen() {
     final splash = document.querySelector("#appSplash");
     // Delete it if found, but it's okay for it not to be -- maybe
@@ -71,10 +65,8 @@
     }
   }
 
-  /**
-   * Swaps and reloads the app cache if an update is ready. Returns false if
-   * an update is not ready.
-   */
+  /// Swaps and reloads the app cache if an update is ready. Returns false if
+  /// an update is not ready.
   bool swapAndReloadCache() {
     ApplicationCache appCache = window.applicationCache;
     if (!identical(appCache.status, ApplicationCache.UPDATEREADY)) {
@@ -88,7 +80,7 @@
     return true;
   }
 
-  /** Returns true if we are running as a packaged application. */
+  /// Returns true if we are running as a packaged application. */
   static bool get isPackaged {
     return window.location.protocol == 'chrome-extension:';
   }
diff --git a/samples-dev/swarm/BiIterator.dart b/samples-dev/swarm/BiIterator.dart
index fb56d61..0badeca 100644
--- a/samples-dev/swarm/BiIterator.dart
+++ b/samples-dev/swarm/BiIterator.dart
@@ -2,33 +2,25 @@
 
 part of swarmlib;
 
-/**
- * An iterator that allows the user to move forward and backward though
- * a set of items. (Bi-directional)
- */
+/// An iterator that allows the user to move forward and backward though
+/// a set of items. (Bi-directional)
 class BiIterator<E> {
-  /**
-   * Provides forward and backward iterator functionality to keep track
-   * which item is currently selected.
-   */
+  /// Provides forward and backward iterator functionality to keep track
+  /// which item is currently selected.
   ObservableValue<int> currentIndex;
 
-  /**
-   * The collection of items we will be iterating through.
-   */
+  /// The collection of items we will be iterating through.
   List<E> list;
 
-  BiIterator(this.list, [List<ChangeListener> oldListeners = null])
-      : currentIndex = new ObservableValue<int>(0) {
+  BiIterator(this.list, [List<ChangeListener> oldListeners])
+      : currentIndex = ObservableValue<int>(0) {
     if (oldListeners != null) {
       currentIndex.listeners = oldListeners;
     }
   }
 
-  /**
-   * Returns the next section from the sections, given the current
-   * position. Returns the last source if there is no next section.
-   */
+  /// Returns the next section from the sections, given the current
+  /// position. Returns the last source if there is no next section.
   E next() {
     if (currentIndex.value < list.length - 1) {
       currentIndex.value += 1;
@@ -36,19 +28,15 @@
     return list[currentIndex.value];
   }
 
-  /**
-   * Returns the current Section (page in the UI) that the user is
-   * looking at.
-   */
+  /// Returns the current Section (page in the UI) that the user is
+  /// looking at.
   E get current {
     return list[currentIndex.value];
   }
 
-  /**
-   * Returns the previous section from the sections, given the current
-   * position. Returns the front section if we are already at the front of
-   * the list.
-   */
+  /// Returns the previous section from the sections, given the current
+  /// position. Returns the front section if we are already at the front of
+  /// the list.
   E previous() {
     if (currentIndex.value > 0) {
       currentIndex.value -= 1;
@@ -56,9 +44,7 @@
     return list[currentIndex.value];
   }
 
-  /**
-   * Move the iterator pointer over so that it points to a given list item.
-   */
+  /// Move the iterator pointer over so that it points to a given list item.
   void jumpToValue(E val) {
     for (int i = 0; i < list.length; i++) {
       if (identical(list[i], val)) {
diff --git a/samples-dev/swarm/CannedData.dart b/samples-dev/swarm/CannedData.dart
index 2f5a467..2f62def 100644
--- a/samples-dev/swarm/CannedData.dart
+++ b/samples-dev/swarm/CannedData.dart
@@ -8,7 +8,7 @@
 
 // TODO(jimhug): Work out correct copyright for this file.
 class CannedData {
-  static const Map<String, String> data = const {
+  static const Map<String, String> data = {
     'Test0_0_0.html': 'Lorem ipsum something or other...',
     'Test0_0_1.html': 'Lorem ipsum something or other...',
     'Test0_0_2.html': 'Lorem ipsum something or other...',
diff --git a/samples-dev/swarm/ConfigHintDialog.dart b/samples-dev/swarm/ConfigHintDialog.dart
index 92acf4b..5f174f6 100644
--- a/samples-dev/swarm/ConfigHintDialog.dart
+++ b/samples-dev/swarm/ConfigHintDialog.dart
@@ -14,18 +14,19 @@
 
   factory ConfigHintDialog(CompositeView parent, Function doneHandler) {
     View content = ConfigHintDialog.makeContent();
-    return new ConfigHintDialog._impl(parent, doneHandler, content);
+    return ConfigHintDialog._impl(parent, doneHandler, content);
   }
 
   ConfigHintDialog._impl(this._parent, this._doneHandler, View content)
       : super('Feed configuration', '', content);
 
+  @override
   void onDone() {
     _doneHandler();
   }
 
   static View makeContent() {
-    return new View.html('''
+    return View.html('''
         <div>
           Add or remove feeds in
           <a href="https://www.google.com/reader" target="_blank">
diff --git a/samples-dev/swarm/DataSource.dart b/samples-dev/swarm/DataSource.dart
index 9f350a1..a181de3 100644
--- a/samples-dev/swarm/DataSource.dart
+++ b/samples-dev/swarm/DataSource.dart
@@ -7,7 +7,7 @@
 
 part of swarmlib;
 
-/** The top-level collection of all sections for a user. */
+/// The top-level collection of all sections for a user. */
 // TODO(jimhug): This is known as UserData in the server model.
 class Sections extends IterableBase<Section> {
   final List<Section> _sections;
@@ -16,6 +16,7 @@
 
   operator [](int i) => _sections[i];
 
+  @override
   int get length => _sections.length;
 
   List<String> get sectionTitles => _sections.map((s) => s.title).toList();
@@ -24,15 +25,14 @@
     // TODO(jimhug): http://b/issue?id=5351067
   }
 
-  /**
-   * Find the Section object that has a given title.
-   * This is used to integrate well with [ConveyorView].
-   */
+  /// Find the Section object that has a given title.
+  /// This is used to integrate well with [ConveyorView].
   Section findSection(String name) {
     return CollectionUtils.find(_sections, (sect) => sect.title == name);
   }
 
   // TODO(jimhug): Track down callers!
+  @override
   Iterator<Section> get iterator => _sections.iterator;
 
   // TODO(jimhug): Better support for switching between local dev and server.
@@ -47,19 +47,19 @@
   }
 
   // This method is exposed for tests.
-  static void initializeFromData(String data, void callback(Sections sects)) {
-    final decoder = new Decoder(data);
+  static void initializeFromData(String data, void Function(Sections sects) callback) {
+    final decoder = Decoder(data);
     int nSections = decoder.readInt();
-    final sections = new List<Section>();
+    final sections = <Section>[];
 
     for (int i = 0; i < nSections; i++) {
       sections.add(Section.decode(decoder));
     }
-    callback(new Sections(sections));
+    callback(Sections(sections));
   }
 
   static void initializeFromUrl(
-      bool useCannedData, void callback(Sections sections)) {
+      bool useCannedData, void Function(Sections sections) callback) {
     if (Sections.runningFromFile || useCannedData) {
       initializeFromData(CannedData.data['user.data'], callback);
     } else {
@@ -79,9 +79,7 @@
     return CollectionUtils.find(_sections, (section) => section.id == id);
   }
 
-  /**
-   * Given the name of a section, find its index in the set.
-   */
+  /// Given the name of a section, find its index in the set.
   int findSectionIndex(String name) {
     for (int i = 0; i < _sections.length; i++) {
       if (name == _sections[i].title) {
@@ -94,10 +92,11 @@
   List<Section> get sections => _sections;
 
   // TODO(jmesserly): this should be a property
+  @override
   bool get isEmpty => length == 0;
 }
 
-/** A collection of data sources representing a page in the UI. */
+/// A collection of data sources representing a page in the UI. */
 class Section {
   final String id;
   final String title;
@@ -117,11 +116,11 @@
     final sectionTitle = decoder.readString();
 
     final nSources = decoder.readInt();
-    final feeds = new ObservableList<Feed>();
+    final feeds = ObservableList<Feed>();
     for (int j = 0; j < nSources; j++) {
       feeds.add(Feed.decode(decoder));
     }
-    return new Section(sectionId, sectionTitle, feeds);
+    return Section(sectionId, sectionTitle, feeds);
   }
 
   Feed findFeed(String id_) {
@@ -129,7 +128,7 @@
   }
 }
 
-/** Provider of a news feed. */
+/// Provider of a news feed. */
 class Feed {
   String id;
   final String title;
@@ -138,15 +137,15 @@
   ObservableList<Article> articles;
   ObservableValue<bool> error; // TODO(jimhug): Check if dead code.
 
-  Feed(this.id, this.title, this.iconUrl, {this.description: ''})
-      : articles = new ObservableList<Article>(),
-        error = new ObservableValue<bool>(false);
+  Feed(this.id, this.title, this.iconUrl, {this.description = ''})
+      : articles = ObservableList<Article>(),
+        error = ObservableValue<bool>(false);
 
   static Feed decode(Decoder decoder) {
     final sourceId = decoder.readString();
     final sourceTitle = decoder.readString();
     final sourceIcon = decoder.readString();
-    final feed = new Feed(sourceId, sourceTitle, sourceIcon);
+    final feed = Feed(sourceId, sourceTitle, sourceIcon);
     final nItems = decoder.readInt();
 
     for (int i = 0; i < nItems; i++) {
@@ -162,7 +161,7 @@
   void refresh() {}
 }
 
-/** A single article or posting to display. */
+/// A single article or posting to display. */
 class Article {
   final String id;
   DateTime date;
@@ -179,9 +178,9 @@
 
   Article(this.dataSource, this.id, this.date, this.title, this.author,
       this.srcUrl, this.hasThumbnail, this.textBody,
-      {htmlBody: null, bool unread: true, this.error: false})
-      : unread = new ObservableValue<bool>(unread),
-        this._htmlBody = htmlBody;
+      {htmlBody, bool unread = true, this.error = false})
+      : unread = ObservableValue<bool>(unread),
+        _htmlBody = htmlBody;
 
   String get htmlBody {
     _ensureLoaded();
@@ -198,7 +197,7 @@
   String get thumbUrl {
     if (!hasThumbnail) return null;
 
-    var home;
+    String home;
     if (Sections.runningFromFile) {
       home = 'http://dart.googleplex.com';
     } else {
@@ -221,7 +220,7 @@
       _htmlBody = CannedData.data[name];
     } else {
       // TODO(jimhug): Remove this truly evil synchronoush xhr.
-      final req = new HttpRequest();
+      final req = HttpRequest();
       req.open('GET', 'data/$name', async: false);
       req.send();
       _htmlBody = req.responseText;
@@ -236,9 +235,9 @@
     final author = decoder.readString();
     final dateInSeconds = decoder.readInt();
     final snippet = decoder.readString();
-    final date = new DateTime.fromMillisecondsSinceEpoch(dateInSeconds * 1000,
+    final date = DateTime.fromMillisecondsSinceEpoch(dateInSeconds * 1000,
         isUtc: true);
-    return new Article(
+    return Article(
         source, id, date, title, author, srcUrl, hasThumbnail, snippet);
   }
 }
diff --git a/samples-dev/swarm/Decoder.dart b/samples-dev/swarm/Decoder.dart
index 6e84bba..8450e4f 100644
--- a/samples-dev/swarm/Decoder.dart
+++ b/samples-dev/swarm/Decoder.dart
@@ -12,7 +12,7 @@
   String data;
 
   Decoder(this.data) {
-    this.index = 0;
+    index = 0;
   }
 
   // Reads numbers in variable-length 7-bit encoding.  This matches the
diff --git a/samples-dev/swarm/HelpDialog.dart b/samples-dev/swarm/HelpDialog.dart
index dfce44c..3d57512 100644
--- a/samples-dev/swarm/HelpDialog.dart
+++ b/samples-dev/swarm/HelpDialog.dart
@@ -6,25 +6,24 @@
 
 part of swarmlib;
 
-/**
- * An informational dialog that shows keyboard shortcuts and provides a
- * link to the Dart language webpage.
- */
+/// An informational dialog that shows keyboard shortcuts and provides a
+/// link to the Dart language webpage.
 //TODO(efortuna): fix DialogView so it doesn't require the HTML passed to
 // the constructor.
 class HelpDialog extends DialogView {
-  CompositeView _parent;
-  Function _doneHandler;
+  final CompositeView _parent;
+  final Function _doneHandler;
 
   HelpDialog(this._parent, this._doneHandler)
       : super('Information', '', makeContent());
 
+  @override
   void onDone() {
     _doneHandler();
   }
 
   static View makeContent() {
-    return new View.html('''
+    return View.html('''
         <div>
 
           <p>
@@ -46,40 +45,40 @@
     String cellStart = '''<th valign="middle" align="center">''';
     return '''<table width="90%" border=1 cellspacing="0" cellpadding="2">
             <tr bgcolor="#c3d9ff">
-              ${cellStart} Shortcut Key </th>
-              ${cellStart} Action </th>
+              $cellStart Shortcut Key </th>
+              $cellStart Action </th>
             </tr>
             <tr>
-              ${cellStart} j, &lt;down arrow&gt; </th>
-              ${cellStart} Next Article </th>
+              $cellStart j, &lt;down arrow&gt; </th>
+              $cellStart Next Article </th>
             </tr>
             <tr>
-              ${cellStart} k, &lt;up arrow&gt; </th>
-              ${cellStart} Previous Article </th>
+              $cellStart k, &lt;up arrow&gt; </th>
+              $cellStart Previous Article </th>
             </tr>
             <tr>
-              ${cellStart} o, &lt;enter&gt; </th>
-              ${cellStart} Open Article </th>
+              $cellStart o, &lt;enter&gt; </th>
+              $cellStart Open Article </th>
             </tr>
             <tr>
-              ${cellStart} &lt;esc&gt;, &lt;delete&gt; </th>
-              ${cellStart} Back </th>
+              $cellStart &lt;esc&gt;, &lt;delete&gt; </th>
+              $cellStart Back </th>
             </tr>
             <tr>
-              ${cellStart} a, h, &lt;left arrow&gt; </th>
-              ${cellStart} Left </th>
+              $cellStart a, h, &lt;left arrow&gt; </th>
+              $cellStart Left </th>
             </tr>
             <tr>
-              ${cellStart} d, l, &lt;right arrow&gt; </th>
-              ${cellStart} Right </th>
+              $cellStart d, l, &lt;right arrow&gt; </th>
+              $cellStart Right </th>
             </tr>
             <tr>
-              ${cellStart} n </th>
-              ${cellStart} Next Category </th>
+              $cellStart n </th>
+              $cellStart Next Category </th>
             </tr>
             <tr>
-              ${cellStart} p </th>
-              ${cellStart} Previous Category </th>
+              $cellStart p </th>
+              $cellStart Previous Category </th>
             </tr>
 
         </table>''';
diff --git a/samples-dev/swarm/SwarmApp.dart b/samples-dev/swarm/SwarmApp.dart
index fc8b2a1..ec6302e 100644
--- a/samples-dev/swarm/SwarmApp.dart
+++ b/samples-dev/swarm/SwarmApp.dart
@@ -6,29 +6,25 @@
 
 part of swarmlib;
 
-/**
- * A simple news reader in Dart.
- */
+/// A simple news reader in Dart.
 class Swarm extends App {
-  /**
-   * Flag to insure the onLoad isn't called when callback from initializeFromUrl
-   * could occur before the document's onload event.
-   */
+  /// Flag to insure the onLoad isn't called when callback from initializeFromUrl
+  /// could occur before the document's onload event.
   bool onLoadFired;
 
-  /** Collections of datafeeds to show per page. */
+  /// Collections of datafeeds to show per page. */
   Sections sections;
 
-  /** The front page of the app. */
+  /// The front page of the app. */
   FrontView frontView;
 
-  /** Observable UI state. */
+  /// Observable UI state. */
   SwarmState state;
 
-  Swarm({bool useCannedData: false}) : onLoadFired = false {
+  Swarm({bool useCannedData = false}) : onLoadFired = false {
     Sections.initializeFromUrl(useCannedData, (currSections) {
       sections = currSections;
-      state = new SwarmState(sections);
+      state = SwarmState(sections);
       setupApp();
     });
     // Catch user keypresses and decide whether to use them for the
@@ -40,16 +36,14 @@
     });
   }
 
-  /**
-   * Tells each data source to check the server for the latest data.
-   */
+  /// Tells each data source to check the server for the latest data.
   void refresh() {
     sections.refresh();
 
     // Hook up listeners about any data source additions or deletions.  We don't
     // differentiate additions or deletions just the fact that data feeds have
     // changed.  We might want more fidelity later.
-    sections.sectionTitles.forEach((title) {
+    for (var title in sections.sectionTitles) {
       Section section = sections.findSection(title);
       // TODO(terry): addChangeListener needs to return an id so previous
       //              listener can be removed, otherwise anonymous functions
@@ -58,19 +52,18 @@
         // TODO(jacobr): implement this.
         print("Refresh sections not impl yet.");
       });
-    });
+    }
   }
 
-  /** The page load event handler. */
+  /// The page load event handler. */
+  @override
   void onLoad() {
     onLoadFired = true;
     super.onLoad();
     setupApp();
   }
 
-  /**
-   * Setup the application's world.
-   */
+  /// Setup the application's world.
   void setupApp() {
     // TODO(terry): Should be able to spinup the app w/o waiting for data.
     // If the document is already loaded so we can setup the app anytime.
@@ -85,7 +78,7 @@
   }
 
   void render() {
-    frontView = new FrontView(this);
+    frontView = FrontView(this);
     frontView.addToDocument(document.body);
   }
 }
diff --git a/samples-dev/swarm/SwarmState.dart b/samples-dev/swarm/SwarmState.dart
index e710bcc..ec19e06 100644
--- a/samples-dev/swarm/SwarmState.dart
+++ b/samples-dev/swarm/SwarmState.dart
@@ -6,79 +6,62 @@
 
 part of swarmlib;
 
-/**
- * The top-level class for the UI state. UI state is essentially a "model" from
- * the view's perspective but whose data just describes the UI itself. It
- * contains data like the currently selected story, etc.
- */
+/// The top-level class for the UI state. UI state is essentially a "model" from
+/// the view's perspective but whose data just describes the UI itself. It
+/// contains data like the currently selected story, etc.
 // TODO(jimhug): Split the two classes here into framework and app-specific.
 class SwarmState extends UIState {
-  /** Core data source for the app. */
+  /// Core data source for the app. */
   final Sections _dataModel;
 
-  /**
-   * Which article the user is currently viewing, or null if they aren't
-   * viewing an Article.
-   */
+  /// Which article the user is currently viewing, or null if they aren't
+  /// viewing an Article.
   final ObservableValue<Article> currentArticle;
-  /**
-   * Which article the user currently has selected (for traversing articles
-   * via keyboard shortcuts).
-   */
+
+  /// Which article the user currently has selected (for traversing articles
+  /// via keyboard shortcuts).
   final ObservableValue<Article> selectedArticle;
 
-  /**
-   * True if the story view is maximized and the top and bottom UI elements
-   * are hidden.
-   */
+  /// True if the story view is maximized and the top and bottom UI elements
+  /// are hidden.
   final ObservableValue<bool> storyMaximized;
 
-  /**
-   * True if the maximized story, if any, is being displayed in text mode
-   * rather than as an embedded web-page.
-   */
+  /// True if the maximized story, if any, is being displayed in text mode
+  /// rather than as an embedded web-page.
   final ObservableValue<bool> storyTextMode;
 
-  /**
-   * Which article the user currently has selected (by keyboard shortcuts),
-   * or null if an article isn't selected by the keyboard.
-   */
+  /// Which article the user currently has selected (by keyboard shortcuts),
+  /// or null if an article isn't selected by the keyboard.
   BiIterator<Article> _articleIterator;
 
-  /**
-   * Which feed is currently selected (for keyboard shortcuts).
-   */
+  /// Which feed is currently selected (for keyboard shortcuts).
   BiIterator<Feed> _feedIterator;
 
-  /**
-   * Which section is currently selected (for keyboard shortcuts).
-   */
+  /// Which section is currently selected (for keyboard shortcuts).
   BiIterator<Section> _sectionIterator;
 
   SwarmState(this._dataModel)
-      : currentArticle = new ObservableValue<Article>(null),
-        selectedArticle = new ObservableValue<Article>(null),
-        storyMaximized = new ObservableValue<bool>(false),
-        storyTextMode = new ObservableValue<bool>(true) {
+      : currentArticle = ObservableValue<Article>(null),
+        selectedArticle = ObservableValue<Article>(null),
+        storyMaximized = ObservableValue<bool>(false),
+        storyTextMode = ObservableValue<bool>(true) {
     startHistoryTracking();
     // TODO(efortuna): consider having this class just hold observable
     // currentIndecies instead of iterators with observablevalues..
-    _sectionIterator = new BiIterator<Section>(_dataModel.sections);
-    _feedIterator = new BiIterator<Feed>(_sectionIterator.current.feeds);
-    _articleIterator = new BiIterator<Article>(_feedIterator.current.articles);
+    _sectionIterator = BiIterator<Section>(_dataModel.sections);
+    _feedIterator = BiIterator<Feed>(_sectionIterator.current.feeds);
+    _articleIterator = BiIterator<Article>(_feedIterator.current.articles);
 
     currentArticle.addChangeListener((e) {
       _articleIterator.jumpToValue(currentArticle.value);
     });
   }
 
-  /**
-   * Registers an event to fire on any state change
-   *
-   * TODO(jmesserly): fix this so we don't have to enumerate all of our fields
-   * again. One idea here is UIState becomes Observable, Observables have
-   * parents and notifications bubble up the parent chain.
-   */
+  /// Registers an event to fire on any state change
+  ///
+  /// TODO(jmesserly): fix this so we don't have to enumerate all of our fields
+  /// again. One idea here is UIState becomes Observable, Observables have
+  /// parents and notifications bubble up the parent chain.
   void addChangeListener(ChangeListener listener) {
     _sectionIterator.currentIndex.addChangeListener(listener);
     _feedIterator.currentIndex.addChangeListener(listener);
@@ -86,6 +69,7 @@
     currentArticle.addChangeListener(listener);
   }
 
+  @override
   Map<String, String> toHistory() {
     final data = {};
     data['section'] = currentSection.id;
@@ -96,97 +80,83 @@
     return data;
   }
 
+  @override
   void loadFromHistory(Map values) {
     // TODO(jimhug): There's a better way of doing this...
     if (values['section'] != null) {
       _sectionIterator
           .jumpToValue(_dataModel.findSectionById(values['section']));
     } else {
-      _sectionIterator = new BiIterator<Section>(_dataModel.sections);
+      _sectionIterator = BiIterator<Section>(_dataModel.sections);
     }
     if (values['feed'] != null && currentSection != null) {
       _feedIterator.jumpToValue(currentSection.findFeed(values['feed']));
     } else {
-      _feedIterator = new BiIterator<Feed>(_sectionIterator.current.feeds);
+      _feedIterator = BiIterator<Feed>(_sectionIterator.current.feeds);
     }
     if (values['article'] != null && currentFeed != null) {
       currentArticle.value = currentFeed.findArticle(values['article']);
       _articleIterator.jumpToValue(currentArticle.value);
     } else {
-      _articleIterator =
-          new BiIterator<Article>(_feedIterator.current.articles);
+      _articleIterator = BiIterator<Article>(_feedIterator.current.articles);
       currentArticle.value = null;
     }
 
     storyMaximized.value = false;
   }
 
-  /**
-   * Move the currentArticle pointer to the next item in the Feed.
-   */
+  /// Move the currentArticle pointer to the next item in the Feed.
   void goToNextArticle() {
     currentArticle.value = _articleIterator.next();
     selectedArticle.value = _articleIterator.current;
   }
 
-  /**
-   * Move the currentArticle pointer to the previous item in the Feed.
-   */
+  /// Move the currentArticle pointer to the previous item in the Feed.
   void goToPreviousArticle() {
     currentArticle.value = _articleIterator.previous();
     selectedArticle.value = _articleIterator.current;
   }
 
-  /**
-   * Move the selectedArticle pointer to the next item in the Feed.
-   */
+  /// Move the selectedArticle pointer to the next item in the Feed.
   void goToNextSelectedArticle() {
     selectedArticle.value = _articleIterator.next();
   }
 
-  /**
-   * Move the selectedArticle pointer to the previous item in the Feed.
-   */
+  /// Move the selectedArticle pointer to the previous item in the Feed.
   void goToPreviousSelectedArticle() {
     selectedArticle.value = _articleIterator.previous();
   }
 
-  /**
-   * Move the pointers for selectedArticle to point to the next
-   * Feed.
-   */
+  /// Move the pointers for selectedArticle to point to the next
+  /// Feed.
   void goToNextFeed() {
     var newFeed = _feedIterator.next();
     int oldIndex = _articleIterator.currentIndex.value;
 
-    _articleIterator = new BiIterator<Article>(
+    _articleIterator = BiIterator<Article>(
         newFeed.articles, _articleIterator.currentIndex.listeners);
 
     _articleIterator.currentIndex.value = oldIndex;
     selectedArticle.value = _articleIterator.current;
   }
 
-  /**
-   * Move the pointers for selectedArticle to point to the previous
-   * DataSource.
-   */
+  /// Move the pointers for selectedArticle to point to the previous
+  /// DataSource.
   void goToPreviousFeed() {
     var newFeed = _feedIterator.previous();
     int oldIndex = _articleIterator.currentIndex.value;
 
-    _articleIterator = new BiIterator<Article>(
+    _articleIterator = BiIterator<Article>(
         newFeed.articles, _articleIterator.currentIndex.listeners);
     _articleIterator.currentIndex.value = oldIndex;
     selectedArticle.value = _articleIterator.current;
   }
 
-  /**
-   * Move to the next section (page) of feeds in the UI.
-   * @param index the previous index (how far down in a given feed)
-   * from the Source we are moving from.
-   * This method takes sliderMenu in the event that it needs to move
-   * to a previous section, it can notify the UI to update.
-   */
+  /// Move to the next section (page) of feeds in the UI.
+  /// @param index the previous index (how far down in a given feed)
+  /// from the Source we are moving from.
+  /// This method takes sliderMenu in the event that it needs to move
+  /// to a previous section, it can notify the UI to update.
   void goToNextSection(SliderMenu sliderMenu) {
     //TODO(efortuna): move sections?
     var oldSection = currentSection;
@@ -195,24 +165,22 @@
     // This check prevents our selector from wrapping around when we try to
     // go to the "next section", but we're already at the last section.
     if (oldSection != _sectionIterator.current) {
-      _feedIterator = new BiIterator<Feed>(
+      _feedIterator = BiIterator<Feed>(
           _sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
-      _articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
+      _articleIterator = BiIterator<Article>(_feedIterator.current.articles,
           _articleIterator.currentIndex.listeners);
       _articleIterator.currentIndex.value = oldIndex;
       selectedArticle.value = _articleIterator.current;
     }
   }
 
-  /**
-   * Move to the previous section (page) of feeds in the UI.
-   * @param index the previous index (how far down in a given feed)
-   * from the Source we are moving from.
-   * @param oldSection the original starting section (before the slider
-   * menu moved)
-   * This method takes sliderMenu in the event that it needs to move
-   * to a previous section, it can notify the UI to update.
-   */
+  /// Move to the previous section (page) of feeds in the UI.
+  /// @param index the previous index (how far down in a given feed)
+  /// from the Source we are moving from.
+  /// @param oldSection the original starting section (before the slider
+  /// menu moved)
+  /// This method takes sliderMenu in the event that it needs to move
+  /// to a previous section, it can notify the UI to update.
   void goToPreviousSection(SliderMenu sliderMenu) {
     //TODO(efortuna): don't pass sliderMenu here. Just update in view!
     var oldSection = currentSection;
@@ -222,72 +190,58 @@
     // This check prevents our selector from wrapping around when we try to
     // go to the "previous section", but we're already at the first section.
     if (oldSection != _sectionIterator.current) {
-      _feedIterator = new BiIterator<Feed>(
+      _feedIterator = BiIterator<Feed>(
           _sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
       // Jump to back of feed set if we are moving backwards through sections.
       _feedIterator.currentIndex.value = _feedIterator.list.length - 1;
-      _articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
+      _articleIterator = BiIterator<Article>(_feedIterator.current.articles,
           _articleIterator.currentIndex.listeners);
       _articleIterator.currentIndex.value = oldIndex;
       selectedArticle.value = _articleIterator.current;
     }
   }
 
-  /**
-   * Set the selected story as the current story (for viewing in the larger
-   * Story View.)
-   */
+  /// Set the selected story as the current story (for viewing in the larger
+  /// Story View.)
   void selectStoryAsCurrent() {
     currentArticle.value = _articleIterator.current;
     selectedArticle.value = _articleIterator.current;
   }
 
-  /**
-   * Remove our currentArticle selection, to move back to the Main Grid view.
-   */
+  /// Remove our currentArticle selection, to move back to the Main Grid view.
   void clearCurrentArticle() {
     currentArticle.value = null;
   }
 
-  /**
-   * Set the selectedArticle as the first item in that section (UI page).
-   */
+  /// Set the selectedArticle as the first item in that section (UI page).
   void goToFirstArticleInSection() {
     selectedArticle.value = _articleIterator.current;
   }
 
-  /**
-   * Returns true if the UI is currently in the Story View state.
-   */
+  /// Returns true if the UI is currently in the Story View state.
   bool get inMainView => currentArticle.value == null;
 
-  /**
-   * Returns true if we currently have an Article selected (for keyboard
-   * shortcuts browsing).
-   */
+  /// Returns true if we currently have an Article selected (for keyboard
+  /// shortcuts browsing).
   bool get hasArticleSelected => selectedArticle.value != null;
 
-  /**
-   * Mark the current article as read
-   */
+  /// Mark the current article as read
   bool markCurrentAsRead() {
     currentArticle.value.unread.value = false;
   }
 
-  /**
-   * The user has moved to a new section (page). This can occur either
-   * if the user clicked on a section page, or used keyboard shortcuts.
-   * The default behavior is to move to the first article in the first
-   * column. The location of the selected item depends on the previous
-   * selected item location if the user used keyboard shortcuts. These
-   * are manipulated in goToPrevious/NextSection().
-   */
+  /// The user has moved to a new section (page). This can occur either
+  /// if the user clicked on a section page, or used keyboard shortcuts.
+  /// The default behavior is to move to the first article in the first
+  /// column. The location of the selected item depends on the previous
+  /// selected item location if the user used keyboard shortcuts. These
+  /// are manipulated in goToPrevious/NextSection().
   void moveToNewSection(String sectionTitle) {
     _sectionIterator.currentIndex.value =
         _dataModel.findSectionIndex(sectionTitle);
-    _feedIterator = new BiIterator<Feed>(
+    _feedIterator = BiIterator<Feed>(
         _sectionIterator.current.feeds, _feedIterator.currentIndex.listeners);
-    _articleIterator = new BiIterator<Article>(_feedIterator.current.articles,
+    _articleIterator = BiIterator<Article>(_feedIterator.current.articles,
         _articleIterator.currentIndex.listeners);
   }
 
diff --git a/samples-dev/swarm/SwarmViews.dart b/samples-dev/swarm/SwarmViews.dart
index 458e4ea..9c9bf1e 100644
--- a/samples-dev/swarm/SwarmViews.dart
+++ b/samples-dev/swarm/SwarmViews.dart
@@ -10,42 +10,35 @@
 // and then doing a large pass to remove functionality that doesn't make sense
 // given the UI layout.
 
-/**
- * Front page of Swarm.
- */
+/// Front page of Swarm.
 // TODO(jacobr): this code now needs a large refactoring.
 // Suggested refactorings:
 //  Move animation specific code into helper classes.
 class FrontView extends CompositeView {
   final Swarm swarm;
 
-  /** View containing all UI anchored to the top of the page. */
+  /// View containing all UI anchored to the top of the page. */
   CompositeView topView;
-  /** View containing all UI anchored to the left side of the page. */
+
+  /// View containing all UI anchored to the left side of the page. */
   CompositeView bottomView;
   HeaderView headerView;
   SliderMenu sliderMenu;
 
-  /**
-   * When the user is viewing a story, the data source for that story is
-   * detached from the section and shown at the bottom of the screen. This keeps
-   * track of that so we can restore it later.
-   */
+  /// When the user is viewing a story, the data source for that story is
+  /// detached from the section and shown at the bottom of the screen. This keeps
+  /// track of that so we can restore it later.
   DataSourceView detachedView;
 
-  /**
-   * Map from section title to the View that shows this section.  This
-   * is populated lazily.
-   */
+  /// Map from section title to the View that shows this section.  This
+  /// is populated lazily.
   StoryContentView storyView;
   bool nextPrevShown;
 
   ConveyorView sections;
 
-  /**
-   * The set of keys that produce a given behavior (going down one story,
-   * navigating to the column to the right, etc).
-   */
+  /// The set of keys that produce a given behavior (going down one story,
+  /// navigating to the column to the right, etc).
   //TODO(jmesserly): we need a key code enumeration
   final Set downKeyPresses;
   final Set upKeyPresses;
@@ -57,22 +50,22 @@
   final Set previousPageKeyPresses;
 
   FrontView(this.swarm)
-      : downKeyPresses = new Set.from([74 /*j*/, 40 /*down*/]),
-        upKeyPresses = new Set.from([75 /*k*/, 38 /*up*/]),
-        rightKeyPresses = new Set.from([39 /*right*/, 68 /*d*/, 76 /*l*/]),
-        leftKeyPresses = new Set.from([37 /*left*/, 65 /*a*/, 72 /*h*/]),
-        openKeyPresses = new Set.from([13 /*enter*/, 79 /*o*/]),
-        backKeyPresses = new Set.from([8 /*delete*/, 27 /*escape*/]),
-        nextPageKeyPresses = new Set.from([78 /*n*/]),
-        previousPageKeyPresses = new Set.from([80 /*p*/]),
+      : downKeyPresses = {74 /*j*/, 40 /*down*/},
+        upKeyPresses = {75 /*k*/, 38 /*up*/},
+        rightKeyPresses = {39 /*right*/, 68 /*d*/, 76 /*l*/},
+        leftKeyPresses = {37 /*left*/, 65 /*a*/, 72 /*h*/},
+        openKeyPresses = {13 /*enter*/, 79 /*o*/},
+        backKeyPresses = {8 /*delete*/, 27 /*escape*/},
+        nextPageKeyPresses = {78 /*n*/},
+        previousPageKeyPresses = {80 /*p*/},
         nextPrevShown = false,
         super('front-view fullpage') {
-    topView = new CompositeView('top-view', false, false, false);
+    topView = CompositeView('top-view', false, false, false);
 
-    headerView = new HeaderView(swarm);
+    headerView = HeaderView(swarm);
     topView.addChild(headerView);
 
-    sliderMenu = new SliderMenu(swarm.sections.sectionTitles, (sectionTitle) {
+    sliderMenu = SliderMenu(swarm.sections.sectionTitles, (sectionTitle) {
       swarm.state.moveToNewSection(sectionTitle);
       _onSectionSelected(sectionTitle);
       // Start with no articles selected.
@@ -81,10 +74,10 @@
     topView.addChild(sliderMenu);
     addChild(topView);
 
-    bottomView = new CompositeView('bottom-view', false, false, false);
+    bottomView = CompositeView('bottom-view', false, false, false);
     addChild(bottomView);
 
-    sections = new ConveyorView();
+    sections = ConveyorView();
     sections.viewSelected = _onSectionTransitionEnded;
   }
 
@@ -98,6 +91,7 @@
     return view;
   }
 
+  @override
   void afterRender(Element node) {
     _createSectionViews();
     attachWatch(swarm.state.currentArticle, (e) {
@@ -116,9 +110,7 @@
     }
   }
 
-  /**
-   * Animates back from the story view to the main grid view.
-   */
+  /// Animates back from the story view to the main grid view.
   void _animateToMainView() {
     sliderMenu.removeClass('hidden');
     storyView.addClass('hidden-story');
@@ -156,7 +148,7 @@
       removeChild(storyView);
 
       // Create the new story view and place in the frame.
-      storyView = addChild(new StoryContentView(swarm, item));
+      storyView = addChild(StoryContentView(swarm, item));
     } else {
       // We are animating from the main view to the story view.
       // TODO(jmesserly): make this code better
@@ -173,16 +165,16 @@
       currentSection.storyMode = true;
 
       // Create the new story view.
-      storyView = new StoryContentView(swarm, item);
-      new Timer(const Duration(milliseconds: 0), () {
+      storyView = StoryContentView(swarm, item);
+      Timer(const Duration(milliseconds: 0), () {
         _animateDataSourceToMinimized();
 
         sliderMenu.addClass('hidden');
         // Make the fancy sliding into the window animation.
-        new Timer(const Duration(milliseconds: 0), () {
+        Timer(const Duration(milliseconds: 0), () {
           storyView.addClass('hidden-story');
           addChild(storyView);
-          new Timer(const Duration(milliseconds: 0), () {
+          Timer(const Duration(milliseconds: 0), () {
             storyView.removeClass('hidden-story');
           });
           headerView.endTransitionToStoryView();
@@ -214,9 +206,7 @@
     }
   }
 
-  /**
-   * Called when the animation to switch to a section has completed.
-   */
+  /// Called when the animation to switch to a section has completed.
   void _onSectionTransitionEnded(SectionView selectedView) {
     // Show the section and hide the others.
     for (SectionView view in sections.childViews) {
@@ -230,10 +220,8 @@
     }
   }
 
-  /**
-   * Called when the user chooses a section on the SliderMenu.  Hides
-   * all views except the one they want to see.
-   */
+  /// Called when the user chooses a section on the SliderMenu.  Hides
+  /// all views except the one they want to see.
   void _onSectionSelected(String sectionTitle) {
     final section = swarm.sections.findSection(sectionTitle);
     // Find the view for this section.
@@ -246,15 +234,13 @@
     }
   }
 
-  /**
-   * Create SectionViews for each Section in the app and add them to the
-   * conveyor. Note that the SectionViews won't actually populate or load data
-   * sources until they are shown in response to [:_onSectionSelected():].
-   */
+  /// Create SectionViews for each Section in the app and add them to the
+  /// conveyor. Note that the SectionViews won't actually populate or load data
+  /// sources until they are shown in response to [:_onSectionSelected():].
   void _createSectionViews() {
     for (final section in swarm.sections) {
-      final viewFactory = new DataSourceViewFactory(swarm);
-      final sectionView = new SectionView(swarm, section, viewFactory);
+      final viewFactory = DataSourceViewFactory(swarm);
+      final sectionView = SectionView(swarm, section, viewFactory);
 
       // TODO(rnystrom): Hack temp. Access node to make sure SectionView has
       // rendered and created scroller. This can go away when event registration
@@ -266,10 +252,8 @@
     addChild(sections);
   }
 
-  /**
-   * Controls the logic of how to respond to keypresses and then update the
-   * UI accordingly.
-   */
+  /// Controls the logic of how to respond to keypresses and then update the
+  /// UI accordingly.
   void processKeyEvent(KeyboardEvent e) {
     int code = e.keyCode;
     if (swarm.state.inMainView) {
@@ -313,7 +297,7 @@
   }
 }
 
-/** Transitions the app back to the main screen. */
+/// Transitions the app back to the main screen. */
 void _backToMain(SwarmState state) {
   if (state.currentArticle.value != null) {
     state.clearCurrentArticle();
@@ -322,14 +306,16 @@
   }
 }
 
-/** A back button that sends the user back to the front page. */
+/// A back button that sends the user back to the front page. */
 class SwarmBackButton extends View {
   Swarm swarm;
 
   SwarmBackButton(this.swarm);
 
-  Element render() => new Element.html('<div class="back-arrow button"></div>');
+  @override
+  Element render() => Element.html('<div class="back-arrow button"></div>');
 
+  @override
   void afterRender(Element node) {
     addOnClick((e) {
       _backToMain(swarm.state);
@@ -337,7 +323,7 @@
   }
 }
 
-/** Top view constaining the title and standard buttons. */
+/// Top view constaining the title and standard buttons. */
 class HeaderView extends CompositeView {
   // TODO(jacobr): make this value be coupled with the CSS file.
   static const HEIGHT = 80;
@@ -357,7 +343,7 @@
   View _newWindowButton;
 
   HeaderView(this.swarm) : super('header-view') {
-    _backButton = addChild(new SwarmBackButton(swarm));
+    _backButton = addChild(SwarmBackButton(swarm));
     _title = addChild(View.div('app-title', 'Swarm'));
     _configButton = addChild(View.div('config button'));
     _refreshButton = addChild(View.div('refresh button'));
@@ -365,11 +351,12 @@
 
     // TODO(rnystrom): No more web/text mode (it's just text) so get rid of
     // these.
-    _webBackButton = addChild(new WebBackButton());
-    _webForwardButton = addChild(new WebForwardButton());
+    _webBackButton = addChild(WebBackButton());
+    _webForwardButton = addChild(WebForwardButton());
     _newWindowButton = addChild(View.div('new-window-button button'));
   }
 
+  @override
   void afterRender(Element node) {
     // Respond to changes to whether the story is being shown as text or web.
     attachWatch(swarm.state.storyTextMode, (e) {
@@ -383,18 +370,18 @@
     // Wire up the events.
     _configButton.addOnClick((e) {
       // Bring up the config dialog.
-      if (this._configDialog == null) {
+      if (_configDialog == null) {
         // TODO(terry): Cleanup, HeaderView shouldn't be tangled with main view.
-        this._configDialog = new ConfigHintDialog(swarm.frontView, () {
-          swarm.frontView.removeChild(this._configDialog);
-          this._configDialog = null;
+        _configDialog = ConfigHintDialog(swarm.frontView, () {
+          swarm.frontView.removeChild(_configDialog);
+          _configDialog = null;
 
           // TODO: Need to push these to the server on a per-user basis.
           // Update the storage now.
           swarm.sections.refresh();
         });
 
-        swarm.frontView.addChild(this._configDialog);
+        swarm.frontView.addChild(_configDialog);
       }
       // TODO(jimhug): Graceful redirection to reader.
     });
@@ -407,16 +394,16 @@
     // On click of the info button, show Dart info page in new window/tab.
     _infoButton.addOnClick((e) {
       // Bring up the config dialog.
-      if (this._infoDialog == null) {
+      if (_infoDialog == null) {
         // TODO(terry): Cleanup, HeaderView shouldn't be tangled with main view.
-        this._infoDialog = new HelpDialog(swarm.frontView, () {
-          swarm.frontView.removeChild(this._infoDialog);
-          this._infoDialog = null;
+        _infoDialog = HelpDialog(swarm.frontView, () {
+          swarm.frontView.removeChild(_infoDialog);
+          _infoDialog = null;
 
           swarm.sections.refresh();
         });
 
-        swarm.frontView.addChild(this._infoDialog);
+        swarm.frontView.addChild(_infoDialog);
       }
     });
 
@@ -429,10 +416,8 @@
     startTransitionToMainView();
   }
 
-  /**
-   * Refreshes whether or not the buttons specific to the display of a story in
-   * the web perspective are visible.
-   */
+  /// Refreshes whether or not the buttons specific to the display of a story in
+  /// the web perspective are visible.
   void refreshWebStoryButtons() {
     bool webButtonsHidden = true;
 
@@ -467,70 +452,73 @@
   }
 }
 
-/** A back button for the web view of a story that is equivalent to clicking
- * "back" in the browser. */
+/// A back button for the web view of a story that is equivalent to clicking
+/// "back" in the browser. */
 // TODO(rnystrom): We have nearly identical versions of this littered through
 // the sample apps. Should consolidate into one.
 class WebBackButton extends View {
   WebBackButton();
 
+  @override
   Element render() {
-    return new Element.html('<div class="web-back-button button"></div>');
+    return Element.html('<div class="web-back-button button"></div>');
   }
 
+  @override
   void afterRender(Element node) {
     addOnClick((e) {
       back();
     });
   }
 
-  /** Equivalent to [window.history.back] */
+  /// Equivalent to [window.history.back] */
   static void back() {
     window.history.back();
   }
 }
 
-/** A back button for the web view of a story that is equivalent to clicking
- * "forward" in the browser. */
+/// A back button for the web view of a story that is equivalent to clicking
+/// "forward" in the browser. */
 // TODO(rnystrom): We have nearly identical versions of this littered through
 // the sample apps. Should consolidate into one.
 class WebForwardButton extends View {
   WebForwardButton();
 
+  @override
   Element render() {
-    return new Element.html('<div class="web-forward-button button"></div>');
+    return Element.html('<div class="web-forward-button button"></div>');
   }
 
+  @override
   void afterRender(Element node) {
     addOnClick((e) {
       forward();
     });
   }
 
-  /** Equivalent to [window.history.forward] */
+  /// Equivalent to [window.history.forward] */
   static void forward() {
     window.history.forward();
   }
 }
 
-/**
- * A factory that creates a view for data sources.
- */
+/// A factory that creates a view for data sources.
 class DataSourceViewFactory implements ViewFactory<Feed> {
   Swarm swarm;
 
-  DataSourceViewFactory(this.swarm) {}
+  DataSourceViewFactory(this.swarm);
 
-  View newView(Feed data) => new DataSourceView(data, swarm);
+  @override
+  View newView(Feed data) => DataSourceView(data, swarm);
 
+  @override
   int get width => ArticleViewLayout.getSingleton().width;
+  @override
   int get height => null; // Width for this view isn't known.
 }
 
-/**
- * A view for the items from a single data source.
- * Shows a title and a list of items.
- */
+/// A view for the items from a single data source.
+/// Shows a title and a list of items.
 class DataSourceView extends CompositeView {
   // TODO(jacobr): make this value be coupled with the CSS file.
   static const TAB_ONLY_HEIGHT = 34;
@@ -541,12 +529,12 @@
   DataSourceView(this.source, Swarm swarm) : super('query') {
     // TODO(jacobr): make the title a view or decide it is sane for a subclass
     // of component view to manually add some DOM cruft.
-    node.nodes.add(new Element.html('<h2>${source.title}</h2>'));
+    node.nodes.add(Element.html('<h2>${source.title}</h2>'));
 
     // TODO(jacobr): use named arguments when available.
-    itemsView = addChild(new VariableSizeListView<Article>(
+    itemsView = addChild(VariableSizeListView<Article>(
         source.articles,
-        new ArticleViewFactory(swarm),
+        ArticleViewFactory(swarm),
         true,
         /* scrollable */
         true,
@@ -559,7 +547,7 @@
         !Device.supportsTouch /* showScrollbar */));
     itemsView.addClass('story-section');
 
-    node.nodes.add(new Element.html('<div class="query-name-shadow"></div>'));
+    node.nodes.add(Element.html('<div class="query-name-shadow"></div>'));
 
     // Clicking the view (i.e. its title area) unmaximizes to show the entire
     // view.
@@ -569,15 +557,17 @@
   }
 }
 
-/** A button that toggles between states. */
+/// A button that toggles between states. */
 class ToggleButton extends View {
   EventListeners onChanged;
   List<String> states;
 
-  ToggleButton(this.states) : onChanged = new EventListeners();
+  ToggleButton(this.states) : onChanged = EventListeners();
 
-  Element render() => new Element.tag('button');
+  @override
+  Element render() => Element.tag('button');
 
+  @override
   void afterRender(Element node) {
     state = states[0];
     node.onClick.listen((event) {
@@ -587,12 +577,12 @@
 
   String get state {
     final currentState = node.innerHtml;
-    assert(states.indexOf(currentState, 0) >= 0);
+    assert(states.contains(currentState));
     return currentState;
   }
 
-  void set state(String state) {
-    assert(states.indexOf(state, 0) >= 0);
+  set state(String state) {
+    assert(states.contains(state));
     node.innerHtml = state;
     onChanged.fire(null);
   }
@@ -605,18 +595,19 @@
   }
 }
 
-/**
- * A factory that creates a view for generic items.
- */
+/// A factory that creates a view for generic items.
 class ArticleViewFactory implements VariableSizeViewFactory<Article> {
   Swarm swarm;
 
   ArticleViewLayout layout;
   ArticleViewFactory(this.swarm) : layout = ArticleViewLayout.getSingleton();
 
-  View newView(Article item) => new ArticleView(item, swarm, layout);
+  @override
+  View newView(Article item) => ArticleView(item, swarm, layout);
 
+  @override
   int getWidth(Article item) => layout.width;
+  @override
   int getHeight(Article item) => layout.computeHeight(item);
 }
 
@@ -650,16 +641,14 @@
   int width;
   static ArticleViewLayout _singleton;
   ArticleViewLayout()
-      : measureBodyText = new MeasureText(BODY_FONT),
-        measureTitleText = new MeasureText(TITLE_FONT) {
+      : measureBodyText = MeasureText(BODY_FONT),
+        measureTitleText = MeasureText(TITLE_FONT) {
     num screenWidth = window.screen.width;
     width = DESKTOP_WIDTH;
   }
 
   static ArticleViewLayout getSingleton() {
-    if (_singleton == null) {
-      _singleton = new ArticleViewLayout();
-    }
+    _singleton ??= ArticleViewLayout();
     return _singleton;
   }
 
@@ -673,10 +662,8 @@
     return computeLayout(item, null, null).height;
   }
 
-  /**
-   * titleContainer and snippetContainer may be null in which case the size is
-   * computed but no actual layout is performed.
-   */
+  /// titleContainer and snippetContainer may be null in which case the size is
+  /// computed but no actual layout is performed.
   ArticleViewMetrics computeLayout(
       Article item, StringBuffer titleBuffer, StringBuffer snippetBuffer) {
     int titleWidth = width - BODY_MARGIN_LEFT;
@@ -696,13 +683,11 @@
       height = 92;
     }
 
-    return new ArticleViewMetrics(height, titleLines, bodyLines);
+    return ArticleViewMetrics(height, titleLines, bodyLines);
   }
 }
 
-/**
- * A view for a generic item.
- */
+/// A view for a generic item.
 class ArticleView extends View {
   // Set to false to make inspecting the HTML more pleasant...
   static const SAVE_IMAGES = false;
@@ -713,10 +698,11 @@
 
   ArticleView(this.item, this.swarm, this.articleLayout);
 
+  @override
   Element render() {
     Element node;
 
-    final byline = item.author.length > 0 ? item.author : item.dataSource.title;
+    final byline = item.author.isNotEmpty ? item.author : item.dataSource.title;
     final date = DateUtils.toRecentTimeString(item.date);
 
     String storyClass = 'story no-thumb';
@@ -727,13 +713,13 @@
       thumbnail = '<img src="${item.thumbUrl}"></img>';
     }
 
-    final title = new StringBuffer();
-    final snippet = new StringBuffer();
+    final title = StringBuffer();
+    final snippet = StringBuffer();
 
     // Note: also populates title and snippet elements.
     final metrics = articleLayout.computeLayout(item, title, snippet);
 
-    node = new Element.html('''
+    node = Element.html('''
 <div class="$storyClass">
   $thumbnail
   <div class="title">$title</div>
@@ -751,6 +737,7 @@
     return node;
   }
 
+  @override
   void afterRender(Element node) {
     // Select this view's item.
     addOnClick((e) {
@@ -789,10 +776,8 @@
     });
   }
 
-  /**
-   * Notify the view to jump to a different area if we are selecting an
-   * article that is currently outside of the visible area.
-   */
+  /// Notify the view to jump to a different area if we are selecting an
+  /// article that is currently outside of the visible area.
   void _updateViewForSelectedArticle() {
     Article selArticle = swarm.state.selectedArticle.value;
     if (swarm.state.hasArticleSelected) {
@@ -818,7 +803,7 @@
   String getDataUriForImage(final img) {
     // TODO(hiltonc,jimhug) eval perf of this vs. reusing one canvas element
     final CanvasElement canvas =
-        new CanvasElement(height: img.height, width: img.width);
+        CanvasElement(height: img.height, width: img.width);
 
     final CanvasRenderingContext2D ctx = canvas.getContext("2d");
     ctx.drawImageScaled(img, 0, 0, img.width, img.height);
@@ -826,10 +811,8 @@
     return canvas.toDataUrl("image/png");
   }
 
-  /**
-   * Update this view's selected appearance based on the currently selected
-   * Article.
-   */
+  /// Update this view's selected appearance based on the currently selected
+  /// Article.
   void _refreshSelected(curItem) {
     if (curItem.value == item) {
       addClass('sel');
@@ -843,10 +826,8 @@
   }
 }
 
-/**
- * An internal view of a story as text. In other words, the article is shown
- * in-place as opposed to as an embedded web-page.
- */
+/// An internal view of a story as text. In other words, the article is shown
+/// in-place as opposed to as an embedded web-page.
 class StoryContentView extends View {
   final Swarm swarm;
   final Article item;
@@ -855,16 +836,18 @@
 
   StoryContentView(this.swarm, this.item);
 
+  @override
   get childViews => [_pagedStory];
 
+  @override
   Element render() {
     final storyContent =
-        new Element.html('<div class="story-content">${item.htmlBody}</div>');
+        Element.html('<div class="story-content">${item.htmlBody}</div>');
     for (Element element in storyContent.querySelectorAll(
         "iframe, script, style, object, embed, frameset, frame")) {
       element.remove();
     }
-    _pagedStory = new PagedContentView(new View.fromNode(storyContent));
+    _pagedStory = PagedContentView(View.fromNode(storyContent));
 
     // Modify all links to open in new windows....
     // TODO(jacobr): would it be better to add an event listener on click that
@@ -874,7 +857,7 @@
     }
 
     final date = DateUtils.toRecentTimeString(item.date);
-    final container = new Element.html('''
+    final container = Element.html('''
       <div class="story-view">
         <div class="story-text-view">
           <div class="story-header">
@@ -906,22 +889,20 @@
   final PageState pageState;
 
   SectionView(this.swarm, this.section, this._viewFactory)
-      : loadingText = new View.html('<div class="loading-section"></div>'),
-        pageState = new PageState(),
+      : loadingText = View.html('<div class="loading-section"></div>'),
+        pageState = PageState(),
         super('section-view') {
     addChild(loadingText);
   }
 
-  /**
-   * Hides the loading text, reloads the data sources, and shows them.
-   */
+  /// Hides the loading text, reloads the data sources, and shows them.
   void showSources() {
     loadingText.node.style.display = 'none';
 
     // Lazy initialize the data source view.
     if (dataSourceView == null) {
       // TODO(jacobr): use named arguments when available.
-      dataSourceView = new ListView<Feed>(
+      dataSourceView = ListView<Feed>(
           section.feeds,
           _viewFactory,
           true /* scrollable */,
@@ -936,7 +917,7 @@
       dataSourceView.addClass("data-source-view");
       addChild(dataSourceView);
 
-      pageNumberView = addChild(new PageNumberView(pageState));
+      pageNumberView = addChild(PageNumberView(pageState));
 
       node.style.opacity = '1';
     } else {
@@ -949,9 +930,7 @@
     dataSourceView.scroller.reconfigure(() {});
   }
 
-  /**
-   * Hides the data sources and shows the loading text.
-   */
+  /// Hides the data sources and shows the loading text.
   void hideSources() {
     if (dataSourceView != null) {
       node.style.opacity = '0.6';
@@ -970,10 +949,8 @@
     }
   }
 
-  /**
-   * Find the [DataSourceView] in this SectionView that's displaying the given
-   * [Feed].
-   */
+  /// Find the [DataSourceView] in this SectionView that's displaying the given
+  /// [Feed].
   DataSourceView findView(Feed dataSource) {
     return dataSourceView.getSubview(dataSourceView.findIndex(dataSource));
   }
diff --git a/samples-dev/swarm/UIState.dart b/samples-dev/swarm/UIState.dart
index 8d7ce1c..ebab171 100644
--- a/samples-dev/swarm/UIState.dart
+++ b/samples-dev/swarm/UIState.dart
@@ -6,14 +6,10 @@
 
 part of swarmlib;
 
-/**
- * The base class for UI state that intends to support browser history.
- */
+/// The base class for UI state that intends to support browser history.
 abstract class UIState {
-  /**
-   * The event listener we hook to the window's "popstate" event.
-   * This event is triggered by the back button or by the first page load.
-   */
+  /// The event listener we hook to the window's "popstate" event.
+  /// This event is triggered by the back button or by the first page load.
   StreamSubscription _historyTracking;
 
   UIState();
@@ -51,7 +47,7 @@
     }
   }
 
-  /** Pushes a state onto the browser history stack */
+  /// Pushes a state onto the browser history stack */
   void pushToHistory() {
     if (_historyTracking == null) {
       throw 'history tracking not started';
@@ -62,17 +58,12 @@
     // TODO(jmesserly): [state] should be an Object, and we should pass it to
     // the state parameter instead of as a #hash URL. Right now we're working
     //  around b/4582542.
-    window.history
-        .pushState(null, '${document.title}', '${document.title}#$state');
+    window.history.pushState(null, document.title, '${document.title}#$state');
   }
 
-  /**
-   * Serialize the state to a form suitable for storing in browser history.
-   */
+  /// Serialize the state to a form suitable for storing in browser history.
   Map<String, String> toHistory();
 
-  /**
-   * Load the UI state from the given [values].
-   */
+  /// Load the UI state from the given [values].
   void loadFromHistory(Map<String, String> values);
 }
diff --git a/samples-dev/swarm/Views.dart b/samples-dev/swarm/Views.dart
index 0588357..db3ae0d 100644
--- a/samples-dev/swarm/Views.dart
+++ b/samples-dev/swarm/Views.dart
@@ -9,32 +9,32 @@
 // This file contains View framework classes.
 // As it grows, it may need to be split into multiple files.
 
-/** A factory that creates a view from a data model. */
+/// A factory that creates a view from a data model. */
 abstract class ViewFactory<D> {
   View newView(D item);
 
-  /** The width of the created view or null if the width is not fixed. */
+  /// The width of the created view or null if the width is not fixed. */
   int get width;
 
-  /** The height of the created view or null if the height is not fixed. */
+  /// The height of the created view or null if the height is not fixed. */
   int get height;
 }
 
 abstract class VariableSizeViewFactory<D> {
   View newView(D item);
 
-  /** The width of the created view for a specific data model. */
+  /// The width of the created view for a specific data model. */
   int getWidth(D item);
 
-  /** The height of the created view for a specific data model. */
+  /// The height of the created view for a specific data model. */
   int getHeight(D item);
 }
 
-/** A collection of event listeners. */
+/// A collection of event listeners. */
 class EventListeners {
   var listeners;
   EventListeners() {
-    listeners = new List();
+    listeners = [];
   }
 
   void addListener(listener) {
@@ -48,67 +48,61 @@
   }
 }
 
-/**
- * Private view class used to store placeholder views for detached ListView
- * elements.
- */
+/// Private view class used to store placeholder views for detached ListView
+/// elements.
 class _PlaceholderView extends View {
   _PlaceholderView();
 
-  Element render() => new Element.tag('div');
+  @override
+  Element render() => Element.tag('div');
 }
 
-/**
- * Class providing all metrics required to layout a data driven list view.
- */
+/// Class providing all metrics required to layout a data driven list view.
 abstract class ListViewLayout<D> {
   void onDataChange();
 
   // TODO(jacobr): placing the newView member function on this class seems like
   // the wrong design.
   View newView(int index);
-  /** Get the height of the view. Possibly expensive to compute. */
+
+  /// Get the height of the view. Possibly expensive to compute. */
   int getHeight(int viewLength);
-  /** Get the width of the view. Possibly expensive to compute. */
+
+  /// Get the width of the view. Possibly expensive to compute. */
   int getWidth(int viewLength);
-  /** Get the length of the view. Possible expensive to compute. */
+
+  /// Get the length of the view. Possible expensive to compute. */
   int getLength(int viewLength);
-  /** Estimated height of the view. Guaranteed to be fast to compute. */
+
+  /// Estimated height of the view. Guaranteed to be fast to compute. */
   int getEstimatedHeight(int viewLength);
-  /** Estimated with of the view. Guaranteed to be fast to compute. */
+
+  /// Estimated with of the view. Guaranteed to be fast to compute. */
   int getEstimatedWidth(int viewLength);
 
-  /**
-   * Returns the offset in px that the ith item in the view should be placed
-   * at.
-   */
+  /// Returns the offset in px that the ith item in the view should be placed
+  /// at.
   int getOffset(int index);
 
-  /**
-   * The page the ith item in the view should be placed in.
-   */
+  /// The page the ith item in the view should be placed in.
   int getPage(int index, int viewLength);
   int getPageStartIndex(int index, int viewLength);
 
   int getEstimatedLength(int viewLength);
-  /**
-   * Snap a specified index to the nearest visible view given the [viewLength].
-   */
+
+  /// Snap a specified index to the nearest visible view given the [viewLength].
   int getSnapIndex(num offset, num viewLength);
-  /**
-   * Returns an interval specifying what views are currently visible given a
-   * particular [:offset:].
-   */
+
+  /// Returns an interval specifying what views are currently visible given a
+  /// particular [:offset:].
   Interval computeVisibleInterval(num offset, num viewLength, num bufferLength);
 }
 
-/**
- * Base class used for the simple fixed size item [:ListView:] classes and more
- * complex list view classes such as [:VariableSizeListView:] using a
- * [:ListViewLayout:] class to drive the actual layout.
- */
+/// Base class used for the simple fixed size item [:ListView:] classes and more
+/// complex list view classes such as [:VariableSizeListView:] using a
+/// [:ListViewLayout:] class to drive the actual layout.
 class GenericListView<D> extends View {
-  /** Minimum throw distance in pixels to trigger snapping to the next item. */
+  /// Minimum throw distance in pixels to trigger snapping to the next item. */
   static const SNAP_TO_NEXT_THROW_THRESHOLD = 15;
 
   static const INDEX_DATA_ATTRIBUTE = 'data-index';
@@ -118,25 +112,24 @@
   final bool _snapToItems;
   Scroller scroller;
   Scrollbar _scrollbar;
-  List<D> _data;
-  ObservableValue<D> _selectedItem;
-  Map<int, View> _itemViews;
+  final List<D> _data;
+  final ObservableValue<D> _selectedItem;
+  final Map<int, View> _itemViews;
   Element _containerElem;
-  bool _vertical;
-  /** Length of the scrollable dimension of the view in px. */
+  final bool _vertical;
+
+  /// Length of the scrollable dimension of the view in px. */
   int _viewLength = 0;
   Interval _activeInterval;
-  bool _paginate;
-  bool _removeClippedViews;
-  ListViewLayout<D> _layout;
+  final bool _paginate;
+  final bool _removeClippedViews;
+  final ListViewLayout<D> _layout;
   D _lastSelectedItem;
-  PageState _pages;
+  final PageState _pages;
 
-  /**
-   * Creates a new GenericListView with the given layout and data. If [:_data:]
-   * is an [:ObservableList<T>:] then it will listen to changes to the list
-   * and update the view appropriately.
-   */
+  /// Creates a new GenericListView with the given layout and data. If [:_data:]
+  /// is an [:ObservableList<T>:] then it will listen to changes to the list
+  /// and update the view appropriately.
   GenericListView(
       this._layout,
       this._data,
@@ -148,8 +141,8 @@
       this._removeClippedViews,
       this._showScrollbar,
       this._pages)
-      : _activeInterval = new Interval(0, 0),
-        _itemViews = new Map<int, View>() {
+      : _activeInterval = Interval(0, 0),
+        _itemViews = <int, View>{} {
     // TODO(rnystrom): Move this into enterDocument once we have an exitDocument
     // that we can use to unregister it.
     if (_scrollable) {
@@ -169,6 +162,7 @@
     _lastSelectedItem = _selectedItem.value;
   }
 
+  @override
   Iterable<View> get childViews {
     return _itemViews.values.toList();
   }
@@ -194,16 +188,17 @@
   int _nodeToIndex(Element node) {
     // TODO(jacobr): use data attributes when available.
     String index = node.attributes[INDEX_DATA_ATTRIBUTE];
-    if (index != null && index.length > 0) {
+    if (index != null && index.isNotEmpty) {
       return int.parse(index);
     }
     return null;
   }
 
+  @override
   Element render() {
-    final node = new Element.tag('div');
+    final node = Element.tag('div');
     if (_scrollable) {
-      _containerElem = new Element.tag('div');
+      _containerElem = Element.tag('div');
       _containerElem.tabIndex = -1;
       node.nodes.add(_containerElem);
     } else {
@@ -211,16 +206,16 @@
     }
 
     if (_scrollable) {
-      scroller = new Scroller(
+      scroller = Scroller(
           _containerElem,
           _vertical /* verticalScrollEnabled */,
           !_vertical /* horizontalScrollEnabled */,
           true /* momentumEnabled */, () {
         num width = _layout.getWidth(_viewLength);
         num height = _layout.getHeight(_viewLength);
-        width = width != null ? width : 0;
-        height = height != null ? height : 0;
-        return new Size(width, height);
+        width = width ?? 0;
+        height = height ?? 0;
+        return Size(width, height);
       },
           _paginate && _snapToItems
               ? Scroller.FAST_SNAP_DECELERATION_FACTOR
@@ -235,7 +230,7 @@
         scroller.onScrollerDragEnd.listen((e) => _decelStart());
       }
       if (_showScrollbar) {
-        _scrollbar = new Scrollbar(scroller, true);
+        _scrollbar = Scrollbar(scroller, true);
       }
     } else {
       _reserveArea();
@@ -245,6 +240,7 @@
     return node;
   }
 
+  @override
   void afterRender(Element node) {
     // If our data source is observable, observe it.
     if (_data is ObservableList<D>) {
@@ -300,6 +296,7 @@
     });
   }
 
+  @override
   void enterDocument() {
     if (scroller != null) {
       onResize();
@@ -361,7 +358,7 @@
       _removeView(i);
     }
     _itemViews.clear();
-    _activeInterval = new Interval(0, 0);
+    _activeInterval = Interval(0, 0);
     if (scroller == null) {
       _reserveArea();
     }
@@ -381,9 +378,7 @@
         : scroller.getHorizontalOffset();
   }
 
-  /**
-   * Calculates visible interval, based on the scroller position.
-   */
+  /// Calculates visible interval, based on the scroller position.
   Interval getVisibleInterval() {
     return _layout.computeVisibleInterval(_offset, _viewLength, 0);
   }
@@ -394,14 +389,14 @@
       targetInterval = getVisibleInterval();
     } else {
       // If the view is not scrollable, render all elements.
-      targetInterval = new Interval(0, _data.length);
+      targetInterval = Interval(0, _data.length);
     }
 
     if (_pages != null) {
       _pages.current.value = _layout.getPage(targetInterval.start, _viewLength);
     }
     if (_pages != null) {
-      _pages.length.value = _data.length > 0
+      _pages.length.value = _data.isNotEmpty
           ? _layout.getPage(_data.length - 1, _viewLength) + 1
           : 0;
     }
@@ -450,7 +445,7 @@
   void _removeView(int index) {
     // Do not remove placeholder views as they need to stay present in case
     // they scroll out of view and then back into view.
-    if (!(_itemViews[index] is _PlaceholderView)) {
+    if (_itemViews[index] is! _PlaceholderView) {
       // Remove from the active DOM but don't destroy.
       _itemViews[index].node.remove();
       childViewRemoved(_itemViews[index]);
@@ -495,10 +490,8 @@
     }
   }
 
-  /**
-   * Detach a subview from the view replacing it with an empty placeholder view.
-   * The detached subview can be safely reparented.
-   */
+  /// Detach a subview from the view replacing it with an empty placeholder view.
+  /// The detached subview can be safely reparented.
   View detachSubview(D itemData) {
     int index = findIndex(itemData);
     View view = _itemViews[index];
@@ -509,22 +502,20 @@
       _addView(index);
       view = _itemViews[index];
     }
-    final placeholder = new _PlaceholderView();
+    final placeholder = _PlaceholderView();
     view.node.replaceWith(placeholder.node);
     _itemViews[index] = placeholder;
     return view;
   }
 
-  /**
-   * Reattach a subview from the view that was detached from the view
-   * by calling detachSubview. [callback] is called once the subview is
-   * reattached and done animating into position.
-   */
+  /// Reattach a subview from the view that was detached from the view
+  /// by calling detachSubview. [callback] is called once the subview is
+  /// reattached and done animating into position.
   void reattachSubview(D data, View view, bool animate) {
     int index = findIndex(data);
     // TODO(jacobr): perform some validation that the view is
     // really detached.
-    var currentPosition;
+    Coordinate currentPosition;
     if (animate) {
       currentPosition =
           FxUtil.computeRelativePosition(view.node, _containerElem);
@@ -614,14 +605,16 @@
 class FixedSizeListViewLayout<D> implements ListViewLayout<D> {
   final ViewFactory<D> itemViewFactory;
   final bool _vertical;
-  List<D> _data;
-  bool _paginate;
+  final List<D> _data;
+  final bool _paginate;
 
   FixedSizeListViewLayout(
       this.itemViewFactory, this._data, this._vertical, this._paginate);
 
+  @override
   void onDataChange() {}
 
+  @override
   View newView(int index) {
     return itemViewFactory.newView(_data[index]);
   }
@@ -630,35 +623,41 @@
     return _vertical ? itemViewFactory.height : itemViewFactory.width;
   }
 
+  @override
   int getWidth(int viewLength) {
     return _vertical ? itemViewFactory.width : getLength(viewLength);
   }
 
+  @override
   int getHeight(int viewLength) {
     return _vertical ? getLength(viewLength) : itemViewFactory.height;
   }
 
+  @override
   int getEstimatedHeight(int viewLength) {
     // Returns the exact height as it is trivial to compute for this layout.
     return getHeight(viewLength);
   }
 
+  @override
   int getEstimatedWidth(int viewLength) {
     // Returns the exact height as it is trivial to compute for this layout.
     return getWidth(viewLength);
   }
 
+  @override
   int getEstimatedLength(int viewLength) {
     // Returns the exact length as it is trivial to compute for this layout.
     return getLength(viewLength);
   }
 
+  @override
   int getLength(int viewLength) {
     int itemLength = _vertical ? itemViewFactory.height : itemViewFactory.width;
     if (viewLength == null || viewLength == 0) {
       return itemLength * _data.length;
     } else if (_paginate) {
-      if (_data.length > 0) {
+      if (_data.isNotEmpty) {
         final pageLength = getPageLength(viewLength);
         return getPage(_data.length - 1, viewLength) * pageLength +
             Math.max(viewLength, pageLength);
@@ -670,6 +669,7 @@
     }
   }
 
+  @override
   int getOffset(int index) {
     return index * _itemLength;
   }
@@ -679,14 +679,17 @@
     return Math.max(1, itemsPerPage) * _itemLength;
   }
 
+  @override
   int getPage(int index, int viewLength) {
     return getOffset(index) ~/ getPageLength(viewLength);
   }
 
+  @override
   int getPageStartIndex(int page, int viewLength) {
     return getPageLength(viewLength) ~/ _itemLength * page;
   }
 
+  @override
   int getSnapIndex(num offset, num viewLength) {
     int index = (-offset / _itemLength).round();
     if (_paginate) {
@@ -695,6 +698,7 @@
     return GoogleMath.clamp(index, 0, _data.length - 1);
   }
 
+  @override
   Interval computeVisibleInterval(
       num offset, num viewLength, num bufferLength) {
     int targetIntervalStart =
@@ -703,28 +707,24 @@
         ((-offset + viewLength + bufferLength) / _itemLength).ceil(),
         targetIntervalStart,
         _data.length);
-    return new Interval(targetIntervalStart, targetIntervalEnd.toInt());
+    return Interval(targetIntervalStart, targetIntervalEnd.toInt());
   }
 }
 
-/**
- * Simple list view class where each item has fixed width and height.
- */
+/// Simple list view class where each item has fixed width and height.
 class ListView<D> extends GenericListView<D> {
-  /**
-   * Creates a new ListView for the given data. If [:_data:] is an
-   * [:ObservableList<T>:] then it will listen to changes to the list and
-   * update the view appropriately.
-   */
+  /// Creates a new ListView for the given data. If [:_data:] is an
+  /// [:ObservableList<T>:] then it will listen to changes to the list and
+  /// update the view appropriately.
   ListView(List<D> data, ViewFactory<D> itemViewFactory, bool scrollable,
       bool vertical, ObservableValue<D> selectedItem,
       [bool snapToItems = false,
       bool paginate = false,
       bool removeClippedViews = false,
       bool showScrollbar = false,
-      PageState pages = null])
+      PageState pages])
       : super(
-            new FixedSizeListViewLayout<D>(
+            FixedSizeListViewLayout<D>(
                 itemViewFactory, data, vertical, paginate),
             data,
             scrollable,
@@ -737,37 +737,38 @@
             pages);
 }
 
-/**
- * Layout where each item may have variable size along the axis the list view
- * extends.
- */
+/// Layout where each item may have variable size along the axis the list view
+/// extends.
 class VariableSizeListViewLayout<D> implements ListViewLayout<D> {
-  List<D> _data;
+  final List<D> _data;
   List<int> _itemOffsets;
   List<int> _lengths;
   int _lastOffset = 0;
-  bool _vertical;
-  bool _paginate;
+  final bool _vertical;
+  final bool _paginate;
   VariableSizeViewFactory<D> itemViewFactory;
   Interval _lastVisibleInterval;
 
   VariableSizeListViewLayout(
       this.itemViewFactory, data, this._vertical, this._paginate)
       : _data = data,
-        _lastVisibleInterval = new Interval(0, 0) {
+        _lastVisibleInterval = Interval(0, 0) {
     _itemOffsets = <int>[];
     _lengths = <int>[];
     _itemOffsets.add(0);
   }
 
+  @override
   void onDataChange() {
     _itemOffsets.clear();
     _itemOffsets.add(0);
     _lengths.clear();
   }
 
+  @override
   View newView(int index) => itemViewFactory.newView(_data[index]);
 
+  @override
   int getWidth(int viewLength) {
     if (_vertical) {
       return itemViewFactory.getWidth(null);
@@ -776,6 +777,7 @@
     }
   }
 
+  @override
   int getHeight(int viewLength) {
     if (_vertical) {
       return getLength(viewLength);
@@ -784,6 +786,7 @@
     }
   }
 
+  @override
   int getEstimatedHeight(int viewLength) {
     if (_vertical) {
       return getEstimatedLength(viewLength);
@@ -792,6 +795,7 @@
     }
   }
 
+  @override
   int getEstimatedWidth(int viewLength) {
     if (_vertical) {
       return itemViewFactory.getWidth(null);
@@ -802,12 +806,13 @@
 
   // TODO(jacobr): this logic is overly complicated. Replace with something
   // simpler.
+  @override
   int getEstimatedLength(int viewLength) {
     if (_lengths.length == _data.length) {
       // No need to estimate... we have all the data already.
       return getLength(viewLength);
     }
-    if (_itemOffsets.length > 1 && _lengths.length > 0) {
+    if (_itemOffsets.length > 1 && _lengths.isNotEmpty) {
       // Estimate length by taking the average of the lengths
       // of the known views.
       num lengthFromAllButLastElement = 0;
@@ -828,8 +833,9 @@
     }
   }
 
+  @override
   int getLength(int viewLength) {
-    if (_data.length == 0) {
+    if (_data.isEmpty) {
       return viewLength;
     } else {
       // Hack so that _lengths[length - 1] is available.
@@ -839,6 +845,7 @@
     }
   }
 
+  @override
   int getOffset(int index) {
     if (index >= _itemOffsets.length) {
       int offset = _itemOffsets[_itemOffsets.length - 1];
@@ -854,16 +861,19 @@
     return _itemOffsets[index];
   }
 
+  @override
   int getPage(int index, int viewLength) {
     // TODO(jacobr): implement.
     throw 'Not implemented';
   }
 
+  @override
   int getPageStartIndex(int page, int viewLength) {
     // TODO(jacobr): implement.
     throw 'Not implemented';
   }
 
+  @override
   int getSnapIndex(num offset, num viewLength) {
     for (int i = 1; i < _data.length; i++) {
       if (getOffset(i) + getOffset(i - 1) > -offset * 2) {
@@ -873,6 +883,7 @@
     return _data.length - 1;
   }
 
+  @override
   Interval computeVisibleInterval(
       num offset, num viewLength, num bufferLength) {
     offset = offset.toInt();
@@ -880,7 +891,7 @@
         _lastVisibleInterval != null ? _lastVisibleInterval.start : 0);
     int end = _findFirstItemAfter(-offset + viewLength + bufferLength,
         _lastVisibleInterval != null ? _lastVisibleInterval.end : 0);
-    _lastVisibleInterval = new Interval(start, Math.max(start, end));
+    _lastVisibleInterval = Interval(start, Math.max(start, end));
     _lastOffset = offset;
     return _lastVisibleInterval;
   }
@@ -914,9 +925,9 @@
       bool paginate = false,
       bool removeClippedViews = false,
       bool showScrollbar = false,
-      PageState pages = null])
+      PageState pages])
       : super(
-            new VariableSizeListViewLayout(
+            VariableSizeListViewLayout(
                 itemViewFactory, data, vertical, paginate),
             data,
             scrollable,
@@ -929,19 +940,21 @@
             pages);
 }
 
-/** A back button that is equivalent to clicking "back" in the browser. */
+/// A back button that is equivalent to clicking "back" in the browser. */
 class BackButton extends View {
   BackButton();
 
-  Element render() => new Element.html('<div class="back-arrow button"></div>');
+  @override
+  Element render() => Element.html('<div class="back-arrow button"></div>');
 
+  @override
   void afterRender(Element node) {
     addOnClick((e) => window.history.back());
   }
 }
 
 // TODO(terry): Maybe should be part of ButtonView class in appstack/view?
-/** OS button. */
+/// OS button. */
 class PushButtonView extends View {
   final String _text;
   final String _cssClass;
@@ -949,10 +962,12 @@
 
   PushButtonView(this._text, this._cssClass, this._clickHandler);
 
+  @override
   Element render() {
-    return new Element.html('<button class="${_cssClass}">${_text}</button>');
+    return Element.html('<button class="$_cssClass">$_text</button>');
   }
 
+  @override
   void afterRender(Element node) {
     addOnClick(_clickHandler);
   }
@@ -961,7 +976,7 @@
 // TODO(terry): Add a drop shadow around edge and corners need to be rounded.
 //              Need to support conveyor for contents of dialog so it's not
 //              larger than the parent window.
-/** A generic dialog view supports title, done button and dialog content. */
+/// A generic dialog view supports title, done button and dialog content. */
 class DialogView extends View {
   final String _title;
   final String _cssName;
@@ -971,8 +986,9 @@
 
   DialogView(this._title, this._cssName, this._content);
 
+  @override
   Element render() {
-    final node = new Element.html('''
+    final node = Element.html('''
       <div class="dialog-modal">
         <div class="dialog $_cssName">
           <div class="dialog-title-area">
@@ -982,8 +998,8 @@
         </div>
       </div>''');
 
-    _done = new PushButtonView(
-        'Done', 'done-button', EventBatch.wrap((e) => onDone()));
+    _done =
+        PushButtonView('Done', 'done-button', EventBatch.wrap((e) => onDone()));
     final titleArea = node.querySelector('.dialog-title-area');
     titleArea.nodes.add(_done.node);
 
@@ -993,6 +1009,6 @@
     return node;
   }
 
-  /** Override to handle dialog done. */
+  /// Override to handle dialog done. */
   void onDone() {}
 }
diff --git a/samples-dev/swarm/analysis_options.yaml b/samples-dev/swarm/analysis_options.yaml
new file mode 100644
index 0000000..79113c2
--- /dev/null
+++ b/samples-dev/swarm/analysis_options.yaml
@@ -0,0 +1,6 @@
+include: package:lints/recommended.yaml
+
+analyzer:
+  exclude: [build/**]
+  language:
+
diff --git a/samples-dev/swarm/pubspec.yaml b/samples-dev/swarm/pubspec.yaml
new file mode 100644
index 0000000..3878175
--- /dev/null
+++ b/samples-dev/swarm/pubspec.yaml
@@ -0,0 +1,5 @@
+name: swarm
+version: 0.0.1
+environment:
+  sdk: '>=2.17.0 <3.0.0'
+dev_dependencies: {lints: ^2.0.0}
diff --git a/samples-dev/swarm/swarm.dart b/samples-dev/swarm/swarm.dart
index 77fa3b0..423daec 100644
--- a/samples-dev/swarm/swarm.dart
+++ b/samples-dev/swarm/swarm.dart
@@ -9,5 +9,5 @@
 import 'swarmlib.dart';
 
 void main() {
-  new Swarm().run();
+  Swarm().run();
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/base/AnimationScheduler.dart b/samples-dev/swarm/swarm_ui_lib/base/AnimationScheduler.dart
index ce0f6c8..c273c6c 100644
--- a/samples-dev/swarm/swarm_ui_lib/base/AnimationScheduler.dart
+++ b/samples-dev/swarm/swarm_ui_lib/base/AnimationScheduler.dart
@@ -4,7 +4,7 @@
 
 part of base;
 
-typedef void AnimationCallback(num currentTime);
+typedef AnimationCallback = void Function(num currentTime);
 
 class CallbackData {
   final AnimationCallback callback;
@@ -13,28 +13,26 @@
 
   static int _nextId = 1;
 
-  bool ready(num time) => minTime == null || minTime <= time;
+  bool ready(num time) => minTime <= time;
 
   CallbackData(this.callback, this.minTime) : id = _nextId++;
 }
 
-/**
- * Animation scheduler implementing the functionality provided by
- * [:window.requestAnimationFrame:] for platforms that do not support it
- * or support it badly.  When multiple UI components are animating at once,
- * this approach yields superior performance to calling setTimeout/Timer
- * directly as all pieces of the UI will animate at the same time resulting in
- * fewer layouts.
- */
+/// Animation scheduler implementing the functionality provided by
+/// [:window.requestAnimationFrame:] for platforms that do not support it
+/// or support it badly.  When multiple UI components are animating at once,
+/// this approach yields superior performance to calling setTimeout/Timer
+/// directly as all pieces of the UI will animate at the same time resulting in
+/// fewer layouts.
 // TODO(jacobr): use window.requestAnimationFrame when it is available and
 // 60fps for the current browser.
 class AnimationScheduler {
   static const FRAMES_PER_SECOND = 60;
   static const MS_PER_FRAME = 1000 ~/ FRAMES_PER_SECOND;
 
-  /** List of callbacks to be executed next animation frame. */
+  /// List of callbacks to be executed next animation frame. */
   List<CallbackData> _callbacks;
-  bool _isMobileSafari = false;
+  final bool _isMobileSafari = false;
   late CssStyleDeclaration _safariHackStyle;
   int _frameCount = 0;
 
@@ -49,23 +47,19 @@
     }
   }
 
-  /**
-   * Cancel the pending callback matching the specified [id].
-   * This is not heavily optimized as typically users don't cancel animation
-   * frames.
-   */
+  /// Cancel the pending callback matching the specified [id].
+  /// This is not heavily optimized as typically users don't cancel animation
+  /// frames.
   void cancelRequestAnimationFrame(int id) {
     _callbacks = _callbacks.where((CallbackData e) => e.id != id).toList();
   }
 
-  /**
-   * Schedule [callback] to execute at the next animation frame that occurs
-   * at or after [minTime].  If [minTime] is not specified, the first available
-   * animation frame is used.  Returns an id that can be used to cancel the
-   * pending callback.
-   */
+  /// Schedule [callback] to execute at the next animation frame that occurs
+  /// at or after [minTime].  If [minTime] is not specified, the first available
+  /// animation frame is used.  Returns an id that can be used to cancel the
+  /// pending callback.
   int requestAnimationFrame(AnimationCallback callback,
-      [Element? element = null, num? minTime = null]) {
+      [Element? element, num? minTime]) {
     final callbackData = CallbackData(callback, minTime!);
     _requestAnimationFrameHelper(callbackData);
     return callbackData.id;
@@ -114,7 +108,7 @@
           (callbackData.callback)(minTime);
         } catch (e) {
           final msg = e.toString();
-          print('Suppressed exception ${msg} triggered by callback');
+          print('Suppressed exception $msg triggered by callback');
         }
       } else {
         _callbacks.add(callbackData);
diff --git a/samples-dev/swarm/swarm_ui_lib/base/Device.dart b/samples-dev/swarm/swarm_ui_lib/base/Device.dart
index 4a6c5d4..81913f0 100644
--- a/samples-dev/swarm/swarm_ui_lib/base/Device.dart
+++ b/samples-dev/swarm/swarm_ui_lib/base/Device.dart
@@ -6,72 +6,48 @@
 
 // TODO(jacobr): cache these results.
 // TODO(jacobr): figure out how to test this.
-/**
- * Utils for device detection.
- */
+/// Utils for device detection.
 class Device {
-  /**
-   * The regular expression for detecting an iPhone or iPod.
-   */
+  /// The regular expression for detecting an iPhone or iPod.
   static final _IPHONE_REGEX = RegExp('iPhone|iPod');
 
-  /**
-   * The regular expression for detecting an iPhone or iPod or iPad.
-   */
+  /// The regular expression for detecting an iPhone or iPod or iPad.
   static final _MOBILE_SAFARI_REGEX = RegExp('iPhone|iPod|iPad');
 
-  /**
-   * The regular expression for detecting an iPhone or iPod or iPad simulator.
-   */
+  /// The regular expression for detecting an iPhone or iPod or iPad simulator.
   static final _APPLE_SIM_REGEX = RegExp('iP.*Simulator');
 
-  /**
-   * Gets the browser's user agent. Using this function allows tests to inject
-   * the user agent.
-   * Returns the user agent.
-   */
+  /// Gets the browser's user agent. Using this function allows tests to inject
+  /// the user agent.
+  /// Returns the user agent.
   static String get userAgent => window.navigator.userAgent;
 
-  /**
-   * Determines if the current device is an iPhone or iPod.
-   * Returns true if the current device is an iPhone or iPod.
-   */
+  /// Determines if the current device is an iPhone or iPod.
+  /// Returns true if the current device is an iPhone or iPod.
   static bool get isIPhone => _IPHONE_REGEX.hasMatch(userAgent);
 
-  /**
-   * Determines if the current device is an iPad.
-   * Returns true if the current device is an iPad.
-   */
+  /// Determines if the current device is an iPad.
+  /// Returns true if the current device is an iPad.
   static bool get isIPad => userAgent.contains("iPad", 0);
 
-  /**
-   * Determines if the current device is running Firefox.
-   */
+  /// Determines if the current device is running Firefox.
   static bool get isFirefox => userAgent.contains("Firefox", 0);
 
-  /**
-   * Determines if the current device is an iPhone or iPod or iPad.
-   * Returns true if the current device is an iPhone or iPod or iPad.
-   */
+  /// Determines if the current device is an iPhone or iPod or iPad.
+  /// Returns true if the current device is an iPhone or iPod or iPad.
   static bool get isMobileSafari => _MOBILE_SAFARI_REGEX.hasMatch(userAgent);
 
-  /**
-   * Determines if the current device is the iP* Simulator.
-   * Returns true if the current device is an iP* Simulator.
-   */
+  /// Determines if the current device is the iP* Simulator.
+  /// Returns true if the current device is an iP* Simulator.
   static bool get isAppleSimulator => _APPLE_SIM_REGEX.hasMatch(userAgent);
 
-  /**
-   * Determines if the current device is an Android.
-   * Returns true if the current device is an Android.
-   */
+  /// Determines if the current device is an Android.
+  /// Returns true if the current device is an Android.
   static bool get isAndroid => userAgent.contains("Android", 0);
 
-  /**
-   * Determines if the current device is WebOS WebKit.
-   * Returns true if the current device is WebOS WebKit.
-   */
+  /// Determines if the current device is WebOS WebKit.
+  /// Returns true if the current device is WebOS WebKit.
   static bool get isWebOs => userAgent.contains("webOS", 0);
 
-  static late bool supportsTouch = isMobileSafari || isAndroid;
+  static bool supportsTouch = isMobileSafari || isAndroid;
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/base/DomWrapper.dart b/samples-dev/swarm/swarm_ui_lib/base/DomWrapper.dart
index f0a77b6f..32d39c83 100644
--- a/samples-dev/swarm/swarm_ui_lib/base/DomWrapper.dart
+++ b/samples-dev/swarm/swarm_ui_lib/base/DomWrapper.dart
@@ -4,11 +4,9 @@
 
 part of base;
 
-/**
- * Embedded DSL for generating DOM elements.
- */
+/// Embedded DSL for generating DOM elements.
 class Dom {
-  static void ready(void f()) {
+  static void ready(void Function() f) {
     if (document.readyState == 'interactive' ||
         document.readyState == 'complete') {
       Timer.run(f);
@@ -20,7 +18,7 @@
     }
   }
 
-  /** Adds the given <style> text to the page. */
+  /// Adds the given <style> text to the page. */
   static void addStyle(String cssText) {
     var style = Element.tag('style') as StyleElement;
     style.type = 'text/css';
diff --git a/samples-dev/swarm/swarm_ui_lib/base/Env.dart b/samples-dev/swarm/swarm_ui_lib/base/Env.dart
index 059a0b4..707c267 100644
--- a/samples-dev/swarm/swarm_ui_lib/base/Env.dart
+++ b/samples-dev/swarm/swarm_ui_lib/base/Env.dart
@@ -4,34 +4,28 @@
 
 part of base;
 
-/**
- * This class has static fields that hold objects that this isolate
- * uses to interact with the environment.  Which objects are available
- * depend on how the isolate was started.  In the UI isolate
- * of the browser, the window object is available.
- */
+/// This class has static fields that hold objects that this isolate
+/// uses to interact with the environment.  Which objects are available
+/// depend on how the isolate was started.  In the UI isolate
+/// of the browser, the window object is available.
 class Env {
-  static AnimationScheduler _animationScheduler = AnimationScheduler();
+  static final AnimationScheduler _animationScheduler = AnimationScheduler();
 
-  /**
-   * Provides functionality similar to [:window.requestAnimationFrame:] for
-   * all platforms. [callback] is executed on the next animation frame that
-   * occurs at or after [minTime].  If [minTime] is not specified, the first
-   * available animation frame is used.  Returns an id that can be used to
-   * cancel the pending callback.
-   */
+  /// Provides functionality similar to [:window.requestAnimationFrame:] for
+  /// all platforms. [callback] is executed on the next animation frame that
+  /// occurs at or after [minTime].  If [minTime] is not specified, the first
+  /// available animation frame is used.  Returns an id that can be used to
+  /// cancel the pending callback.
   static int requestAnimationFrame(AnimationCallback callback,
-      [Element? element = null, num? minTime = null]) {
+      [Element? element, num? minTime]) {
     return _animationScheduler.requestAnimationFrame(
         callback, element, minTime);
   }
 
-  /**
-   * Cancel the pending callback callback matching the specified [id].
-   */
+  /// Cancel the pending callback callback matching the specified [id].
   static void cancelRequestAnimationFrame(int id) {
     _animationScheduler.cancelRequestAnimationFrame(id);
   }
 }
 
-typedef void XMLHttpRequestCompleted(HttpRequest req);
+typedef XMLHttpRequestCompleted = void Function(HttpRequest req);
diff --git a/samples-dev/swarm/swarm_ui_lib/base/Size.dart b/samples-dev/swarm/swarm_ui_lib/base/Size.dart
index 727631c..4359fd9 100644
--- a/samples-dev/swarm/swarm_ui_lib/base/Size.dart
+++ b/samples-dev/swarm/swarm_ui_lib/base/Size.dart
@@ -4,127 +4,101 @@
 
 part of base;
 
-/**
- * A utility class for representing two-dimensional sizes.
- */
+/// A utility class for representing two-dimensional sizes.
 class Size {
   num width;
   num height;
 
-  Size(num this.width, num this.height) {}
+  Size(this.width, this.height);
 
+  @override
   bool operator ==(covariant Size other) {
-    return other != null && width == other.width && height == other.height;
+    return width == other.width && height == other.height;
   }
 
+  @override
   int get hashCode => throw UnimplementedError();
 
-  /**
-   * Returns the area of the size (width * height).
-   */
+  /// Returns the area of the size (width * height).
   num area() {
     return width * height;
   }
 
-  /**
-   * Returns the ratio of the size's width to its height.
-   */
+  /// Returns the ratio of the size's width to its height.
   num aspectRatio() {
     return width / height;
   }
 
-  /**
-   * Clamps the width and height parameters upward to integer values.
-   * Returns this size with ceil'd components.
-   */
+  /// Clamps the width and height parameters upward to integer values.
+  /// Returns this size with ceil'd components.
   Size ceil() {
     width = width.ceil();
     height = height.ceil();
     return this;
   }
 
-  /**
-   * Returns a copy of the Size.
-   */
+  /// Returns a copy of the Size.
   Size clone() {
     return Size(width, height);
   }
 
-  /**
-   * Returns true if this Size is the same size or smaller than the
-   * [target] size in both dimensions.
-   */
+  /// Returns true if this Size is the same size or smaller than the
+  /// [target] size in both dimensions.
   bool fitsInside(Size target) {
     return width <= target.width && height <= target.height;
   }
 
-  /**
-   * Clamps the width and height parameters downward to integer values.
-   * Returns this size with floored components.
-   */
+  /// Clamps the width and height parameters downward to integer values.
+  /// Returns this size with floored components.
   Size floor() {
     width = width.floor();
     height = height.floor();
     return this;
   }
 
-  /**
-   * Returns the longer of the two dimensions in the size.
-   */
+  /// Returns the longer of the two dimensions in the size.
   num getLongest() {
     return max(width, height);
   }
 
-  /**
-   * Returns the shorter of the two dimensions in the size.
-   */
+  /// Returns the shorter of the two dimensions in the size.
   num getShortest() {
     return min(width, height);
   }
 
-  /**
-   * Returns true if the size has zero area, false if both dimensions
-   *     are non-zero numbers.
-   */
+  /// Returns true if the size has zero area, false if both dimensions
+  ///     are non-zero numbers.
   bool get isEmpty {
     return area() == 0;
   }
 
-  /**
-   * Returns the perimeter of the size (width + height) * 2.
-   */
+  /// Returns the perimeter of the size (width + height) * 2.
   num perimeter() {
     return (width + height) * 2;
   }
 
-  /**
-   * Rounds the width and height parameters to integer values.
-   * Returns this size with rounded components.
-   */
+  /// Rounds the width and height parameters to integer values.
+  /// Returns this size with rounded components.
   Size round() {
     width = width.round();
     height = height.round();
     return this;
   }
 
-  /**
-   * Scales the size uniformly by a factor.
-   * [s] The scale factor.
-   * Returns this Size object after scaling.
-   */
+  /// Scales the size uniformly by a factor.
+  /// [s] The scale factor.
+  /// Returns this Size object after scaling.
   Size scale(num s) {
     width *= s;
     height *= s;
     return this;
   }
 
-  /**
-   * Uniformly scales the size to fit inside the dimensions of a given size. The
-   * original aspect ratio will be preserved.
-   *
-   * This function assumes that both Sizes contain strictly positive dimensions.
-   * Returns this Size object, after optional scaling.
-   */
+  /// Uniformly scales the size to fit inside the dimensions of a given size. The
+  /// original aspect ratio will be preserved.
+  ///
+  /// This function assumes that both Sizes contain strictly positive dimensions.
+  /// Returns this Size object, after optional scaling.
   Size scaleToFit(Size target) {
     num s = aspectRatio() > target.aspectRatio()
         ? target.width / width
@@ -132,11 +106,10 @@
     return scale(s);
   }
 
-  /**
-   * Returns a nice string representing size.
-   * Returns in the form (50 x 73).
-   */
+  /// Returns a nice string representing size.
+  /// Returns in the form (50 x 73).
+  @override
   String toString() {
-    return "(${width} x ${height})";
+    return "($width x $height)";
   }
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/layout/GridLayout.dart b/samples-dev/swarm/swarm_ui_lib/layout/GridLayout.dart
index 005f182..958a68d 100644
--- a/samples-dev/swarm/swarm_ui_lib/layout/GridLayout.dart
+++ b/samples-dev/swarm/swarm_ui_lib/layout/GridLayout.dart
@@ -4,14 +4,12 @@
 
 part of layout;
 
-/**
- * Implements a grid-based layout system based on:
- * [http://dev.w3.org/csswg/css3-grid-align/]
- *
- * This layout is designed to support animations and work on browsers that
- * don't support grid natively. As such, we implement it on top of absolute
- * positioning.
- */
+/// Implements a grid-based layout system based on:
+/// [http://dev.w3.org/csswg/css3-grid-align/]
+///
+/// This layout is designed to support animations and work on browsers that
+/// don't support grid natively. As such, we implement it on top of absolute
+/// positioning.
 // TODO(jmesserly): the DOM integration still needs work:
 //  - The grid assumes it is absolutely positioned in its container.
 //    Because of that, the grid doesn't work right unless it has at least one
@@ -43,31 +41,27 @@
 //  - Optimize for the case of no content sized tracks
 //  - Optimize for the "incremental update" cases
 class GridLayout extends ViewLayout {
-  /** Configuration parameters defined in CSS. */
+  /// Configuration parameters defined in CSS. */
   final GridTrackList? rows;
   final GridTrackList? columns;
   final GridTemplate? template;
 
-  /** The default sizing for new rows. */
+  /// The default sizing for new rows. */
   final TrackSizing rowSizing;
 
-  /** The default sizing for new columns. */
+  /// The default sizing for new columns. */
   final TrackSizing columnSizing;
 
-  /**
-   * This stores the grid's size during a layout.
-   * Used for rows/columns with % or fr units.
-   */
+  /// This stores the grid's size during a layout.
+  /// Used for rows/columns with % or fr units.
   int? _gridWidth, _gridHeight;
 
-  /**
-   * During a layout, this stores all row/column size information.
-   * Because grid-items can implicitly specify their own rows/columns, we can't
-   * compute this until we know the set of items.
-   */
+  /// During a layout, this stores all row/column size information.
+  /// Because grid-items can implicitly specify their own rows/columns, we can't
+  /// compute this until we know the set of items.
   late List<GridTrack> _rowTracks, _columnTracks;
 
-  /** During a layout, tracks which dimension we're processing. */
+  /// During a layout, tracks which dimension we're processing. */
   Dimension? _dimension;
 
   GridLayout(Positionable view)
@@ -83,9 +77,12 @@
     _columnTracks = columns?.tracks ?? [];
   }
 
+  @override
   int? get currentWidth => _gridWidth;
+  @override
   int? get currentHeight => _gridHeight;
 
+  @override
   void cacheExistingBrowserLayout() {
     // We don't need to do anything as we don't rely on the _cachedViewRect
     // when the grid layout is used.
@@ -93,14 +90,15 @@
 
   // TODO(jacobr): cleanup this method so that it returns a Future
   // rather than taking a Completer as an argument.
-  /** The main entry point for layout computation. */
+  /// The main entry point for layout computation. */
+  @override
   void measureLayout(Future<Size> size, Completer<bool>? changed) {
     _ensureAllTracks();
     size.then((value) {
       _gridWidth = value.width as int?;
       _gridHeight = value.height as int?;
 
-      if (_rowTracks.length > 0 && _columnTracks.length > 0) {
+      if (_rowTracks.isNotEmpty && _columnTracks.isNotEmpty) {
         _measureTracks();
         _setBoundsOfChildren();
         if (changed != null) {
@@ -110,10 +108,8 @@
     });
   }
 
-  /**
-   * The top level measurement function.
-   * [http://dev.w3.org/csswg/css3-grid-align/#calculating-size-of-grid-tracks]
-   */
+  /// The top level measurement function.
+  /// [http://dev.w3.org/csswg/css3-grid-align/#calculating-size-of-grid-tracks]
   void _measureTracks() {
     // Resolve logical width, then height. Width comes first so we can use
     // the width when determining the content-sized height.
@@ -137,14 +133,12 @@
     return Math.max(0, remaining);
   }
 
-  /**
-   * This is the core Grid Track sizing algorithm. It is run for Grid columns
-   * and Grid rows. The goal of the function is to ensure:
-   *   1. That each Grid Track satisfies its minSizing
-   *   2. That each Grid Track grows from the breadth which satisfied its
-   *      minSizing to a breadth which satifies its
-   *      maxSizing, subject to RemainingSpace.
-   */
+  /// This is the core Grid Track sizing algorithm. It is run for Grid columns
+  /// and Grid rows. The goal of the function is to ensure:
+  ///   1. That each Grid Track satisfies its minSizing
+  ///   2. That each Grid Track grows from the breadth which satisfied its
+  ///      minSizing to a breadth which satifies its
+  ///      maxSizing, subject to RemainingSpace.
   // Note: spec does not correctly doc all the parameters to this function.
   void _computeUsedBreadthOfTracks(List<GridTrack> tracks) {
     // TODO(jmesserly): as a performance optimization we could cache this
@@ -161,12 +155,12 @@
     }
 
     // 2. Resolve content-based MinTrackSizingFunctions
-    final USED_BREADTH = const _UsedBreadthAccumulator();
-    final MAX_BREADTH = const _MaxBreadthAccumulator();
+    final USEDBREADTH = const _UsedBreadthAccumulator();
+    final MAXBREADTH = const _MaxBreadthAccumulator();
 
-    _distributeSpaceBySpanCount(items, ContentSizeMode.MIN, USED_BREADTH);
+    _distributeSpaceBySpanCount(items, ContentSizeMode.MIN, USEDBREADTH);
 
-    _distributeSpaceBySpanCount(items, ContentSizeMode.MAX, USED_BREADTH);
+    _distributeSpaceBySpanCount(items, ContentSizeMode.MAX, USEDBREADTH);
 
     // 3. Ensure that maxBreadth is as big as usedBreadth for each track
     for (final t in tracks) {
@@ -176,16 +170,16 @@
     }
 
     // 4. Resolve content-based MaxTrackSizingFunctions
-    _distributeSpaceBySpanCount(items, ContentSizeMode.MIN, MAX_BREADTH);
+    _distributeSpaceBySpanCount(items, ContentSizeMode.MIN, MAXBREADTH);
 
-    _distributeSpaceBySpanCount(items, ContentSizeMode.MAX, MAX_BREADTH);
+    _distributeSpaceBySpanCount(items, ContentSizeMode.MAX, MAXBREADTH);
 
     // 5. Grow all Grid Tracks in GridTracks from their usedBreadth up to their
     //    maxBreadth value until RemainingSpace is exhausted.
     // Note: it's not spec'd what to pass as the accumulator, but usedBreadth
     // seems right.
     _distributeSpaceToTracks(
-        tracks, _getRemainingSpace(tracks), USED_BREADTH, false);
+        tracks, _getRemainingSpace(tracks), USEDBREADTH, false);
 
     // Spec wording is confusing about which direction this assignment happens,
     // but this is the way that makes sense.
@@ -203,10 +197,8 @@
     _computeTrackPositions(tracks);
   }
 
-  /**
-   * Final steps to finish positioning tracks. Takes the track size and uses
-   * it to get start and end positions. Also rounds the positions to integers.
-   */
+  /// Final steps to finish positioning tracks. Takes the track size and uses
+  /// it to get start and end positions. Also rounds the positions to integers.
   void _computeTrackPositions(List<GridTrack> tracks) {
     // Compute start positions of tracks, as well as the final position
 
@@ -238,14 +230,12 @@
     }
   }
 
-  /**
-   * This method computes a '1fr' value, referred to as the
-   * tempBreadth, for a set of Grid Tracks. The value computed
-   * will ensure that when the tempBreadth is multiplied by the
-   * fractions associated with tracks, that the UsedBreadths of tracks
-   * will increase by an amount equal to the maximum of zero and the specified
-   * freeSpace less the sum of the current UsedBreadths.
-   */
+  /// This method computes a '1fr' value, referred to as the
+  /// tempBreadth, for a set of Grid Tracks. The value computed
+  /// will ensure that when the tempBreadth is multiplied by the
+  /// fractions associated with tracks, that the UsedBreadths of tracks
+  /// will increase by an amount equal to the maximum of zero and the specified
+  /// freeSpace less the sum of the current UsedBreadths.
   num _calcNormalizedFractionBreadth(List<GridTrack> tracks) {
     final fractionTracks = tracks.where((t) => t.maxSizing.isFraction).toList();
 
@@ -279,11 +269,9 @@
     return spaceNeededFromFractionTracks / accumulatedFractions;
   }
 
-  /**
-   * Ensures that for each Grid Track in tracks, a value will be
-   * computed, updatedBreadth, that represents the Grid Track's share of
-   * freeSpace.
-   */
+  /// Ensures that for each Grid Track in tracks, a value will be
+  /// computed, updatedBreadth, that represents the Grid Track's share of
+  /// freeSpace.
   void _distributeSpaceToTracks(List<GridTrack?> tracks, num? freeSpace,
       _BreadthAccumulator breadth, bool ignoreMaxBreadth) {
     // TODO(jmesserly): in some cases it would be safe to sort the passed in
@@ -321,14 +309,12 @@
     }
   }
 
-  /**
-   * This function prioritizes the distribution of space driven by Grid Items
-   * in content-sized Grid Tracks by the Grid Item's spanCount. That is, Grid
-   * Items having a lower spanCount have an opportunity to increase the size of
-   * the Grid Tracks they cover before those with larger SpanCounts.
-   *
-   * Note: items are assumed to be already sorted in increasing span count
-   */
+  /// This function prioritizes the distribution of space driven by Grid Items
+  /// in content-sized Grid Tracks by the Grid Item's spanCount. That is, Grid
+  /// Items having a lower spanCount have an opportunity to increase the size of
+  /// the Grid Tracks they cover before those with larger SpanCounts.
+  ///
+  /// Note: items are assumed to be already sorted in increasing span count
   void _distributeSpaceBySpanCount(List<ViewLayout> items,
       ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
     items = items
@@ -366,10 +352,8 @@
     }
   }
 
-  /**
-   * Returns true if we have an appropriate content sized dimension, and don't
-   * cross a fractional track.
-   */
+  /// Returns true if we have an appropriate content sized dimension, and don't
+  /// cross a fractional track.
   static bool _hasContentSizedTracks(Iterable<GridTrack?> tracks,
       ContentSizeMode sizeMode, _BreadthAccumulator breadth) {
     for (final t in tracks) {
@@ -383,7 +367,7 @@
     return false;
   }
 
-  /** Ensures that the numbered track exists. */
+  /// Ensures that the numbered track exists. */
   void _ensureTrack(
       List<GridTrack> tracks, TrackSizing sizing, int start, int span) {
     // Start is 1-based. Make it 0-based.
@@ -402,13 +386,11 @@
     }
   }
 
-  /**
-   * Scans children creating GridLayoutParams as needed, and creates all of the
-   * rows and columns that we will need.
-   *
-   * Note: this can potentially create new qrows/columns, so this needs to be
-   * run before the track sizing algorithm.
-   */
+  /// Scans children creating GridLayoutParams as needed, and creates all of the
+  /// rows and columns that we will need.
+  ///
+  /// Note: this can potentially create new qrows/columns, so this needs to be
+  /// run before the track sizing algorithm.
   void _ensureAllTracks() {
     final items = view.childViews.map((view_) => view_.layout);
 
@@ -423,9 +405,7 @@
     }
   }
 
-  /**
-   * Given the track sizes that were computed, position children in the grid.
-   */
+  /// Given the track sizes that were computed, position children in the grid.
   void _setBoundsOfChildren() {
     final items = view.childViews.map((view_) => view_.layout);
 
@@ -453,6 +433,7 @@
     } else if (_dimension == Dimension.HEIGHT) {
       return _gridHeight;
     }
+    return null;
   }
 
   _GridLocation _getTrackLocationX(GridLayoutParams childLayout) {
@@ -475,7 +456,7 @@
     return _GridLocation(start, end - start);
   }
 
-  /** Gets the tracks that this item crosses. */
+  /// Gets the tracks that this item crosses. */
   // TODO(jmesserly): might be better to return an iterable
   List<GridTrack?> _getTracks(ViewLayout item) {
     GridLayoutParams? childLayout = item.layoutParams as GridLayoutParams?;
diff --git a/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParams.dart b/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParams.dart
index c47f2ca..a2d72eb 100644
--- a/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParams.dart
+++ b/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParams.dart
@@ -4,23 +4,22 @@
 
 part of layout;
 
-/**
- * Caches the layout parameters that were specified in CSS during a layout
- * computation. These values are immutable during a layout.
- */
+/// Caches the layout parameters that were specified in CSS during a layout
+/// computation. These values are immutable during a layout.
 // TODO(jmesserly): I would like all fields to be final, but it's too painful
 // to do this right now in Dart. If I create a factory constructor, then I need
 // to create locals, and pass all parameters to the real constructor. Each
 // field ends up being mentioned 4 times instead of just twice.
 class GridLayoutParams extends LayoutParams {
-  /** The coordinates of this item in the grid. */
+  /// The coordinates of this item in the grid. */
   int? row;
   int? column;
   int? rowSpan;
   int? columnSpan;
+  @override
   int? layer;
 
-  /** Alignment within its box */
+  /// Alignment within its box */
   GridItemAlignment rowAlign;
   GridItemAlignment columnAlign;
 
@@ -89,16 +88,16 @@
       columnSpan = rect.columnSpan;
     } else {
       // Apply default row, column span values.
-      if (rowSpan == null) rowSpan = 1;
-      if (columnSpan == null) columnSpan = 1;
+      rowSpan ??= 1;
+      columnSpan ??= 1;
 
       if (row == null && column == null) {
-        throw UnsupportedError('grid-flow is not implemented' +
+        throw UnsupportedError('grid-flow is not implemented'
             ' so at least one row or one column must be defined');
       }
 
-      if (row == null) row = 1;
-      if (column == null) column = 1;
+      row ??= 1;
+      column ??= 1;
     }
 
     assert(row! > 0 && rowSpan! > 0 && column! > 0 && columnSpan! > 0);
diff --git a/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParser.dart b/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParser.dart
index 009392a..6aa77f2 100644
--- a/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParser.dart
+++ b/samples-dev/swarm/swarm_ui_lib/layout/GridLayoutParser.dart
@@ -4,10 +4,8 @@
 
 part of layout;
 
-/**
- * Base class for simple recursive descent parsers.
- * Handles the lower level stuff, i.e. what a scanner/tokenizer would do.
- */
+/// Base class for simple recursive descent parsers.
+/// Handles the lower level stuff, i.e. what a scanner/tokenizer would do.
 class _Parser {
   static const WHITESPACE = ' \r\n\t';
 
@@ -124,7 +122,7 @@
     return true;
   }
 
-  void _eat(String value, [bool eatWhitespace = true]) {
+  void _eat(String value) {
     if (!_maybeEat(value)) {
       _error('expected "$value"');
     }
@@ -159,7 +157,7 @@
     return result;
   }
 
-  /** Eats something like a keyword. */
+  /// Eats something like a keyword. */
   String _eatWord() {
     int start = _offset;
     while (_offset < length && _isLetter(_peekChar())) {
@@ -168,7 +166,7 @@
     return _src.substring(start, _offset);
   }
 
-  /** Eats an integer. */
+  /// Eats an integer. */
   int? _maybeEatInt() {
     int start = _offset;
     bool dot = false;
@@ -183,7 +181,7 @@
     return int.parse(_src.substring(start, _offset));
   }
 
-  /** Eats an integer. */
+  /// Eats an integer. */
   int? _eatInt() {
     int? result = _maybeEatInt();
     if (result == null) {
@@ -192,7 +190,7 @@
     return result;
   }
 
-  /** Eats something like a positive decimal: 12.345. */
+  /// Eats something like a positive decimal: 12.345. */
   num _eatDouble() {
     int start = _offset;
     bool dot = false;
@@ -217,11 +215,11 @@
   }
 }
 
-/** Parses a grid template. */
+/// Parses a grid template. */
 class _GridTemplateParser extends _Parser {
   _GridTemplateParser._internal(String src) : super(src);
 
-  /** Parses the grid-rows and grid-columns CSS properties into object form. */
+  /// Parses the grid-rows and grid-columns CSS properties into object form. */
   static GridTemplate? parse(String? str) {
     if (str == null) return null;
     final p = _GridTemplateParser._internal(str);
@@ -230,7 +228,7 @@
     return result;
   }
 
-  /** Parses a grid-cell value. */
+  /// Parses a grid-cell value. */
   static String? parseCell(String? str) {
     if (str == null) return null;
     final p = _GridTemplateParser._internal(str);
@@ -249,18 +247,18 @@
     while ((row = _maybeEatString()) != null) {
       rows.add(row);
     }
-    if (rows.length == 0) {
+    if (rows.isEmpty) {
       _error('expected at least one cell, or "none"');
     }
     return GridTemplate(rows);
   }
 }
 
-/** Parses a grid-row or grid-column */
+/// Parses a grid-row or grid-column */
 class _GridItemParser extends _Parser {
   _GridItemParser._internal(String src) : super(src);
 
-  /** Parses the grid-rows and grid-columns CSS properties into object form. */
+  /// Parses the grid-rows and grid-columns CSS properties into object form. */
   static _GridLocation? parse(String? cell, GridTrackList? list) {
     if (cell == null) return null;
     final p = _GridItemParser._internal(cell);
@@ -281,7 +279,7 @@
       _error('expected row/column number or name');
     }
     int? end = _maybeParseLine(list);
-    int? span = null;
+    int? span;
     if (end != null) {
       span = end - start!;
       if (span <= 0) {
@@ -318,11 +316,9 @@
   }
 }
 
-/**
- * Parses grid-rows and grid-column properties, see:
- * [http://dev.w3.org/csswg/css3-grid-align/#grid-columns-and-rows-properties]
- * This is kept as a recursive descent parser for simplicity.
- */
+/// Parses grid-rows and grid-column properties, see:
+/// [http://dev.w3.org/csswg/css3-grid-align/#grid-columns-and-rows-properties]
+/// This is kept as a recursive descent parser for simplicity.
 // TODO(jmesserly): implement missing features from the spec. Mainly around
 // CSS units, support for all escape sequences, etc.
 class _GridTrackParser extends _Parser {
@@ -331,10 +327,10 @@
 
   _GridTrackParser._internal(String src)
       : _tracks = <GridTrack>[],
-        _lineNames = Map<String?, int>(),
+        _lineNames = <String?, int>{},
         super(src);
 
-  /** Parses the grid-rows and grid-columns CSS properties into object form. */
+  /// Parses the grid-rows and grid-columns CSS properties into object form. */
   static GridTrackList? parse(String? str) {
     if (str == null) return null;
     final p = _GridTrackParser._internal(str);
@@ -343,12 +339,10 @@
     return result;
   }
 
-  /**
-   * Parses the grid-row-sizing and grid-column-sizing CSS properties into
-   * object form.
-   */
+  /// Parses the grid-row-sizing and grid-column-sizing CSS properties into
+  /// object form.
   static TrackSizing parseTrackSizing(String? str) {
-    if (str == null) str = 'auto';
+    str ??= 'auto';
     final p = _GridTrackParser._internal(str);
     final result = p._parseTrackMinmax();
     p._eatEnd();
@@ -364,8 +358,8 @@
     return GridTrackList(_tracks, _lineNames);
   }
 
-  /** Code shared by _parseTrackList and _parseTrackGroup */
-  void _parseTrackListHelper([List<GridTrack>? resultTracks = null]) {
+  /// Code shared by _parseTrackList and _parseTrackGroup */
+  void _parseTrackListHelper([List<GridTrack>? resultTracks]) {
     _maybeEatWhitespace();
     while (!endOfInput) {
       String? name;
@@ -465,9 +459,7 @@
   }
 }
 
-/**
- * Exception thrown because the grid style properties had incorrect values.
- */
+/// Exception thrown because the grid style properties had incorrect values.
 class SyntaxErrorException implements Exception {
   final String _message;
   final int _offset;
@@ -475,6 +467,7 @@
 
   const SyntaxErrorException(this._message, this._source, this._offset);
 
+  @override
   String toString() {
     String location;
     if (_offset < _source.length) {
diff --git a/samples-dev/swarm/swarm_ui_lib/layout/GridTracks.dart b/samples-dev/swarm/swarm_ui_lib/layout/GridTracks.dart
index 8baa1fb..a94506c 100644
--- a/samples-dev/swarm/swarm_ui_lib/layout/GridTracks.dart
+++ b/samples-dev/swarm/swarm_ui_lib/layout/GridTracks.dart
@@ -6,33 +6,27 @@
 
 // This file has classes representing the grid tracks and grid template
 
-/**
- * The data structure representing the grid-rows or grid-columns
- * properties.
- */
+/// The data structure representing the grid-rows or grid-columns
+/// properties.
 class GridTrackList {
-  /** The set of tracks defined in CSS via grid-rows and grid-columns */
+  /// The set of tracks defined in CSS via grid-rows and grid-columns */
   final List<GridTrack> tracks;
 
-  /**
-   * Maps edge names to the corresponding track. Depending on whether the index
-   * is used as a start or end, it might be interpreted exclusively or
-   * inclusively.
-   */
+  /// Maps edge names to the corresponding track. Depending on whether the index
+  /// is used as a start or end, it might be interpreted exclusively or
+  /// inclusively.
   final Map<String?, int> lineNames;
 
-  GridTrackList(this.tracks, this.lineNames) {}
+  GridTrackList(this.tracks, this.lineNames);
 }
 
-/** Represents a row or a column. */
+/// Represents a row or a column. */
 class GridTrack {
-  /**
-   * The start position of this track. Equal to the sum of previous track's
-   * usedBreadth.
-   */
+  /// The start position of this track. Equal to the sum of previous track's
+  /// usedBreadth.
   late num start;
 
-  /** The final computed breadth of this track. */
+  /// The final computed breadth of this track. */
   late num usedBreadth;
 
   // Fields used internally by the sizing algorithm
@@ -42,18 +36,16 @@
 
   final TrackSizing sizing;
 
-  GridTrack(this.sizing) {}
+  GridTrack(this.sizing);
 
-  /**
-   * Support for the feature that repeats rows and columns, e.g.
-   * [:grid-columns: 10px ("content" 250px 10px)[4]:]
-   */
+  /// Support for the feature that repeats rows and columns, e.g.
+  /// [:grid-columns: 10px ("content" 250px 10px)[4]:]
   GridTrack clone() => GridTrack(sizing.clone());
 
-  /** The min sizing function for the track. */
+  /// The min sizing function for the track. */
   SizingFunction get minSizing => sizing.min;
 
-  /** The min sizing function for the track. */
+  /// The min sizing function for the track. */
   SizingFunction get maxSizing => sizing.max;
 
   num get end => start + usedBreadth;
@@ -61,14 +53,14 @@
   bool get isFractional => minSizing.isFraction || maxSizing.isFraction;
 }
 
-/** Represents the grid-row-align or grid-column-align. */
+/// Represents the grid-row-align or grid-column-align. */
 class GridItemAlignment {
   // TODO(jmesserly): should this be stored as an int for performance?
   final String value;
 
   // 'start' | 'end' | 'center' | 'stretch'
   GridItemAlignment.fromString(String? value)
-      : this.value = (value == null) ? 'stretch' : value {
+      : value = (value == null) ? 'stretch' : value {
     switch (this.value) {
       case 'start':
       case 'end':
@@ -98,10 +90,8 @@
   }
 }
 
-/**
- * Represents a grid-template. Used in conjunction with a grid-cell to
- * place cells in the grid, without needing to specify the exact row/column.
- */
+/// Represents a grid-template. Used in conjunction with a grid-cell to
+/// place cells in the grid, without needing to specify the exact row/column.
 class GridTemplate {
   final Map<int, _GridTemplateRect> _rects;
   final int _numRows;
@@ -112,7 +102,7 @@
     _buildRects(rows);
   }
 
-  /** Scans the template strings and computes bounds for each one. */
+  /// Scans the template strings and computes bounds for each one. */
   void _buildRects(List<String?> templateRows) {
     for (int r = 0; r < templateRows.length; r++) {
       String row = templateRows[r]!;
@@ -133,9 +123,7 @@
     }
   }
 
-  /**
-   * Looks up the given cell in the template, and returns the rect.
-   */
+  /// Looks up the given cell in the template, and returns the rect.
   _GridTemplateRect lookupCell(String cell) {
     if (cell.length != 1) {
       throw UnsupportedError(
@@ -150,13 +138,13 @@
   }
 }
 
-/** Used by GridTemplate to track a single cell's bounds. */
+/// Used by GridTemplate to track a single cell's bounds. */
 class _GridTemplateRect {
   int row, column, rowSpan, columnSpan, _count, _char;
   _GridTemplateRect(this._char, this.row, this.column)
       : rowSpan = 1,
         columnSpan = 1,
-        _count = 1 {}
+        _count = 1;
 
   void add(int r, int c) {
     assert(r >= row && c >= column);
@@ -177,13 +165,11 @@
   }
 }
 
-/**
- * Used to return a row/column and span during parsing of grid-row and
- * grid-column during parsing.
- */
+/// Used to return a row/column and span during parsing of grid-row and
+/// grid-column during parsing.
 class _GridLocation {
   final int? start, length;
-  _GridLocation(this.start, this.length) {}
+  _GridLocation(this.start, this.length);
 
   int get end => start! + length!;
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/layout/SizingFunctions.dart b/samples-dev/swarm/swarm_ui_lib/layout/SizingFunctions.dart
index a85a420..00022d4 100644
--- a/samples-dev/swarm/swarm_ui_lib/layout/SizingFunctions.dart
+++ b/samples-dev/swarm/swarm_ui_lib/layout/SizingFunctions.dart
@@ -6,9 +6,7 @@
 
 // This file has classes representing the grid sizing functions
 
-/**
- * Represents the sizing function used for the min or max of a row or column.
- */
+/// Represents the sizing function used for the min or max of a row or column.
 // TODO(jmesserly): rename to GridSizing, or make internal
 class SizingFunction {
   const SizingFunction();
@@ -26,13 +24,11 @@
   SizingFunction clone() => this;
 }
 
-/**
- * Fixed size represents a length as defined by CSS3 Values spec.
- * Can also be a percentage of the Grid element's logical width (for columns)
- * or logical height (for rows). When the width or height of the Grid element
- * is undefined, the percentage is ignored and the Grid Track will be
- * auto-sized.
- */
+/// Fixed size represents a length as defined by CSS3 Values spec.
+/// Can also be a percentage of the Grid element's logical width (for columns)
+/// or logical height (for rows). When the width or height of the Grid element
+/// is undefined, the percentage is ignored and the Grid Track will be
+/// auto-sized.
 class FixedSizing extends SizingFunction {
   final String units;
   final num length;
@@ -49,10 +45,13 @@
   }
 
   // TODO(jmesserly): this is only needed because of our mutable property
+  @override
   FixedSizing clone() => FixedSizing(length, units);
 
+  @override
   bool get isMinContentSized => _contentSized;
 
+  @override
   num resolveLength(num? gridSize) {
     if (units == '%') {
       if (gridSize == null) {
@@ -68,60 +67,66 @@
     }
   }
 
-  String toString() => 'FixedSizing: ${length}${units} $_contentSized';
+  @override
+  String toString() => 'FixedSizing: $length$units $_contentSized';
 }
 
-/**
- * Fraction is a non-negative floating-point number followed by 'fr'. Each
- * fraction value takes a share of the remaining space proportional to its
- * number.
- */
+/// Fraction is a non-negative floating-point number followed by 'fr'. Each
+/// fraction value takes a share of the remaining space proportional to its
+/// number.
 class FractionSizing extends SizingFunction {
+  @override
   final num fractionValue;
   FractionSizing(this.fractionValue);
 
+  @override
   bool get isFraction => true;
 
+  @override
   String toString() => 'FixedSizing: ${fractionValue}fr';
 }
 
 class MinContentSizing extends SizingFunction {
   const MinContentSizing();
 
+  @override
   bool get isMinContentSized => true;
 
+  @override
   String toString() => 'MinContentSizing';
 }
 
 class MaxContentSizing extends SizingFunction {
   const MaxContentSizing();
 
+  @override
   bool get isMaxContentSized {
     return true;
   }
 
+  @override
   String toString() => 'MaxContentSizing';
 }
 
-/** The min and max sizing functions for a track. */
+/// The min and max sizing functions for a track. */
 class TrackSizing {
-  /** The min sizing function for the track. */
+  /// The min sizing function for the track. */
   final SizingFunction min;
 
-  /** The min sizing function for the track. */
+  /// The min sizing function for the track. */
   final SizingFunction max;
 
   const TrackSizing.auto()
       : min = const MinContentSizing(),
         max = const MaxContentSizing();
 
-  TrackSizing(this.min, this.max) {}
+  TrackSizing(this.min, this.max);
 
   // TODO(jmesserly): this is only needed because FixedSizing is mutable
   TrackSizing clone() => TrackSizing(min.clone(), max.clone());
 }
 
-/** Represents a GridTrack breadth property. */
+/// Represents a GridTrack breadth property. */
 // TODO(jmesserly): these classes could be replaced with reflection/mirrors
 abstract class _BreadthAccumulator {
   void setSize(GridTrack? t, num value);
@@ -133,23 +138,29 @@
 class _UsedBreadthAccumulator implements _BreadthAccumulator {
   const _UsedBreadthAccumulator();
 
+  @override
   void setSize(GridTrack? t, num value) {
     t!.usedBreadth = value;
   }
 
+  @override
   num? getSize(GridTrack? t) => t!.usedBreadth;
 
+  @override
   SizingFunction getSizingFunction(GridTrack? t) => t!.minSizing;
 }
 
 class _MaxBreadthAccumulator implements _BreadthAccumulator {
   const _MaxBreadthAccumulator();
 
+  @override
   void setSize(GridTrack? t, num value) {
     t!.maxBreadth = value;
   }
 
+  @override
   num? getSize(GridTrack? t) => t!.maxBreadth;
 
+  @override
   SizingFunction getSizingFunction(GridTrack? t) => t!.maxSizing;
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/layout/ViewLayout.dart b/samples-dev/swarm/swarm_ui_lib/layout/ViewLayout.dart
index 5c284e1..792a967 100644
--- a/samples-dev/swarm/swarm_ui_lib/layout/ViewLayout.dart
+++ b/samples-dev/swarm/swarm_ui_lib/layout/ViewLayout.dart
@@ -4,27 +4,25 @@
 
 part of layout;
 
-/** The interface that the layout algorithms use to talk to the view. */
+/// The interface that the layout algorithms use to talk to the view. */
 abstract class Positionable {
   ViewLayout get layout;
 
-  /** Gets our custom CSS properties, as provided by the CSS preprocessor. */
+  /// Gets our custom CSS properties, as provided by the CSS preprocessor. */
   Map<String, String> get customStyle;
 
-  /** Gets the root DOM used for layout. */
+  /// Gets the root DOM used for layout. */
   Element get node;
 
-  /** Gets the collection of child views. */
+  /// Gets the collection of child views. */
   Iterable<Positionable> get childViews;
 
-  /** Causes a view to layout its children. */
+  /// Causes a view to layout its children. */
   void doLayout();
 }
 
-/**
- * Caches the layout parameters that were specified in CSS during a layout
- * computation. These values are immutable during a layout.
- */
+/// Caches the layout parameters that were specified in CSS during a layout
+/// computation. These values are immutable during a layout.
 class LayoutParams {
   // TODO(jmesserly): should be const, but there's a bug in DartC preventing us
   // from calling "window." in an initializer. See b/5332777
@@ -40,19 +38,19 @@
 // TODO(jmesserly): enums would really help here
 class Dimension {
   // TODO(jmesserly): perhaps this should be X and Y
-  static const WIDTH = const Dimension._internal('width');
-  static const HEIGHT = const Dimension._internal('height');
+  static const WIDTH = Dimension._internal('width');
+  static const HEIGHT = Dimension._internal('height');
 
   final String name; // for debugging
   const Dimension._internal(this.name);
 }
 
 class ContentSizeMode {
-  /** Minimum content size, e.g. min-width and min-height in CSS. */
-  static const MIN = const ContentSizeMode._internal('min');
+  /// Minimum content size, e.g. min-width and min-height in CSS. */
+  static const MIN = ContentSizeMode._internal('min');
 
-  /** Maximum content size, e.g. min-width and min-height in CSS. */
-  static const MAX = const ContentSizeMode._internal('max');
+  /// Maximum content size, e.g. min-width and min-height in CSS. */
+  static const MAX = ContentSizeMode._internal('max');
 
   // TODO(jmesserly): we probably want some sort of "auto" or "best fit" mode
   // Don't need it yet though.
@@ -61,35 +59,27 @@
   const ContentSizeMode._internal(this.name);
 }
 
-/**
- * Abstract base class for View layout. Tracks relevant layout state.
- * This code was inspired by code in Android's View.java; it's needed for the
- * rest of the layout system.
- */
+/// Abstract base class for View layout. Tracks relevant layout state.
+/// This code was inspired by code in Android's View.java; it's needed for the
+/// rest of the layout system.
 class ViewLayout {
-  /**
-   * The layout parameters associated with this view and used by the parent
-   * to determine how this view should be laid out.
-   */
+  /// The layout parameters associated with this view and used by the parent
+  /// to determine how this view should be laid out.
   LayoutParams? layoutParams;
   int? _offsetWidth;
   int? _offsetHeight;
 
-  /** The view that this layout belongs to. */
+  /// The view that this layout belongs to. */
   final Positionable view;
 
-  /**
-   * To get a perforant positioning model on top of the DOM, we read all
-   * properties in the first pass while computing positions. Then we have a
-   * second pass that actually moves everything.
-   */
+  /// To get a perforant positioning model on top of the DOM, we read all
+  /// properties in the first pass while computing positions. Then we have a
+  /// second pass that actually moves everything.
   int? _measuredLeft, _measuredTop, _measuredWidth, _measuredHeight;
 
   ViewLayout(this.view);
 
-  /**
-   * Creates the appropriate view layout, depending on the properties.
-   */
+  /// Creates the appropriate view layout, depending on the properties.
   // TODO(jmesserly): we should support user defined layouts somehow. Perhaps
   // registered with a LayoutProvider.
   factory ViewLayout.fromView(Positionable view) {
@@ -126,13 +116,11 @@
   int get borderWidth => borderLeftWidth + borderRightWidth;
   int get borderHeight => borderTopWidth + borderBottomWidth;
 
-  /** Implements the custom layout computation. */
+  /// Implements the custom layout computation. */
   void measureLayout(Future<Size> size, Completer<bool>? changed) {}
 
-  /**
-   * Positions the view within its parent container.
-   * Also performs a layout of its children.
-   */
+  /// Positions the view within its parent container.
+  /// Also performs a layout of its children.
   void setBounds(int? left, int? top, int width, int height) {
     assert(width >= 0 && height >= 0);
 
@@ -147,7 +135,7 @@
     measureLayout(completer.future, null);
   }
 
-  /** Applies the layout to the node. */
+  /// Applies the layout to the node. */
   void applyLayout() {
     if (_measuredLeft != null) {
       // TODO(jmesserly): benchmark the performance of this DOM interaction
@@ -180,12 +168,13 @@
   }
 
   int? measureContent(ViewLayout parent, Dimension? dimension,
-      [ContentSizeMode? mode = null]) {
+      [ContentSizeMode? mode]) {
     if (dimension == Dimension.WIDTH) {
       return measureWidth(parent, mode);
     } else if (dimension == Dimension.HEIGHT) {
       return measureHeight(parent, mode);
     }
+    return null;
   }
 
   int? measureWidth(ViewLayout parent, ContentSizeMode? mode) {
@@ -195,6 +184,7 @@
     } else if (mode == ContentSizeMode.MAX) {
       return _styleToPixels(style!.maxWidth, currentWidth, parent.currentWidth);
     }
+    return null;
   }
 
   int? measureHeight(ViewLayout parent, ContentSizeMode? mode) {
@@ -206,6 +196,7 @@
       return _styleToPixels(
           style!.maxHeight, currentHeight, parent.currentHeight);
     }
+    return null;
   }
 
   static int _toPixels(String style) {
diff --git a/samples-dev/swarm/swarm_ui_lib/observable/ChangeEvent.dart b/samples-dev/swarm/swarm_ui_lib/observable/ChangeEvent.dart
index bafa8dd..5266c91 100644
--- a/samples-dev/swarm/swarm_ui_lib/observable/ChangeEvent.dart
+++ b/samples-dev/swarm/swarm_ui_lib/observable/ChangeEvent.dart
@@ -4,58 +4,54 @@
 
 part of observable;
 
-/** A change to an observable instance. */
+/// A change to an observable instance. */
 class ChangeEvent {
   // TODO(sigmund): capture language issues around enums & create a canonical
   // Dart enum design.
-  /** Type denoting an in-place update event. */
+  /// Type denoting an in-place update event. */
   static const UPDATE = 0;
 
-  /** Type denoting an insertion event. */
+  /// Type denoting an insertion event. */
   static const INSERT = 1;
 
-  /** Type denoting a single-remove event. */
+  /// Type denoting a single-remove event. */
   static const REMOVE = 2;
 
-  /**
-   * Type denoting events that affect the entire observable instance. For
-   * example, a list operation like clear or sort.
-   */
+  /// Type denoting events that affect the entire observable instance. For
+  /// example, a list operation like clear or sort.
   static const GLOBAL = 3;
 
-  /** The observable instance that changed. */
+  /// The observable instance that changed. */
   final Observable target;
 
-  /** Whether the change was an [INSERT], [REMOVE], or [UPDATE]. */
+  /// Whether the change was an [INSERT], [REMOVE], or [UPDATE]. */
   final int type;
 
-  /** The value after the change (or inserted value in a list). */
+  /// The value after the change (or inserted value in a list). */
   final newValue;
 
-  /** The value before the change (or removed value from a list). */
+  /// The value before the change (or removed value from a list). */
   final oldValue;
 
-  /** Property that changed (null for list changes). */
+  /// Property that changed (null for list changes). */
   final String? propertyName;
 
-  /**
-   * Index of the list operation. Insertions prepend in front of the given
-   * index (insert at 0 means an insertion at the beginning of the list).
-   */
+  /// Index of the list operation. Insertions prepend in front of the given
+  /// index (insert at 0 means an insertion at the beginning of the list).
   final int? index;
 
-  /** Factory constructor for property change events. */
+  /// Factory constructor for property change events. */
   ChangeEvent.property(
       this.target, this.propertyName, this.newValue, this.oldValue)
       : type = UPDATE,
         index = null;
 
-  /** Factory constructor for list change events. */
+  /// Factory constructor for list change events. */
   ChangeEvent.list(
       this.target, this.type, this.index, this.newValue, this.oldValue)
       : propertyName = null;
 
-  /** Factory constructor for [GLOBAL] change events. */
+  /// Factory constructor for [GLOBAL] change events. */
   ChangeEvent.global(this.target)
       : type = GLOBAL,
         newValue = null,
@@ -64,7 +60,7 @@
         index = null;
 }
 
-/** A collection of change events on a single observable instance. */
+/// A collection of change events on a single observable instance. */
 class EventSummary {
   final Observable target;
 
@@ -77,9 +73,9 @@
     events.add(e);
   }
 
-  /** Notify listeners of [target] and parents of [target] about all changes. */
+  /// Notify listeners of [target] and parents of [target] about all changes. */
   void notify() {
-    if (!events.isEmpty) {
+    if (events.isNotEmpty) {
       for (Observable? obj = target; obj != null; obj = obj.parent) {
         for (final listener in obj.listeners) {
           listener(this);
@@ -89,5 +85,5 @@
   }
 }
 
-/** A listener of change events. */
-typedef void ChangeListener(EventSummary events);
+/// A listener of change events. */
+typedef ChangeListener = void Function(EventSummary events);
diff --git a/samples-dev/swarm/swarm_ui_lib/observable/EventBatch.dart b/samples-dev/swarm/swarm_ui_lib/observable/EventBatch.dart
index 53eaa99..7eed98f 100644
--- a/samples-dev/swarm/swarm_ui_lib/observable/EventBatch.dart
+++ b/samples-dev/swarm/swarm_ui_lib/observable/EventBatch.dart
@@ -4,43 +4,37 @@
 
 part of observable;
 
-/**
- * Accumulates change events from several observable objects.
- *
- * wrap() is public and used by client code.  The other methods are used by
- * AbstractObservable, which works with this class to implement batching.
- */
+/// Accumulates change events from several observable objects.
+///
+/// wrap() is public and used by client code.  The other methods are used by
+/// AbstractObservable, which works with this class to implement batching.
 class EventBatch {
-  /** The current active batch, if any. */
+  /// The current active batch, if any. */
   static EventBatch? current;
 
-  /** Used to generate unique ids for observable objects. */
+  /// Used to generate unique ids for observable objects. */
   static int nextUid = 1;
 
-  /** Map from observable object's uid to their tracked events. */
+  /// Map from observable object's uid to their tracked events. */
   // TODO(sigmund): use [Observable] instead of [int] when [Map] can support it,
   Map<int, EventSummary> summaries;
 
-  /** Whether this batch is currently firing and therefore is sealed. */
+  /// Whether this batch is currently firing and therefore is sealed. */
   bool sealed = false;
 
-  /**
-   * Private constructor that shouldn't be used externally. Use [wrap] to ensure
-   * that a batch exists when running a function.
-   */
-  EventBatch._internal() : summaries = Map<int, EventSummary>();
+  /// Private constructor that shouldn't be used externally. Use [wrap] to ensure
+  /// that a batch exists when running a function.
+  EventBatch._internal() : summaries = <int, EventSummary>{};
 
-  /**
-   * Ensure there is an event batch where [userFunction] can accumulate events.
-   * When the batch is complete, fire all events at once.
-   */
+  /// Ensure there is an event batch where [userFunction] can accumulate events.
+  /// When the batch is complete, fire all events at once.
   static Function wrap(userFunction(var a)) {
     return (e) {
       if (current == null) {
         // Not in a batch so create one.
         final batch = EventBatch._internal();
         current = batch;
-        var result = null;
+        var result;
         try {
           // TODO(jmesserly): don't return here, otherwise an exception in
           // the finally clause will cause it to rerun. See bug#5350131.
@@ -74,12 +68,12 @@
     };
   }
 
-  /** Returns a unique global id for observable objects. */
+  /// Returns a unique global id for observable objects. */
   static int genUid() {
     return nextUid++;
   }
 
-  /** Retrieves the events associated with {@code obj}. */
+  /// Retrieves the events associated with {@code obj}. */
   EventSummary getEvents(Observable obj) {
     int uid = obj.uid;
     EventSummary? summary = summaries[uid];
@@ -91,7 +85,7 @@
     return summary;
   }
 
-  /** Fires all events at once. */
+  /// Fires all events at once. */
   void _notify() {
     assert(!sealed);
     sealed = true;
diff --git a/samples-dev/swarm/swarm_ui_lib/observable/observable.dart b/samples-dev/swarm/swarm_ui_lib/observable/observable.dart
index c91bb88..990d8d9 100644
--- a/samples-dev/swarm/swarm_ui_lib/observable/observable.dart
+++ b/samples-dev/swarm/swarm_ui_lib/observable/observable.dart
@@ -7,61 +7,59 @@
 part 'ChangeEvent.dart';
 part 'EventBatch.dart';
 
-/**
- * An object whose changes are tracked and who can issue events notifying how it
- * has been changed.
- */
+/// An object whose changes are tracked and who can issue events notifying how it
+/// has been changed.
 abstract class Observable {
-  /** Returns a globally unique identifier for the object. */
+  /// Returns a globally unique identifier for the object. */
   // TODO(sigmund): remove once dart supports maps with arbitrary keys.
   int get uid;
 
-  /** Listeners on this model. */
+  /// Listeners on this model. */
   List<ChangeListener> get listeners;
 
-  /** The parent observable to notify when this child is changed. */
+  /// The parent observable to notify when this child is changed. */
   Observable? get parent;
 
-  /**
-   * Adds a listener for changes on this observable instance. Returns whether
-   * the listener was added successfully.
-   */
+  /// Adds a listener for changes on this observable instance. Returns whether
+  /// the listener was added successfully.
   bool addChangeListener(ChangeListener listener);
 
-  /**
-   * Removes a listener for changes on this observable instance. Returns whether
-   * the listener was removed successfully.
-   */
+  /// Removes a listener for changes on this observable instance. Returns whether
+  /// the listener was removed successfully.
   bool removeChangeListener(ChangeListener listener);
 }
 
-/** Common functionality for observable objects. */
+/// Common functionality for observable objects. */
 class AbstractObservable implements Observable {
-  /** Unique id to identify this model in an event batch. */
+  /// Unique id to identify this model in an event batch. */
+  @override
   final int uid;
 
-  /** The parent observable to notify when this child is changed. */
+  /// The parent observable to notify when this child is changed. */
+  @override
   final Observable? parent;
 
-  /** Listeners on this model. */
+  /// Listeners on this model. */
+  @override
   List<ChangeListener> listeners;
 
-  /** Whether this object is currently observed by listeners or propagators. */
+  /// Whether this object is currently observed by listeners or propagators. */
   bool get isObserved {
     for (Observable? obj = this; obj != null; obj = obj.parent) {
-      if (listeners.length > 0) {
+      if (listeners.isNotEmpty) {
         return true;
       }
     }
     return false;
   }
 
-  AbstractObservable([this.parent = null])
+  AbstractObservable([this.parent])
       : uid = EventBatch.genUid(),
         listeners = List<ChangeListener>.empty();
 
+  @override
   bool addChangeListener(ChangeListener listener) {
-    if (listeners.indexOf(listener, 0) == -1) {
+    if (!listeners.contains(listener)) {
       listeners.add(listener);
       return true;
     }
@@ -69,6 +67,7 @@
     return false;
   }
 
+  @override
   bool removeChangeListener(ChangeListener listener) {
     var index = listeners.indexOf(listener, 0);
     if (index != -1) {
@@ -126,62 +125,77 @@
   }
 }
 
-/** A growable list that fires events when it's modified. */
+/// A growable list that fires events when it's modified. */
 class ObservableList<T> extends AbstractObservable
     implements List<T>, Observable {
-  /** Underlying list. */
+  /// Underlying list. */
   // TODO(rnystrom): Make this final if we get list.remove().
-  List<T> _internal;
+  final List<T> _internal;
 
-  ObservableList([Observable? parent = null])
+  ObservableList([Observable? parent])
       : _internal = List<T>.empty(),
         super(parent);
 
+  @override
   T operator [](int index) => _internal[index];
 
+  @override
   void operator []=(int index, T value) {
     recordListUpdate(index, value, _internal[index]);
     _internal[index] = value;
   }
 
+  @override
   int get length => _internal.length;
 
+  @override
   List<R> cast<R>() => _internal.cast<R>();
+  @override
   Iterable<R> whereType<R>() => _internal.whereType<R>();
 
+  @override
   List<T> operator +(List<T> other) => _internal + other;
 
+  @override
   Iterable<T> followedBy(Iterable<T> other) => _internal.followedBy(other);
 
-  int indexWhere(bool test(T element), [int start = 0]) =>
+  @override
+  int indexWhere(bool Function(T element) test, [int start = 0]) =>
       _internal.indexWhere(test, start);
 
-  int lastIndexWhere(bool test(T element), [int? start]) =>
+  @override
+  int lastIndexWhere(bool Function(T element) test, [int? start]) =>
       _internal.lastIndexWhere(test, start);
 
-  void set length(int value) {
+  @override
+  set length(int value) {
     _internal.length = value;
     recordGlobalChange();
   }
 
+  @override
   void clear() {
     _internal.clear();
     recordGlobalChange();
   }
 
+  @override
   Iterable<T> get reversed => _internal.reversed;
 
-  void sort([int compare(T a, T b)?]) {
+  @override
+  void sort([int Function(T a, T b)? compare]) {
     //if (compare == null) compare = (u, v) => Comparable.compare(u, v);
     _internal.sort(compare);
     recordGlobalChange();
   }
 
+  @override
   void add(T element) {
     recordListInsert(length, element);
     _internal.add(element);
   }
 
+  @override
   void addAll(Iterable<T> elements) {
     for (T element in elements) {
       add(element);
@@ -194,49 +208,61 @@
     return _internal.length;
   }
 
+  @override
   T get first => _internal.first;
-  void set first(T value) {
+  @override
+  set first(T value) {
     _internal.first = value;
   }
 
+  @override
   T get last => _internal.last;
-  void set last(T value) {
+  @override
+  set last(T value) {
     _internal.last = value;
   }
 
+  @override
   T get single => _internal.single;
 
+  @override
   void insert(int index, T element) {
     _internal.insert(index, element);
     recordListInsert(index, element);
   }
 
+  @override
   void insertAll(int index, Iterable<T> iterable) {
     throw UnimplementedError();
   }
 
+  @override
   void setAll(int index, Iterable<T> iterable) {
     throw UnimplementedError();
   }
 
+  @override
   T removeLast() {
     final result = _internal.removeLast();
     recordListRemove(length, result);
     return result;
   }
 
+  @override
   T removeAt(int index) {
     T result = _internal.removeAt(index);
     recordListRemove(index, result);
     return result;
   }
 
+  @override
   int indexOf(T element, [int start = 0]) {
     return _internal.indexOf(element, start);
   }
 
+  @override
   int lastIndexOf(T element, [int? start]) {
-    if (start == null) start = length - 1;
+    start ??= length - 1;
     return _internal.lastIndexOf(element, start);
   }
 
@@ -261,8 +287,8 @@
 
   void copyFrom(List<T> src, int? srcStart, int? dstStart, int count) {
     List dst = this;
-    if (srcStart == null) srcStart = 0;
-    if (dstStart == null) dstStart = 0;
+    srcStart ??= 0;
+    dstStart ??= 0;
 
     if (srcStart < dstStart) {
       for (int i = srcStart + count - 1, j = dstStart + count - 1;
@@ -277,88 +303,125 @@
     }
   }
 
+  @override
   void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) {
     throw UnimplementedError();
   }
 
+  @override
   void removeRange(int start, int end) {
     throw UnimplementedError();
   }
 
+  @override
   void replaceRange(int start, int end, Iterable<T> iterable) {
     throw UnimplementedError();
   }
 
+  @override
   void fillRange(int start, int end, [T? fillValue]) {
     throw UnimplementedError();
   }
 
+  @override
   List<T> sublist(int start, [int? end]) {
     throw UnimplementedError();
   }
 
+  @override
   Iterable<T> getRange(int start, int end) {
     throw UnimplementedError();
   }
 
+  @override
   bool contains(Object? element) {
     throw UnimplementedError();
   }
 
-  T reduce(T combine(T previousValue, T element)) {
+  @override
+  T reduce(T Function(T previousValue, T element) combine) {
     throw UnimplementedError();
   }
 
-  R fold<R>(R initialValue, R combine(R previousValue, T element)) {
+  @override
+  R fold<R>(R initialValue, R Function(R previousValue, T element) combine) {
     throw UnimplementedError();
   }
 
   // Iterable<T>:
+  @override
   Iterator<T> get iterator => _internal.iterator;
 
-  Iterable<T> where(bool f(T element)) => _internal.where(f);
-  Iterable<R> map<R>(R f(T element)) => _internal.map(f);
-  Iterable<R> expand<R>(Iterable<R> f(T element)) => _internal.expand(f);
+  @override
+  Iterable<T> where(bool Function(T element) f) => _internal.where(f);
+  @override
+  Iterable<R> map<R>(R Function(T element) f) => _internal.map(f);
+  @override
+  Iterable<R> expand<R>(Iterable<R> Function(T element) f) =>
+      _internal.expand(f);
+  @override
   List<T> skip(int count) => _internal.skip(count) as List<T>;
+  @override
   List<T> take(int count) => _internal.take(count) as List<T>;
-  bool every(bool f(T element)) => _internal.every(f);
-  bool any(bool f(T element)) => _internal.any(f);
-  void forEach(void f(T element)) {
+  @override
+  bool every(bool Function(T element) f) => _internal.every(f);
+  @override
+  bool any(bool Function(T element) f) => _internal.any(f);
+  @override
+  void forEach(void Function(T element) f) {
     _internal.forEach(f);
   }
 
+  @override
   String join([String separator = ""]) => _internal.join(separator);
-  T firstWhere(bool test(T value), {T orElse()?}) {
+  @override
+  T firstWhere(bool Function(T value) test, {T Function()? orElse}) {
     return _internal.firstWhere(test, orElse: orElse);
   }
 
-  T lastWhere(bool test(T value), {T orElse()?}) {
+  @override
+  T lastWhere(bool Function(T value) test, {T Function()? orElse}) {
     return _internal.lastWhere(test, orElse: orElse);
   }
 
+  @override
   void shuffle([random]) => throw UnimplementedError();
+  @override
   bool remove(Object? element) => throw UnimplementedError();
-  void removeWhere(bool test(T element)) => throw UnimplementedError();
-  void retainWhere(bool test(T element)) => throw UnimplementedError();
-  List<T> toList({bool growable: true}) => throw UnimplementedError();
+  @override
+  void removeWhere(bool Function(T element) test) => throw UnimplementedError();
+  @override
+  void retainWhere(bool Function(T element) test) => throw UnimplementedError();
+  @override
+  List<T> toList({bool growable = true}) => throw UnimplementedError();
+  @override
   Set<T> toSet() => throw UnimplementedError();
-  Iterable<T> takeWhile(bool test(T value)) => throw UnimplementedError();
-  Iterable<T> skipWhile(bool test(T value)) => throw UnimplementedError();
+  @override
+  Iterable<T> takeWhile(bool Function(T value) test) =>
+      throw UnimplementedError();
+  @override
+  Iterable<T> skipWhile(bool Function(T value) test) =>
+      throw UnimplementedError();
 
-  T singleWhere(bool test(T value), {T orElse()?}) {
+  @override
+  T singleWhere(bool Function(T value) test, {T Function()? orElse}) {
     return _internal.singleWhere(test, orElse: orElse);
   }
 
+  @override
   T elementAt(int index) {
     return _internal.elementAt(index);
   }
 
+  @override
   Map<int, T> asMap() {
     return _internal.asMap();
   }
 
+  @override
   bool get isEmpty => length == 0;
 
+  @override
   bool get isNotEmpty => !isEmpty;
 }
 
@@ -368,15 +431,15 @@
 // much. Also, making a value observable necessitates adding ".value" to lots
 // of places, and constructing all fields with the verbose
 // "ObservableValue<DataType>(myValue)".
-/** A wrapper around a single value whose change can be observed. */
+/// A wrapper around a single value whose change can be observed. */
 class ObservableValue<T> extends AbstractObservable {
-  ObservableValue(T value, [Observable? parent = null])
+  ObservableValue(T value, [Observable? parent])
       : _value = value,
         super(parent);
 
   T get value => _value;
 
-  void set value(T newValue) {
+  set value(T newValue) {
     // Only fire on an actual change.
     if (!identical(newValue, _value)) {
       final oldValue = _value;
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/BezierPhysics.dart b/samples-dev/swarm/swarm_ui_lib/touch/BezierPhysics.dart
index 65900d82..9626ae5 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/BezierPhysics.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/BezierPhysics.dart
@@ -6,40 +6,34 @@
 
 part of touch;
 
-/**
- * Functions to model constant acceleration as a cubic Bezier
- * curve (http://en.wikipedia.org/wiki/Bezier_curve). These functions are
- * intended to generate the transition timing function for CSS transitions.
- * Please see
- * [http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag].
- *
- * The main operation of computing a cubic Bezier is split up into multiple
- * functions so that, should it be required, more operations and cases can be
- * supported in the future.
- */
+/// Functions to model constant acceleration as a cubic Bezier
+/// curve (http://en.wikipedia.org/wiki/Bezier_curve). These functions are
+/// intended to generate the transition timing function for CSS transitions.
+/// Please see
+/// [http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag].
+///
+/// The main operation of computing a cubic Bezier is split up into multiple
+/// functions so that, should it be required, more operations and cases can be
+/// supported in the future.
 class BezierPhysics {
   static const _ONE_THIRD = 1 / 3;
   static const _TWO_THIRDS = 2 / 3;
 
-  /**
-   * A list [:[x1, y1, x2, y2]:] of the intermediate control points of a cubic
-   * bezier when the final velocity is zero. This is a special case for which
-   * these control points are constants.
-   */
-  static const List<num> _FINAL_VELOCITY_ZERO_BEZIER = const [
+  /// A list [:[x1, y1, x2, y2]:] of the intermediate control points of a cubic
+  /// bezier when the final velocity is zero. This is a special case for which
+  /// these control points are constants.
+  static const List<num> _FINAL_VELOCITY_ZERO_BEZIER = [
     _ONE_THIRD,
     _TWO_THIRDS,
     _TWO_THIRDS,
     1
   ];
 
-  /**
-   * Given consistent kinematics parameters for constant acceleration, returns
-   * the intermediate control points of the cubic Bezier curve that models the
-   * motion. All input values must have correct signs.
-   * Returns a list [:[x1, y1, x2, y2]:] representing the intermediate control
-   *     points of the cubic Bezier.
-   */
+  /// Given consistent kinematics parameters for constant acceleration, returns
+  /// the intermediate control points of the cubic Bezier curve that models the
+  /// motion. All input values must have correct signs.
+  /// Returns a list [:[x1, y1, x2, y2]:] representing the intermediate control
+  ///     points of the cubic Bezier.
   static List<num> calculateCubicBezierFromKinematics(num initialVelocity,
       num finalVelocity, num totalTime, num totalDisplacement) {
     // Total time must be greater than 0.
@@ -61,18 +55,16 @@
     return _quadraticToCubic(controlPoint[0], controlPoint[1]);
   }
 
-  /**
-   * Given a quadratic curve crossing points (0, 0) and (x2, y2), calculates the
-   * intermediate control point (x1, y1) of the equivalent quadratic Bezier
-   * curve with starting point (0, 0) and ending point (x2, y2).
-   * [m0] The slope of the line tangent to the curve at (0, 0).
-   * [m2] The slope of the line tangent to the curve at a different
-   *     point (x2, y2).
-   * [x2] The x-coordinate of the other point on the curve.
-   * [y2] The y-coordinate of the other point on the curve.
-   * Returns a list [:[x1, y1]:] representing the intermediate
-   *     control point of the quadratic Bezier.
-   */
+  /// Given a quadratic curve crossing points (0, 0) and (x2, y2), calculates the
+  /// intermediate control point (x1, y1) of the equivalent quadratic Bezier
+  /// curve with starting point (0, 0) and ending point (x2, y2).
+  /// [m0] The slope of the line tangent to the curve at (0, 0).
+  /// [m2] The slope of the line tangent to the curve at a different
+  ///     point (x2, y2).
+  /// [x2] The x-coordinate of the other point on the curve.
+  /// [y2] The y-coordinate of the other point on the curve.
+  /// Returns a list [:[x1, y1]:] representing the intermediate
+  ///     control point of the quadratic Bezier.
   static List<num> _tangentLinesToQuadraticBezier(
       num m0, num m2, num x2, num y2) {
     if (GoogleMath.nearlyEquals(m0, m2)) {
@@ -83,30 +75,26 @@
     return [x1, y1];
   }
 
-  /**
-   * Normalizes a quadratic Bezier curve to have end point at (1, 1).
-   * [x1] The x-coordinate of the intermediate control point.
-   * [y1] The y-coordinate of the intermediate control point.
-   * [x2] The x-coordinate of the end point.
-   * [y2] The y-coordinate of the end point.
-   * Returns a list [:[x1, y1]:] representing the intermediate control point.
-   */
+  /// Normalizes a quadratic Bezier curve to have end point at (1, 1).
+  /// [x1] The x-coordinate of the intermediate control point.
+  /// [y1] The y-coordinate of the intermediate control point.
+  /// [x2] The x-coordinate of the end point.
+  /// [y2] The y-coordinate of the end point.
+  /// Returns a list [:[x1, y1]:] representing the intermediate control point.
   static List<num> _normalizeQuadraticBezier(num x1, num y1, num x2, num y2) {
     // The end point must not lie on any axes.
     assert(!GoogleMath.nearlyEquals(x2, 0) && !GoogleMath.nearlyEquals(y2, 0));
     return [x1 / x2, y1 / y2];
   }
 
-  /**
-   * Converts a quadratic Bezier curve defined by the control points
-   * (x0, y0) = (0, 0), (x1, y1) = (x, y), and (x2, y2) = (1, 1) into an
-   * equivalent cubic Bezier curve with four control points. Note that the start
-   * and end points will be unchanged.
-   * [x] The x-coordinate of the intermediate control point.
-   * [y] The y-coordinate of the intermediate control point.
-   * Returns a list [:[x1, y1, x2, y2]:] containing the two
-   *     intermediate points of the equivalent cubic Bezier curve.
-   */
+  /// Converts a quadratic Bezier curve defined by the control points
+  /// (x0, y0) = (0, 0), (x1, y1) = (x, y), and (x2, y2) = (1, 1) into an
+  /// equivalent cubic Bezier curve with four control points. Note that the start
+  /// and end points will be unchanged.
+  /// [x] The x-coordinate of the intermediate control point.
+  /// [y] The y-coordinate of the intermediate control point.
+  /// Returns a list [:[x1, y1, x2, y2]:] containing the two
+  ///     intermediate points of the equivalent cubic Bezier curve.
   static List<num> _quadraticToCubic(num x, num y) {
     // The intermediate control point must have coordinates within the
     // interval [0,1].
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/ClickBuster.dart b/samples-dev/swarm/swarm_ui_lib/touch/ClickBuster.dart
index 6f942b4..06f1740 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/ClickBuster.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/ClickBuster.dart
@@ -6,57 +6,47 @@
 
 part of touch;
 
-/**
- * Click buster implementation, which is a behavior that prevents native clicks
- * from firing at undesirable times. There are two scenarios where we may want
- * to 'bust' a click.
- *
- * Buttons implemented with touch events usually have click handlers as well.
- * This is because sometimes touch events stop working, and the click handler
- * serves as a fallback. Here we use a click buster to prevent the native click
- * from firing if the touchend event was successfully handled.
- *
- * When native scrolling behavior is disabled (see Scroller), click events will
- * fire after the touchend event when the drag sequence is complete. The click
- * event also happens to fire at the location of the touchstart event which can
- * lead to some very strange behavior.
- *
- * This class puts a single click handler on the body, and calls preventDefault
- * on the click event if we detect that there was a touchend event that already
- * fired in the same spot recently.
- */
+/// Click buster implementation, which is a behavior that prevents native clicks
+/// from firing at undesirable times. There are two scenarios where we may want
+/// to 'bust' a click.
+///
+/// Buttons implemented with touch events usually have click handlers as well.
+/// This is because sometimes touch events stop working, and the click handler
+/// serves as a fallback. Here we use a click buster to prevent the native click
+/// from firing if the touchend event was successfully handled.
+///
+/// When native scrolling behavior is disabled (see Scroller), click events will
+/// fire after the touchend event when the drag sequence is complete. The click
+/// event also happens to fire at the location of the touchstart event which can
+/// lead to some very strange behavior.
+///
+/// This class puts a single click handler on the body, and calls preventDefault
+/// on the click event if we detect that there was a touchend event that already
+/// fired in the same spot recently.
 class ClickBuster {
-  /**
-   * The threshold for how long we allow a click to occur after a touchstart.
-   */
+  /// The threshold for how long we allow a click to occur after a touchstart.
   static const _TIME_THRESHOLD = 2500;
 
-  /**
-   * The threshold for how close a click has to be to the saved coordinate for
-   * us to allow it.
-   */
+  /// The threshold for how close a click has to be to the saved coordinate for
+  /// us to allow it.
   static const _DISTANCE_THRESHOLD = 25;
 
-  /**
-   * The list of coordinates that we use to measure the distance of clicks from.
-   * If a click is within the distance threshold of any of these coordinates
-   * then we allow the click.
-   */
+  /// The list of coordinates that we use to measure the distance of clicks from.
+  /// If a click is within the distance threshold of any of these coordinates
+  /// then we allow the click.
   static DoubleLinkedQueue<num> _coordinates;
 
-  /** The last time preventGhostClick was called. */
+  /// The last time preventGhostClick was called. */
   static int _lastPreventedTime;
 
-  /**
-   * This handler will prevent the default behavior for any clicks unless the
-   * click is within the distance threshold of one of the temporary allowed
-   * coordinates.
-   */
+  /// This handler will prevent the default behavior for any clicks unless the
+  /// click is within the distance threshold of one of the temporary allowed
+  /// coordinates.
   static void _onClick(Event e) {
     if (TimeUtil.now() - _lastPreventedTime > _TIME_THRESHOLD) {
       return;
     }
-    final coord = new Coordinate.fromClient(e);
+    final coord = Coordinate.fromClient(e);
     // TODO(rnystrom): On Android, we get spurious click events at (0, 0). We
     // *do* want those clicks to be busted, so commenting this out fixes it.
     // Leaving it commented out instead of just deleting it because I'm not sure
@@ -87,33 +77,27 @@
     e.preventDefault();
   }
 
-  /**
-   * This handler will temporarily allow a click to occur near the touch event's
-   * coordinates.
-   */
+  /// This handler will temporarily allow a click to occur near the touch event's
+  /// coordinates.
   static void _onTouchStart(Event e) {
     TouchEvent te = e;
-    final coord = new Coordinate.fromClient(te.touches[0]);
+    final coord = Coordinate.fromClient(te.touches[0]);
     _coordinates.add(coord.x);
     _coordinates.add(coord.y);
-    new Timer(const Duration(milliseconds: _TIME_THRESHOLD), () {
+    Timer(const Duration(milliseconds: _TIME_THRESHOLD), () {
       _removeCoordinate(coord.x, coord.y);
     });
     _toggleTapHighlights(true);
   }
 
-  /**
-   * Hit test for whether a coordinate is within the distance threshold of an
-   * event.
-   */
+  /// Hit test for whether a coordinate is within the distance threshold of an
+  /// event.
   static bool _hitTest(num x, num y, num eventX, num eventY) {
     return (eventX - x).abs() < _DISTANCE_THRESHOLD &&
         (eventY - y).abs() < _DISTANCE_THRESHOLD;
   }
 
-  /**
-   * Remove one specified coordinate from the coordinates list.
-   */
+  /// Remove one specified coordinate from the coordinates list.
   static void _removeCoordinate(num x, num y) {
     DoubleLinkedQueueEntry<num> entry = _coordinates.firstEntry();
     while (entry != null) {
@@ -127,26 +111,22 @@
     }
   }
 
-  /**
-   * Enable or disable tap highlights. They are disabled when preventGhostClick
-   * is called so that the flicker on links is not invoked when the ghost click
-   * does fire. This is due to a bug: links get highlighted even if the click
-   * event has preventDefault called on it.
-   */
+  /// Enable or disable tap highlights. They are disabled when preventGhostClick
+  /// is called so that the flicker on links is not invoked when the ghost click
+  /// does fire. This is due to a bug: links get highlighted even if the click
+  /// event has preventDefault called on it.
   static void _toggleTapHighlights(bool enable) {
     document.body.style.setProperty(
         "-webkit-tap-highlight-color", enable ? "" : "rgba(0,0,0,0)", "");
   }
 
-  /**
-   * Registers new touches to create temporary "allowable zones" and registers
-   * new clicks to be prevented unless they fall in one of the current
-   * "allowable zones". Note that if the touchstart and touchend locations are
-   * different, it is still possible for a ghost click to be fired if you
-   * called preventDefault on all touchmove events. In this case the ghost
-   * click will be fired at the location of the touchstart event, so the
-   * coordinate you pass in should be the coordinate of the touchstart.
-   */
+  /// Registers new touches to create temporary "allowable zones" and registers
+  /// new clicks to be prevented unless they fall in one of the current
+  /// "allowable zones". Note that if the touchstart and touchend locations are
+  /// different, it is still possible for a ghost click to be fired if you
+  /// called preventDefault on all touchmove events. In this case the ghost
+  /// click will be fired at the location of the touchstart event, so the
+  /// coordinate you pass in should be the coordinate of the touchstart.
   static void preventGhostClick(num x, num y) {
     // First time this is called the following occurs:
     //   1) Attaches a handler to touchstart events so that each touch will
@@ -196,14 +176,14 @@
       if (!Device.supportsTouch) {
         startFn = mouseToTouchCallback(startFn);
       }
-      var stream;
+      Stream<UIEvent> stream;
       if (Device.supportsTouch) {
         stream = Element.touchStartEvent.forTarget(document, useCapture: true);
       } else {
         stream = Element.mouseDownEvent.forTarget(document, useCapture: true);
       }
       EventUtil.observe(document, stream, startFn, true);
-      _coordinates = new DoubleLinkedQueue<num>();
+      _coordinates = DoubleLinkedQueue<num>();
     }
 
     // Turn tap highlights off until we know the ghost click has fired.
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/EventUtil.dart b/samples-dev/swarm/swarm_ui_lib/touch/EventUtil.dart
index fc71bb7..543df42 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/EventUtil.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/EventUtil.dart
@@ -7,17 +7,13 @@
 
 part of touch;
 
-/**
- * Common events related helpers.
- */
+/// Common events related helpers.
 class EventUtil {
-  /**
-   * Add an event listener to an element.
-   * The event callback is specified by [handler].
-   * If [capture] is true, the listener gets events on the capture phase.
-   * If [removeHandlerOnFocus] is true the handler is removed when there is any
-   * focus event, and added back on blur events.
-   */
+  /// Add an event listener to an element.
+  /// The event callback is specified by [handler].
+  /// If [capture] is true, the listener gets events on the capture phase.
+  /// If [removeHandlerOnFocus] is true the handler is removed when there is any
+  /// focus event, and added back on blur events.
   static void observe(
       /*Element or Document*/ element, Stream stream, Function handler,
       [bool removeHandlerOnFocus = false]) {
@@ -33,11 +29,9 @@
     }
   }
 
-  /**
-   * Clear the keyboard focus of the currently focused element (if there is
-   * one). If there is no currently focused element then this function will do
-   * nothing. For most browsers this will cause the keyboard to be dismissed.
-   */
+  /// Clear the keyboard focus of the currently focused element (if there is
+  /// one). If there is no currently focused element then this function will do
+  /// nothing. For most browsers this will cause the keyboard to be dismissed.
   static void blurFocusedElement() {
     Element focusedEl = document.querySelector("*:focus");
     if (focusedEl != null) {
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart b/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart
index e543a59..1267b856 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/FxUtil.dart
@@ -6,23 +6,21 @@
 
 part of touch;
 
-/**
- * Common effects related helpers.
- */
+/// Common effects related helpers.
 class FxUtil {
-  /** On transition end event. */
+  /// On transition end event. */
   static const TRANSITION_END_EVENT = 'webkitTransitionEnd';
 
-  /** The translate3d transform function. */
+  /// The translate3d transform function. */
   static const TRANSLATE_3D = 'translate3d';
 
-  /** The rotate transform function. */
+  /// The rotate transform function. */
   static const ROTATE = 'rotate';
 
-  /** The scale transform function. */
+  /// The scale transform function. */
   static const SCALE = 'scale';
 
-  /** Stops and clears the transition on an element. */
+  /// Stops and clears the transition on an element. */
   static void clearWebkitTransition(Element el) {
     el.style.transition = '';
   }
@@ -30,31 +28,27 @@
   static void setPosition(Element el, Coordinate point) {
     num x = point.x;
     num y = point.y;
-    el.style.transform = '${TRANSLATE_3D}(${x}px,${y}px,0px)';
+    el.style.transform = '$TRANSLATE_3D(${x}px,${y}px,0px)';
   }
 
-  /** Apply a transform using translate3d to an HTML element. */
+  /// Apply a transform using translate3d to an HTML element. */
   static void setTranslate(Element el, num x, num y, num z) {
-    el.style.transform = '${TRANSLATE_3D}(${x}px,${y}px,${z}px)';
+    el.style.transform = '$TRANSLATE_3D(${x}px,${y}px,${z}px)';
   }
 
-  /** Apply a -webkit-transform using translate3d to an HTML element. */
+  /// Apply a -webkit-transform using translate3d to an HTML element. */
   static void setWebkitTransform(Element el, num x, num y,
-      [num z = 0,
-      num rotation = null,
-      num scale = null,
-      num originX = null,
-      num originY = null]) {
+      [num z = 0, num rotation, num scale, num originX, num originY]) {
     final style = el.style;
     // TODO(jacobr): create a helper class that simplifies building
     // transformation matricies that will be set as CSS styles. We should
     // consider using CSSMatrix although that may be overkill.
-    String transform = '${TRANSLATE_3D}(${x}px,${y}px,${z}px)';
+    String transform = '$TRANSLATE_3D(${x}px,${y}px,${z}px)';
     if (rotation != null) {
-      transform += ' ${ROTATE}(${rotation}deg)';
+      transform += ' $ROTATE(${rotation}deg)';
     }
     if (scale != null) {
-      transform += ' ${SCALE}(${scale})';
+      transform += ' $SCALE($scale)';
     }
     style.transform = transform;
     if (originX != null || originY != null) {
@@ -63,15 +57,13 @@
     }
   }
 
-  /**
-   * Determine the position of an [element] relative to a [target] element.
-   * Moving the [element] to be a child of [target] and setting the
-   * [element]'s top and left values to the returned coordinate should result
-   * in the [element]'s position remaining unchanged while its parent is
-   * changed.
-   */
+  /// Determine the position of an [element] relative to a [target] element.
+  /// Moving the [element] to be a child of [target] and setting the
+  /// [element]'s top and left values to the returned coordinate should result
+  /// in the [element]'s position remaining unchanged while its parent is
+  /// changed.
   static Coordinate computeRelativePosition(Element element, Element target) {
-    final testPoint = new Point(0, 0);
+    final testPoint = Point(0, 0);
     /*
     final pagePoint =
         window.convertPointFromNodeToPage(element, testPoint);
@@ -83,25 +75,21 @@
     // `convertPointFromPageToNode`.
     var eRect = element.getBoundingClientRect();
     var tRect = target.getBoundingClientRect();
-    return new Coordinate(eRect.left - tRect.left, eRect.top - tRect.top);
+    return Coordinate(eRect.left - tRect.left, eRect.top - tRect.top);
   }
 
-  /** Clear a -webkit-transform from an element. */
+  /// Clear a -webkit-transform from an element. */
   static void clearWebkitTransform(Element el) {
     el.style.transform = '';
   }
 
-  /**
-   * Checks whether an element has a translate3d webkit transform applied.
-   */
+  /// Checks whether an element has a translate3d webkit transform applied.
   static bool hasWebkitTransform(Element el) {
-    return el.style.transform.indexOf(TRANSLATE_3D, 0) != -1;
+    return el.style.transform.contains(TRANSLATE_3D, 0);
   }
 
-  /**
-   * Translates [el], an HTML element that has a relative CSS
-   * position, by setting its left and top CSS styles.
-   */
+  /// Translates [el], an HTML element that has a relative CSS
+  /// position, by setting its left and top CSS styles.
   static void setLeftAndTop(Element el, num x, num y) {
     final style = el.style;
     style.left = '${x}px';
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Geometry.dart b/samples-dev/swarm/swarm_ui_lib/touch/Geometry.dart
index fcd7398..43f7231 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Geometry.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Geometry.dart
@@ -6,30 +6,22 @@
 
 part of touch;
 
-/**
- * Represents a point in 2 dimensional space.
- */
+/// Represents a point in 2 dimensional space.
 class Coordinate {
-  /**
-   * X-value
-   */
+  /// X-value
   num x;
 
-  /**
-   * Y-value
-   */
+  /// Y-value
   num y;
 
-  Coordinate([num this.x = 0, num this.y = 0]) {}
+  Coordinate([this.x = 0, this.y = 0]);
 
-  /**
-   * Gets the coordinates of a touch's location relative to the window's
-   * viewport. [input] is either a touch object or an event object.
-   */
+  /// Gets the coordinates of a touch's location relative to the window's
+  /// viewport. [input] is either a touch object or an event object.
   Coordinate.fromClient(var input) : this(input.client.x, input.client.y);
 
   static Coordinate difference(Coordinate a, Coordinate b) {
-    return new Coordinate(a.x - b.x, a.y - b.y);
+    return Coordinate(a.x - b.x, a.y - b.y);
   }
 
   static num distance(Coordinate a, Coordinate b) {
@@ -38,11 +30,13 @@
     return Math.sqrt(dx * dx + dy * dy);
   }
 
+  @override
   bool operator ==(covariant Coordinate other) {
-    return other != null && x == other.x && y == other.y;
+    return x == other.x && y == other.y;
   }
 
-  int get hashCode => throw new UnimplementedError();
+  @override
+  int get hashCode => throw UnimplementedError();
 
   static num squaredDistance(Coordinate a, Coordinate b) {
     final dx = a.x - b.x;
@@ -51,45 +45,45 @@
   }
 
   static Coordinate sum(Coordinate a, Coordinate b) {
-    return new Coordinate(a.x + b.x, a.y + b.y);
+    return Coordinate(a.x + b.x, a.y + b.y);
   }
 
-  /**
-   * Returns a new copy of the coordinate.
-   */
-  Coordinate clone() => new Coordinate(x, y);
+  /// Returns a new copy of the coordinate.
+  Coordinate clone() => Coordinate(x, y);
 
+  @override
   String toString() => "($x, $y)";
 }
 
-/**
- * Represents the interval { x | start <= x < end }.
- */
+/// Represents the interval { x | start <= x < end }.
 class Interval {
   final num start;
   final num end;
 
-  Interval(num this.start, num this.end) {}
+  Interval(this.start, this.end);
 
   num get length {
     return end - start;
   }
 
+  @override
   bool operator ==(covariant Interval other) {
-    return other != null && other.start == start && other.end == end;
+    return other.start == start && other.end == end;
   }
 
-  int get hashCode => throw new UnimplementedError();
+  @override
+  int get hashCode => throw UnimplementedError();
 
   Interval union(Interval other) {
-    return new Interval(Math.min(start, other.start), Math.max(end, other.end));
+    return Interval(Math.min(start, other.start), Math.max(end, other.end));
   }
 
   bool contains(num value) {
     return value >= start && value < end;
   }
 
+  @override
   String toString() {
-    return '(${start}, ${end})';
+    return '($start, $end)';
   }
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/InfiniteScroller.dart b/samples-dev/swarm/swarm_ui_lib/touch/InfiniteScroller.dart
index d38c33b..7e40be0 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/InfiniteScroller.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/InfiniteScroller.dart
@@ -6,50 +6,44 @@
 
 part of touch;
 
-/**
- * Adds a listener to the scroller with triggers events
- * when a trigger point at the top, or bottom, of the screen is reached.
- *
- * To use this you will need to have an element with a scroller attached
- * to it. You need to have defined (in pixels) how far from the top or
- * bottom the scroll position must be in order to trigger (the "trigger
- * point") The element using this must have functions for hitting the top
- * trigger, and the bottom trigger. In general, these methods will
- * ascertain whether we have more data to scroll to (i.e. when we hit
- * the bottom trigger point but have reached the end of the data
- * displayed in the element we should ignore it), make the call for
- * more data and reposition the scroller - repositioning is key to
- * good user experience.
- *
- * Triggers are generated by listening for the SCROLL_END event from the
- * scroller, so data calls are not initiated whilst scrolling is happening,
- * but after.
- *
- * Controls changing divs between the usual (non-loading) div and the
- * loading div. To take advantage of this, callback function should return
- * a boolean indicating whether the usual div should be replaced by the
- * loading div.
- */
+/// Adds a listener to the scroller with triggers events
+/// when a trigger point at the top, or bottom, of the screen is reached.
+///
+/// To use this you will need to have an element with a scroller attached
+/// to it. You need to have defined (in pixels) how far from the top or
+/// bottom the scroll position must be in order to trigger (the "trigger
+/// point") The element using this must have functions for hitting the top
+/// trigger, and the bottom trigger. In general, these methods will
+/// ascertain whether we have more data to scroll to (i.e. when we hit
+/// the bottom trigger point but have reached the end of the data
+/// displayed in the element we should ignore it), make the call for
+/// more data and reposition the scroller - repositioning is key to
+/// good user experience.
+///
+/// Triggers are generated by listening for the SCROLL_END event from the
+/// scroller, so data calls are not initiated whilst scrolling is happening,
+/// but after.
+///
+/// Controls changing divs between the usual (non-loading) div and the
+/// loading div. To take advantage of this, callback function should return
+/// a boolean indicating whether the usual div should be replaced by the
+/// loading div.
 class InfiniteScroller {
-  Scroller _scroller;
+  final Scroller _scroller;
 
-  /**
-   * Function to invoke when trigger point is reached at the top of the view.
-   */
-  Function _onTopScroll;
+  /// Function to invoke when trigger point is reached at the top of the view.
+  final Function _onTopScroll;
 
-  /**
-   * Function to invoke when trigger point is reached at the bottom of the view.
-   */
-  Function _onBottomScroll;
+  /// Function to invoke when trigger point is reached at the bottom of the view.
+  final Function _onBottomScroll;
 
-  /** Offset for trigger point at the top of the view. */
-  double _offsetTop;
+  /// Offset for trigger point at the top of the view. */
+  final double _offsetTop;
 
-  /** Offset for trigger point at the bottom of the view. */
-  double _offsetBottom;
+  /// Offset for trigger point at the bottom of the view. */
+  final double _offsetBottom;
 
-  /** Saves the last Y position. */
+  /// Saves the last Y position. */
   double _lastScrollY;
   Element _topDiv;
   Element _topLoadingDiv;
@@ -58,28 +52,26 @@
 
   InfiniteScroller(Scroller scroller, Function onTopScroll,
       Function onBottomScroll, double offsetTop,
-      [double offsetBottom = null])
+      [double offsetBottom])
       : _scroller = scroller,
         _onTopScroll = onTopScroll,
         _onBottomScroll = onBottomScroll,
         _offsetTop = offsetTop,
-        _offsetBottom = offsetBottom == null ? offsetTop : offsetBottom,
-        _lastScrollY = 0.0 {}
+        _offsetBottom = offsetBottom ?? offsetTop,
+        _lastScrollY = 0.0;
 
-  /**
-   * Adds the loading divs.
-   * [topDiv] The div usually shown at the top.
-   * [topLoadingDiv] is the div to show at the top when waiting for more
-   * content to load at the top of the page.
-   * [bottomDiv] is the div usually shown at the bottom.
-   * [bottomLoadingDiv] is the div to show at the bottom when waiting for more
-   * content to load at the end of the page.
-   */
+  /// Adds the loading divs.
+  /// [topDiv] The div usually shown at the top.
+  /// [topLoadingDiv] is the div to show at the top when waiting for more
+  /// content to load at the top of the page.
+  /// [bottomDiv] is the div usually shown at the bottom.
+  /// [bottomLoadingDiv] is the div to show at the bottom when waiting for more
+  /// content to load at the end of the page.
   void addLoadingDivs(
-      [Element topDiv = null,
-      Element topLoadingDiv = null,
-      Element bottomDiv = null,
-      Element bottomLoadingDiv = null]) {
+      [Element topDiv,
+      Element topLoadingDiv,
+      Element bottomDiv,
+      Element bottomLoadingDiv]) {
     _topDiv = topDiv;
     _topLoadingDiv = topLoadingDiv;
     _bottomDiv = bottomDiv;
@@ -92,18 +84,14 @@
     _registerEventListeners();
   }
 
-  /**
-   * Switch back the divs after loading complete. Delegate should call
-   * this function after loading is complete.
-   */
+  /// Switch back the divs after loading complete. Delegate should call
+  /// this function after loading is complete.
   void loadEnd() {
     _updateVisibility(false, _topDiv, _topLoadingDiv);
     _updateVisibility(false, _bottomDiv, _bottomLoadingDiv);
   }
 
-  /**
-   * Called at the end of a scroll event.
-   */
+  /// Called at the end of a scroll event.
   void _onScrollEnd() {
     double ypos = _scroller.getVerticalOffset();
 
@@ -127,18 +115,14 @@
     _lastScrollY = ypos;
   }
 
-  /**
-   * Register the event listeners.
-   */
+  /// Register the event listeners.
   void _registerEventListeners() {
     _scroller.onScrollerEnd.listen((Event event) {
       _onScrollEnd();
     });
   }
 
-  /**
-   * Hides one div and shows another.
-   */
+  /// Hides one div and shows another.
   void _updateVisibility(
       bool isLoading, Element element, Element loadingElement) {
     if (element != null) {
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Math.dart b/samples-dev/swarm/swarm_ui_lib/touch/Math.dart
index 01db437..69cfaf7 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Math.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Math.dart
@@ -7,25 +7,19 @@
 part of touch;
 
 // TODO(jacobr): pick a better name. This was goog.math in Closure.
-/**
- * Math utility functions originally from the closure Math library.
- */
+/// Math utility functions originally from the closure Math library.
 class GoogleMath {
-  /**
-   * Takes a [value] and clamps it to within the bounds specified by
-   * [min] and [max].
-   */
+  /// Takes a [value] and clamps it to within the bounds specified by
+  /// [min] and [max].
   static num clamp(num value, num min, num max) {
     return Math.min(Math.max(value, min), max);
   }
 
-  /**
-   * Tests whether the two values are equal to each other, within a certain
-   * tolerance to adjust for floating point errors.
-   * The optional [tolerance] value d Defaults to 0.000001. If specified,
-   * it should be greater than 0.
-   * Returns whether [a] and [b] are nearly equal.
-   */
+  /// Tests whether the two values are equal to each other, within a certain
+  /// tolerance to adjust for floating point errors.
+  /// The optional [tolerance] value d Defaults to 0.000001. If specified,
+  /// it should be greater than 0.
+  /// Returns whether [a] and [b] are nearly equal.
   static bool nearlyEquals(num a, num b, [num tolerance = 0.000001]) {
     return (a - b).abs() <= tolerance;
   }
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Momentum.dart b/samples-dev/swarm/swarm_ui_lib/touch/Momentum.dart
index 7078b33..1bdd555 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Momentum.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Momentum.dart
@@ -6,31 +6,29 @@
 
 part of touch;
 
-/**
- * Implementations can be used to simulate the deceleration of an element within
- * a certain region. To use this behavior you need to provide an initial
- * velocity that is meant to represent the gesture that is initiating this
- * deceleration. You also provide the bounds of the region that the element
- * exists in, and the current offset of the element within that region. The
- * transitions will have the element decelerate to rest, or stretch past the
- * offset boundaries and then come to rest.
- *
- * This is primarily designed to solve the problem of slow scrolling in mobile
- * safari. You can use this along with the [Scroller] behavior to make a
- * scrollable area scroll the same way it would in a native application.
- *
- * Implementations of this interface do not maintain any references to HTML
- * elements, and therefore cannot do any redrawing of elements. They only
- * calculates where the element should be on an interval. It is the delegate's
- * responsibility to redraw the element when the onDecelerate callback is
- * invoked. It is recommended that you move the element with a hardware
- * accelerated method such as using 'translate3d' on the element's
- * -webkit-transform style property.
- */
+/// Implementations can be used to simulate the deceleration of an element within
+/// a certain region. To use this behavior you need to provide an initial
+/// velocity that is meant to represent the gesture that is initiating this
+/// deceleration. You also provide the bounds of the region that the element
+/// exists in, and the current offset of the element within that region. The
+/// transitions will have the element decelerate to rest, or stretch past the
+/// offset boundaries and then come to rest.
+///
+/// This is primarily designed to solve the problem of slow scrolling in mobile
+/// safari. You can use this along with the [Scroller] behavior to make a
+/// scrollable area scroll the same way it would in a native application.
+///
+/// Implementations of this interface do not maintain any references to HTML
+/// elements, and therefore cannot do any redrawing of elements. They only
+/// calculates where the element should be on an interval. It is the delegate's
+/// responsibility to redraw the element when the onDecelerate callback is
+/// invoked. It is recommended that you move the element with a hardware
+/// accelerated method such as using 'translate3d' on the element's
+/// -webkit-transform style property.
 abstract class Momentum {
   factory Momentum(MomentumDelegate delegate,
           [num defaultDecelerationFactor = 1]) =>
-      new TimeoutMomentum(delegate, defaultDecelerationFactor);
+      TimeoutMomentum(delegate, defaultDecelerationFactor);
 
   bool get decelerating;
 
@@ -42,50 +40,40 @@
   */
   void onTransitionEnd();
 
-  /**
-   * Start decelerating.
-   * The [velocity] passed should be in terms of number of pixels / millisecond.
-   * [minCoord] and [maxCoord] specify the content's scrollable boundary.
-   * The current offset of the element within its boundaries is specified by
-   * [initialOffset].
-   * Returns true if deceleration has been initiated.
-   */
+  /// Start decelerating.
+  /// The [velocity] passed should be in terms of number of pixels / millisecond.
+  /// [minCoord] and [maxCoord] specify the content's scrollable boundary.
+  /// The current offset of the element within its boundaries is specified by
+  /// [initialOffset].
+  /// Returns true if deceleration has been initiated.
   bool start(Coordinate velocity, Coordinate minCoord, Coordinate maxCoord,
       Coordinate initialOffset,
       [num decelerationFactor]);
 
-  /**
-   * Calculate the velocity required to transition between coordinates [start]
-   * and [target] optionally specifying a custom [decelerationFactor].
-   */
+  /// Calculate the velocity required to transition between coordinates [start]
+  /// and [target] optionally specifying a custom [decelerationFactor].
   Coordinate calculateVelocity(Coordinate start, Coordinate target,
       [num decelerationFactor]);
 
-  /** Stop decelerating and return the current velocity. */
+  /// Stop decelerating and return the current velocity. */
   Coordinate stop();
 
-  /** Aborts decelerating without dispatching any notification events. */
+  /// Aborts decelerating without dispatching any notification events. */
   void abort();
 
-  /** null if no transition is in progress. */
+  /// null if no transition is in progress. */
   Coordinate get destination;
 }
 
-/**
- * Momentum Delegate interface.
- * You are required to implement this interface in order to use the
- * Momentum behavior.
- */
+/// Momentum Delegate interface.
+/// You are required to implement this interface in order to use the
+/// Momentum behavior.
 abstract class MomentumDelegate {
-  /**
-   * Callback for a deceleration step. The delegate is responsible for redrawing
-   * the element in its new position specified in px.
-   */
+  /// Callback for a deceleration step. The delegate is responsible for redrawing
+  /// the element in its new position specified in px.
   void onDecelerate(num x, num y);
 
-  /**
-   * Callback for end of deceleration.
-   */
+  /// Callback for end of deceleration.
   void onDecelerationEnd();
 }
 
@@ -105,14 +93,12 @@
   _Move(this.x, this.y, this.vx, this.vy, this.time);
 }
 
-/**
- * Secant method root solver helper class.
- * We use http://en.wikipedia.org/wiki/Secant_method
- * falling back to the http://en.wikipedia.org/wiki/Bisection_method
- * if it doesn't appear we are converging properlty.
- * TODO(jacobr): simplify the code so we don't have to use this solver
- * class at all.
- */
+/// Secant method root solver helper class.
+/// We use http://en.wikipedia.org/wiki/Secant_method
+/// falling back to the http://en.wikipedia.org/wiki/Bisection_method
+/// if it doesn't appear we are converging properlty.
+/// TODO(jacobr): simplify the code so we don't have to use this solver
+/// class at all.
 class Solver {
   static num solve(num Function(num) fn, num targetY, num startX,
       [int maxIterations = 50]) {
@@ -120,8 +106,8 @@
     num lastY = fn(lastX);
     num deltaX;
     num deltaY;
-    num minX = null;
-    num maxX = null;
+    num minX;
+    num maxX;
     num x = startX;
     num delta = startX;
     for (int i = 0; i < maxIterations; i++) {
@@ -151,94 +137,74 @@
         x = (minX + maxX) / 2;
       }
     }
-    window.console.warn('''Could not find an exact solution. LastY=${lastY},
-        targetY=${targetY} lastX=$lastX delta=$delta  deltaX=$deltaX
+    window.console.warn('''Could not find an exact solution. LastY=$lastY,
+        targetY=$targetY lastX=$lastX delta=$delta  deltaX=$deltaX
         deltaY=$deltaY''');
     return x;
   }
 }
 
-/**
- * Helper class modeling the physics of a throwable scrollable area along a
- * single dimension.
- */
+/// Helper class modeling the physics of a throwable scrollable area along a
+/// single dimension.
 class SingleDimensionPhysics {
-  /** The number of frames per second the animation should run at. */
+  /// The number of frames per second the animation should run at. */
   static const _FRAMES_PER_SECOND = 60;
 
-  /**
-   * The spring coefficient for when the element has passed a boundary and is
-   * decelerating to change direction and bounce back. Each frame, the velocity
-   * will be changed by x times this coefficient, where x is the current stretch
-   * value of the element from its boundary. This will end when velocity reaches
-   * zero.
-   */
+  /// The spring coefficient for when the element has passed a boundary and is
+  /// decelerating to change direction and bounce back. Each frame, the velocity
+  /// will be changed by x times this coefficient, where x is the current stretch
+  /// value of the element from its boundary. This will end when velocity reaches
+  /// zero.
   static const _PRE_BOUNCE_COEFFICIENT = 7.0 / _FRAMES_PER_SECOND;
 
-  /**
-   * The spring coefficient for when the element is bouncing back from a
-   * stretched offset to a min or max position. Each frame, the velocity will
-   * be changed to x times this coefficient, where x is the current stretch
-   * value of the element from its boundary. This will end when the stretch
-   * value reaches 0.
-   */
+  /// The spring coefficient for when the element is bouncing back from a
+  /// stretched offset to a min or max position. Each frame, the velocity will
+  /// be changed to x times this coefficient, where x is the current stretch
+  /// value of the element from its boundary. This will end when the stretch
+  /// value reaches 0.
   static const _POST_BOUNCE_COEFFICIENT = 7.0 / _FRAMES_PER_SECOND;
 
-  /**
-   * The number of milliseconds per animation frame.
-   */
+  /// The number of milliseconds per animation frame.
   static const _MS_PER_FRAME = 1000.0 / _FRAMES_PER_SECOND;
 
-  /**
-   * The constant factor applied to velocity at each frame to simulate
-   * deceleration.
-   */
+  /// The constant factor applied to velocity at each frame to simulate
+  /// deceleration.
   static const _DECELERATION_FACTOR = 0.97;
 
   static const _MAX_VELOCITY_STATIC_FRICTION = 0.08 * _MS_PER_FRAME;
   static const _DECELERATION_FACTOR_STATIC_FRICTION = 0.92;
 
-  /**
-   * Minimum velocity required to start or continue deceleration, in
-   * pixels/frame. This is equivalent to 0.25 px/ms.
-   */
+  /// Minimum velocity required to start or continue deceleration, in
+  /// pixels/frame. This is equivalent to 0.25 px/ms.
   static const _MIN_VELOCITY = 0.25 * _MS_PER_FRAME;
 
-  /**
-   * Minimum velocity during a step, in pixels/frame. This is equivalent to 0.01
-   * px/ms.
-   */
+  /// Minimum velocity during a step, in pixels/frame. This is equivalent to 0.01
+  /// px/ms.
   static const _MIN_STEP_VELOCITY = 0.01 * _MS_PER_FRAME;
 
-  /**
-   * Boost the initial velocity by a certain factor before applying momentum.
-   * This just gives the momentum a better feel.
-   */
+  /// Boost the initial velocity by a certain factor before applying momentum.
+  /// This just gives the momentum a better feel.
   static const _INITIAL_VELOCITY_BOOST_FACTOR = 1.25;
 
-  /**
-   * Additional deceleration factor to apply for the current move only.  This
-   * is helpful for cases such as scroll wheel scrolling where the default
-   * amount of deceleration is inadequate.
-   */
+  /// Additional deceleration factor to apply for the current move only.  This
+  /// is helpful for cases such as scroll wheel scrolling where the default
+  /// amount of deceleration is inadequate.
   num customDecelerationFactor = 1;
   num _minCoord;
   num _maxCoord;
 
-  /** The bouncing state. */
+  /// The bouncing state. */
   int _bouncingState;
 
   num velocity;
   num _currentOffset;
 
-  /**
-   * constant used when guessing at the velocity required to throw to a specific
-   * location. Chosen arbitrarily. All that really matters is that the velocity
-   * is large enough that a throw gesture will occur.
-   */
+  /// constant used when guessing at the velocity required to throw to a specific
+  /// location. Chosen arbitrarily. All that really matters is that the velocity
+  /// is large enough that a throw gesture will occur.
   static const _VELOCITY_GUESS = 20;
 
-  SingleDimensionPhysics() : _bouncingState = BouncingState.NOT_BOUNCING {}
+  SingleDimensionPhysics() : _bouncingState = BouncingState.NOT_BOUNCING;
 
   void configure(num minCoord, num maxCoord, num initialOffset,
       num customDecelerationFactor_, num velocity_) {
@@ -246,7 +212,7 @@
     _minCoord = minCoord;
     _maxCoord = maxCoord;
     _currentOffset = initialOffset;
-    this.customDecelerationFactor = customDecelerationFactor_;
+    customDecelerationFactor = customDecelerationFactor_;
     _adjustInitialVelocityAndBouncingState(velocity_);
   }
 
@@ -268,11 +234,9 @@
         targetOffset > initialOffset ? _VELOCITY_GUESS : -_VELOCITY_GUESS);
   }
 
-  /**
-   * Helper method to calculate initial velocity.
-   * The [velocity] passed here should be in terms of number of
-   * pixels / millisecond. Returns the adjusted x and y velocities.
-   */
+  /// Helper method to calculate initial velocity.
+  /// The [velocity] passed here should be in terms of number of
+  /// pixels / millisecond. Returns the adjusted x and y velocities.
   void _adjustInitialVelocityAndBouncingState(num v) {
     velocity = v * _MS_PER_FRAME * _INITIAL_VELOCITY_BOOST_FACTOR;
 
@@ -289,9 +253,7 @@
     }
   }
 
-  /**
-   * Apply deceleration.
-   */
+  /// Apply deceleration.
   void _adjustVelocity() {
     num speed = velocity.abs();
     velocity *= _DECELERATION_FACTOR;
@@ -346,10 +308,8 @@
     }
   }
 
-  /**
-   * Whether or not the current velocity is above the threshold required to
-   * continue decelerating.
-   */
+  /// Whether or not the current velocity is above the threshold required to
+  /// continue decelerating.
   bool isVelocityAboveThreshold(num threshold) {
     return velocity.abs() >= threshold;
   }
@@ -360,35 +320,31 @@
   }
 }
 
-/**
- * Implementation of a momentum strategy using webkit-transforms
- * and timeouts.
- */
+/// Implementation of a momentum strategy using webkit-transforms
+/// and timeouts.
 class TimeoutMomentum implements Momentum {
   SingleDimensionPhysics physicsX;
   SingleDimensionPhysics physicsY;
   Coordinate _previousOffset;
-  Queue<_Move> _moves;
+  final Queue<_Move> _moves;
   num _stepTimeout;
   bool _decelerating;
-  MomentumDelegate _delegate;
+  final MomentumDelegate _delegate;
   int _nextY;
   int _nextX;
   Coordinate _minCoord;
   Coordinate _maxCoord;
   num _customDecelerationFactor;
-  num _defaultDecelerationFactor;
+  final num _defaultDecelerationFactor;
 
   TimeoutMomentum(this._delegate, [num defaultDecelerationFactor = 1])
       : _defaultDecelerationFactor = defaultDecelerationFactor,
         _decelerating = false,
-        _moves = new Queue<_Move>(),
-        physicsX = new SingleDimensionPhysics(),
-        physicsY = new SingleDimensionPhysics();
+        _moves = Queue<_Move>(),
+        physicsX = SingleDimensionPhysics(),
+        physicsY = SingleDimensionPhysics();
 
-  /**
-   * Calculate and return the moves for the deceleration motion.
-   */
+  /// Calculate and return the moves for the deceleration motion.
   void _calculateMoves() {
     _moves.clear();
     num time = TimeUtil.now();
@@ -396,43 +352,43 @@
       _stepWithoutAnimation();
       time += SingleDimensionPhysics._MS_PER_FRAME;
       if (_isStepNecessary()) {
-        _moves.add(new _Move(
-            _nextX, _nextY, physicsX.velocity, physicsY.velocity, time));
+        _moves.add(
+            _Move(_nextX, _nextY, physicsX.velocity, physicsY.velocity, time));
         _previousOffset.y = _nextY;
         _previousOffset.x = _nextX;
       }
     }
   }
 
+  @override
   bool get decelerating => _decelerating;
+  @override
   num get decelerationFactor => _customDecelerationFactor;
 
-  /**
-   * Checks whether or not an animation step is necessary or not. Animations
-   * steps are not necessary when the velocity gets so low that in several
-   * frames the offset is the same.
-   * Returns true if there is movement to be done in the next frame.
-   */
+  /// Checks whether or not an animation step is necessary or not. Animations
+  /// steps are not necessary when the velocity gets so low that in several
+  /// frames the offset is the same.
+  /// Returns true if there is movement to be done in the next frame.
   bool _isStepNecessary() {
     return _nextY != _previousOffset.y || _nextX != _previousOffset.x;
   }
 
-  /**
-   * The [TouchHandler] requires this function but we don't need to do
-   * anything here.
-   */
+  /// The [TouchHandler] requires this function but we don't need to do
+  /// anything here.
+  @override
   void onTransitionEnd() {}
 
+  @override
   Coordinate calculateVelocity(Coordinate start_, Coordinate target,
-      [num decelerationFactor = null]) {
-    return new Coordinate(
-        physicsX.solve(start_.x, target.x, decelerationFactor),
+      [num decelerationFactor]) {
+    return Coordinate(physicsX.solve(start_.x, target.x, decelerationFactor),
         physicsY.solve(start_.y, target.y, decelerationFactor));
   }
 
+  @override
   bool start(Coordinate velocity, Coordinate minCoord, Coordinate maxCoord,
       Coordinate initialOffset,
-      [num decelerationFactor = null]) {
+      [num decelerationFactor]) {
     _customDecelerationFactor = _defaultDecelerationFactor;
     if (decelerationFactor != null) {
       _customDecelerationFactor = decelerationFactor;
@@ -453,7 +409,7 @@
         _customDecelerationFactor, velocity.y);
     if (!physicsX.isDone() || !physicsY.isDone()) {
       _calculateMoves();
-      if (!_moves.isEmpty) {
+      if (_moves.isNotEmpty) {
         num firstTime = _moves.first.time;
         _stepTimeout = Env.requestAnimationFrame(_step, null, firstTime);
         _decelerating = true;
@@ -464,12 +420,10 @@
     return false;
   }
 
-  /**
-   * Update the x, y values of the element offset without actually moving the
-   * element. This is done because we store decimal values for x, y for
-   * precision, but moving is only required when the offset is changed by at
-   * least a whole integer.
-   */
+  /// Update the x, y values of the element offset without actually moving the
+  /// element. This is done because we store decimal values for x, y for
+  /// precision, but moving is only required when the offset is changed by at
+  /// least a whole integer.
   void _stepWithoutAnimation() {
     physicsX.step();
     physicsY.step();
@@ -477,25 +431,23 @@
     _nextY = physicsY._currentOffset.round();
   }
 
-  /**
-   * Calculate the next offset of the element and animate it to that position.
-   */
+  /// Calculate the next offset of the element and animate it to that position.
   void _step(num timestamp) {
     _stepTimeout = null;
 
     // Prune moves that are more than 1 frame behind when we have more
     // available moves.
     num lastEpoch = timestamp - SingleDimensionPhysics._MS_PER_FRAME;
-    while (!_moves.isEmpty &&
+    while (_moves.isNotEmpty &&
         !identical(_moves.first, _moves.last) &&
         _moves.first.time < lastEpoch) {
       _moves.removeFirst();
     }
 
-    if (!_moves.isEmpty) {
+    if (_moves.isNotEmpty) {
       final move = _moves.removeFirst();
       _delegate.onDecelerate(move.x, move.y);
-      if (!_moves.isEmpty) {
+      if (_moves.isNotEmpty) {
         num nextTime = _moves.first.time;
         assert(_stepTimeout == null);
         _stepTimeout = Env.requestAnimationFrame(_step, null, nextTime);
@@ -505,6 +457,7 @@
     }
   }
 
+  @override
   void abort() {
     _decelerating = false;
     _moves.clear();
@@ -514,20 +467,20 @@
     }
   }
 
+  @override
   Coordinate stop() {
     final wasDecelerating = _decelerating;
     _decelerating = false;
     Coordinate velocity;
-    if (!_moves.isEmpty) {
+    if (_moves.isNotEmpty) {
       final move = _moves.first;
       // This is a workaround for the ugly hacks that get applied when a user
       // passed a velocity in to this Momentum implementation.
       num velocityScale = SingleDimensionPhysics._MS_PER_FRAME *
           SingleDimensionPhysics._INITIAL_VELOCITY_BOOST_FACTOR;
-      velocity =
-          new Coordinate(move.vx / velocityScale, move.vy / velocityScale);
+      velocity = Coordinate(move.vx / velocityScale, move.vy / velocityScale);
     } else {
-      velocity = new Coordinate(0, 0);
+      velocity = Coordinate(0, 0);
     }
     _moves.clear();
     if (_stepTimeout != null) {
@@ -540,10 +493,11 @@
     return velocity;
   }
 
+  @override
   Coordinate get destination {
-    if (!_moves.isEmpty) {
+    if (_moves.isNotEmpty) {
       final lastMove = _moves.last;
-      return new Coordinate(lastMove.x, lastMove.y);
+      return Coordinate(lastMove.x, lastMove.y);
     } else {
       return null;
     }
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/ScrollWatcher.dart b/samples-dev/swarm/swarm_ui_lib/touch/ScrollWatcher.dart
index cb4a1b6..e4fe6e9 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/ScrollWatcher.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/ScrollWatcher.dart
@@ -7,49 +7,41 @@
 part of touch;
 
 abstract class ScrollListener {
-  /**
-   * The callback invoked for a scroll event.
-   * [decelerating] specifies whether or not the content is moving due
-   * to deceleration. It should be false if the content is moving because the
-   * user is dragging the content.
-   */
+  /// The callback invoked for a scroll event.
+  /// [decelerating] specifies whether or not the content is moving due
+  /// to deceleration. It should be false if the content is moving because the
+  /// user is dragging the content.
   void onScrollerMoved(double scrollX, double scrollY, bool decelerating);
 }
 
-/**
- * The scroll watcher is intended to provide a single way to
- * listen for scroll events from instances of Scroller.
- * TODO(jacobr): this class is obsolete.
- */
+/// The scroll watcher is intended to provide a single way to
+/// listen for scroll events from instances of Scroller.
+/// TODO(jacobr): this class is obsolete.
 class ScrollWatcher {
-  Scroller _scroller;
+  final Scroller _scroller;
 
-  List<ScrollListener> _listeners;
+  final List<ScrollListener> _listeners;
 
   Element _scrollerEl;
 
   ScrollWatcher(Scroller scroller)
       : _scroller = scroller,
-        _listeners = new List<ScrollListener>() {}
+        _listeners = <ScrollListener>[];
 
   void addListener(ScrollListener listener) {
     _listeners.add(listener);
   }
 
-  /**
-   * Send the scroll event to all listeners.
-   * [decelerating] is true if the offset is changing because of deceleration.
-   */
+  /// Send the scroll event to all listeners.
+  /// [decelerating] is true if the offset is changing because of deceleration.
   void _dispatchScroll(num scrollX, num scrollY, [bool decelerating = false]) {
     for (final listener in _listeners) {
       listener.onScrollerMoved(scrollX, scrollY, decelerating);
     }
   }
 
-  /**
-   * Initializes elements and event handlers. Must be called after construction
-   * and before usage.
-   */
+  /// Initializes elements and event handlers. Must be called after construction
+  /// and before usage.
   void initialize() {
     _scrollerEl = _scroller.getElement();
     _scroller.onContentMoved.listen((e) {
@@ -57,9 +49,7 @@
     });
   }
 
-  /**
-   * This callback is invoked any time the scroller content offset changes.
-   */
+  /// This callback is invoked any time the scroller content offset changes.
   void _onContentMoved(Event e) {
     num scrollX = _scroller.getHorizontalOffset();
     num scrollY = _scroller.getVerticalOffset();
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart b/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
index aebd48d..33bd906f 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Scrollbar.dart
@@ -6,45 +6,35 @@
 
 part of touch;
 
-/**
- * Implementation of a scrollbar for the custom scrolling behavior
- * defined in [:Scroller:].
- */
+/// Implementation of a scrollbar for the custom scrolling behavior
+/// defined in [:Scroller:].
 class Scrollbar implements ScrollListener {
-  /**
-   * The minimum size of scrollbars when not compressed.
-   */
+  /// The minimum size of scrollbars when not compressed.
   static const _MIN_SIZE = 30;
 
-  /**
-   * The minimum compressed size of scrollbars. Scrollbars are compressed when
-   * the content is stretching past its boundaries.
-   */
+  /// The minimum compressed size of scrollbars. Scrollbars are compressed when
+  /// the content is stretching past its boundaries.
   static const _MIN_COMPRESSED_SIZE = 8;
-  /** Padding in pixels to add above and bellow the scrollbar. */
+
+  /// Padding in pixels to add above and bellow the scrollbar. */
   static const _PADDING_LENGTH = 10;
-  /**
-   * The amount of time to wait before hiding scrollbars after showing them.
-   * Measured in ms.
-   */
+
+  /// The amount of time to wait before hiding scrollbars after showing them.
+  /// Measured in ms.
   static const _DISPLAY_TIME = 300;
   static const DRAG_CLASS_NAME = 'drag';
 
-  Scroller _scroller;
-  Element _frame;
+  final Scroller _scroller;
+  final Element _frame;
   bool _scrollInProgress = false;
   bool _scrollBarDragInProgressValue = false;
 
-  /**
-   * Cached values of height and width. Keys will be 'height' and 'width'
-   * depending on if they are applied to vertical or horizontal scrollbar.
-   */
-  Map<String, num> _cachedSize;
+  /// Cached values of height and width. Keys will be 'height' and 'width'
+  /// depending on if they are applied to vertical or horizontal scrollbar.
+  final Map<String, num> _cachedSize;
 
-  /**
-   * This bound function will be used as the input to window.setTimeout when
-   * scheduling the hiding of the scrollbars.
-   */
+  /// This bound function will be used as the input to window.setTimeout when
+  /// scheduling the hiding of the scrollbars.
   Function _boundHideFn;
 
   Element _verticalElement;
@@ -56,14 +46,14 @@
   num _currentScrollRatio;
   Timer _timer;
 
-  bool _displayOnHover;
+  final bool _displayOnHover;
   bool _hovering = false;
 
   Scrollbar(Scroller scroller, [displayOnHover = true])
       : _displayOnHover = displayOnHover,
         _scroller = scroller,
         _frame = scroller.getFrame(),
-        _cachedSize = new Map<String, num>() {
+        _cachedSize = <String, num>{} {
     _boundHideFn = () {
       _showScrollbars(false);
     };
@@ -71,7 +61,7 @@
 
   bool get _scrollBarDragInProgress => _scrollBarDragInProgressValue;
 
-  void set _scrollBarDragInProgress(bool value) {
+  set _scrollBarDragInProgress(bool value) {
     _scrollBarDragInProgressValue = value;
     _toggleClass(
         _verticalElement, DRAG_CLASS_NAME, value && _currentScrollVertical);
@@ -90,10 +80,8 @@
     }
   }
 
-  /**
-   * Initializes elements and event handlers. Must be called after
-   * construction and before usage.
-   */
+  /// Initializes elements and event handlers. Must be called after
+  /// construction and before usage.
   void initialize() {
     // Don't initialize if we have already been initialized.
     // TODO(jacobr): remove this once bugs are fixed and enterDocument is only
@@ -101,9 +89,9 @@
     if (_verticalElement != null) {
       return;
     }
-    _verticalElement = new Element.html(
+    _verticalElement = Element.html(
         '<div class="touch-scrollbar touch-scrollbar-vertical"></div>');
-    _horizontalElement = new Element.html(
+    _horizontalElement = Element.html(
         '<div class="touch-scrollbar touch-scrollbar-horizontal"></div>');
     _scroller.addScrollListener(this);
 
@@ -223,19 +211,17 @@
   void _onEnd(Event e) {
     _scrollBarDragInProgress = false;
     // TODO(jacobr): make scrollbar less tightly coupled to the scroller.
-    _scroller._onScrollerDragEnd.add(new Event(ScrollerEventType.DRAG_END));
+    _scroller._onScrollerDragEnd.add(Event(ScrollerEventType.DRAG_END));
   }
 
-  /**
-   * When scrolling ends, schedule a timeout to hide the scrollbars.
-   */
+  /// When scrolling ends, schedule a timeout to hide the scrollbars.
   void _onScrollerEnd(Event e) {
     _cancelTimeout();
-    _timer =
-        new Timer(const Duration(milliseconds: _DISPLAY_TIME), _boundHideFn);
+    _timer = Timer(const Duration(milliseconds: _DISPLAY_TIME), _boundHideFn);
     _scrollInProgress = false;
   }
 
+  @override
   void onScrollerMoved(num scrollX, num scrollY, bool decelerating) {
     if (_scrollInProgress == false) {
       // Display the scrollbar and then immediately prepare to hide it...
@@ -270,9 +256,7 @@
     }
   }
 
-  /**
-   * When scrolling starts, show scrollbars and clear hide intervals.
-   */
+  /// When scrolling starts, show scrollbars and clear hide intervals.
   void _onScrollerStart(Event e) {
     _scrollInProgress = true;
     _cancelTimeout();
@@ -286,9 +270,7 @@
     }
   }
 
-  /**
-   * Show or hide the scrollbars by changing the opacity.
-   */
+  /// Show or hide the scrollbars by changing the opacity.
   void _showScrollbars(bool show) {
     if (_hovering == true && _displayOnHover) {
       show = true;
@@ -312,12 +294,10 @@
         frameSize - _PADDING_LENGTH * 2);
   }
 
-  /**
-   * Update the vertical or horizontal scrollbar based on the new scroll
-   * properties. The CSS property to adjust for position (bottom|right) is
-   * specified by [cssPos]. The CSS property to adjust for size (height|width)
-   * is specified by [cssSize].
-   */
+  /// Update the vertical or horizontal scrollbar based on the new scroll
+  /// properties. The CSS property to adjust for position (bottom|right) is
+  /// specified by [cssPos]. The CSS property to adjust for size (height|width)
+  /// is specified by [cssSize].
   void _updateScrollbar(Element element, num offset, num scrollPercent,
       num frameSize, num contentSize, String cssPos, String cssSize) {
     if (!_cachedSize.containsKey(cssSize)) {
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/Scroller.dart b/samples-dev/swarm/swarm_ui_lib/touch/Scroller.dart
index a9d9c13..6dde597 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/Scroller.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/Scroller.dart
@@ -6,35 +6,33 @@
 
 part of touch;
 
-/**
- * Implementation of a custom scrolling behavior.
- * This behavior overrides native scrolling for an area. This area can be a
- * single defined part of a page, the entire page, or several different parts
- * of a page.
- *
- * To use this scrolling behavior you need to define a frame and the content.
- * The frame defines the area that the content will scroll within. The frame and
- * content must both be HTML Elements, with the content being a direct child of
- * the frame. Usually the frame is smaller in size than the content. This is
- * not necessary though, if the content is smaller then bouncing will occur to
- * provide feedback that you are past the scrollable area.
- *
- * The scrolling behavior works using the webkit translate3d transformation,
- * which means browsers that do not have hardware accelerated transformations
- * will not perform as well using this. Simple scrolling should be fine even
- * without hardware acceleration, but animating momentum and deceleration is
- * unacceptably slow without it. There is also the option to use relative
- * positioning (setting the left and top styles).
- *
- * For this to work properly you need to set -webkit-text-size-adjust to 'none'
- * on an ancestor element of the frame, or on the frame itself. If you forget
- * this you may see the text content of the scrollable area changing size as it
- * moves.
- *
- * The behavior is intended to support vertical and horizontal scrolling, and
- * scrolling with momentum when a touch gesture flicks with enough velocity.
- */
-typedef void Callback();
+/// Implementation of a custom scrolling behavior.
+/// This behavior overrides native scrolling for an area. This area can be a
+/// single defined part of a page, the entire page, or several different parts
+/// of a page.
+///
+/// To use this scrolling behavior you need to define a frame and the content.
+/// The frame defines the area that the content will scroll within. The frame and
+/// content must both be HTML Elements, with the content being a direct child of
+/// the frame. Usually the frame is smaller in size than the content. This is
+/// not necessary though, if the content is smaller then bouncing will occur to
+/// provide feedback that you are past the scrollable area.
+///
+/// The scrolling behavior works using the webkit translate3d transformation,
+/// which means browsers that do not have hardware accelerated transformations
+/// will not perform as well using this. Simple scrolling should be fine even
+/// without hardware acceleration, but animating momentum and deceleration is
+/// unacceptably slow without it. There is also the option to use relative
+/// positioning (setting the left and top styles).
+///
+/// For this to work properly you need to set -webkit-text-size-adjust to 'none'
+/// on an ancestor element of the frame, or on the frame itself. If you forget
+/// this you may see the text content of the scrollable area changing size as it
+/// moves.
+///
+/// The behavior is intended to support vertical and horizontal scrolling, and
+/// scrolling with momentum when a touch gesture flicks with enough velocity.
+typedef Callback = void Function();
 
 // Helper method to await the completion of 2 futures.
 void joinFutures(List<Future> futures, Callback callback) {
@@ -53,7 +51,7 @@
 }
 
 class Scroller implements Draggable, MomentumDelegate {
-  /** Pixels to move each time an arrow key is pressed. */
+  /// Pixels to move each time an arrow key is pressed. */
   static const ARROW_KEY_DELTA = 30;
   static const SCROLL_WHEEL_VELOCITY = 0.01;
   static const FAST_SNAP_DECELERATION_FACTOR = 0.84;
@@ -62,16 +60,14 @@
   // TODO(jacobr): remove this static variable.
   static bool _dragInProgress = false;
 
-  /** The node that will actually scroll. */
-  Element _element;
+  /// The node that will actually scroll. */
+  final Element _element;
 
-  /**
-   * Frame is the node that will serve as the container for the scrolling
-   * content.
-   */
-  Element _frame;
+  /// Frame is the node that will serve as the container for the scrolling
+  /// content.
+  final Element _frame;
 
-  /** Touch manager to track the events on the scrollable area. */
+  /// Touch manager to track the events on the scrollable area. */
   TouchHandler _touchHandler;
 
   Momentum _momentum;
@@ -87,57 +83,48 @@
   StreamController<Event> _onDecelStart;
   Stream<Event> _onDecelStartStream;
 
-  /** Set if vertical scrolling should be enabled. */
+  /// Set if vertical scrolling should be enabled. */
+  @override
   bool verticalEnabled;
 
-  /** Set if horizontal scrolling should be enabled. */
+  /// Set if horizontal scrolling should be enabled. */
+  @override
   bool horizontalEnabled;
 
-  /**
-   * Set if momentum should be enabled.
-   */
+  /// Set if momentum should be enabled.
   bool _momentumEnabled;
 
-  /** Set which type of scrolling translation technique should be used. */
-  int _scrollTechnique;
+  /// Set which type of scrolling translation technique should be used. */
+  final int _scrollTechnique;
 
-  /**
-   * The maximum coordinate that the left upper corner of the content can scroll
-   * to.
-   */
+  /// The maximum coordinate that the left upper corner of the content can scroll
+  /// to.
   Coordinate _maxPoint;
 
-  /**
-   * An offset to subtract from the maximum coordinate that the left upper
-   * corner of the content can scroll to.
-   */
-  Coordinate _maxOffset;
+  /// An offset to subtract from the maximum coordinate that the left upper
+  /// corner of the content can scroll to.
+  final Coordinate _maxOffset;
 
-  /**
-   * An offset to add to the minimum coordinate that the left upper corner of
-   * the content can scroll to.
-   */
-  Coordinate _minOffset;
+  /// An offset to add to the minimum coordinate that the left upper corner of
+  /// the content can scroll to.
+  final Coordinate _minOffset;
 
-  /** Initialize the current content offset. */
-  Coordinate _contentOffset;
+  /// Initialize the current content offset. */
+  final Coordinate _contentOffset;
 
   // TODO(jacobr): the function type is
   // [:Function(Element, num, num)->void:].
-  /**
-   * The function to use that will actually translate the scrollable node.
-   */
+  /// The function to use that will actually translate the scrollable node.
   Function _setOffsetFunction;
-  /**
-   * Function that returns the content size that can be specified instead of
-   * querying the DOM.
-   */
-  Function _lookupContentSizeDelegate;
+
+  /// Function that returns the content size that can be specified instead of
+  /// querying the DOM.
+  final Function _lookupContentSizeDelegate;
 
   Size _scrollSize;
   Size _contentSize;
   Coordinate _minPoint;
-  bool _isStopping = false;
+  final bool _isStopping = false;
   Coordinate _contentStartOffset;
   bool _started = false;
   bool _activeGesture = false;
@@ -147,24 +134,23 @@
       [this.verticalEnabled = false,
       this.horizontalEnabled = false,
       momentumEnabled = true,
-      lookupContentSizeDelegate = null,
+      lookupContentSizeDelegate,
       num defaultDecelerationFactor = 1,
-      int scrollTechnique = null,
+      int scrollTechnique,
       bool capture = false])
       : _momentumEnabled = momentumEnabled,
         _lookupContentSizeDelegate = lookupContentSizeDelegate,
         _element = scrollableElem,
         _frame = scrollableElem.parent,
-        _scrollTechnique = scrollTechnique != null
-            ? scrollTechnique
-            : ScrollerScrollTechnique.TRANSFORM_3D,
-        _minPoint = new Coordinate(0, 0),
-        _maxPoint = new Coordinate(0, 0),
-        _maxOffset = new Coordinate(0, 0),
-        _minOffset = new Coordinate(0, 0),
-        _contentOffset = new Coordinate(0, 0) {
-    _touchHandler = new TouchHandler(this, scrollableElem.parent);
-    _momentum = new Momentum(this, defaultDecelerationFactor);
+        _scrollTechnique =
+            scrollTechnique ?? ScrollerScrollTechnique.TRANSFORM_3D,
+        _minPoint = Coordinate(0, 0),
+        _maxPoint = Coordinate(0, 0),
+        _maxOffset = Coordinate(0, 0),
+        _minOffset = Coordinate(0, 0),
+        _contentOffset = Coordinate(0, 0) {
+    _touchHandler = TouchHandler(this, scrollableElem.parent);
+    _momentum = Momentum(this, defaultDecelerationFactor);
 
     Element parentElem = scrollableElem.parent;
     assert(parentElem != null);
@@ -246,7 +232,7 @@
 
   Stream<Event> get onScrollerStart {
     if (_onScrollerStart == null) {
-      _onScrollerStart = new StreamController<Event>.broadcast(sync: true);
+      _onScrollerStart = StreamController<Event>.broadcast(sync: true);
       _onScrollerStartStream = _onScrollerStart.stream;
     }
     return _onScrollerStartStream;
@@ -254,7 +240,7 @@
 
   Stream<Event> get onScrollerEnd {
     if (_onScrollerEnd == null) {
-      _onScrollerEnd = new StreamController<Event>.broadcast(sync: true);
+      _onScrollerEnd = StreamController<Event>.broadcast(sync: true);
       _onScrollerEndStream = _onScrollerEnd.stream;
     }
     return _onScrollerEndStream;
@@ -262,7 +248,7 @@
 
   Stream<Event> get onScrollerDragEnd {
     if (_onScrollerDragEnd == null) {
-      _onScrollerDragEnd = new StreamController<Event>.broadcast(sync: true);
+      _onScrollerDragEnd = StreamController<Event>.broadcast(sync: true);
       _onScrollerDragEndStream = _onScrollerDragEnd.stream;
     }
     return _onScrollerDragEndStream;
@@ -270,7 +256,7 @@
 
   Stream<Event> get onContentMoved {
     if (_onContentMoved == null) {
-      _onContentMoved = new StreamController<Event>.broadcast(sync: true);
+      _onContentMoved = StreamController<Event>.broadcast(sync: true);
       _onContentMovedStream = _onContentMoved.stream;
     }
     return _onContentMovedStream;
@@ -278,28 +264,24 @@
 
   Stream<Event> get onDecelStart {
     if (_onDecelStart == null) {
-      _onDecelStart = new StreamController<Event>.broadcast(sync: true);
+      _onDecelStart = StreamController<Event>.broadcast(sync: true);
       _onDecelStartStream = _onDecelStart.stream;
     }
     return _onDecelStartStream;
   }
 
-  /**
-   * Add a scroll listener. This allows other classes to subscribe to scroll
-   * notifications from this scroller.
-   */
+  /// Add a scroll listener. This allows other classes to subscribe to scroll
+  /// notifications from this scroller.
   void addScrollListener(ScrollListener listener) {
     if (_scrollWatcher == null) {
-      _scrollWatcher = new ScrollWatcher(this);
+      _scrollWatcher = ScrollWatcher(this);
       _scrollWatcher.initialize();
     }
     _scrollWatcher.addListener(listener);
   }
 
-  /**
-   * Adjust the new calculated scroll position based on the minimum allowed
-   * position and returns the adjusted scroll value.
-   */
+  /// Adjust the new calculated scroll position based on the minimum allowed
+  /// position and returns the adjusted scroll value.
   num _adjustValue(num newPosition, num minPosition, num maxPosition) {
     assert(minPosition <= maxPosition);
 
@@ -313,32 +295,24 @@
     return newPosition;
   }
 
-  /**
-   * Coordinate we would end up at if we did nothing.
-   */
+  /// Coordinate we would end up at if we did nothing.
   Coordinate get currentTarget {
     Coordinate end = _momentum.destination;
-    if (end == null) {
-      end = _contentOffset;
-    }
+    end ??= _contentOffset;
     return end;
   }
 
   Coordinate get contentOffset => _contentOffset;
 
-  /**
-   * Animate the position of the scroller to the specified [x], [y] coordinates
-   * by applying the throw gesture with the correct velocity to end at that
-   * location.
-   */
-  void throwTo(num x, num y, [num decelerationFactor = null]) {
+  /// Animate the position of the scroller to the specified [x], [y] coordinates
+  /// by applying the throw gesture with the correct velocity to end at that
+  /// location.
+  void throwTo(num x, num y, [num decelerationFactor]) {
     reconfigure(() {
       final snappedTarget = _snapToBounds(x, y);
       // If a deceleration factor is not specified, use the existing
       // deceleration factor specified by the momentum simulator.
-      if (decelerationFactor == null) {
-        decelerationFactor = _momentum.decelerationFactor;
-      }
+      decelerationFactor ??= _momentum.decelerationFactor;
 
       if (snappedTarget != currentTarget) {
         _momentum.abort();
@@ -348,13 +322,13 @@
                 _contentOffset, snappedTarget, decelerationFactor),
             decelerationFactor);
         if (_onDecelStart != null) {
-          _onDecelStart.add(new Event(ScrollerEventType.DECEL_START));
+          _onDecelStart.add(Event(ScrollerEventType.DECEL_START));
         }
       }
     });
   }
 
-  void throwDelta(num deltaX, num deltaY, [num decelerationFactor = null]) {
+  void throwDelta(num deltaX, num deltaY, [num decelerationFactor]) {
     Coordinate start = _contentOffset;
     Coordinate end = currentTarget;
     int x = end.x.toInt();
@@ -380,28 +354,25 @@
     _setContentOffset(_contentOffset.x, _contentOffset.y);
   }
 
-  /**
-   * Adjusted content size is a size with the combined largest height and width
-   * of both the content and the frame.
-   */
+  /// Adjusted content size is a size with the combined largest height and width
+  /// of both the content and the frame.
   Size _getAdjustedContentSize() {
-    return new Size(Math.max(_scrollSize.width, _contentSize.width),
+    return Size(Math.max(_scrollSize.width, _contentSize.width),
         Math.max(_scrollSize.height, _contentSize.height));
   }
 
   // TODO(jmesserly): these should be properties instead of get* methods
   num getDefaultVerticalOffset() => _maxPoint.y;
+  @override
   Element getElement() => _element;
   Element getFrame() => _frame;
   num getHorizontalOffset() => _contentOffset.x;
 
-  /**
-   * [x] Value to use as reference for percent measurement. If
-   *      none is provided then the content's current x offset will be used.
-   * Returns the percent of the page scrolled horizontally.
-   */
-  num getHorizontalScrollPercent([num x = null]) {
-    x = x != null ? x : _contentOffset.x;
+  /// [x] Value to use as reference for percent measurement. If
+  ///      none is provided then the content's current x offset will be used.
+  /// Returns the percent of the page scrolled horizontally.
+  num getHorizontalScrollPercent([num x]) {
+    x = x ?? _contentOffset.x;
     return (x - _minPoint.x) / (_maxPoint.x - _minPoint.x);
   }
 
@@ -409,25 +380,19 @@
   num getMinPointY() => _minPoint.y;
   Momentum get momentum => _momentum;
 
-  /**
-   * Provide access to the touch handler that the scroller created to manage
-   * touch events.
-   */
+  /// Provide access to the touch handler that the scroller created to manage
+  /// touch events.
   TouchHandler getTouchHandler() => _touchHandler;
   num getVerticalOffset() => _contentOffset.y;
 
-  /**
-   * [y] value is used as reference for percent measurement. If
-   * none is provided then the content's current y offset will be used.
-   */
-  num getVerticalScrollPercent([num y = null]) {
-    y = y != null ? y : _contentOffset.y;
+  /// [y] value is used as reference for percent measurement. If
+  /// none is provided then the content's current y offset will be used.
+  num getVerticalScrollPercent([num y]) {
+    y = y ?? _contentOffset.y;
     return (y - _minPoint.y) / Math.max(1, _maxPoint.y - _minPoint.y);
   }
 
-  /**
-   * Initialize the dom elements necessary for the scrolling to work.
-   */
+  /// Initialize the dom elements necessary for the scrolling to work.
   void _initLayer() {
     // The scrollable node provided to Scroller must be a direct child
     // of the scrollable frame.
@@ -436,17 +401,20 @@
     _setContentOffset(_maxPoint.x, _maxPoint.y);
   }
 
+  @override
   void onDecelerate(num x, num y) {
     _setContentOffset(x, y);
   }
 
+  @override
   void onDecelerationEnd() {
     if (_onScrollerEnd != null) {
-      _onScrollerEnd.add(new Event(ScrollerEventType.SCROLLER_END));
+      _onScrollerEnd.add(Event(ScrollerEventType.SCROLLER_END));
     }
     _started = false;
   }
 
+  @override
   void onDragEnd() {
     _dragInProgress = false;
 
@@ -458,23 +426,24 @@
     }
 
     if (_onScrollerDragEnd != null) {
-      _onScrollerDragEnd.add(new Event(ScrollerEventType.DRAG_END));
+      _onScrollerDragEnd.add(Event(ScrollerEventType.DRAG_END));
     }
 
     if (!decelerating) {
       _snapContentOffsetToBounds();
       if (_onScrollerEnd != null) {
-        _onScrollerEnd.add(new Event(ScrollerEventType.SCROLLER_END));
+        _onScrollerEnd.add(Event(ScrollerEventType.SCROLLER_END));
       }
       _started = false;
     } else {
       if (_onDecelStart != null) {
-        _onDecelStart.add(new Event(ScrollerEventType.DECEL_START));
+        _onDecelStart.add(Event(ScrollerEventType.DECEL_START));
       }
     }
     _activeGesture = false;
   }
 
+  @override
   void onDragMove() {
     if (_isStopping || (!_activeGesture && _dragInProgress)) {
       return;
@@ -497,12 +466,13 @@
     if (!_started) {
       _started = true;
       if (_onScrollerStart != null) {
-        _onScrollerStart.add(new Event(ScrollerEventType.SCROLLER_START));
+        _onScrollerStart.add(Event(ScrollerEventType.SCROLLER_START));
       }
     }
     _setContentOffset(newX, newY);
   }
 
+  @override
   bool onDragStart(TouchEvent e) {
     if (e.touches.length > 1) {
       return false;
@@ -514,11 +484,11 @@
     return !!(shouldVertical || shouldHorizontal && !verticalish);
   }
 
+  @override
   void onTouchEnd() {}
 
-  /**
-   * Prepare the scrollable area for possible movement.
-   */
+  /// Prepare the scrollable area for possible movement.
+  @override
   bool onTouchStart(TouchEvent e) {
     reconfigure(() {
       final touch = e.touches[0];
@@ -533,12 +503,10 @@
     return true;
   }
 
-  /**
-   * Recalculate dimensions of the frame and the content. Adjust the minPoint
-   * and maxPoint allowed for scrolling and scroll to a valid position. Call
-   * this method if you know the frame or content has been updated. Called
-   * internally on every touchstart event the frame receives.
-   */
+  /// Recalculate dimensions of the frame and the content. Adjust the minPoint
+  /// and maxPoint allowed for scrolling and scroll to a valid position. Call
+  /// this method if you know the frame or content has been updated. Called
+  /// internally on every touchstart event the frame receives.
   void reconfigure(Callback callback) {
     _resize(() {
       _snapContentOffsetToBounds();
@@ -556,22 +524,20 @@
     reconfigure(() => _setContentOffset(_maxPoint.x, _maxPoint.y));
   }
 
-  /**
-   * Recalculate dimensions of the frame and the content. Adjust the minPoint
-   * and maxPoint allowed for scrolling.
-   */
+  /// Recalculate dimensions of the frame and the content. Adjust the minPoint
+  /// and maxPoint allowed for scrolling.
   void _resize(Callback callback) {
     scheduleMicrotask(() {
       if (_lookupContentSizeDelegate != null) {
         _contentSize = _lookupContentSizeDelegate();
       } else {
-        _contentSize = new Size(_element.scrollWidth, _element.scrollHeight);
+        _contentSize = Size(_element.scrollWidth, _element.scrollHeight);
       }
 
-      _scrollSize = new Size(_frame.offset.width, _frame.offset.height);
+      _scrollSize = Size(_frame.offset.width, _frame.offset.height);
       Size adjusted = _getAdjustedContentSize();
-      _maxPoint = new Coordinate(-_maxOffset.x, -_maxOffset.y);
-      _minPoint = new Coordinate(
+      _maxPoint = Coordinate(-_maxOffset.x, -_maxOffset.y);
+      _minPoint = Coordinate(
           Math.min(
               _scrollSize.width - adjusted.width + _minOffset.x, _maxPoint.x),
           Math.min(_scrollSize.height - adjusted.height + _minOffset.y,
@@ -583,61 +549,49 @@
   Coordinate _snapToBounds(num x, num y) {
     num clampX = GoogleMath.clamp(_minPoint.x, x, _maxPoint.x);
     num clampY = GoogleMath.clamp(_minPoint.y, y, _maxPoint.y);
-    return new Coordinate(clampX, clampY);
+    return Coordinate(clampX, clampY);
   }
 
-  /**
-   * Translate the content to a new position specified in px.
-   */
+  /// Translate the content to a new position specified in px.
   void _setContentOffset(num x, num y) {
     _contentOffset.x = x;
     _contentOffset.y = y;
     _setOffsetFunction(_element, x, y);
     if (_onContentMoved != null) {
-      _onContentMoved.add(new Event(ScrollerEventType.CONTENT_MOVED));
+      _onContentMoved.add(Event(ScrollerEventType.CONTENT_MOVED));
     }
   }
 
-  /**
-   * Enable or disable momentum.
-   */
+  /// Enable or disable momentum.
   void setMomentum(bool enable) {
     _momentumEnabled = enable;
   }
 
-  /**
-   * Sets the vertical scrolled offset of the element where [y] is the amount
-   * of vertical space to be scrolled, in pixels.
-   */
+  /// Sets the vertical scrolled offset of the element where [y] is the amount
+  /// of vertical space to be scrolled, in pixels.
   void setVerticalOffset(num y) {
     _setContentOffset(_contentOffset.x, y);
   }
 
-  /**
-   * Whether the scrollable area should scroll horizontally. Only
-   * returns true if the client has enabled horizontal scrolling, and the
-   * content is wider than the frame.
-   */
+  /// Whether the scrollable area should scroll horizontally. Only
+  /// returns true if the client has enabled horizontal scrolling, and the
+  /// content is wider than the frame.
   bool _shouldScrollHorizontally() {
     return horizontalEnabled && _scrollSize.width < _contentSize.width;
   }
 
-  /**
-   * Whether the scrollable area should scroll vertically. Only
-   * returns true if the client has enabled vertical scrolling.
-   * Vertical bouncing will occur even if frame is taller than content, because
-   * this is what iPhone web apps tend to do. If this is not the desired
-   * behavior, either disable vertical scrolling for this scroller or add a
-   * 'bouncing' parameter to this interface.
-   */
+  /// Whether the scrollable area should scroll vertically. Only
+  /// returns true if the client has enabled vertical scrolling.
+  /// Vertical bouncing will occur even if frame is taller than content, because
+  /// this is what iPhone web apps tend to do. If this is not the desired
+  /// behavior, either disable vertical scrolling for this scroller or add a
+  /// 'bouncing' parameter to this interface.
   bool _shouldScrollVertically() {
     return verticalEnabled;
   }
 
-  /**
-   * In the event that the content is currently beyond the bounds of
-   * the frame, snap it back in to place.
-   */
+  /// In the event that the content is currently beyond the bounds of
+  /// the frame, snap it back in to place.
   void _snapContentOffsetToBounds() {
     num clampX = GoogleMath.clamp(_minPoint.x, _contentOffset.x, _maxPoint.x);
     num clampY = GoogleMath.clamp(_minPoint.y, _contentOffset.y, _maxPoint.y);
@@ -646,12 +600,9 @@
     }
   }
 
-  /**
-   * Initiate the deceleration behavior given a flick [velocity].
-   * Returns true if deceleration has been initiated.
-   */
-  bool _startDeceleration(Coordinate velocity,
-      [num decelerationFactor = null]) {
+  /// Initiate the deceleration behavior given a flick [velocity].
+  /// Returns true if deceleration has been initiated.
+  bool _startDeceleration(Coordinate velocity, [num decelerationFactor]) {
     if (!_shouldScrollHorizontally()) {
       velocity.x = 0;
     }
@@ -668,9 +619,7 @@
     return _momentum.stop();
   }
 
-  /**
-   * Stop the deceleration of the scrollable content given a new position in px.
-   */
+  /// Stop the deceleration of the scrollable content given a new position in px.
   void _stopDecelerating(num x, num y) {
     _momentum.stop();
     _setContentOffset(x, y);
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/TimeUtil.dart b/samples-dev/swarm/swarm_ui_lib/touch/TimeUtil.dart
index a578134..3757dbe 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/TimeUtil.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/TimeUtil.dart
@@ -6,13 +6,11 @@
 
 part of touch;
 
-/**
- * Convenience methods for dealing with time.
- * In the future this could also provide an entry point to mock out time
- * calculation for tests.
- */
+/// Convenience methods for dealing with time.
+/// In the future this could also provide an entry point to mock out time
+/// calculation for tests.
 class TimeUtil {
   static int now() {
-    return new DateTime.now().millisecondsSinceEpoch;
+    return DateTime.now().millisecondsSinceEpoch;
   }
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/TouchHandler.dart b/samples-dev/swarm/swarm_ui_lib/touch/TouchHandler.dart
index 2e362be..3855c3d 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/TouchHandler.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/TouchHandler.dart
@@ -6,98 +6,84 @@
 
 part of touch;
 
-/**
- * Touch Handler. Class that handles all touch events and
- * uses them to interpret higher level gestures and behaviors. TouchEvent is a
- * built in mobile safari type:
- * [http://developer.apple.com/safari/library/documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html].
- *
- * Examples of higher level gestures this class is intended to support
- * - click, double click, long click
- * - dragging, swiping, zooming
- *
- * Touch Behavior:
- *      Use this class to make your elements 'touchable' (see Touchable.dart).
- *      Intended to work with all webkit browsers.
- *
- * Drag Behavior:
- *      Use this class to make your elements 'draggable' (see draggable.js).
- *      This behavior will handle all of the required events and report the
- *      properties of the drag to you while the touch is happening and at the
- *      end of the drag sequence. This behavior will NOT perform the actual
- *      dragging (redrawing the element) for you, this responsibility is left to
- *      the client code. This behavior contains a work around for a mobile
- *      safari bug where the 'touchend' event is not dispatched when the touch
- *      goes past the bottom of the browser window.
- *      This is intended to work well in iframes.
- *      Intended to work with all webkit browsers, tested only on iPhone 3.x so
- *      far.
- *
- * Click Behavior:
- *      Not yet implemented.
- *
- * Zoom Behavior:
- *      Not yet implemented.
- *
- * Swipe Behavior:
- *      Not yet implemented.
- */
+/// Touch Handler. Class that handles all touch events and
+/// uses them to interpret higher level gestures and behaviors. TouchEvent is a
+/// built in mobile safari type:
+/// [http://developer.apple.com/safari/library/documentation/UserExperience/Reference/TouchEventClassReference/TouchEvent/TouchEvent.html].
+///
+/// Examples of higher level gestures this class is intended to support
+/// - click, double click, long click
+/// - dragging, swiping, zooming
+///
+/// Touch Behavior:
+///      Use this class to make your elements 'touchable' (see Touchable.dart).
+///      Intended to work with all webkit browsers.
+///
+/// Drag Behavior:
+///      Use this class to make your elements 'draggable' (see draggable.js).
+///      This behavior will handle all of the required events and report the
+///      properties of the drag to you while the touch is happening and at the
+///      end of the drag sequence. This behavior will NOT perform the actual
+///      dragging (redrawing the element) for you, this responsibility is left to
+///      the client code. This behavior contains a work around for a mobile
+///      safari bug where the 'touchend' event is not dispatched when the touch
+///      goes past the bottom of the browser window.
+///      This is intended to work well in iframes.
+///      Intended to work with all webkit browsers, tested only on iPhone 3.x so
+///      far.
+///
+/// Click Behavior:
+///      Not yet implemented.
+///
+/// Zoom Behavior:
+///      Not yet implemented.
+///
+/// Swipe Behavior:
+///      Not yet implemented.
 class TouchHandler {
-  Touchable _touchable;
+  final Touchable _touchable;
   Element _element;
 
-  /** The absolute sum of all touch y deltas. */
+  /// The absolute sum of all touch y deltas. */
   int _totalMoveY;
 
-  /** The absolute sum of all touch x deltas. */
+  /// The absolute sum of all touch x deltas. */
   int _totalMoveX;
 
-  /**
-   * A list of tuples where the first item is the horizontal component of a
-   * recent relevant touch and the second item is the touch's time stamp. Old
-   * touches are removed based on the max tracking time and when direction
-   * changes.
-   */
+  /// A list of tuples where the first item is the horizontal component of a
+  /// recent relevant touch and the second item is the touch's time stamp. Old
+  /// touches are removed based on the max tracking time and when direction
+  /// changes.
   List<int> _recentTouchesX;
 
-  /**
-   * A list of tuples where the first item is the vertical component of a
-   * recent relevant touch and the second item is the touch's time stamp. Old
-   * touches are removed based on the max tracking time and when direction
-   * changes.
-   */
+  /// A list of tuples where the first item is the vertical component of a
+  /// recent relevant touch and the second item is the touch's time stamp. Old
+  /// touches are removed based on the max tracking time and when direction
+  /// changes.
   List<int> _recentTouchesY;
 
   // TODO(jacobr): make customizable by passing optional parameters to the
   // TouchHandler constructor.
-  /**
-   * Minimum movement of touch required to be considered a drag.
-   */
+  /// Minimum movement of touch required to be considered a drag.
   static const _MIN_TRACKING_FOR_DRAG = 2;
 
-  /**
-   * The maximum number of ms to track a touch event. After an event is older
-   * than this value, it will be ignored in velocity calculations.
-   */
+  /// The maximum number of ms to track a touch event. After an event is older
+  /// than this value, it will be ignored in velocity calculations.
   static const _MAX_TRACKING_TIME = 250;
 
-  /** The maximum number of touches to track. */
+  /// The maximum number of touches to track. */
   static const _MAX_TRACKING_TOUCHES = 5;
 
-  /**
-   * The maximum velocity to return, in pixels per millisecond, that is used to
-   * guard against errors in calculating end velocity of a drag. This is a very
-   * fast drag velocity.
-   */
+  /// The maximum velocity to return, in pixels per millisecond, that is used to
+  /// guard against errors in calculating end velocity of a drag. This is a very
+  /// fast drag velocity.
   static const _MAXIMUM_VELOCITY = 5;
 
-  /**
-   * The velocity to return, in pixel per millisecond, when the time stamps on
-   * the events are erroneous. The browser can return bad time stamps if the
-   * thread is blocked for the duration of the drag. This is a low velocity to
-   * prevent the content from moving quickly after a slow drag. It is less
-   * jarring if the content moves slowly after a fast drag.
-   */
+  /// The velocity to return, in pixel per millisecond, when the time stamps on
+  /// the events are erroneous. The browser can return bad time stamps if the
+  /// thread is blocked for the duration of the drag. This is a low velocity to
+  /// prevent the content from moving quickly after a slow drag. It is less
+  /// jarring if the content moves slowly after a fast drag.
   static const _VELOCITY_FOR_INCORRECT_EVENTS = 1;
 
   Draggable _draggable;
@@ -116,30 +102,26 @@
   int _endTouchX;
   int _endTouchY;
 
-  TouchHandler(Touchable touchable, [Element element = null])
+  TouchHandler(Touchable touchable, [Element element])
       : _touchable = touchable,
         _totalMoveY = 0,
         _totalMoveX = 0,
-        _recentTouchesX = new List<int>(),
-        _recentTouchesY = new List<int>(),
+        _recentTouchesX = <int>[],
+        _recentTouchesY = <int>[],
         // TODO(jmesserly): I don't like having to initialize all booleans here
         // See b/5045736
         _dragging = false,
         _tracking = false,
         _touching = false {
-    _element = element != null ? element : touchable.getElement();
+    _element = element ?? touchable.getElement();
   }
 
-  /**
-   * Begin tracking the touchable element, it is eligible for dragging.
-   */
+  /// Begin tracking the touchable element, it is eligible for dragging.
   void _beginTracking() {
     _tracking = true;
   }
 
-  /**
-   * Stop tracking the touchable element, it is no longer dragging.
-   */
+  /// Stop tracking the touchable element, it is no longer dragging.
   void _endTracking() {
     _tracking = false;
     _dragging = false;
@@ -147,11 +129,9 @@
     _totalMoveX = 0;
   }
 
-  /**
-   * Correct erroneous velocities by capping the velocity if we think it's too
-   * high, or setting it to a default velocity if know that the event data is
-   * bad. Returns the corrected velocity.
-   */
+  /// Correct erroneous velocities by capping the velocity if we think it's too
+  /// high, or setting it to a default velocity if know that the event data is
+  /// bad. Returns the corrected velocity.
   num _correctVelocity(num velocity) {
     num absVelocity = velocity.abs();
     if (absVelocity > _MAXIMUM_VELOCITY) {
@@ -162,15 +142,14 @@
     return absVelocity * (velocity < 0 ? -1 : 1);
   }
 
-  /**
-   * Start listenting for events.
-   * If [capture] is True the TouchHandler should listen during the capture
-   * phase.
-   */
+  /// Start listenting for events.
+  /// If [capture] is True the TouchHandler should listen during the capture
+  /// phase.
   void enable([bool capture = false]) {
-    Function onEnd = (e) {
+    onEnd(e) {
       _onEnd(e.timeStamp.toInt(), e);
-    };
+    }
+
     _addEventListeners(_element, (e) {
       _onStart(e);
     }, (e) {
@@ -178,67 +157,55 @@
     }, onEnd, onEnd, capture);
   }
 
-  /**
-   * Get the current horizontal drag delta. Drag delta is defined as the deltaX
-   * of the start touch position and the last touch position.
-   */
+  /// Get the current horizontal drag delta. Drag delta is defined as the deltaX
+  /// of the start touch position and the last touch position.
   int getDragDeltaX() {
     return _lastTouchX - _startTouchX;
   }
 
-  /**
-   * Get the current vertical drag delta. Drag delta is defined as the deltaY of
-   * the start touch position and the last touch position.
-   */
+  /// Get the current vertical drag delta. Drag delta is defined as the deltaY of
+  /// the start touch position and the last touch position.
   int getDragDeltaY() {
     return _lastTouchY - _startTouchY;
   }
 
-  /**
-   * Get end velocity of the drag. This method is specific to drag behavior, so
-   * if touch behavior and drag behavior is split then this should go with drag
-   * behavior. End velocity is defined as deltaXY / deltaTime where deltaXY is
-   * the difference between endPosition and the oldest recent position, and
-   * deltaTime is the difference between endTime and the oldest recent time
-   * stamp.
-   */
+  /// Get end velocity of the drag. This method is specific to drag behavior, so
+  /// if touch behavior and drag behavior is split then this should go with drag
+  /// behavior. End velocity is defined as deltaXY / deltaTime where deltaXY is
+  /// the difference between endPosition and the oldest recent position, and
+  /// deltaTime is the difference between endTime and the oldest recent time
+  /// stamp.
   Coordinate getEndVelocity() {
     num velocityX = 0;
     num velocityY = 0;
 
-    if (_recentTouchesX.length > 0) {
+    if (_recentTouchesX.isNotEmpty) {
       num timeDeltaX = Math.max(1, _endTime - _recentTouchesX[1]);
       velocityX = (_endTouchX - _recentTouchesX[0]) / timeDeltaX;
     }
 
-    if (_recentTouchesY.length > 0) {
+    if (_recentTouchesY.isNotEmpty) {
       num timeDeltaY = Math.max(1, _endTime - _recentTouchesY[1]);
       velocityY = (_endTouchY - _recentTouchesY[0]) / timeDeltaY;
     }
     velocityX = _correctVelocity(velocityX);
     velocityY = _correctVelocity(velocityY);
-    return new Coordinate(velocityX, velocityY);
+    return Coordinate(velocityX, velocityY);
   }
 
-  /**
-   * Return the touch of the last event.
-   */
+  /// Return the touch of the last event.
   Touch _getLastTouch() {
     assert(_lastEvent != null); // Last event not set
     return _lastEvent.touches[0];
   }
 
-  /**
-   * Is the touch manager currently tracking touch moves to detect a drag?
-   */
+  /// Is the touch manager currently tracking touch moves to detect a drag?
   bool isTracking() {
     return _tracking;
   }
 
-  /**
-   * Touch end handler.
-   */
-  void _onEnd(int timeStamp, [TouchEvent e = null]) {
+  /// Touch end handler.
+  void _onEnd(int timeStamp, [TouchEvent e]) {
     _touching = false;
     _touchable.onTouchEnd();
     if (!_tracking || _draggable == null) {
@@ -262,9 +229,7 @@
     _endTracking();
   }
 
-  /**
-   * Touch move handler.
-   */
+  /// Touch move handler.
   void _onMove(TouchEvent e) {
     if (!_tracking || _draggable == null) {
       return;
@@ -311,9 +276,7 @@
     _lastMoveY = moveY;
   }
 
-  /**
-   * Touch start handler.
-   */
+  /// Touch start handler.
   void _onStart(TouchEvent e) {
     if (_touching) {
       return;
@@ -328,8 +291,8 @@
     int timeStamp = e.timeStamp.toInt();
     _startTime = timeStamp;
     // TODO(jacobr): why don't we just clear the lists?
-    _recentTouchesX = new List<int>();
-    _recentTouchesY = new List<int>();
+    _recentTouchesX = <int>[];
+    _recentTouchesY = <int>[];
     _recentTouchesX.add(touch.client.x);
     _recentTouchesX.add(timeStamp);
     _recentTouchesY.add(touch.client.y);
@@ -338,13 +301,11 @@
     _beginTracking();
   }
 
-  /**
-   * Filters the provided recent touches list to remove all touches older than
-   * the max tracking time or the 5th most recent touch.
-   * [recentTouches] specifies a list of tuples where the first item is the x
-   * or y component of the recent touch and the second item is the touch time
-   * stamp. The time of the most recent event is specified by [recentTime].
-   */
+  /// Filters the provided recent touches list to remove all touches older than
+  /// the max tracking time or the 5th most recent touch.
+  /// [recentTouches] specifies a list of tuples where the first item is the x
+  /// or y component of the recent touch and the second item is the touch time
+  /// stamp. The time of the most recent event is specified by [recentTime].
   List<int> _removeOldTouches(List<int> recentTouches, int recentTime) {
     int count = 0;
     final len = recentTouches.length;
@@ -361,14 +322,12 @@
     return list.sublist(n);
   }
 
-  /**
-   * Filters the provided recent touches list to remove all touches except the
-   * last if the move direction has changed.
-   * [recentTouches] specifies a list of tuples where the first item is the x
-   * or y component of the recent touch and the second item is the touch time
-   * stamp. The x or y component of the most recent move is specified by
-   * [recentMove].
-   */
+  /// Filters the provided recent touches list to remove all touches except the
+  /// last if the move direction has changed.
+  /// [recentTouches] specifies a list of tuples where the first item is the x
+  /// or y component of the recent touch and the second item is the touch time
+  /// stamp. The x or y component of the most recent move is specified by
+  /// [recentMove].
   List<int> _removeTouchesInWrongDirection(
       List<int> recentTouches, int lastMove, int recentMove) {
     if (lastMove != 0 &&
@@ -383,19 +342,15 @@
   // TODO(jacobr): why doesn't bool implement the xor operator directly?
   static bool _xor(bool a, bool b) => a != b;
 
-  /**
-   * Reset the touchable element.
-   */
+  /// Reset the touchable element.
   void reset() {
     _endTracking();
     _touching = false;
   }
 
-  /**
-   * Call this method to enable drag behavior on a draggable delegate.
-   * The [draggable] object can be the same as the [_touchable] object, they are
-   * assigned to different members to allow for strong typing with interfaces.
-   */
+  /// Call this method to enable drag behavior on a draggable delegate.
+  /// The [draggable] object can be the same as the [_touchable] object, they are
+  /// assigned to different members to allow for strong typing with interfaces.
   void setDraggable(Draggable draggable) {
     _draggable = draggable;
   }
diff --git a/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart b/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart
index 39183c7..298818f 100644
--- a/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart
+++ b/samples-dev/swarm/swarm_ui_lib/touch/TouchUtil.dart
@@ -6,17 +6,15 @@
 
 part of touch;
 
-/**
- * Wraps a callback with translations of mouse events to touch events. Use
- * this function to invoke your callback that expects touch events after
- * touch events are created from the actual mouse events.
- */
+/// Wraps a callback with translations of mouse events to touch events. Use
+/// this function to invoke your callback that expects touch events after
+/// touch events are created from the actual mouse events.
 EventListener mouseToTouchCallback(EventListener callback) {
   return (Event e) {
     var touches = <Touch>[];
     var targetTouches = <Touch>[];
     var changedTouches = <Touch>[];
-    final mockTouch = new MockTouch(e);
+    final mockTouch = MockTouch(e);
     final mockTouchList = <Touch>[mockTouch];
     if (e.type == 'mouseup') {
       changedTouches = mockTouchList;
@@ -24,14 +22,14 @@
       touches = mockTouchList;
       targetTouches = mockTouchList;
     }
-    callback(new MockTouchEvent(e, touches, targetTouches, changedTouches));
+    callback(MockTouchEvent(e, touches, targetTouches, changedTouches));
     // Required to prevent spurious selection changes while tracking touches
     // on devices that don't support touch events.
     e.preventDefault();
   };
 }
 
-/** Helper method to attach event listeners to a [node]. */
+/// Helper method to attach event listeners to a [node]. */
 void _addEventListeners(Element node, EventListener onStart,
     EventListener onMove, EventListener onEnd, EventListener onCancel,
     [bool capture = false]) {
@@ -53,10 +51,10 @@
   }
 
   if (Device.supportsTouch) {
-    var touchMoveSub;
-    var touchEndSub;
-    var touchLeaveSub;
-    var touchCancelSub;
+    StreamSubscription<TouchEvent> touchMoveSub;
+    StreamSubscription<TouchEvent> touchEndSub;
+    StreamSubscription<TouchEvent> touchLeaveSub;
+    StreamSubscription<TouchEvent> touchCancelSub;
 
     removeListeners = () {
       touchMoveSub.cancel();
@@ -86,9 +84,9 @@
     onEnd = mouseToTouchCallback(onEnd);
     // onLeave will never be called if the device does not support touches.
 
-    var mouseMoveSub;
-    var mouseUpSub;
-    var touchCancelSub;
+    StreamSubscription<MouseEvent> mouseMoveSub;
+    StreamSubscription<MouseEvent> mouseUpSub;
+    StreamSubscription<TouchEvent> touchCancelSub;
 
     removeListeners = () {
       mouseMoveSub.cancel();
@@ -111,10 +109,8 @@
   }
 }
 
-/**
- * Gets whether the given touch event targets the node, or one of the node's
- * children.
- */
+/// Gets whether the given touch event targets the node, or one of the node's
+/// children.
 bool _touchEventTargetsNode(event, Node node) {
   Node target = event.changedTouches[0].target;
 
@@ -131,40 +127,28 @@
 }
 
 abstract class Touchable {
-  /**
-   * Provide the HTML element that should respond to touch events.
-   */
+  /// Provide the HTML element that should respond to touch events.
   Element getElement();
 
-  /**
-   * The object has received a touchend event.
-   */
+  /// The object has received a touchend event.
   void onTouchEnd();
 
-  /**
-   * The object has received a touchstart event.
-   * Returns return true if you want to allow a drag sequence to begin,
-   *      false you want to disable dragging for the duration of this touch.
-   */
+  /// The object has received a touchstart event.
+  /// Returns return true if you want to allow a drag sequence to begin,
+  ///      false you want to disable dragging for the duration of this touch.
   bool onTouchStart(TouchEvent e);
 }
 
 abstract class Draggable implements Touchable {
-  /**
-   * The object's drag sequence is now complete.
-   */
+  /// The object's drag sequence is now complete.
   void onDragEnd();
 
-  /**
-   * The object has been dragged to a new position.
-   */
+  /// The object has been dragged to a new position.
   void onDragMove();
 
-  /**
-   * The object has started dragging.
-   * Returns true to allow a drag sequence to begin (custom behavior),
-   * false to disable dragging for this touch duration (allow native scrolling).
-   */
+  /// The object has started dragging.
+  /// Returns true to allow a drag sequence to begin (custom behavior),
+  /// false to disable dragging for this touch duration (allow native scrolling).
   bool onDragStart(TouchEvent e);
 
   bool get verticalEnabled;
@@ -174,14 +158,16 @@
 class MockTouch implements Touch {
   MouseEvent wrapped;
 
-  MockTouch(MouseEvent this.wrapped) {}
+  MockTouch(this.wrapped);
 
   int get clientX => wrapped.client.x;
 
   int get clientY => wrapped.client.y;
 
+  @override
   get client => wrapped.client;
 
+  @override
   int get identifier => 0;
 
   int get pageX => wrapped.page.x;
@@ -194,50 +180,58 @@
     return wrapped.screen.y;
   }
 
+  @override
   EventTarget get target => wrapped.target;
 
+  @override
   double get force {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   Point get page {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   int get radiusX {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   int get radiusY {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   String get region {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   num get rotationAngle {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   Point get screen {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   num get webkitForce {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   int get webkitRadiusX {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   int get webkitRadiusY {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   num get webkitRotationAngle {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 }
 
@@ -250,75 +244,95 @@
 
   static bool get supported => true;
 
+  @override
   int get length => values.length;
 
+  @override
   Touch operator [](int index) => values[index];
 
+  @override
   void operator []=(int index, Touch value) {
-    throw new UnsupportedError("Cannot assign element of immutable List.");
+    throw UnsupportedError("Cannot assign element of immutable List.");
   }
 
+  @override
   set length(int value) {
-    throw new UnsupportedError("Cannot resize immutable List.");
+    throw UnsupportedError("Cannot resize immutable List.");
   }
 
+  @override
   Touch item(int index) => values[index];
 }
 
 class MockTouchEvent implements TouchEvent {
   dynamic /*MouseEvent*/ wrapped;
+  @override
   final TouchList touches;
+  @override
   final TouchList targetTouches;
+  @override
   final TouchList changedTouches;
   MockTouchEvent(MouseEvent this.wrapped, List<Touch> touches,
       List<Touch> targetTouches, List<Touch> changedTouches)
-      : touches = new MockTouchList(touches),
-        targetTouches = new MockTouchList(targetTouches),
-        changedTouches = new MockTouchList(changedTouches);
+      : touches = MockTouchList(touches),
+        targetTouches = MockTouchList(targetTouches),
+        changedTouches = MockTouchList(changedTouches);
 
+  @override
   bool get bubbles => wrapped.bubbles;
 
   bool get cancelBubble => wrapped.cancelBubble;
 
-  void set cancelBubble(bool value) {
+  set cancelBubble(bool value) {
     wrapped.cancelBubble = value;
   }
 
+  @override
   bool get cancelable => wrapped.cancelable;
 
+  @override
   EventTarget get currentTarget => wrapped.currentTarget;
 
+  @override
   bool get defaultPrevented => wrapped.defaultPrevented;
 
+  @override
   int get eventPhase => wrapped.eventPhase;
 
-  void set returnValue(bool value) {
+  set returnValue(bool value) {
     wrapped.returnValue = value;
   }
 
   bool get returnValue => wrapped.returnValue;
 
+  @override
   EventTarget get target => wrapped.target;
 
   /*At different times, int, double, and String*/
+  @override
   get timeStamp => wrapped.timeStamp;
 
+  @override
   String get type => wrapped.type;
 
+  @override
   void preventDefault() {
     wrapped.preventDefault();
   }
 
+  @override
   void stopImmediatePropagation() {
     wrapped.stopImmediatePropagation();
   }
 
+  @override
   void stopPropagation() {
     wrapped.stopPropagation();
   }
 
   int get charCode => wrapped.charCode;
 
+  @override
   int get detail => wrapped.detail;
 
   // TODO(sra): keyCode is not on MouseEvent.
@@ -332,67 +346,78 @@
 
   int get pageY => wrapped.page.y;
 
+  @override
   Window get view => wrapped.view;
 
   int get which => wrapped.which;
 
+  @override
   bool get altKey => wrapped.altKey;
 
+  @override
   bool get ctrlKey => wrapped.ctrlKey;
 
+  @override
   bool get metaKey => wrapped.metaKey;
 
+  @override
   bool get shiftKey => wrapped.shiftKey;
 
   DataTransfer get clipboardData {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   List<EventTarget> deepPath() {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   bool get isTrusted {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   Point get layer {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   Element get matchingTarget {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   Point get page {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   List<EventTarget> get path {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   bool get scoped {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
   Point get screen {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
-  /*InputDeviceCapabilities*/ get sourceCapabilities {
-    throw new UnimplementedError();
+  /*InputDeviceCapabilities*/ @override
+  get sourceCapabilities {
+    throw UnimplementedError();
   }
 
   /*InputDevice*/ get sourceDevice {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   bool get composed {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 
+  @override
   List<EventTarget> composedPath() {
-    throw new UnimplementedError();
+    throw UnimplementedError();
   }
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/util/CollectionUtils.dart b/samples-dev/swarm/swarm_ui_lib/util/CollectionUtils.dart
index bba7cf2..3dbef87 100644
--- a/samples-dev/swarm/swarm_ui_lib/util/CollectionUtils.dart
+++ b/samples-dev/swarm/swarm_ui_lib/util/CollectionUtils.dart
@@ -4,12 +4,10 @@
 
 part of utilslib;
 
-typedef int NumericValueSelector<T>(T value);
+typedef NumericValueSelector<T> = int Function(T value);
 
-/**
- * General purpose collection utilities.
- * TODO(jmesserly): make these top level functions?
- */
+/// General purpose collection utilities.
+/// TODO(jmesserly): make these top level functions?
 class CollectionUtils {
   static void insertAt(List arr, int pos, value) {
     assert(pos >= 0);
@@ -39,12 +37,10 @@
     }
   }
 
-  /**
-   * Finds the item in [source] that matches [test].  Returns null if
-   * no item matches.  The typing should be:
-   * T find(Iterable<T> source, bool test(T item)), but we don't have generic
-   * functions.
-   */
+  /// Finds the item in [source] that matches [test].  Returns null if
+  /// no item matches.  The typing should be:
+  /// T find(Iterable<T> source, bool test(T item)), but we don't have generic
+  /// functions.
   static find(Iterable source, bool test(item)) {
     for (final item in source) {
       if (test(item)) return item;
@@ -53,7 +49,7 @@
     return null;
   }
 
-  /** Compute the minimum of an iterable. Returns null if empty. */
+  /// Compute the minimum of an iterable. Returns null if empty. */
   static num? min(Iterable source) {
     final iter = source.iterator;
     if (!iter.moveNext()) {
@@ -66,7 +62,7 @@
     return best;
   }
 
-  /** Compute the maximum of an iterable. Returns null if empty. */
+  /// Compute the maximum of an iterable. Returns null if empty. */
   static num? max(Iterable source) {
     final iter = source.iterator;
     if (!iter.moveNext()) {
@@ -79,19 +75,19 @@
     return best;
   }
 
-  /** Orders an iterable by its values, or by a key selector. */
+  /// Orders an iterable by its values, or by a key selector. */
   static List<T> orderBy<T>(Iterable<T> source,
-      [NumericValueSelector? selector = null]) {
+      [NumericValueSelector? selector]) {
     final result = List<T>.from(source);
     sortBy(result, selector);
     return result;
   }
 
-  /** Sorts a list by its values, or by a key selector. */
+  /// Sorts a list by its values, or by a key selector. */
   // TODO(jmesserly): we probably don't want to call the key selector more than
   // once for a given element. This would improve performance and the API
   // contract could be stronger.
-  static void sortBy(List list, [NumericValueSelector? selector = null]) {
+  static void sortBy(List list, [NumericValueSelector? selector]) {
     if (selector != null) {
       list.sort((x, y) => selector(x) - selector(y));
     } else {
@@ -99,8 +95,8 @@
     }
   }
 
-  /** Compute the sum of an iterable. An empty iterable is an error. */
-  static num sum(Iterable source, [NumericValueSelector? selector = null]) {
+  /// Compute the sum of an iterable. An empty iterable is an error. */
+  static num sum(Iterable source, [NumericValueSelector? selector]) {
     final iter = source.iterator;
     bool wasEmpty = true;
     num total = 0;
diff --git a/samples-dev/swarm/swarm_ui_lib/util/DateUtils.dart b/samples-dev/swarm/swarm_ui_lib/util/DateUtils.dart
index a8cff44..e73dd53 100644
--- a/samples-dev/swarm/swarm_ui_lib/util/DateUtils.dart
+++ b/samples-dev/swarm/swarm_ui_lib/util/DateUtils.dart
@@ -4,12 +4,10 @@
 
 part of utilslib;
 
-/**
- * General purpose date/time utilities.
- */
+/// General purpose date/time utilities.
 class DateUtils {
   // TODO(jmesserly): localized strings
-  static const WEEKDAYS = const [
+  static const WEEKDAYS = [
     'Monday',
     'Tuesday',
     'Wednesday',
@@ -83,7 +81,7 @@
     return result.toLocal();
   }
 
-  /** Parse a string like: 2011-07-19T22:03:04.000Z */
+  /// Parse a string like: 2011-07-19T22:03:04.000Z */
   // TODO(jmesserly): workaround for DateTime.fromDate, which has issues:
   //   * on Dart VM it doesn't handle all of ISO 8601. See b/5055106.
   //   * on DartC it doesn't work on Safari. See b/5062557.
@@ -110,7 +108,7 @@
     ensure(time.length == 3);
 
     final seconds = time[2].split('.');
-    ensure(seconds.length >= 1 && seconds.length <= 2);
+    ensure(seconds.isNotEmpty && seconds.length <= 2);
     int milliseconds = 0;
     if (seconds.length == 2) {
       milliseconds = int.parse(seconds[1]);
@@ -126,13 +124,11 @@
         milliseconds);
   }
 
-  /**
-   * A date/time formatter that takes into account the current date/time:
-   *  - if it's from today, just show the time
-   *  - if it's from yesterday, just show 'Yesterday'
-   *  - if it's from the same week, just show the weekday
-   *  - otherwise, show just the date
-   */
+  /// A date/time formatter that takes into account the current date/time:
+  ///  - if it's from today, just show the time
+  ///  - if it's from yesterday, just show 'Yesterday'
+  ///  - if it's from the same week, just show the weekday
+  ///  - otherwise, show just the date
   static String toRecentTimeString(DateTime then) {
     bool datesAreEqual(DateTime d1, DateTime d2) {
       return (d1.year == d2.year) &&
@@ -159,13 +155,13 @@
     } else {
       // TODO(jmesserly): locale specific date format
       String twoDigits(int n) {
-        if (n >= 10) return "${n}";
-        return "0${n}";
+        if (n >= 10) return "$n";
+        return "0$n";
       }
 
       String twoDigitMonth = twoDigits(then.month);
       String twoDigitDay = twoDigits(then.day);
-      return "${then.year}-${twoDigitMonth}-${twoDigitDay}";
+      return "${then.year}-$twoDigitMonth-$twoDigitDay";
     }
   }
 
@@ -179,7 +175,7 @@
     return ((daysSince1970 + DateTime.thursday) % DateTime.daysPerWeek);
   }
 
-  /** Formats a time in H:MM A format */
+  /// Formats a time in H:MM A format */
   // TODO(jmesserly): should get 12 vs 24 hour clock setting from the locale
   static String toHourMinutesString(Duration duration) {
     assert(duration.inDays == 0);
@@ -197,12 +193,12 @@
       }
     }
     String twoDigits(int n) {
-      if (n >= 10) return "${n}";
-      return "0${n}";
+      if (n >= 10) return "$n";
+      return "0$n";
     }
 
     String mm =
         twoDigits(duration.inMinutes.remainder(Duration.minutesPerHour));
-    return "${hours}:${mm} ${a}";
+    return "$hours:$mm $a";
   }
 }
diff --git a/samples-dev/swarm/swarm_ui_lib/util/StringUtils.dart b/samples-dev/swarm/swarm_ui_lib/util/StringUtils.dart
index 1a06fb6..efbae29 100644
--- a/samples-dev/swarm/swarm_ui_lib/util/StringUtils.dart
+++ b/samples-dev/swarm/swarm_ui_lib/util/StringUtils.dart
@@ -4,30 +4,26 @@
 
 part of utilslib;
 
-/**
- * General purpose string manipulation utilities.
- */
+/// General purpose string manipulation utilities.
 class StringUtils {
-  /**
-   * Returns either [str], or if [str] is null, the value of [defaultStr].
-   */
+  /// Returns either [str], or if [str] is null, the value of [defaultStr].
   static String defaultString(String? str, [String defaultStr = '']) {
-    return str == null ? defaultStr : str;
+    return str ?? defaultStr;
   }
 
-  /** Parse string to a double, and handle null intelligently */
-  static double? parseDouble(String? str, [double? ifNull = null]) {
+  /// Parse string to a double, and handle null intelligently */
+  static double? parseDouble(String? str, [double? ifNull]) {
     return (str == null) ? ifNull : double.parse(str);
   }
 
-  /** Parse string to a int, and handle null intelligently */
-  static int? parseInt(String? str, [int? ifNull = null]) {
+  /// Parse string to a int, and handle null intelligently */
+  static int? parseInt(String? str, [int? ifNull]) {
     return (str == null) ? ifNull : int.parse(str);
   }
 
-  /** Parse bool to a double, and handle null intelligently */
+  /// Parse bool to a double, and handle null intelligently */
   // TODO(jacobr): corelib should have a boolean parsing method
-  static bool? parseBool(String? str, [bool? ifNull = null]) {
+  static bool? parseBool(String? str, [bool? ifNull]) {
     assert(str == null || str == 'true' || str == 'false');
     return (str == null) ? ifNull : (str == 'true');
   }
diff --git a/samples-dev/swarm/swarm_ui_lib/util/Uri.dart b/samples-dev/swarm/swarm_ui_lib/util/Uri.dart
index 03fce60..df9bb09 100644
--- a/samples-dev/swarm/swarm_ui_lib/util/Uri.dart
+++ b/samples-dev/swarm/swarm_ui_lib/util/Uri.dart
@@ -4,20 +4,16 @@
 
 part of utilslib;
 
-/**
- * A parsed URI, inspired by:
- * https://github.com/google/closure-library/blob/master/closure/goog/uri/uri.js
- */
+/// A parsed URI, inspired by:
+/// https://github.com/google/closure-library/blob/master/closure/goog/uri/uri.js
 class SwarmUri {
-  /**
-   * Parses a URL query string into a map. Because you can have multiple values
-   * for the same parameter name, each parameter name maps to a list of
-   * values. For example, '?a=b&c=d&a=e' would be parsed as
-   * [{'a':['b','e'],'c':['d']}].
-   */
+  /// Parses a URL query string into a map. Because you can have multiple values
+  /// for the same parameter name, each parameter name maps to a list of
+  /// values. For example, '?a=b&c=d&a=e' would be parsed as
+  /// [{'a':['b','e'],'c':['d']}].
   // TODO(jmesserly): consolidate with Uri.parse(...)
   static Map<String, List<String>> parseQuery(String queryString) {
-    final queryParams = Map<String, List<String>>();
+    final queryParams = <String, List<String>>{};
     if (queryString.startsWith('?')) {
       final params = queryString.substring(1, queryString.length).split('&');
       for (final param in params) {
@@ -41,9 +37,7 @@
     return queryParams;
   }
 
-  /**
-   * Percent-encodes a string for use as a query parameter in a URI.
-   */
+  /// Percent-encodes a string for use as a query parameter in a URI.
   // TODO(rnystrom): Get rid of this when the real encodeURIComponent()
   // function is available within Dart.
   static String? encodeComponent(String? component) {
@@ -60,10 +54,8 @@
         .replaceAll(' ', '%20');
   }
 
-  /**
-   * Decodes a string used a query parameter by replacing percent-encoded
-   * sequences with their original characters.
-   */
+  /// Decodes a string used a query parameter by replacing percent-encoded
+  /// sequences with their original characters.
   // TODO(jmesserly): replace this with a better implementation
   static String? decodeComponent(String? component) {
     if (component == null) return component;
diff --git a/samples-dev/swarm/swarm_ui_lib/view/CompositeView.dart b/samples-dev/swarm/swarm_ui_lib/view/CompositeView.dart
index dc6390e..a55f47c 100644
--- a/samples-dev/swarm/swarm_ui_lib/view/CompositeView.dart
+++ b/samples-dev/swarm/swarm_ui_lib/view/CompositeView.dart
@@ -6,10 +6,9 @@
 
 part of view;
 
-/**
- * A View that is composed of child views.
- */
+/// A View that is composed of child views.
 class CompositeView extends View {
+  @override
   List<View> childViews;
 
   // TODO(rnystrom): Allowing this to be public is gross. CompositeView should
@@ -26,7 +25,7 @@
   final bool _nestedContainer;
   final bool _showScrollbar;
 
-  CompositeView(String this._cssName,
+  CompositeView(this._cssName,
       [nestedContainer = false,
       scrollable = false,
       vertical = false,
@@ -35,26 +34,27 @@
         _scrollable = scrollable,
         _vertical = vertical,
         _showScrollbar = showScrollbar,
-        childViews = new List<View>() {}
+        childViews = <View>[];
 
+  @override
   Element render() {
-    Element node = new Element.html('<div class="$_cssName"></div>');
+    Element node = Element.html('<div class="$_cssName"></div>');
 
     if (_nestedContainer) {
-      container = new Element.html('<div class="scroll-container"></div>');
+      container = Element.html('<div class="scroll-container"></div>');
       node.nodes.add(container);
     } else {
       container = node;
     }
 
     if (_scrollable) {
-      scroller = new Scroller(
+      scroller = Scroller(
           container,
           _vertical /* verticalScrollEnabled */,
           !_vertical /* horizontalScrollEnabled */,
           true /* momementumEnabled */);
       if (_showScrollbar) {
-        _scrollbar = new Scrollbar(scroller);
+        _scrollbar = Scrollbar(scroller);
       }
     }
 
@@ -65,6 +65,7 @@
     return node;
   }
 
+  @override
   void afterRender(Element node) {
     if (_scrollbar != null) {
       _scrollbar.initialize();
diff --git a/samples-dev/swarm/swarm_ui_lib/view/ConveyorView.dart b/samples-dev/swarm/swarm_ui_lib/view/ConveyorView.dart
index 66641e2..fc67d2bb 100644
--- a/samples-dev/swarm/swarm_ui_lib/view/ConveyorView.dart
+++ b/samples-dev/swarm/swarm_ui_lib/view/ConveyorView.dart
@@ -6,11 +6,9 @@
 
 part of view;
 
-/**
- * Holds a number of child views.  As you switch between views, the old
- * view is pushed off to the side and the new view slides in from the other
- * side.
- */
+/// Holds a number of child views.  As you switch between views, the old
+/// view is pushed off to the side and the new view slides in from the other
+/// side.
 class ConveyorView extends CompositeView {
   // TODO(jmesserly): some places use this property to know when the slide
   // transition is finished. It would be better to have an event that fires
@@ -29,8 +27,9 @@
 
   ConveyorView()
       : animationTimer = null,
-        super('conveyor-view', true) {}
+        super('conveyor-view', true);
 
+  @override
   Element render() {
     final result = super.render();
     // TODO(rnystrom): Have to do this in render() because container doesn't
@@ -60,11 +59,11 @@
     // specified in miliseconds rather than accepting a string.
     style.transitionDuration = '${durationSeconds}s';
     final xTranslationPercent = -index * 100;
-    style.transform = 'translate3d(${xTranslationPercent}%, 0px, 0px)';
+    style.transform = 'translate3d($xTranslationPercent%, 0px, 0px)';
 
     if (animate) {
-      animationTimer = new Timer(
-          new Duration(milliseconds: ((durationSeconds * 1000).toInt())), () {
+      animationTimer =
+          Timer(Duration(milliseconds: ((durationSeconds * 1000).toInt())), () {
         _onAnimationEnd();
       });
     }
@@ -81,10 +80,9 @@
     throw "view not found";
   }
 
-  /**
-   * Adds a child view to the ConveyorView.  The views are stacked horizontally
-   * in the order they are added.
-   */
+  /// Adds a child view to the ConveyorView.  The views are stacked horizontally
+  /// in the order they are added.
+  @override
   View addChild(View view) {
     view.addClass('conveyor-item');
     view.transform = 'translate3d(${(childViews.length * 100)}%, 0, 0)';
diff --git a/samples-dev/swarm/swarm_ui_lib/view/MeasureText.dart b/samples-dev/swarm/swarm_ui_lib/view/MeasureText.dart
index 7e768ee..a0cc55f 100644
--- a/samples-dev/swarm/swarm_ui_lib/view/MeasureText.dart
+++ b/samples-dev/swarm/swarm_ui_lib/view/MeasureText.dart
@@ -8,10 +8,8 @@
 
 // TODO(jacobr): handle splitting lines on symbols such as '-' that aren't
 // whitespace but are valid word breaking points.
-/**
- * Utility class to efficiently word break and measure text without requiring
- * access to the DOM.
- */
+/// Utility class to efficiently word break and measure text without requiring
+/// access to the DOM.
 class MeasureText {
   static CanvasRenderingContext2D _context;
 
@@ -23,7 +21,7 @@
 
   MeasureText(this.font) {
     if (_context == null) {
-      CanvasElement canvas = new Element.tag('canvas');
+      CanvasElement canvas = Element.tag('canvas');
       _context = canvas.getContext('2d');
     }
     if (_spaceLength == null) {
@@ -60,12 +58,10 @@
     }
   }
 
-  /**
-   * Add line broken text as html separated by <br> elements.
-   * Returns the number of lines in the output.
-   * This function is safe to call with [:sb == null:] in which case just the
-   * line count is returned.
-   */
+  /// Add line broken text as html separated by <br> elements.
+  /// Returns the number of lines in the output.
+  /// This function is safe to call with [:sb == null:] in which case just the
+  /// line count is returned.
   int addLineBrokenText(
       StringBuffer sb, String text, num lineWidth, int maxLines) {
     // Strip surrounding whitespace. This ensures we create zero lines if there
@@ -119,8 +115,8 @@
     int lines = 0;
     num currentLength = 0;
     int startIndex = 0;
-    int wordStartIndex = null;
-    int lastWordEndIndex = null;
+    int wordStartIndex;
+    int lastWordEndIndex;
     bool lastWhitespace = true;
     // TODO(jacobr): optimize this further.
     // To simplify the logic, we simulate injecting a whitespace character
diff --git a/samples-dev/swarm/swarm_ui_lib/view/PagedViews.dart b/samples-dev/swarm/swarm_ui_lib/view/PagedViews.dart
index d8e6c79..1198d87 100644
--- a/samples-dev/swarm/swarm_ui_lib/view/PagedViews.dart
+++ b/samples-dev/swarm/swarm_ui_lib/view/PagedViews.dart
@@ -11,25 +11,25 @@
   final ObservableValue<int> target;
   final ObservableValue<int> length;
   PageState()
-      : current = new ObservableValue<int>(0),
-        target = new ObservableValue<int>(0),
-        length = new ObservableValue<int>(1);
+      : current = ObservableValue<int>(0),
+        target = ObservableValue<int>(0),
+        length = ObservableValue<int>(1);
 }
 
-/** Simplifies using a PageNumberView and PagedColumnView together. */
+/// Simplifies using a PageNumberView and PagedColumnView together. */
 class PagedContentView extends CompositeView {
   final View content;
   final PageState pages;
 
   PagedContentView(this.content)
-      : pages = new PageState(),
+      : pages = PageState(),
         super('paged-content') {
-    addChild(new PagedColumnView(pages, content));
-    addChild(new PageNumberView(pages));
+    addChild(PagedColumnView(pages, content));
+    addChild(PageNumberView(pages));
   }
 }
 
-/** Displays current page and a left/right arrow. Used with [PagedColumnView] */
+/// Displays current page and a left/right arrow. Used with [PagedColumnView] */
 class PageNumberView extends View {
   final PageState pages;
   Element _label;
@@ -37,11 +37,12 @@
 
   PageNumberView(this.pages);
 
+  @override
   Element render() {
     // TODO(jmesserly): this was supposed to use the somewhat flatter unicode
     // glyphs that Chrome uses on the new tab page, but the text is getting
     // corrupted.
-    final node = new Element.html('''
+    final node = Element.html('''
         <div class="page-number">
           <div class="page-number-left">&lsaquo;</div>
           <div class="page-number-label"></div>
@@ -54,6 +55,7 @@
     return node;
   }
 
+  @override
   void enterDocument() {
     watch(pages.current, (s) => _update());
     watch(pages.length, (s) => _update());
@@ -76,16 +78,14 @@
   }
 }
 
-/**
- * A horizontal scrolling view that snaps to items like [ConveyorView], but only
- * has one child. Instead of scrolling between views, it scrolls between content
- * that flows horizontally in columns. Supports left/right swipe to switch
- * between pages. Can also be used with [PageNumberView].
- *
- * This control assumes that it is styled with fixed or percent width and
- * height, so the content will flow out horizontally. This allows it to compute
- * the number of pages using [:scrollWidth:] and [:offsetWidth:].
- */
+/// A horizontal scrolling view that snaps to items like [ConveyorView], but only
+/// has one child. Instead of scrolling between views, it scrolls between content
+/// that flows horizontally in columns. Supports left/right swipe to switch
+/// between pages. Can also be used with [PageNumberView].
+///
+/// This control assumes that it is styled with fixed or percent width and
+/// height, so the content will flow out horizontally. This allows it to compute
+/// the number of pages using [:scrollWidth:] and [:offsetWidth:].
 class PagedColumnView extends View {
   static const MIN_THROW_PAGE_FRACTION = 0.01;
   final View contentView;
@@ -99,8 +99,9 @@
 
   PagedColumnView(this.pages, this.contentView);
 
+  @override
   Element render() {
-    final node = new Element.html('''
+    final node = Element.html('''
       <div class="paged-column">
         <div class="paged-column-container"></div>
       </div>''');
@@ -113,9 +114,9 @@
     // the scroller configured the default way.
 
     // TODO(jacobr): use named arguments when available.
-    scroller = new Scroller(_container, false /* verticalScrollEnabled */,
+    scroller = Scroller(_container, false /* verticalScrollEnabled */,
         true /* horizontalScrollEnabled */, true /* momementumEnabled */, () {
-      return new Size(_getViewLength(_container), 1);
+      return Size(_getViewLength(_container), 1);
     }, Scroller.FAST_SNAP_DECELERATION_FACTOR);
 
     scroller.onDecelStart.listen(_snapToPage);
@@ -130,6 +131,7 @@
 
   // TODO(jmesserly): would be better to not have this code in enterDocument.
   // But we need computedStyle to read our CSS properties.
+  @override
   void enterDocument() {
     scheduleMicrotask(() {
       var style = contentView.node.getComputedStyle();
@@ -153,7 +155,7 @@
     });
   }
 
-  /** Read the column-gap setting so we know how far to translate the child. */
+  /// Read the column-gap setting so we know how far to translate the child. */
   void _computeColumnGap(CssStyleDeclaration style) {
     String gap = style.columnGap;
     if (gap == 'normal') {
@@ -172,7 +174,8 @@
     return double.parse(value).round();
   }
 
-  /** Watch for resize and update page count. */
+  /// Watch for resize and update page count. */
+  @override
   void windowResized() {
     // TODO(jmesserly): verify we aren't triggering unnecessary layouts.
 
diff --git a/samples-dev/swarm/swarm_ui_lib/view/SliderMenu.dart b/samples-dev/swarm/swarm_ui_lib/view/SliderMenu.dart
index 3f13e4d..aba98b8 100644
--- a/samples-dev/swarm/swarm_ui_lib/view/SliderMenu.dart
+++ b/samples-dev/swarm/swarm_ui_lib/view/SliderMenu.dart
@@ -6,12 +6,10 @@
 
 part of view;
 
-typedef void SelectHandler(String menuText);
+typedef SelectHandler = void Function(String menuText);
 
-/**
- * This implements a horizontal menu bar with a sliding triangle arrow
- * that points at the currently selected item.
- */
+/// This implements a horizontal menu bar with a sliding triangle arrow
+/// that points at the currently selected item.
 class SliderMenu extends View {
   static const int TRIANGLE_WIDTH = 24;
 
@@ -24,25 +22,24 @@
   // TODO(mattsh) - move this to a touch mixin
   Element touchItem;
 
-  /**
-   * Callback function that we call when the user chooses something from
-   * the menu.  This is passed the menu item text.
-   */
+  /// Callback function that we call when the user chooses something from
+  /// the menu.  This is passed the menu item text.
   SelectHandler onSelect;
 
-  List<String> _menuItems;
+  final List<String> _menuItems;
 
   SliderMenu(this._menuItems, this.onSelect);
 
+  @override
   Element render() {
     // Create a div for each menu item.
-    final items = new StringBuffer();
+    final items = StringBuffer();
     for (final item in _menuItems) {
       items.write('<div class="sm-item">$item</div>');
     }
 
     // Create a root node to hold this view.
-    return new Element.html('''
+    return Element.html('''
         <div class="sm-root">
           <div class="sm-item-box">
             <div class="sm-item-filler"></div>
@@ -56,6 +53,7 @@
         ''');
   }
 
+  @override
   void enterDocument() {
     // select the first item
     // todo(jacobr): too much actual work is performed in enterDocument.
@@ -95,10 +93,8 @@
     window.onResize.listen((Event event) => updateIndicator(false));
   }
 
-  /**
-   * Walks the parent chain of the first Touch target to find the first ancestor
-   * that has sm-item class.
-   */
+  /// Walks the parent chain of the first Touch target to find the first ancestor
+  /// that has sm-item class.
   Element itemOfTouchEvent(event) {
     Node node = event.changedTouches[0].target;
     return itemOfNode(node);
@@ -153,9 +149,7 @@
     }
   }
 
-  /**
-   * animate - if true, then animate the movement of the triangle slider
-   */
+  /// animate - if true, then animate the movement of the triangle slider
   void updateIndicator(bool animate) {
     if (selectedItem != null) {
       // calculate where we want to put the triangle
diff --git a/samples-dev/swarm/swarm_ui_lib/view/view.dart b/samples-dev/swarm/swarm_ui_lib/view/view.dart
index 30f5e46..fef3cb8 100644
--- a/samples-dev/swarm/swarm_ui_lib/view/view.dart
+++ b/samples-dev/swarm/swarm_ui_lib/view/view.dart
@@ -26,7 +26,7 @@
 // subclasses are refactored to use the new way. There will be some scaffolding
 // and construction cones laying around. Try not to freak out.
 
-/** A generic view. */
+/// A generic view. */
 class View implements Positionable {
   Element _node;
   ViewLayout _layout;
@@ -35,25 +35,25 @@
   // App track the views that want to be notified of resize()
   StreamSubscription _resizeSubscription;
 
-  /**
-   * Style properties configured for this view.
-   */
+  /// Style properties configured for this view.
   // TODO(jmesserly): We should be getting these from our CSS preprocessor.
   // I'm not sure if this will stay as a Map, or just be a get method.
   // TODO(jacobr): Consider returning a somewhat typed base.Style wrapper
   // object instead, and integrating with built in CSS properties.
+  @override
   final Map<String, String> customStyle;
 
-  View() : customStyle = new Map<String, String>();
+  View() : customStyle = <String, String>{};
 
-  View.fromNode(Element this._node) : customStyle = new Map<String, String>();
+  View.fromNode(this._node) : customStyle = <String, String>{};
 
   View.html(String html)
-      : customStyle = new Map<String, String>(),
-        _node = new Element.html(html);
+      : customStyle = <String, String>{},
+        _node = Element.html(html);
 
   // TODO(rnystrom): Get rid of this when all views are refactored to not use
   // it.
+  @override
   Element get node {
     // Lazy render.
     if (_node == null) {
@@ -63,22 +63,19 @@
     return _node;
   }
 
-  /**
-   * A subclass that contains child views should override this to return those
-   * views. View uses this to ensure that child views are properly rendered
-   * and initialized when their parent view is without the parent having to
-   * manually handle that traversal.
-   */
+  /// A subclass that contains child views should override this to return those
+  /// views. View uses this to ensure that child views are properly rendered
+  /// and initialized when their parent view is without the parent having to
+  /// manually handle that traversal.
+  @override
   Iterable<View> get childViews {
     return const [];
   }
 
-  /**
-   * View presumes the collection of views returned by childViews is more or
-   * less static after the view is first created. Subclasses should call this
-   * when that invariant doesn't hold to let View know that a new childView has
-   * appeared.
-   */
+  /// View presumes the collection of views returned by childViews is more or
+  /// less static after the view is first created. Subclasses should call this
+  /// when that invariant doesn't hold to let View know that a new childView has
+  /// appeared.
   void childViewAdded(View child) {
     if (isInDocument) {
       child._enterDocument();
@@ -88,37 +85,31 @@
     }
   }
 
-  /**
-   * View presumes the collection of views returned by childViews is more or
-   * less static after the view is first created. Subclasses should call this
-   * when that invariant doesn't hold to let View know that a childView has
-   * been removed.
-   */
+  /// View presumes the collection of views returned by childViews is more or
+  /// less static after the view is first created. Subclasses should call this
+  /// when that invariant doesn't hold to let View know that a childView has
+  /// been removed.
   void childViewRemoved(View child) {
     if (isInDocument) {
       child._exitDocument();
     }
   }
 
-  /** Gets whether this View has already been rendered or not. */
+  /// Gets whether this View has already been rendered or not. */
   bool get isRendered {
     return _node != null;
   }
 
-  /**
-   * Gets whether this View (or one of its parents) has been added to the
-   * document or not.
-   */
+  /// Gets whether this View (or one of its parents) has been added to the
+  /// document or not.
   bool get isInDocument {
     return _node != null &&
         node.ownerDocument is HtmlDocument &&
         (node.ownerDocument as HtmlDocument).body.contains(node);
   }
 
-  /**
-   * Adds this view to the document as a child of the given node. This should
-   * generally only be called once for the top-level view.
-   */
+  /// Adds this view to the document as a child of the given node. This should
+  /// generally only be called once for the top-level view.
   void addToDocument(Element parentNode) {
     assert(!isInDocument);
 
@@ -137,66 +128,58 @@
     _node.remove();
   }
 
-  /**
-   * Override this to generate the DOM structure for the view.
-   */
+  /// Override this to generate the DOM structure for the view.
   // TODO(rnystrom): make this method abstract, see b/5015671
   Element render() {
     throw 'abstract';
   }
 
-  /**
-   * Override this to perform initialization behavior that requires access to
-   * the DOM associated with the View, such as event wiring.
-   */
+  /// Override this to perform initialization behavior that requires access to
+  /// the DOM associated with the View, such as event wiring.
   void afterRender(Element node) {
     // Do nothing by default.
   }
 
-  /**
-   * Override this to perform behavior after this View has been added to the
-   * document. This is appropriate if you need access to state (such as the
-   * calculated size of an element) that's only available when the View is in
-   * the document.
-   *
-   * This will be called each time the View is added to the document, if it is
-   * added and removed multiple times.
-   */
+  /// Override this to perform behavior after this View has been added to the
+  /// document. This is appropriate if you need access to state (such as the
+  /// calculated size of an element) that's only available when the View is in
+  /// the document.
+  ///
+  /// This will be called each time the View is added to the document, if it is
+  /// added and removed multiple times.
   void enterDocument() {}
 
-  /**
-   * Override this to perform behavior after this View has been removed from the
-   * document. This can be a convenient time to unregister event handlers bound
-   * in enterDocument().
-   *
-   * This will be called each time the View is removed from the document, if it
-   * is added and removed multiple times.
-   */
+  /// Override this to perform behavior after this View has been removed from the
+  /// document. This can be a convenient time to unregister event handlers bound
+  /// in enterDocument().
+  ///
+  /// This will be called each time the View is removed from the document, if it
+  /// is added and removed multiple times.
   void exitDocument() {}
 
-  /** Override this to perform behavior after the window is resized. */
+  /// Override this to perform behavior after the window is resized. */
   // TODO(jmesserly): this isn't really the event we want. Ideally we want to
   // fire the event only if this particular View changed size. Also we should
   // give a view the ability to measure itself when added to the document.
   void windowResized() {}
 
-  /**
-   * Registers the given listener callback to the given observable. Also
-   * immediately invokes the callback once as if a change has just come in.
-   * This lets you define a render() method that renders the skeleton of a
-   * view, then register a bunch of listeners which all fire to populate the
-   * view with model data.
-   */
-  void watch(Observable observable, void watcher(EventSummary summary)) {
+  /// Registers the given listener callback to the given observable. Also
+  /// immediately invokes the callback once as if a change has just come in.
+  /// This lets you define a render() method that renders the skeleton of a
+  /// view, then register a bunch of listeners which all fire to populate the
+  /// view with model data.
+  void watch(
+      Observable observable, void Function(EventSummary summary) watcher) {
     // Make a fake summary for the initial watch.
-    final summary = new EventSummary(observable);
+    final summary = EventSummary(observable);
     watcher(summary);
 
     attachWatch(observable, watcher);
   }
 
-  /** Registers the given listener callback to the given observable. */
-  void attachWatch(Observable observable, void watcher(EventSummary summary)) {
+  /// Registers the given listener callback to the given observable. */
+  void attachWatch(
+      Observable observable, void Function(EventSummary summary) watcher) {
     observable.addChangeListener(watcher);
 
     // TODO(rnystrom): Should keep track of this and unregister when the view
@@ -207,15 +190,11 @@
     _node.onClick.listen(handler);
   }
 
-  /**
-   * Gets whether the view is hidden.
-   */
+  /// Gets whether the view is hidden.
   bool get hidden => _node.style.display == 'none';
 
-  /**
-   * Sets whether the view is hidden.
-   */
-  void set hidden(bool hidden) {
+  /// Sets whether the view is hidden.
+  set hidden(bool hidden) {
     if (hidden) {
       node.style.display = 'none';
     } else {
@@ -231,43 +210,35 @@
     node.classes.remove(className);
   }
 
-  /** Sets the CSS3 transform applied to the view. */
+  /// Sets the CSS3 transform applied to the view. */
   set transform(String transform) {
     node.style.transform = transform;
   }
 
   // TODO(rnystrom): Get rid of this, or move into a separate class?
-  /** Creates a View whose node is a <div> with the given class(es). */
-  static View div(String cssClass, [String body = null]) {
-    if (body == null) {
-      body = '';
-    }
-    return new View.html('<div class="$cssClass">$body</div>');
+  /// Creates a View whose node is a <div> with the given class(es). */
+  static View div(String cssClass, [String body]) {
+    body ??= '';
+    return View.html('<div class="$cssClass">$body</div>');
   }
 
-  /**
-   * Internal render method that deals with traversing child views. Should not
-   * be overridden.
-   */
+  /// Internal render method that deals with traversing child views. Should not
+  /// be overridden.
   void _render() {
     // TODO(rnystrom): Should render child views here. Not implemented yet.
     // Instead, we rely on the parent accessing .node to implicitly cause the
     // child to be rendered.
 
     // Render this view.
-    if (_node == null) {
-      _node = render();
-    }
+    _node ??= render();
 
     // Pass the node back to the derived view so it can register event
     // handlers on it.
     afterRender(_node);
   }
 
-  /**
-   * Internal method that deals with traversing child views. Should not be
-   * overridden.
-   */
+  /// Internal method that deals with traversing child views. Should not be
+  /// overridden.
   void _enterDocument() {
     // Notify the children first.
     for (final child in childViews) {
@@ -279,17 +250,14 @@
 
   // Layout related methods
 
+  @override
   ViewLayout get layout {
-    if (_layout == null) {
-      _layout = new ViewLayout.fromView(this);
-    }
+    _layout ??= ViewLayout.fromView(this);
     return _layout;
   }
 
-  /**
-   * Internal method that deals with traversing child views. Should not be
-   * overridden.
-   */
+  /// Internal method that deals with traversing child views. Should not be
+  /// overridden.
   void _exitDocument() {
     // Notify this View first so that it's children are still valid.
     exitDocument();
@@ -300,11 +268,9 @@
     }
   }
 
-  /**
-   * If needed, starts a layout computation from the top level.
-   * Also hooks the relevant events like window resize, so we can layout on too
-   * demand.
-   */
+  /// If needed, starts a layout computation from the top level.
+  /// Also hooks the relevant events like window resize, so we can layout on too
+  /// demand.
   void _hookGlobalLayoutEvents() {
     if (_resizeSubscription == null) {
       var handler = EventBatch.wrap((e) => doLayout());
@@ -322,6 +288,7 @@
     }
   }
 
+  @override
   void doLayout() {
     _measureLayout().then((changed) {
       if (changed) {
@@ -332,7 +299,7 @@
 
   Future<bool> _measureLayout() {
     // TODO(10459): code should not use Completer.sync.
-    final changed = new Completer<bool>.sync();
+    final changed = Completer<bool>.sync();
     _measureLayoutHelper(changed);
 
     var changedComplete = false;
@@ -356,10 +323,9 @@
     // a good tradeoff?
     if (ViewLayout.hasCustomLayout(this)) {
       // TODO(10459): code should not use Completer.sync.
-      Completer sizeCompleter = new Completer<Size>.sync();
+      Completer sizeCompleter = Completer<Size>.sync();
       scheduleMicrotask(() {
-        sizeCompleter
-            .complete(new Size(_node.client.width, _node.client.height));
+        sizeCompleter.complete(Size(_node.client.width, _node.client.height));
       });
       layout.measureLayout(sizeCompleter.future, changed);
     } else {
diff --git a/tests/ffi/vmspecific_static_checks_ffinative_test.dart b/tests/ffi/vmspecific_static_checks_ffinative_test.dart
index 72549f7..8038c09 100644
--- a/tests/ffi/vmspecific_static_checks_ffinative_test.dart
+++ b/tests/ffi/vmspecific_static_checks_ffinative_test.dart
@@ -37,6 +37,10 @@
   // Error: Missing receiver in FfiNative annotation.
   @FfiNative<Void Function(IntPtr)>('doesntmatter') //# 05: compile-time error
   external void badMissingReceiver(int v); //# 05: compile-time error
+
+  // Error: wrong return type.
+  @FfiNative<Handle Function(Pointer<Void>, Uint32, Uint32, Handle)>('doesntmatter') //# 49471: compile-time error
+  external void toImageSync(int width, int height, Object outImage);  //# 49471: compile-time error
 }
 
 // Error: Too many FfiNative parameters.
diff --git a/tests/ffi/vmspecific_static_checks_test.dart b/tests/ffi/vmspecific_static_checks_test.dart
index 692fc1e..378264d 100644
--- a/tests/ffi/vmspecific_static_checks_test.dart
+++ b/tests/ffi/vmspecific_static_checks_test.dart
@@ -64,6 +64,7 @@
   testAsFunctionTakesHandle();
   testLookupFunctionReturnsHandle();
   testAsFunctionReturnsHandle();
+  testReturnVoidNotVoid();
 }
 
 typedef Int8UnOp = Int8 Function(Int8);
@@ -820,3 +821,11 @@
 {
   external Pointer<Void> field;
 }
+
+void testReturnVoidNotVoid() {
+  // Taking a more specific argument is okay.
+  testLibrary //# 49471: compile-time error
+      .lookupFunction< //# 49471: compile-time error
+          Handle Function(), //# 49471: compile-time error
+          void Function()>("doesntmatter"); //# 49471: compile-time error
+}
diff --git a/tools/VERSION b/tools/VERSION
index 6265d32..74a7ffc 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 19
 PATCH 0
-PRERELEASE 51
+PRERELEASE 52
 PRERELEASE_PATCH 0
\ No newline at end of file