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, <down arrow> </th>
- ${cellStart} Next Article </th>
+ $cellStart j, <down arrow> </th>
+ $cellStart Next Article </th>
</tr>
<tr>
- ${cellStart} k, <up arrow> </th>
- ${cellStart} Previous Article </th>
+ $cellStart k, <up arrow> </th>
+ $cellStart Previous Article </th>
</tr>
<tr>
- ${cellStart} o, <enter> </th>
- ${cellStart} Open Article </th>
+ $cellStart o, <enter> </th>
+ $cellStart Open Article </th>
</tr>
<tr>
- ${cellStart} <esc>, <delete> </th>
- ${cellStart} Back </th>
+ $cellStart <esc>, <delete> </th>
+ $cellStart Back </th>
</tr>
<tr>
- ${cellStart} a, h, <left arrow> </th>
- ${cellStart} Left </th>
+ $cellStart a, h, <left arrow> </th>
+ $cellStart Left </th>
</tr>
<tr>
- ${cellStart} d, l, <right arrow> </th>
- ${cellStart} Right </th>
+ $cellStart d, l, <right arrow> </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">‹</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