Version 0.6.0.0
svn merge -r 24101:24454 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@24460 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/client/tools/buildbot_annotated_steps.py b/client/tools/buildbot_annotated_steps.py
index d65c4e0..347b483 100755
--- a/client/tools/buildbot_annotated_steps.py
+++ b/client/tools/buildbot_annotated_steps.py
@@ -218,7 +218,8 @@
match = re.search('dart-editor-fyi(.*)', name)
name = 'dart-editor' + match.group(1)
# In case we're an FYI builder, run 'tools/bots/editor.py'.
- status = ProcessBot(name, 'editor')
+ status = ProcessBot(name, 'editor',
+ custom_env=EnvironmentWithoutBotoConfig())
else:
# Run the old annotated steps script
status = ProcessTools('release', name, version)
diff --git a/pkg/analyzer_experimental/bin/coverage.dart b/pkg/analyzer_experimental/bin/coverage.dart
index 87be02e..ed6d2f6 100644
--- a/pkg/analyzer_experimental/bin/coverage.dart
+++ b/pkg/analyzer_experimental/bin/coverage.dart
@@ -4,19 +4,86 @@
library runtime.coverage;
-import "package:logging/logging.dart" as log;
+import 'dart:io';
-import 'package:analyzer_experimental/src/services/runtime/coverage_impl.dart';
+import 'package:args/args.dart';
+
+import 'package:analyzer_experimental/src/services/runtime/log.dart' as log;
+import 'package:analyzer_experimental/src/services/runtime/coverage/coverage_impl.dart';
main() {
- var logger = log.Logger.root;
- logger.level = log.Level.ALL;
- logger.onRecord.listen((log.LogRecord record) {
- String levelString = record.level.toString();
- while (levelString.length < 6) levelString += ' ';
- print('${record.time}: ${levelString} ${record.message}');
- });
- // TODO(scheglov) get script from options
- new CoverageServer('/Users/scheglov/dart/Test/bin').start();
-}
\ No newline at end of file
+ ArgResults options;
+ try {
+ options = _argParser.parse(new Options().arguments);
+ } on FormatException catch (e) {
+ print(e.message);
+ print('Run "coverage --help" to see available options.');
+ exit(ERROR);
+ }
+
+ if (options['help']) {
+ printUsage();
+ return;
+ }
+
+ // No script to run.
+ if (options.rest.isEmpty) {
+ printUsage('<No script to run specified>');
+ exit(ERROR);
+ }
+
+ // More than one script specified.
+ if (options.rest.length != 1) {
+ print('<Only one script should be specified>');
+ exit(ERROR);
+ }
+
+ var scriptPath = options.rest[0];
+
+ // Validate that script file exists.
+ if (!new File(scriptPath).existsSync()) {
+ print('<File "$scriptPath" does not exist>');
+ exit(ERROR);
+ }
+
+ // Prepare output file path.
+ var outPath = options['out'];
+ if (outPath == null) {
+ printUsage('No --out specified.');
+ exit(ERROR);
+ }
+
+ // Configure logigng.
+ log.everything();
+ log.toConsole();
+
+ // Run script.
+ runServerApplication(scriptPath, outPath);
+}
+
+
+final ArgParser _argParser = new ArgParser()
+ ..addFlag('help', negatable: false, help: 'Print this usage information.')
+ ..addOption(
+ 'level',
+ help: 'The level of the coverage.',
+ allowed: ['method', 'block', 'statement'],
+ defaultsTo: 'statement')
+ ..addOption('out', help: 'The output file with statistics.')
+ ..addOption(
+ 'port',
+ help: 'The port to run server on, if 0 select any.',
+ defaultsTo: '0');
+
+
+printUsage([var description = 'Code coverage tool for Dart.']) {
+ var usage = _argParser.getUsage();
+ print('$description\n');
+ print('Usage: coverage [options] <script>\n');
+ print('$usage\n');
+}
+
+
+/// General error code.
+const ERROR = 1;
diff --git a/pkg/analyzer_experimental/lib/analyzer.dart b/pkg/analyzer_experimental/lib/analyzer.dart
index 30f8857..47ca97c 100644
--- a/pkg/analyzer_experimental/lib/analyzer.dart
+++ b/pkg/analyzer_experimental/lib/analyzer.dart
@@ -6,6 +6,8 @@
import 'dart:io';
+import 'package:pathos/path.dart' as pathos;
+
import 'src/error.dart';
import 'src/generated/ast.dart';
import 'src/generated/error.dart';
@@ -13,7 +15,6 @@
import 'src/generated/parser.dart';
import 'src/generated/scanner.dart';
import 'src/generated/source_io.dart';
-import 'src/utils.dart';
export 'src/error.dart';
export 'src/generated/ast.dart';
@@ -25,7 +26,7 @@
var contents = new File(path).readAsStringSync();
var errorCollector = new _ErrorCollector();
var sourceFactory = new SourceFactory.con2([new FileUriResolver()]);
- var source = sourceFactory.forUri(pathToFileUri(path).toString());
+ var source = sourceFactory.forUri(pathos.toUri(path).toString());
var scanner = new StringScanner(source, contents, errorCollector);
var token = scanner.tokenize();
var parser = new Parser(source, errorCollector);
diff --git a/pkg/analyzer_experimental/lib/options.dart b/pkg/analyzer_experimental/lib/options.dart
index 83d5585..dd841f0 100644
--- a/pkg/analyzer_experimental/lib/options.dart
+++ b/pkg/analyzer_experimental/lib/options.dart
@@ -153,7 +153,7 @@
static String _getVersion() {
try {
- Path path = new Path(new Options().script);
+ Path path = new Path(Platform.script);
Path versionPath = path.directoryPath.append('..').append('version');
File versionFile = new File.fromPath(versionPath);
return versionFile.readAsStringSync().trim();
@@ -251,7 +251,6 @@
}
}
- print(filtered);
return filtered;
}
diff --git a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
index 5d8fc4c..4e46d61 100644
--- a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
@@ -81,7 +81,6 @@
} else {
packageDirectory = getPackageDirectoryFor(sourceFile);
}
- print('packageDirectory: ${packageDirectory.getPath()}');
if (packageDirectory != null) {
resolvers.add(new PackageUriResolver([packageDirectory]));
}
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart
index 0adebba..6b7d525 100644
--- a/pkg/analyzer_experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -11,25 +11,25 @@
import 'utilities_dart.dart';
import 'element.dart';
/**
- * The abstract class {@code ASTNode} defines the behavior common to all nodes in the AST structure
+ * The abstract class `ASTNode` defines the behavior common to all nodes in the AST structure
* for a Dart program.
* @coverage dart.engine.ast
*/
abstract class ASTNode {
/**
- * The parent of the node, or {@code null} if the node is the root of an AST structure.
+ * The parent of the node, or `null` if the node is the root of an AST structure.
*/
ASTNode _parent;
/**
- * A table mapping the names of properties to their values, or {@code null} if this node does not
+ * A table mapping the names of properties to their values, or `null` if this node does not
* have any properties associated with it.
*/
Map<String, Object> _propertyMap;
/**
- * A comparator that can be used to sort AST nodes in lexical order. In other words,{@code compare} will return a negative value if the offset of the first node is less than the
+ * A comparator that can be used to sort AST nodes in lexical order. In other words,`compare` will return a negative value if the offset of the first node is less than the
* offset of the second node, zero (0) if the nodes have the same offset, and a positive value if
* if the offset of the first node is greater than the offset of the second node.
*/
@@ -43,7 +43,7 @@
accept(ASTVisitor visitor);
/**
- * @return the {@link ASTNode} of given {@link Class} which is {@link ASTNode} itself, or one of
+ * @return the [ASTNode] of given [Class] which is [ASTNode] itself, or one of
* its parents.
*/
ASTNode getAncestor(Type enclosingClass) {
@@ -63,7 +63,7 @@
/**
* Return the offset of the character immediately following the last character of this node's
- * source range. This is equivalent to {@code node.getOffset() + node.getLength()}. For a
+ * source range. This is equivalent to `node.getOffset() + node.getLength()`. For a
* compilation unit this will be equal to the length of the unit's source. For synthetic nodes
* this will be equivalent to the node's offset (because the length is zero (0) by definition).
* @return the offset of the character just past the node's source range
@@ -104,16 +104,16 @@
}
/**
- * Return this node's parent node, or {@code null} if this node is the root of an AST structure.
- * <p>
+ * Return this node's parent node, or `null` if this node is the root of an AST structure.
+ *
* Note that the relationship between an AST node and its parent node may change over the lifetime
* of a node.
- * @return the parent of this node, or {@code null} if none
+ * @return the parent of this node, or `null` if none
*/
ASTNode get parent => _parent;
/**
- * Return the value of the property with the given name, or {@code null} if this node does not
+ * Return the value of the property with the given name, or `null` if this node does not
* have a property with the given name.
* @return the value of the property with the given name
*/
@@ -140,15 +140,15 @@
}
/**
- * Return {@code true} if this node is a synthetic node. A synthetic node is a node that was
+ * Return `true` if this node is a synthetic node. A synthetic node is a node that was
* introduced by the parser in order to recover from an error in the code. Synthetic nodes always
- * have a length of zero ({@code 0}).
- * @return {@code true} if this node is a synthetic node
+ * have a length of zero (`0`).
+ * @return `true` if this node is a synthetic node
*/
- bool isSynthetic() => false;
+ bool get isSynthetic => false;
/**
- * Set the value of the property with the given name to the given value. If the value is{@code null}, the property will effectively be removed.
+ * Set the value of the property with the given name to the given value. If the value is`null`, the property will effectively be removed.
* @param propertyName the name of the property whose value is to be set
* @param propertyValue the new value of the property
*/
@@ -201,7 +201,7 @@
}
/**
- * If the given child is not {@code null}, use the given visitor to visit it.
+ * If the given child is not `null`, use the given visitor to visit it.
* @param child the child to be visited
* @param visitor the visitor that will be used to visit the child
*/
@@ -222,7 +222,7 @@
final int hashCode = ++_hashCodeGenerator;
}
/**
- * The interface {@code ASTVisitor} defines the behavior of objects that can be used to visit an AST
+ * The interface `ASTVisitor` defines the behavior of objects that can be used to visit an AST
* structure.
* @coverage dart.engine.ast
*/
@@ -330,13 +330,13 @@
R visitWithClause(WithClause node);
}
/**
- * Instances of the class {@code AdjacentStrings} represents two or more string literals that are
+ * Instances of the class `AdjacentStrings` represents two or more string literals that are
* implicitly concatenated because of being adjacent (separated only by whitespace).
- * <p>
+ *
* While the grammar only allows adjacent strings when all of the strings are of the same kind
* (single line or multi-line), this class doesn't enforce that restriction.
* <pre>
- * adjacentStrings ::={@link StringLiteral string} {@link StringLiteral string}+
+ * adjacentStrings ::=[StringLiteral string] [StringLiteral string]+
* </pre>
* @coverage dart.engine.ast
*/
@@ -380,14 +380,14 @@
}
}
/**
- * The abstract class {@code AnnotatedNode} defines the behavior of nodes that can be annotated with
+ * The abstract class `AnnotatedNode` defines the behavior of nodes that can be annotated with
* both a comment and metadata.
* @coverage dart.engine.ast
*/
abstract class AnnotatedNode extends ASTNode {
/**
- * The documentation comment associated with this node, or {@code null} if this node does not have
+ * The documentation comment associated with this node, or `null` if this node does not have
* a documentation comment associated with it.
*/
Comment _comment;
@@ -433,7 +433,7 @@
}
/**
- * Return the documentation comment associated with this node, or {@code null} if this node does
+ * Return the documentation comment associated with this node, or `null` if this node does
* not have a documentation comment associated with it.
* @return the documentation comment associated with this node
*/
@@ -479,8 +479,8 @@
Token get firstTokenAfterCommentAndMetadata;
/**
- * Return {@code true} if the comment is lexically before any annotations.
- * @return {@code true} if the comment is lexically before any annotations
+ * Return `true` if the comment is lexically before any annotations.
+ * @return `true` if the comment is lexically before any annotations
*/
bool commentIsBeforeAnnotations() {
if (_comment == null || _metadata.isEmpty) {
@@ -506,13 +506,13 @@
}
}
/**
- * Instances of the class {@code Annotation} represent an annotation that can be associated with an
+ * Instances of the class `Annotation` represent an annotation that can be associated with an
* AST node.
* <pre>
* metadata ::=
* annotation
* annotation ::=
- * '@' {@link Identifier qualified} ('.' {@link SimpleIdentifier identifier})? {@link ArgumentList arguments}?
+ * '@' [Identifier qualified] ('.' [SimpleIdentifier identifier])? [ArgumentList arguments]?
* </pre>
* @coverage dart.engine.ast
*/
@@ -530,19 +530,19 @@
Identifier _name;
/**
- * The period before the constructor name, or {@code null} if this annotation is not the
+ * The period before the constructor name, or `null` if this annotation is not the
* invocation of a named constructor.
*/
Token _period;
/**
- * The name of the constructor being invoked, or {@code null} if this annotation is not the
+ * The name of the constructor being invoked, or `null` if this annotation is not the
* invocation of a named constructor.
*/
SimpleIdentifier _constructorName;
/**
- * The arguments to the constructor being invoked, or {@code null} if this annotation is not the
+ * The arguments to the constructor being invoked, or `null` if this annotation is not the
* invocation of a constructor.
*/
ArgumentList _arguments;
@@ -552,11 +552,11 @@
* @param atSign the at sign that introduced the annotation
* @param name the name of the class defining the constructor that is being invoked or the name of
* the field that is being referenced
- * @param period the period before the constructor name, or {@code null} if this annotation is not
+ * @param period the period before the constructor name, or `null` if this annotation is not
* the invocation of a named constructor
- * @param constructorName the name of the constructor being invoked, or {@code null} if this
+ * @param constructorName the name of the constructor being invoked, or `null` if this
* annotation is not the invocation of a named constructor
- * @param arguments the arguments to the constructor being invoked, or {@code null} if this
+ * @param arguments the arguments to the constructor being invoked, or `null` if this
* annotation is not the invocation of a constructor
*/
Annotation.full(Token atSign, Identifier name, Token period, SimpleIdentifier constructorName, ArgumentList arguments) {
@@ -572,18 +572,18 @@
* @param atSign the at sign that introduced the annotation
* @param name the name of the class defining the constructor that is being invoked or the name of
* the field that is being referenced
- * @param period the period before the constructor name, or {@code null} if this annotation is not
+ * @param period the period before the constructor name, or `null` if this annotation is not
* the invocation of a named constructor
- * @param constructorName the name of the constructor being invoked, or {@code null} if this
+ * @param constructorName the name of the constructor being invoked, or `null` if this
* annotation is not the invocation of a named constructor
- * @param arguments the arguments to the constructor being invoked, or {@code null} if this
+ * @param arguments the arguments to the constructor being invoked, or `null` if this
* annotation is not the invocation of a constructor
*/
Annotation({Token atSign, Identifier name, Token period, SimpleIdentifier constructorName, ArgumentList arguments}) : this.full(atSign, name, period, constructorName, arguments);
accept(ASTVisitor visitor) => visitor.visitAnnotation(this);
/**
- * Return the arguments to the constructor being invoked, or {@code null} if this annotation is
+ * Return the arguments to the constructor being invoked, or `null` if this annotation is
* not the invocation of a constructor.
* @return the arguments to the constructor being invoked
*/
@@ -597,14 +597,14 @@
Token get beginToken => _atSign;
/**
- * Return the name of the constructor being invoked, or {@code null} if this annotation is not the
+ * Return the name of the constructor being invoked, or `null` if this annotation is not the
* invocation of a named constructor.
* @return the name of the constructor being invoked
*/
SimpleIdentifier get constructorName => _constructorName;
/**
- * Return the element associated with this annotation, or {@code null} if the AST structure has
+ * Return the element associated with this annotation, or `null` if the AST structure has
* not been resolved or if this annotation could not be resolved.
* @return the element associated with this annotation
*/
@@ -633,7 +633,7 @@
Identifier get name => _name;
/**
- * Return the period before the constructor name, or {@code null} if this annotation is not the
+ * Return the period before the constructor name, or `null` if this annotation is not the
* invocation of a named constructor.
* @return the period before the constructor name
*/
@@ -686,10 +686,10 @@
}
}
/**
- * Instances of the class {@code ArgumentDefinitionTest} represent an argument definition test.
+ * Instances of the class `ArgumentDefinitionTest` represent an argument definition test.
* <pre>
* argumentDefinitionTest ::=
- * '?' {@link SimpleIdentifier identifier}</pre>
+ * '?' [SimpleIdentifier identifier]</pre>
* @coverage dart.engine.ast
*/
class ArgumentDefinitionTest extends Expression {
@@ -756,13 +756,13 @@
}
}
/**
- * Instances of the class {@code ArgumentList} represent a list of arguments in the invocation of a
+ * Instances of the class `ArgumentList` represent a list of arguments in the invocation of a
* executable element: a function, method, or constructor.
* <pre>
* argumentList ::=
* '(' arguments? ')'
- * arguments ::={@link NamedExpression namedArgument} (',' {@link NamedExpression namedArgument})
- * | {@link Expression expressionList} (',' {@link NamedExpression namedArgument})
+ * arguments ::=[NamedExpression namedArgument] (',' [NamedExpression namedArgument])
+ * | [Expression expressionList] (',' [NamedExpression namedArgument])
* </pre>
* @coverage dart.engine.ast
*/
@@ -785,18 +785,18 @@
/**
* An array containing the elements representing the parameters corresponding to each of the
- * arguments in this list, or {@code null} if the AST has not been resolved or if the function or
+ * arguments in this list, or `null` if the AST has not been resolved or if the function or
* method being invoked could not be determined based on static type information. The array must
- * be the same length as the number of arguments, but can contain {@code null} entries if a given
+ * be the same length as the number of arguments, but can contain `null` entries if a given
* argument does not correspond to a formal parameter.
*/
List<ParameterElement> _correspondingStaticParameters;
/**
* An array containing the elements representing the parameters corresponding to each of the
- * arguments in this list, or {@code null} if the AST has not been resolved or if the function or
+ * arguments in this list, or `null` if the AST has not been resolved or if the function or
* method being invoked could not be determined based on propagated type information. The array
- * must be the same length as the number of arguments, but can contain {@code null} entries if a
+ * must be the same length as the number of arguments, but can contain `null` entries if a
* given argument does not correspond to a formal parameter.
*/
List<ParameterElement> _correspondingPropagatedParameters;
@@ -848,7 +848,7 @@
/**
* Set the parameter elements corresponding to each of the arguments in this list to the given
* array of parameters. The array of parameters must be the same length as the number of
- * arguments, but can contain {@code null} entries if a given argument does not correspond to a
+ * arguments, but can contain `null` entries if a given argument does not correspond to a
* formal parameter.
* @param parameters the parameter elements corresponding to the arguments
*/
@@ -862,7 +862,7 @@
/**
* Set the parameter elements corresponding to each of the arguments in this list to the given
* array of parameters. The array of parameters must be the same length as the number of
- * arguments, but can contain {@code null} entries if a given argument does not correspond to a
+ * arguments, but can contain `null` entries if a given argument does not correspond to a
* formal parameter.
* @param parameters the parameter elements corresponding to the arguments
*/
@@ -897,9 +897,9 @@
* the function being invoked is known based on propagated type information, and the expression
* corresponds to one of the parameters of the function being invoked, then return the parameter
* element representing the parameter to which the value of the given expression will be bound.
- * Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getParameterElement()}.
+ * Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getParameterElement].
* @param expression the expression corresponding to the parameter to be returned
* @return the parameter element representing the parameter to which the value of the expression
* will be bound
@@ -920,9 +920,9 @@
* the function being invoked is known based on static type information, and the expression
* corresponds to one of the parameters of the function being invoked, then return the parameter
* element representing the parameter to which the value of the given expression will be bound.
- * Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getStaticParameterElement()}.
+ * Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getStaticParameterElement].
* @param expression the expression corresponding to the parameter to be returned
* @return the parameter element representing the parameter to which the value of the expression
* will be bound
@@ -939,9 +939,9 @@
}
}
/**
- * Instances of the class {@code AsExpression} represent an 'as' expression.
+ * Instances of the class `AsExpression` represent an 'as' expression.
* <pre>
- * asExpression ::={@link Expression expression} 'as' {@link TypeName type}</pre>
+ * asExpression ::=[Expression expression] 'as' [TypeName type]</pre>
* @coverage dart.engine.ast
*/
class AsExpression extends Expression {
@@ -1031,10 +1031,10 @@
}
}
/**
- * Instances of the class {@code AssertStatement} represent an assert statement.
+ * Instances of the class `AssertStatement` represent an assert statement.
* <pre>
* assertStatement ::=
- * 'assert' '(' {@link Expression conditionalExpression} ')' ';'
+ * 'assert' '(' [Expression conditionalExpression] ')' ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -1051,7 +1051,7 @@
Token _leftParenthesis;
/**
- * The condition that is being asserted to be {@code true}.
+ * The condition that is being asserted to be `true`.
*/
Expression _condition;
@@ -1069,7 +1069,7 @@
* Initialize a newly created assert statement.
* @param keyword the token representing the 'assert' keyword
* @param leftParenthesis the left parenthesis
- * @param condition the condition that is being asserted to be {@code true}
+ * @param condition the condition that is being asserted to be `true`
* @param rightParenthesis the right parenthesis
* @param semicolon the semicolon terminating the statement
*/
@@ -1085,7 +1085,7 @@
* Initialize a newly created assert statement.
* @param keyword the token representing the 'assert' keyword
* @param leftParenthesis the left parenthesis
- * @param condition the condition that is being asserted to be {@code true}
+ * @param condition the condition that is being asserted to be `true`
* @param rightParenthesis the right parenthesis
* @param semicolon the semicolon terminating the statement
*/
@@ -1094,8 +1094,8 @@
Token get beginToken => _keyword;
/**
- * Return the condition that is being asserted to be {@code true}.
- * @return the condition that is being asserted to be {@code true}
+ * Return the condition that is being asserted to be `true`.
+ * @return the condition that is being asserted to be `true`
*/
Expression get condition => _condition;
Token get endToken => _semicolon;
@@ -1125,8 +1125,8 @@
Token get semicolon => _semicolon;
/**
- * Set the condition that is being asserted to be {@code true} to the given expression.
- * @param the condition that is being asserted to be {@code true}
+ * Set the condition that is being asserted to be `true` to the given expression.
+ * @param the condition that is being asserted to be `true`
*/
void set condition(Expression condition2) {
this._condition = becomeParentOf(condition2);
@@ -1168,9 +1168,9 @@
}
}
/**
- * Instances of the class {@code AssignmentExpression} represent an assignment expression.
+ * Instances of the class `AssignmentExpression` represent an assignment expression.
* <pre>
- * assignmentExpression ::={@link Expression leftHandSide} {@link Token operator} {@link Expression rightHandSide}</pre>
+ * assignmentExpression ::=[Expression leftHandSide] [Token operator] [Expression rightHandSide]</pre>
* @coverage dart.engine.ast
*/
class AssignmentExpression extends Expression {
@@ -1191,13 +1191,13 @@
Expression _rightHandSide;
/**
- * The element associated with the operator based on the static type of the left-hand-side, or{@code null} if the AST structure has not been resolved, if the operator is not a compound
+ * The element associated with the operator based on the static type of the left-hand-side, or`null` if the AST structure has not been resolved, if the operator is not a compound
* operator, or if the operator could not be resolved.
*/
MethodElement _staticElement;
/**
- * The element associated with the operator based on the propagated type of the left-hand-side, or{@code null} if the AST structure has not been resolved, if the operator is not a compound
+ * The element associated with the operator based on the propagated type of the left-hand-side, or`null` if the AST structure has not been resolved, if the operator is not a compound
* operator, or if the operator could not be resolved.
*/
MethodElement _propagatedElement;
@@ -1226,7 +1226,7 @@
/**
* Return the element associated with the operator based on the propagated type of the
- * left-hand-side, or {@code null} if the AST structure has not been resolved, if the operator is
+ * left-hand-side, or `null` if the AST structure has not been resolved, if the operator is
* not a compound operator, or if the operator could not be resolved. One example of the latter
* case is an operator that is not defined for the type of the left-hand operand.
* @return the element associated with the operator
@@ -1254,7 +1254,7 @@
/**
* Return the element associated with the operator based on the static type of the left-hand-side,
- * or {@code null} if the AST structure has not been resolved, if the operator is not a compound
+ * or `null` if the AST structure has not been resolved, if the operator is not a compound
* operator, or if the operator could not be resolved. One example of the latter case is an
* operator that is not defined for the type of the left-hand operand.
* @return the element associated with the operator
@@ -1308,9 +1308,9 @@
}
}
/**
- * Instances of the class {@code BinaryExpression} represent a binary (infix) expression.
+ * Instances of the class `BinaryExpression` represent a binary (infix) expression.
* <pre>
- * binaryExpression ::={@link Expression leftOperand} {@link Token operator} {@link Expression rightOperand}</pre>
+ * binaryExpression ::=[Expression leftOperand] [Token operator] [Expression rightOperand]</pre>
* @coverage dart.engine.ast
*/
class BinaryExpression extends Expression {
@@ -1331,13 +1331,13 @@
Expression _rightOperand;
/**
- * The element associated with the operator based on the static type of the left operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * The element associated with the operator based on the static type of the left operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved.
*/
MethodElement _staticElement;
/**
- * The element associated with the operator based on the propagated type of the left operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * The element associated with the operator based on the propagated type of the left operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved.
*/
MethodElement _propagatedElement;
@@ -1366,7 +1366,7 @@
/**
* Return the element associated with the operator based on the propagated type of the left
- * operand, or {@code null} if the AST structure has not been resolved, if the operator is not
+ * operand, or `null` if the AST structure has not been resolved, if the operator is not
* user definable, or if the operator could not be resolved. One example of the latter case is an
* operator that is not defined for the type of the left-hand operand.
* @return the element associated with the operator
@@ -1394,7 +1394,7 @@
/**
* Return the element associated with the operator based on the static type of the left operand,
- * or {@code null} if the AST structure has not been resolved, if the operator is not user
+ * or `null` if the AST structure has not been resolved, if the operator is not user
* definable, or if the operator could not be resolved. One example of the latter case is an
* operator that is not defined for the type of the left operand.
* @return the element associated with the operator
@@ -1450,9 +1450,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on
* propagated type information, then return the parameter element representing the parameter to
- * which the value of the right operand will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getParameterElement()}.
+ * which the value of the right operand will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getParameterElement].
* @return the parameter element representing the parameter to which the value of the right
* operand will be bound
*/
@@ -1470,9 +1470,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on static
* type information, then return the parameter element representing the parameter to which the
- * value of the right operand will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getStaticParameterElement()}.
+ * value of the right operand will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getStaticParameterElement].
* @return the parameter element representing the parameter to which the value of the right
* operand will be bound
*/
@@ -1488,7 +1488,7 @@
}
}
/**
- * Instances of the class {@code Block} represent a sequence of statements.
+ * Instances of the class `Block` represent a sequence of statements.
* <pre>
* block ::=
* '{' statement* '}'
@@ -1574,10 +1574,10 @@
}
}
/**
- * Instances of the class {@code BlockFunctionBody} represent a function body that consists of a
+ * Instances of the class `BlockFunctionBody` represent a function body that consists of a
* block of statements.
* <pre>
- * blockFunctionBody ::={@link Block block}</pre>
+ * blockFunctionBody ::=[Block block]</pre>
* @coverage dart.engine.ast
*/
class BlockFunctionBody extends FunctionBody {
@@ -1622,7 +1622,7 @@
}
}
/**
- * Instances of the class {@code BooleanLiteral} represent a boolean literal expression.
+ * Instances of the class `BooleanLiteral` represent a boolean literal expression.
* <pre>
* booleanLiteral ::=
* 'false' | 'true'
@@ -1672,7 +1672,7 @@
* @return the value of the literal
*/
bool get value => _value;
- bool isSynthetic() => _literal.isSynthetic();
+ bool get isSynthetic => _literal.isSynthetic;
/**
* Set the token representing the literal to the given token.
@@ -1693,10 +1693,10 @@
}
}
/**
- * Instances of the class {@code BreakStatement} represent a break statement.
+ * Instances of the class `BreakStatement` represent a break statement.
* <pre>
* breakStatement ::=
- * 'break' {@link SimpleIdentifier label}? ';'
+ * 'break' [SimpleIdentifier label]? ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -1708,7 +1708,7 @@
Token _keyword;
/**
- * The label associated with the statement, or {@code null} if there is no label.
+ * The label associated with the statement, or `null` if there is no label.
*/
SimpleIdentifier _label;
@@ -1747,7 +1747,7 @@
Token get keyword => _keyword;
/**
- * Return the label associated with the statement, or {@code null} if there is no label.
+ * Return the label associated with the statement, or `null` if there is no label.
* @return the label associated with the statement
*/
SimpleIdentifier get label => _label;
@@ -1786,11 +1786,11 @@
}
}
/**
- * Instances of the class {@code CascadeExpression} represent a sequence of cascaded expressions:
+ * Instances of the class `CascadeExpression` represent a sequence of cascaded expressions:
* expressions that share a common target. There are three kinds of expressions that can be used in
- * a cascade expression: {@link IndexExpression}, {@link MethodInvocation} and{@link PropertyAccess}.
+ * a cascade expression: [IndexExpression], [MethodInvocation] and[PropertyAccess].
* <pre>
- * cascadeExpression ::={@link Expression conditionalExpression} cascadeSection
+ * cascadeExpression ::=[Expression conditionalExpression] cascadeSection
* cascadeSection ::=
* '..' (cascadeSelector arguments*) (assignableSelector arguments*)* (assignmentOperator expressionWithoutCascade)?
* cascadeSelector ::=
@@ -1857,29 +1857,29 @@
}
}
/**
- * Instances of the class {@code CatchClause} represent a catch clause within a try statement.
+ * Instances of the class `CatchClause` represent a catch clause within a try statement.
* <pre>
* onPart ::=
- * catchPart {@link Block block}| 'on' type catchPart? {@link Block block}catchPart ::=
- * 'catch' '(' {@link SimpleIdentifier exceptionParameter} (',' {@link SimpleIdentifier stackTraceParameter})? ')'
+ * catchPart [Block block]| 'on' type catchPart? [Block block]catchPart ::=
+ * 'catch' '(' [SimpleIdentifier exceptionParameter] (',' [SimpleIdentifier stackTraceParameter])? ')'
* </pre>
* @coverage dart.engine.ast
*/
class CatchClause extends ASTNode {
/**
- * The token representing the 'on' keyword, or {@code null} if there is no 'on' keyword.
+ * The token representing the 'on' keyword, or `null` if there is no 'on' keyword.
*/
Token _onKeyword;
/**
- * The type of exceptions caught by this catch clause, or {@code null} if this catch clause
+ * The type of exceptions caught by this catch clause, or `null` if this catch clause
* catches every type of exception.
*/
TypeName _exceptionType;
/**
- * The token representing the 'catch' keyword, or {@code null} if there is no 'catch' keyword.
+ * The token representing the 'catch' keyword, or `null` if there is no 'catch' keyword.
*/
Token _catchKeyword;
@@ -1965,7 +1965,7 @@
Block get body => _body;
/**
- * Return the token representing the 'catch' keyword, or {@code null} if there is no 'catch'
+ * Return the token representing the 'catch' keyword, or `null` if there is no 'catch'
* keyword.
* @return the token representing the 'catch' keyword
*/
@@ -1985,7 +1985,7 @@
SimpleIdentifier get exceptionParameter => _exceptionParameter;
/**
- * Return the type of exceptions caught by this catch clause, or {@code null} if this catch clause
+ * Return the type of exceptions caught by this catch clause, or `null` if this catch clause
* catches every type of exception.
* @return the type of exceptions caught by this catch clause
*/
@@ -1998,7 +1998,7 @@
Token get leftParenthesis => _leftParenthesis;
/**
- * Return the token representing the 'on' keyword, or {@code null} if there is no 'on' keyword.
+ * Return the token representing the 'on' keyword, or `null` if there is no 'on' keyword.
* @return the token representing the 'on' keyword
*/
Token get onKeyword => _onKeyword;
@@ -2096,19 +2096,19 @@
}
}
/**
- * Instances of the class {@code ClassDeclaration} represent the declaration of a class.
+ * Instances of the class `ClassDeclaration` represent the declaration of a class.
* <pre>
* classDeclaration ::=
- * 'abstract'? 'class' {@link SimpleIdentifier name} {@link TypeParameterList typeParameterList}?
- * ({@link ExtendsClause extendsClause} {@link WithClause withClause}?)?{@link ImplementsClause implementsClause}?
- * '{' {@link ClassMember classMember}* '}'
+ * 'abstract'? 'class' [SimpleIdentifier name] [TypeParameterList typeParameterList]?
+ * ([ExtendsClause extendsClause] [WithClause withClause]?)?[ImplementsClause implementsClause]?
+ * '{' [ClassMember classMember]* '}'
* </pre>
* @coverage dart.engine.ast
*/
class ClassDeclaration extends CompilationUnitMember {
/**
- * The 'abstract' keyword, or {@code null} if the keyword was absent.
+ * The 'abstract' keyword, or `null` if the keyword was absent.
*/
Token _abstractKeyword;
@@ -2123,23 +2123,23 @@
SimpleIdentifier _name;
/**
- * The type parameters for the class, or {@code null} if the class does not have any type
+ * The type parameters for the class, or `null` if the class does not have any type
* parameters.
*/
TypeParameterList _typeParameters;
/**
- * The extends clause for the class, or {@code null} if the class does not extend any other class.
+ * The extends clause for the class, or `null` if the class does not extend any other class.
*/
ExtendsClause _extendsClause;
/**
- * The with clause for the class, or {@code null} if the class does not have a with clause.
+ * The with clause for the class, or `null` if the class does not have a with clause.
*/
WithClause _withClause;
/**
- * The implements clause for the class, or {@code null} if the class does not implement any
+ * The implements clause for the class, or `null` if the class does not implement any
* interfaces.
*/
ImplementsClause _implementsClause;
@@ -2163,7 +2163,7 @@
* Initialize a newly created class declaration.
* @param comment the documentation comment associated with this class
* @param metadata the annotations associated with this class
- * @param abstractKeyword the 'abstract' keyword, or {@code null} if the keyword was absent
+ * @param abstractKeyword the 'abstract' keyword, or `null` if the keyword was absent
* @param classKeyword the token representing the 'class' keyword
* @param name the name of the class being declared
* @param typeParameters the type parameters for the class
@@ -2192,7 +2192,7 @@
* Initialize a newly created class declaration.
* @param comment the documentation comment associated with this class
* @param metadata the annotations associated with this class
- * @param abstractKeyword the 'abstract' keyword, or {@code null} if the keyword was absent
+ * @param abstractKeyword the 'abstract' keyword, or `null` if the keyword was absent
* @param classKeyword the token representing the 'class' keyword
* @param name the name of the class being declared
* @param typeParameters the type parameters for the class
@@ -2207,7 +2207,7 @@
accept(ASTVisitor visitor) => visitor.visitClassDeclaration(this);
/**
- * Return the 'abstract' keyword, or {@code null} if the keyword was absent.
+ * Return the 'abstract' keyword, or `null` if the keyword was absent.
* @return the 'abstract' keyword
*/
Token get abstractKeyword => _abstractKeyword;
@@ -2221,14 +2221,14 @@
Token get endToken => _rightBracket;
/**
- * Return the extends clause for this class, or {@code null} if the class does not extend any
+ * Return the extends clause for this class, or `null` if the class does not extend any
* other class.
* @return the extends clause for this class
*/
ExtendsClause get extendsClause => _extendsClause;
/**
- * Return the implements clause for the class, or {@code null} if the class does not implement any
+ * Return the implements clause for the class, or `null` if the class does not implement any
* interfaces.
* @return the implements clause for the class
*/
@@ -2259,14 +2259,14 @@
Token get rightBracket => _rightBracket;
/**
- * Return the type parameters for the class, or {@code null} if the class does not have any type
+ * Return the type parameters for the class, or `null` if the class does not have any type
* parameters.
* @return the type parameters for the class
*/
TypeParameterList get typeParameters => _typeParameters;
/**
- * Return the with clause for the class, or {@code null} if the class does not have a with clause.
+ * Return the with clause for the class, or `null` if the class does not have a with clause.
* @return the with clause for the class
*/
WithClause get withClause => _withClause;
@@ -2359,7 +2359,7 @@
}
}
/**
- * The abstract class {@code ClassMember} defines the behavior common to nodes that declare a name
+ * The abstract class `ClassMember` defines the behavior common to nodes that declare a name
* within the scope of a class.
* @coverage dart.engine.ast
*/
@@ -2381,10 +2381,10 @@
ClassMember({Comment comment, List<Annotation> metadata}) : this.full(comment, metadata);
}
/**
- * Instances of the class {@code ClassTypeAlias} represent a class type alias.
+ * Instances of the class `ClassTypeAlias` represent a class type alias.
* <pre>
- * classTypeAlias ::={@link SimpleIdentifier identifier} {@link TypeParameterList typeParameters}? '=' 'abstract'? mixinApplication
- * mixinApplication ::={@link TypeName superclass} {@link WithClause withClause} {@link ImplementsClause implementsClause}? ';'
+ * classTypeAlias ::=[SimpleIdentifier identifier] [TypeParameterList typeParameters]? '=' 'abstract'? mixinApplication
+ * mixinApplication ::=[TypeName superclass] [WithClause withClause] [ImplementsClause implementsClause]? ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -2396,7 +2396,7 @@
SimpleIdentifier _name;
/**
- * The type parameters for the class, or {@code null} if the class does not have any type
+ * The type parameters for the class, or `null` if the class does not have any type
* parameters.
*/
TypeParameterList _typeParameters;
@@ -2407,7 +2407,7 @@
Token _equals;
/**
- * The token for the 'abstract' keyword, or {@code null} if this is not defining an abstract
+ * The token for the 'abstract' keyword, or `null` if this is not defining an abstract
* class.
*/
Token _abstractKeyword;
@@ -2423,7 +2423,7 @@
WithClause _withClause;
/**
- * The implements clause for this class, or {@code null} if there is no implements clause.
+ * The implements clause for this class, or `null` if there is no implements clause.
*/
ImplementsClause _implementsClause;
@@ -2469,7 +2469,7 @@
accept(ASTVisitor visitor) => visitor.visitClassTypeAlias(this);
/**
- * Return the token for the 'abstract' keyword, or {@code null} if this is not defining an
+ * Return the token for the 'abstract' keyword, or `null` if this is not defining an
* abstract class.
* @return the token for the 'abstract' keyword
*/
@@ -2483,7 +2483,7 @@
Token get equals => _equals;
/**
- * Return the implements clause for this class, or {@code null} if there is no implements clause.
+ * Return the implements clause for this class, or `null` if there is no implements clause.
* @return the implements clause for this class
*/
ImplementsClause get implementsClause => _implementsClause;
@@ -2501,7 +2501,7 @@
TypeName get superclass => _superclass;
/**
- * Return the type parameters for the class, or {@code null} if the class does not have any type
+ * Return the type parameters for the class, or `null` if the class does not have any type
* parameters.
* @return the type parameters for the class
*/
@@ -2578,10 +2578,10 @@
}
}
/**
- * Instances of the class {@code Combinator} represent the combinator associated with an import
+ * Instances of the class `Combinator` represent the combinator associated with an import
* directive.
* <pre>
- * combinator ::={@link HideCombinator hideCombinator}| {@link ShowCombinator showCombinator}</pre>
+ * combinator ::=[HideCombinator hideCombinator]| [ShowCombinator showCombinator]</pre>
* @coverage dart.engine.ast
*/
abstract class Combinator extends ASTNode {
@@ -2625,7 +2625,7 @@
}
}
/**
- * Instances of the class {@code Comment} represent a comment within the source code.
+ * Instances of the class `Comment` represent a comment within the source code.
* <pre>
* comment ::=
* endOfLineComment
@@ -2636,7 +2636,7 @@
* blockComment ::=
* '/ *' CHARACTER* '*/'
* documentationComment ::=
- * '/ **' (CHARACTER | {@link CommentReference commentReference})* '*/'
+ * '/ **' (CHARACTER | [CommentReference commentReference])* '*/'
* | ('///' (CHARACTER - EOL)* EOL)+
* </pre>
* @coverage dart.engine.ast
@@ -2725,28 +2725,28 @@
List<Token> get tokens => _tokens;
/**
- * Return {@code true} if this is a block comment.
- * @return {@code true} if this is a block comment
+ * Return `true` if this is a block comment.
+ * @return `true` if this is a block comment
*/
- bool isBlock() => identical(_type, CommentType.BLOCK);
+ bool get isBlock => identical(_type, CommentType.BLOCK);
/**
- * Return {@code true} if this is a documentation comment.
- * @return {@code true} if this is a documentation comment
+ * Return `true` if this is a documentation comment.
+ * @return `true` if this is a documentation comment
*/
- bool isDocumentation() => identical(_type, CommentType.DOCUMENTATION);
+ bool get isDocumentation => identical(_type, CommentType.DOCUMENTATION);
/**
- * Return {@code true} if this is an end-of-line comment.
- * @return {@code true} if this is an end-of-line comment
+ * Return `true` if this is an end-of-line comment.
+ * @return `true` if this is an end-of-line comment
*/
- bool isEndOfLine() => identical(_type, CommentType.END_OF_LINE);
+ bool get isEndOfLine => identical(_type, CommentType.END_OF_LINE);
void visitChildren(ASTVisitor<Object> visitor) {
_references.accept(visitor);
}
}
/**
- * The enumeration {@code CommentType} encodes all the different types of comments that are
+ * The enumeration `CommentType` encodes all the different types of comments that are
* recognized by the parser.
*/
class CommentType implements Comparable<CommentType> {
@@ -2779,18 +2779,18 @@
String toString() => name;
}
/**
- * Instances of the class {@code CommentReference} represent a reference to a Dart element that is
+ * Instances of the class `CommentReference` represent a reference to a Dart element that is
* found within a documentation comment.
* <pre>
* commentReference ::=
- * '\[' 'new'? {@link Identifier identifier} '\]'
+ * '\[' 'new'? [Identifier identifier] '\]'
* </pre>
* @coverage dart.engine.ast
*/
class CommentReference extends ASTNode {
/**
- * The token representing the 'new' keyword, or {@code null} if there was no 'new' keyword.
+ * The token representing the 'new' keyword, or `null` if there was no 'new' keyword.
*/
Token _newKeyword;
@@ -2826,7 +2826,7 @@
Identifier get identifier => _identifier;
/**
- * Return the token representing the 'new' keyword, or {@code null} if there was no 'new' keyword.
+ * Return the token representing the 'new' keyword, or `null` if there was no 'new' keyword.
* @return the token representing the 'new' keyword
*/
Token get newKeyword => _newKeyword;
@@ -2851,8 +2851,8 @@
}
}
/**
- * Instances of the class {@code CompilationUnit} represent a compilation unit.
- * <p>
+ * Instances of the class `CompilationUnit` represent a compilation unit.
+ *
* While the grammar restricts the order of the directives and declarations within a compilation
* unit, this class does not enforce those restrictions. In particular, the children of a
* compilation unit will be visited in lexical order even if lexical order does not conform to the
@@ -2860,7 +2860,7 @@
* <pre>
* compilationUnit ::=
* directives declarations
- * directives ::={@link ScriptTag scriptTag}? {@link LibraryDirective libraryDirective}? namespaceDirective* {@link PartDirective partDirective}| {@link PartOfDirective partOfDirective}namespaceDirective ::={@link ImportDirective importDirective}| {@link ExportDirective exportDirective}declarations ::={@link CompilationUnitMember compilationUnitMember}</pre>
+ * directives ::=[ScriptTag scriptTag]? [LibraryDirective libraryDirective]? namespaceDirective* [PartDirective partDirective]| [PartOfDirective partOfDirective]namespaceDirective ::=[ImportDirective importDirective]| [ExportDirective exportDirective]declarations ::=[CompilationUnitMember compilationUnitMember]</pre>
* @coverage dart.engine.ast
*/
class CompilationUnit extends ASTNode {
@@ -2871,7 +2871,7 @@
Token _beginToken;
/**
- * The script tag at the beginning of the compilation unit, or {@code null} if there is no script
+ * The script tag at the beginning of the compilation unit, or `null` if there is no script
* tag in this compilation unit.
*/
ScriptTag _scriptTag;
@@ -2888,18 +2888,18 @@
/**
* The last token in the token stream that was parsed to form this compilation unit. This token
- * should always have a type of {@link TokenType.EOF}.
+ * should always have a type of [TokenType.EOF].
*/
Token _endToken;
/**
- * The element associated with this compilation unit, or {@code null} if the AST structure has not
+ * The element associated with this compilation unit, or `null` if the AST structure has not
* been resolved.
*/
CompilationUnitElement _element;
/**
- * The {@link LineInfo} for this {@link CompilationUnit}.
+ * The [LineInfo] for this [CompilationUnit].
*/
LineInfo _lineInfo;
@@ -2956,7 +2956,7 @@
NodeList<Directive> get directives => _directives;
/**
- * Return the element associated with this compilation unit, or {@code null} if the AST structure
+ * Return the element associated with this compilation unit, or `null` if the AST structure
* has not been resolved.
* @return the element associated with this compilation unit
*/
@@ -2965,8 +2965,8 @@
/**
* Return an array containing all of the errors associated with the receiver. If the receiver has
- * not been resolved, then return {@code null}.
- * @return an array of errors (contains no {@code null}s) or {@code null} if the receiver has not
+ * not been resolved, then return `null`.
+ * @return an array of errors (contains no `null`s) or `null` if the receiver has not
* been resolved
*/
List<AnalysisError> get errors {
@@ -2992,28 +2992,28 @@
}
/**
- * Get the {@link LineInfo} object for this compilation unit.
- * @return the associated {@link LineInfo}
+ * Get the [LineInfo] object for this compilation unit.
+ * @return the associated [LineInfo]
*/
LineInfo get lineInfo => _lineInfo;
int get offset => 0;
/**
* Return an array containing all of the parsing errors associated with the receiver.
- * @return an array of errors (not {@code null}, contains no {@code null}s).
+ * @return an array of errors (not `null`, contains no `null`s).
*/
List<AnalysisError> get parsingErrors => _parsingErrors;
/**
* Return an array containing all of the resolution errors associated with the receiver. If the
- * receiver has not been resolved, then return {@code null}.
- * @return an array of errors (contains no {@code null}s) or {@code null} if the receiver has not
+ * receiver has not been resolved, then return `null`.
+ * @return an array of errors (contains no `null`s) or `null` if the receiver has not
* been resolved
*/
List<AnalysisError> get resolutionErrors => _resolutionErrors;
/**
- * Return the script tag at the beginning of the compilation unit, or {@code null} if there is no
+ * Return the script tag at the beginning of the compilation unit, or `null` if there is no
* script tag in this compilation unit.
* @return the script tag at the beginning of the compilation unit
*/
@@ -3028,7 +3028,7 @@
}
/**
- * Set the {@link LineInfo} object for this compilation unit.
+ * Set the [LineInfo] object for this compilation unit.
* @param errors LineInfo to associate with this compilation unit
*/
void set lineInfo(LineInfo lineInfo2) {
@@ -3037,8 +3037,8 @@
/**
* Called to cache the parsing errors when the unit is parsed.
- * @param errors an array of parsing errors, if {@code null} is passed, the error array is set to
- * an empty array, {@link AnalysisError#NO_ERRORS}
+ * @param errors an array of parsing errors, if `null` is passed, the error array is set to
+ * an empty array, [AnalysisError#NO_ERRORS]
*/
void set parsingErrors(List<AnalysisError> errors) {
_parsingErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
@@ -3046,8 +3046,8 @@
/**
* Called to cache the resolution errors when the unit is resolved.
- * @param errors an array of resolution errors, if {@code null} is passed, the error array is set
- * to an empty array, {@link AnalysisError#NO_ERRORS}
+ * @param errors an array of resolution errors, if `null` is passed, the error array is set
+ * to an empty array, [AnalysisError#NO_ERRORS]
*/
void set resolutionErrors(List<AnalysisError> errors) {
_resolutionErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
@@ -3073,8 +3073,8 @@
}
/**
- * Return {@code true} if all of the directives are lexically before any declarations.
- * @return {@code true} if all of the directives are lexically before any declarations
+ * Return `true` if all of the directives are lexically before any declarations.
+ * @return `true` if all of the directives are lexically before any declarations
*/
bool directivesAreBeforeDeclarations() {
if (_directives.isEmpty || _declarations.isEmpty) {
@@ -3101,10 +3101,10 @@
}
}
/**
- * Instances of the class {@code CompilationUnitMember} defines the behavior common to nodes that
+ * Instances of the class `CompilationUnitMember` defines the behavior common to nodes that
* declare a name within the scope of a compilation unit.
* <pre>
- * compilationUnitMember ::={@link ClassDeclaration classDeclaration}| {@link TypeAlias typeAlias}| {@link FunctionDeclaration functionDeclaration}| {@link MethodDeclaration getOrSetDeclaration}| {@link VariableDeclaration constantsDeclaration}| {@link VariableDeclaration variablesDeclaration}</pre>
+ * compilationUnitMember ::=[ClassDeclaration classDeclaration]| [TypeAlias typeAlias]| [FunctionDeclaration functionDeclaration]| [MethodDeclaration getOrSetDeclaration]| [VariableDeclaration constantsDeclaration]| [VariableDeclaration variablesDeclaration]</pre>
* @coverage dart.engine.ast
*/
abstract class CompilationUnitMember extends Declaration {
@@ -3125,9 +3125,9 @@
CompilationUnitMember({Comment comment, List<Annotation> metadata}) : this.full(comment, metadata);
}
/**
- * Instances of the class {@code ConditionalExpression} represent a conditional expression.
+ * Instances of the class `ConditionalExpression` represent a conditional expression.
* <pre>
- * conditionalExpression ::={@link Expression condition} '?' {@link Expression thenExpression} ':' {@link Expression elseExpression}</pre>
+ * conditionalExpression ::=[Expression condition] '?' [Expression thenExpression] ':' [Expression elseExpression]</pre>
* @coverage dart.engine.ast
*/
class ConditionalExpression extends Expression {
@@ -3143,7 +3143,7 @@
Token _question;
/**
- * The expression that is executed if the condition evaluates to {@code true}.
+ * The expression that is executed if the condition evaluates to `true`.
*/
Expression _thenExpression;
@@ -3153,7 +3153,7 @@
Token _colon;
/**
- * The expression that is executed if the condition evaluates to {@code false}.
+ * The expression that is executed if the condition evaluates to `false`.
*/
Expression _elseExpression;
@@ -3161,9 +3161,9 @@
* Initialize a newly created conditional expression.
* @param condition the condition used to determine which expression is executed next
* @param question the token used to separate the condition from the then expression
- * @param thenExpression the expression that is executed if the condition evaluates to{@code true}
+ * @param thenExpression the expression that is executed if the condition evaluates to`true`
* @param colon the token used to separate the then expression from the else expression
- * @param elseExpression the expression that is executed if the condition evaluates to{@code false}
+ * @param elseExpression the expression that is executed if the condition evaluates to`false`
*/
ConditionalExpression.full(Expression condition, Token question, Expression thenExpression, Token colon, Expression elseExpression) {
this._condition = becomeParentOf(condition);
@@ -3177,9 +3177,9 @@
* Initialize a newly created conditional expression.
* @param condition the condition used to determine which expression is executed next
* @param question the token used to separate the condition from the then expression
- * @param thenExpression the expression that is executed if the condition evaluates to{@code true}
+ * @param thenExpression the expression that is executed if the condition evaluates to`true`
* @param colon the token used to separate the then expression from the else expression
- * @param elseExpression the expression that is executed if the condition evaluates to{@code false}
+ * @param elseExpression the expression that is executed if the condition evaluates to`false`
*/
ConditionalExpression({Expression condition, Token question, Expression thenExpression, Token colon, Expression elseExpression}) : this.full(condition, question, thenExpression, colon, elseExpression);
accept(ASTVisitor visitor) => visitor.visitConditionalExpression(this);
@@ -3198,8 +3198,8 @@
Expression get condition => _condition;
/**
- * Return the expression that is executed if the condition evaluates to {@code false}.
- * @return the expression that is executed if the condition evaluates to {@code false}
+ * Return the expression that is executed if the condition evaluates to `false`.
+ * @return the expression that is executed if the condition evaluates to `false`
*/
Expression get elseExpression => _elseExpression;
Token get endToken => _elseExpression.endToken;
@@ -3211,8 +3211,8 @@
Token get question => _question;
/**
- * Return the expression that is executed if the condition evaluates to {@code true}.
- * @return the expression that is executed if the condition evaluates to {@code true}
+ * Return the expression that is executed if the condition evaluates to `true`.
+ * @return the expression that is executed if the condition evaluates to `true`
*/
Expression get thenExpression => _thenExpression;
@@ -3234,9 +3234,9 @@
}
/**
- * Set the expression that is executed if the condition evaluates to {@code false} to the given
+ * Set the expression that is executed if the condition evaluates to `false` to the given
* expression.
- * @param expression the expression that is executed if the condition evaluates to {@code false}
+ * @param expression the expression that is executed if the condition evaluates to `false`
*/
void set elseExpression(Expression expression) {
_elseExpression = becomeParentOf(expression);
@@ -3251,9 +3251,9 @@
}
/**
- * Set the expression that is executed if the condition evaluates to {@code true} to the given
+ * Set the expression that is executed if the condition evaluates to `true` to the given
* expression.
- * @param expression the expression that is executed if the condition evaluates to {@code true}
+ * @param expression the expression that is executed if the condition evaluates to `true`
*/
void set thenExpression(Expression expression) {
_thenExpression = becomeParentOf(expression);
@@ -3265,37 +3265,37 @@
}
}
/**
- * Instances of the class {@code ConstructorDeclaration} represent a constructor declaration.
+ * Instances of the class `ConstructorDeclaration` represent a constructor declaration.
* <pre>
* constructorDeclaration ::=
- * constructorSignature {@link FunctionBody body}?
- * | constructorName formalParameterList ':' 'this' ('.' {@link SimpleIdentifier name})? arguments
+ * constructorSignature [FunctionBody body]?
+ * | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier name])? arguments
* constructorSignature ::=
* 'external'? constructorName formalParameterList initializerList?
* | 'external'? 'factory' factoryName formalParameterList initializerList?
* | 'external'? 'const' constructorName formalParameterList initializerList?
- * constructorName ::={@link SimpleIdentifier returnType} ('.' {@link SimpleIdentifier name})?
- * factoryName ::={@link Identifier returnType} ('.' {@link SimpleIdentifier name})?
+ * constructorName ::=[SimpleIdentifier returnType] ('.' [SimpleIdentifier name])?
+ * factoryName ::=[Identifier returnType] ('.' [SimpleIdentifier name])?
* initializerList ::=
- * ':' {@link ConstructorInitializer initializer} (',' {@link ConstructorInitializer initializer})
+ * ':' [ConstructorInitializer initializer] (',' [ConstructorInitializer initializer])
* </pre>
* @coverage dart.engine.ast
*/
class ConstructorDeclaration extends ClassMember {
/**
- * The token for the 'external' keyword, or {@code null} if the constructor is not external.
+ * The token for the 'external' keyword, or `null` if the constructor is not external.
*/
Token _externalKeyword;
/**
- * The token for the 'const' keyword, or {@code null} if the constructor is not a const
+ * The token for the 'const' keyword, or `null` if the constructor is not a const
* constructor.
*/
Token _constKeyword;
/**
- * The token for the 'factory' keyword, or {@code null} if the constructor is not a factory
+ * The token for the 'factory' keyword, or `null` if the constructor is not a factory
* constructor.
*/
Token _factoryKeyword;
@@ -3307,18 +3307,18 @@
Identifier _returnType;
/**
- * The token for the period before the constructor name, or {@code null} if the constructor being
+ * The token for the period before the constructor name, or `null` if the constructor being
* declared is unnamed.
*/
Token _period;
/**
- * The name of the constructor, or {@code null} if the constructor being declared is unnamed.
+ * The name of the constructor, or `null` if the constructor being declared is unnamed.
*/
SimpleIdentifier _name;
/**
- * The element associated with this constructor, or {@code null} if the AST structure has not been
+ * The element associated with this constructor, or `null` if the AST structure has not been
* resolved or if this constructor could not be resolved.
*/
ConstructorElement _element;
@@ -3329,7 +3329,7 @@
FormalParameterList _parameters;
/**
- * The token for the separator (colon or equals) before the initializers, or {@code null} if there
+ * The token for the separator (colon or equals) before the initializers, or `null` if there
* are no initializers.
*/
Token _separator;
@@ -3340,13 +3340,13 @@
NodeList<ConstructorInitializer> _initializers;
/**
- * The name of the constructor to which this constructor will be redirected, or {@code null} if
+ * The name of the constructor to which this constructor will be redirected, or `null` if
* this is not a redirecting factory constructor.
*/
ConstructorName _redirectedConstructor;
/**
- * The body of the constructor, or {@code null} if the constructor does not have a body.
+ * The body of the constructor, or `null` if the constructor does not have a body.
*/
FunctionBody _body;
@@ -3403,7 +3403,7 @@
accept(ASTVisitor visitor) => visitor.visitConstructorDeclaration(this);
/**
- * Return the body of the constructor, or {@code null} if the constructor does not have a body.
+ * Return the body of the constructor, or `null` if the constructor does not have a body.
* @return the body of the constructor
*/
FunctionBody get body => _body;
@@ -3424,7 +3424,7 @@
}
/**
- * Return the token for the 'external' keyword, or {@code null} if the constructor is not
+ * Return the token for the 'external' keyword, or `null` if the constructor is not
* external.
* @return the token for the 'external' keyword
*/
@@ -3443,7 +3443,7 @@
NodeList<ConstructorInitializer> get initializers => _initializers;
/**
- * Return the name of the constructor, or {@code null} if the constructor being declared is
+ * Return the name of the constructor, or `null` if the constructor being declared is
* unnamed.
* @return the name of the constructor
*/
@@ -3456,14 +3456,14 @@
FormalParameterList get parameters => _parameters;
/**
- * Return the token for the period before the constructor name, or {@code null} if the constructor
+ * Return the token for the period before the constructor name, or `null` if the constructor
* being declared is unnamed.
* @return the token for the period before the constructor name
*/
Token get period => _period;
/**
- * Return the name of the constructor to which this constructor will be redirected, or{@code null} if this is not a redirecting factory constructor.
+ * Return the name of the constructor to which this constructor will be redirected, or`null` if this is not a redirecting factory constructor.
* @return the name of the constructor to which this constructor will be redirected
*/
ConstructorName get redirectedConstructor => _redirectedConstructor;
@@ -3477,7 +3477,7 @@
Identifier get returnType => _returnType;
/**
- * Return the token for the separator (colon or equals) before the initializers, or {@code null}if there are no initializers.
+ * Return the token for the separator (colon or equals) before the initializers, or `null`if there are no initializers.
* @return the token for the separator (colon or equals) before the initializers
*/
Token get separator => _separator;
@@ -3589,8 +3589,8 @@
}
/**
- * Return the left-most of the given tokens, or {@code null} if there are no tokens given or if
- * all of the given tokens are {@code null}.
+ * Return the left-most of the given tokens, or `null` if there are no tokens given or if
+ * all of the given tokens are `null`.
* @param tokens the tokens being compared to find the left-most token
* @return the left-most of the given tokens
*/
@@ -3606,22 +3606,22 @@
}
}
/**
- * Instances of the class {@code ConstructorFieldInitializer} represent the initialization of a
+ * Instances of the class `ConstructorFieldInitializer` represent the initialization of a
* field within a constructor's initialization list.
* <pre>
* fieldInitializer ::=
- * ('this' '.')? {@link SimpleIdentifier fieldName} '=' {@link Expression conditionalExpression cascadeSection*}</pre>
+ * ('this' '.')? [SimpleIdentifier fieldName] '=' [Expression conditionalExpression cascadeSection*]</pre>
* @coverage dart.engine.ast
*/
class ConstructorFieldInitializer extends ConstructorInitializer {
/**
- * The token for the 'this' keyword, or {@code null} if there is no 'this' keyword.
+ * The token for the 'this' keyword, or `null` if there is no 'this' keyword.
*/
Token _keyword;
/**
- * The token for the period after the 'this' keyword, or {@code null} if there is no 'this'
+ * The token for the period after the 'this' keyword, or `null` if there is no 'this'
* keyword.
*/
Token _period;
@@ -3696,13 +3696,13 @@
SimpleIdentifier get fieldName => _fieldName;
/**
- * Return the token for the 'this' keyword, or {@code null} if there is no 'this' keyword.
+ * Return the token for the 'this' keyword, or `null` if there is no 'this' keyword.
* @return the token for the 'this' keyword
*/
Token get keyword => _keyword;
/**
- * Return the token for the period after the 'this' keyword, or {@code null} if there is no 'this'
+ * Return the token for the period after the 'this' keyword, or `null` if there is no 'this'
* keyword.
* @return the token for the period after the 'this' keyword
*/
@@ -3754,16 +3754,16 @@
}
}
/**
- * Instances of the class {@code ConstructorInitializer} defines the behavior of nodes that can
+ * Instances of the class `ConstructorInitializer` defines the behavior of nodes that can
* occur in the initializer list of a constructor declaration.
* <pre>
- * constructorInitializer ::={@link SuperConstructorInvocation superInvocation}| {@link ConstructorFieldInitializer fieldInitializer}</pre>
+ * constructorInitializer ::=[SuperConstructorInvocation superInvocation]| [ConstructorFieldInitializer fieldInitializer]</pre>
* @coverage dart.engine.ast
*/
abstract class ConstructorInitializer extends ASTNode {
}
/**
- * Instances of the class {@code ConstructorName} represent the name of the constructor.
+ * Instances of the class `ConstructorName` represent the name of the constructor.
* <pre>
* constructorName:
* type ('.' identifier)?
@@ -3778,25 +3778,25 @@
TypeName _type;
/**
- * The token for the period before the constructor name, or {@code null} if the specified
+ * The token for the period before the constructor name, or `null` if the specified
* constructor is the unnamed constructor.
*/
Token _period;
/**
- * The name of the constructor, or {@code null} if the specified constructor is the unnamed
+ * The name of the constructor, or `null` if the specified constructor is the unnamed
* constructor.
*/
SimpleIdentifier _name;
/**
- * The element associated with this constructor name based on static type information, or{@code null} if the AST structure has not been resolved or if this constructor name could not
+ * The element associated with this constructor name based on static type information, or`null` if the AST structure has not been resolved or if this constructor name could not
* be resolved.
*/
ConstructorElement _staticElement;
/**
- * The element associated with this constructor name based on propagated type information, or{@code null} if the AST structure has not been resolved or if this constructor name could not
+ * The element associated with this constructor name based on propagated type information, or`null` if the AST structure has not been resolved or if this constructor name could not
* be resolved.
*/
ConstructorElement _propagatedElement;
@@ -3825,7 +3825,7 @@
/**
* Return the element associated with this constructor name based on propagated type information,
- * or {@code null} if the AST structure has not been resolved or if this constructor name could
+ * or `null` if the AST structure has not been resolved or if this constructor name could
* not be resolved.
* @return the element associated with this constructor name
*/
@@ -3838,21 +3838,21 @@
}
/**
- * Return the name of the constructor, or {@code null} if the specified constructor is the unnamed
+ * Return the name of the constructor, or `null` if the specified constructor is the unnamed
* constructor.
* @return the name of the constructor
*/
SimpleIdentifier get name => _name;
/**
- * Return the token for the period before the constructor name, or {@code null} if the specified
+ * Return the token for the period before the constructor name, or `null` if the specified
* constructor is the unnamed constructor.
* @return the token for the period before the constructor name
*/
Token get period => _period;
/**
- * Return the element associated with this constructor name based on static type information, or{@code null} if the AST structure has not been resolved or if this constructor name could not
+ * Return the element associated with this constructor name based on static type information, or`null` if the AST structure has not been resolved or if this constructor name could not
* be resolved.
* @return the element associated with this constructor name
*/
@@ -3911,10 +3911,10 @@
}
}
/**
- * Instances of the class {@code ContinueStatement} represent a continue statement.
+ * Instances of the class `ContinueStatement` represent a continue statement.
* <pre>
* continueStatement ::=
- * 'continue' {@link SimpleIdentifier label}? ';'
+ * 'continue' [SimpleIdentifier label]? ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -3926,7 +3926,7 @@
Token _keyword;
/**
- * The label associated with the statement, or {@code null} if there is no label.
+ * The label associated with the statement, or `null` if there is no label.
*/
SimpleIdentifier _label;
@@ -3965,7 +3965,7 @@
Token get keyword => _keyword;
/**
- * Return the label associated with the statement, or {@code null} if there is no label.
+ * Return the label associated with the statement, or `null` if there is no label.
* @return the label associated with the statement
*/
SimpleIdentifier get label => _label;
@@ -4004,7 +4004,7 @@
}
}
/**
- * The abstract class {@code Declaration} defines the behavior common to nodes that represent the
+ * The abstract class `Declaration` defines the behavior common to nodes that represent the
* declaration of a name. Each declared name is visible within a name scope.
* @coverage dart.engine.ast
*/
@@ -4026,30 +4026,30 @@
Declaration({Comment comment, List<Annotation> metadata}) : this.full(comment, metadata);
/**
- * Return the element associated with this declaration, or {@code null} if either this node
+ * Return the element associated with this declaration, or `null` if either this node
* corresponds to a list of declarations or if the AST structure has not been resolved.
* @return the element associated with this declaration
*/
Element get element;
}
/**
- * Instances of the class {@code DeclaredIdentifier} represent the declaration of a single
+ * Instances of the class `DeclaredIdentifier` represent the declaration of a single
* identifier.
* <pre>
* declaredIdentifier ::=
- * ({@link Annotation metadata} finalConstVarOrType {@link SimpleIdentifier identifier}</pre>
+ * ([Annotation metadata] finalConstVarOrType [SimpleIdentifier identifier]</pre>
* @coverage dart.engine.ast
*/
class DeclaredIdentifier extends Declaration {
/**
- * The token representing either the 'final', 'const' or 'var' keyword, or {@code null} if no
+ * The token representing either the 'final', 'const' or 'var' keyword, or `null` if no
* keyword was used.
*/
Token _keyword;
/**
- * The name of the declared type of the parameter, or {@code null} if the parameter does not have
+ * The name of the declared type of the parameter, or `null` if the parameter does not have
* a declared type.
*/
TypeName _type;
@@ -4105,25 +4105,25 @@
Token get keyword => _keyword;
/**
- * Return the name of the declared type of the parameter, or {@code null} if the parameter does
+ * Return the name of the declared type of the parameter, or `null` if the parameter does
* not have a declared type.
* @return the name of the declared type of the parameter
*/
TypeName get type => _type;
/**
- * Return {@code true} if this variable was declared with the 'const' modifier.
- * @return {@code true} if this variable was declared with the 'const' modifier
+ * Return `true` if this variable was declared with the 'const' modifier.
+ * @return `true` if this variable was declared with the 'const' modifier
*/
- bool isConst() => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
+ bool get isConst => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
/**
- * Return {@code true} if this variable was declared with the 'final' modifier. Variables that are
- * declared with the 'const' modifier will return {@code false} even though they are implicitly
+ * Return `true` if this variable was declared with the 'final' modifier. Variables that are
+ * declared with the 'const' modifier will return `false` even though they are implicitly
* final.
- * @return {@code true} if this variable was declared with the 'final' modifier
+ * @return `true` if this variable was declared with the 'final' modifier
*/
- bool isFinal() => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
+ bool get isFinal => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
/**
* Set the token representing either the 'final', 'const' or 'var' keyword to the given token.
@@ -4155,12 +4155,12 @@
}
}
/**
- * Instances of the class {@code DefaultFormalParameter} represent a formal parameter with a default
+ * Instances of the class `DefaultFormalParameter` represent a formal parameter with a default
* value. There are two kinds of parameters that are both represented by this class: named formal
* parameters and positional formal parameters.
* <pre>
- * defaultFormalParameter ::={@link NormalFormalParameter normalFormalParameter} ('=' {@link Expression defaultValue})?
- * defaultNamedParameter ::={@link NormalFormalParameter normalFormalParameter} (':' {@link Expression defaultValue})?
+ * defaultFormalParameter ::=[NormalFormalParameter normalFormalParameter] ('=' [Expression defaultValue])?
+ * defaultNamedParameter ::=[NormalFormalParameter normalFormalParameter] (':' [Expression defaultValue])?
* </pre>
* @coverage dart.engine.ast
*/
@@ -4177,13 +4177,13 @@
ParameterKind _kind;
/**
- * The token separating the parameter from the default value, or {@code null} if there is no
+ * The token separating the parameter from the default value, or `null` if there is no
* default value.
*/
Token _separator;
/**
- * The expression computing the default value for the parameter, or {@code null} if there is no
+ * The expression computing the default value for the parameter, or `null` if there is no
* default value.
*/
Expression _defaultValue;
@@ -4214,7 +4214,7 @@
Token get beginToken => _parameter.beginToken;
/**
- * Return the expression computing the default value for the parameter, or {@code null} if there
+ * Return the expression computing the default value for the parameter, or `null` if there
* is no default value.
* @return the expression computing the default value for the parameter
*/
@@ -4235,25 +4235,25 @@
NormalFormalParameter get parameter => _parameter;
/**
- * Return the token separating the parameter from the default value, or {@code null} if there is
+ * Return the token separating the parameter from the default value, or `null` if there is
* no default value.
* @return the token separating the parameter from the default value
*/
Token get separator => _separator;
/**
- * Return {@code true} if this parameter was declared with the 'const' modifier.
- * @return {@code true} if this parameter was declared with the 'const' modifier
+ * Return `true` if this parameter was declared with the 'const' modifier.
+ * @return `true` if this parameter was declared with the 'const' modifier
*/
- bool isConst() => _parameter != null && _parameter.isConst();
+ bool get isConst => _parameter != null && _parameter.isConst;
/**
- * Return {@code true} if this parameter was declared with the 'final' modifier. Parameters that
- * are declared with the 'const' modifier will return {@code false} even though they are
+ * Return `true` if this parameter was declared with the 'final' modifier. Parameters that
+ * are declared with the 'const' modifier will return `false` even though they are
* implicitly final.
- * @return {@code true} if this parameter was declared with the 'final' modifier
+ * @return `true` if this parameter was declared with the 'final' modifier
*/
- bool isFinal() => _parameter != null && _parameter.isFinal();
+ bool get isFinal => _parameter != null && _parameter.isFinal;
/**
* Set the expression computing the default value for the parameter to the given expression.
@@ -4292,16 +4292,16 @@
}
}
/**
- * The abstract class {@code Directive} defines the behavior common to nodes that represent a
+ * The abstract class `Directive` defines the behavior common to nodes that represent a
* directive.
* <pre>
- * directive ::={@link ExportDirective exportDirective}| {@link ImportDirective importDirective}| {@link LibraryDirective libraryDirective}| {@link PartDirective partDirective}| {@link PartOfDirective partOfDirective}</pre>
+ * directive ::=[ExportDirective exportDirective]| [ImportDirective importDirective]| [LibraryDirective libraryDirective]| [PartDirective partDirective]| [PartOfDirective partOfDirective]</pre>
* @coverage dart.engine.ast
*/
abstract class Directive extends AnnotatedNode {
/**
- * The element associated with this directive, or {@code null} if the AST structure has not been
+ * The element associated with this directive, or `null` if the AST structure has not been
* resolved or if this directive could not be resolved.
*/
Element _element;
@@ -4322,7 +4322,7 @@
Directive({Comment comment, List<Annotation> metadata}) : this.full(comment, metadata);
/**
- * Return the element associated with this directive, or {@code null} if the AST structure has not
+ * Return the element associated with this directive, or `null` if the AST structure has not
* been resolved or if this directive could not be resolved. Examples of the latter case include a
* directive that contains an invalid URL or a URL that does not exist.
* @return the element associated with this directive
@@ -4345,10 +4345,10 @@
}
}
/**
- * Instances of the class {@code DoStatement} represent a do statement.
+ * Instances of the class `DoStatement` represent a do statement.
* <pre>
* doStatement ::=
- * 'do' {@link Statement body} 'while' '(' {@link Expression condition} ')' ';'
+ * 'do' [Statement body] 'while' '(' [Expression condition] ')' ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -4527,7 +4527,7 @@
}
}
/**
- * Instances of the class {@code DoubleLiteral} represent a floating point literal expression.
+ * Instances of the class `DoubleLiteral` represent a floating point literal expression.
* <pre>
* doubleLiteral ::=
* decimalDigit+ ('.' decimalDigit*)? exponent?
@@ -4600,7 +4600,7 @@
}
}
/**
- * Instances of the class {@code EmptyFunctionBody} represent an empty function body, which can only
+ * Instances of the class `EmptyFunctionBody` represent an empty function body, which can only
* appear in constructors or abstract methods.
* <pre>
* emptyFunctionBody ::=
@@ -4650,7 +4650,7 @@
}
}
/**
- * Instances of the class {@code EmptyStatement} represent an empty statement.
+ * Instances of the class `EmptyStatement` represent an empty statement.
* <pre>
* emptyStatement ::=
* ';'
@@ -4708,9 +4708,9 @@
EphemeralIdentifier({ASTNode parent, int location}) : this.full(parent, location);
}
/**
- * Instances of the class {@code ExportDirective} represent an export directive.
+ * Instances of the class `ExportDirective` represent an export directive.
* <pre>
- * exportDirective ::={@link Annotation metadata} 'export' {@link StringLiteral libraryUri} {@link Combinator combinator}* ';'
+ * exportDirective ::=[Annotation metadata] 'export' [StringLiteral libraryUri] [Combinator combinator]* ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -4752,22 +4752,22 @@
}
}
/**
- * Instances of the class {@code Expression} defines the behavior common to nodes that represent an
+ * Instances of the class `Expression` defines the behavior common to nodes that represent an
* expression.
* <pre>
- * expression ::={@link AssignmentExpression assignmentExpression}| {@link ConditionalExpression conditionalExpression} cascadeSection
- * | {@link ThrowExpression throwExpression}</pre>
+ * expression ::=[AssignmentExpression assignmentExpression]| [ConditionalExpression conditionalExpression] cascadeSection
+ * | [ThrowExpression throwExpression]</pre>
* @coverage dart.engine.ast
*/
abstract class Expression extends ASTNode {
/**
- * The static type of this expression, or {@code null} if the AST structure has not been resolved.
+ * The static type of this expression, or `null` if the AST structure has not been resolved.
*/
Type2 _staticType;
/**
- * The propagated type of this expression, or {@code null} if type propagation has not been
+ * The propagated type of this expression, or `null` if type propagation has not been
* performed on the AST structure.
*/
Type2 _propagatedType;
@@ -4777,7 +4777,7 @@
* and the function being invoked is known based on propagated type information, and this
* expression corresponds to one of the parameters of the function being invoked, then return the
* parameter element representing the parameter to which the value of this expression will be
- * bound. Otherwise, return {@code null}.
+ * bound. Otherwise, return `null`.
* @return the parameter element representing the parameter to which the value of this expression
* will be bound
*/
@@ -4804,7 +4804,7 @@
}
/**
- * Return the propagated type of this expression, or {@code null} if type propagation has not been
+ * Return the propagated type of this expression, or `null` if type propagation has not been
* performed on the AST structure.
* @return the propagated type of this expression
*/
@@ -4815,7 +4815,7 @@
* and the function being invoked is known based on static type information, and this expression
* corresponds to one of the parameters of the function being invoked, then return the parameter
* element representing the parameter to which the value of this expression will be bound.
- * Otherwise, return {@code null}.
+ * Otherwise, return `null`.
* @return the parameter element representing the parameter to which the value of this expression
* will be bound
*/
@@ -4842,17 +4842,17 @@
}
/**
- * Return the static type of this expression, or {@code null} if the AST structure has not been
+ * Return the static type of this expression, or `null` if the AST structure has not been
* resolved.
* @return the static type of this expression
*/
Type2 get staticType => _staticType;
/**
- * Return {@code true} if this expression is syntactically valid for the LHS of an{@link AssignmentExpression assignment expression}.
- * @return {@code true} if this expression matches the {@code assignableExpression} production
+ * Return `true` if this expression is syntactically valid for the LHS of an[AssignmentExpression assignment expression].
+ * @return `true` if this expression matches the `assignableExpression` production
*/
- bool isAssignable() => false;
+ bool get isAssignable => false;
/**
* Set the propagated type of this expression to the given type.
@@ -4871,11 +4871,11 @@
}
}
/**
- * Instances of the class {@code ExpressionFunctionBody} represent a function body consisting of a
+ * Instances of the class `ExpressionFunctionBody` represent a function body consisting of a
* single expression.
* <pre>
* expressionFunctionBody ::=
- * '=>' {@link Expression expression} ';'
+ * '=>' [Expression expression] ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -4973,9 +4973,9 @@
}
}
/**
- * Instances of the class {@code ExpressionStatement} wrap an expression as a statement.
+ * Instances of the class `ExpressionStatement` wrap an expression as a statement.
* <pre>
- * expressionStatement ::={@link Expression expression}? ';'
+ * expressionStatement ::=[Expression expression]? ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -4987,7 +4987,7 @@
Expression _expression;
/**
- * The semicolon terminating the statement, or {@code null} if the expression is a function
+ * The semicolon terminating the statement, or `null` if the expression is a function
* expression and isn't followed by a semicolon.
*/
Token _semicolon;
@@ -5028,7 +5028,7 @@
* @return the semicolon terminating the statement
*/
Token get semicolon => _semicolon;
- bool isSynthetic() => _expression.isSynthetic() && _semicolon.isSynthetic();
+ bool get isSynthetic => _expression.isSynthetic && _semicolon.isSynthetic;
/**
* Set the expression that comprises the statement to the given expression.
@@ -5050,11 +5050,11 @@
}
}
/**
- * Instances of the class {@code ExtendsClause} represent the "extends" clause in a class
+ * Instances of the class `ExtendsClause` represent the "extends" clause in a class
* declaration.
* <pre>
* extendsClause ::=
- * 'extends' {@link TypeName superclass}</pre>
+ * 'extends' [TypeName superclass]</pre>
* @coverage dart.engine.ast
*/
class ExtendsClause extends ASTNode {
@@ -5121,18 +5121,18 @@
}
}
/**
- * Instances of the class {@code FieldDeclaration} represent the declaration of one or more fields
+ * Instances of the class `FieldDeclaration` represent the declaration of one or more fields
* of the same type.
* <pre>
* fieldDeclaration ::=
- * 'static'? {@link VariableDeclarationList fieldList} ';'
+ * 'static'? [VariableDeclarationList fieldList] ';'
* </pre>
* @coverage dart.engine.ast
*/
class FieldDeclaration extends ClassMember {
/**
- * The token representing the 'static' keyword, or {@code null} if the fields are not static.
+ * The token representing the 'static' keyword, or `null` if the fields are not static.
*/
Token _keyword;
@@ -5180,7 +5180,7 @@
VariableDeclarationList get fields => _fieldList;
/**
- * Return the token representing the 'static' keyword, or {@code null} if the fields are not
+ * Return the token representing the 'static' keyword, or `null` if the fields are not
* static.
* @return the token representing the 'static' keyword
*/
@@ -5193,10 +5193,10 @@
Token get semicolon => _semicolon;
/**
- * Return {@code true} if the fields are static.
- * @return {@code true} if the fields are declared to be static
+ * Return `true` if the fields are static.
+ * @return `true` if the fields are declared to be static
*/
- bool isStatic() => _keyword != null;
+ bool get isStatic => _keyword != null;
/**
* Set the fields being declared to the given list of variables.
@@ -5233,22 +5233,22 @@
}
}
/**
- * Instances of the class {@code FieldFormalParameter} represent a field formal parameter.
+ * Instances of the class `FieldFormalParameter` represent a field formal parameter.
* <pre>
* fieldFormalParameter ::=
- * ('final' {@link TypeName type} | 'const' {@link TypeName type} | 'var' | {@link TypeName type})? 'this' '.' {@link SimpleIdentifier identifier}</pre>
+ * ('final' [TypeName type] | 'const' [TypeName type] | 'var' | [TypeName type])? 'this' '.' [SimpleIdentifier identifier]</pre>
* @coverage dart.engine.ast
*/
class FieldFormalParameter extends NormalFormalParameter {
/**
- * The token representing either the 'final', 'const' or 'var' keyword, or {@code null} if no
+ * The token representing either the 'final', 'const' or 'var' keyword, or `null` if no
* keyword was used.
*/
Token _keyword;
/**
- * The name of the declared type of the parameter, or {@code null} if the parameter does not have
+ * The name of the declared type of the parameter, or `null` if the parameter does not have
* a declared type.
*/
TypeName _type;
@@ -5321,13 +5321,13 @@
Token get thisToken => _thisToken;
/**
- * Return the name of the declared type of the parameter, or {@code null} if the parameter does
+ * Return the name of the declared type of the parameter, or `null` if the parameter does
* not have a declared type.
* @return the name of the declared type of the parameter
*/
TypeName get type => _type;
- bool isConst() => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
- bool isFinal() => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
+ bool get isConst => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
+ bool get isFinal => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
/**
* Set the token representing either the 'final', 'const' or 'var' keyword to the given token.
@@ -5367,10 +5367,10 @@
}
}
/**
- * Instances of the class {@code ForEachStatement} represent a for-each statement.
+ * Instances of the class `ForEachStatement` represent a for-each statement.
* <pre>
* forEachStatement ::=
- * 'for' '(' {@link SimpleFormalParameter loopParameter} 'in' {@link Expression iterator} ')' {@link Block body}</pre>
+ * 'for' '(' [SimpleFormalParameter loopParameter] 'in' [Expression iterator] ')' [Block body]</pre>
* @coverage dart.engine.ast
*/
class ForEachStatement extends Statement {
@@ -5547,12 +5547,12 @@
}
}
/**
- * Instances of the class {@code ForStatement} represent a for statement.
+ * Instances of the class `ForStatement` represent a for statement.
* <pre>
* forStatement ::=
- * 'for' '(' forLoopParts ')' {@link Statement statement}forLoopParts ::=
- * forInitializerStatement ';' {@link Expression expression}? ';' {@link Expression expressionList}?
- * forInitializerStatement ::={@link DefaultFormalParameter initializedVariableDeclaration}| {@link Expression expression}?
+ * 'for' '(' forLoopParts ')' [Statement statement]forLoopParts ::=
+ * forInitializerStatement ';' [Expression expression]? ';' [Expression expressionList]?
+ * forInitializerStatement ::=[DefaultFormalParameter initializedVariableDeclaration]| [Expression expression]?
* </pre>
* @coverage dart.engine.ast
*/
@@ -5569,14 +5569,14 @@
Token _leftParenthesis;
/**
- * The declaration of the loop variables, or {@code null} if there are no variables. Note that a
+ * The declaration of the loop variables, or `null` if there are no variables. Note that a
* for statement cannot have both a variable list and an initialization expression, but can
* validly have neither.
*/
VariableDeclarationList _variableList;
/**
- * The initialization expression, or {@code null} if there is no initialization expression. Note
+ * The initialization expression, or `null` if there is no initialization expression. Note
* that a for statement cannot have both a variable list and an initialization expression, but can
* validly have neither.
*/
@@ -5676,7 +5676,7 @@
Token get forKeyword => _forKeyword;
/**
- * Return the initialization expression, or {@code null} if there is no initialization expression.
+ * Return the initialization expression, or `null` if there is no initialization expression.
* @return the initialization expression
*/
Expression get initialization => _initialization;
@@ -5712,8 +5712,8 @@
NodeList<Expression> get updaters => _updaters;
/**
- * Return the declaration of the loop variables, or {@code null} if there are no variables.
- * @return the declaration of the loop variables, or {@code null} if there are no variables
+ * Return the declaration of the loop variables, or `null` if there are no variables.
+ * @return the declaration of the loop variables, or `null` if there are no variables
*/
VariableDeclarationList get variables => _variableList;
@@ -5797,16 +5797,16 @@
}
}
/**
- * The abstract class {@code FormalParameter} defines the behavior of objects representing a
+ * The abstract class `FormalParameter` defines the behavior of objects representing a
* parameter to a function.
* <pre>
- * formalParameter ::={@link NormalFormalParameter normalFormalParameter}| {@link DefaultFormalParameter namedFormalParameter}| {@link DefaultFormalParameter optionalFormalParameter}</pre>
+ * formalParameter ::=[NormalFormalParameter normalFormalParameter]| [DefaultFormalParameter namedFormalParameter]| [DefaultFormalParameter optionalFormalParameter]</pre>
* @coverage dart.engine.ast
*/
abstract class FormalParameter extends ASTNode {
/**
- * Return the element representing this parameter, or {@code null} if this parameter has not been
+ * Return the element representing this parameter, or `null` if this parameter has not been
* resolved.
* @return the element representing this parameter
*/
@@ -5831,9 +5831,9 @@
ParameterKind get kind;
}
/**
- * Instances of the class {@code FormalParameterList} represent the formal parameter list of a
+ * Instances of the class `FormalParameterList` represent the formal parameter list of a
* method declaration, function declaration, or function type alias.
- * <p>
+ *
* While the grammar requires all optional formal parameters to follow all of the normal formal
* parameters and at most one grouping of optional formal parameters, this class does not enforce
* those constraints. All parameters are flattened into a single list, which can have any or all
@@ -5843,14 +5843,14 @@
* '(' ')'
* | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
* | '(' optionalFormalParameters ')'
- * normalFormalParameters ::={@link NormalFormalParameter normalFormalParameter} (',' {@link NormalFormalParameter normalFormalParameter})
+ * normalFormalParameters ::=[NormalFormalParameter normalFormalParameter] (',' [NormalFormalParameter normalFormalParameter])
* optionalFormalParameters ::=
* optionalPositionalFormalParameters
* | namedFormalParameters
* optionalPositionalFormalParameters ::=
- * '\[' {@link DefaultFormalParameter positionalFormalParameter} (',' {@link DefaultFormalParameter positionalFormalParameter})* '\]'
+ * '\[' [DefaultFormalParameter positionalFormalParameter] (',' [DefaultFormalParameter positionalFormalParameter])* '\]'
* namedFormalParameters ::=
- * '{' {@link DefaultFormalParameter namedFormalParameter} (',' {@link DefaultFormalParameter namedFormalParameter})* '}'
+ * '{' [DefaultFormalParameter namedFormalParameter] (',' [DefaultFormalParameter namedFormalParameter])* '}'
* </pre>
* @coverage dart.engine.ast
*/
@@ -5912,7 +5912,7 @@
/**
* Return an array containing the elements representing the parameters in this list. The array
- * will contain {@code null}s if the parameters in this list have not been resolved.
+ * will contain `null`s if the parameters in this list have not been resolved.
* @return the elements representing the parameters in this list
*/
List<ParameterElement> get elements {
@@ -5997,44 +5997,44 @@
}
}
/**
- * The abstract class {@code FunctionBody} defines the behavior common to objects representing the
+ * The abstract class `FunctionBody` defines the behavior common to objects representing the
* body of a function or method.
* <pre>
- * functionBody ::={@link BlockFunctionBody blockFunctionBody}| {@link EmptyFunctionBody emptyFunctionBody}| {@link ExpressionFunctionBody expressionFunctionBody}</pre>
+ * functionBody ::=[BlockFunctionBody blockFunctionBody]| [EmptyFunctionBody emptyFunctionBody]| [ExpressionFunctionBody expressionFunctionBody]</pre>
* @coverage dart.engine.ast
*/
abstract class FunctionBody extends ASTNode {
}
/**
- * Instances of the class {@code FunctionDeclaration} wrap a {@link FunctionExpression function
- * expression} as a top-level declaration.
+ * Instances of the class `FunctionDeclaration` wrap a [FunctionExpression function
+ * expression] as a top-level declaration.
* <pre>
* functionDeclaration ::=
* 'external' functionSignature
- * | functionSignature {@link FunctionBody functionBody}functionSignature ::={@link Type returnType}? ('get' | 'set')? {@link SimpleIdentifier functionName} {@link FormalParameterList formalParameterList}</pre>
+ * | functionSignature [FunctionBody functionBody]functionSignature ::=[Type returnType]? ('get' | 'set')? [SimpleIdentifier functionName] [FormalParameterList formalParameterList]</pre>
* @coverage dart.engine.ast
*/
class FunctionDeclaration extends CompilationUnitMember {
/**
- * The token representing the 'external' keyword, or {@code null} if this is not an external
+ * The token representing the 'external' keyword, or `null` if this is not an external
* function.
*/
Token _externalKeyword;
/**
- * The return type of the function, or {@code null} if no return type was declared.
+ * The return type of the function, or `null` if no return type was declared.
*/
TypeName _returnType;
/**
- * The token representing the 'get' or 'set' keyword, or {@code null} if this is a function
+ * The token representing the 'get' or 'set' keyword, or `null` if this is a function
* declaration rather than a property declaration.
*/
Token _propertyKeyword;
/**
- * The name of the function, or {@code null} if the function is not named.
+ * The name of the function, or `null` if the function is not named.
*/
SimpleIdentifier _name;
@@ -6077,7 +6077,7 @@
Token get endToken => _functionExpression.endToken;
/**
- * Return the token representing the 'external' keyword, or {@code null} if this is not an
+ * Return the token representing the 'external' keyword, or `null` if this is not an
* external function.
* @return the token representing the 'external' keyword
*/
@@ -6090,35 +6090,35 @@
FunctionExpression get functionExpression => _functionExpression;
/**
- * Return the name of the function, or {@code null} if the function is not named.
+ * Return the name of the function, or `null` if the function is not named.
* @return the name of the function
*/
SimpleIdentifier get name => _name;
/**
- * Return the token representing the 'get' or 'set' keyword, or {@code null} if this is a function
+ * Return the token representing the 'get' or 'set' keyword, or `null` if this is a function
* declaration rather than a property declaration.
* @return the token representing the 'get' or 'set' keyword
*/
Token get propertyKeyword => _propertyKeyword;
/**
- * Return the return type of the function, or {@code null} if no return type was declared.
+ * Return the return type of the function, or `null` if no return type was declared.
* @return the return type of the function
*/
TypeName get returnType => _returnType;
/**
- * Return {@code true} if this function declares a getter.
- * @return {@code true} if this function declares a getter
+ * Return `true` if this function declares a getter.
+ * @return `true` if this function declares a getter
*/
- bool isGetter() => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.GET);
+ bool get isGetter => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.GET);
/**
- * Return {@code true} if this function declares a setter.
- * @return {@code true} if this function declares a setter
+ * Return `true` if this function declares a setter.
+ * @return `true` if this function declares a setter
*/
- bool isSetter() => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.SET);
+ bool get isSetter => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.SET);
/**
* Set the token representing the 'external' keyword to the given token.
@@ -6180,7 +6180,7 @@
}
}
/**
- * Instances of the class {@code FunctionDeclarationStatement} wrap a {@link FunctionDeclarationfunction declaration} as a statement.
+ * Instances of the class `FunctionDeclarationStatement` wrap a [FunctionDeclarationfunction declaration] as a statement.
* @coverage dart.engine.ast
*/
class FunctionDeclarationStatement extends Statement {
@@ -6225,9 +6225,9 @@
}
}
/**
- * Instances of the class {@code FunctionExpression} represent a function expression.
+ * Instances of the class `FunctionExpression` represent a function expression.
* <pre>
- * functionExpression ::={@link FormalParameterList formalParameterList} {@link FunctionBody functionBody}</pre>
+ * functionExpression ::=[FormalParameterList formalParameterList] [FunctionBody functionBody]</pre>
* @coverage dart.engine.ast
*/
class FunctionExpression extends Expression {
@@ -6238,12 +6238,12 @@
FormalParameterList _parameters;
/**
- * The body of the function, or {@code null} if this is an external function.
+ * The body of the function, or `null` if this is an external function.
*/
FunctionBody _body;
/**
- * The element associated with the function, or {@code null} if the AST structure has not been
+ * The element associated with the function, or `null` if the AST structure has not been
* resolved.
*/
ExecutableElement _element;
@@ -6275,13 +6275,13 @@
}
/**
- * Return the body of the function, or {@code null} if this is an external function.
+ * Return the body of the function, or `null` if this is an external function.
* @return the body of the function
*/
FunctionBody get body => _body;
/**
- * Return the element associated with this function, or {@code null} if the AST structure has not
+ * Return the element associated with this function, or `null` if the AST structure has not
* been resolved.
* @return the element associated with this function
*/
@@ -6330,12 +6330,12 @@
}
}
/**
- * Instances of the class {@code FunctionExpressionInvocation} represent the invocation of a
+ * Instances of the class `FunctionExpressionInvocation` represent the invocation of a
* function resulting from evaluating an expression. Invocations of methods and other forms of
- * functions are represented by {@link MethodInvocation method invocation} nodes. Invocations of
- * getters and setters are represented by either {@link PrefixedIdentifier prefixed identifier} or{@link PropertyAccess property access} nodes.
+ * functions are represented by [MethodInvocation method invocation] nodes. Invocations of
+ * getters and setters are represented by either [PrefixedIdentifier prefixed identifier] or[PropertyAccess property access] nodes.
* <pre>
- * functionExpressionInvoction ::={@link Expression function} {@link ArgumentList argumentList}</pre>
+ * functionExpressionInvoction ::=[Expression function] [ArgumentList argumentList]</pre>
* @coverage dart.engine.ast
*/
class FunctionExpressionInvocation extends Expression {
@@ -6351,12 +6351,12 @@
ArgumentList _argumentList;
/**
- * The element associated with the function being invoked based on static type information, or{@code null} if the AST structure has not been resolved or the function could not be resolved.
+ * The element associated with the function being invoked based on static type information, or`null` if the AST structure has not been resolved or the function could not be resolved.
*/
ExecutableElement _staticElement;
/**
- * The element associated with the function being invoked based on propagated type information, or{@code null} if the AST structure has not been resolved or the function could not be resolved.
+ * The element associated with the function being invoked based on propagated type information, or`null` if the AST structure has not been resolved or the function could not be resolved.
*/
ExecutableElement _propagatedElement;
@@ -6387,7 +6387,7 @@
/**
* Return the element associated with the function being invoked based on propagated type
- * information, or {@code null} if the AST structure has not been resolved or the function could
+ * information, or `null` if the AST structure has not been resolved or the function could
* not be resolved. One common example of the latter case is an expression whose value can change
* over time.
* @return the element associated with the function being invoked
@@ -6403,7 +6403,7 @@
/**
* Return the element associated with the function being invoked based on static type information,
- * or {@code null} if the AST structure has not been resolved or the function could not be
+ * or `null` if the AST structure has not been resolved or the function could not be
* resolved. One common example of the latter case is an expression whose value can change over
* time.
* @return the element associated with the function
@@ -6449,17 +6449,17 @@
}
}
/**
- * Instances of the class {@code FunctionTypeAlias} represent a function type alias.
+ * Instances of the class `FunctionTypeAlias` represent a function type alias.
* <pre>
* functionTypeAlias ::=
- * functionPrefix {@link TypeParameterList typeParameterList}? {@link FormalParameterList formalParameterList} ';'
- * functionPrefix ::={@link TypeName returnType}? {@link SimpleIdentifier name}</pre>
+ * functionPrefix [TypeParameterList typeParameterList]? [FormalParameterList formalParameterList] ';'
+ * functionPrefix ::=[TypeName returnType]? [SimpleIdentifier name]</pre>
* @coverage dart.engine.ast
*/
class FunctionTypeAlias extends TypeAlias {
/**
- * The name of the return type of the function type being defined, or {@code null} if no return
+ * The name of the return type of the function type being defined, or `null` if no return
* type was given.
*/
TypeName _returnType;
@@ -6470,7 +6470,7 @@
SimpleIdentifier _name;
/**
- * The type parameters for the function type, or {@code null} if the function type does not have
+ * The type parameters for the function type, or `null` if the function type does not have
* any type parameters.
*/
TypeParameterList _typeParameters;
@@ -6526,14 +6526,14 @@
FormalParameterList get parameters => _parameters;
/**
- * Return the name of the return type of the function type being defined, or {@code null} if no
+ * Return the name of the return type of the function type being defined, or `null` if no
* return type was given.
* @return the name of the return type of the function type being defined
*/
TypeName get returnType => _returnType;
/**
- * Return the type parameters for the function type, or {@code null} if the function type does not
+ * Return the type parameters for the function type, or `null` if the function type does not
* have any type parameters.
* @return the type parameters for the function type
*/
@@ -6579,16 +6579,16 @@
}
}
/**
- * Instances of the class {@code FunctionTypedFormalParameter} represent a function-typed formal
+ * Instances of the class `FunctionTypedFormalParameter` represent a function-typed formal
* parameter.
* <pre>
- * functionSignature ::={@link TypeName returnType}? {@link SimpleIdentifier identifier} {@link FormalParameterList formalParameterList}</pre>
+ * functionSignature ::=[TypeName returnType]? [SimpleIdentifier identifier] [FormalParameterList formalParameterList]</pre>
* @coverage dart.engine.ast
*/
class FunctionTypedFormalParameter extends NormalFormalParameter {
/**
- * The return type of the function, or {@code null} if the function does not have a return type.
+ * The return type of the function, or `null` if the function does not have a return type.
*/
TypeName _returnType;
@@ -6601,7 +6601,7 @@
* Initialize a newly created formal parameter.
* @param comment the documentation comment associated with this parameter
* @param metadata the annotations associated with this parameter
- * @param returnType the return type of the function, or {@code null} if the function does not
+ * @param returnType the return type of the function, or `null` if the function does not
* have a return type
* @param identifier the name of the function-typed parameter
* @param parameters the parameters of the function-typed parameter
@@ -6615,7 +6615,7 @@
* Initialize a newly created formal parameter.
* @param comment the documentation comment associated with this parameter
* @param metadata the annotations associated with this parameter
- * @param returnType the return type of the function, or {@code null} if the function does not
+ * @param returnType the return type of the function, or `null` if the function does not
* have a return type
* @param identifier the name of the function-typed parameter
* @param parameters the parameters of the function-typed parameter
@@ -6637,13 +6637,13 @@
FormalParameterList get parameters => _parameters;
/**
- * Return the return type of the function, or {@code null} if the function does not have a return
+ * Return the return type of the function, or `null` if the function does not have a return
* type.
* @return the return type of the function
*/
TypeName get returnType => _returnType;
- bool isConst() => false;
- bool isFinal() => false;
+ bool get isConst => false;
+ bool get isFinal => false;
/**
* Set the parameters of the function-typed parameter to the given parameters.
@@ -6668,11 +6668,11 @@
}
}
/**
- * Instances of the class {@code HideCombinator} represent a combinator that restricts the names
+ * Instances of the class `HideCombinator` represent a combinator that restricts the names
* being imported to those that are not in a given list.
* <pre>
* hideCombinator ::=
- * 'hide' {@link SimpleIdentifier identifier} (',' {@link SimpleIdentifier identifier})
+ * 'hide' [SimpleIdentifier identifier] (',' [SimpleIdentifier identifier])
* </pre>
* @coverage dart.engine.ast
*/
@@ -6712,24 +6712,24 @@
}
}
/**
- * The abstract class {@code Identifier} defines the behavior common to nodes that represent an
+ * The abstract class `Identifier` defines the behavior common to nodes that represent an
* identifier.
* <pre>
- * identifier ::={@link SimpleIdentifier simpleIdentifier}| {@link PrefixedIdentifier prefixedIdentifier}</pre>
+ * identifier ::=[SimpleIdentifier simpleIdentifier]| [PrefixedIdentifier prefixedIdentifier]</pre>
* @coverage dart.engine.ast
*/
abstract class Identifier extends Expression {
/**
- * Return {@code true} if the given name is visible only within the library in which it is
+ * Return `true` if the given name is visible only within the library in which it is
* declared.
* @param name the name being tested
- * @return {@code true} if the given name is private
+ * @return `true` if the given name is private
*/
static bool isPrivateName(String name) => name.startsWith("_");
/**
- * Return the element associated with this identifier based on propagated type information, or{@code null} if the AST structure has not been resolved or if this identifier could not be
+ * Return the element associated with this identifier based on propagated type information, or`null` if the AST structure has not been resolved or if this identifier could not be
* resolved. One example of the latter case is an identifier that is not defined within the scope
* in which it appears.
* @return the element associated with this identifier
@@ -6743,19 +6743,19 @@
String get name;
/**
- * Return the element associated with this identifier based on static type information, or{@code null} if the AST structure has not been resolved or if this identifier could not be
+ * Return the element associated with this identifier based on static type information, or`null` if the AST structure has not been resolved or if this identifier could not be
* resolved. One example of the latter case is an identifier that is not defined within the scope
* in which it appears
* @return the element associated with the operator
*/
Element get staticElement;
- bool isAssignable() => true;
+ bool get isAssignable => true;
}
/**
- * Instances of the class {@code IfStatement} represent an if statement.
+ * Instances of the class `IfStatement` represent an if statement.
* <pre>
* ifStatement ::=
- * 'if' '(' {@link Expression expression} ')' {@link Statement thenStatement} ('else' {@link Statement elseStatement})?
+ * 'if' '(' [Expression expression] ')' [Statement thenStatement] ('else' [Statement elseStatement])?
* </pre>
* @coverage dart.engine.ast
*/
@@ -6782,7 +6782,7 @@
Token _rightParenthesis;
/**
- * The statement that is executed if the condition evaluates to {@code true}.
+ * The statement that is executed if the condition evaluates to `true`.
*/
Statement _thenStatement;
@@ -6792,7 +6792,7 @@
Token _elseKeyword;
/**
- * The statement that is executed if the condition evaluates to {@code false}, or {@code null} if
+ * The statement that is executed if the condition evaluates to `false`, or `null` if
* there is no else statement.
*/
Statement _elseStatement;
@@ -6803,9 +6803,9 @@
* @param leftParenthesis the left parenthesis
* @param condition the condition used to determine which of the statements is executed next
* @param rightParenthesis the right parenthesis
- * @param thenStatement the statement that is executed if the condition evaluates to {@code true}
+ * @param thenStatement the statement that is executed if the condition evaluates to `true`
* @param elseKeyword the token representing the 'else' keyword
- * @param elseStatement the statement that is executed if the condition evaluates to {@code false}
+ * @param elseStatement the statement that is executed if the condition evaluates to `false`
*/
IfStatement.full(Token ifKeyword, Token leftParenthesis, Expression condition, Token rightParenthesis, Statement thenStatement, Token elseKeyword, Statement elseStatement) {
this._ifKeyword = ifKeyword;
@@ -6823,9 +6823,9 @@
* @param leftParenthesis the left parenthesis
* @param condition the condition used to determine which of the statements is executed next
* @param rightParenthesis the right parenthesis
- * @param thenStatement the statement that is executed if the condition evaluates to {@code true}
+ * @param thenStatement the statement that is executed if the condition evaluates to `true`
* @param elseKeyword the token representing the 'else' keyword
- * @param elseStatement the statement that is executed if the condition evaluates to {@code false}
+ * @param elseStatement the statement that is executed if the condition evaluates to `false`
*/
IfStatement({Token ifKeyword, Token leftParenthesis, Expression condition, Token rightParenthesis, Statement thenStatement, Token elseKeyword, Statement elseStatement}) : this.full(ifKeyword, leftParenthesis, condition, rightParenthesis, thenStatement, elseKeyword, elseStatement);
accept(ASTVisitor visitor) => visitor.visitIfStatement(this);
@@ -6844,8 +6844,8 @@
Token get elseKeyword => _elseKeyword;
/**
- * Return the statement that is executed if the condition evaluates to {@code false}, or{@code null} if there is no else statement.
- * @return the statement that is executed if the condition evaluates to {@code false}
+ * Return the statement that is executed if the condition evaluates to `false`, or`null` if there is no else statement.
+ * @return the statement that is executed if the condition evaluates to `false`
*/
Statement get elseStatement => _elseStatement;
Token get endToken {
@@ -6874,8 +6874,8 @@
Token get rightParenthesis => _rightParenthesis;
/**
- * Return the statement that is executed if the condition evaluates to {@code true}.
- * @return the statement that is executed if the condition evaluates to {@code true}
+ * Return the statement that is executed if the condition evaluates to `true`.
+ * @return the statement that is executed if the condition evaluates to `true`
*/
Statement get thenStatement => _thenStatement;
@@ -6897,9 +6897,9 @@
}
/**
- * Set the statement that is executed if the condition evaluates to {@code false} to the given
+ * Set the statement that is executed if the condition evaluates to `false` to the given
* statement.
- * @param statement the statement that is executed if the condition evaluates to {@code false}
+ * @param statement the statement that is executed if the condition evaluates to `false`
*/
void set elseStatement(Statement statement) {
_elseStatement = becomeParentOf(statement);
@@ -6930,9 +6930,9 @@
}
/**
- * Set the statement that is executed if the condition evaluates to {@code true} to the given
+ * Set the statement that is executed if the condition evaluates to `true` to the given
* statement.
- * @param statement the statement that is executed if the condition evaluates to {@code true}
+ * @param statement the statement that is executed if the condition evaluates to `true`
*/
void set thenStatement(Statement statement) {
_thenStatement = becomeParentOf(statement);
@@ -6944,11 +6944,11 @@
}
}
/**
- * Instances of the class {@code ImplementsClause} represent the "implements" clause in an class
+ * Instances of the class `ImplementsClause` represent the "implements" clause in an class
* declaration.
* <pre>
* implementsClause ::=
- * 'implements' {@link TypeName superclass} (',' {@link TypeName superclass})
+ * 'implements' [TypeName superclass] (',' [TypeName superclass])
* </pre>
* @coverage dart.engine.ast
*/
@@ -7009,21 +7009,21 @@
}
}
/**
- * Instances of the class {@code ImportDirective} represent an import directive.
+ * Instances of the class `ImportDirective` represent an import directive.
* <pre>
- * importDirective ::={@link Annotation metadata} 'import' {@link StringLiteral libraryUri} ('as' identifier)? {@link Combinator combinator}* ';'
+ * importDirective ::=[Annotation metadata] 'import' [StringLiteral libraryUri] ('as' identifier)? [Combinator combinator]* ';'
* </pre>
* @coverage dart.engine.ast
*/
class ImportDirective extends NamespaceDirective {
/**
- * The token representing the 'as' token, or {@code null} if the imported names are not prefixed.
+ * The token representing the 'as' token, or `null` if the imported names are not prefixed.
*/
Token _asToken;
/**
- * The prefix to be used with the imported names, or {@code null} if the imported names are not
+ * The prefix to be used with the imported names, or `null` if the imported names are not
* prefixed.
*/
SimpleIdentifier _prefix;
@@ -7059,14 +7059,14 @@
accept(ASTVisitor visitor) => visitor.visitImportDirective(this);
/**
- * Return the token representing the 'as' token, or {@code null} if the imported names are not
+ * Return the token representing the 'as' token, or `null` if the imported names are not
* prefixed.
* @return the token representing the 'as' token
*/
Token get asToken => _asToken;
/**
- * Return the prefix to be used with the imported names, or {@code null} if the imported names are
+ * Return the prefix to be used with the imported names, or `null` if the imported names are
* not prefixed.
* @return the prefix to be used with the imported names
*/
@@ -7101,22 +7101,22 @@
}
}
/**
- * Instances of the class {@code IndexExpression} represent an index expression.
+ * Instances of the class `IndexExpression` represent an index expression.
* <pre>
- * indexExpression ::={@link Expression target} '\[' {@link Expression index} '\]'
+ * indexExpression ::=[Expression target] '\[' [Expression index] '\]'
* </pre>
* @coverage dart.engine.ast
*/
class IndexExpression extends Expression {
/**
- * The expression used to compute the object being indexed, or {@code null} if this index
+ * The expression used to compute the object being indexed, or `null` if this index
* expression is part of a cascade expression.
*/
Expression _target;
/**
- * The period ("..") before a cascaded index expression, or {@code null} if this index expression
+ * The period ("..") before a cascaded index expression, or `null` if this index expression
* is not part of a cascade expression.
*/
Token _period;
@@ -7137,13 +7137,13 @@
Token _rightBracket;
/**
- * The element associated with the operator based on the static type of the target, or{@code null} if the AST structure has not been resolved or if the operator could not be
+ * The element associated with the operator based on the static type of the target, or`null` if the AST structure has not been resolved or if the operator could not be
* resolved.
*/
MethodElement _staticElement;
/**
- * The element associated with the operator based on the propagated type of the target, or{@code null} if the AST structure has not been resolved or if the operator could not be
+ * The element associated with the operator based on the propagated type of the target, or`null` if the AST structure has not been resolved or if the operator could not be
* resolved.
*/
MethodElement _propagatedElement;
@@ -7202,7 +7202,7 @@
accept(ASTVisitor visitor) => visitor.visitIndexExpression(this);
/**
- * Return the expression used to compute the object being indexed, or {@code null} if this index
+ * Return the expression used to compute the object being indexed, or `null` if this index
* expression is part of a cascade expression.
* @return the expression used to compute the object being indexed
* @see #getRealTarget()
@@ -7216,7 +7216,7 @@
}
/**
- * Return the element associated with the operator based on the propagated type of the target, or{@code null} if the AST structure has not been resolved or if the operator could not be
+ * Return the element associated with the operator based on the propagated type of the target, or`null` if the AST structure has not been resolved or if the operator could not be
* resolved. One example of the latter case is an operator that is not defined for the type of the
* target.
* @return the element associated with this operator
@@ -7237,7 +7237,7 @@
Token get leftBracket => _leftBracket;
/**
- * Return the period ("..") before a cascaded index expression, or {@code null} if this index
+ * Return the period ("..") before a cascaded index expression, or `null` if this index
* expression is not part of a cascade expression.
* @return the period ("..") before a cascaded index expression
*/
@@ -7245,14 +7245,14 @@
/**
* Return the expression used to compute the object being indexed. If this index expression is not
- * part of a cascade expression, then this is the same as {@link #getArray()}. If this index
+ * part of a cascade expression, then this is the same as [getArray]. If this index
* expression is part of a cascade expression, then the target expression stored with the cascade
* expression is returned.
* @return the expression used to compute the object being indexed
* @see #getArray()
*/
Expression get realTarget {
- if (isCascaded()) {
+ if (isCascaded) {
ASTNode ancestor = parent;
while (ancestor is! CascadeExpression) {
if (ancestor == null) {
@@ -7272,7 +7272,7 @@
Token get rightBracket => _rightBracket;
/**
- * Return the element associated with the operator based on the static type of the target, or{@code null} if the AST structure has not been resolved or if the operator could not be
+ * Return the element associated with the operator based on the static type of the target, or`null` if the AST structure has not been resolved or if the operator could not be
* resolved. One example of the latter case is an operator that is not defined for the type of the
* target.
* @return the element associated with the operator
@@ -7280,11 +7280,11 @@
MethodElement get staticElement => _staticElement;
/**
- * Return {@code true} if this expression is computing a right-hand value.
- * <p>
- * Note that {@link #inGetterContext()} and {@link #inSetterContext()} are not opposites, nor are
- * they mutually exclusive. In other words, it is possible for both methods to return {@code true}when invoked on the same node.
- * @return {@code true} if this expression is in a context where the operator '\[\]' will be invoked
+ * Return `true` if this expression is computing a right-hand value.
+ *
+ * Note that [inGetterContext] and [inSetterContext] are not opposites, nor are
+ * they mutually exclusive. In other words, it is possible for both methods to return `true`when invoked on the same node.
+ * @return `true` if this expression is in a context where the operator '\[\]' will be invoked
*/
bool inGetterContext() {
ASTNode parent = this.parent;
@@ -7298,17 +7298,17 @@
}
/**
- * Return {@code true} if this expression is computing a left-hand value.
- * <p>
- * Note that {@link #inGetterContext()} and {@link #inSetterContext()} are not opposites, nor are
- * they mutually exclusive. In other words, it is possible for both methods to return {@code true}when invoked on the same node.
- * @return {@code true} if this expression is in a context where the operator '\[\]=' will be
+ * Return `true` if this expression is computing a left-hand value.
+ *
+ * Note that [inGetterContext] and [inSetterContext] are not opposites, nor are
+ * they mutually exclusive. In other words, it is possible for both methods to return `true`when invoked on the same node.
+ * @return `true` if this expression is in a context where the operator '\[\]=' will be
* invoked
*/
bool inSetterContext() {
ASTNode parent = this.parent;
if (parent is PrefixExpression) {
- return ((parent as PrefixExpression)).operator.type.isIncrementOperator();
+ return ((parent as PrefixExpression)).operator.type.isIncrementOperator;
} else if (parent is PostfixExpression) {
return true;
} else if (parent is AssignmentExpression) {
@@ -7316,14 +7316,14 @@
}
return false;
}
- bool isAssignable() => true;
+ bool get isAssignable => true;
/**
- * Return {@code true} if this expression is cascaded. If it is, then the target of this
- * expression is not stored locally but is stored in the nearest ancestor that is a{@link CascadeExpression}.
- * @return {@code true} if this expression is cascaded
+ * Return `true` if this expression is cascaded. If it is, then the target of this
+ * expression is not stored locally but is stored in the nearest ancestor that is a[CascadeExpression].
+ * @return `true` if this expression is cascaded
*/
- bool isCascaded() => _period != null;
+ bool get isCascaded => _period != null;
/**
* Set the expression used to compute the object being indexed to the given expression.
@@ -7390,9 +7390,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on
* propagated type information, then return the parameter element representing the parameter to
- * which the value of the index expression will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getParameterElement()}.
+ * which the value of the index expression will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getParameterElement].
* @return the parameter element representing the parameter to which the value of the index
* expression will be bound
*/
@@ -7410,9 +7410,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on static
* type information, then return the parameter element representing the parameter to which the
- * value of the index expression will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getStaticParameterElement()}.
+ * value of the index expression will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getStaticParameterElement].
* @return the parameter element representing the parameter to which the value of the index
* expression will be bound
*/
@@ -7428,11 +7428,11 @@
}
}
/**
- * Instances of the class {@code InstanceCreationExpression} represent an instance creation
+ * Instances of the class `InstanceCreationExpression` represent an instance creation
* expression.
* <pre>
* newExpression ::=
- * ('new' | 'const') {@link TypeName type} ('.' {@link SimpleIdentifier identifier})? {@link ArgumentList argumentList}</pre>
+ * ('new' | 'const') [TypeName type] ('.' [SimpleIdentifier identifier])? [ArgumentList argumentList]</pre>
* @coverage dart.engine.ast
*/
class InstanceCreationExpression extends Expression {
@@ -7453,12 +7453,12 @@
ArgumentList _argumentList;
/**
- * The element associated with the constructor based on static type information, or {@code null}if the AST structure has not been resolved or if the constructor could not be resolved.
+ * The element associated with the constructor based on static type information, or `null`if the AST structure has not been resolved or if the constructor could not be resolved.
*/
ConstructorElement _staticElement;
/**
- * The element associated with the constructor based on propagated type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * The element associated with the constructor based on propagated type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
*/
ConstructorElement _propagatedElement;
@@ -7498,7 +7498,7 @@
ConstructorName get constructorName => _constructorName;
/**
- * Return the element associated with the constructor based on propagated type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * Return the element associated with the constructor based on propagated type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
* @return the element associated with the constructor
*/
@@ -7512,17 +7512,17 @@
Token get keyword => _keyword;
/**
- * Return the element associated with the constructor based on static type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * Return the element associated with the constructor based on static type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
* @return the element associated with the constructor
*/
ConstructorElement get staticElement => _staticElement;
/**
- * Return {@code true} if this creation expression is used to invoke a constant constructor.
- * @return {@code true} if this creation expression is used to invoke a constant constructor
+ * Return `true` if this creation expression is used to invoke a constant constructor.
+ * @return `true` if this creation expression is used to invoke a constant constructor
*/
- bool isConst() => _keyword is KeywordToken && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
+ bool get isConst => _keyword is KeywordToken && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
/**
* Set the list of arguments to the constructor to the given list.
@@ -7571,7 +7571,7 @@
}
}
/**
- * Instances of the class {@code IntegerLiteral} represent an integer literal expression.
+ * Instances of the class `IntegerLiteral` represent an integer literal expression.
* <pre>
* integerLiteral ::=
* decimalIntegerLiteral
@@ -7647,19 +7647,19 @@
}
}
/**
- * The abstract class {@code InterpolationElement} defines the behavior common to elements within a{@link StringInterpolation string interpolation}.
+ * The abstract class `InterpolationElement` defines the behavior common to elements within a[StringInterpolation string interpolation].
* <pre>
- * interpolationElement ::={@link InterpolationExpression interpolationExpression}| {@link InterpolationString interpolationString}</pre>
+ * interpolationElement ::=[InterpolationExpression interpolationExpression]| [InterpolationString interpolationString]</pre>
* @coverage dart.engine.ast
*/
abstract class InterpolationElement extends ASTNode {
}
/**
- * Instances of the class {@code InterpolationExpression} represent an expression embedded in a
+ * Instances of the class `InterpolationExpression` represent an expression embedded in a
* string interpolation.
* <pre>
* interpolationExpression ::=
- * '$' {@link SimpleIdentifier identifier}| '$' '{' {@link Expression expression} '}'
+ * '$' [SimpleIdentifier identifier]| '$' '{' [Expression expression] '}'
* </pre>
* @coverage dart.engine.ast
*/
@@ -7677,7 +7677,7 @@
Expression _expression;
/**
- * The right curly bracket, or {@code null} if the expression is an identifier without brackets.
+ * The right curly bracket, or `null` if the expression is an identifier without brackets.
*/
Token _rightBracket;
@@ -7756,7 +7756,7 @@
}
}
/**
- * Instances of the class {@code InterpolationString} represent a non-empty substring of an
+ * Instances of the class `InterpolationString` represent a non-empty substring of an
* interpolated string.
* <pre>
* interpolationString ::=
@@ -7827,9 +7827,9 @@
}
}
/**
- * Instances of the class {@code IsExpression} represent an is expression.
+ * Instances of the class `IsExpression` represent an is expression.
* <pre>
- * isExpression ::={@link Expression expression} 'is' '!'? {@link TypeName type}</pre>
+ * isExpression ::=[Expression expression] 'is' '!'? [TypeName type]</pre>
* @coverage dart.engine.ast
*/
class IsExpression extends Expression {
@@ -7845,7 +7845,7 @@
Token _isOperator;
/**
- * The not operator, or {@code null} if the sense of the test is not negated.
+ * The not operator, or `null` if the sense of the test is not negated.
*/
Token _notOperator;
@@ -7858,7 +7858,7 @@
* Initialize a newly created is expression.
* @param expression the expression used to compute the value whose type is being tested
* @param isOperator the is operator
- * @param notOperator the not operator, or {@code null} if the sense of the test is not negated
+ * @param notOperator the not operator, or `null` if the sense of the test is not negated
* @param type the name of the type being tested for
*/
IsExpression.full(Expression expression, Token isOperator, Token notOperator, TypeName type) {
@@ -7872,7 +7872,7 @@
* Initialize a newly created is expression.
* @param expression the expression used to compute the value whose type is being tested
* @param isOperator the is operator
- * @param notOperator the not operator, or {@code null} if the sense of the test is not negated
+ * @param notOperator the not operator, or `null` if the sense of the test is not negated
* @param type the name of the type being tested for
*/
IsExpression({Expression expression, Token isOperator, Token notOperator, TypeName type}) : this.full(expression, isOperator, notOperator, type);
@@ -7942,9 +7942,9 @@
}
}
/**
- * Instances of the class {@code Label} represent a label.
+ * Instances of the class `Label` represent a label.
* <pre>
- * label ::={@link SimpleIdentifier label} ':'
+ * label ::=[SimpleIdentifier label] ':'
* </pre>
* @coverage dart.engine.ast
*/
@@ -8012,10 +8012,10 @@
}
}
/**
- * Instances of the class {@code LabeledStatement} represent a statement that has a label associated
+ * Instances of the class `LabeledStatement` represent a statement that has a label associated
* with them.
* <pre>
- * labeledStatement ::={@link Label label}+ {@link Statement statement}</pre>
+ * labeledStatement ::=[Label label]+ [Statement statement]</pre>
* @coverage dart.engine.ast
*/
class LabeledStatement extends Statement {
@@ -8081,9 +8081,9 @@
}
}
/**
- * Instances of the class {@code LibraryDirective} represent a library directive.
+ * Instances of the class `LibraryDirective` represent a library directive.
* <pre>
- * libraryDirective ::={@link Annotation metadata} 'library' {@link Identifier name} ';'
+ * libraryDirective ::=[Annotation metadata] 'library' [Identifier name] ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -8179,9 +8179,9 @@
Token get firstTokenAfterCommentAndMetadata => _libraryToken;
}
/**
- * Instances of the class {@code LibraryIdentifier} represent the identifier for a library.
+ * Instances of the class `LibraryIdentifier` represent the identifier for a library.
* <pre>
- * libraryIdentifier ::={@link SimpleIdentifier component} ('.' {@link SimpleIdentifier component})
+ * libraryIdentifier ::=[SimpleIdentifier component] ('.' [SimpleIdentifier component])
* </pre>
* @coverage dart.engine.ast
*/
@@ -8235,10 +8235,10 @@
}
}
/**
- * Instances of the class {@code ListLiteral} represent a list literal.
+ * Instances of the class `ListLiteral` represent a list literal.
* <pre>
* listLiteral ::=
- * 'const'? ('<' {@link TypeName type} '>')? '\[' ({@link Expression expressionList} ','?)? '\]'
+ * 'const'? ('<' [TypeName type] '>')? '\[' ([Expression expressionList] ','?)? '\]'
* </pre>
* @coverage dart.engine.ast
*/
@@ -8262,7 +8262,7 @@
/**
* Initialize a newly created list literal.
* @param modifier the const modifier associated with this literal
- * @param typeArguments the type argument associated with this literal, or {@code null} if no type
+ * @param typeArguments the type argument associated with this literal, or `null` if no type
* arguments were declared
* @param leftBracket the left square bracket
* @param elements the expressions used to compute the elements of the list
@@ -8278,7 +8278,7 @@
/**
* Initialize a newly created list literal.
* @param modifier the const modifier associated with this literal
- * @param typeArguments the type argument associated with this literal, or {@code null} if no type
+ * @param typeArguments the type argument associated with this literal, or `null` if no type
* arguments were declared
* @param leftBracket the left square bracket
* @param elements the expressions used to compute the elements of the list
@@ -8338,19 +8338,19 @@
}
}
/**
- * The abstract class {@code Literal} defines the behavior common to nodes that represent a literal
+ * The abstract class `Literal` defines the behavior common to nodes that represent a literal
* expression.
* <pre>
- * literal ::={@link BooleanLiteral booleanLiteral}| {@link DoubleLiteral doubleLiteral}| {@link IntegerLiteral integerLiteral}| {@link ListLiteral listLiteral}| {@link MapLiteral mapLiteral}| {@link NullLiteral nullLiteral}| {@link StringLiteral stringLiteral}</pre>
+ * literal ::=[BooleanLiteral booleanLiteral]| [DoubleLiteral doubleLiteral]| [IntegerLiteral integerLiteral]| [ListLiteral listLiteral]| [MapLiteral mapLiteral]| [NullLiteral nullLiteral]| [StringLiteral stringLiteral]</pre>
* @coverage dart.engine.ast
*/
abstract class Literal extends Expression {
}
/**
- * Instances of the class {@code MapLiteral} represent a literal map.
+ * Instances of the class `MapLiteral` represent a literal map.
* <pre>
* mapLiteral ::=
- * 'const'? ('<' {@link TypeName type} (',' {@link TypeName type})* '>')? '{' ({@link MapLiteralEntry entry} (',' {@link MapLiteralEntry entry})* ','?)? '}'
+ * 'const'? ('<' [TypeName type] (',' [TypeName type])* '>')? '{' ([MapLiteralEntry entry] (',' [MapLiteralEntry entry])* ','?)? '}'
* </pre>
* @coverage dart.engine.ast
*/
@@ -8374,7 +8374,7 @@
/**
* Initialize a newly created map literal.
* @param modifier the const modifier associated with this literal
- * @param typeArguments the type argument associated with this literal, or {@code null} if no type
+ * @param typeArguments the type argument associated with this literal, or `null` if no type
* arguments were declared
* @param leftBracket the left curly bracket
* @param entries the entries in the map
@@ -8390,7 +8390,7 @@
/**
* Initialize a newly created map literal.
* @param modifier the const modifier associated with this literal
- * @param typeArguments the type argument associated with this literal, or {@code null} if no type
+ * @param typeArguments the type argument associated with this literal, or `null` if no type
* arguments were declared
* @param leftBracket the left curly bracket
* @param entries the entries in the map
@@ -8450,10 +8450,10 @@
}
}
/**
- * Instances of the class {@code MapLiteralEntry} represent a single key/value pair in a map
+ * Instances of the class `MapLiteralEntry` represent a single key/value pair in a map
* literal.
* <pre>
- * mapLiteralEntry ::={@link Expression key} ':' {@link Expression value}</pre>
+ * mapLiteralEntry ::=[Expression key] ':' [Expression value]</pre>
* @coverage dart.engine.ast
*/
class MapLiteralEntry extends ASTNode {
@@ -8545,39 +8545,39 @@
}
}
/**
- * Instances of the class {@code MethodDeclaration} represent a method declaration.
+ * Instances of the class `MethodDeclaration` represent a method declaration.
* <pre>
* methodDeclaration ::=
- * methodSignature {@link FunctionBody body}methodSignature ::=
- * 'external'? ('abstract' | 'static')? {@link Type returnType}? ('get' | 'set')? methodName{@link FormalParameterList formalParameterList}methodName ::={@link SimpleIdentifier name}| 'operator' {@link SimpleIdentifier operator}</pre>
+ * methodSignature [FunctionBody body]methodSignature ::=
+ * 'external'? ('abstract' | 'static')? [Type returnType]? ('get' | 'set')? methodName[FormalParameterList formalParameterList]methodName ::=[SimpleIdentifier name]| 'operator' [SimpleIdentifier operator]</pre>
* @coverage dart.engine.ast
*/
class MethodDeclaration extends ClassMember {
/**
- * The token for the 'external' keyword, or {@code null} if the constructor is not external.
+ * The token for the 'external' keyword, or `null` if the constructor is not external.
*/
Token _externalKeyword;
/**
- * The token representing the 'abstract' or 'static' keyword, or {@code null} if neither modifier
+ * The token representing the 'abstract' or 'static' keyword, or `null` if neither modifier
* was specified.
*/
Token _modifierKeyword;
/**
- * The return type of the method, or {@code null} if no return type was declared.
+ * The return type of the method, or `null` if no return type was declared.
*/
TypeName _returnType;
/**
- * The token representing the 'get' or 'set' keyword, or {@code null} if this is a method
+ * The token representing the 'get' or 'set' keyword, or `null` if this is a method
* declaration rather than a property declaration.
*/
Token _propertyKeyword;
/**
- * The token representing the 'operator' keyword, or {@code null} if this method does not declare
+ * The token representing the 'operator' keyword, or `null` if this method does not declare
* an operator.
*/
Token _operatorKeyword;
@@ -8588,7 +8588,7 @@
SimpleIdentifier _name;
/**
- * The parameters associated with the method, or {@code null} if this method declares a getter.
+ * The parameters associated with the method, or `null` if this method declares a getter.
*/
FormalParameterList _parameters;
@@ -8607,7 +8607,7 @@
* @param propertyKeyword the token representing the 'get' or 'set' keyword
* @param operatorKeyword the token representing the 'operator' keyword
* @param name the name of the method
- * @param parameters the parameters associated with the method, or {@code null} if this method
+ * @param parameters the parameters associated with the method, or `null` if this method
* declares a getter
* @param body the body of the method
*/
@@ -8632,7 +8632,7 @@
* @param propertyKeyword the token representing the 'get' or 'set' keyword
* @param operatorKeyword the token representing the 'operator' keyword
* @param name the name of the method
- * @param parameters the parameters associated with the method, or {@code null} if this method
+ * @param parameters the parameters associated with the method, or `null` if this method
* declares a getter
* @param body the body of the method
*/
@@ -8646,9 +8646,9 @@
FunctionBody get body => _body;
/**
- * Return the element associated with this method, or {@code null} if the AST structure has not
- * been resolved. The element can either be a {@link MethodElement}, if this represents the
- * declaration of a normal method, or a {@link PropertyAccessorElement} if this represents the
+ * Return the element associated with this method, or `null` if the AST structure has not
+ * been resolved. The element can either be a [MethodElement], if this represents the
+ * declaration of a normal method, or a [PropertyAccessorElement] if this represents the
* declaration of either a getter or a setter.
* @return the element associated with this method
*/
@@ -8656,14 +8656,14 @@
Token get endToken => _body.endToken;
/**
- * Return the token for the 'external' keyword, or {@code null} if the constructor is not
+ * Return the token for the 'external' keyword, or `null` if the constructor is not
* external.
* @return the token for the 'external' keyword
*/
Token get externalKeyword => _externalKeyword;
/**
- * Return the token representing the 'abstract' or 'static' keyword, or {@code null} if neither
+ * Return the token representing the 'abstract' or 'static' keyword, or `null` if neither
* modifier was specified.
* @return the token representing the 'abstract' or 'static' keyword
*/
@@ -8676,61 +8676,61 @@
SimpleIdentifier get name => _name;
/**
- * Return the token representing the 'operator' keyword, or {@code null} if this method does not
+ * Return the token representing the 'operator' keyword, or `null` if this method does not
* declare an operator.
* @return the token representing the 'operator' keyword
*/
Token get operatorKeyword => _operatorKeyword;
/**
- * Return the parameters associated with the method, or {@code null} if this method declares a
+ * Return the parameters associated with the method, or `null` if this method declares a
* getter.
* @return the parameters associated with the method
*/
FormalParameterList get parameters => _parameters;
/**
- * Return the token representing the 'get' or 'set' keyword, or {@code null} if this is a method
+ * Return the token representing the 'get' or 'set' keyword, or `null` if this is a method
* declaration rather than a property declaration.
* @return the token representing the 'get' or 'set' keyword
*/
Token get propertyKeyword => _propertyKeyword;
/**
- * Return the return type of the method, or {@code null} if no return type was declared.
+ * Return the return type of the method, or `null` if no return type was declared.
* @return the return type of the method
*/
TypeName get returnType => _returnType;
/**
- * Return {@code true} if this method is declared to be an abstract method.
- * @return {@code true} if this method is declared to be an abstract method
+ * Return `true` if this method is declared to be an abstract method.
+ * @return `true` if this method is declared to be an abstract method
*/
- bool isAbstract() => _externalKeyword == null && (_body is EmptyFunctionBody);
+ bool get isAbstract => _externalKeyword == null && (_body is EmptyFunctionBody);
/**
- * Return {@code true} if this method declares a getter.
- * @return {@code true} if this method declares a getter
+ * Return `true` if this method declares a getter.
+ * @return `true` if this method declares a getter
*/
- bool isGetter() => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.GET);
+ bool get isGetter => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.GET);
/**
- * Return {@code true} if this method declares an operator.
- * @return {@code true} if this method declares an operator
+ * Return `true` if this method declares an operator.
+ * @return `true` if this method declares an operator
*/
- bool isOperator() => _operatorKeyword != null;
+ bool get isOperator => _operatorKeyword != null;
/**
- * Return {@code true} if this method declares a setter.
- * @return {@code true} if this method declares a setter
+ * Return `true` if this method declares a setter.
+ * @return `true` if this method declares a setter
*/
- bool isSetter() => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.SET);
+ bool get isSetter => _propertyKeyword != null && identical(((_propertyKeyword as KeywordToken)).keyword, Keyword.SET);
/**
- * Return {@code true} if this method is declared to be a static method.
- * @return {@code true} if this method is declared to be a static method
+ * Return `true` if this method is declared to be a static method.
+ * @return `true` if this method is declared to be a static method
*/
- bool isStatic() => _modifierKeyword != null && identical(((_modifierKeyword as KeywordToken)).keyword, Keyword.STATIC);
+ bool get isStatic => _modifierKeyword != null && identical(((_modifierKeyword as KeywordToken)).keyword, Keyword.STATIC);
/**
* Set the body of the method to the given function body.
@@ -8816,24 +8816,24 @@
}
}
/**
- * Instances of the class {@code MethodInvocation} represent the invocation of either a function or
- * a method. Invocations of functions resulting from evaluating an expression are represented by{@link FunctionExpressionInvocation function expression invocation} nodes. Invocations of getters
- * and setters are represented by either {@link PrefixedIdentifier prefixed identifier} or{@link PropertyAccess property access} nodes.
+ * Instances of the class `MethodInvocation` represent the invocation of either a function or
+ * a method. Invocations of functions resulting from evaluating an expression are represented by[FunctionExpressionInvocation function expression invocation] nodes. Invocations of getters
+ * and setters are represented by either [PrefixedIdentifier prefixed identifier] or[PropertyAccess property access] nodes.
* <pre>
* methodInvoction ::=
- * ({@link Expression target} '.')? {@link SimpleIdentifier methodName} {@link ArgumentList argumentList}</pre>
+ * ([Expression target] '.')? [SimpleIdentifier methodName] [ArgumentList argumentList]</pre>
* @coverage dart.engine.ast
*/
class MethodInvocation extends Expression {
/**
- * The expression producing the object on which the method is defined, or {@code null} if there is
- * no target (that is, the target is implicitly {@code this}).
+ * The expression producing the object on which the method is defined, or `null` if there is
+ * no target (that is, the target is implicitly `this`).
*/
Expression _target;
/**
- * The period that separates the target from the method name, or {@code null} if there is no
+ * The period that separates the target from the method name, or `null` if there is no
* target.
*/
Token _period;
@@ -8894,7 +8894,7 @@
SimpleIdentifier get methodName => _methodName;
/**
- * Return the period that separates the target from the method name, or {@code null} if there is
+ * Return the period that separates the target from the method name, or `null` if there is
* no target.
* @return the period that separates the target from the method name
*/
@@ -8902,14 +8902,14 @@
/**
* Return the expression used to compute the receiver of the invocation. If this invocation is not
- * part of a cascade expression, then this is the same as {@link #getTarget()}. If this invocation
+ * part of a cascade expression, then this is the same as [getTarget]. If this invocation
* is part of a cascade expression, then the target stored with the cascade expression is
* returned.
* @return the expression used to compute the receiver of the invocation
* @see #getTarget()
*/
Expression get realTarget {
- if (isCascaded()) {
+ if (isCascaded) {
ASTNode ancestor = parent;
while (ancestor is! CascadeExpression) {
if (ancestor == null) {
@@ -8923,8 +8923,8 @@
}
/**
- * Return the expression producing the object on which the method is defined, or {@code null} if
- * there is no target (that is, the target is implicitly {@code this}) or if this method
+ * Return the expression producing the object on which the method is defined, or `null` if
+ * there is no target (that is, the target is implicitly `this`) or if this method
* invocation is part of a cascade expression.
* @return the expression producing the object on which the method is defined
* @see #getRealTarget()
@@ -8932,11 +8932,11 @@
Expression get target => _target;
/**
- * Return {@code true} if this expression is cascaded. If it is, then the target of this
- * expression is not stored locally but is stored in the nearest ancestor that is a{@link CascadeExpression}.
- * @return {@code true} if this expression is cascaded
+ * Return `true` if this expression is cascaded. If it is, then the target of this
+ * expression is not stored locally but is stored in the nearest ancestor that is a[CascadeExpression].
+ * @return `true` if this expression is cascaded
*/
- bool isCascaded() => _period != null && identical(_period.type, TokenType.PERIOD_PERIOD);
+ bool get isCascaded => _period != null && identical(_period.type, TokenType.PERIOD_PERIOD);
/**
* Set the list of arguments to the method to the given list.
@@ -8976,10 +8976,10 @@
}
}
/**
- * Instances of the class {@code NamedExpression} represent an expression that has a name associated
+ * Instances of the class `NamedExpression` represent an expression that has a name associated
* with it. They are used in method invocations when there are named parameters.
* <pre>
- * namedExpression ::={@link Label name} {@link Expression expression}</pre>
+ * namedExpression ::=[Label name] [Expression expression]</pre>
* @coverage dart.engine.ast
*/
class NamedExpression extends Expression {
@@ -9014,7 +9014,7 @@
Token get beginToken => _name.beginToken;
/**
- * Return the element representing the parameter being named by this expression, or {@code null}if the AST structure has not been resolved or if there is no parameter with the same name as
+ * Return the element representing the parameter being named by this expression, or `null`if the AST structure has not been resolved or if there is no parameter with the same name as
* this expression.
* @return the element representing the parameter being named by this expression
*/
@@ -9060,10 +9060,10 @@
}
}
/**
- * The abstract class {@code NamespaceDirective} defines the behavior common to nodes that represent
+ * The abstract class `NamespaceDirective` defines the behavior common to nodes that represent
* a directive that impacts the namespace of a library.
* <pre>
- * directive ::={@link ExportDirective exportDirective}| {@link ImportDirective importDirective}</pre>
+ * directive ::=[ExportDirective exportDirective]| [ImportDirective importDirective]</pre>
* @coverage dart.engine.ast
*/
abstract class NamespaceDirective extends UriBasedDirective {
@@ -9143,11 +9143,11 @@
Token get firstTokenAfterCommentAndMetadata => _keyword;
}
/**
- * Instances of the class {@code NativeFunctionBody} represent a function body that consists of a
+ * Instances of the class `NativeFunctionBody` represent a function body that consists of a
* native keyword followed by a string literal.
* <pre>
* nativeFunctionBody ::=
- * 'native' {@link SimpleStringLiteral simpleStringLiteral} ';'
+ * 'native' [SimpleStringLiteral simpleStringLiteral] ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -9215,16 +9215,16 @@
}
}
/**
- * The abstract class {@code NormalFormalParameter} defines the behavior common to formal parameters
+ * The abstract class `NormalFormalParameter` defines the behavior common to formal parameters
* that are required (are not optional).
* <pre>
- * normalFormalParameter ::={@link FunctionTypedFormalParameter functionSignature}| {@link FieldFormalParameter fieldFormalParameter}| {@link SimpleFormalParameter simpleFormalParameter}</pre>
+ * normalFormalParameter ::=[FunctionTypedFormalParameter functionSignature]| [FieldFormalParameter fieldFormalParameter]| [SimpleFormalParameter simpleFormalParameter]</pre>
* @coverage dart.engine.ast
*/
abstract class NormalFormalParameter extends FormalParameter {
/**
- * The documentation comment associated with this parameter, or {@code null} if this parameter
+ * The documentation comment associated with this parameter, or `null` if this parameter
* does not have a documentation comment associated with it.
*/
Comment _comment;
@@ -9261,7 +9261,7 @@
NormalFormalParameter({Comment comment, List<Annotation> metadata, SimpleIdentifier identifier}) : this.full(comment, metadata, identifier);
/**
- * Return the documentation comment associated with this parameter, or {@code null} if this
+ * Return the documentation comment associated with this parameter, or `null` if this
* parameter does not have a documentation comment associated with it.
* @return the documentation comment associated with this parameter
*/
@@ -9282,18 +9282,18 @@
NodeList<Annotation> get metadata => _metadata;
/**
- * Return {@code true} if this parameter was declared with the 'const' modifier.
- * @return {@code true} if this parameter was declared with the 'const' modifier
+ * Return `true` if this parameter was declared with the 'const' modifier.
+ * @return `true` if this parameter was declared with the 'const' modifier
*/
- bool isConst();
+ bool get isConst;
/**
- * Return {@code true} if this parameter was declared with the 'final' modifier. Parameters that
- * are declared with the 'const' modifier will return {@code false} even though they are
+ * Return `true` if this parameter was declared with the 'final' modifier. Parameters that
+ * are declared with the 'const' modifier will return `false` even though they are
* implicitly final.
- * @return {@code true} if this parameter was declared with the 'final' modifier
+ * @return `true` if this parameter was declared with the 'final' modifier
*/
- bool isFinal();
+ bool get isFinal;
/**
* Set the documentation comment associated with this parameter to the given comment
@@ -9322,8 +9322,8 @@
}
/**
- * Return {@code true} if the comment is lexically before any annotations.
- * @return {@code true} if the comment is lexically before any annotations
+ * Return `true` if the comment is lexically before any annotations.
+ * @return `true` if the comment is lexically before any annotations
*/
bool commentIsBeforeAnnotations() {
if (_comment == null || _metadata.isEmpty) {
@@ -9349,7 +9349,7 @@
}
}
/**
- * Instances of the class {@code NullLiteral} represent a null literal expression.
+ * Instances of the class `NullLiteral` represent a null literal expression.
* <pre>
* nullLiteral ::=
* 'null'
@@ -9397,10 +9397,10 @@
}
}
/**
- * Instances of the class {@code ParenthesizedExpression} represent a parenthesized expression.
+ * Instances of the class `ParenthesizedExpression` represent a parenthesized expression.
* <pre>
* parenthesizedExpression ::=
- * '(' {@link Expression expression} ')'
+ * '(' [Expression expression] ')'
* </pre>
* @coverage dart.engine.ast
*/
@@ -9490,9 +9490,9 @@
}
}
/**
- * Instances of the class {@code PartDirective} represent a part directive.
+ * Instances of the class `PartDirective` represent a part directive.
* <pre>
- * partDirective ::={@link Annotation metadata} 'part' {@link StringLiteral partUri} ';'
+ * partDirective ::=[Annotation metadata] 'part' [StringLiteral partUri] ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -9565,9 +9565,9 @@
Token get firstTokenAfterCommentAndMetadata => _partToken;
}
/**
- * Instances of the class {@code PartOfDirective} represent a part-of directive.
+ * Instances of the class `PartOfDirective` represent a part-of directive.
* <pre>
- * partOfDirective ::={@link Annotation metadata} 'part' 'of' {@link Identifier libraryName} ';'
+ * partOfDirective ::=[Annotation metadata] 'part' 'of' [Identifier libraryName] ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -9685,9 +9685,9 @@
Token get firstTokenAfterCommentAndMetadata => _partToken;
}
/**
- * Instances of the class {@code PostfixExpression} represent a postfix unary expression.
+ * Instances of the class `PostfixExpression` represent a postfix unary expression.
* <pre>
- * postfixExpression ::={@link Expression operand} {@link Token operator}</pre>
+ * postfixExpression ::=[Expression operand] [Token operator]</pre>
* @coverage dart.engine.ast
*/
class PostfixExpression extends Expression {
@@ -9703,13 +9703,13 @@
Token _operator;
/**
- * The element associated with this the operator based on the propagated type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * The element associated with this the operator based on the propagated type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved.
*/
MethodElement _propagatedElement;
/**
- * The element associated with the operator based on the static type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * The element associated with the operator based on the static type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved.
*/
MethodElement _staticElement;
@@ -9734,7 +9734,7 @@
Token get beginToken => _operand.beginToken;
/**
- * Return the element associated with the operator based on the propagated type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * Return the element associated with the operator based on the propagated type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved. One example of the latter case is an operator that is
* not defined for the type of the operand.
* @return the element associated with the operator
@@ -9755,7 +9755,7 @@
Token get operator => _operator;
/**
- * Return the element associated with the operator based on the static type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * Return the element associated with the operator based on the static type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved. One example of the latter case is an operator that is
* not defined for the type of the operand.
* @return the element associated with the operator
@@ -9802,9 +9802,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on
* propagated type information, then return the parameter element representing the parameter to
- * which the value of the operand will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getParameterElement()}.
+ * which the value of the operand will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getParameterElement].
* @return the parameter element representing the parameter to which the value of the right
* operand will be bound
*/
@@ -9822,9 +9822,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on static
* type information, then return the parameter element representing the parameter to which the
- * value of the operand will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getStaticParameterElement()}.
+ * value of the operand will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getStaticParameterElement].
* @return the parameter element representing the parameter to which the value of the right
* operand will be bound
*/
@@ -9840,9 +9840,9 @@
}
}
/**
- * Instances of the class {@code PrefixExpression} represent a prefix unary expression.
+ * Instances of the class `PrefixExpression` represent a prefix unary expression.
* <pre>
- * prefixExpression ::={@link Token operator} {@link Expression operand}</pre>
+ * prefixExpression ::=[Token operator] [Expression operand]</pre>
* @coverage dart.engine.ast
*/
class PrefixExpression extends Expression {
@@ -9858,13 +9858,13 @@
Expression _operand;
/**
- * The element associated with the operator based on the static type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * The element associated with the operator based on the static type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved.
*/
MethodElement _staticElement;
/**
- * The element associated with the operator based on the propagated type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * The element associated with the operator based on the propagated type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved.
*/
MethodElement _propagatedElement;
@@ -9889,7 +9889,7 @@
Token get beginToken => _operator;
/**
- * Return the element associated with the operator based on the propagated type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * Return the element associated with the operator based on the propagated type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved. One example of the latter case is an operator that is
* not defined for the type of the operand.
* @return the element associated with the operator
@@ -9910,7 +9910,7 @@
Token get operator => _operator;
/**
- * Return the element associated with the operator based on the static type of the operand, or{@code null} if the AST structure has not been resolved, if the operator is not user definable,
+ * Return the element associated with the operator based on the static type of the operand, or`null` if the AST structure has not been resolved, if the operator is not user definable,
* or if the operator could not be resolved. One example of the latter case is an operator that is
* not defined for the type of the operand.
* @return the element associated with the operator
@@ -9957,9 +9957,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on
* propagated type information, then return the parameter element representing the parameter to
- * which the value of the operand will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getParameterElement()}.
+ * which the value of the operand will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getParameterElement].
* @return the parameter element representing the parameter to which the value of the right
* operand will be bound
*/
@@ -9977,9 +9977,9 @@
/**
* If the AST structure has been resolved, and the function being invoked is known based on static
* type information, then return the parameter element representing the parameter to which the
- * value of the operand will be bound. Otherwise, return {@code null}.
- * <p>
- * This method is only intended to be used by {@link Expression#getStaticParameterElement()}.
+ * value of the operand will be bound. Otherwise, return `null`.
+ *
+ * This method is only intended to be used by [Expression#getStaticParameterElement].
* @return the parameter element representing the parameter to which the value of the right
* operand will be bound
*/
@@ -9995,11 +9995,11 @@
}
}
/**
- * Instances of the class {@code PrefixedIdentifier} represent either an identifier that is prefixed
+ * Instances of the class `PrefixedIdentifier` represent either an identifier that is prefixed
* or an access to an object property where the target of the property access is a simple
* identifier.
* <pre>
- * prefixedIdentifier ::={@link SimpleIdentifier prefix} '.' {@link SimpleIdentifier identifier}</pre>
+ * prefixedIdentifier ::=[SimpleIdentifier prefix] '.' [SimpleIdentifier identifier]</pre>
* @coverage dart.engine.ast
*/
class PrefixedIdentifier extends Identifier {
@@ -10103,12 +10103,12 @@
}
}
/**
- * Instances of the class {@code PropertyAccess} represent the access of a property of an object.
- * <p>
- * Note, however, that accesses to properties of objects can also be represented as{@link PrefixedIdentifier prefixed identifier} nodes in cases where the target is also a simple
+ * Instances of the class `PropertyAccess` represent the access of a property of an object.
+ *
+ * Note, however, that accesses to properties of objects can also be represented as[PrefixedIdentifier prefixed identifier] nodes in cases where the target is also a simple
* identifier.
* <pre>
- * propertyAccess ::={@link Expression target} '.' {@link SimpleIdentifier propertyName}</pre>
+ * propertyAccess ::=[Expression target] '.' [SimpleIdentifier propertyName]</pre>
* @coverage dart.engine.ast
*/
class PropertyAccess extends Expression {
@@ -10170,14 +10170,14 @@
/**
* Return the expression used to compute the receiver of the invocation. If this invocation is not
- * part of a cascade expression, then this is the same as {@link #getTarget()}. If this invocation
+ * part of a cascade expression, then this is the same as [getTarget]. If this invocation
* is part of a cascade expression, then the target stored with the cascade expression is
* returned.
* @return the expression used to compute the receiver of the invocation
* @see #getTarget()
*/
Expression get realTarget {
- if (isCascaded()) {
+ if (isCascaded) {
ASTNode ancestor = parent;
while (ancestor is! CascadeExpression) {
if (ancestor == null) {
@@ -10191,19 +10191,19 @@
}
/**
- * Return the expression computing the object defining the property being accessed, or{@code null} if this property access is part of a cascade expression.
+ * Return the expression computing the object defining the property being accessed, or`null` if this property access is part of a cascade expression.
* @return the expression computing the object defining the property being accessed
* @see #getRealTarget()
*/
Expression get target => _target;
- bool isAssignable() => true;
+ bool get isAssignable => true;
/**
- * Return {@code true} if this expression is cascaded. If it is, then the target of this
- * expression is not stored locally but is stored in the nearest ancestor that is a{@link CascadeExpression}.
- * @return {@code true} if this expression is cascaded
+ * Return `true` if this expression is cascaded. If it is, then the target of this
+ * expression is not stored locally but is stored in the nearest ancestor that is a[CascadeExpression].
+ * @return `true` if this expression is cascaded
*/
- bool isCascaded() => _operator != null && identical(_operator.type, TokenType.PERIOD_PERIOD);
+ bool get isCascaded => _operator != null && identical(_operator.type, TokenType.PERIOD_PERIOD);
/**
* Set the property access operator to the given token.
@@ -10235,7 +10235,7 @@
}
}
/**
- * Instances of the class {@code RedirectingConstructorInvocation} represent the invocation of a
+ * Instances of the class `RedirectingConstructorInvocation` represent the invocation of a
* another constructor in the same class from within a constructor's initialization list.
* <pre>
* redirectingConstructorInvocation ::=
@@ -10251,12 +10251,12 @@
Token _keyword;
/**
- * The token for the period before the name of the constructor that is being invoked, or{@code null} if the unnamed constructor is being invoked.
+ * The token for the period before the name of the constructor that is being invoked, or`null` if the unnamed constructor is being invoked.
*/
Token _period;
/**
- * The name of the constructor that is being invoked, or {@code null} if the unnamed constructor
+ * The name of the constructor that is being invoked, or `null` if the unnamed constructor
* is being invoked.
*/
SimpleIdentifier _constructorName;
@@ -10267,12 +10267,12 @@
ArgumentList _argumentList;
/**
- * The element associated with the constructor based on static type information, or {@code null}if the AST structure has not been resolved or if the constructor could not be resolved.
+ * The element associated with the constructor based on static type information, or `null`if the AST structure has not been resolved or if the constructor could not be resolved.
*/
ConstructorElement _staticElement;
/**
- * The element associated with the constructor based on propagated type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * The element associated with the constructor based on propagated type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
*/
ConstructorElement _propagatedElement;
@@ -10311,14 +10311,14 @@
Token get beginToken => _keyword;
/**
- * Return the name of the constructor that is being invoked, or {@code null} if the unnamed
+ * Return the name of the constructor that is being invoked, or `null` if the unnamed
* constructor is being invoked.
* @return the name of the constructor that is being invoked
*/
SimpleIdentifier get constructorName => _constructorName;
/**
- * Return the element associated with the constructor based on propagated type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * Return the element associated with the constructor based on propagated type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
* @return the element associated with the super constructor
*/
@@ -10332,13 +10332,13 @@
Token get keyword => _keyword;
/**
- * Return the token for the period before the name of the constructor that is being invoked, or{@code null} if the unnamed constructor is being invoked.
+ * Return the token for the period before the name of the constructor that is being invoked, or`null` if the unnamed constructor is being invoked.
* @return the token for the period before the name of the constructor that is being invoked
*/
Token get period => _period;
/**
- * Return the element associated with the constructor based on static type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * Return the element associated with the constructor based on static type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
* @return the element associated with the constructor
*/
@@ -10400,7 +10400,7 @@
}
}
/**
- * Instances of the class {@code RethrowExpression} represent a rethrow expression.
+ * Instances of the class `RethrowExpression` represent a rethrow expression.
* <pre>
* rethrowExpression ::=
* 'rethrow'
@@ -10448,10 +10448,10 @@
}
}
/**
- * Instances of the class {@code ReturnStatement} represent a return statement.
+ * Instances of the class `ReturnStatement` represent a return statement.
* <pre>
* returnStatement ::=
- * 'return' {@link Expression expression}? ';'
+ * 'return' [Expression expression]? ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -10463,7 +10463,7 @@
Token _keyword;
/**
- * The expression computing the value to be returned, or {@code null} if no explicit value was
+ * The expression computing the value to be returned, or `null` if no explicit value was
* provided.
*/
Expression _expression;
@@ -10497,7 +10497,7 @@
Token get endToken => _semicolon;
/**
- * Return the expression computing the value to be returned, or {@code null} if no explicit value
+ * Return the expression computing the value to be returned, or `null` if no explicit value
* was provided.
* @return the expression computing the value to be returned
*/
@@ -10543,7 +10543,7 @@
}
}
/**
- * Instances of the class {@code ScriptTag} represent the script tag that can optionally occur at
+ * Instances of the class `ScriptTag` represent the script tag that can optionally occur at
* the beginning of a compilation unit.
* <pre>
* scriptTag ::=
@@ -10592,11 +10592,11 @@
}
}
/**
- * Instances of the class {@code ShowCombinator} represent a combinator that restricts the names
+ * Instances of the class `ShowCombinator` represent a combinator that restricts the names
* being imported to those in a given list.
* <pre>
* showCombinator ::=
- * 'show' {@link SimpleIdentifier identifier} (',' {@link SimpleIdentifier identifier})
+ * 'show' [SimpleIdentifier identifier] (',' [SimpleIdentifier identifier])
* </pre>
* @coverage dart.engine.ast
*/
@@ -10636,22 +10636,22 @@
}
}
/**
- * Instances of the class {@code SimpleFormalParameter} represent a simple formal parameter.
+ * Instances of the class `SimpleFormalParameter` represent a simple formal parameter.
* <pre>
* simpleFormalParameter ::=
- * ('final' {@link TypeName type} | 'var' | {@link TypeName type})? {@link SimpleIdentifier identifier}</pre>
+ * ('final' [TypeName type] | 'var' | [TypeName type])? [SimpleIdentifier identifier]</pre>
* @coverage dart.engine.ast
*/
class SimpleFormalParameter extends NormalFormalParameter {
/**
- * The token representing either the 'final', 'const' or 'var' keyword, or {@code null} if no
+ * The token representing either the 'final', 'const' or 'var' keyword, or `null` if no
* keyword was used.
*/
Token _keyword;
/**
- * The name of the declared type of the parameter, or {@code null} if the parameter does not have
+ * The name of the declared type of the parameter, or `null` if the parameter does not have
* a declared type.
*/
TypeName _type;
@@ -10696,13 +10696,13 @@
Token get keyword => _keyword;
/**
- * Return the name of the declared type of the parameter, or {@code null} if the parameter does
+ * Return the name of the declared type of the parameter, or `null` if the parameter does
* not have a declared type.
* @return the name of the declared type of the parameter
*/
TypeName get type => _type;
- bool isConst() => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
- bool isFinal() => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
+ bool get isConst => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
+ bool get isFinal => (_keyword is KeywordToken) && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
/**
* Set the token representing either the 'final', 'const' or 'var' keyword to the given token.
@@ -10726,7 +10726,7 @@
}
}
/**
- * Instances of the class {@code SimpleIdentifier} represent a simple identifier.
+ * Instances of the class `SimpleIdentifier` represent a simple identifier.
* <pre>
* simpleIdentifier ::=
* initialCharacter internalCharacter
@@ -10743,12 +10743,12 @@
Token _token;
/**
- * The element associated with this identifier based on static type information, or {@code null}if the AST structure has not been resolved or if this identifier could not be resolved.
+ * The element associated with this identifier based on static type information, or `null`if the AST structure has not been resolved or if this identifier could not be resolved.
*/
Element _staticElement;
/**
- * The element associated with this identifier based on propagated type information, or{@code null} if the AST structure has not been resolved or if this identifier could not be
+ * The element associated with this identifier based on propagated type information, or`null` if the AST structure has not been resolved or if this identifier could not be
* resolved.
*/
Element _propagatedElement;
@@ -10780,8 +10780,8 @@
Token get token => _token;
/**
- * Return {@code true} if this identifier is the name being declared in a declaration.
- * @return {@code true} if this identifier is the name being declared in a declaration
+ * Return `true` if this identifier is the name being declared in a declaration.
+ * @return `true` if this identifier is the name being declared in a declaration
*/
bool inDeclarationContext() {
ASTNode parent = this.parent;
@@ -10813,11 +10813,11 @@
}
/**
- * Return {@code true} if this expression is computing a right-hand value.
- * <p>
- * Note that {@link #inGetterContext()} and {@link #inSetterContext()} are not opposites, nor are
- * they mutually exclusive. In other words, it is possible for both methods to return {@code true}when invoked on the same node.
- * @return {@code true} if this expression is in a context where a getter will be invoked
+ * Return `true` if this expression is computing a right-hand value.
+ *
+ * Note that [inGetterContext] and [inSetterContext] are not opposites, nor are
+ * they mutually exclusive. In other words, it is possible for both methods to return `true`when invoked on the same node.
+ * @return `true` if this expression is in a context where a getter will be invoked
*/
bool inGetterContext() {
ASTNode parent = this.parent;
@@ -10850,11 +10850,11 @@
}
/**
- * Return {@code true} if this expression is computing a left-hand value.
- * <p>
- * Note that {@link #inGetterContext()} and {@link #inSetterContext()} are not opposites, nor are
- * they mutually exclusive. In other words, it is possible for both methods to return {@code true}when invoked on the same node.
- * @return {@code true} if this expression is in a context where a setter will be invoked
+ * Return `true` if this expression is computing a left-hand value.
+ *
+ * Note that [inGetterContext] and [inSetterContext] are not opposites, nor are
+ * they mutually exclusive. In other words, it is possible for both methods to return `true`when invoked on the same node.
+ * @return `true` if this expression is in a context where a setter will be invoked
*/
bool inSetterContext() {
ASTNode parent = this.parent;
@@ -10875,7 +10875,7 @@
target = access;
}
if (parent is PrefixExpression) {
- return ((parent as PrefixExpression)).operator.type.isIncrementOperator();
+ return ((parent as PrefixExpression)).operator.type.isIncrementOperator;
} else if (parent is PostfixExpression) {
return true;
} else if (parent is AssignmentExpression) {
@@ -10883,7 +10883,7 @@
}
return false;
}
- bool isSynthetic() => _token.isSynthetic();
+ bool get isSynthetic => _token.isSynthetic;
/**
* Set the element associated with this identifier based on propagated type information to the
@@ -10914,7 +10914,7 @@
}
}
/**
- * Instances of the class {@code SimpleStringLiteral} represent a string literal expression that
+ * Instances of the class `SimpleStringLiteral` represent a string literal expression that
* does not contain any interpolations.
* <pre>
* simpleStringLiteral ::=
@@ -10979,10 +10979,10 @@
String get value => _value;
/**
- * Return {@code true} if this string literal is a multi-line string.
- * @return {@code true} if this string literal is a multi-line string
+ * Return `true` if this string literal is a multi-line string.
+ * @return `true` if this string literal is a multi-line string
*/
- bool isMultiline() {
+ bool get isMultiline {
if (_value.length < 6) {
return false;
}
@@ -10990,11 +10990,11 @@
}
/**
- * Return {@code true} if this string literal is a raw string.
- * @return {@code true} if this string literal is a raw string
+ * Return `true` if this string literal is a raw string.
+ * @return `true` if this string literal is a raw string
*/
- bool isRaw() => _value.codeUnitAt(0) == 0x40;
- bool isSynthetic() => _literal.isSynthetic();
+ bool get isRaw => _value.codeUnitAt(0) == 0x40;
+ bool get isSynthetic => _literal.isSynthetic;
/**
* Set the token representing the literal to the given token.
@@ -11018,20 +11018,20 @@
}
}
/**
- * Instances of the class {@code Statement} defines the behavior common to nodes that represent a
+ * Instances of the class `Statement` defines the behavior common to nodes that represent a
* statement.
* <pre>
- * statement ::={@link Block block}| {@link VariableDeclarationStatement initializedVariableDeclaration ';'}| {@link ForStatement forStatement}| {@link ForEachStatement forEachStatement}| {@link WhileStatement whileStatement}| {@link DoStatement doStatement}| {@link SwitchStatement switchStatement}| {@link IfStatement ifStatement}| {@link TryStatement tryStatement}| {@link BreakStatement breakStatement}| {@link ContinueStatement continueStatement}| {@link ReturnStatement returnStatement}| {@link ExpressionStatement expressionStatement}| {@link FunctionDeclarationStatement functionSignature functionBody}</pre>
+ * statement ::=[Block block]| [VariableDeclarationStatement initializedVariableDeclaration ';']| [ForStatement forStatement]| [ForEachStatement forEachStatement]| [WhileStatement whileStatement]| [DoStatement doStatement]| [SwitchStatement switchStatement]| [IfStatement ifStatement]| [TryStatement tryStatement]| [BreakStatement breakStatement]| [ContinueStatement continueStatement]| [ReturnStatement returnStatement]| [ExpressionStatement expressionStatement]| [FunctionDeclarationStatement functionSignature functionBody]</pre>
* @coverage dart.engine.ast
*/
abstract class Statement extends ASTNode {
}
/**
- * Instances of the class {@code StringInterpolation} represent a string interpolation literal.
+ * Instances of the class `StringInterpolation` represent a string interpolation literal.
* <pre>
* stringInterpolation ::=
- * ''' {@link InterpolationElement interpolationElement}* '''
- * | '"' {@link InterpolationElement interpolationElement}* '"'
+ * ''' [InterpolationElement interpolationElement]* '''
+ * | '"' [InterpolationElement interpolationElement]* '"'
* </pre>
* @coverage dart.engine.ast
*/
@@ -11073,15 +11073,15 @@
}
}
/**
- * Instances of the class {@code StringLiteral} represent a string literal expression.
+ * Instances of the class `StringLiteral` represent a string literal expression.
* <pre>
- * stringLiteral ::={@link SimpleStringLiteral simpleStringLiteral}| {@link AdjacentStrings adjacentStrings}| {@link StringInterpolation stringInterpolation}</pre>
+ * stringLiteral ::=[SimpleStringLiteral simpleStringLiteral]| [AdjacentStrings adjacentStrings]| [StringInterpolation stringInterpolation]</pre>
* @coverage dart.engine.ast
*/
abstract class StringLiteral extends Literal {
/**
- * Return the value of the string literal, or {@code null} if the string is not a constant string
+ * Return the value of the string literal, or `null` if the string is not a constant string
* without any string interpolation.
* @return the value of the string literal
*/
@@ -11104,11 +11104,11 @@
void appendStringValue(JavaStringBuilder builder);
}
/**
- * Instances of the class {@code SuperConstructorInvocation} represent the invocation of a
+ * Instances of the class `SuperConstructorInvocation` represent the invocation of a
* superclass' constructor from within a constructor's initialization list.
* <pre>
* superInvocation ::=
- * 'super' ('.' {@link SimpleIdentifier name})? {@link ArgumentList argumentList}</pre>
+ * 'super' ('.' [SimpleIdentifier name])? [ArgumentList argumentList]</pre>
* @coverage dart.engine.ast
*/
class SuperConstructorInvocation extends ConstructorInitializer {
@@ -11119,12 +11119,12 @@
Token _keyword;
/**
- * The token for the period before the name of the constructor that is being invoked, or{@code null} if the unnamed constructor is being invoked.
+ * The token for the period before the name of the constructor that is being invoked, or`null` if the unnamed constructor is being invoked.
*/
Token _period;
/**
- * The name of the constructor that is being invoked, or {@code null} if the unnamed constructor
+ * The name of the constructor that is being invoked, or `null` if the unnamed constructor
* is being invoked.
*/
SimpleIdentifier _constructorName;
@@ -11135,12 +11135,12 @@
ArgumentList _argumentList;
/**
- * The element associated with the constructor based on static type information, or {@code null}if the AST structure has not been resolved or if the constructor could not be resolved.
+ * The element associated with the constructor based on static type information, or `null`if the AST structure has not been resolved or if the constructor could not be resolved.
*/
ConstructorElement _staticElement;
/**
- * The element associated with the constructor based on propagated type information, or {@code null} if the AST structure has not been
+ * The element associated with the constructor based on propagated type information, or `null` if the AST structure has not been
* resolved or if the constructor could not be resolved.
*/
ConstructorElement _propagatedElement;
@@ -11179,14 +11179,14 @@
Token get beginToken => _keyword;
/**
- * Return the name of the constructor that is being invoked, or {@code null} if the unnamed
+ * Return the name of the constructor that is being invoked, or `null` if the unnamed
* constructor is being invoked.
* @return the name of the constructor that is being invoked
*/
SimpleIdentifier get constructorName => _constructorName;
/**
- * Return the element associated with the constructor based on propagated type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * Return the element associated with the constructor based on propagated type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
* @return the element associated with the super constructor
*/
@@ -11200,13 +11200,13 @@
Token get keyword => _keyword;
/**
- * Return the token for the period before the name of the constructor that is being invoked, or{@code null} if the unnamed constructor is being invoked.
+ * Return the token for the period before the name of the constructor that is being invoked, or`null` if the unnamed constructor is being invoked.
* @return the token for the period before the name of the constructor that is being invoked
*/
Token get period => _period;
/**
- * Return the element associated with the constructor based on static type information, or{@code null} if the AST structure has not been resolved or if the constructor could not be
+ * Return the element associated with the constructor based on static type information, or`null` if the AST structure has not been resolved or if the constructor could not be
* resolved.
* @return the element associated with the constructor
*/
@@ -11268,7 +11268,7 @@
}
}
/**
- * Instances of the class {@code SuperExpression} represent a super expression.
+ * Instances of the class `SuperExpression` represent a super expression.
* <pre>
* superExpression ::=
* 'super'
@@ -11316,9 +11316,9 @@
}
}
/**
- * Instances of the class {@code SwitchCase} represent the case in a switch statement.
+ * Instances of the class `SwitchCase` represent the case in a switch statement.
* <pre>
- * switchCase ::={@link SimpleIdentifier label}* 'case' {@link Expression expression} ':' {@link Statement statement}</pre>
+ * switchCase ::=[SimpleIdentifier label]* 'case' [Expression expression] ':' [Statement statement]</pre>
* @coverage dart.engine.ast
*/
class SwitchCase extends SwitchMember {
@@ -11371,9 +11371,9 @@
}
}
/**
- * Instances of the class {@code SwitchDefault} represent the default case in a switch statement.
+ * Instances of the class `SwitchDefault` represent the default case in a switch statement.
* <pre>
- * switchDefault ::={@link SimpleIdentifier label}* 'default' ':' {@link Statement statement}</pre>
+ * switchDefault ::=[SimpleIdentifier label]* 'default' ':' [Statement statement]</pre>
* @coverage dart.engine.ast
*/
class SwitchDefault extends SwitchMember {
@@ -11403,7 +11403,7 @@
}
}
/**
- * The abstract class {@code SwitchMember} defines the behavior common to objects representing
+ * The abstract class `SwitchMember` defines the behavior common to objects representing
* elements within a switch statement.
* <pre>
* switchMember ::=
@@ -11512,10 +11512,10 @@
}
}
/**
- * Instances of the class {@code SwitchStatement} represent a switch statement.
+ * Instances of the class `SwitchStatement` represent a switch statement.
* <pre>
* switchStatement ::=
- * 'switch' '(' {@link Expression expression} ')' '{' {@link SwitchCase switchCase}* {@link SwitchDefault defaultCase}? '}'
+ * 'switch' '(' [Expression expression] ')' '{' [SwitchCase switchCase]* [SwitchDefault defaultCase]? '}'
* </pre>
* @coverage dart.engine.ast
*/
@@ -11688,7 +11688,7 @@
}
}
/**
- * Instances of the class {@code ThisExpression} represent a this expression.
+ * Instances of the class `ThisExpression` represent a this expression.
* <pre>
* thisExpression ::=
* 'this'
@@ -11736,10 +11736,10 @@
}
}
/**
- * Instances of the class {@code ThrowExpression} represent a throw expression.
+ * Instances of the class `ThrowExpression` represent a throw expression.
* <pre>
* throwExpression ::=
- * 'throw' {@link Expression expression}</pre>
+ * 'throw' [Expression expression]</pre>
* @coverage dart.engine.ast
*/
class ThrowExpression extends Expression {
@@ -11811,7 +11811,7 @@
}
}
/**
- * Instances of the class {@code TopLevelVariableDeclaration} represent the declaration of one or
+ * Instances of the class `TopLevelVariableDeclaration` represent the declaration of one or
* more top-level variables of the same type.
* <pre>
* topLevelVariableDeclaration ::=
@@ -11890,12 +11890,12 @@
Token get firstTokenAfterCommentAndMetadata => _variableList.beginToken;
}
/**
- * Instances of the class {@code TryStatement} represent a try statement.
+ * Instances of the class `TryStatement` represent a try statement.
* <pre>
* tryStatement ::=
- * 'try' {@link Block block} ({@link CatchClause catchClause}+ finallyClause? | finallyClause)
+ * 'try' [Block block] ([CatchClause catchClause]+ finallyClause? | finallyClause)
* finallyClause ::=
- * 'finally' {@link Block block}</pre>
+ * 'finally' [Block block]</pre>
* @coverage dart.engine.ast
*/
class TryStatement extends Statement {
@@ -11916,13 +11916,13 @@
NodeList<CatchClause> _catchClauses;
/**
- * The token representing the 'finally' keyword, or {@code null} if the statement does not contain
+ * The token representing the 'finally' keyword, or `null` if the statement does not contain
* a finally clause.
*/
Token _finallyKeyword;
/**
- * The finally clause contained in the try statement, or {@code null} if the statement does not
+ * The finally clause contained in the try statement, or `null` if the statement does not
* contain a finally clause.
*/
Block _finallyClause;
@@ -11979,14 +11979,14 @@
}
/**
- * Return the finally clause contained in the try statement, or {@code null} if the statement does
+ * Return the finally clause contained in the try statement, or `null` if the statement does
* not contain a finally clause.
* @return the finally clause contained in the try statement
*/
Block get finallyClause => _finallyClause;
/**
- * Return the token representing the 'finally' keyword, or {@code null} if the statement does not
+ * Return the token representing the 'finally' keyword, or `null` if the statement does not
* contain a finally clause.
* @return the token representing the 'finally' keyword
*/
@@ -12036,7 +12036,7 @@
}
}
/**
- * The abstract class {@code TypeAlias} defines the behavior common to declarations of type aliases.
+ * The abstract class `TypeAlias` defines the behavior common to declarations of type aliases.
* <pre>
* typeAlias ::=
* 'typedef' typeAliasBody
@@ -12110,7 +12110,7 @@
Token get firstTokenAfterCommentAndMetadata => _keyword;
}
/**
- * Instances of the class {@code TypeArgumentList} represent a list of type arguments.
+ * Instances of the class `TypeArgumentList` represent a list of type arguments.
* <pre>
* typeArguments ::=
* '<' typeName (',' typeName)* '>'
@@ -12196,10 +12196,10 @@
}
}
/**
- * Instances of the class {@code TypeName} represent the name of a type, which can optionally
+ * Instances of the class `TypeName` represent the name of a type, which can optionally
* include type arguments.
* <pre>
- * typeName ::={@link Identifier identifier} typeArguments?
+ * typeName ::=[Identifier identifier] typeArguments?
* </pre>
* @coverage dart.engine.ast
*/
@@ -12211,19 +12211,19 @@
Identifier _name;
/**
- * The type arguments associated with the type, or {@code null} if there are no type arguments.
+ * The type arguments associated with the type, or `null` if there are no type arguments.
*/
TypeArgumentList _typeArguments;
/**
- * The type being named, or {@code null} if the AST structure has not been resolved.
+ * The type being named, or `null` if the AST structure has not been resolved.
*/
Type2 _type;
/**
* Initialize a newly created type name.
* @param name the name of the type
- * @param typeArguments the type arguments associated with the type, or {@code null} if there are
+ * @param typeArguments the type arguments associated with the type, or `null` if there are
* no type arguments
*/
TypeName.full(Identifier name, TypeArgumentList typeArguments) {
@@ -12234,7 +12234,7 @@
/**
* Initialize a newly created type name.
* @param name the name of the type
- * @param typeArguments the type arguments associated with the type, or {@code null} if there are
+ * @param typeArguments the type arguments associated with the type, or `null` if there are
* no type arguments
*/
TypeName({Identifier name, TypeArgumentList typeArguments}) : this.full(name, typeArguments);
@@ -12254,18 +12254,18 @@
Identifier get name => _name;
/**
- * Return the type being named, or {@code null} if the AST structure has not been resolved.
+ * Return the type being named, or `null` if the AST structure has not been resolved.
* @return the type being named
*/
Type2 get type => _type;
/**
- * Return the type arguments associated with the type, or {@code null} if there are no type
+ * Return the type arguments associated with the type, or `null` if there are no type
* arguments.
* @return the type arguments associated with the type
*/
TypeArgumentList get typeArguments => _typeArguments;
- bool isSynthetic() => _name.isSynthetic() && _typeArguments == null;
+ bool get isSynthetic => _name.isSynthetic && _typeArguments == null;
/**
* Set the name of the type to the given identifier.
@@ -12296,9 +12296,9 @@
}
}
/**
- * Instances of the class {@code TypeParameter} represent a type parameter.
+ * Instances of the class `TypeParameter` represent a type parameter.
* <pre>
- * typeParameter ::={@link SimpleIdentifier name} ('extends' {@link TypeName bound})?
+ * typeParameter ::=[SimpleIdentifier name] ('extends' [TypeName bound])?
* </pre>
* @coverage dart.engine.ast
*/
@@ -12310,13 +12310,13 @@
SimpleIdentifier _name;
/**
- * The token representing the 'extends' keyword, or {@code null} if there was no explicit upper
+ * The token representing the 'extends' keyword, or `null` if there was no explicit upper
* bound.
*/
Token _keyword;
/**
- * The name of the upper bound for legal arguments, or {@code null} if there was no explicit upper
+ * The name of the upper bound for legal arguments, or `null` if there was no explicit upper
* bound.
*/
TypeName _bound;
@@ -12347,7 +12347,7 @@
accept(ASTVisitor visitor) => visitor.visitTypeParameter(this);
/**
- * Return the name of the upper bound for legal arguments, or {@code null} if there was no
+ * Return the name of the upper bound for legal arguments, or `null` if there was no
* explicit upper bound.
* @return the name of the upper bound for legal arguments
*/
@@ -12403,10 +12403,10 @@
Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
}
/**
- * Instances of the class {@code TypeParameterList} represent type parameters within a declaration.
+ * Instances of the class `TypeParameterList` represent type parameters within a declaration.
* <pre>
* typeParameterList ::=
- * '<' {@link TypeParameter typeParameter} (',' {@link TypeParameter typeParameter})* '>'
+ * '<' [TypeParameter typeParameter] (',' [TypeParameter typeParameter])* '>'
* </pre>
* @coverage dart.engine.ast
*/
@@ -12473,22 +12473,22 @@
}
}
/**
- * The abstract class {@code TypedLiteral} defines the behavior common to literals that have a type
+ * The abstract class `TypedLiteral` defines the behavior common to literals that have a type
* associated with them.
* <pre>
- * listLiteral ::={@link ListLiteral listLiteral}| {@link MapLiteral mapLiteral}</pre>
+ * listLiteral ::=[ListLiteral listLiteral]| [MapLiteral mapLiteral]</pre>
* @coverage dart.engine.ast
*/
abstract class TypedLiteral extends Literal {
/**
- * The const modifier associated with this literal, or {@code null} if the literal is not a
+ * The const modifier associated with this literal, or `null` if the literal is not a
* constant.
*/
Token _modifier;
/**
- * The type argument associated with this literal, or {@code null} if no type arguments were
+ * The type argument associated with this literal, or `null` if no type arguments were
* declared.
*/
TypeArgumentList _typeArguments;
@@ -12496,7 +12496,7 @@
/**
* Initialize a newly created typed literal.
* @param modifier the const modifier associated with this literal
- * @param typeArguments the type argument associated with this literal, or {@code null} if no type
+ * @param typeArguments the type argument associated with this literal, or `null` if no type
* arguments were declared
*/
TypedLiteral.full(Token modifier, TypeArgumentList typeArguments) {
@@ -12507,7 +12507,7 @@
/**
* Initialize a newly created typed literal.
* @param modifier the const modifier associated with this literal
- * @param typeArguments the type argument associated with this literal, or {@code null} if no type
+ * @param typeArguments the type argument associated with this literal, or `null` if no type
* arguments were declared
*/
TypedLiteral({Token modifier, TypeArgumentList typeArguments}) : this.full(modifier, typeArguments);
@@ -12519,7 +12519,7 @@
Token get modifier => _modifier;
/**
- * Return the type argument associated with this literal, or {@code null} if no type arguments
+ * Return the type argument associated with this literal, or `null` if no type arguments
* were declared.
* @return the type argument associated with this literal
*/
@@ -12545,10 +12545,10 @@
}
}
/**
- * The abstract class {@code UriBasedDirective} defines the behavior common to nodes that represent
+ * The abstract class `UriBasedDirective` defines the behavior common to nodes that represent
* a directive that references a URI.
* <pre>
- * uriBasedDirective ::={@link ExportDirective exportDirective}| {@link ImportDirective importDirective}| {@link PartDirective partDirective}</pre>
+ * uriBasedDirective ::=[ExportDirective exportDirective]| [ImportDirective importDirective]| [PartDirective partDirective]</pre>
* @coverage dart.engine.ast
*/
abstract class UriBasedDirective extends Directive {
@@ -12583,7 +12583,7 @@
StringLiteral get uri => _uri;
/**
- * Return the element associated with the URI of this directive, or {@code null} if the AST
+ * Return the element associated with the URI of this directive, or `null` if the AST
* structure has not been resolved or if this URI could not be resolved. Examples of the latter
* case include a directive that contains an invalid URL or a URL that does not exist.
* @return the element associated with this directive
@@ -12603,10 +12603,10 @@
}
}
/**
- * Instances of the class {@code VariableDeclaration} represent an identifier that has an initial
- * value associated with it. Instances of this class are always children of the class{@link VariableDeclarationList}.
+ * Instances of the class `VariableDeclaration` represent an identifier that has an initial
+ * value associated with it. Instances of this class are always children of the class[VariableDeclarationList].
* <pre>
- * variableDeclaration ::={@link SimpleIdentifier identifier} ('=' {@link Expression initialValue})?
+ * variableDeclaration ::=[SimpleIdentifier identifier] ('=' [Expression initialValue])?
* </pre>
* @coverage dart.engine.ast
*/
@@ -12618,13 +12618,13 @@
SimpleIdentifier _name;
/**
- * The equal sign separating the variable name from the initial value, or {@code null} if the
+ * The equal sign separating the variable name from the initial value, or `null` if the
* initial value was not specified.
*/
Token _equals;
/**
- * The expression used to compute the initial value for the variable, or {@code null} if the
+ * The expression used to compute the initial value for the variable, or `null` if the
* initial value was not specified.
*/
Expression _initializer;
@@ -12679,14 +12679,14 @@
}
/**
- * Return the equal sign separating the variable name from the initial value, or {@code null} if
+ * Return the equal sign separating the variable name from the initial value, or `null` if
* the initial value was not specified.
* @return the equal sign separating the variable name from the initial value
*/
Token get equals => _equals;
/**
- * Return the expression used to compute the initial value for the variable, or {@code null} if
+ * Return the expression used to compute the initial value for the variable, or `null` if
* the initial value was not specified.
* @return the expression used to compute the initial value for the variable
*/
@@ -12699,23 +12699,23 @@
SimpleIdentifier get name => _name;
/**
- * Return {@code true} if this variable was declared with the 'const' modifier.
- * @return {@code true} if this variable was declared with the 'const' modifier
+ * Return `true` if this variable was declared with the 'const' modifier.
+ * @return `true` if this variable was declared with the 'const' modifier
*/
- bool isConst() {
+ bool get isConst {
ASTNode parent = this.parent;
- return parent is VariableDeclarationList && ((parent as VariableDeclarationList)).isConst();
+ return parent is VariableDeclarationList && ((parent as VariableDeclarationList)).isConst;
}
/**
- * Return {@code true} if this variable was declared with the 'final' modifier. Variables that are
- * declared with the 'const' modifier will return {@code false} even though they are implicitly
+ * Return `true` if this variable was declared with the 'final' modifier. Variables that are
+ * declared with the 'const' modifier will return `false` even though they are implicitly
* final.
- * @return {@code true} if this variable was declared with the 'final' modifier
+ * @return `true` if this variable was declared with the 'final' modifier
*/
- bool isFinal() {
+ bool get isFinal {
ASTNode parent = this.parent;
- return parent is VariableDeclarationList && ((parent as VariableDeclarationList)).isFinal();
+ return parent is VariableDeclarationList && ((parent as VariableDeclarationList)).isFinal;
}
/**
@@ -12749,28 +12749,28 @@
Token get firstTokenAfterCommentAndMetadata => _name.beginToken;
}
/**
- * Instances of the class {@code VariableDeclarationList} represent the declaration of one or more
+ * Instances of the class `VariableDeclarationList` represent the declaration of one or more
* variables of the same type.
* <pre>
* variableDeclarationList ::=
- * finalConstVarOrType {@link VariableDeclaration variableDeclaration} (',' {@link VariableDeclaration variableDeclaration})
+ * finalConstVarOrType [VariableDeclaration variableDeclaration] (',' [VariableDeclaration variableDeclaration])
* finalConstVarOrType ::=
- * | 'final' {@link TypeName type}?
- * | 'const' {@link TypeName type}?
+ * | 'final' [TypeName type]?
+ * | 'const' [TypeName type]?
* | 'var'
- * | {@link TypeName type}</pre>
+ * | [TypeName type]</pre>
* @coverage dart.engine.ast
*/
class VariableDeclarationList extends AnnotatedNode {
/**
- * The token representing the 'final', 'const' or 'var' keyword, or {@code null} if no keyword was
+ * The token representing the 'final', 'const' or 'var' keyword, or `null` if no keyword was
* included.
*/
Token _keyword;
/**
- * The type of the variables being declared, or {@code null} if no type was provided.
+ * The type of the variables being declared, or `null` if no type was provided.
*/
TypeName _type;
@@ -12807,14 +12807,14 @@
Token get endToken => _variables.endToken;
/**
- * Return the token representing the 'final', 'const' or 'var' keyword, or {@code null} if no
+ * Return the token representing the 'final', 'const' or 'var' keyword, or `null` if no
* keyword was included.
* @return the token representing the 'final', 'const' or 'var' keyword
*/
Token get keyword => _keyword;
/**
- * Return the type of the variables being declared, or {@code null} if no type was provided.
+ * Return the type of the variables being declared, or `null` if no type was provided.
* @return the type of the variables being declared
*/
TypeName get type => _type;
@@ -12826,18 +12826,18 @@
NodeList<VariableDeclaration> get variables => _variables;
/**
- * Return {@code true} if the variables in this list were declared with the 'const' modifier.
- * @return {@code true} if the variables in this list were declared with the 'const' modifier
+ * Return `true` if the variables in this list were declared with the 'const' modifier.
+ * @return `true` if the variables in this list were declared with the 'const' modifier
*/
- bool isConst() => _keyword is KeywordToken && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
+ bool get isConst => _keyword is KeywordToken && identical(((_keyword as KeywordToken)).keyword, Keyword.CONST);
/**
- * Return {@code true} if the variables in this list were declared with the 'final' modifier.
- * Variables that are declared with the 'const' modifier will return {@code false} even though
+ * Return `true` if the variables in this list were declared with the 'final' modifier.
+ * Variables that are declared with the 'const' modifier will return `false` even though
* they are implicitly final.
- * @return {@code true} if the variables in this list were declared with the 'final' modifier
+ * @return `true` if the variables in this list were declared with the 'final' modifier
*/
- bool isFinal() => _keyword is KeywordToken && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
+ bool get isFinal => _keyword is KeywordToken && identical(((_keyword as KeywordToken)).keyword, Keyword.FINAL);
/**
* Set the token representing the 'final', 'const' or 'var' keyword to the given token.
@@ -12868,10 +12868,10 @@
}
}
/**
- * Instances of the class {@code VariableDeclarationStatement} represent a list of variables that
+ * Instances of the class `VariableDeclarationStatement` represent a list of variables that
* are being declared in a context where a statement is required.
* <pre>
- * variableDeclarationStatement ::={@link VariableDeclarationList variableList} ';'
+ * variableDeclarationStatement ::=[VariableDeclarationList variableList] ';'
* </pre>
* @coverage dart.engine.ast
*/
@@ -12939,10 +12939,10 @@
}
}
/**
- * Instances of the class {@code WhileStatement} represent a while statement.
+ * Instances of the class `WhileStatement` represent a while statement.
* <pre>
* whileStatement ::=
- * 'while' '(' {@link Expression condition} ')' {@link Statement body}</pre>
+ * 'while' '(' [Expression condition] ')' [Statement body]</pre>
* @coverage dart.engine.ast
*/
class WhileStatement extends Statement {
@@ -13077,10 +13077,10 @@
}
}
/**
- * Instances of the class {@code WithClause} represent the with clause in a class declaration.
+ * Instances of the class `WithClause` represent the with clause in a class declaration.
* <pre>
* withClause ::=
- * 'with' {@link TypeName mixin} (',' {@link TypeName mixin})
+ * 'with' [TypeName mixin] (',' [TypeName mixin])
* </pre>
* @coverage dart.engine.ast
*/
@@ -13141,9 +13141,9 @@
}
}
/**
- * Instances of the class {@code BreadthFirstVisitor} implement an AST visitor that will recursively
- * visit all of the nodes in an AST structure, similar to {@link GeneralizingASTVisitor}. This
- * visitor uses a breadth-first ordering rather than the depth-first ordering of{@link GeneralizingASTVisitor}.
+ * Instances of the class `BreadthFirstVisitor` implement an AST visitor that will recursively
+ * visit all of the nodes in an AST structure, similar to [GeneralizingASTVisitor]. This
+ * visitor uses a breadth-first ordering rather than the depth-first ordering of[GeneralizingASTVisitor].
* @coverage dart.engine.ast
*/
class BreadthFirstVisitor<R> extends GeneralizingASTVisitor<R> {
@@ -13151,7 +13151,7 @@
GeneralizingASTVisitor<Object> _childVisitor;
/**
- * Visit all nodes in the tree starting at the given {@code root} node, in depth-first order.
+ * Visit all nodes in the tree starting at the given `root` node, in depth-first order.
* @param root the root of the ASTNode tree
*/
void visitAllNodes(ASTNode root) {
@@ -13178,32 +13178,32 @@
}
}
/**
- * Instances of the class {@code ConstantEvaluator} evaluate constant expressions to produce their
+ * Instances of the class `ConstantEvaluator` evaluate constant expressions to produce their
* compile-time value. According to the Dart Language Specification: <blockquote> A constant
* expression is one of the following:
- * <ul>
- * <li>A literal number.</li>
- * <li>A literal boolean.</li>
- * <li>A literal string where any interpolated expression is a compile-time constant that evaluates
- * to a numeric, string or boolean value or to {@code null}.</li>
- * <li>{@code null}.</li>
- * <li>A reference to a static constant variable.</li>
- * <li>An identifier expression that denotes a constant variable, a class or a type variable.</li>
- * <li>A constant constructor invocation.</li>
- * <li>A constant list literal.</li>
- * <li>A constant map literal.</li>
- * <li>A simple or qualified identifier denoting a top-level function or a static method.</li>
- * <li>A parenthesized expression {@code (e)} where {@code e} is a constant expression.</li>
- * <li>An expression of one of the forms {@code identical(e1, e2)}, {@code e1 == e2},{@code e1 != e2} where {@code e1} and {@code e2} are constant expressions that evaluate to a
- * numeric, string or boolean value or to {@code null}.</li>
- * <li>An expression of one of the forms {@code !e}, {@code e1 && e2} or {@code e1 || e2}, where{@code e}, {@code e1} and {@code e2} are constant expressions that evaluate to a boolean value or
- * to {@code null}.</li>
- * <li>An expression of one of the forms {@code ~e}, {@code e1 ^ e2}, {@code e1 & e2},{@code e1 | e2}, {@code e1 >> e2} or {@code e1 << e2}, where {@code e}, {@code e1} and {@code e2}are constant expressions that evaluate to an integer value or to {@code null}.</li>
- * <li>An expression of one of the forms {@code -e}, {@code e1 + e2}, {@code e1 - e2},{@code e1 * e2}, {@code e1 / e2}, {@code e1 ~/ e2}, {@code e1 > e2}, {@code e1 < e2},{@code e1 >= e2}, {@code e1 <= e2} or {@code e1 % e2}, where {@code e}, {@code e1} and {@code e2}are constant expressions that evaluate to a numeric value or to {@code null}.</li>
- * </ul>
- * </blockquote> The values returned by instances of this class are therefore {@code null} and
- * instances of the classes {@code Boolean}, {@code BigInteger}, {@code Double}, {@code String}, and{@code DartObject}.
- * <p>
+ *
+ * * A literal number.
+ * * A literal boolean.
+ * * A literal string where any interpolated expression is a compile-time constant that evaluates
+ * to a numeric, string or boolean value or to `null`.
+ * * `null`.
+ * * A reference to a static constant variable.
+ * * An identifier expression that denotes a constant variable, a class or a type variable.
+ * * A constant constructor invocation.
+ * * A constant list literal.
+ * * A constant map literal.
+ * * A simple or qualified identifier denoting a top-level function or a static method.
+ * * A parenthesized expression `(e)` where `e` is a constant expression.
+ * * An expression of one of the forms `identical(e1, e2)`, `e1 == e2`,`e1 != e2` where `e1` and `e2` are constant expressions that evaluate to a
+ * numeric, string or boolean value or to `null`.
+ * * An expression of one of the forms `!e`, `e1 && e2` or `e1 || e2`, where`e`, `e1` and `e2` are constant expressions that evaluate to a boolean value or
+ * to `null`.
+ * * An expression of one of the forms `~e`, `e1 ^ e2`, `e1 & e2`,`e1 | e2`, `e1 >> e2` or `e1 << e2`, where `e`, `e1` and `e2`are constant expressions that evaluate to an integer value or to `null`.
+ * * An expression of one of the forms `-e`, `e1 + e2`, `e1 - e2`,`e1 * e2`, `e1 / e2`, `e1 ~/ e2`, `e1 > e2`, `e1 < e2`,`e1 >= e2`, `e1 <= e2` or `e1 % e2`, where `e`, `e1` and `e2`are constant expressions that evaluate to a numeric value or to `null`.
+ *
+ * </blockquote> The values returned by instances of this class are therefore `null` and
+ * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and`DartObject`.
+ *
* In addition, this class defines several values that can be returned to indicate various
* conditions encountered during evaluation. These are documented with the static field that define
* those values.
@@ -13449,23 +13449,23 @@
Object getConstantValue(Element element) {
if (element is FieldElement) {
FieldElement field = element as FieldElement;
- if (field.isStatic() && field.isConst()) {
+ if (field.isStatic && field.isConst) {
}
}
return NOT_A_CONSTANT;
}
}
/**
- * Instances of the class {@code ElementLocator} locate the {@link Element Dart model element}associated with a given {@link ASTNode AST node}.
+ * Instances of the class `ElementLocator` locate the [Element Dart model element]associated with a given [ASTNode AST node].
* @coverage dart.engine.ast
*/
class ElementLocator {
/**
- * Locate the {@link Element Dart model element} associated with the given {@link ASTNode AST
- * node}.
- * @param node the node (not {@code null})
- * @return the associated element, or {@code null} if none is found
+ * Locate the [Element Dart model element] associated with the given [ASTNode AST
+ * node].
+ * @param node the node (not `null`)
+ * @return the associated element, or `null` if none is found
*/
static Element locate(ASTNode node) {
ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper();
@@ -13527,15 +13527,15 @@
Element visitVariableDeclaration(VariableDeclaration node) => node.element;
}
/**
- * Instances of the class {@code GeneralizingASTVisitor} implement an AST visitor that will
- * recursively visit all of the nodes in an AST structure (like instances of the class{@link RecursiveASTVisitor}). In addition, when a node of a specific type is visited not only
+ * Instances of the class `GeneralizingASTVisitor` implement an AST visitor that will
+ * recursively visit all of the nodes in an AST structure (like instances of the class[RecursiveASTVisitor]). In addition, when a node of a specific type is visited not only
* will the visit method for that specific type of node be invoked, but additional methods for the
* superclasses of that node will also be invoked. For example, using an instance of this class to
- * visit a {@link Block} will cause the method {@link #visitBlock(Block)} to be invoked but will
- * also cause the methods {@link #visitStatement(Statement)} and {@link #visitNode(ASTNode)} to be
+ * visit a [Block] will cause the method [visitBlock] to be invoked but will
+ * also cause the methods [visitStatement] and [visitNode] to be
* subsequently invoked. This allows visitors to be written that visit all statements without
- * needing to override the visit method for each of the specific subclasses of {@link Statement}.
- * <p>
+ * needing to override the visit method for each of the specific subclasses of [Statement].
+ *
* Subclasses that override a visit method must either invoke the overridden visit method or
* explicitly invoke the more general visit method. Failure to do so will cause the visit methods
* for superclasses of the node to not be invoked and will cause the children of the visited node to
@@ -13671,9 +13671,9 @@
R visitWithClause(WithClause node) => visitNode(node);
}
/**
- * Instances of the class {@code NodeLocator} locate the {@link ASTNode AST node} associated with a
+ * Instances of the class `NodeLocator` locate the [ASTNode AST node] associated with a
* source range, given the AST structure built from the source. More specifically, they will return
- * the {@link ASTNode AST node} with the shortest length whose source range completely encompasses
+ * the [ASTNode AST node] with the shortest length whose source range completely encompasses
* the specified range.
* @coverage dart.engine.ast
*/
@@ -13690,13 +13690,13 @@
int _endOffset = 0;
/**
- * The element that was found that corresponds to the given source range, or {@code null} if there
+ * The element that was found that corresponds to the given source range, or `null` if there
* is no such element.
*/
ASTNode _foundNode;
/**
- * Initialize a newly created locator to locate one or more {@link ASTNode AST nodes} by locating
+ * Initialize a newly created locator to locate one or more [ASTNode AST nodes] by locating
* the node within an AST structure that corresponds to the given offset in the source.
* @param offset the offset used to identify the node
*/
@@ -13708,7 +13708,7 @@
}
/**
- * Initialize a newly created locator to locate one or more {@link ASTNode AST nodes} by locating
+ * Initialize a newly created locator to locate one or more [ASTNode AST nodes] by locating
* the node within an AST structure that corresponds to the given range of characters in the
* source.
* @param start the start offset of the range used to identify the node
@@ -13723,15 +13723,15 @@
}
/**
- * Return the node that was found that corresponds to the given source range, or {@code null} if
+ * Return the node that was found that corresponds to the given source range, or `null` if
* there is no such node.
* @return the node that was found
*/
ASTNode get foundNode => _foundNode;
/**
- * Search within the given AST node for an identifier representing a {@link DartElement Dart
- * element} in the specified source range. Return the element that was found, or {@code null} if
+ * Search within the given AST node for an identifier representing a [DartElement Dart
+ * element] in the specified source range. Return the element that was found, or `null` if
* no element was found.
* @param node the AST node within which to search
* @return the element that was found
@@ -13770,17 +13770,17 @@
}
}
/**
- * Instances of the class {@code NodeFoundException} are used to cancel visiting after a node has
+ * Instances of the class `NodeFoundException` are used to cancel visiting after a node has
* been found.
*/
class NodeLocator_NodeFoundException extends RuntimeException {
static int _serialVersionUID = 1;
}
/**
- * Instances of the class {@code RecursiveASTVisitor} implement an AST visitor that will recursively
+ * Instances of the class `RecursiveASTVisitor` implement an AST visitor that will recursively
* visit all of the nodes in an AST structure. For example, using an instance of this class to visit
- * a {@link Block} will also cause all of the statements in the block to be visited.
- * <p>
+ * a [Block] will also cause all of the statements in the block to be visited.
+ *
* Subclasses that override a visit method must either invoke the overridden visit method or must
* explicitly ask the visited node to visit its children. Failure to do so will cause the children
* of the visited node to not be visited.
@@ -14193,7 +14193,7 @@
}
}
/**
- * Instances of the class {@code SimpleASTVisitor} implement an AST visitor that will do nothing
+ * Instances of the class `SimpleASTVisitor` implement an AST visitor that will do nothing
* when visiting an AST node. It is intended to be a superclass for classes that use the visitor
* pattern primarily as a dispatch mechanism (and hence don't need to recursively visit a whole
* structure) and that only need to visit a small number of node types.
@@ -14303,7 +14303,7 @@
R visitWithClause(WithClause node) => null;
}
/**
- * Instances of the class {@code ToSourceVisitor} write a source representation of a visited AST
+ * Instances of the class `ToSourceVisitor` write a source representation of a visited AST
* node (and all of it's children) to a writer.
* @coverage dart.engine.ast
*/
@@ -14680,7 +14680,7 @@
return null;
}
Object visitIndexExpression(IndexExpression node) {
- if (node.isCascaded()) {
+ if (node.isCascaded) {
_writer.print("..");
} else {
visit(node.array);
@@ -14780,14 +14780,14 @@
visit5(node.propertyKeyword, " ");
visit5(node.operatorKeyword, " ");
visit(node.name);
- if (!node.isGetter()) {
+ if (!node.isGetter) {
visit(node.parameters);
}
visit4(" ", node.body);
return null;
}
Object visitMethodInvocation(MethodInvocation node) {
- if (node.isCascaded()) {
+ if (node.isCascaded) {
_writer.print("..");
} else {
visit2(node.target, ".");
@@ -14846,7 +14846,7 @@
return null;
}
Object visitPropertyAccess(PropertyAccess node) {
- if (node.isCascaded()) {
+ if (node.isCascaded) {
_writer.print("..");
} else {
visit(node.target);
@@ -15017,7 +15017,7 @@
}
/**
- * Safely visit the given node, printing the suffix after the node if it is non-{@code null}.
+ * Safely visit the given node, printing the suffix after the node if it is non-`null`.
* @param suffix the suffix to be printed if there is a node to visit
* @param node the node to be visited
*/
@@ -15029,7 +15029,7 @@
}
/**
- * Safely visit the given node, printing the prefix before the node if it is non-{@code null}.
+ * Safely visit the given node, printing the prefix before the node if it is non-`null`.
* @param prefix the prefix to be printed if there is a node to visit
* @param node the node to be visited
*/
@@ -15053,7 +15053,7 @@
}
/**
- * Safely visit the given node, printing the suffix after the node if it is non-{@code null}.
+ * Safely visit the given node, printing the suffix after the node if it is non-`null`.
* @param suffix the suffix to be printed if there is a node to visit
* @param node the node to be visited
*/
@@ -15133,7 +15133,7 @@
}
}
/**
- * Instances of the class {@code ASTCloner} implement an object that will clone any AST structure
+ * Instances of the class `ASTCloner` implement an object that will clone any AST structure
* that it visits. The cloner will only clone the structure, it will not preserve any resolution
* results or properties associated with the nodes.
*/
@@ -15155,9 +15155,9 @@
ClassDeclaration visitClassDeclaration(ClassDeclaration node) => new ClassDeclaration.full(clone2(node.documentationComment), clone3(node.metadata), node.abstractKeyword, node.classKeyword, clone2(node.name), clone2(node.typeParameters), clone2(node.extendsClause), clone2(node.withClause), clone2(node.implementsClause), node.leftBracket, clone3(node.members), node.rightBracket);
ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias.full(clone2(node.documentationComment), clone3(node.metadata), node.keyword, clone2(node.name), clone2(node.typeParameters), node.equals, node.abstractKeyword, clone2(node.superclass), clone2(node.withClause), clone2(node.implementsClause), node.semicolon);
Comment visitComment(Comment node) {
- if (node.isDocumentation()) {
+ if (node.isDocumentation) {
return Comment.createDocumentationComment2(node.tokens, clone3(node.references));
- } else if (node.isBlock()) {
+ } else if (node.isBlock) {
return Comment.createBlockComment(node.tokens);
}
return Comment.createEndOfLineComment(node.tokens);
@@ -15277,7 +15277,7 @@
* Traverse the AST from initial child node to successive parents, building a collection of local
* variable and parameter names visible to the initial child node. In case of name shadowing, the
* first name seen is the most specific one so names are not redefined.
- * <p>
+ *
* Completion test code coverage is 95%. The two basic blocks that are not executed cannot be
* executed. They are included for future reference.
* @coverage com.google.dart.engine.services.completion
diff --git a/pkg/analyzer_experimental/lib/src/generated/constant.dart b/pkg/analyzer_experimental/lib/src/generated/constant.dart
index 2b39d59..294d22c 100644
--- a/pkg/analyzer_experimental/lib/src/generated/constant.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/constant.dart
@@ -9,32 +9,32 @@
import 'element.dart';
import 'engine.dart' show AnalysisEngine;
/**
- * Instances of the class {@code ConstantEvaluator} evaluate constant expressions to produce their
+ * Instances of the class `ConstantEvaluator` evaluate constant expressions to produce their
* compile-time value. According to the Dart Language Specification: <blockquote> A constant
* expression is one of the following:
- * <ul>
- * <li>A literal number.</li>
- * <li>A literal boolean.</li>
- * <li>A literal string where any interpolated expression is a compile-time constant that evaluates
- * to a numeric, string or boolean value or to {@code null}.</li>
- * <li>{@code null}.</li>
- * <li>A reference to a static constant variable.</li>
- * <li>An identifier expression that denotes a constant variable, a class or a type variable.</li>
- * <li>A constant constructor invocation.</li>
- * <li>A constant list literal.</li>
- * <li>A constant map literal.</li>
- * <li>A simple or qualified identifier denoting a top-level function or a static method.</li>
- * <li>A parenthesized expression {@code (e)} where {@code e} is a constant expression.</li>
- * <li>An expression of one of the forms {@code identical(e1, e2)}, {@code e1 == e2},{@code e1 != e2} where {@code e1} and {@code e2} are constant expressions that evaluate to a
- * numeric, string or boolean value or to {@code null}.</li>
- * <li>An expression of one of the forms {@code !e}, {@code e1 && e2} or {@code e1 || e2}, where{@code e}, {@code e1} and {@code e2} are constant expressions that evaluate to a boolean value or
- * to {@code null}.</li>
- * <li>An expression of one of the forms {@code ~e}, {@code e1 ^ e2}, {@code e1 & e2},{@code e1 | e2}, {@code e1 >> e2} or {@code e1 << e2}, where {@code e}, {@code e1} and {@code e2}are constant expressions that evaluate to an integer value or to {@code null}.</li>
- * <li>An expression of one of the forms {@code -e}, {@code e1 + e2}, {@code e1 - e2},{@code e1 * e2}, {@code e1 / e2}, {@code e1 ~/ e2}, {@code e1 > e2}, {@code e1 < e2},{@code e1 >= e2}, {@code e1 <= e2} or {@code e1 % e2}, where {@code e}, {@code e1} and {@code e2}are constant expressions that evaluate to a numeric value or to {@code null}.</li>
- * </ul>
- * </blockquote> The values returned by instances of this class are therefore {@code null} and
- * instances of the classes {@code Boolean}, {@code BigInteger}, {@code Double}, {@code String}, and{@code DartObject}.
- * <p>
+ *
+ * * A literal number.
+ * * A literal boolean.
+ * * A literal string where any interpolated expression is a compile-time constant that evaluates
+ * to a numeric, string or boolean value or to `null`.
+ * * `null`.
+ * * A reference to a static constant variable.
+ * * An identifier expression that denotes a constant variable, a class or a type variable.
+ * * A constant constructor invocation.
+ * * A constant list literal.
+ * * A constant map literal.
+ * * A simple or qualified identifier denoting a top-level function or a static method.
+ * * A parenthesized expression `(e)` where `e` is a constant expression.
+ * * An expression of one of the forms `identical(e1, e2)`, `e1 == e2`,`e1 != e2` where `e1` and `e2` are constant expressions that evaluate to a
+ * numeric, string or boolean value or to `null`.
+ * * An expression of one of the forms `!e`, `e1 && e2` or `e1 || e2`, where`e`, `e1` and `e2` are constant expressions that evaluate to a boolean value or
+ * to `null`.
+ * * An expression of one of the forms `~e`, `e1 ^ e2`, `e1 & e2`,`e1 | e2`, `e1 >> e2` or `e1 << e2`, where `e`, `e1` and `e2`are constant expressions that evaluate to an integer value or to `null`.
+ * * An expression of one of the forms `-e`, `e1 + e2`, `e1 - e2`,`e1 * e2`, `e1 / e2`, `e1 ~/ e2`, `e1 > e2`, `e1 < e2`,`e1 >= e2`, `e1 <= e2` or `e1 % e2`, where `e`, `e1` and `e2`are constant expressions that evaluate to a numeric value or to `null`.
+ *
+ * </blockquote> The values returned by instances of this class are therefore `null` and
+ * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and`DartObject`.
+ *
* In addition, this class defines several values that can be returned to indicate various
* conditions encountered during evaluation. These are documented with the static field that define
* those values.
@@ -67,7 +67,7 @@
}
}
/**
- * Instances of the class {@code EvaluationResult} represent the result of attempting to evaluate an
+ * Instances of the class `EvaluationResult` represent the result of attempting to evaluate an
* expression.
*/
class EvaluationResult {
@@ -100,7 +100,7 @@
/**
* Initialize a newly created result object with the given state. Clients should use one of the
- * factory methods: {@link #forErrors(AnalysisError\[\])} and {@link #forValue(Object)}.
+ * factory methods: [forErrors] and [forValue].
* @param value the value of the expression
* @param errors the errors that should be reported for the expression(s) that were evaluated
*/
@@ -118,21 +118,21 @@
List<AnalysisError> get errors => _errors == null ? AnalysisError.NO_ERRORS : _errors;
/**
- * Return the value of the expression, or {@code null} if the expression evaluated to {@code null}or if the expression could not be evaluated, either because it was not a compile-time constant
+ * Return the value of the expression, or `null` if the expression evaluated to `null`or if the expression could not be evaluated, either because it was not a compile-time constant
* expression or because it would throw an exception when evaluated.
* @return the value of the expression
*/
Object get value => _value;
/**
- * Return {@code true} if the expression is a compile-time constant expression that would not
+ * Return `true` if the expression is a compile-time constant expression that would not
* throw an exception when evaluated.
- * @return {@code true} if the expression is a valid compile-time constant expression
+ * @return `true` if the expression is a valid compile-time constant expression
*/
- bool isValid() => _errors == null;
+ bool get isValid => _errors == null;
}
/**
- * Instances of the class {@code ConstantFinder} are used to traverse the AST structures of all of
+ * Instances of the class `ConstantFinder` are used to traverse the AST structures of all of
* the compilation units being resolved and build a table mapping constant variable elements to the
* declarations of those variables.
*/
@@ -151,7 +151,7 @@
Object visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
Expression initializer = node.initializer;
- if (initializer != null && node.isConst()) {
+ if (initializer != null && node.isConst) {
VariableElement element = node.element;
if (element != null) {
_variableMap[element] = node;
@@ -161,10 +161,10 @@
}
}
/**
- * Instances of the class {@code ConstantValueComputer} compute the values of constant variables in
+ * Instances of the class `ConstantValueComputer` compute the values of constant variables in
* one or more compilation units. The expected usage pattern is for the compilation units to be
- * added to this computer using the method {@link #add(CompilationUnit)} and then for the method{@link #computeValues()} to invoked exactly once. Any use of an instance after invoking the
- * method {@link #computeValues()} will result in unpredictable behavior.
+ * added to this computer using the method [add] and then for the method[computeValues] to invoked exactly once. Any use of an instance after invoking the
+ * method [computeValues] will result in unpredictable behavior.
*/
class ConstantValueComputer {
@@ -204,13 +204,13 @@
_referenceGraph.addNode(element);
entry.getValue().initializer.accept(referenceFinder);
}
- while (!_referenceGraph.isEmpty()) {
+ while (!_referenceGraph.isEmpty) {
VariableElement element = _referenceGraph.removeSink();
while (element != null) {
computeValueFor(element);
element = _referenceGraph.removeSink();
}
- if (!_referenceGraph.isEmpty()) {
+ if (!_referenceGraph.isEmpty) {
List<VariableElement> variablesInCycle = _referenceGraph.findCycle();
if (variablesInCycle == null) {
AnalysisEngine.instance.logger.logError("Exiting constant value computer with ${_referenceGraph.nodeCount} variables that are neither sinks no in a cycle");
@@ -256,29 +256,29 @@
}
}
/**
- * Instances of the class {@code ConstantVisitor} evaluate constant expressions to produce their
+ * Instances of the class `ConstantVisitor` evaluate constant expressions to produce their
* compile-time value. According to the Dart Language Specification: <blockquote> A constant
* expression is one of the following:
- * <ul>
- * <li>A literal number.</li>
- * <li>A literal boolean.</li>
- * <li>A literal string where any interpolated expression is a compile-time constant that evaluates
- * to a numeric, string or boolean value or to {@code null}.</li>
- * <li>{@code null}.</li>
- * <li>A reference to a static constant variable.</li>
- * <li>An identifier expression that denotes a constant variable, a class or a type variable.</li>
- * <li>A constant constructor invocation.</li>
- * <li>A constant list literal.</li>
- * <li>A constant map literal.</li>
- * <li>A simple or qualified identifier denoting a top-level function or a static method.</li>
- * <li>A parenthesized expression {@code (e)} where {@code e} is a constant expression.</li>
- * <li>An expression of one of the forms {@code identical(e1, e2)}, {@code e1 == e2},{@code e1 != e2} where {@code e1} and {@code e2} are constant expressions that evaluate to a
- * numeric, string or boolean value or to {@code null}.</li>
- * <li>An expression of one of the forms {@code !e}, {@code e1 && e2} or {@code e1 || e2}, where{@code e}, {@code e1} and {@code e2} are constant expressions that evaluate to a boolean value or
- * to {@code null}.</li>
- * <li>An expression of one of the forms {@code ~e}, {@code e1 ^ e2}, {@code e1 & e2},{@code e1 | e2}, {@code e1 >> e2} or {@code e1 << e2}, where {@code e}, {@code e1} and {@code e2}are constant expressions that evaluate to an integer value or to {@code null}.</li>
- * <li>An expression of one of the forms {@code -e}, {@code e1 + e2}, {@code e1 - e2},{@code e1 * e2}, {@code e1 / e2}, {@code e1 ~/ e2}, {@code e1 > e2}, {@code e1 < e2},{@code e1 >= e2}, {@code e1 <= e2} or {@code e1 % e2}, where {@code e}, {@code e1} and {@code e2}are constant expressions that evaluate to a numeric value or to {@code null}.</li>
- * </ul>
+ *
+ * * A literal number.
+ * * A literal boolean.
+ * * A literal string where any interpolated expression is a compile-time constant that evaluates
+ * to a numeric, string or boolean value or to `null`.
+ * * `null`.
+ * * A reference to a static constant variable.
+ * * An identifier expression that denotes a constant variable, a class or a type variable.
+ * * A constant constructor invocation.
+ * * A constant list literal.
+ * * A constant map literal.
+ * * A simple or qualified identifier denoting a top-level function or a static method.
+ * * A parenthesized expression `(e)` where `e` is a constant expression.
+ * * An expression of one of the forms `identical(e1, e2)`, `e1 == e2`,`e1 != e2` where `e1` and `e2` are constant expressions that evaluate to a
+ * numeric, string or boolean value or to `null`.
+ * * An expression of one of the forms `!e`, `e1 && e2` or `e1 || e2`, where`e`, `e1` and `e2` are constant expressions that evaluate to a boolean value or
+ * to `null`.
+ * * An expression of one of the forms `~e`, `e1 ^ e2`, `e1 & e2`,`e1 | e2`, `e1 >> e2` or `e1 << e2`, where `e`, `e1` and `e2`are constant expressions that evaluate to an integer value or to `null`.
+ * * An expression of one of the forms `-e`, `e1 + e2`, `e1 - e2`,`e1 * e2`, `e1 / e2`, `e1 ~/ e2`, `e1 > e2`, `e1 < e2`,`e1 >= e2`, `e1 <= e2` or `e1 % e2`, where `e`, `e1` and `e2`are constant expressions that evaluate to a numeric value or to `null`.
+ *
* </blockquote>
*/
class ConstantVisitor extends GeneralizingASTVisitor<EvaluationResultImpl> {
@@ -298,7 +298,7 @@
EvaluationResultImpl rightResult = node.rightOperand.accept(this);
TokenType operatorType = node.operator.type;
if (operatorType != TokenType.BANG_EQ && operatorType != TokenType.EQ_EQ) {
- if (leftResult is ValidResult && ((leftResult as ValidResult)).isNull() || rightResult is ValidResult && ((rightResult as ValidResult)).isNull()) {
+ if (leftResult is ValidResult && ((leftResult as ValidResult)).isNull || rightResult is ValidResult && ((rightResult as ValidResult)).isNull) {
return error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
}
@@ -350,7 +350,7 @@
EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => new ValidResult(node.value);
EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpression node) {
ConstructorElement constructor = node.element;
- if (constructor != null && constructor.isConst()) {
+ if (constructor != null && constructor.isConst) {
node.argumentList.accept(this);
return ValidResult.RESULT_OBJECT;
}
@@ -399,7 +399,7 @@
Element enclosingElement = function.enclosingElement;
if (enclosingElement is CompilationUnitElement) {
LibraryElement library = ((enclosingElement as CompilationUnitElement)).library;
- if (library.isDartCore()) {
+ if (library.isDartCore) {
EvaluationResultImpl leftArgument = arguments[0].accept(this);
EvaluationResultImpl rightArgument = arguments[1].accept(this);
return leftArgument.equalEqual(node, rightArgument);
@@ -416,7 +416,7 @@
EvaluationResultImpl visitPrefixedIdentifier(PrefixedIdentifier node) => getConstantValue(node, node.element);
EvaluationResultImpl visitPrefixExpression(PrefixExpression node) {
EvaluationResultImpl operand = node.operand.accept(this);
- if (operand is ValidResult && ((operand as ValidResult)).isNull()) {
+ if (operand is ValidResult && ((operand as ValidResult)).isNull) {
return error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
}
while (true) {
@@ -479,7 +479,7 @@
/**
* Return the union of the errors encoded in the given results.
- * @param leftResult the first set of errors, or {@code null} if there was no previous collection
+ * @param leftResult the first set of errors, or `null` if there was no previous collection
* of errors
* @param rightResult the errors to be added to the collection, or a valid result if there are no
* errors to be added
@@ -497,7 +497,7 @@
}
}
/**
- * Instances of the class {@code DirectedGraph} implement a directed graph in which the nodes are
+ * Instances of the class `DirectedGraph` implement a directed graph in which the nodes are
* arbitrary (client provided) objects and edges are represented implicitly. The graph will allow an
* edge from any node to any other node, including itself, but will not represent multiple edges
* between the same pair of nodes.
@@ -543,7 +543,7 @@
}
/**
- * Return a list of nodes that form a cycle, or {@code null} if there are no cycles in this graph.
+ * Return a list of nodes that form a cycle, or `null` if there are no cycles in this graph.
* @return a list of nodes that form a cycle
*/
List<N> findCycle() => null;
@@ -570,10 +570,10 @@
}
/**
- * Return {@code true} if this graph is empty.
- * @return {@code true} if this graph is empty
+ * Return `true` if this graph is empty.
+ * @return `true` if this graph is empty
*/
- bool isEmpty() => _edges.isEmpty;
+ bool get isEmpty => _edges.isEmpty;
/**
* Remove all of the given nodes from this graph. As a consequence, any edges for which those
@@ -592,7 +592,7 @@
* the same (neither node will either be added or removed).
* @param head the node at the head of the edge
* @param tail the node at the tail of the edge
- * @return {@code true} if the graph was modified as a result of this operation
+ * @return `true` if the graph was modified as a result of this operation
*/
void removeEdge(N head, N tail) {
Set<N> tails = _edges[head];
@@ -616,7 +616,7 @@
/**
* Find one node (referred to as a sink node) that has no outgoing edges (that is, for which there
* are no edges that have that node as the head of the edge) and remove it from this graph. Return
- * the node that was removed, or {@code null} if there are no such nodes either because the graph
+ * the node that was removed, or `null` if there are no such nodes either because the graph
* is empty or because every node in the graph has at least one outgoing edge. As a consequence of
* removing the node from the graph any edges for which that node was a tail will also be removed.
* @return the sink node that was removed
@@ -632,7 +632,7 @@
/**
* Return one node that has no outgoing edges (that is, for which there are no edges that have
- * that node as the head of the edge), or {@code null} if there are no such nodes.
+ * that node as the head of the edge), or `null` if there are no such nodes.
* @return a sink node
*/
N findSink() {
@@ -643,7 +643,7 @@
}
}
/**
- * Instances of the class {@code ErrorResult} represent the result of evaluating an expression that
+ * Instances of the class `ErrorResult` represent the result of evaluating an expression that
* is not a valid compile time constant.
*/
class ErrorResult extends EvaluationResultImpl {
@@ -687,6 +687,7 @@
EvaluationResultImpl concatenate(Expression node, EvaluationResultImpl rightOperand) => rightOperand.concatenateError(node, this);
EvaluationResultImpl divide(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.divideError(node, this);
EvaluationResultImpl equalEqual(Expression node, EvaluationResultImpl rightOperand) => rightOperand.equalEqualError(node, this);
+ bool equalValues(EvaluationResultImpl result) => false;
List<ErrorResult_ErrorData> get errorData => _errors;
EvaluationResultImpl greaterThan(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanError(node, this);
EvaluationResultImpl greaterThanOrEqual(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqualError(node, this);
@@ -781,7 +782,7 @@
ASTNode get node => _node;
}
/**
- * Instances of the class {@code InternalResult} represent the result of attempting to evaluate a
+ * Instances of the class `InternalResult` represent the result of attempting to evaluate a
* expression.
*/
abstract class EvaluationResultImpl {
@@ -793,6 +794,7 @@
EvaluationResultImpl concatenate(Expression node, EvaluationResultImpl rightOperand);
EvaluationResultImpl divide(BinaryExpression node, EvaluationResultImpl rightOperand);
EvaluationResultImpl equalEqual(Expression node, EvaluationResultImpl rightOperand);
+ bool equalValues(EvaluationResultImpl result);
EvaluationResultImpl greaterThan(BinaryExpression node, EvaluationResultImpl rightOperand);
EvaluationResultImpl greaterThanOrEqual(BinaryExpression node, EvaluationResultImpl rightOperand);
EvaluationResultImpl integerDivide(BinaryExpression node, EvaluationResultImpl rightOperand);
@@ -851,7 +853,7 @@
EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand);
}
/**
- * Instances of the class {@code ReferenceFinder} add reference information for a given variable to
+ * Instances of the class `ReferenceFinder` add reference information for a given variable to
* the bi-directional mapping used to order the evaluation of constants.
*/
class ReferenceFinder extends RecursiveASTVisitor<Object> {
@@ -885,7 +887,7 @@
}
if (element is VariableElement) {
VariableElement variable = element as VariableElement;
- if (variable.isConst()) {
+ if (variable.isConst) {
_referenceGraph.addEdge(_source, variable);
}
}
@@ -893,7 +895,7 @@
}
}
/**
- * Instances of the class {@code ValidResult} represent the result of attempting to evaluate a valid
+ * Instances of the class `ValidResult` represent the result of attempting to evaluate a valid
* compile time constant expression.
*/
class ValidResult extends EvaluationResultImpl {
@@ -916,7 +918,7 @@
static ValidResult RESULT_INT = new ValidResult(null);
/**
- * A result object representing the {@code null} value.
+ * A result object representing the `null` value.
*/
static ValidResult RESULT_NULL = new ValidResult(null);
@@ -964,7 +966,7 @@
EvaluationResultImpl add(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.addToValid(node, this);
EvaluationResultImpl bitAnd(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.bitAndValid(node, this);
EvaluationResultImpl bitNot(Expression node) {
- if (isSomeInt()) {
+ if (isSomeInt) {
return RESULT_INT;
}
if (_value == null) {
@@ -979,6 +981,7 @@
EvaluationResultImpl concatenate(Expression node, EvaluationResultImpl rightOperand) => rightOperand.concatenateValid(node, this);
EvaluationResultImpl divide(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.divideValid(node, this);
EvaluationResultImpl equalEqual(Expression node, EvaluationResultImpl rightOperand) => rightOperand.equalEqualValid(node, this);
+ bool equalValues(EvaluationResultImpl result) => identical(equalEqual(null, result), RESULT_TRUE);
Object get value => _value;
EvaluationResultImpl greaterThan(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanValid(node, this);
EvaluationResultImpl greaterThanOrEqual(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqualValid(node, this);
@@ -987,7 +990,7 @@
EvaluationResultImpl lessThanOrEqual(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualValid(node, this);
EvaluationResultImpl logicalAnd(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.logicalAndValid(node, this);
EvaluationResultImpl logicalNot(Expression node) {
- if (isSomeBool()) {
+ if (isSomeBool) {
return RESULT_BOOL;
}
if (_value == null) {
@@ -1000,7 +1003,7 @@
EvaluationResultImpl logicalOr(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.logicalOrValid(node, this);
EvaluationResultImpl minus(BinaryExpression node, EvaluationResultImpl rightOperand) => rightOperand.minusValid(node, this);
EvaluationResultImpl negated(Expression node) {
- if (isSomeNum()) {
+ if (isSomeNum) {
return RESULT_INT;
}
if (_value == null) {
@@ -1039,8 +1042,8 @@
}
EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_NUM;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1071,8 +1074,8 @@
}
EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeInt() || leftOperand2.isSomeInt()) {
- if (isAnyInt() && leftOperand2.isAnyInt()) {
+ if (isSomeInt || leftOperand2.isSomeInt) {
+ if (isAnyInt && leftOperand2.isAnyInt) {
return RESULT_INT;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
@@ -1095,8 +1098,8 @@
}
EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeInt() || leftOperand2.isSomeInt()) {
- if (isAnyInt() && leftOperand2.isAnyInt()) {
+ if (isSomeInt || leftOperand2.isSomeInt) {
+ if (isAnyInt && leftOperand2.isAnyInt) {
return RESULT_INT;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
@@ -1119,8 +1122,8 @@
}
EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeInt() || leftOperand2.isSomeInt()) {
- if (isAnyInt() && leftOperand2.isAnyInt()) {
+ if (isSomeInt || leftOperand2.isSomeInt) {
+ if (isAnyInt && leftOperand2.isAnyInt) {
return RESULT_INT;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
@@ -1151,8 +1154,8 @@
}
EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_NUM;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1183,7 +1186,7 @@
EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl equalEqualValid(Expression node, ValidResult leftOperand) {
if (node is BinaryExpression) {
- if (!isAnyNullBoolNumString() || !leftOperand.isAnyNullBoolNumString()) {
+ if (!isAnyNullBoolNumString || !leftOperand.isAnyNullBoolNumString) {
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
}
}
@@ -1220,8 +1223,8 @@
EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_BOOL;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1247,8 +1250,8 @@
return error(node);
}
EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_BOOL;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1275,8 +1278,8 @@
}
EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_INT;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1310,8 +1313,8 @@
EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_BOOL;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1337,8 +1340,8 @@
return error(node);
}
EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_BOOL;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1365,8 +1368,8 @@
}
EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl logicalAndValid(BinaryExpression node, ValidResult leftOperand) {
- if (isSomeBool() || leftOperand.isSomeBool()) {
- if (isAnyBool() && leftOperand.isAnyBool()) {
+ if (isSomeBool || leftOperand.isSomeBool) {
+ if (isAnyBool && leftOperand.isAnyBool) {
return RESULT_BOOL;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
@@ -1382,8 +1385,8 @@
}
EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl logicalOrValid(BinaryExpression node, ValidResult leftOperand) {
- if (isSomeBool() || leftOperand.isSomeBool()) {
- if (isAnyBool() && leftOperand.isAnyBool()) {
+ if (isSomeBool || leftOperand.isSomeBool) {
+ if (isAnyBool && leftOperand.isAnyBool) {
return RESULT_BOOL;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
@@ -1396,8 +1399,8 @@
}
EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_NUM;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1424,7 +1427,7 @@
}
EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl notEqualValid(BinaryExpression node, ValidResult leftOperand) {
- if (!isAnyNullBoolNumString() || !leftOperand.isAnyNullBoolNumString()) {
+ if (!isAnyNullBoolNumString || !leftOperand.isAnyNullBoolNumString) {
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
}
Object leftValue = leftOperand.value;
@@ -1459,8 +1462,8 @@
}
EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_NUM;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1490,8 +1493,8 @@
}
EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeInt() || leftOperand2.isSomeInt()) {
- if (isAnyInt() && leftOperand2.isAnyInt()) {
+ if (isSomeInt || leftOperand2.isSomeInt) {
+ if (isAnyInt && leftOperand2.isAnyInt) {
return RESULT_INT;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
@@ -1514,8 +1517,8 @@
}
EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeInt() || leftOperand2.isSomeInt()) {
- if (isAnyInt() && leftOperand2.isAnyInt()) {
+ if (isSomeInt || leftOperand2.isSomeInt) {
+ if (isAnyInt && leftOperand2.isAnyInt) {
return RESULT_INT;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
@@ -1538,8 +1541,8 @@
}
EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand) => leftOperand;
EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand2) {
- if (isSomeNum() || leftOperand2.isSomeNum()) {
- if (isAnyNum() && leftOperand2.isAnyNum()) {
+ if (isSomeNum || leftOperand2.isSomeNum) {
+ if (isAnyNum && leftOperand2.isAnyNum) {
return RESULT_NUM;
}
return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
@@ -1564,7 +1567,7 @@
}
return error(node);
}
- bool isNull() => identical(this, RESULT_NULL);
+ bool get isNull => identical(this, RESULT_NULL);
/**
* Return the result of applying boolean conversion to the given value.
@@ -1595,37 +1598,37 @@
/**
* Checks if this result has type "bool", with known or unknown value.
*/
- bool isAnyBool() => isSomeBool() || identical(this, RESULT_TRUE) || identical(this, RESULT_FALSE);
+ bool get isAnyBool => isSomeBool || identical(this, RESULT_TRUE) || identical(this, RESULT_FALSE);
/**
* Checks if this result has type "int", with known or unknown value.
*/
- bool isAnyInt() => identical(this, RESULT_INT) || _value is int;
+ bool get isAnyInt => identical(this, RESULT_INT) || _value is int;
/**
- * Checks if this result has one of the types - "bool", "num" or "string"; or may be {@code null}.
+ * Checks if this result has one of the types - "bool", "num" or "string"; or may be `null`.
*/
- bool isAnyNullBoolNumString() => isNull() || isAnyBool() || isAnyNum() || _value is String;
+ bool get isAnyNullBoolNumString => isNull || isAnyBool || isAnyNum || _value is String;
/**
* Checks if this result has type "num", with known or unknown value.
*/
- bool isAnyNum() => isSomeNum() || _value is num;
+ bool get isAnyNum => isSomeNum || _value is num;
/**
* Checks if this result has type "bool", exact value of which we don't know.
*/
- bool isSomeBool() => identical(this, RESULT_BOOL);
+ bool get isSomeBool => identical(this, RESULT_BOOL);
/**
* Checks if this result has type "int", exact value of which we don't know.
*/
- bool isSomeInt() => identical(this, RESULT_INT);
+ bool get isSomeInt => identical(this, RESULT_INT);
/**
* Checks if this result has type "num" (or "int"), exact value of which we don't know.
*/
- bool isSomeNum() => identical(this, RESULT_DYNAMIC) || identical(this, RESULT_INT) || identical(this, RESULT_NUM);
+ bool get isSomeNum => identical(this, RESULT_DYNAMIC) || identical(this, RESULT_INT) || identical(this, RESULT_NUM);
double toDouble(int value) => value.toDouble();
/**
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart
index 5cc4a23..af56601 100644
--- a/pkg/analyzer_experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -13,7 +13,7 @@
import 'constant.dart' show EvaluationResultImpl;
import 'utilities_dart.dart';
/**
- * The interface {@code ClassElement} defines the behavior of elements that represent a class.
+ * The interface `ClassElement` defines the behavior of elements that represent a class.
* @coverage dart.engine.element
*/
abstract class ClassElement implements Element {
@@ -45,7 +45,7 @@
/**
* Return the element representing the getter with the given name that is declared in this class,
- * or {@code null} if this class does not declare a getter with the given name.
+ * or `null` if this class does not declare a getter with the given name.
* @param getterName the name of the getter to be returned
* @return the getter declared in this class with the given name
*/
@@ -53,7 +53,7 @@
/**
* Return an array containing all of the interfaces that are implemented by this class.
- * <p>
+ *
* <b>Note:</b> Because the element model represents the state of the code, it is possible for it
* to be semantically invalid. In particular, it is not safe to assume that the inheritance
* structure of a class does not contain a cycle. Clients that traverse the inheritance structure
@@ -64,7 +64,7 @@
/**
* Return the element representing the method with the given name that is declared in this class,
- * or {@code null} if this class does not declare a method with the given name.
+ * or `null` if this class does not declare a method with the given name.
* @param methodName the name of the method to be returned
* @return the method declared in this class with the given name
*/
@@ -79,7 +79,7 @@
/**
* Return an array containing all of the mixins that are applied to the class being extended in
* order to derive the superclass of this class.
- * <p>
+ *
* <b>Note:</b> Because the element model represents the state of the code, it is possible for it
* to be semantically invalid. In particular, it is not safe to assume that the inheritance
* structure of a class does not contain a cycle. Clients that traverse the inheritance structure
@@ -89,7 +89,7 @@
List<InterfaceType> get mixins;
/**
- * Return the named constructor declared in this class with the given name, or {@code null} if
+ * Return the named constructor declared in this class with the given name, or `null` if
* this class does not declare a named constructor with the given name.
* @param name the name of the constructor to be returned
* @return the element representing the specified constructor
@@ -98,17 +98,17 @@
/**
* Return the element representing the setter with the given name that is declared in this class,
- * or {@code null} if this class does not declare a setter with the given name.
+ * or `null` if this class does not declare a setter with the given name.
* @param setterName the name of the getter to be returned
* @return the setter declared in this class with the given name
*/
PropertyAccessorElement getSetter(String setterName);
/**
- * Return the superclass of this class, or {@code null} if the class represents the class
- * 'Object'. All other classes will have a non-{@code null} superclass. If the superclass was not
+ * Return the superclass of this class, or `null` if the class represents the class
+ * 'Object'. All other classes will have a non-`null` superclass. If the superclass was not
* explicitly declared then the implicit superclass 'Object' will be returned.
- * <p>
+ *
* <b>Note:</b> Because the element model represents the state of the code, it is possible for it
* to be semantically invalid. In particular, it is not safe to assume that the inheritance
* structure of a class does not contain a cycle. Clients that traverse the inheritance structure
@@ -130,7 +130,7 @@
List<TypeVariableElement> get typeVariables;
/**
- * Return the unnamed constructor declared in this class, or {@code null} if this class does not
+ * Return the unnamed constructor declared in this class, or `null` if this class does not
* declare an unnamed constructor but does declare named constructors. The returned constructor
* will be synthetic if this class does not declare any constructors, in which case it will
* represent the default constructor for the class.
@@ -139,55 +139,61 @@
ConstructorElement get unnamedConstructor;
/**
- * Return {@code true} if this class or its superclass declares a non-final instance field.
- * @return {@code true} if this class or its superclass declares a non-final instance field
+ * Return `true` if this class has (implicit or explicit) default constructor.
+ * @return `true` if this class has (implicit or explicit) default constructor
+ */
+ bool hasDefaultConstructor();
+
+ /**
+ * Return `true` if this class or its superclass declares a non-final instance field.
+ * @return `true` if this class or its superclass declares a non-final instance field
*/
bool hasNonFinalField();
/**
- * Return {@code true} if this class has reference to super (so, for example, cannot be used as a
+ * Return `true` if this class has reference to super (so, for example, cannot be used as a
* mixin).
- * @return {@code true} if this class has reference to super
+ * @return `true` if this class has reference to super
*/
bool hasReferenceToSuper();
/**
- * Return {@code true} if this class is abstract. A class is abstract if it has an explicit{@code abstract} modifier. Note, that this definition of <i>abstract</i> is different from
+ * Return `true` if this class is abstract. A class is abstract if it has an explicit`abstract` modifier. Note, that this definition of <i>abstract</i> is different from
* <i>has unimplemented members</i>.
- * @return {@code true} if this class is abstract
+ * @return `true` if this class is abstract
*/
- bool isAbstract();
+ bool get isAbstract;
/**
- * Return {@code true} if this class is defined by a typedef construct.
- * @return {@code true} if this class is defined by a typedef construct
+ * Return `true` if this class is defined by a typedef construct.
+ * @return `true` if this class is defined by a typedef construct
*/
- bool isTypedef();
+ bool get isTypedef;
/**
- * Return {@code true} if this class can validly be used as a mixin when defining another class.
+ * Return `true` if this class can validly be used as a mixin when defining another class.
* The behavior of this method is defined by the Dart Language Specification in section 9:
* <blockquote>It is a compile-time error if a declared or derived mixin refers to super. It is a
* compile-time error if a declared or derived mixin explicitly declares a constructor. It is a
* compile-time error if a mixin is derived from a class whose superclass is not
* Object.</blockquote>
- * @return {@code true} if this class can validly be used as a mixin
+ * @return `true` if this class can validly be used as a mixin
*/
- bool isValidMixin();
+ bool get isValidMixin;
/**
* Return the element representing the getter that results from looking up the given getter in
- * this class with respect to the given library, or {@code null} if the look up fails. The
+ * this class with respect to the given library, or `null` if the look up fails. The
* behavior of this method is defined by the Dart Language Specification in section 12.15.1:
* <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
* with respect to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ *
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
* accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
* Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
* of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param getterName the name of the getter being looked up
* @param library the library with respect to which the lookup is being performed
@@ -198,16 +204,16 @@
/**
* Return the element representing the method that results from looking up the given method in
- * this class with respect to the given library, or {@code null} if the look up fails. The
+ * this class with respect to the given library, or `null` if the look up fails. The
* behavior of this method is defined by the Dart Language Specification in section 12.15.1:
* <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect to library
* <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
+ *
+ * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
* that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
* the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
- * to <i>L</i>. Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * to <i>L</i>. Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param methodName the name of the method being looked up
* @param library the library with respect to which the lookup is being performed
@@ -218,17 +224,17 @@
/**
* Return the element representing the setter that results from looking up the given setter in
- * this class with respect to the given library, or {@code null} if the look up fails. The
+ * this class with respect to the given library, or `null` if the look up fails. The
* behavior of this method is defined by the Dart Language Specification in section 12.16:
* <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
* with respect to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ *
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
* accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
* Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
* of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param setterName the name of the setter being looked up
* @param library the library with respect to which the lookup is being performed
@@ -238,8 +244,8 @@
PropertyAccessorElement lookUpSetter(String setterName, LibraryElement library);
}
/**
- * The interface {@code ClassMemberElement} defines the behavior of elements that are contained
- * within a {@link ClassElement}.
+ * The interface `ClassMemberElement` defines the behavior of elements that are contained
+ * within a [ClassElement].
*/
abstract class ClassMemberElement implements Element {
@@ -250,7 +256,7 @@
ClassElement get enclosingElement;
}
/**
- * The interface {@code CompilationUnitElement} defines the behavior of elements representing a
+ * The interface `CompilationUnitElement` defines the behavior of elements representing a
* compilation unit.
* @coverage dart.engine.element
*/
@@ -288,7 +294,7 @@
List<TopLevelVariableElement> get topLevelVariables;
/**
- * Return the class defined in this compilation unit that has the given name, or {@code null} if
+ * Return the class defined in this compilation unit that has the given name, or `null` if
* this compilation unit does not define a class with the given name.
* @param className the name of the class to be returned
* @return the class with the given name that is defined in this compilation unit
@@ -302,7 +308,7 @@
List<ClassElement> get types;
}
/**
- * The interface {@code ConstructorElement} defines the behavior of elements representing a
+ * The interface `ConstructorElement` defines the behavior of elements representing a
* constructor or a factory method defined within a type.
* @coverage dart.engine.element
*/
@@ -315,33 +321,40 @@
ConstructorElement get redirectedConstructor;
/**
- * Return {@code true} if this constructor is a const constructor.
- * @return {@code true} if this constructor is a const constructor
+ * Return `true` if this constructor is a const constructor.
+ * @return `true` if this constructor is a const constructor
*/
- bool isConst();
+ bool get isConst;
/**
- * Return {@code true} if this constructor represents a factory constructor.
- * @return {@code true} if this constructor represents a factory constructor
+ * Return `true` if this constructor can be used as a default constructor - unnamed and has
+ * no required parameters.
+ * @return `true` if this constructor can be used as a default constructor.
*/
- bool isFactory();
+ bool get isDefaultConstructor;
+
+ /**
+ * Return `true` if this constructor represents a factory constructor.
+ * @return `true` if this constructor represents a factory constructor
+ */
+ bool get isFactory;
}
/**
- * The interface {@code Element} defines the behavior common to all of the elements in the element
+ * The interface `Element` defines the behavior common to all of the elements in the element
* model. Generally speaking, the element model is a semantic model of the program that represents
* things that are declared with a name and hence can be referenced elsewhere in the code.
- * <p>
+ *
* There are two exceptions to the general case. First, there are elements in the element model that
* are created for the convenience of various kinds of analysis but that do not have any
* corresponding declaration within the source code. Such elements are marked as being
* <i>synthetic</i>. Examples of synthetic elements include
- * <ul>
- * <li>default constructors in classes that do not define any explicit constructors,
- * <li>getters and setters that are induced by explicit field declarations,
- * <li>fields that are induced by explicit declarations of getters and setters, and
- * <li>functions representing the initialization expression for a variable.
- * </ul>
- * <p>
+ *
+ * * default constructors in classes that do not define any explicit constructors,
+ * * getters and setters that are induced by explicit field declarations,
+ * * fields that are induced by explicit declarations of getters and setters, and
+ * * functions representing the initialization expression for a variable.
+ *
+ *
* Second, there are elements in the element model that do not have a name. These correspond to
* unnamed functions and exist in order to more accurately represent the semantic structure of the
* program.
@@ -364,7 +377,7 @@
/**
* Return the documentation comment for this element as it appears in the original source
- * (complete with the beginning and ending delimiters), or {@code null} if this element does not
+ * (complete with the beginning and ending delimiters), or `null` if this element does not
* have a documentation comment associated with it. This can be a long-running operation if the
* information needed to access the comment is not cached.
* @return this element's documentation comment
@@ -374,7 +387,7 @@
String computeDocumentationComment();
/**
- * Return the element of the given class that most immediately encloses this element, or{@code null} if there is no enclosing element of the given class.
+ * Return the element of the given class that most immediately encloses this element, or`null` if there is no enclosing element of the given class.
* @param elementClass the class of the element to be returned
* @return the element that encloses this element
*/
@@ -387,16 +400,16 @@
AnalysisContext get context;
/**
- * Return the display name of this element, or {@code null} if this element does not have a name.
- * <p>
+ * Return the display name of this element, or `null` if this element does not have a name.
+ *
* In most cases the name and the display name are the same. Differences though are cases such as
- * setters where the name of some setter {@code set f(x)} is {@code f=}, instead of {@code f}.
+ * setters where the name of some setter `set f(x)` is `f=`, instead of `f`.
* @return the display name of this element
*/
String get displayName;
/**
- * Return the element that either physically or logically encloses this element. This will be{@code null} if this element is a library because libraries are the top-level elements in the
+ * Return the element that either physically or logically encloses this element. This will be`null` if this element is a library because libraries are the top-level elements in the
* model.
* @return the element that encloses this element
*/
@@ -410,7 +423,7 @@
/**
* Return the library that contains this element. This will be the element itself if it is a
- * library element. This will be {@code null} if this element is an HTML file because HTML files
+ * library element. This will be `null` if this element is an HTML file because HTML files
* are not contained in libraries.
* @return the library that contains this element
*/
@@ -430,43 +443,43 @@
List<ElementAnnotation> get metadata;
/**
- * Return the name of this element, or {@code null} if this element does not have a name.
+ * Return the name of this element, or `null` if this element does not have a name.
* @return the name of this element
*/
String get name;
/**
* Return the offset of the name of this element in the file that contains the declaration of this
- * element, or {@code -1} if this element is synthetic, does not have a name, or otherwise does
+ * element, or `-1` if this element is synthetic, does not have a name, or otherwise does
* not have an offset.
* @return the offset of the name of this element
*/
int get nameOffset;
/**
- * Return the source that contains this element, or {@code null} if this element is not contained
+ * Return the source that contains this element, or `null` if this element is not contained
* in a source.
* @return the source that contains this element
*/
Source get source;
/**
- * Return {@code true} if this element, assuming that it is within scope, is accessible to code in
+ * Return `true` if this element, assuming that it is within scope, is accessible to code in
* the given library. This is defined by the Dart Language Specification in section 3.2:
* <blockquote> A declaration <i>m</i> is accessible to library <i>L</i> if <i>m</i> is declared
* in <i>L</i> or if <i>m</i> is public. </blockquote>
* @param library the library in which a possible reference to this element would occur
- * @return {@code true} if this element is accessible to code in the given library
+ * @return `true` if this element is accessible to code in the given library
*/
bool isAccessibleIn(LibraryElement library);
/**
- * Return {@code true} if this element is synthetic. A synthetic element is an element that is not
+ * Return `true` if this element is synthetic. A synthetic element is an element that is not
* represented in the source code explicitly, but is implied by the source code, such as the
* default constructor for a class that does not explicitly define any constructors.
- * @return {@code true} if this element is synthetic
+ * @return `true` if this element is synthetic
*/
- bool isSynthetic();
+ bool get isSynthetic;
/**
* Use the given visitor to visit all of the children of this element. There is no guarantee of
@@ -476,7 +489,7 @@
void visitChildren(ElementVisitor<Object> visitor);
}
/**
- * The interface {@code ElementAnnotation} defines the behavior of objects representing a single
+ * The interface `ElementAnnotation` defines the behavior of objects representing a single
* annotation associated with an element.
* @coverage dart.engine.element
*/
@@ -490,7 +503,7 @@
Element get element;
}
/**
- * The enumeration {@code ElementKind} defines the various kinds of elements in the element model.
+ * The enumeration `ElementKind` defines the various kinds of elements in the element model.
* @coverage dart.engine.element
*/
class ElementKind implements Comparable<ElementKind> {
@@ -528,7 +541,7 @@
final int ordinal;
/**
- * Return the kind of the given element, or {@link #ERROR} if the element is {@code null}. This is
+ * Return the kind of the given element, or [ERROR] if the element is `null`. This is
* a utility method that can reduce the need for null checks in other places.
* @param element the element whose kind is to be returned
* @return the kind of the given element
@@ -555,7 +568,7 @@
/**
* Return the name displayed in the UI for this kind of element.
- * @return the name of this {@link ElementKind} to display in UI.
+ * @return the name of this [ElementKind] to display in UI.
*/
String get displayName => _displayName;
int compareTo(ElementKind other) => ordinal - other.ordinal;
@@ -563,7 +576,7 @@
String toString() => name;
}
/**
- * The interface {@code ElementLocation} defines the behavior of objects that represent the location
+ * The interface `ElementLocation` defines the behavior of objects that represent the location
* of an element within the element model.
* @coverage dart.engine.element
*/
@@ -577,7 +590,7 @@
String get encoding;
}
/**
- * The interface {@code ElementVisitor} defines the behavior of objects that can be used to visit an
+ * The interface `ElementVisitor` defines the behavior of objects that can be used to visit an
* element structure.
* @coverage dart.engine.element
*/
@@ -606,7 +619,7 @@
R visitTypeVariableElement(TypeVariableElement element);
}
/**
- * The interface {@code EmbeddedHtmlScriptElement} defines the behavior of elements representing a
+ * The interface `EmbeddedHtmlScriptElement` defines the behavior of elements representing a
* script tag in an HTML file having content that defines a Dart library.
* @coverage dart.engine.element
*/
@@ -614,12 +627,12 @@
/**
* Return the library element defined by the content of the script tag.
- * @return the library element (not {@code null})
+ * @return the library element (not `null`)
*/
LibraryElement get scriptLibrary;
}
/**
- * The interface {@code ExecutableElement} defines the behavior of elements representing an
+ * The interface `ExecutableElement` defines the behavior of elements representing an
* executable object, including functions, methods, constructors, getters, and setters.
* @coverage dart.engine.element
*/
@@ -650,28 +663,34 @@
List<ParameterElement> get parameters;
/**
+ * Return the return type defined by this executable element.
+ * @return the return type defined by this executable element
+ */
+ Type2 get returnType;
+
+ /**
* Return the type of function defined by this executable element.
* @return the type of function defined by this executable element
*/
FunctionType get type;
/**
- * Return {@code true} if this executable element is an operator. The test may be based on the
+ * Return `true` if this executable element is an operator. The test may be based on the
* name of the executable element, in which case the result will be correct when the name is
* legal.
- * @return {@code true} if this executable element is an operator
+ * @return `true` if this executable element is an operator
*/
- bool isOperator();
+ bool get isOperator;
/**
- * Return {@code true} if this element is a static element. A static element is an element that is
+ * Return `true` if this element is a static element. A static element is an element that is
* not associated with a particular instance, but rather with an entire library or class.
- * @return {@code true} if this executable element is a static element
+ * @return `true` if this executable element is a static element
*/
- bool isStatic();
+ bool get isStatic;
}
/**
- * The interface {@code ExportElement} defines the behavior of objects representing information
+ * The interface `ExportElement` defines the behavior of objects representing information
* about a single export directive within a library.
* @coverage dart.engine.element
*/
@@ -696,49 +715,49 @@
LibraryElement get exportedLibrary;
}
/**
- * The interface {@code ExternalHtmlScriptElement} defines the behavior of elements representing a
- * script tag in an HTML file having a {@code source} attribute that references a Dart library
+ * The interface `ExternalHtmlScriptElement` defines the behavior of elements representing a
+ * script tag in an HTML file having a `source` attribute that references a Dart library
* source file.
* @coverage dart.engine.element
*/
abstract class ExternalHtmlScriptElement implements HtmlScriptElement {
/**
- * Return the source referenced by this element, or {@code null} if this element does not
+ * Return the source referenced by this element, or `null` if this element does not
* reference a Dart library source file.
* @return the source for the external Dart library
*/
Source get scriptSource;
}
/**
- * The interface {@code FieldElement} defines the behavior of elements representing a field defined
+ * The interface `FieldElement` defines the behavior of elements representing a field defined
* within a type.
* @coverage dart.engine.element
*/
abstract class FieldElement implements ClassMemberElement, PropertyInducingElement {
}
/**
- * The interface {@code FieldFormalParameterElement} defines the behavior of elements representing a
+ * The interface `FieldFormalParameterElement` defines the behavior of elements representing a
* field formal parameter defined within a constructor element.
*/
abstract class FieldFormalParameterElement implements ParameterElement {
/**
- * Return the field element associated with this field formal parameter, or {@code null} if the
+ * Return the field element associated with this field formal parameter, or `null` if the
* parameter references a field that doesn't exist.
* @return the field element associated with this field formal parameter
*/
FieldElement get field;
}
/**
- * The interface {@code FunctionElement} defines the behavior of elements representing a function.
+ * The interface `FunctionElement` defines the behavior of elements representing a function.
* @coverage dart.engine.element
*/
abstract class FunctionElement implements ExecutableElement, LocalElement {
}
/**
- * The interface {@code FunctionTypeAliasElement} defines the behavior of elements representing a
- * function type alias ({@code typedef}).
+ * The interface `FunctionTypeAliasElement` defines the behavior of elements representing a
+ * function type alias (`typedef`).
* @coverage dart.engine.element
*/
abstract class FunctionTypeAliasElement implements Element {
@@ -756,6 +775,12 @@
List<ParameterElement> get parameters;
/**
+ * Return the return type defined by this type alias.
+ * @return the return type defined by this type alias
+ */
+ Type2 get returnType;
+
+ /**
* Return the type of function defined by this type alias.
* @return the type of function defined by this type alias
*/
@@ -768,7 +793,7 @@
List<TypeVariableElement> get typeVariables;
}
/**
- * The interface {@code HideElementCombinator} defines the behavior of combinators that cause some
+ * The interface `HideElementCombinator` defines the behavior of combinators that cause some
* of the names in a namespace to be hidden when being imported.
* @coverage dart.engine.element
*/
@@ -782,7 +807,7 @@
List<String> get hiddenNames;
}
/**
- * The interface {@code HtmlElement} defines the behavior of elements representing an HTML file.
+ * The interface `HtmlElement` defines the behavior of elements representing an HTML file.
* @coverage dart.engine.element
*/
abstract class HtmlElement implements Element {
@@ -791,12 +816,12 @@
* Return an array containing all of the script elements contained in the HTML file. This includes
* scripts with libraries that are defined by the content of a script tag as well as libraries
* that are referenced in the {@core source} attribute of a script tag.
- * @return the script elements in the HTML file (not {@code null}, contains no {@code null}s)
+ * @return the script elements in the HTML file (not `null`, contains no `null`s)
*/
List<HtmlScriptElement> get scripts;
}
/**
- * The interface {@code HtmlScriptElement} defines the behavior of elements representing a script
+ * The interface `HtmlScriptElement` defines the behavior of elements representing a script
* tag in an HTML file.
* @see EmbeddedHtmlScriptElement
* @see ExternalHtmlScriptElement
@@ -805,7 +830,7 @@
abstract class HtmlScriptElement implements Element {
}
/**
- * The interface {@code ImportElement} defines the behavior of objects representing information
+ * The interface `ImportElement` defines the behavior of objects representing information
* about a single import directive within a library.
* @coverage dart.engine.element
*/
@@ -830,14 +855,14 @@
LibraryElement get importedLibrary;
/**
- * Return the prefix that was specified as part of the import directive, or {@code null} if there
+ * Return the prefix that was specified as part of the import directive, or `null` if there
* was no prefix specified.
* @return the prefix that was specified as part of the import directive
*/
PrefixElement get prefix;
}
/**
- * The interface {@code LabelElement} defines the behavior of elements representing a label
+ * The interface `LabelElement` defines the behavior of elements representing a label
* associated with a statement.
* @coverage dart.engine.element
*/
@@ -850,7 +875,7 @@
ExecutableElement get enclosingElement;
}
/**
- * The interface {@code LibraryElement} defines the behavior of elements representing a library.
+ * The interface `LibraryElement` defines the behavior of elements representing a library.
* @coverage dart.engine.element
*/
abstract class LibraryElement implements Element {
@@ -862,8 +887,8 @@
CompilationUnitElement get definingCompilationUnit;
/**
- * Return the entry point for this library, or {@code null} if this library does not have an entry
- * point. The entry point is defined to be a zero argument top-level function whose name is{@code main}.
+ * Return the entry point for this library, or `null` if this library does not have an entry
+ * point. The entry point is defined to be a zero argument top-level function whose name is`main`.
* @return the entry point for this library
*/
FunctionElement get entryPoint;
@@ -883,7 +908,7 @@
/**
* Return an array containing all of the libraries that are imported into this library. This
* includes all of the libraries that are imported using a prefix (also available through the
- * prefixes returned by {@link #getPrefixes()}) and those that are imported without a prefix.
+ * prefixes returned by [getPrefixes]) and those that are imported without a prefix.
* @return an array containing all of the libraries that are imported into this library
*/
List<LibraryElement> get importedLibraries;
@@ -896,20 +921,20 @@
/**
* Return an array containing all of the compilation units that are included in this library using
- * a {@code part} directive. This does not include the defining compilation unit that contains the{@code part} directives.
+ * a `part` directive. This does not include the defining compilation unit that contains the`part` directives.
* @return the compilation units that are included in this library
*/
List<CompilationUnitElement> get parts;
/**
- * Return an array containing elements for each of the prefixes used to {@code import} libraries
- * into this library. Each prefix can be used in more than one {@code import} directive.
- * @return the prefixes used to {@code import} libraries into this library
+ * Return an array containing elements for each of the prefixes used to `import` libraries
+ * into this library. Each prefix can be used in more than one `import` directive.
+ * @return the prefixes used to `import` libraries into this library
*/
List<PrefixElement> get prefixes;
/**
- * Return the class defined in this library that has the given name, or {@code null} if this
+ * Return the class defined in this library that has the given name, or `null` if this
* library does not define a class with the given name.
* @param className the name of the class to be returned
* @return the class with the given name that is defined in this library
@@ -917,73 +942,73 @@
ClassElement getType(String className);
/**
- * Answer {@code true} if this library is an application that can be run in the browser.
- * @return {@code true} if this library is an application that can be run in the browser
+ * Answer `true` if this library is an application that can be run in the browser.
+ * @return `true` if this library is an application that can be run in the browser
*/
- bool isBrowserApplication();
+ bool get isBrowserApplication;
/**
- * Return {@code true} if this library is the dart:core library.
- * @return {@code true} if this library is the dart:core library
+ * Return `true` if this library is the dart:core library.
+ * @return `true` if this library is the dart:core library
*/
- bool isDartCore();
+ bool get isDartCore;
/**
- * Return {@code true} if this library is up to date with respect to the given time stamp. If any
+ * Return `true` if this library is up to date with respect to the given time stamp. If any
* transitively referenced Source is newer than the time stamp, this method returns false.
* @param timeStamp the time stamp to compare against
- * @return {@code true} if this library is up to date with respect to the given time stamp
+ * @return `true` if this library is up to date with respect to the given time stamp
*/
bool isUpToDate2(int timeStamp);
}
/**
- * The interface {@code LocalElement} defines the behavior of elements that can be (but are not
- * required to be) defined within a method or function (an {@link ExecutableElement}).
+ * The interface `LocalElement` defines the behavior of elements that can be (but are not
+ * required to be) defined within a method or function (an [ExecutableElement]).
* @coverage dart.engine.element
*/
abstract class LocalElement implements Element {
/**
* Return a source range that covers the approximate portion of the source in which the name of
- * this element is visible, or {@code null} if there is no single range of characters within which
+ * this element is visible, or `null` if there is no single range of characters within which
* the element name is visible.
- * <ul>
- * <li>For a local variable, this includes everything from the end of the variable's initializer
- * to the end of the block that encloses the variable declaration.</li>
- * <li>For a parameter, this includes the body of the method or function that declares the
- * parameter.</li>
- * <li>For a local function, this includes everything from the beginning of the function's body to
- * the end of the block that encloses the function declaration.</li>
- * <li>For top-level functions, {@code null} will be returned because they are potentially visible
- * in multiple sources.</li>
- * </ul>
+ *
+ * * For a local variable, this includes everything from the end of the variable's initializer
+ * to the end of the block that encloses the variable declaration.
+ * * For a parameter, this includes the body of the method or function that declares the
+ * parameter.
+ * * For a local function, this includes everything from the beginning of the function's body to
+ * the end of the block that encloses the function declaration.
+ * * For top-level functions, `null` will be returned because they are potentially visible
+ * in multiple sources.
+ *
* @return the range of characters in which the name of this element is visible
*/
SourceRange get visibleRange;
}
/**
- * The interface {@code LocalVariableElement} defines the behavior common to elements that represent
+ * The interface `LocalVariableElement` defines the behavior common to elements that represent
* a local variable.
* @coverage dart.engine.element
*/
abstract class LocalVariableElement implements LocalElement, VariableElement {
}
/**
- * The interface {@code MethodElement} defines the behavior of elements that represent a method
+ * The interface `MethodElement` defines the behavior of elements that represent a method
* defined within a type.
* @coverage dart.engine.element
*/
abstract class MethodElement implements ClassMemberElement, ExecutableElement {
/**
- * Return {@code true} if this method is abstract. Methods are abstract if they are not external
+ * Return `true` if this method is abstract. Methods are abstract if they are not external
* and have no body.
- * @return {@code true} if this method is abstract
+ * @return `true` if this method is abstract
*/
- bool isAbstract();
+ bool get isAbstract;
}
/**
- * The interface {@code MultiplyDefinedElement} defines the behavior of pseudo-elements that
+ * The interface `MultiplyDefinedElement` defines the behavior of pseudo-elements that
* represent multiple elements defined within a single scope that have the same name. This situation
* is not allowed by the language, so objects implementing this interface always represent an error.
* As a result, most of the normal operations on elements do not make sense and will return useless
@@ -1000,7 +1025,7 @@
List<Element> get conflictingElements;
}
/**
- * The interface {@code NamespaceCombinator} defines the behavior common to objects that control how
+ * The interface `NamespaceCombinator` defines the behavior common to objects that control how
* namespaces are combined.
* @coverage dart.engine.element
*/
@@ -1012,7 +1037,7 @@
static final List<NamespaceCombinator> EMPTY_ARRAY = new List<NamespaceCombinator>(0);
}
/**
- * The interface {@code ParameterElement} defines the behavior of elements representing a parameter
+ * The interface `ParameterElement` defines the behavior of elements representing a parameter
* defined within an executable element.
* @coverage dart.engine.element
*/
@@ -1020,7 +1045,7 @@
/**
* Return a source range that covers the portion of the source in which the default value for this
- * parameter is specified, or {@code null} if there is no default value.
+ * parameter is specified, or `null` if there is no default value.
* @return the range of characters in which the default value of this parameter is specified
*/
SourceRange get defaultValueRange;
@@ -1039,13 +1064,13 @@
List<ParameterElement> get parameters;
/**
- * Return {@code true} if this parameter is an initializing formal parameter.
- * @return {@code true} if this parameter is an initializing formal parameter
+ * Return `true` if this parameter is an initializing formal parameter.
+ * @return `true` if this parameter is an initializing formal parameter
*/
- bool isInitializingFormal();
+ bool get isInitializingFormal;
}
/**
- * The interface {@code PrefixElement} defines the behavior common to elements that represent a
+ * The interface `PrefixElement` defines the behavior common to elements that represent a
* prefix used to import one or more libraries into another library.
* @coverage dart.engine.element
*/
@@ -1064,25 +1089,25 @@
List<LibraryElement> get importedLibraries;
}
/**
- * The interface {@code PropertyAccessorElement} defines the behavior of elements representing a
+ * The interface `PropertyAccessorElement` defines the behavior of elements representing a
* getter or a setter. Note that explicitly defined property accessors implicitly define a synthetic
* field. Symmetrically, synthetic accessors are implicitly created for explicitly defined fields.
* The following rules apply:
- * <ul>
- * <li>Every explicit field is represented by a non-synthetic {@link FieldElement}.
- * <li>Every explicit field induces a getter and possibly a setter, both of which are represented by
- * synthetic {@link PropertyAccessorElement}s.
- * <li>Every explicit getter or setter is represented by a non-synthetic{@link PropertyAccessorElement}.
- * <li>Every explicit getter or setter (or pair thereof if they have the same name) induces a field
- * that is represented by a synthetic {@link FieldElement}.
- * </ul>
+ *
+ * * Every explicit field is represented by a non-synthetic [FieldElement].
+ * * Every explicit field induces a getter and possibly a setter, both of which are represented by
+ * synthetic [PropertyAccessorElement]s.
+ * * Every explicit getter or setter is represented by a non-synthetic[PropertyAccessorElement].
+ * * Every explicit getter or setter (or pair thereof if they have the same name) induces a field
+ * that is represented by a synthetic [FieldElement].
+ *
* @coverage dart.engine.element
*/
abstract class PropertyAccessorElement implements ExecutableElement {
/**
* Return the accessor representing the getter that corresponds to (has the same name as) this
- * setter, or {@code null} if this accessor is not a setter or if there is no corresponding
+ * setter, or `null` if this accessor is not a setter or if there is no corresponding
* getter.
* @return the getter that corresponds to this setter
*/
@@ -1090,7 +1115,7 @@
/**
* Return the accessor representing the setter that corresponds to (has the same name as) this
- * getter, or {@code null} if this accessor is not a getter or if there is no corresponding
+ * getter, or `null` if this accessor is not a getter or if there is no corresponding
* setter.
* @return the setter that corresponds to this getter
*/
@@ -1104,38 +1129,38 @@
PropertyInducingElement get variable;
/**
- * Return {@code true} if this accessor is abstract. Accessors are abstract if they are not
+ * Return `true` if this accessor is abstract. Accessors are abstract if they are not
* external and have no body.
- * @return {@code true} if this accessor is abstract
+ * @return `true` if this accessor is abstract
*/
- bool isAbstract();
+ bool get isAbstract;
/**
- * Return {@code true} if this accessor represents a getter.
- * @return {@code true} if this accessor represents a getter
+ * Return `true` if this accessor represents a getter.
+ * @return `true` if this accessor represents a getter
*/
- bool isGetter();
+ bool get isGetter;
/**
- * Return {@code true} if this accessor represents a setter.
- * @return {@code true} if this accessor represents a setter
+ * Return `true` if this accessor represents a setter.
+ * @return `true` if this accessor represents a setter
*/
- bool isSetter();
+ bool get isSetter;
}
/**
- * The interface {@code PropertyInducingElement} defines the behavior of elements representing a
+ * The interface `PropertyInducingElement` defines the behavior of elements representing a
* variable that has an associated getter and possibly a setter. Note that explicitly defined
- * variables implicitly define a synthetic getter and that non-{@code final} explicitly defined
+ * variables implicitly define a synthetic getter and that non-`final` explicitly defined
* variables implicitly define a synthetic setter. Symmetrically, synthetic fields are implicitly
* created for explicitly defined getters and setters. The following rules apply:
- * <ul>
- * <li>Every explicit variable is represented by a non-synthetic {@link PropertyInducingElement}.
- * <li>Every explicit variable induces a getter and possibly a setter, both of which are represented
- * by synthetic {@link PropertyAccessorElement}s.
- * <li>Every explicit getter or setter is represented by a non-synthetic{@link PropertyAccessorElement}.
- * <li>Every explicit getter or setter (or pair thereof if they have the same name) induces a
- * variable that is represented by a synthetic {@link PropertyInducingElement}.
- * </ul>
+ *
+ * * Every explicit variable is represented by a non-synthetic [PropertyInducingElement].
+ * * Every explicit variable induces a getter and possibly a setter, both of which are represented
+ * by synthetic [PropertyAccessorElement]s.
+ * * Every explicit getter or setter is represented by a non-synthetic[PropertyAccessorElement].
+ * * Every explicit getter or setter (or pair thereof if they have the same name) induces a
+ * variable that is represented by a synthetic [PropertyInducingElement].
+ *
* @coverage dart.engine.element
*/
abstract class PropertyInducingElement implements VariableElement {
@@ -1148,8 +1173,8 @@
PropertyAccessorElement get getter;
/**
- * Return the setter associated with this variable, or {@code null} if the variable is effectively{@code final} and therefore does not have a setter associated with it. (This can happen either
- * because the variable is explicitly defined as being {@code final} or because the variable is
+ * Return the setter associated with this variable, or `null` if the variable is effectively`final` and therefore does not have a setter associated with it. (This can happen either
+ * because the variable is explicitly defined as being `final` or because the variable is
* induced by an explicit getter that does not have a corresponding setter.) If this variable was
* explicitly defined (is not synthetic) then the setter associated with it will be synthetic.
* @return the setter associated with this variable
@@ -1157,14 +1182,14 @@
PropertyAccessorElement get setter;
/**
- * Return {@code true} if this element is a static element. A static element is an element that is
+ * Return `true` if this element is a static element. A static element is an element that is
* not associated with a particular instance, but rather with an entire library or class.
- * @return {@code true} if this executable element is a static element
+ * @return `true` if this executable element is a static element
*/
- bool isStatic();
+ bool get isStatic;
}
/**
- * The interface {@code ShowElementCombinator} defines the behavior of combinators that cause some
+ * The interface `ShowElementCombinator` defines the behavior of combinators that cause some
* of the names in a namespace to be visible (and the rest hidden) when being imported.
* @coverage dart.engine.element
*/
@@ -1178,21 +1203,21 @@
List<String> get shownNames;
}
/**
- * The interface {@code TopLevelVariableElement} defines the behavior of elements representing a
+ * The interface `TopLevelVariableElement` defines the behavior of elements representing a
* top-level variable.
* @coverage dart.engine.element
*/
abstract class TopLevelVariableElement implements PropertyInducingElement {
}
/**
- * The interface {@code TypeVariableElement} defines the behavior of elements representing a type
+ * The interface `TypeVariableElement` defines the behavior of elements representing a type
* variable.
* @coverage dart.engine.element
*/
abstract class TypeVariableElement implements Element {
/**
- * Return the type representing the bound associated with this variable, or {@code null} if this
+ * Return the type representing the bound associated with this variable, or `null` if this
* variable does not have an explicit bound.
* @return the type representing the bound associated with this variable
*/
@@ -1205,7 +1230,7 @@
TypeVariableType get type;
}
/**
- * The interface {@code UndefinedElement} defines the behavior of pseudo-elements that represent
+ * The interface `UndefinedElement` defines the behavior of pseudo-elements that represent
* names that are undefined. This situation is not allowed by the language, so objects implementing
* this interface always represent an error. As a result, most of the normal operations on elements
* do not make sense and will return useless results.
@@ -1214,27 +1239,27 @@
abstract class UndefinedElement implements Element {
}
/**
- * The interface {@code UriReferencedElement} defines the behavior of objects included into a
+ * The interface `UriReferencedElement` defines the behavior of objects included into a
* library using some URI.
* @coverage dart.engine.element
*/
abstract class UriReferencedElement implements Element {
/**
- * Return the URI that is used to include this element into the enclosing library, or {@code null}if this is the defining compilation unit of a library.
+ * Return the URI that is used to include this element into the enclosing library, or `null`if this is the defining compilation unit of a library.
* @return the URI that is used to include this element into the enclosing library
*/
String get uri;
}
/**
- * The interface {@code VariableElement} defines the behavior common to elements that represent a
+ * The interface `VariableElement` defines the behavior common to elements that represent a
* variable.
* @coverage dart.engine.element
*/
abstract class VariableElement implements Element {
/**
- * Return a synthetic function representing this variable's initializer, or {@code null} if this
+ * Return a synthetic function representing this variable's initializer, or `null` if this
* variable does not have an initializer. The function will have no parameters. The return type of
* the function will be the compile-time type of the initialization expression.
* @return a synthetic function representing this variable's initializer
@@ -1242,41 +1267,41 @@
FunctionElement get initializer;
/**
- * Return the declared type of this variable, or {@code null} if the variable did not have a
+ * Return the declared type of this variable, or `null` if the variable did not have a
* declared type (such as if it was declared using the keyword 'var').
* @return the declared type of this variable
*/
Type2 get type;
/**
- * Return {@code true} if this variable was declared with the 'const' modifier.
- * @return {@code true} if this variable was declared with the 'const' modifier
+ * Return `true` if this variable was declared with the 'const' modifier.
+ * @return `true` if this variable was declared with the 'const' modifier
*/
- bool isConst();
+ bool get isConst;
/**
- * Return {@code true} if this variable was declared with the 'final' modifier. Variables that are
- * declared with the 'const' modifier will return {@code false} even though they are implicitly
+ * Return `true` if this variable was declared with the 'final' modifier. Variables that are
+ * declared with the 'const' modifier will return `false` even though they are implicitly
* final.
- * @return {@code true} if this variable was declared with the 'final' modifier
+ * @return `true` if this variable was declared with the 'final' modifier
*/
- bool isFinal();
+ bool get isFinal;
}
/**
- * Instances of the class {@code GeneralizingElementVisitor} implement an element visitor that will
- * recursively visit all of the elements in an element model (like instances of the class{@link RecursiveElementVisitor}). In addition, when an element of a specific type is visited not
+ * Instances of the class `GeneralizingElementVisitor` implement an element visitor that will
+ * recursively visit all of the elements in an element model (like instances of the class[RecursiveElementVisitor]). In addition, when an element of a specific type is visited not
* only will the visit method for that specific type of element be invoked, but additional methods
* for the supertypes of that element will also be invoked. For example, using an instance of this
- * class to visit a {@link MethodElement} will cause the method{@link #visitMethodElement(MethodElement)} to be invoked but will also cause the methods{@link #visitExecutableElement(ExecutableElement)} and {@link #visitElement(Element)} to be
+ * class to visit a [MethodElement] will cause the method[visitMethodElement] to be invoked but will also cause the methods[visitExecutableElement] and [visitElement] to be
* subsequently invoked. This allows visitors to be written that visit all executable elements
- * without needing to override the visit method for each of the specific subclasses of{@link ExecutableElement}.
- * <p>
+ * without needing to override the visit method for each of the specific subclasses of[ExecutableElement].
+ *
* Note, however, that unlike many visitors, element visitors visit objects based on the interfaces
* implemented by those elements. Because interfaces form a graph structure rather than a tree
* structure the way classes do, and because it is generally undesirable for an object to be visited
* more than once, this class flattens the interface graph into a pseudo-tree. In particular, this
* class treats elements as if the element types were structured in the following way:
- * <p>
+ *
* <pre>
* Element
* ClassElement
@@ -1306,7 +1331,7 @@
* ParameterElement
* FieldFormalParameterElement
* </pre>
- * <p>
+ *
* Subclasses that override a visit method must either invoke the overridden visit method or
* explicitly invoke the more general visit method. Failure to do so will cause the visit methods
* for superclasses of the element to not be invoked and will cause the children of the visited node
@@ -1356,11 +1381,11 @@
R visitVariableElement(VariableElement element) => visitElement(element);
}
/**
- * Instances of the class {@code RecursiveElementVisitor} implement an element visitor that will
+ * Instances of the class `RecursiveElementVisitor` implement an element visitor that will
* recursively visit all of the element in an element model. For example, using an instance of this
- * class to visit a {@link CompilationUnitElement} will also cause all of the types in the
+ * class to visit a [CompilationUnitElement] will also cause all of the types in the
* compilation unit to be visited.
- * <p>
+ *
* Subclasses that override a visit method must either invoke the overridden visit method or must
* explicitly ask the visited element to visit its children. Failure to do so will cause the
* children of the visited element to not be visited.
@@ -1457,7 +1482,7 @@
}
}
/**
- * Instances of the class {@code SimpleElementVisitor} implement an element visitor that will do
+ * Instances of the class `SimpleElementVisitor` implement an element visitor that will do
* nothing when visiting an element. It is intended to be a superclass for classes that use the
* visitor pattern primarily as a dispatch mechanism (and hence don't need to recursively visit a
* whole structure) and that only need to visit a small number of element types.
@@ -1488,7 +1513,7 @@
R visitTypeVariableElement(TypeVariableElement element) => null;
}
/**
- * Instances of the class {@code ClassElementImpl} implement a {@code ClassElement}.
+ * Instances of the class `ClassElementImpl` implement a `ClassElement`.
* @coverage dart.engine.element
*/
class ClassElementImpl extends ElementImpl implements ClassElement {
@@ -1525,7 +1550,7 @@
List<MethodElement> _methods = MethodElementImpl.EMPTY_ARRAY;
/**
- * The superclass of the class, or {@code null} if the class does not have an explicit superclass.
+ * The superclass of the class, or `null` if the class does not have an explicit superclass.
*/
InterfaceType _supertype;
@@ -1588,10 +1613,10 @@
List<ConstructorElement> get constructors => _constructors;
/**
- * Given some name, this returns the {@link FieldElement} with the matching name, if there is no
- * such field, then {@code null} is returned.
+ * Given some name, this returns the [FieldElement] with the matching name, if there is no
+ * such field, then `null` is returned.
* @param name some name to lookup a field element with
- * @return the matching field element, or {@code null} if no such element was found
+ * @return the matching field element, or `null` if no such element was found
*/
FieldElement getField(String name2) {
for (FieldElement fieldElement in _fields) {
@@ -1604,7 +1629,7 @@
List<FieldElement> get fields => _fields;
PropertyAccessorElement getGetter(String getterName) {
for (PropertyAccessorElement accessor in _accessors) {
- if (accessor.isGetter() && accessor.name == getterName) {
+ if (accessor.isGetter && accessor.name == getterName) {
return accessor;
}
}
@@ -1636,7 +1661,7 @@
setterName += '=';
}
for (PropertyAccessorElement accessor in _accessors) {
- if (accessor.isSetter() && accessor.name == setterName) {
+ if (accessor.isSetter && accessor.name == setterName) {
return accessor;
}
}
@@ -1654,6 +1679,14 @@
}
return null;
}
+ bool hasDefaultConstructor() {
+ for (ConstructorElement constructor in constructors) {
+ if (constructor.isDefaultConstructor) {
+ return true;
+ }
+ }
+ return false;
+ }
bool hasNonFinalField() {
List<ClassElement> classesToVisit = new List<ClassElement>();
Set<ClassElement> visitedClasses = new Set<ClassElement>();
@@ -1662,7 +1695,7 @@
ClassElement currentElement = classesToVisit.removeAt(0);
if (javaSetAdd(visitedClasses, currentElement)) {
for (FieldElement field in currentElement.fields) {
- if (!field.isFinal() && !field.isConst() && !field.isStatic() && !field.isSynthetic()) {
+ if (!field.isFinal && !field.isConst && !field.isStatic && !field.isSynthetic) {
return true;
}
}
@@ -1682,9 +1715,9 @@
return false;
}
bool hasReferenceToSuper() => hasModifier(Modifier.REFERENCES_SUPER);
- bool isAbstract() => hasModifier(Modifier.ABSTRACT);
- bool isTypedef() => hasModifier(Modifier.TYPEDEF);
- bool isValidMixin() => hasModifier(Modifier.MIXIN);
+ bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+ bool get isTypedef => hasModifier(Modifier.TYPEDEF);
+ bool get isValidMixin => hasModifier(Modifier.MIXIN);
PropertyAccessorElement lookUpGetter(String getterName, LibraryElement library) {
Set<ClassElement> visitedClasses = new Set<ClassElement>();
ClassElement currentElement = this;
@@ -1766,7 +1799,7 @@
/**
* Set whether this class is abstract to correspond to the given value.
- * @param isAbstract {@code true} if the class is abstract
+ * @param isAbstract `true` if the class is abstract
*/
void set abstract(bool isAbstract) {
setModifier(Modifier.ABSTRACT, isAbstract);
@@ -1807,7 +1840,7 @@
/**
* Set whether this class references 'super' to the given value.
- * @param isReferencedSuper {@code true} references 'super'
+ * @param isReferencedSuper `true` references 'super'
*/
void set hasReferenceToSuper2(bool isReferencedSuper) {
setModifier(Modifier.REFERENCES_SUPER, isReferencedSuper);
@@ -1859,7 +1892,7 @@
/**
* Set whether this class is defined by a typedef construct to correspond to the given value.
- * @param isTypedef {@code true} if the class is defined by a typedef construct
+ * @param isTypedef `true` if the class is defined by a typedef construct
*/
void set typedef(bool isTypedef) {
setModifier(Modifier.TYPEDEF, isTypedef);
@@ -1878,7 +1911,7 @@
/**
* Set whether this class is a valid mixin to correspond to the given value.
- * @param isValidMixin {@code true} if this class can be used as a mixin
+ * @param isValidMixin `true` if this class can be used as a mixin
*/
void set validMixin(bool isValidMixin) {
setModifier(Modifier.MIXIN, isValidMixin);
@@ -1940,7 +1973,7 @@
}
}
/**
- * Instances of the class {@code CompilationUnitElementImpl} implement a{@link CompilationUnitElement}.
+ * Instances of the class `CompilationUnitElementImpl` implement a[CompilationUnitElement].
* @coverage dart.engine.element
*/
class CompilationUnitElementImpl extends ElementImpl implements CompilationUnitElement {
@@ -1982,7 +2015,7 @@
List<ClassElement> _types = ClassElementImpl.EMPTY_ARRAY;
/**
- * The URI that is specified by the "part" directive in the enclosing library, or {@code null} if
+ * The URI that is specified by the "part" directive in the enclosing library, or `null` if
* this is the defining compilation unit of a library.
*/
String _uri;
@@ -2131,7 +2164,7 @@
}
}
/**
- * Instances of the class {@code ConstFieldElementImpl} implement a {@code FieldElement} for a
+ * Instances of the class `ConstFieldElementImpl` implement a `FieldElement` for a
* 'const' field that has an initializer.
*/
class ConstFieldElementImpl extends FieldElementImpl {
@@ -2153,7 +2186,7 @@
}
}
/**
- * Instances of the class {@code ConstLocalVariableElementImpl} implement a{@code LocalVariableElement} for a local 'const' variable that has an initializer.
+ * Instances of the class `ConstLocalVariableElementImpl` implement a`LocalVariableElement` for a local 'const' variable that has an initializer.
* @coverage dart.engine.element
*/
class ConstLocalVariableElementImpl extends LocalVariableElementImpl {
@@ -2175,30 +2208,7 @@
}
}
/**
- * Instances of the class {@code ConstParameterElementImpl} implement a {@code ParameterElement} for
- * a 'const' parameter that has an initializer.
- * @coverage dart.engine.element
- */
-class ConstParameterElementImpl extends ParameterElementImpl {
-
- /**
- * The result of evaluating this variable's initializer.
- */
- EvaluationResultImpl _result;
-
- /**
- * Initialize a newly created parameter element to have the given name.
- * @param name the name of this element
- */
- ConstParameterElementImpl(Identifier name) : super(name) {
- }
- EvaluationResultImpl get evaluationResult => _result;
- void set evaluationResult(EvaluationResultImpl result2) {
- this._result = result2;
- }
-}
-/**
- * Instances of the class {@code ConstTopLevelVariableElementImpl} implement a{@code TopLevelVariableElement} for a top-level 'const' variable that has an initializer.
+ * Instances of the class `ConstTopLevelVariableElementImpl` implement a`TopLevelVariableElement` for a top-level 'const' variable that has an initializer.
*/
class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl {
@@ -2219,7 +2229,7 @@
}
}
/**
- * Instances of the class {@code ConstructorElementImpl} implement a {@code ConstructorElement}.
+ * Instances of the class `ConstructorElementImpl` implement a `ConstructorElement`.
* @coverage dart.engine.element
*/
class ConstructorElementImpl extends ExecutableElementImpl implements ConstructorElement {
@@ -2244,13 +2254,25 @@
ClassElement get enclosingElement => super.enclosingElement as ClassElement;
ElementKind get kind => ElementKind.CONSTRUCTOR;
ConstructorElement get redirectedConstructor => _redirectedConstructor;
- bool isConst() => hasModifier(Modifier.CONST);
- bool isFactory() => hasModifier(Modifier.FACTORY);
- bool isStatic() => false;
+ bool get isConst => hasModifier(Modifier.CONST);
+ bool get isDefaultConstructor {
+ String name = this.name;
+ if (name != null && name.length != 0) {
+ return false;
+ }
+ for (ParameterElement parameter in parameters) {
+ if (identical(parameter.parameterKind, ParameterKind.REQUIRED)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ bool get isFactory => hasModifier(Modifier.FACTORY);
+ bool get isStatic => false;
/**
* Set whether this constructor represents a 'const' constructor to the given value.
- * @param isConst {@code true} if this constructor represents a 'const' constructor
+ * @param isConst `true` if this constructor represents a 'const' constructor
*/
void set const2(bool isConst) {
setModifier(Modifier.CONST, isConst);
@@ -2258,7 +2280,7 @@
/**
* Set whether this constructor represents a factory method to the given value.
- * @param isFactory {@code true} if this constructor represents a factory method
+ * @param isFactory `true` if this constructor represents a factory method
*/
void set factory(bool isFactory) {
setModifier(Modifier.FACTORY, isFactory);
@@ -2282,8 +2304,52 @@
}
}
/**
- * Instances of the class {@code DynamicElementImpl} represent the synthetic element representing
- * the declaration of the type {@code dynamic}.
+ * Instances of the class `DefaultFieldFormalParameterElementImpl` implement a`FieldFormalParameterElementImpl` for parameters that have an initializer.
+ * @coverage dart.engine.element
+ */
+class DefaultFieldFormalParameterElementImpl extends FieldFormalParameterElementImpl {
+
+ /**
+ * The result of evaluating this variable's initializer.
+ */
+ EvaluationResultImpl _result;
+
+ /**
+ * Initialize a newly created parameter element to have the given name.
+ * @param name the name of this element
+ */
+ DefaultFieldFormalParameterElementImpl(Identifier name) : super(name) {
+ }
+ EvaluationResultImpl get evaluationResult => _result;
+ void set evaluationResult(EvaluationResultImpl result2) {
+ this._result = result2;
+ }
+}
+/**
+ * Instances of the class `DefaultParameterElementImpl` implement a `ParameterElement`for parameters that have an initializer.
+ * @coverage dart.engine.element
+ */
+class DefaultParameterElementImpl extends ParameterElementImpl {
+
+ /**
+ * The result of evaluating this variable's initializer.
+ */
+ EvaluationResultImpl _result;
+
+ /**
+ * Initialize a newly created parameter element to have the given name.
+ * @param name the name of this element
+ */
+ DefaultParameterElementImpl(Identifier name) : super(name) {
+ }
+ EvaluationResultImpl get evaluationResult => _result;
+ void set evaluationResult(EvaluationResultImpl result2) {
+ this._result = result2;
+ }
+}
+/**
+ * Instances of the class `DynamicElementImpl` represent the synthetic element representing
+ * the declaration of the type `dynamic`.
* @coverage dart.engine.element
*/
class DynamicElementImpl extends ElementImpl {
@@ -2302,7 +2368,7 @@
/**
* Initialize a newly created instance of this class. Instances of this class should <b>not</b> be
* created except as part of creating the type associated with this element. The single instance
- * of this class should be accessed through the method {@link #getInstance()}.
+ * of this class should be accessed through the method [getInstance].
*/
DynamicElementImpl() : super.con2(Keyword.DYNAMIC.syntax, -1) {
setModifier(Modifier.SYNTHETIC, true);
@@ -2325,7 +2391,7 @@
}
}
/**
- * Instances of the class {@code ElementAnnotationImpl} implement an {@link ElementAnnotation}.
+ * Instances of the class `ElementAnnotationImpl` implement an [ElementAnnotation].
* @coverage dart.engine.element
*/
class ElementAnnotationImpl implements ElementAnnotation {
@@ -2352,14 +2418,14 @@
String toString() => "@${_element.toString()}";
}
/**
- * The abstract class {@code ElementImpl} implements the behavior common to objects that implement
- * an {@link Element}.
+ * The abstract class `ElementImpl` implements the behavior common to objects that implement
+ * an [Element].
* @coverage dart.engine.element
*/
abstract class ElementImpl implements Element {
/**
- * The enclosing element of this element, or {@code null} if this element is at the root of the
+ * The enclosing element of this element, or `null` if this element is at the root of the
* element structure.
*/
ElementImpl _enclosingElement;
@@ -2395,10 +2461,10 @@
* @param name the name of this element
*/
ElementImpl.con1(Identifier name2) {
- _jtd_constructor_194_impl(name2);
+ _jtd_constructor_195_impl(name2);
}
- _jtd_constructor_194_impl(Identifier name2) {
- _jtd_constructor_195_impl(name2 == null ? "" : name2.name, name2 == null ? -1 : name2.offset);
+ _jtd_constructor_195_impl(Identifier name2) {
+ _jtd_constructor_196_impl(name2 == null ? "" : name2.name, name2 == null ? -1 : name2.offset);
}
/**
@@ -2408,9 +2474,9 @@
* declaration of this element
*/
ElementImpl.con2(String name2, int nameOffset2) {
- _jtd_constructor_195_impl(name2, nameOffset2);
+ _jtd_constructor_196_impl(name2, nameOffset2);
}
- _jtd_constructor_195_impl(String name2, int nameOffset2) {
+ _jtd_constructor_196_impl(String name2, int nameOffset2) {
this._name = StringUtilities.intern(name2);
this._nameOffset = nameOffset2;
}
@@ -2431,7 +2497,7 @@
}
/**
- * Return the child of this element that is uniquely identified by the given identifier, or{@code null} if there is no such child.
+ * Return the child of this element that is uniquely identified by the given identifier, or`null` if there is no such child.
* @param identifier the identifier used to select a child
* @return the child of this element with the given identifier
*/
@@ -2467,7 +2533,7 @@
}
return true;
}
- bool isSynthetic() => hasModifier(Modifier.SYNTHETIC);
+ bool get isSynthetic => hasModifier(Modifier.SYNTHETIC);
/**
* Set the metadata associate with this element to the given array of annotations.
@@ -2489,7 +2555,7 @@
/**
* Set whether this element is synthetic to correspond to the given value.
- * @param isSynthetic {@code true} if the element is synthetic
+ * @param isSynthetic `true` if the element is synthetic
*/
void set synthetic(bool isSynthetic) {
setModifier(Modifier.SYNTHETIC, isSynthetic);
@@ -2524,14 +2590,14 @@
String get identifier => name;
/**
- * Return {@code true} if this element has the given modifier associated with it.
+ * Return `true` if this element has the given modifier associated with it.
* @param modifier the modifier being tested for
- * @return {@code true} if this element has the given modifier associated with it
+ * @return `true` if this element has the given modifier associated with it
*/
bool hasModifier(Modifier modifier) => _modifiers != null && _modifiers.contains(modifier);
/**
- * If the given child is not {@code null}, use the given visitor to visit it.
+ * If the given child is not `null`, use the given visitor to visit it.
* @param child the child to be visited
* @param visitor the visitor to be used to visit the child
*/
@@ -2566,7 +2632,7 @@
* Set whether the given modifier is associated with this element to correspond to the given
* value.
* @param modifier the modifier to be set
- * @param value {@code true} if the modifier is to be associated with this element
+ * @param value `true` if the modifier is to be associated with this element
*/
void setModifier(Modifier modifier, bool value) {
if (value) {
@@ -2585,7 +2651,7 @@
}
}
/**
- * Instances of the class {@code ElementLocationImpl} implement an {@link ElementLocation}.
+ * Instances of the class `ElementLocationImpl` implement an [ElementLocation].
* @coverage dart.engine.element
*/
class ElementLocationImpl implements ElementLocation {
@@ -2605,9 +2671,9 @@
* @param element the element whose location is being represented
*/
ElementLocationImpl.con1(Element element) {
- _jtd_constructor_196_impl(element);
+ _jtd_constructor_197_impl(element);
}
- _jtd_constructor_196_impl(Element element) {
+ _jtd_constructor_197_impl(Element element) {
List<String> components = new List<String>();
Element ancestor = element;
while (ancestor != null) {
@@ -2622,9 +2688,9 @@
* @param encoding the encoded form of a location
*/
ElementLocationImpl.con2(String encoding) {
- _jtd_constructor_197_impl(encoding);
+ _jtd_constructor_198_impl(encoding);
}
- _jtd_constructor_197_impl(String encoding) {
+ _jtd_constructor_198_impl(String encoding) {
this._components = decode(encoding);
}
bool operator ==(Object object) {
@@ -2719,11 +2785,11 @@
}
/**
- * Return {@code true} if the given components, when interpreted to be encoded sources with a
+ * Return `true` if the given components, when interpreted to be encoded sources with a
* leading source type indicator, are equal when the source type's are ignored.
* @param left the left component being compared
* @param right the right component being compared
- * @return {@code true} if the given components are equal when the source type's are ignored
+ * @return `true` if the given components are equal when the source type's are ignored
*/
bool equalSourceComponents(String left, String right) {
if (left == null) {
@@ -2738,7 +2804,7 @@
}
}
/**
- * Instances of the class {@code EmbeddedHtmlScriptElementImpl} implement an{@link EmbeddedHtmlScriptElement}.
+ * Instances of the class `EmbeddedHtmlScriptElementImpl` implement an[EmbeddedHtmlScriptElement].
* @coverage dart.engine.element
*/
class EmbeddedHtmlScriptElementImpl extends HtmlScriptElementImpl implements EmbeddedHtmlScriptElement {
@@ -2750,7 +2816,7 @@
/**
* Initialize a newly created script element to have the specified tag name and offset.
- * @param node the XML node from which this element is derived (not {@code null})
+ * @param node the XML node from which this element is derived (not `null`)
*/
EmbeddedHtmlScriptElementImpl(XmlTagNode node) : super(node) {
}
@@ -2760,7 +2826,7 @@
/**
* Set the script library defined by the script tag's content.
- * @param scriptLibrary the library or {@code null} if none
+ * @param scriptLibrary the library or `null` if none
*/
void set scriptLibrary(LibraryElementImpl scriptLibrary2) {
scriptLibrary2.enclosingElement = this;
@@ -2771,7 +2837,7 @@
}
}
/**
- * The abstract class {@code ExecutableElementImpl} implements the behavior common to{@code ExecutableElement}s.
+ * The abstract class `ExecutableElementImpl` implements the behavior common to`ExecutableElement`s.
* @coverage dart.engine.element
*/
abstract class ExecutableElementImpl extends ElementImpl implements ExecutableElement {
@@ -2797,6 +2863,11 @@
List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
/**
+ * The return type defined by this executable element.
+ */
+ Type2 _returnType;
+
+ /**
* The type of function defined by this executable element.
*/
FunctionType _type;
@@ -2811,9 +2882,9 @@
* @param name the name of this element
*/
ExecutableElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_199_impl(name);
+ _jtd_constructor_200_impl(name);
}
- _jtd_constructor_199_impl(Identifier name) {
+ _jtd_constructor_200_impl(Identifier name) {
}
/**
@@ -2823,9 +2894,9 @@
* declaration of this element
*/
ExecutableElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset) {
- _jtd_constructor_200_impl(name, nameOffset);
+ _jtd_constructor_201_impl(name, nameOffset);
}
- _jtd_constructor_200_impl(String name, int nameOffset) {
+ _jtd_constructor_201_impl(String name, int nameOffset) {
}
ElementImpl getChild(String identifier2) {
for (ExecutableElement function in _functions) {
@@ -2854,8 +2925,9 @@
List<LabelElement> get labels => _labels;
List<LocalVariableElement> get localVariables => _localVariables;
List<ParameterElement> get parameters => _parameters;
+ Type2 get returnType => _returnType;
FunctionType get type => _type;
- bool isOperator() => false;
+ bool get isOperator => false;
/**
* Set the functions defined within this executable element to the given functions.
@@ -2902,6 +2974,14 @@
}
/**
+ * Set the return type defined by this executable element.
+ * @param returnType the return type defined by this executable element
+ */
+ void set returnType(Type2 returnType2) {
+ this._returnType = returnType2;
+ }
+
+ /**
* Set the type of function defined by this executable element to the given type.
* @param type the type of function defined by this executable element
*/
@@ -2932,7 +3012,7 @@
}
}
/**
- * Instances of the class {@code ExportElementImpl} implement an {@link ExportElement}.
+ * Instances of the class `ExportElementImpl` implement an [ExportElement].
* @coverage dart.engine.element
*/
class ExportElementImpl extends ElementImpl implements ExportElement {
@@ -2996,19 +3076,19 @@
String get identifier => _exportedLibrary.name;
}
/**
- * Instances of the class {@code ExternalHtmlScriptElementImpl} implement an{@link ExternalHtmlScriptElement}.
+ * Instances of the class `ExternalHtmlScriptElementImpl` implement an[ExternalHtmlScriptElement].
* @coverage dart.engine.element
*/
class ExternalHtmlScriptElementImpl extends HtmlScriptElementImpl implements ExternalHtmlScriptElement {
/**
- * The source specified in the {@code source} attribute or {@code null} if unspecified.
+ * The source specified in the `source` attribute or `null` if unspecified.
*/
Source _scriptSource;
/**
* Initialize a newly created script element to have the specified tag name and offset.
- * @param node the XML node from which this element is derived (not {@code null})
+ * @param node the XML node from which this element is derived (not `null`)
*/
ExternalHtmlScriptElementImpl(XmlTagNode node) : super(node) {
}
@@ -3017,15 +3097,15 @@
Source get scriptSource => _scriptSource;
/**
- * Set the source specified in the {@code source} attribute.
- * @param scriptSource the script source or {@code null} if unspecified
+ * Set the source specified in the `source` attribute.
+ * @param scriptSource the script source or `null` if unspecified
*/
void set scriptSource(Source scriptSource2) {
this._scriptSource = scriptSource2;
}
}
/**
- * Instances of the class {@code FieldElementImpl} implement a {@code FieldElement}.
+ * Instances of the class `FieldElementImpl` implement a `FieldElement`.
* @coverage dart.engine.element
*/
class FieldElementImpl extends PropertyInducingElementImpl implements FieldElement {
@@ -3040,9 +3120,9 @@
* @param name the name of this element
*/
FieldElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_203_impl(name);
+ _jtd_constructor_204_impl(name);
}
- _jtd_constructor_203_impl(Identifier name) {
+ _jtd_constructor_204_impl(Identifier name) {
}
/**
@@ -3050,25 +3130,25 @@
* @param name the name of this element
*/
FieldElementImpl.con2(String name) : super.con2(name) {
- _jtd_constructor_204_impl(name);
+ _jtd_constructor_205_impl(name);
}
- _jtd_constructor_204_impl(String name) {
+ _jtd_constructor_205_impl(String name) {
}
accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
ClassElement get enclosingElement => super.enclosingElement as ClassElement;
ElementKind get kind => ElementKind.FIELD;
- bool isStatic() => hasModifier(Modifier.STATIC);
+ bool get isStatic => hasModifier(Modifier.STATIC);
/**
* Set whether this field is static to correspond to the given value.
- * @param isStatic {@code true} if the field is static
+ * @param isStatic `true` if the field is static
*/
void set static(bool isStatic) {
setModifier(Modifier.STATIC, isStatic);
}
}
/**
- * Instances of the class {@code FieldFormalParameterElementImpl} extend{@link ParameterElementImpl} to provide the additional information of the {@link FieldElement}associated with the parameter.
+ * Instances of the class `FieldFormalParameterElementImpl` extend[ParameterElementImpl] to provide the additional information of the [FieldElement]associated with the parameter.
* @coverage dart.engine.element
*/
class FieldFormalParameterElementImpl extends ParameterElementImpl implements FieldFormalParameterElement {
@@ -3086,7 +3166,7 @@
}
accept(ElementVisitor visitor) => visitor.visitFieldFormalParameterElement(this);
FieldElement get field => _field;
- bool isInitializingFormal() => true;
+ bool get isInitializingFormal => true;
/**
* Set the field element associated with this field formal parameter to the given element.
@@ -3097,7 +3177,7 @@
}
}
/**
- * Instances of the class {@code FunctionElementImpl} implement a {@code FunctionElement}.
+ * Instances of the class `FunctionElementImpl` implement a `FunctionElement`.
* @coverage dart.engine.element
*/
class FunctionElementImpl extends ExecutableElementImpl implements FunctionElement {
@@ -3108,7 +3188,7 @@
int _visibleRangeOffset = 0;
/**
- * The length of the visible range for this element, or {@code -1} if this element does not have a
+ * The length of the visible range for this element, or `-1` if this element does not have a
* visible range.
*/
int _visibleRangeLength = -1;
@@ -3122,9 +3202,9 @@
* Initialize a newly created synthetic function element.
*/
FunctionElementImpl() : super.con2("", -1) {
- _jtd_constructor_206_impl();
+ _jtd_constructor_207_impl();
}
- _jtd_constructor_206_impl() {
+ _jtd_constructor_207_impl() {
synthetic = true;
}
@@ -3133,9 +3213,9 @@
* @param name the name of this element
*/
FunctionElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_207_impl(name);
+ _jtd_constructor_208_impl(name);
}
- _jtd_constructor_207_impl(Identifier name) {
+ _jtd_constructor_208_impl(Identifier name) {
}
/**
@@ -3145,9 +3225,9 @@
* declaration of this element
*/
FunctionElementImpl.con2(int nameOffset) : super.con2("", nameOffset) {
- _jtd_constructor_208_impl(nameOffset);
+ _jtd_constructor_209_impl(nameOffset);
}
- _jtd_constructor_208_impl(int nameOffset) {
+ _jtd_constructor_209_impl(int nameOffset) {
}
accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
String get identifier => "${name}@${nameOffset}";
@@ -3158,13 +3238,13 @@
}
return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
}
- bool isStatic() => enclosingElement is CompilationUnitElement;
+ bool get isStatic => enclosingElement is CompilationUnitElement;
/**
* Set the visible range for this element to the range starting at the given offset with the given
* length.
* @param offset the offset to the beginning of the visible range for this element
- * @param length the length of the visible range for this element, or {@code -1} if this element
+ * @param length the length of the visible range for this element, or `-1` if this element
* does not have a visible range
*/
void setVisibleRange(int offset, int length) {
@@ -3180,7 +3260,7 @@
}
}
/**
- * Instances of the class {@code FunctionTypeAliasElementImpl} implement a{@code FunctionTypeAliasElement}.
+ * Instances of the class `FunctionTypeAliasElementImpl` implement a`FunctionTypeAliasElement`.
* @coverage dart.engine.element
*/
class FunctionTypeAliasElementImpl extends ElementImpl implements FunctionTypeAliasElement {
@@ -3191,6 +3271,11 @@
List<ParameterElement> _parameters = ParameterElementImpl.EMPTY_ARRAY;
/**
+ * The return type defined by this type alias.
+ */
+ Type2 _returnType;
+
+ /**
* The type of function defined by this type alias.
*/
FunctionType _type;
@@ -3228,6 +3313,7 @@
CompilationUnitElement get enclosingElement => super.enclosingElement as CompilationUnitElement;
ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
List<ParameterElement> get parameters => _parameters;
+ Type2 get returnType => _returnType;
FunctionType get type => _type;
List<TypeVariableElement> get typeVariables => _typeVariables;
@@ -3245,6 +3331,14 @@
}
/**
+ * Set the return type defined by this type alias.
+ * @param returnType the return type defined by this type alias
+ */
+ void set returnType(Type2 returnType2) {
+ this._returnType = returnType2;
+ }
+
+ /**
* Set the type of function defined by this type alias to the given type.
* @param type the type of function defined by this type alias
*/
@@ -3297,7 +3391,7 @@
}
}
/**
- * Instances of the class {@code HideElementCombinatorImpl} implement a{@link HideElementCombinator}.
+ * Instances of the class `HideElementCombinatorImpl` implement a[HideElementCombinator].
* @coverage dart.engine.element
*/
class HideElementCombinatorImpl implements HideElementCombinator {
@@ -3331,7 +3425,7 @@
}
}
/**
- * Instances of the class {@code HtmlElementImpl} implement an {@link HtmlElement}.
+ * Instances of the class `HtmlElementImpl` implement an [HtmlElement].
* @coverage dart.engine.element
*/
class HtmlElementImpl extends ElementImpl implements HtmlElement {
@@ -3406,7 +3500,7 @@
}
}
/**
- * Instances of the class {@code HtmlScriptElementImpl} implement an {@link HtmlScriptElement}.
+ * Instances of the class `HtmlScriptElementImpl` implement an [HtmlScriptElement].
* @coverage dart.engine.element
*/
abstract class HtmlScriptElementImpl extends ElementImpl implements HtmlScriptElement {
@@ -3418,13 +3512,13 @@
/**
* Initialize a newly created script element to have the specified tag name and offset.
- * @param node the XML node from which this element is derived (not {@code null})
+ * @param node the XML node from which this element is derived (not `null`)
*/
HtmlScriptElementImpl(XmlTagNode node) : super.con2(node.tag.lexeme, node.tag.offset) {
}
}
/**
- * Instances of the class {@code ImportElementImpl} implement an {@link ImportElement}.
+ * Instances of the class `ImportElementImpl` implement an [ImportElement].
* @coverage dart.engine.element
*/
class ImportElementImpl extends ElementImpl implements ImportElement {
@@ -3446,7 +3540,7 @@
List<NamespaceCombinator> _combinators = NamespaceCombinator.EMPTY_ARRAY;
/**
- * The prefix that was specified as part of the import directive, or {@code null} if there was no
+ * The prefix that was specified as part of the import directive, or `null` if there was no
* prefix specified.
*/
PrefixElement _prefix;
@@ -3507,18 +3601,18 @@
String get identifier => ((_importedLibrary as LibraryElementImpl)).identifier;
}
/**
- * Instances of the class {@code LabelElementImpl} implement a {@code LabelElement}.
+ * Instances of the class `LabelElementImpl` implement a `LabelElement`.
* @coverage dart.engine.element
*/
class LabelElementImpl extends ElementImpl implements LabelElement {
/**
- * A flag indicating whether this label is associated with a {@code switch} statement.
+ * A flag indicating whether this label is associated with a `switch` statement.
*/
bool _onSwitchStatement = false;
/**
- * A flag indicating whether this label is associated with a {@code switch} member ({@code case}or {@code default}).
+ * A flag indicating whether this label is associated with a `switch` member (`case`or `default`).
*/
bool _onSwitchMember = false;
@@ -3530,8 +3624,8 @@
/**
* Initialize a newly created label element to have the given name.
* @param name the name of this element
- * @param onSwitchStatement {@code true} if this label is associated with a {@code switch}statement
- * @param onSwitchMember {@code true} if this label is associated with a {@code switch} member
+ * @param onSwitchStatement `true` if this label is associated with a `switch`statement
+ * @param onSwitchMember `true` if this label is associated with a `switch` member
*/
LabelElementImpl(Identifier name, bool onSwitchStatement, bool onSwitchMember) : super.con1(name) {
this._onSwitchStatement = onSwitchStatement;
@@ -3542,19 +3636,19 @@
ElementKind get kind => ElementKind.LABEL;
/**
- * Return {@code true} if this label is associated with a {@code switch} member ({@code case} or{@code default}).
- * @return {@code true} if this label is associated with a {@code switch} member
+ * Return `true` if this label is associated with a `switch` member (`case` or`default`).
+ * @return `true` if this label is associated with a `switch` member
*/
- bool isOnSwitchMember() => _onSwitchMember;
+ bool get isOnSwitchMember => _onSwitchMember;
/**
- * Return {@code true} if this label is associated with a {@code switch} statement.
- * @return {@code true} if this label is associated with a {@code switch} statement
+ * Return `true` if this label is associated with a `switch` statement.
+ * @return `true` if this label is associated with a `switch` statement
*/
- bool isOnSwitchStatement() => _onSwitchStatement;
+ bool get isOnSwitchStatement => _onSwitchStatement;
}
/**
- * Instances of the class {@code LibraryElementImpl} implement a {@code LibraryElement}.
+ * Instances of the class `LibraryElementImpl` implement a `LibraryElement`.
* @coverage dart.engine.element
*/
class LibraryElementImpl extends ElementImpl implements LibraryElement {
@@ -3606,7 +3700,7 @@
CompilationUnitElement _definingCompilationUnit;
/**
- * The entry point for this library, or {@code null} if this library does not have an entry point.
+ * The entry point for this library, or `null` if this library does not have an entry point.
*/
FunctionElement _entryPoint;
@@ -3621,7 +3715,7 @@
List<ExportElement> _exports = ExportElement.EMPTY_ARRAY;
/**
- * An array containing all of the compilation units that are included in this library using a{@code part} directive.
+ * An array containing all of the compilation units that are included in this library using a`part` directive.
*/
List<CompilationUnitElement> _parts = CompilationUnitElementImpl.EMPTY_ARRAY;
@@ -3715,8 +3809,8 @@
return null;
}
int get hashCode => _definingCompilationUnit.hashCode;
- bool isBrowserApplication() => _entryPoint != null && isOrImportsBrowserLibrary();
- bool isDartCore() => name == "dart.core";
+ bool get isBrowserApplication => _entryPoint != null && isOrImportsBrowserLibrary;
+ bool get isDartCore => name == "dart.core";
bool isUpToDate2(int timeStamp) {
Set<LibraryElement> visitedLibraries = new Set();
return isUpToDate(this, timeStamp, visitedLibraries);
@@ -3766,8 +3860,8 @@
}
/**
- * Set the compilation units that are included in this library using a {@code part} directive.
- * @param parts the compilation units that are included in this library using a {@code part}directive
+ * Set the compilation units that are included in this library using a `part` directive.
+ * @param parts the compilation units that are included in this library using a `part`directive
*/
void set parts(List<CompilationUnitElement> parts2) {
for (CompilationUnitElement compilationUnit in parts2) {
@@ -3784,10 +3878,10 @@
}
/**
- * Answer {@code true} if the receiver directly or indirectly imports the dart:html libraries.
- * @return {@code true} if the receiver directly or indirectly imports the dart:html libraries
+ * Answer `true` if the receiver directly or indirectly imports the dart:html libraries.
+ * @return `true` if the receiver directly or indirectly imports the dart:html libraries
*/
- bool isOrImportsBrowserLibrary() {
+ bool get isOrImportsBrowserLibrary {
List<LibraryElement> visited = new List<LibraryElement>();
Source htmlLibSource = _context.sourceFactory.forUri(DartSdk.DART_HTML);
visited.add(this);
@@ -3812,7 +3906,7 @@
}
}
/**
- * Instances of the class {@code LocalVariableElementImpl} implement a {@code LocalVariableElement}.
+ * Instances of the class `LocalVariableElementImpl` implement a `LocalVariableElement`.
* @coverage dart.engine.element
*/
class LocalVariableElementImpl extends VariableElementImpl implements LocalVariableElement {
@@ -3823,7 +3917,7 @@
int _visibleRangeOffset = 0;
/**
- * The length of the visible range for this element, or {@code -1} if this element does not have a
+ * The length of the visible range for this element, or `-1` if this element does not have a
* visible range.
*/
int _visibleRangeLength = -1;
@@ -3852,7 +3946,7 @@
* Set the visible range for this element to the range starting at the given offset with the given
* length.
* @param offset the offset to the beginning of the visible range for this element
- * @param length the length of the visible range for this element, or {@code -1} if this element
+ * @param length the length of the visible range for this element, or `-1` if this element
* does not have a visible range
*/
void setVisibleRange(int offset, int length) {
@@ -3867,7 +3961,7 @@
String get identifier => "${super.identifier}@${nameOffset}";
}
/**
- * Instances of the class {@code MethodElementImpl} implement a {@code MethodElement}.
+ * Instances of the class `MethodElementImpl` implement a `MethodElement`.
* @coverage dart.engine.element
*/
class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
@@ -3882,9 +3976,9 @@
* @param name the name of this element
*/
MethodElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_217_impl(name);
+ _jtd_constructor_218_impl(name);
}
- _jtd_constructor_217_impl(Identifier name) {
+ _jtd_constructor_218_impl(Identifier name) {
}
/**
@@ -3894,24 +3988,24 @@
* declaration of this element
*/
MethodElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset) {
- _jtd_constructor_218_impl(name, nameOffset);
+ _jtd_constructor_219_impl(name, nameOffset);
}
- _jtd_constructor_218_impl(String name, int nameOffset) {
+ _jtd_constructor_219_impl(String name, int nameOffset) {
}
accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
ClassElement get enclosingElement => super.enclosingElement as ClassElement;
ElementKind get kind => ElementKind.METHOD;
String get name {
String name = super.name;
- if (isOperator() && name == "-") {
+ if (isOperator && name == "-") {
if (parameters.length == 0) {
return "unary-";
}
}
return super.name;
}
- bool isAbstract() => hasModifier(Modifier.ABSTRACT);
- bool isOperator() {
+ bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+ bool get isOperator {
String name = displayName;
if (name.isEmpty) {
return false;
@@ -3919,11 +4013,11 @@
int first = name.codeUnitAt(0);
return !((0x61 <= first && first <= 0x7A) || (0x41 <= first && first <= 0x5A) || first == 0x5F || first == 0x24);
}
- bool isStatic() => hasModifier(Modifier.STATIC);
+ bool get isStatic => hasModifier(Modifier.STATIC);
/**
* Set whether this method is abstract to correspond to the given value.
- * @param isAbstract {@code true} if the method is abstract
+ * @param isAbstract `true` if the method is abstract
*/
void set abstract(bool isAbstract) {
setModifier(Modifier.ABSTRACT, isAbstract);
@@ -3931,7 +4025,7 @@
/**
* Set whether this method is static to correspond to the given value.
- * @param isStatic {@code true} if the method is static
+ * @param isStatic `true` if the method is static
*/
void set static(bool isStatic) {
setModifier(Modifier.STATIC, isStatic);
@@ -3944,7 +4038,7 @@
}
}
/**
- * The enumeration {@code Modifier} defines constants for all of the modifiers defined by the Dart
+ * The enumeration `Modifier` defines constants for all of the modifiers defined by the Dart
* language and for a few additional flags that are useful.
* @coverage dart.engine.element
*/
@@ -3974,7 +4068,7 @@
String toString() => name;
}
/**
- * Instances of the class {@code MultiplyDefinedElementImpl} represent a collection of elements that
+ * Instances of the class `MultiplyDefinedElementImpl` represent a collection of elements that
* have the same name within the same scope.
* @coverage dart.engine.element
*/
@@ -4027,7 +4121,7 @@
}
return false;
}
- bool isSynthetic() => true;
+ bool get isSynthetic => true;
String toString() {
JavaStringBuilder builder = new JavaStringBuilder();
builder.append("[");
@@ -4076,7 +4170,7 @@
}
}
/**
- * Instances of the class {@code ParameterElementImpl} implement a {@code ParameterElement}.
+ * Instances of the class `ParameterElementImpl` implement a `ParameterElement`.
* @coverage dart.engine.element
*/
class ParameterElementImpl extends VariableElementImpl implements ParameterElement {
@@ -4098,7 +4192,7 @@
int _defaultValueRangeOffset = 0;
/**
- * The length of the default value range for this element, or {@code -1} if this element does not
+ * The length of the default value range for this element, or `-1` if this element does not
* have a default value.
*/
int _defaultValueRangeLength = -1;
@@ -4109,7 +4203,7 @@
int _visibleRangeOffset = 0;
/**
- * The length of the visible range for this element, or {@code -1} if this element does not have a
+ * The length of the visible range for this element, or `-1` if this element does not have a
* visible range.
*/
int _visibleRangeLength = -1;
@@ -4141,13 +4235,13 @@
}
return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
}
- bool isInitializingFormal() => false;
+ bool get isInitializingFormal => false;
/**
* Set the range of the default value for this parameter to the range starting at the given offset
* with the given length.
* @param offset the offset to the beginning of the default value range for this element
- * @param length the length of the default value range for this element, or {@code -1} if this
+ * @param length the length of the default value range for this element, or `-1` if this
* element does not have a default value
*/
void setDefaultValueRange(int offset, int length) {
@@ -4178,7 +4272,7 @@
* Set the visible range for this element to the range starting at the given offset with the given
* length.
* @param offset the offset to the beginning of the visible range for this element
- * @param length the length of the visible range for this element, or {@code -1} if this element
+ * @param length the length of the visible range for this element, or `-1` if this element
* does not have a visible range
*/
void setVisibleRange(int offset, int length) {
@@ -4210,7 +4304,7 @@
}
}
/**
- * Instances of the class {@code PrefixElementImpl} implement a {@code PrefixElement}.
+ * Instances of the class `PrefixElementImpl` implement a `PrefixElement`.
* @coverage dart.engine.element
*/
class PrefixElementImpl extends ElementImpl implements PrefixElement {
@@ -4252,7 +4346,7 @@
}
}
/**
- * Instances of the class {@code PropertyAccessorElementImpl} implement a{@code PropertyAccessorElement}.
+ * Instances of the class `PropertyAccessorElementImpl` implement a`PropertyAccessorElement`.
* @coverage dart.engine.element
*/
class PropertyAccessorElementImpl extends ExecutableElementImpl implements PropertyAccessorElement {
@@ -4272,9 +4366,9 @@
* @param name the name of this element
*/
PropertyAccessorElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_223_impl(name);
+ _jtd_constructor_224_impl(name);
}
- _jtd_constructor_223_impl(Identifier name) {
+ _jtd_constructor_224_impl(Identifier name) {
}
/**
@@ -4283,47 +4377,47 @@
* @param variable the variable with which this access is associated
*/
PropertyAccessorElementImpl.con2(PropertyInducingElementImpl variable2) : super.con2(variable2.name, variable2.nameOffset) {
- _jtd_constructor_224_impl(variable2);
+ _jtd_constructor_225_impl(variable2);
}
- _jtd_constructor_224_impl(PropertyInducingElementImpl variable2) {
+ _jtd_constructor_225_impl(PropertyInducingElementImpl variable2) {
this._variable = variable2;
synthetic = true;
}
accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
- bool operator ==(Object object) => super == object && identical(isGetter(), ((object as PropertyAccessorElement)).isGetter());
+ bool operator ==(Object object) => super == object && identical(isGetter, ((object as PropertyAccessorElement)).isGetter);
PropertyAccessorElement get correspondingGetter {
- if (isGetter() || _variable == null) {
+ if (isGetter || _variable == null) {
return null;
}
return _variable.getter;
}
PropertyAccessorElement get correspondingSetter {
- if (isSetter() || _variable == null) {
+ if (isSetter || _variable == null) {
return null;
}
return _variable.setter;
}
ElementKind get kind {
- if (isGetter()) {
+ if (isGetter) {
return ElementKind.GETTER;
}
return ElementKind.SETTER;
}
String get name {
- if (isSetter()) {
+ if (isSetter) {
return "${super.name}=";
}
return super.name;
}
PropertyInducingElement get variable => _variable;
- bool isAbstract() => hasModifier(Modifier.ABSTRACT);
- bool isGetter() => hasModifier(Modifier.GETTER);
- bool isSetter() => hasModifier(Modifier.SETTER);
- bool isStatic() => hasModifier(Modifier.STATIC);
+ bool get isAbstract => hasModifier(Modifier.ABSTRACT);
+ bool get isGetter => hasModifier(Modifier.GETTER);
+ bool get isSetter => hasModifier(Modifier.SETTER);
+ bool get isStatic => hasModifier(Modifier.STATIC);
/**
* Set whether this accessor is abstract to correspond to the given value.
- * @param isAbstract {@code true} if the accessor is abstract
+ * @param isAbstract `true` if the accessor is abstract
*/
void set abstract(bool isAbstract) {
setModifier(Modifier.ABSTRACT, isAbstract);
@@ -4331,7 +4425,7 @@
/**
* Set whether this accessor is a getter to correspond to the given value.
- * @param isGetter {@code true} if the accessor is a getter
+ * @param isGetter `true` if the accessor is a getter
*/
void set getter(bool isGetter) {
setModifier(Modifier.GETTER, isGetter);
@@ -4339,7 +4433,7 @@
/**
* Set whether this accessor is a setter to correspond to the given value.
- * @param isSetter {@code true} if the accessor is a setter
+ * @param isSetter `true` if the accessor is a setter
*/
void set setter(bool isSetter) {
setModifier(Modifier.SETTER, isSetter);
@@ -4347,7 +4441,7 @@
/**
* Set whether this accessor is static to correspond to the given value.
- * @param isStatic {@code true} if the accessor is static
+ * @param isStatic `true` if the accessor is static
*/
void set static(bool isStatic) {
setModifier(Modifier.STATIC, isStatic);
@@ -4361,13 +4455,13 @@
this._variable = variable2;
}
void appendTo(JavaStringBuilder builder) {
- builder.append(isGetter() ? "get " : "set ");
+ builder.append(isGetter ? "get " : "set ");
builder.append(variable.displayName);
super.appendTo(builder);
}
}
/**
- * Instances of the class {@code PropertyInducingElementImpl} implement a{@code PropertyInducingElement}.
+ * Instances of the class `PropertyInducingElementImpl` implement a`PropertyInducingElement`.
* @coverage dart.engine.element
*/
abstract class PropertyInducingElementImpl extends VariableElementImpl implements PropertyInducingElement {
@@ -4378,7 +4472,7 @@
PropertyAccessorElement _getter;
/**
- * The setter associated with this element, or {@code null} if the element is effectively{@code final} and therefore does not have a setter associated with it.
+ * The setter associated with this element, or `null` if the element is effectively`final` and therefore does not have a setter associated with it.
*/
PropertyAccessorElement _setter;
@@ -4392,9 +4486,9 @@
* @param name the name of this element
*/
PropertyInducingElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_225_impl(name);
+ _jtd_constructor_226_impl(name);
}
- _jtd_constructor_225_impl(Identifier name) {
+ _jtd_constructor_226_impl(Identifier name) {
}
/**
@@ -4402,9 +4496,9 @@
* @param name the name of this element
*/
PropertyInducingElementImpl.con2(String name) : super.con2(name, -1) {
- _jtd_constructor_226_impl(name);
+ _jtd_constructor_227_impl(name);
}
- _jtd_constructor_226_impl(String name) {
+ _jtd_constructor_227_impl(String name) {
synthetic = true;
}
PropertyAccessorElement get getter => _getter;
@@ -4427,7 +4521,7 @@
}
}
/**
- * Instances of the class {@code ShowElementCombinatorImpl} implement a{@link ShowElementCombinator}.
+ * Instances of the class `ShowElementCombinatorImpl` implement a[ShowElementCombinator].
* @coverage dart.engine.element
*/
class ShowElementCombinatorImpl implements ShowElementCombinator {
@@ -4461,7 +4555,7 @@
}
}
/**
- * Instances of the class {@code TopLevelVariableElementImpl} implement a{@code TopLevelVariableElement}.
+ * Instances of the class `TopLevelVariableElementImpl` implement a`TopLevelVariableElement`.
* @coverage dart.engine.element
*/
class TopLevelVariableElementImpl extends PropertyInducingElementImpl implements TopLevelVariableElement {
@@ -4476,9 +4570,9 @@
* @param name the name of this element
*/
TopLevelVariableElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_228_impl(name);
+ _jtd_constructor_229_impl(name);
}
- _jtd_constructor_228_impl(Identifier name) {
+ _jtd_constructor_229_impl(Identifier name) {
}
/**
@@ -4486,16 +4580,16 @@
* @param name the name of this element
*/
TopLevelVariableElementImpl.con2(String name) : super.con2(name) {
- _jtd_constructor_229_impl(name);
+ _jtd_constructor_230_impl(name);
}
- _jtd_constructor_229_impl(String name) {
+ _jtd_constructor_230_impl(String name) {
}
accept(ElementVisitor visitor) => visitor.visitTopLevelVariableElement(this);
ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;
- bool isStatic() => true;
+ bool get isStatic => true;
}
/**
- * Instances of the class {@code TypeVariableElementImpl} implement a {@code TypeVariableElement}.
+ * Instances of the class `TypeVariableElementImpl` implement a `TypeVariableElement`.
* @coverage dart.engine.element
*/
class TypeVariableElementImpl extends ElementImpl implements TypeVariableElement {
@@ -4506,7 +4600,7 @@
TypeVariableType _type;
/**
- * The type representing the bound associated with this variable, or {@code null} if this variable
+ * The type representing the bound associated with this variable, or `null` if this variable
* does not have an explicit bound.
*/
Type2 _bound;
@@ -4551,7 +4645,7 @@
}
}
/**
- * Instances of the class {@code VariableElementImpl} implement a {@code VariableElement}.
+ * Instances of the class `VariableElementImpl` implement a `VariableElement`.
* @coverage dart.engine.element
*/
abstract class VariableElementImpl extends ElementImpl implements VariableElement {
@@ -4562,7 +4656,7 @@
Type2 _type;
/**
- * A synthetic function representing this variable's initializer, or {@code null} if this variable
+ * A synthetic function representing this variable's initializer, or `null` if this variable
* does not have an initializer.
*/
FunctionElement _initializer;
@@ -4577,9 +4671,9 @@
* @param name the name of this element
*/
VariableElementImpl.con1(Identifier name) : super.con1(name) {
- _jtd_constructor_231_impl(name);
+ _jtd_constructor_232_impl(name);
}
- _jtd_constructor_231_impl(Identifier name) {
+ _jtd_constructor_232_impl(Identifier name) {
}
/**
@@ -4589,26 +4683,26 @@
* declaration of this element
*/
VariableElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset) {
- _jtd_constructor_232_impl(name, nameOffset);
+ _jtd_constructor_233_impl(name, nameOffset);
}
- _jtd_constructor_232_impl(String name, int nameOffset) {
+ _jtd_constructor_233_impl(String name, int nameOffset) {
}
/**
* Return the result of evaluating this variable's initializer as a compile-time constant
- * expression, or {@code null} if this variable is not a 'const' variable or does not have an
+ * expression, or `null` if this variable is not a 'const' variable or does not have an
* initializer.
* @return the result of evaluating this variable's initializer
*/
EvaluationResultImpl get evaluationResult => null;
FunctionElement get initializer => _initializer;
Type2 get type => _type;
- bool isConst() => hasModifier(Modifier.CONST);
- bool isFinal() => hasModifier(Modifier.FINAL);
+ bool get isConst => hasModifier(Modifier.CONST);
+ bool get isFinal => hasModifier(Modifier.FINAL);
/**
* Set whether this variable is const to correspond to the given value.
- * @param isConst {@code true} if the variable is const
+ * @param isConst `true` if the variable is const
*/
void set const3(bool isConst) {
setModifier(Modifier.CONST, isConst);
@@ -4625,7 +4719,7 @@
/**
* Set whether this variable is final to correspond to the given value.
- * @param isFinal {@code true} if the variable is final
+ * @param isFinal `true` if the variable is final
*/
void set final2(bool isFinal) {
setModifier(Modifier.FINAL, isFinal);
@@ -4660,7 +4754,7 @@
}
}
/**
- * Instances of the class {@code ConstructorMember} represent a constructor element defined in a
+ * Instances of the class `ConstructorMember` represent a constructor element defined in a
* parameterized type where the values of the type parameters are known.
*/
class ConstructorMember extends ExecutableMember implements ConstructorElement {
@@ -4681,7 +4775,7 @@
}
FunctionType baseType = baseConstructor.type;
List<Type2> argumentTypes = definingType.typeArguments;
- List<Type2> parameterTypes = TypeVariableTypeImpl.getTypes(definingType.element.typeVariables);
+ List<Type2> parameterTypes = definingType.element.type.typeArguments;
FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
if (baseType == substitutedType) {
return baseConstructor;
@@ -4700,8 +4794,9 @@
ConstructorElement get baseElement => super.baseElement as ConstructorElement;
ClassElement get enclosingElement => baseElement.enclosingElement;
ConstructorElement get redirectedConstructor => from(baseElement.redirectedConstructor, definingType);
- bool isConst() => baseElement.isConst();
- bool isFactory() => baseElement.isFactory();
+ bool get isConst => baseElement.isConst;
+ bool get isDefaultConstructor => baseElement.isDefaultConstructor;
+ bool get isFactory => baseElement.isFactory;
String toString() {
ConstructorElement baseElement = this.baseElement;
List<ParameterElement> parameters = this.parameters;
@@ -4731,7 +4826,7 @@
InterfaceType get definingType => super.definingType as InterfaceType;
}
/**
- * The abstract class {@code ExecutableMember} defines the behavior common to members that represent
+ * The abstract class `ExecutableMember` defines the behavior common to members that represent
* an executable element defined in a parameterized type where the values of the type parameters are
* known.
*/
@@ -4765,9 +4860,10 @@
}
return parameterizedParameters;
}
+ Type2 get returnType => substituteFor(baseElement.returnType);
FunctionType get type => substituteFor(baseElement.type);
- bool isOperator() => baseElement.isOperator();
- bool isStatic() => baseElement.isStatic();
+ bool get isOperator => baseElement.isOperator;
+ bool get isStatic => baseElement.isStatic;
void visitChildren(ElementVisitor<Object> visitor) {
super.visitChildren(visitor);
safelyVisitChildren(baseElement.functions, visitor);
@@ -4777,7 +4873,7 @@
}
}
/**
- * Instances of the class {@code FieldMember} represent a field element defined in a parameterized
+ * Instances of the class `FieldMember` represent a field element defined in a parameterized
* type where the values of the type parameters are known.
*/
class FieldMember extends VariableMember implements FieldElement {
@@ -4801,7 +4897,7 @@
return baseField;
}
List<Type2> argumentTypes = definingType.typeArguments;
- List<Type2> parameterTypes = TypeVariableTypeImpl.getTypes(definingType.element.typeVariables);
+ List<Type2> parameterTypes = definingType.element.type.typeArguments;
Type2 substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
if (baseType == substitutedType) {
return baseField;
@@ -4821,11 +4917,11 @@
ClassElement get enclosingElement => baseElement.enclosingElement;
PropertyAccessorElement get getter => PropertyAccessorMember.from(baseElement.getter, definingType);
PropertyAccessorElement get setter => PropertyAccessorMember.from(baseElement.setter, definingType);
- bool isStatic() => baseElement.isStatic();
+ bool get isStatic => baseElement.isStatic;
InterfaceType get definingType => super.definingType as InterfaceType;
}
/**
- * The abstract class {@code Member} defines the behavior common to elements that represent members
+ * The abstract class `Member` defines the behavior common to elements that represent members
* of parameterized types.
*/
abstract class Member implements Element {
@@ -4867,7 +4963,7 @@
int get nameOffset => _baseElement.nameOffset;
Source get source => _baseElement.source;
bool isAccessibleIn(LibraryElement library) => _baseElement.isAccessibleIn(library);
- bool isSynthetic() => _baseElement.isSynthetic();
+ bool get isSynthetic => _baseElement.isSynthetic;
void visitChildren(ElementVisitor<Object> visitor) {
}
@@ -4878,7 +4974,7 @@
ParameterizedType get definingType => _definingType;
/**
- * If the given child is not {@code null}, use the given visitor to visit it.
+ * If the given child is not `null`, use the given visitor to visit it.
* @param child the child to be visited
* @param visitor the visitor to be used to visit the child
*/
@@ -4929,7 +5025,7 @@
}
}
/**
- * Instances of the class {@code MethodMember} represent a method element defined in a parameterized
+ * Instances of the class `MethodMember` represent a method element defined in a parameterized
* type where the values of the type parameters are known.
*/
class MethodMember extends ExecutableMember implements MethodElement {
@@ -4950,7 +5046,7 @@
}
FunctionType baseType = baseMethod.type;
List<Type2> argumentTypes = definingType.typeArguments;
- List<Type2> parameterTypes = TypeVariableTypeImpl.getTypes(definingType.element.typeVariables);
+ List<Type2> parameterTypes = definingType.element.type.typeArguments;
FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
if (baseType == substitutedType) {
return baseMethod;
@@ -4968,7 +5064,7 @@
accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
MethodElement get baseElement => super.baseElement as MethodElement;
ClassElement get enclosingElement => baseElement.enclosingElement;
- bool isAbstract() => baseElement.isAbstract();
+ bool get isAbstract => baseElement.isAbstract;
String toString() {
MethodElement baseElement = this.baseElement;
List<ParameterElement> parameters = this.parameters;
@@ -4994,7 +5090,7 @@
}
}
/**
- * Instances of the class {@code ParameterMember} represent a parameter element defined in a
+ * Instances of the class `ParameterMember` represent a parameter element defined in a
* parameterized type where the values of the type parameters are known.
*/
class ParameterMember extends VariableMember implements ParameterElement {
@@ -5063,7 +5159,7 @@
return parameterizedParameters;
}
SourceRange get visibleRange => baseElement.visibleRange;
- bool isInitializingFormal() => baseElement.isInitializingFormal();
+ bool get isInitializingFormal => baseElement.isInitializingFormal;
String toString() {
ParameterElement baseElement = this.baseElement;
String left = "";
@@ -5092,7 +5188,7 @@
}
}
/**
- * Instances of the class {@code PropertyAccessorMember} represent a property accessor element
+ * Instances of the class `PropertyAccessorMember` represent a property accessor element
* defined in a parameterized type where the values of the type parameters are known.
*/
class PropertyAccessorMember extends ExecutableMember implements PropertyAccessorElement {
@@ -5113,7 +5209,7 @@
}
FunctionType baseType = baseAccessor.type;
List<Type2> argumentTypes = definingType.typeArguments;
- List<Type2> parameterTypes = TypeVariableTypeImpl.getTypes(definingType.element.typeVariables);
+ List<Type2> parameterTypes = definingType.element.type.typeArguments;
FunctionType substitutedType = baseType.substitute2(argumentTypes, parameterTypes);
if (baseType == substitutedType) {
return baseAccessor;
@@ -5141,13 +5237,13 @@
}
return variable;
}
- bool isAbstract() => baseElement.isAbstract();
- bool isGetter() => baseElement.isGetter();
- bool isSetter() => baseElement.isSetter();
+ bool get isAbstract => baseElement.isAbstract;
+ bool get isGetter => baseElement.isGetter;
+ bool get isSetter => baseElement.isSetter;
InterfaceType get definingType => super.definingType as InterfaceType;
}
/**
- * The abstract class {@code VariableMember} defines the behavior common to members that represent a
+ * The abstract class `VariableMember` defines the behavior common to members that represent a
* variable element defined in a parameterized type where the values of the type parameters are
* known.
*/
@@ -5166,38 +5262,15 @@
throw new UnsupportedOperationException();
}
Type2 get type => substituteFor(baseElement.type);
- bool isConst() => baseElement.isConst();
- bool isFinal() => baseElement.isFinal();
+ bool get isConst => baseElement.isConst;
+ bool get isFinal => baseElement.isFinal;
void visitChildren(ElementVisitor<Object> visitor) {
super.visitChildren(visitor);
safelyVisitChild(baseElement.initializer, visitor);
}
}
/**
- * Instances of the class {@code AnonymousFunctionTypeImpl} extend the behavior of{@link FunctionTypeImpl} to support anonymous function types created for function typed
- * parameters.
- * @coverage dart.engine.type
- */
-class AnonymousFunctionTypeImpl extends FunctionTypeImpl {
-
- /**
- * An array of parameters elements of this type of function.
- */
- List<ParameterElement> _baseParameters = ParameterElementImpl.EMPTY_ARRAY;
- AnonymousFunctionTypeImpl() : super.con2((null as FunctionTypeAliasElement)) {
- }
-
- /**
- * Sets the parameters elements of this type of function.
- * @param parameters the parameters elements of this type of function
- */
- void set baseParameters(List<ParameterElement> parameters) {
- this._baseParameters = parameters;
- }
- List<ParameterElement> get baseParameters => _baseParameters;
-}
-/**
- * The unique instance of the class {@code BottomTypeImpl} implements the type {@code bottom}.
+ * The unique instance of the class `BottomTypeImpl` implements the type `bottom`.
* @coverage dart.engine.type
*/
class BottomTypeImpl extends TypeImpl {
@@ -5225,7 +5298,7 @@
BottomTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) => this;
}
/**
- * The unique instance of the class {@code DynamicTypeImpl} implements the type {@code dynamic}.
+ * The unique instance of the class `DynamicTypeImpl` implements the type `dynamic`.
* @coverage dart.engine.type
*/
class DynamicTypeImpl extends TypeImpl {
@@ -5248,26 +5321,26 @@
((element as DynamicElementImpl)).type = this;
}
bool operator ==(Object object) => object is DynamicTypeImpl;
- bool isDynamic() => true;
+ bool get isDynamic => true;
bool isMoreSpecificThan(Type2 type) => false;
bool isSubtypeOf(Type2 type) => identical(this, type);
bool isSupertypeOf(Type2 type) => true;
DynamicTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) => this;
}
/**
- * Instances of the class {@code FunctionTypeImpl} defines the behavior common to objects
+ * Instances of the class `FunctionTypeImpl` defines the behavior common to objects
* representing the type of a function, method, constructor, getter, or setter.
* @coverage dart.engine.type
*/
class FunctionTypeImpl extends TypeImpl implements FunctionType {
/**
- * Return {@code true} if all of the name/type pairs in the first map are equal to the
+ * Return `true` if all of the name/type pairs in the first map are equal to the
* corresponding name/type pairs in the second map. The maps are expected to iterate over their
* entries in the same order in which those entries were added to the map.
* @param firstTypes the first map of name/type pairs being compared
* @param secondTypes the second map of name/type pairs being compared
- * @return {@code true} if all of the name/type pairs in the first map are equal to the
+ * @return `true` if all of the name/type pairs in the first map are equal to the
* corresponding name/type pairs in the second map
*/
static bool equals2(Map<String, Type2> firstTypes, Map<String, Type2> secondTypes) {
@@ -5331,11 +5404,6 @@
Map<String, Type2> _namedParameterTypes = new Map();
/**
- * The type of object returned by this type of function.
- */
- Type2 _returnType = VoidTypeImpl.instance;
-
- /**
* Initialize a newly created function type to be declared by the given element and to have the
* given name.
* @param element the element representing the declaration of the function type
@@ -5361,11 +5429,12 @@
return false;
}
FunctionTypeImpl otherType = object as FunctionTypeImpl;
- return element == otherType.element && JavaArrays.equals(_normalParameterTypes, otherType._normalParameterTypes) && JavaArrays.equals(_optionalParameterTypes, otherType._optionalParameterTypes) && equals2(_namedParameterTypes, otherType._namedParameterTypes) && _returnType == otherType._returnType;
+ return element == otherType.element && JavaArrays.equals(_normalParameterTypes, otherType._normalParameterTypes) && JavaArrays.equals(_optionalParameterTypes, otherType._optionalParameterTypes) && equals2(_namedParameterTypes, otherType._namedParameterTypes) && returnType == otherType.returnType;
}
String get displayName {
String name = this.name;
if (name == null) {
+ Type2 returnType = this.returnType;
JavaStringBuilder builder = new JavaStringBuilder();
builder.append("(");
bool needsComma = false;
@@ -5416,10 +5485,10 @@
needsComma = true;
}
builder.append(") -> ");
- if (_returnType == null) {
+ if (returnType == null) {
builder.append("null");
} else {
- builder.append(_returnType.displayName);
+ builder.append(returnType.displayName);
}
name = builder.toString();
}
@@ -5440,13 +5509,20 @@
}
return specializedParameters;
}
- Type2 get returnType => _returnType;
+ Type2 get returnType {
+ Type2 baseReturnType = this.baseReturnType;
+ return baseReturnType.substitute2(_typeArguments, TypeVariableTypeImpl.getTypes(typeVariables));
+ }
List<Type2> get typeArguments => _typeArguments;
List<TypeVariableElement> get typeVariables {
Element element = this.element;
if (element is FunctionTypeAliasElement) {
return ((element as FunctionTypeAliasElement)).typeVariables;
}
+ ClassElement definingClass = element.getAncestor(ClassElement);
+ if (definingClass != null) {
+ return definingClass.typeVariables;
+ }
return TypeVariableElementImpl.EMPTY_ARRAY;
}
int get hashCode {
@@ -5459,7 +5535,7 @@
bool isSubtypeOf(Type2 type) {
if (type == null) {
return false;
- } else if (identical(this, type) || type.isDynamic() || type.isDartCoreFunction() || type.isObject()) {
+ } else if (identical(this, type) || type.isDynamic || type.isDartCoreFunction || type.isObject) {
return true;
} else if (type is! FunctionType) {
return false;
@@ -5561,14 +5637,6 @@
}
/**
- * Set the type of object returned by this type of function to the given type.
- * @param returnType the type of object returned by this type of function
- */
- void set returnType(Type2 returnType2) {
- this._returnType = returnType2;
- }
-
- /**
* Set the actual types of the type arguments to the given types.
* @param typeArguments the actual types of the type arguments
*/
@@ -5585,14 +5653,14 @@
}
Element element = this.element;
FunctionTypeImpl newType = (element is ExecutableElement) ? new FunctionTypeImpl.con1((element as ExecutableElement)) : new FunctionTypeImpl.con2((element as FunctionTypeAliasElement));
- newType.returnType = _returnType.substitute2(argumentTypes, parameterTypes);
newType.normalParameterTypes = TypeImpl.substitute(_normalParameterTypes, argumentTypes, parameterTypes);
newType.optionalParameterTypes = TypeImpl.substitute(_optionalParameterTypes, argumentTypes, parameterTypes);
newType._namedParameterTypes = substitute3(_namedParameterTypes, argumentTypes, parameterTypes);
- newType.typeArguments = argumentTypes;
+ newType.typeArguments = TypeImpl.substitute(_typeArguments, argumentTypes, parameterTypes);
return newType;
}
void appendTo(JavaStringBuilder builder) {
+ Type2 returnType = this.returnType;
builder.append("(");
bool needsComma = false;
if (_normalParameterTypes.length > 0) {
@@ -5642,15 +5710,15 @@
needsComma = true;
}
builder.append(") -> ");
- if (_returnType == null) {
+ if (returnType == null) {
builder.append("null");
} else {
- ((_returnType as TypeImpl)).appendTo(builder);
+ ((returnType as TypeImpl)).appendTo(builder);
}
}
/**
- * @return the base parameter elements of this function element, not {@code null}.
+ * @return the base parameter elements of this function element, not `null`.
*/
List<ParameterElement> get baseParameters {
Element element = this.element;
@@ -5660,9 +5728,22 @@
return ((element as FunctionTypeAliasElement)).parameters;
}
}
+
+ /**
+ * Return the return type defined by this function's element.
+ * @return the return type defined by this function's element
+ */
+ Type2 get baseReturnType {
+ Element element = this.element;
+ if (element is ExecutableElement) {
+ return ((element as ExecutableElement)).returnType;
+ } else {
+ return ((element as FunctionTypeAliasElement)).returnType;
+ }
+ }
}
/**
- * Instances of the class {@code InterfaceTypeImpl} defines the behavior common to objects
+ * Instances of the class `InterfaceTypeImpl` defines the behavior common to objects
* representing the type introduced by either a class or an interface, or a reference to such a
* type.
* @coverage dart.engine.type
@@ -5675,25 +5756,25 @@
static List<InterfaceType> EMPTY_ARRAY = new List<InterfaceType>(0);
/**
- * This method computes the longest inheritance path from some passed {@link Type} to Object.
- * @param type the {@link Type} to compute the longest inheritance path of from the passed{@link Type} to Object
+ * This method computes the longest inheritance path from some passed [Type] to Object.
+ * @param type the [Type] to compute the longest inheritance path of from the passed[Type] to Object
* @return the computed longest inheritance path to Object
* @see InterfaceType#getLeastUpperBound(Type)
*/
static int computeLongestInheritancePathToObject(InterfaceType type) => computeLongestInheritancePathToObject2(type, 0, new Set<ClassElement>());
/**
- * Returns the set of all superinterfaces of the passed {@link Type}.
- * @param type the {@link Type} to compute the set of superinterfaces of
- * @return the {@link Set} of superinterfaces of the passed {@link Type}
+ * Returns the set of all superinterfaces of the passed [Type].
+ * @param type the [Type] to compute the set of superinterfaces of
+ * @return the [Set] of superinterfaces of the passed [Type]
* @see #getLeastUpperBound(Type)
*/
static Set<InterfaceType> computeSuperinterfaceSet(InterfaceType type) => computeSuperinterfaceSet2(type, new Set<InterfaceType>());
/**
- * This method computes the longest inheritance path from some passed {@link Type} to Object. This
- * method calls itself recursively, callers should use the public method{@link #computeLongestInheritancePathToObject(Type)}.
- * @param type the {@link Type} to compute the longest inheritance path of from the passed{@link Type} to Object
+ * This method computes the longest inheritance path from some passed [Type] to Object. This
+ * method calls itself recursively, callers should use the public method[computeLongestInheritancePathToObject].
+ * @param type the [Type] to compute the longest inheritance path of from the passed[Type] to Object
* @param depth a field used recursively
* @param visitedClasses the classes that have already been visited
* @return the computed longest inheritance path to Object
@@ -5730,11 +5811,11 @@
}
/**
- * Returns the set of all superinterfaces of the passed {@link Type}. This is a recursive method,
- * callers should call the public {@link #computeSuperinterfaceSet(Type)}.
- * @param type the {@link Type} to compute the set of superinterfaces of
- * @param set a {@link HashSet} used recursively by this method
- * @return the {@link Set} of superinterfaces of the passed {@link Type}
+ * Returns the set of all superinterfaces of the passed [Type]. This is a recursive method,
+ * callers should call the public [computeSuperinterfaceSet].
+ * @param type the [Type] to compute the set of superinterfaces of
+ * @param set a [HashSet] used recursively by this method
+ * @return the [Set] of superinterfaces of the passed [Type]
* @see #computeSuperinterfaceSet(Type)
* @see #getLeastUpperBound(Type)
*/
@@ -5848,19 +5929,28 @@
InterfaceTypeImpl otherType = object as InterfaceTypeImpl;
return element == otherType.element && JavaArrays.equals(_typeArguments, otherType._typeArguments);
}
+ List<PropertyAccessorElement> get accessors {
+ List<PropertyAccessorElement> accessors = element.accessors;
+ List<PropertyAccessorElement> members = new List<PropertyAccessorElement>(accessors.length);
+ for (int i = 0; i < accessors.length; i++) {
+ members[i] = PropertyAccessorMember.from(accessors[i], this);
+ }
+ return members;
+ }
ClassElement get element => super.element as ClassElement;
PropertyAccessorElement getGetter(String getterName) => PropertyAccessorMember.from(((element as ClassElementImpl)).getGetter(getterName), this);
List<InterfaceType> get interfaces {
ClassElement classElement = element;
List<InterfaceType> interfaces = classElement.interfaces;
List<TypeVariableElement> typeVariables = classElement.typeVariables;
+ List<Type2> parameterTypes = classElement.type.typeArguments;
if (typeVariables.length == 0) {
return interfaces;
}
int count = interfaces.length;
List<InterfaceType> typedInterfaces = new List<InterfaceType>(count);
for (int i = 0; i < count; i++) {
- typedInterfaces[i] = interfaces[i].substitute2(_typeArguments, TypeVariableTypeImpl.getTypes(typeVariables));
+ typedInterfaces[i] = interfaces[i].substitute2(_typeArguments, parameterTypes);
}
return typedInterfaces;
}
@@ -5906,17 +5996,26 @@
return null;
}
MethodElement getMethod(String methodName) => MethodMember.from(((element as ClassElementImpl)).getMethod(methodName), this);
+ List<MethodElement> get methods {
+ List<MethodElement> methods = element.methods;
+ List<MethodElement> members = new List<MethodElement>(methods.length);
+ for (int i = 0; i < methods.length; i++) {
+ members[i] = MethodMember.from(methods[i], this);
+ }
+ return members;
+ }
List<InterfaceType> get mixins {
ClassElement classElement = element;
List<InterfaceType> mixins = classElement.mixins;
List<TypeVariableElement> typeVariables = classElement.typeVariables;
+ List<Type2> parameterTypes = classElement.type.typeArguments;
if (typeVariables.length == 0) {
return mixins;
}
int count = mixins.length;
List<InterfaceType> typedMixins = new List<InterfaceType>(count);
for (int i = 0; i < count; i++) {
- typedMixins[i] = mixins[i].substitute2(_typeArguments, TypeVariableTypeImpl.getTypes(typeVariables));
+ typedMixins[i] = mixins[i].substitute2(_typeArguments, parameterTypes);
}
return typedMixins;
}
@@ -5927,7 +6026,7 @@
if (supertype == null) {
return null;
}
- return supertype.substitute2(_typeArguments, TypeVariableTypeImpl.getTypes(classElement.typeVariables));
+ return supertype.substitute2(_typeArguments, classElement.type.typeArguments);
}
List<Type2> get typeArguments => _typeArguments;
List<TypeVariableElement> get typeVariables => element.typeVariables;
@@ -5938,12 +6037,12 @@
}
return element.hashCode;
}
- bool isDartCoreFunction() {
+ bool get isDartCoreFunction {
ClassElement element = this.element;
if (element == null) {
return false;
}
- return element.name == "Function" && element.library.isDartCore();
+ return element.name == "Function" && element.library.isDartCore;
}
bool isDirectSupertypeOf(InterfaceType type) {
ClassElement i = element;
@@ -5976,7 +6075,7 @@
}
return isMoreSpecificThan2((type as InterfaceType), new Set<ClassElement>());
}
- bool isObject() => element.supertype == null;
+ bool get isObject => element.supertype == null;
bool isSubtypeOf(Type2 type2) {
if (identical(type2, DynamicTypeImpl.instance)) {
return true;
@@ -6187,15 +6286,15 @@
}
return false;
}
- bool isSubtypeOf2(InterfaceType type, Set<ClassElement> visitedClasses) {
+ bool isSubtypeOf2(InterfaceType type2, Set<ClassElement> visitedClasses) {
InterfaceType typeT = this;
- InterfaceType typeS = type;
+ InterfaceType typeS = type2;
ClassElement elementT = element;
if (elementT == null || visitedClasses.contains(elementT)) {
return false;
}
javaSetAdd(visitedClasses, elementT);
- typeT = substitute2(_typeArguments, TypeVariableTypeImpl.getTypes(elementT.typeVariables));
+ typeT = substitute2(_typeArguments, elementT.type.typeArguments);
if (typeT == typeS) {
return true;
} else if (elementT == typeS.element) {
@@ -6210,7 +6309,7 @@
}
}
return true;
- } else if (typeS.isDartCoreFunction() && elementT.getMethod("call") != null) {
+ } else if (typeS.isDartCoreFunction && elementT.getMethod("call") != null) {
return true;
}
InterfaceType supertype = elementT.supertype;
@@ -6233,7 +6332,7 @@
}
}
/**
- * The abstract class {@code TypeImpl} implements the behavior common to objects representing the
+ * The abstract class `TypeImpl` implements the behavior common to objects representing the
* declared type of elements in the element model.
* @coverage dart.engine.type
*/
@@ -6260,13 +6359,13 @@
}
/**
- * The element representing the declaration of this type, or {@code null} if the type has not, or
+ * The element representing the declaration of this type, or `null` if the type has not, or
* cannot, be associated with an element.
*/
Element _element;
/**
- * The name of this type, or {@code null} if the type does not have a name.
+ * The name of this type, or `null` if the type does not have a name.
*/
String _name;
@@ -6289,12 +6388,12 @@
Type2 getLeastUpperBound(Type2 type) => null;
String get name => _name;
bool isAssignableTo(Type2 type) => this.isSubtypeOf(type) || type.isSubtypeOf(this);
- bool isDartCoreFunction() => false;
- bool isDynamic() => false;
+ bool get isDartCoreFunction => false;
+ bool get isDynamic => false;
bool isMoreSpecificThan(Type2 type) => false;
- bool isObject() => false;
+ bool get isObject => false;
bool isSupertypeOf(Type2 type) => type.isSubtypeOf(this);
- bool isVoid() => false;
+ bool get isVoid => false;
String toString() {
JavaStringBuilder builder = new JavaStringBuilder();
appendTo(builder);
@@ -6314,13 +6413,18 @@
}
}
/**
- * Instances of the class {@code TypeVariableTypeImpl} defines the behavior of objects representing
+ * Instances of the class `TypeVariableTypeImpl` defines the behavior of objects representing
* the type introduced by a type variable.
* @coverage dart.engine.type
*/
class TypeVariableTypeImpl extends TypeImpl implements TypeVariableType {
/**
+ * An empty array of type variable types.
+ */
+ static List<TypeVariableType> EMPTY_ARRAY = new List<TypeVariableType>(0);
+
+ /**
* Return an array containing the type variable types defined by the given array of type variable
* elements.
* @param typeVariables the type variable elements defining the type variable types to be returned
@@ -6328,6 +6432,9 @@
*/
static List<TypeVariableType> getTypes(List<TypeVariableElement> typeVariables) {
int count = typeVariables.length;
+ if (count == 0) {
+ return EMPTY_ARRAY;
+ }
List<TypeVariableType> types = new List<TypeVariableType>(count);
for (int i = 0; i < count; i++) {
types[i] = typeVariables[i].type;
@@ -6361,7 +6468,7 @@
}
}
/**
- * The unique instance of the class {@code VoidTypeImpl} implements the type {@code void}.
+ * The unique instance of the class `VoidTypeImpl` implements the type `void`.
* @coverage dart.engine.type
*/
class VoidTypeImpl extends TypeImpl implements VoidType {
@@ -6384,20 +6491,20 @@
}
bool operator ==(Object object) => identical(object, this);
bool isSubtypeOf(Type2 type) => identical(type, this) || identical(type, DynamicTypeImpl.instance);
- bool isVoid() => true;
+ bool get isVoid => true;
VoidTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) => this;
}
/**
- * The interface {@code FunctionType} defines the behavior common to objects representing the type
+ * The interface `FunctionType` defines the behavior common to objects representing the type
* of a function, method, constructor, getter, or setter. Function types come in three variations:
* <ol>
- * <li>The types of functions that only have required parameters. These have the general form
- * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i>.</li>
- * <li>The types of functions with optional positional parameters. These have the general form
+ * * The types of functions that only have required parameters. These have the general form
+ * <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i>.
+ * * The types of functions with optional positional parameters. These have the general form
* <i>(T<sub>1</sub>, …, T<sub>n</sub>, \[T<sub>n+1</sub>, …, T<sub>n+k</sub>\]) →
- * T</i>.</li>
- * <li>The types of functions with named parameters. These have the general form <i>(T<sub>1</sub>,
- * …, T<sub>n</sub>, {T<sub>x1</sub> x1, …, T<sub>xk</sub> xk}) → T</i>.</li>
+ * T</i>.
+ * * The types of functions with named parameters. These have the general form <i>(T<sub>1</sub>,
+ * …, T<sub>n</sub>, {T<sub>x1</sub> x1, …, T<sub>xk</sub> xk}) → T</i>.
* </ol>
* @coverage dart.engine.type
*/
@@ -6442,53 +6549,53 @@
Type2 get returnType;
/**
- * Return {@code true} if this type is a subtype of the given type.
- * <p>
+ * Return `true` if this type is a subtype of the given type.
+ *
* A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T</i> is a subtype of the
* function type <i>(S<sub>1</sub>, …, S<sub>n</sub>) → S</i>, if all of the following
* conditions are met:
- * <ul>
- * <li>Either
- * <ul>
- * <li><i>S</i> is void, or</li>
- * <li><i>T ⇔ S</i>.</li>
- * </ul>
- * </li>
- * <li>For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ S<sub>i</sub></i>.</li>
- * </ul>
+ *
+ * * Either
+ *
+ * * <i>S</i> is void, or
+ * * <i>T ⇔ S</i>.
+ *
+ *
+ * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ S<sub>i</sub></i>.
+ *
* A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, \[T<sub>n+1</sub>, …,
* T<sub>n+k</sub>\]) → T</i> is a subtype of the function type <i>(S<sub>1</sub>, …,
* S<sub>n</sub>, \[S<sub>n+1</sub>, …, S<sub>n+m</sub>\]) → S</i>, if all of the
* following conditions are met:
- * <ul>
- * <li>Either
- * <ul>
- * <li><i>S</i> is void, or</li>
- * <li><i>T ⇔ S</i>.</li>
- * </ul>
- * </li>
- * <li><i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, <i>T<sub>i</sub>
- * ⇔ S<sub>i</sub></i>.</li>
- * </ul>
+ *
+ * * Either
+ *
+ * * <i>S</i> is void, or
+ * * <i>T ⇔ S</i>.
+ *
+ *
+ * * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>, <i>T<sub>i</sub>
+ * ⇔ S<sub>i</sub></i>.
+ *
* A function type <i>(T<sub>1</sub>, …, T<sub>n</sub>, {T<sub>x1</sub> x1, …,
* T<sub>xk</sub> xk}) → T</i> is a subtype of the function type <i>(S<sub>1</sub>, …,
* S<sub>n</sub>, {S<sub>y1</sub> y1, …, S<sub>ym</sub> ym}) → S</i>, if all of the
* following conditions are met:
- * <ul>
- * <li>Either
- * <ul>
- * <li><i>S</i> is void,</li>
- * <li>or <i>T ⇔ S</i>.</li>
- * </ul>
- * </li>
- * <li>For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ S<sub>i</sub></i>.</li>
- * <li><i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, …,
- * x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>.</li>
- * <li>For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, …, y<sub>m</sub>}</i>,
- * <i>y<sub>i</sub> = x<sub>j</sub> => Tj ⇔ Si</i>.</li>
- * </ul>
+ *
+ * * Either
+ *
+ * * <i>S</i> is void,
+ * * or <i>T ⇔ S</i>.
+ *
+ *
+ * * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> ⇔ S<sub>i</sub></i>.
+ * * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>, …,
+ * x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>.
+ * * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, …, y<sub>m</sub>}</i>,
+ * <i>y<sub>i</sub> = x<sub>j</sub> => Tj ⇔ Si</i>.
+ *
* In addition, the following subtype rules apply:
- * <p>
+ *
* <i>(T<sub>1</sub>, …, T<sub>n</sub>, \[\]) → T <: (T<sub>1</sub>, …,
* T<sub>n</sub>) → T.</i><br>
* <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, …,
@@ -6497,18 +6604,18 @@
* T<sub>n</sub>) → T.</i><br>
* <i>(T<sub>1</sub>, …, T<sub>n</sub>) → T <: (T<sub>1</sub>, …,
* T<sub>n</sub>, \[\]) → T.</i>
- * <p>
- * All functions implement the class {@code Function}. However not all function types are a
- * subtype of {@code Function}. If an interface type <i>I</i> includes a method named{@code call()}, and the type of {@code call()} is the function type <i>F</i>, then <i>I</i> is
+ *
+ * All functions implement the class `Function`. However not all function types are a
+ * subtype of `Function`. If an interface type <i>I</i> includes a method named`call()`, and the type of `call()` is the function type <i>F</i>, then <i>I</i> is
* considered to be a subtype of <i>F</i>.
* @param type the type being compared with this type
- * @return {@code true} if this type is a subtype of the given type
+ * @return `true` if this type is a subtype of the given type
*/
bool isSubtypeOf(Type2 type);
/**
* Return the type resulting from substituting the given arguments for this type's parameters.
- * This is fully equivalent to {@code substitute(argumentTypes, getTypeArguments())}.
+ * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`.
* @param argumentTypes the actual type arguments being substituted for the type parameters
* @return the result of performing the substitution
*/
@@ -6516,16 +6623,22 @@
FunctionType substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes);
}
/**
- * The interface {@code InterfaceType} defines the behavior common to objects representing the type
+ * The interface `InterfaceType` defines the behavior common to objects representing the type
* introduced by either a class or an interface, or a reference to such a type.
* @coverage dart.engine.type
*/
abstract class InterfaceType implements ParameterizedType {
+
+ /**
+ * Return an array containing all of the accessors (getters and setters) declared in this type.
+ * @return the accessors declared in this type
+ */
+ List<PropertyAccessorElement> get accessors;
ClassElement get element;
/**
* Return the element representing the getter with the given name that is declared in this class,
- * or {@code null} if this class does not declare a getter with the given name.
+ * or `null` if this class does not declare a getter with the given name.
* @param getterName the name of the getter to be returned
* @return the getter declared in this class with the given name
*/
@@ -6540,9 +6653,9 @@
List<InterfaceType> get interfaces;
/**
- * Return the least upper bound of this type and the given type, or {@code null} if there is no
+ * Return the least upper bound of this type and the given type, or `null` if there is no
* least upper bound.
- * <p>
+ *
* Given two interfaces <i>I</i> and <i>J</i>, let <i>S<sub>I</sub></i> be the set of
* superinterfaces of <i>I<i>, let <i>S<sub>J</sub></i> be the set of superinterfaces of <i>J</i>
* and let <i>S = (I ∪ S<sub>I</sub>) ∩ (J ∪ S<sub>J</sub>)</i>. Furthermore, we
@@ -6558,13 +6671,19 @@
/**
* Return the element representing the method with the given name that is declared in this class,
- * or {@code null} if this class does not declare a method with the given name.
+ * or `null` if this class does not declare a method with the given name.
* @param methodName the name of the method to be returned
* @return the method declared in this class with the given name
*/
MethodElement getMethod(String methodName);
/**
+ * Return an array containing all of the methods declared in this type.
+ * @return the methods declared in this type
+ */
+ List<MethodElement> get methods;
+
+ /**
* Return an array containing all of the mixins that are applied to the class being extended in
* order to derive the superclass of this class. Note that this is <b>not</b>, in general,
* equivalent to getting the mixins from this type's element because the types returned by this
@@ -6575,7 +6694,7 @@
/**
* Return the element representing the setter with the given name that is declared in this class,
- * or {@code null} if this class does not declare a setter with the given name.
+ * or `null` if this class does not declare a setter with the given name.
* @param setterName the name of the setter to be returned
* @return the setter declared in this class with the given name
*/
@@ -6591,55 +6710,55 @@
InterfaceType get superclass;
/**
- * Return {@code true} if this type is a direct supertype of the given type. The implicit
+ * Return `true` if this type is a direct supertype of the given type. The implicit
* interface of class <i>I</i> is a direct supertype of the implicit interface of class <i>J</i>
* iff:
- * <ul>
- * <li><i>I</i> is Object, and <i>J</i> has no extends clause.</li>
- * <li><i>I</i> is listed in the extends clause of <i>J</i>.</li>
- * <li><i>I</i> is listed in the implements clause of <i>J</i>.</li>
- * <li><i>I</i> is listed in the with clause of <i>J</i>.</li>
- * <li><i>J</i> is a mixin application of the mixin of <i>I</i>.</li>
- * </ul>
+ *
+ * * <i>I</i> is Object, and <i>J</i> has no extends clause.
+ * * <i>I</i> is listed in the extends clause of <i>J</i>.
+ * * <i>I</i> is listed in the implements clause of <i>J</i>.
+ * * <i>I</i> is listed in the with clause of <i>J</i>.
+ * * <i>J</i> is a mixin application of the mixin of <i>I</i>.
+ *
* @param type the type being compared with this type
- * @return {@code true} if this type is a direct supertype of the given type
+ * @return `true` if this type is a direct supertype of the given type
*/
bool isDirectSupertypeOf(InterfaceType type);
/**
- * Return {@code true} if this type is more specific than the given type. An interface type
+ * Return `true` if this type is more specific than the given type. An interface type
* <i>T</i> is more specific than an interface type <i>S</i>, written <i>T « S</i>, if one
* of the following conditions is met:
- * <ul>
- * <li>Reflexivity: <i>T</i> is <i>S</i>.
- * <li><i>T</i> is bottom.
- * <li><i>S</i> is dynamic.
- * <li>Direct supertype: <i>S</i> is a direct supertype of <i>T</i>.
- * <li><i>T</i> is a type variable and <i>S</i> is the upper bound of <i>T</i>.
- * <li>Covariance: <i>T</i> is of the form <i>I<T<sub>1</sub>, …, T<sub>n</sub>></i>
+ *
+ * * Reflexivity: <i>T</i> is <i>S</i>.
+ * * <i>T</i> is bottom.
+ * * <i>S</i> is dynamic.
+ * * Direct supertype: <i>S</i> is a direct supertype of <i>T</i>.
+ * * <i>T</i> is a type variable and <i>S</i> is the upper bound of <i>T</i>.
+ * * Covariance: <i>T</i> is of the form <i>I<T<sub>1</sub>, …, T<sub>n</sub>></i>
* and S</i> is of the form <i>I<S<sub>1</sub>, …, S<sub>n</sub>></i> and
* <i>T<sub>i</sub> « S<sub>i</sub></i>, <i>1 <= i <= n</i>.
- * <li>Transitivity: <i>T « U</i> and <i>U « S</i>.
- * </ul>
+ * * Transitivity: <i>T « U</i> and <i>U « S</i>.
+ *
* @param type the type being compared with this type
- * @return {@code true} if this type is more specific than the given type
+ * @return `true` if this type is more specific than the given type
*/
bool isMoreSpecificThan(Type2 type);
/**
- * Return {@code true} if this type is a subtype of the given type. An interface type <i>T</i> is
+ * Return `true` if this type is a subtype of the given type. An interface type <i>T</i> is
* a subtype of an interface type <i>S</i>, written <i>T</i> <: <i>S</i>, iff
* <i>\[bottom/dynamic\]T</i> « <i>S</i> (<i>T</i> is more specific than <i>S</i>). If an
* interface type <i>I</i> includes a method named <i>call()</i>, and the type of <i>call()</i> is
* the function type <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>.
* @param type the type being compared with this type
- * @return {@code true} if this type is a subtype of the given type
+ * @return `true` if this type is a subtype of the given type
*/
bool isSubtypeOf(Type2 type);
/**
* Return the element representing the constructor that results from looking up the given
- * constructor in this class with respect to the given library, or {@code null} if the look up
+ * constructor in this class with respect to the given library, or `null` if the look up
* fails. The behavior of this method is defined by the Dart Language Specification in section
* 12.11.1: <blockquote>If <i>e</i> is of the form <b>new</b> <i>T.id()</i> then let <i>q<i> be
* the constructor <i>T.id</i>, otherwise let <i>q<i> be the constructor <i>T<i>. Otherwise, if
@@ -6653,17 +6772,17 @@
/**
* Return the element representing the getter that results from looking up the given getter in
- * this class with respect to the given library, or {@code null} if the look up fails. The
+ * this class with respect to the given library, or `null` if the look up fails. The
* behavior of this method is defined by the Dart Language Specification in section 12.15.1:
* <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
* with respect to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ *
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
* accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
* Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
* of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param getterName the name of the getter being looked up
* @param library the library with respect to which the lookup is being performed
@@ -6674,17 +6793,17 @@
/**
* Return the element representing the getter that results from looking up the given getter in the
- * superclass of this class with respect to the given library, or {@code null} if the look up
+ * superclass of this class with respect to the given library, or `null` if the look up
* fails. The behavior of this method is defined by the Dart Language Specification in section
* 12.15.1: <blockquote>The result of looking up getter (respectively setter) <i>m</i> in class
* <i>C</i> with respect to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ *
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
* accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
* Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
* of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param getterName the name of the getter being looked up
* @param library the library with respect to which the lookup is being performed
@@ -6695,16 +6814,16 @@
/**
* Return the element representing the method that results from looking up the given method in
- * this class with respect to the given library, or {@code null} if the look up fails. The
+ * this class with respect to the given library, or `null` if the look up fails. The
* behavior of this method is defined by the Dart Language Specification in section 12.15.1:
* <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect to library
* <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
+ *
+ * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
* that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
* the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
- * to <i>L</i>. Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * to <i>L</i>. Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param methodName the name of the method being looked up
* @param library the library with respect to which the lookup is being performed
@@ -6715,16 +6834,16 @@
/**
* Return the element representing the method that results from looking up the given method in the
- * superclass of this class with respect to the given library, or {@code null} if the look up
+ * superclass of this class with respect to the given library, or `null` if the look up
* fails. The behavior of this method is defined by the Dart Language Specification in section
* 12.15.1: <blockquote> The result of looking up method <i>m</i> in class <i>C</i> with respect
* to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
+ *
+ * * If <i>C</i> declares an instance method named <i>m</i> that is accessible to <i>L</i>, then
* that method is the result of the lookup. Otherwise, if <i>C</i> has a superclass <i>S</i>, then
* the result of the lookup is the result of looking up method <i>m</i> in <i>S</i> with respect
- * to <i>L</i>. Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * to <i>L</i>. Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param methodName the name of the method being looked up
* @param library the library with respect to which the lookup is being performed
@@ -6735,17 +6854,17 @@
/**
* Return the element representing the setter that results from looking up the given setter in
- * this class with respect to the given library, or {@code null} if the look up fails. The
+ * this class with respect to the given library, or `null` if the look up fails. The
* behavior of this method is defined by the Dart Language Specification in section 12.16:
* <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class <i>C</i>
* with respect to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ *
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
* accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
* Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
* of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param setterName the name of the setter being looked up
* @param library the library with respect to which the lookup is being performed
@@ -6756,17 +6875,17 @@
/**
* Return the element representing the setter that results from looking up the given setter in the
- * superclass of this class with respect to the given library, or {@code null} if the look up
+ * superclass of this class with respect to the given library, or `null` if the look up
* fails. The behavior of this method is defined by the Dart Language Specification in section
* 12.16: <blockquote> The result of looking up getter (respectively setter) <i>m</i> in class
* <i>C</i> with respect to library <i>L</i> is:
- * <ul>
- * <li>If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
+ *
+ * * If <i>C</i> declares an instance getter (respectively setter) named <i>m</i> that is
* accessible to <i>L</i>, then that getter (respectively setter) is the result of the lookup.
* Otherwise, if <i>C</i> has a superclass <i>S</i>, then the result of the lookup is the result
* of looking up getter (respectively setter) <i>m</i> in <i>S</i> with respect to <i>L</i>.
- * Otherwise, we say that the lookup has failed.</li>
- * </ul>
+ * Otherwise, we say that the lookup has failed.
+ *
* </blockquote>
* @param setterName the name of the setter being looked up
* @param library the library with respect to which the lookup is being performed
@@ -6777,7 +6896,7 @@
/**
* Return the type resulting from substituting the given arguments for this type's parameters.
- * This is fully equivalent to {@code substitute(argumentTypes, getTypeArguments())}.
+ * This is fully equivalent to `substitute(argumentTypes, getTypeArguments())`.
* @param argumentTypes the actual type arguments being substituted for the type parameters
* @return the result of performing the substitution
*/
@@ -6785,7 +6904,7 @@
InterfaceType substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes);
}
/**
- * The interface {@code ParameterizedType} defines the behavior common to objects representing the
+ * The interface `ParameterizedType` defines the behavior common to objects representing the
* type with type parameters, such as class and function type alias.
* @coverage dart.engine.type
*/
@@ -6808,7 +6927,7 @@
List<TypeVariableElement> get typeVariables;
}
/**
- * The interface {@code Type} defines the behavior of objects representing the declared type of
+ * The interface `Type` defines the behavior of objects representing the declared type of
* elements in the element model.
* @coverage dart.engine.type
*/
@@ -6822,7 +6941,7 @@
String get displayName;
/**
- * Return the element representing the declaration of this type, or {@code null} if the type has
+ * Return the element representing the declaration of this type, or `null` if the type has
* not, or cannot, be associated with an element. The former case will occur if the element model
* is not yet complete; the latter case will occur if this object represents an undefined type.
* @return the element representing the declaration of this type
@@ -6830,7 +6949,7 @@
Element get element;
/**
- * Return the least upper bound of this type and the given type, or {@code null} if there is no
+ * Return the least upper bound of this type and the given type, or `null` if there is no
* least upper bound.
* @param type the other type used to compute the least upper bound
* @return the least upper bound of this type and the given type
@@ -6838,68 +6957,68 @@
Type2 getLeastUpperBound(Type2 type);
/**
- * Return the name of this type, or {@code null} if the type does not have a name, such as when
+ * Return the name of this type, or `null` if the type does not have a name, such as when
* the type represents the type of an unnamed function.
* @return the name of this type
*/
String get name;
/**
- * Return {@code true} if this type is assignable to the given type. A type <i>T</i> may be
+ * Return `true` if this type is assignable to the given type. A type <i>T</i> may be
* assigned to a type <i>S</i>, written <i>T</i> ⇔ <i>S</i>, iff either <i>T</i> <: <i>S</i>
* or <i>S</i> <: <i>T</i>.
* @param type the type being compared with this type
- * @return {@code true} if this type is assignable to the given type
+ * @return `true` if this type is assignable to the given type
*/
bool isAssignableTo(Type2 type);
/**
- * Return {@code true} if this type represents the type 'Function' defined in the dart:core
+ * Return `true` if this type represents the type 'Function' defined in the dart:core
* library.
- * @return {@code true} if this type represents the type 'Function' defined in the dart:core
+ * @return `true` if this type represents the type 'Function' defined in the dart:core
* library
*/
- bool isDartCoreFunction();
+ bool get isDartCoreFunction;
/**
- * Return {@code true} if this type represents the type 'dynamic'.
- * @return {@code true} if this type represents the type 'dynamic'
+ * Return `true` if this type represents the type 'dynamic'.
+ * @return `true` if this type represents the type 'dynamic'
*/
- bool isDynamic();
+ bool get isDynamic;
/**
- * Return {@code true} if this type is more specific than the given type.
+ * Return `true` if this type is more specific than the given type.
* @param type the type being compared with this type
- * @return {@code true} if this type is more specific than the given type
+ * @return `true` if this type is more specific than the given type
*/
bool isMoreSpecificThan(Type2 type);
/**
- * Return {@code true} if this type represents the type 'Object'.
- * @return {@code true} if this type represents the type 'Object'
+ * Return `true` if this type represents the type 'Object'.
+ * @return `true` if this type represents the type 'Object'
*/
- bool isObject();
+ bool get isObject;
/**
- * Return {@code true} if this type is a subtype of the given type.
+ * Return `true` if this type is a subtype of the given type.
* @param type the type being compared with this type
- * @return {@code true} if this type is a subtype of the given type
+ * @return `true` if this type is a subtype of the given type
*/
bool isSubtypeOf(Type2 type);
/**
- * Return {@code true} if this type is a supertype of the given type. A type <i>S</i> is a
+ * Return `true` if this type is a supertype of the given type. A type <i>S</i> is a
* supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff <i>T</i> is a subtype of <i>S</i>.
* @param type the type being compared with this type
- * @return {@code true} if this type is a supertype of the given type
+ * @return `true` if this type is a supertype of the given type
*/
bool isSupertypeOf(Type2 type);
/**
- * Return {@code true} if this type represents the type 'void'.
- * @return {@code true} if this type represents the type 'void'
+ * Return `true` if this type represents the type 'void'.
+ * @return `true` if this type represents the type 'void'
*/
- bool isVoid();
+ bool get isVoid;
/**
* Return the type resulting from substituting the given arguments for the given parameters in
@@ -6916,7 +7035,7 @@
Type2 substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes);
}
/**
- * The interface {@code TypeVariableType} defines the behavior of objects representing the type
+ * The interface `TypeVariableType` defines the behavior of objects representing the type
* introduced by a type variable.
* @coverage dart.engine.type
*/
@@ -6924,7 +7043,7 @@
TypeVariableElement get element;
}
/**
- * The interface {@code VoidType} defines the behavior of the unique object representing the type{@code void}.
+ * The interface `VoidType` defines the behavior of the unique object representing the type`void`.
* @coverage dart.engine.type
*/
abstract class VoidType implements Type2 {
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index fd4a2e5..42407bf 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -15,7 +15,7 @@
import 'resolver.dart';
import 'html.dart' show XmlTagNode, XmlAttributeNode, RecursiveXmlVisitor, HtmlScanner, HtmlScanResult, HtmlParser, HtmlParseResult, HtmlUnit;
/**
- * The unique instance of the class {@code AnalysisEngine} serves as the entry point for the
+ * The unique instance of the class `AnalysisEngine` serves as the entry point for the
* functionality provided by the analysis engine.
* @coverage dart.engine
*/
@@ -48,9 +48,9 @@
static AnalysisEngine get instance => _UniqueInstance;
/**
- * Return {@code true} if the given file name is assumed to contain Dart source code.
+ * Return `true` if the given file name is assumed to contain Dart source code.
* @param fileName the name of the file being tested
- * @return {@code true} if the given file name is assumed to contain Dart source code
+ * @return `true` if the given file name is assumed to contain Dart source code
*/
static bool isDartFileName(String fileName) {
if (fileName == null) {
@@ -60,9 +60,9 @@
}
/**
- * Return {@code true} if the given file name is assumed to contain HTML.
+ * Return `true` if the given file name is assumed to contain HTML.
* @param fileName the name of the file being tested
- * @return {@code true} if the given file name is assumed to contain HTML
+ * @return `true` if the given file name is assumed to contain HTML
*/
static bool isHtmlFileName(String fileName) {
if (fileName == null) {
@@ -82,7 +82,7 @@
* @return the analysis context that was created
*/
AnalysisContext createAnalysisContext() {
- if (Instrumentation.isNullLogger()) {
+ if (Instrumentation.isNullLogger) {
return new DelegatingAnalysisContextImpl();
} else {
return new InstrumentedAnalysisContextImpl.con1(new DelegatingAnalysisContextImpl());
@@ -106,32 +106,32 @@
}
}
/**
- * The interface {@code AnalysisContext} defines the behavior of objects that represent a context in
+ * The interface `AnalysisContext` defines the behavior of objects that represent a context in
* which a single analysis can be performed and incrementally maintained. The context includes such
* information as the version of the SDK being analyzed against as well as the package-root used to
- * resolve 'package:' URI's. (Both of which are known indirectly through the {@link SourceFactorysource factory}.)
- * <p>
+ * resolve 'package:' URI's. (Both of which are known indirectly through the [SourceFactorysource factory].)
+ *
* An analysis context also represents the state of the analysis, which includes knowing which
* sources have been included in the analysis (either directly or indirectly) and the results of the
- * analysis. Sources must be added and removed from the context using the method{@link #applyChanges(ChangeSet)}, which is also used to notify the context when sources have been
+ * analysis. Sources must be added and removed from the context using the method[applyChanges], which is also used to notify the context when sources have been
* modified and, consequently, previously known results might have been invalidated.
- * <p>
+ *
* There are two ways to access the results of the analysis. The most common is to use one of the
* 'get' methods to access the results. The 'get' methods have the advantage that they will always
* return quickly, but have the disadvantage that if the results are not currently available they
* will return either nothing or in some cases an incomplete result. The second way to access
* results is by using one of the 'compute' methods. The 'compute' methods will always attempt to
* compute the requested results but might block the caller for a significant period of time.
- * <p>
+ *
* When results have been invalidated, have never been computed (as is the case for newly added
* sources), or have been removed from the cache, they are <b>not</b> automatically recreated. They
* will only be recreated if one of the 'compute' methods is invoked.
- * <p>
+ *
* However, this is not always acceptable. Some clients need to keep the analysis results
* up-to-date. For such clients there is a mechanism that allows them to incrementally perform
* needed analysis and get notified of the consequent changes to the analysis results. This
- * mechanism is realized by the method {@link #performAnalysisTask()}.
- * <p>
+ * mechanism is realized by the method [performAnalysisTask].
+ *
* Analysis engine allows for having more than one context. This can be used, for example, to
* perform one analysis based on the state of files on disk and a separate analysis based on the
* state of those files in open editors. It can also be used to perform an analysis based on a
@@ -148,7 +148,7 @@
/**
* Return the documentation comment for the given element as it appears in the original source
- * (complete with the beginning and ending delimiters), or {@code null} if the element does not
+ * (complete with the beginning and ending delimiters), or `null` if the element does not
* have a documentation comment associated with it. This can be a long-running operation if the
* information needed to access the comment is not cached.
* @param element the element whose documentation comment is to be returned
@@ -185,7 +185,7 @@
HtmlElement computeHtmlElement(Source source);
/**
- * Return the kind of the given source, computing it's kind if it is not already known. Return{@link SourceKind#UNKNOWN} if the source is not contained in this context.
+ * Return the kind of the given source, computing it's kind if it is not already known. Return[SourceKind#UNKNOWN] if the source is not contained in this context.
* @param source the source whose kind is to be returned
* @return the kind of the given source
* @see #getKindOf(Source)
@@ -206,7 +206,7 @@
LibraryElement computeLibraryElement(Source source);
/**
- * Return the line information for the given source, or {@code null} if the source is not of a
+ * Return the line information for the given source, or `null` if the source is not of a
* recognized kind (neither a Dart nor HTML file). If the line information was not previously
* known it will be created. The line information is used to map offsets from the beginning of the
* source to line and column pairs.
@@ -234,7 +234,7 @@
AnalysisOptions get analysisOptions;
/**
- * Return the element referenced by the given location, or {@code null} if the element is not
+ * Return the element referenced by the given location, or `null` if the element is not
* immediately available or if there is no element with the given location. The latter condition
* can occur, for example, if the location describes an element from a different context or if the
* element has been removed from this context as a result of some change since it was originally
@@ -256,7 +256,7 @@
AnalysisErrorInfo getErrors(Source source);
/**
- * Return the element model corresponding to the HTML file defined by the given source, or{@code null} if the source does not represent an HTML file, the element representing the file
+ * Return the element model corresponding to the HTML file defined by the given source, or`null` if the source does not represent an HTML file, the element representing the file
* has not yet been created, or the analysis of the HTML file failed for some reason.
* @param source the source defining the HTML file whose element model is to be returned
* @return the element model corresponding to the HTML file defined by the given source
@@ -281,7 +281,7 @@
List<Source> get htmlSources;
/**
- * Return the kind of the given source, or {@code null} if the kind is not known to this context.
+ * Return the kind of the given source, or `null` if the kind is not known to this context.
* @param source the source whose kind is to be returned
* @return the kind of the given source
* @see #computeKindOf(Source)
@@ -331,7 +331,7 @@
List<Source> getLibrariesDependingOn(Source librarySource);
/**
- * Return the element model corresponding to the library defined by the given source, or{@code null} if the element model does not currently exist or if the library cannot be analyzed
+ * Return the element model corresponding to the library defined by the given source, or`null` if the element model does not currently exist or if the library cannot be analyzed
* for some reason.
* @param source the source defining the library whose element model is to be returned
* @return the element model corresponding to the library defined by the given source
@@ -347,7 +347,7 @@
List<Source> get librarySources;
/**
- * Return the line information for the given source, or {@code null} if the line information is
+ * Return the line information for the given source, or `null` if the line information is
* not known. The line information is used to map offsets from the beginning of the source to line
* and column pairs.
* @param source the source whose line information is to be returned
@@ -357,7 +357,7 @@
LineInfo getLineInfo(Source source);
/**
- * Return a fully resolved AST for a single compilation unit within the given library, or{@code null} if the resolved AST is not already computed.
+ * Return a fully resolved AST for a single compilation unit within the given library, or`null` if the resolved AST is not already computed.
* @param unitSource the source of the compilation unit
* @param library the library containing the compilation unit
* @return a fully resolved AST for the compilation unit
@@ -366,7 +366,7 @@
CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library);
/**
- * Return a fully resolved AST for a single compilation unit within the given library, or{@code null} if the resolved AST is not already computed.
+ * Return a fully resolved AST for a single compilation unit within the given library, or`null` if the resolved AST is not already computed.
* @param unitSource the source of the compilation unit
* @param librarySource the source of the defining compilation unit of the library containing the
* compilation unit
@@ -382,28 +382,28 @@
SourceFactory get sourceFactory;
/**
- * Return {@code true} if the given source is known to be the defining compilation unit of a
+ * Return `true` if the given source is known to be the defining compilation unit of a
* library that can be run on a client (references 'dart:html', either directly or indirectly).
- * <p>
- * <b>Note:</b> In addition to the expected case of returning {@code false} if the source is known
- * to be a library that cannot be run on a client, this method will also return {@code false} if
+ *
+ * <b>Note:</b> In addition to the expected case of returning `false` if the source is known
+ * to be a library that cannot be run on a client, this method will also return `false` if
* the source is not known to be a library or if we do not know whether it can be run on a client.
* @param librarySource the source being tested
- * @return {@code true} if the given source is known to be a library that can be run on a client
+ * @return `true` if the given source is known to be a library that can be run on a client
*/
bool isClientLibrary(Source librarySource);
/**
- * Return {@code true} if the given source is known to be the defining compilation unit of a
+ * Return `true` if the given source is known to be the defining compilation unit of a
* library that can be run on the server (does not reference 'dart:html', either directly or
* indirectly).
- * <p>
- * <b>Note:</b> In addition to the expected case of returning {@code false} if the source is known
- * to be a library that cannot be run on the server, this method will also return {@code false} if
+ *
+ * <b>Note:</b> In addition to the expected case of returning `false` if the source is known
+ * to be a library that cannot be run on the server, this method will also return `false` if
* the source is not known to be a library or if we do not know whether it can be run on the
* server.
* @param librarySource the source being tested
- * @return {@code true} if the given source is known to be a library that can be run on the server
+ * @return `true` if the given source is known to be a library that can be run on the server
*/
bool isServerLibrary(Source librarySource);
@@ -429,7 +429,7 @@
* may not be resolved, and may have a slightly different structure depending upon whether it is
* resolved.
* @param source the HTML source to be parsed
- * @return the parse result (not {@code null})
+ * @return the parse result (not `null`)
* @throws AnalysisException if the analysis could not be performed
*/
HtmlUnit parseHtmlUnit(Source source);
@@ -438,7 +438,7 @@
* Perform the next unit of work required to keep the analysis results up-to-date and return
* information about the consequent changes to the analysis results. If there were no results the
* returned array will be empty. If there are no more units of work required, then this method
- * returns {@code null}. This method can be long running.
+ * returns `null`. This method can be long running.
* @return an array containing notices of changes to the analysis results
*/
List<ChangeNotice> performAnalysisTask();
@@ -484,7 +484,7 @@
/**
* Set the contents of the given source to the given contents and mark the source as having
* changed. This has the effect of overriding the default contents of the source. If the contents
- * are {@code null} the override is removed so that the default contents will be returned.
+ * are `null` the override is removed so that the default contents will be returned.
* @param source the source whose contents are being overridden
* @param contents the new contents of the source
*/
@@ -500,33 +500,33 @@
void set sourceFactory(SourceFactory factory);
/**
- * Given a collection of sources with content that has changed, return an {@link Iterable}identifying the sources that need to be resolved.
- * @param changedSources an array of sources (not {@code null}, contains no {@code null}s)
+ * Given a collection of sources with content that has changed, return an [Iterable]identifying the sources that need to be resolved.
+ * @param changedSources an array of sources (not `null`, contains no `null`s)
* @return An iterable returning the sources to be resolved
*/
Iterable<Source> sourcesToResolve(List<Source> changedSources);
}
/**
- * The interface {@code AnalysisErrorInfo} contains the analysis errors and line information for the
+ * The interface `AnalysisErrorInfo` contains the analysis errors and line information for the
* errors.
*/
abstract class AnalysisErrorInfo {
/**
- * Return the errors that as a result of the analysis, or {@code null} if there were no errors.
+ * Return the errors that as a result of the analysis, or `null` if there were no errors.
* @return the errors as a result of the analysis
*/
List<AnalysisError> get errors;
/**
- * Return the line information associated with the errors, or {@code null} if there were no
+ * Return the line information associated with the errors, or `null` if there were no
* errors.
* @return the line information associated with the errors
*/
LineInfo get lineInfo;
}
/**
- * Instances of the class {@code AnalysisException} represent an exception that occurred during the
+ * Instances of the class `AnalysisException` represent an exception that occurred during the
* analysis of one or more sources.
* @coverage dart.engine
*/
@@ -573,27 +573,27 @@
}
}
/**
- * The interface {@code AnalysisOptions} defines the behavior of objects that provide access to a
+ * The interface `AnalysisOptions` defines the behavior of objects that provide access to a
* set of analysis options used to control the behavior of an analysis context.
*/
abstract class AnalysisOptions {
/**
- * Return {@code true} if analysis is to use strict mode. In strict mode, error reporting is based
+ * Return `true` if analysis is to use strict mode. In strict mode, error reporting is based
* exclusively on the static type information.
- * @return {@code true} if analysis is to use strict mode
+ * @return `true` if analysis is to use strict mode
*/
bool get strictMode;
}
/**
- * The interface {@code ChangeNotice} defines the behavior of objects that represent a change to the
+ * The interface `ChangeNotice` defines the behavior of objects that represent a change to the
* analysis results associated with a given source.
* @coverage dart.engine
*/
abstract class ChangeNotice implements AnalysisErrorInfo {
/**
- * Return the fully resolved AST that changed as a result of the analysis, or {@code null} if the
+ * Return the fully resolved AST that changed as a result of the analysis, or `null` if the
* AST was not changed.
* @return the fully resolved AST that changed as a result of the analysis
*/
@@ -606,7 +606,7 @@
Source get source;
}
/**
- * Instances of the class {@code ChangeSet} indicate what sources have been added, changed, or
+ * Instances of the class `ChangeSet` indicate what sources have been added, changed, or
* removed.
* @coverage dart.engine
*/
@@ -675,10 +675,10 @@
List<SourceContainer> get removedContainers => _removedContainers;
/**
- * Return {@code true} if this change set does not contain any changes.
- * @return {@code true} if this change set does not contain any changes
+ * Return `true` if this change set does not contain any changes.
+ * @return `true` if this change set does not contain any changes
*/
- bool isEmpty() => _added2.isEmpty && _changed2.isEmpty && _removed2.isEmpty && _removedContainers.isEmpty;
+ bool get isEmpty => _added2.isEmpty && _changed2.isEmpty && _removed2.isEmpty && _removedContainers.isEmpty;
/**
* Record that the specified source has been removed.
@@ -701,7 +701,7 @@
}
}
/**
- * The interface {@code DartEntry} defines the behavior of objects that maintain the information
+ * The interface `DartEntry` defines the behavior of objects that maintain the information
* cached by an analysis context about an individual Dart file.
* @coverage dart.engine
*/
@@ -776,14 +776,14 @@
/**
* Return a valid parsed compilation unit, either an unresolved AST structure or the result of
- * resolving the AST structure in the context of some library, or {@code null} if there is no
+ * resolving the AST structure in the context of some library, or `null` if there is no
* parsed compilation unit available.
* @return a valid parsed compilation unit
*/
CompilationUnit get anyParsedCompilationUnit;
/**
- * Return the result of resolving the compilation unit as part of any library, or {@code null} if
+ * Return the result of resolving the compilation unit as part of any library, or `null` if
* there is no cached resolved compilation unit.
* @return any resolved compilation unit
*/
@@ -801,7 +801,7 @@
/**
* Return the value of the data represented by the given descriptor in the context of the given
- * library, or {@code null} if the data represented by the descriptor is not in the cache.
+ * library, or `null` if the data represented by the descriptor is not in the cache.
* @param descriptor the descriptor representing which data is to be returned
* @param librarySource the source of the defining compilation unit of the library that is the
* context for the data
@@ -811,7 +811,7 @@
DartEntryImpl get writableCopy;
}
/**
- * Instances of the class {@code DartEntryImpl} implement a {@link DartEntry}.
+ * Instances of the class `DartEntryImpl` implement a [DartEntry].
* @coverage dart.engine
*/
class DartEntryImpl extends SourceEntryImpl implements DartEntry {
@@ -832,7 +832,7 @@
CacheState _parsedUnitState = CacheState.INVALID;
/**
- * The parsed compilation unit, or {@code null} if the parsed compilation unit is not currently
+ * The parsed compilation unit, or `null` if the parsed compilation unit is not currently
* cached.
*/
CompilationUnit _parsedUnit;
@@ -843,7 +843,7 @@
CacheState _parseErrorsState = CacheState.INVALID;
/**
- * The errors produced while scanning and parsing the compilation unit, or {@code null} if the
+ * The errors produced while scanning and parsing the compilation unit, or `null` if the
* errors are not currently cached.
*/
List<AnalysisError> _parseErrors = AnalysisError.NO_ERRORS;
@@ -873,7 +873,7 @@
/**
* The information known as a result of resolving this compilation unit as part of the library
- * that contains this unit. This field will never be {@code null}.
+ * that contains this unit. This field will never be `null`.
*/
DartEntryImpl_ResolutionState _resolutionState = new DartEntryImpl_ResolutionState();
@@ -883,7 +883,7 @@
CacheState _elementState = CacheState.INVALID;
/**
- * The element representing the library, or {@code null} if the element is not currently cached.
+ * The element representing the library, or `null` if the element is not currently cached.
*/
LibraryElement _element;
@@ -893,7 +893,7 @@
CacheState _publicNamespaceState = CacheState.INVALID;
/**
- * The public namespace of the library, or {@code null} if the namespace is not currently cached.
+ * The public namespace of the library, or `null` if the namespace is not currently cached.
*/
Namespace _publicNamespace;
@@ -908,7 +908,7 @@
CacheState _launchableState = CacheState.INVALID;
/**
- * An integer holding bit masks such as {@link #LAUNCHABLE} and {@link #CLIENT_CODE}.
+ * An integer holding bit masks such as [LAUNCHABLE] and [CLIENT_CODE].
*/
int _bitmask = 0;
@@ -1280,7 +1280,7 @@
/**
* Set the value of the data represented by the given descriptor in the context of the given
- * library to the given value, and set the state of that data to {@link CacheState#VALID}.
+ * library to the given value, and set the state of that data to [CacheState#VALID].
* @param descriptor the descriptor representing which data is to have its value set
* @param librarySource the source of the defining compilation unit of the library that is the
* context for the data
@@ -1321,8 +1321,8 @@
/**
* Return a resolution state for the specified library, creating one as necessary.
- * @param librarySource the library source (not {@code null})
- * @return the resolution state (not {@code null})
+ * @param librarySource the library source (not `null`)
+ * @return the resolution state (not `null`)
*/
DartEntryImpl_ResolutionState getOrCreateResolutionState(Source librarySource2) {
DartEntryImpl_ResolutionState state = _resolutionState;
@@ -1360,13 +1360,13 @@
}
}
/**
- * Instances of the class {@code ResolutionState} represent the information produced by resolving
+ * Instances of the class `ResolutionState` represent the information produced by resolving
* a compilation unit as part of a specific library.
*/
class DartEntryImpl_ResolutionState {
/**
- * The next resolution state or {@code null} if none.
+ * The next resolution state or `null` if none.
*/
DartEntryImpl_ResolutionState _nextState;
@@ -1383,7 +1383,7 @@
CacheState _resolvedUnitState = CacheState.INVALID;
/**
- * The resolved compilation unit, or {@code null} if the resolved compilation unit is not
+ * The resolved compilation unit, or `null` if the resolved compilation unit is not
* currently cached.
*/
CompilationUnit _resolvedUnit;
@@ -1394,7 +1394,7 @@
CacheState _resolutionErrorsState = CacheState.INVALID;
/**
- * The errors produced while resolving the compilation unit, or {@code null} if the errors are
+ * The errors produced while resolving the compilation unit, or `null` if the errors are
* not currently cached.
*/
List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
@@ -1443,7 +1443,7 @@
}
}
/**
- * Instances of the class {@code DataDescriptor} are immutable constants representing data that can
+ * Instances of the class `DataDescriptor` are immutable constants representing data that can
* be stored in the cache.
*/
class DataDescriptor<E> {
@@ -1463,7 +1463,7 @@
String toString() => _name;
}
/**
- * The interface {@code HtmlEntry} defines the behavior of objects that maintain the information
+ * The interface `HtmlEntry` defines the behavior of objects that maintain the information
* cached by an analysis context about an individual HTML file.
* @coverage dart.engine
*/
@@ -1502,7 +1502,7 @@
HtmlEntryImpl get writableCopy;
}
/**
- * Instances of the class {@code HtmlEntryImpl} implement an {@link HtmlEntry}.
+ * Instances of the class `HtmlEntryImpl` implement an [HtmlEntry].
* @coverage dart.engine
*/
class HtmlEntryImpl extends SourceEntryImpl implements HtmlEntry {
@@ -1513,7 +1513,7 @@
CacheState _parsedUnitState = CacheState.INVALID;
/**
- * The parsed HTML unit, or {@code null} if the parsed HTML unit is not currently cached.
+ * The parsed HTML unit, or `null` if the parsed HTML unit is not currently cached.
*/
HtmlUnit _parsedUnit;
@@ -1523,7 +1523,7 @@
CacheState _resolutionErrorsState = CacheState.INVALID;
/**
- * The errors produced while resolving the compilation unit, or {@code null} if the errors are not
+ * The errors produced while resolving the compilation unit, or `null` if the errors are not
* currently cached.
*/
List<AnalysisError> _resolutionErrors = AnalysisError.NO_ERRORS;
@@ -1534,7 +1534,7 @@
CacheState _resolvedUnitState = CacheState.INVALID;
/**
- * The resolved HTML unit, or {@code null} if the resolved HTML unit is not currently cached.
+ * The resolved HTML unit, or `null` if the resolved HTML unit is not currently cached.
*/
HtmlUnit _resolvedUnit;
@@ -1544,7 +1544,7 @@
CacheState _referencedLibrariesState = CacheState.INVALID;
/**
- * The list of libraries referenced in the HTML, or {@code null} if the list is not currently
+ * The list of libraries referenced in the HTML, or `null` if the list is not currently
* cached. Note that this list does not include libraries defined directly within the HTML file.
*/
List<Source> _referencedLibraries = Source.EMPTY_ARRAY;
@@ -1555,7 +1555,7 @@
CacheState _elementState = CacheState.INVALID;
/**
- * The element representing the HTML file, or {@code null} if the element is not currently cached.
+ * The element representing the HTML file, or `null` if the element is not currently cached.
*/
HtmlElement _element;
List<AnalysisError> get allErrors {
@@ -1658,9 +1658,9 @@
}
}
/**
- * The interface {@code SourceEntry} defines the behavior of objects that maintain the information
+ * The interface `SourceEntry` defines the behavior of objects that maintain the information
* cached by an analysis context about an individual source, no matter what kind of source it is.
- * <p>
+ *
* Source entries should be treated as if they were immutable unless a writable copy of the entry
* has been obtained and has not yet been made visible to other threads.
* @coverage dart.engine
@@ -1673,7 +1673,7 @@
static final DataDescriptor<LineInfo> LINE_INFO = new DataDescriptor<LineInfo>("SourceEntry.LINE_INFO");
/**
- * Return the kind of the source, or {@code null} if the kind is not currently cached.
+ * Return the kind of the source, or `null` if the kind is not currently cached.
* @return the kind of the source
*/
SourceKind get kind;
@@ -1693,7 +1693,7 @@
CacheState getState(DataDescriptor<Object> descriptor);
/**
- * Return the value of the data represented by the given descriptor, or {@code null} if the data
+ * Return the value of the data represented by the given descriptor, or `null` if the data
* represented by the descriptor is not in the cache.
* @param descriptor the descriptor representing which data is to be returned
* @return the value of the data represented by the given descriptor
@@ -1708,7 +1708,7 @@
SourceEntryImpl get writableCopy;
}
/**
- * Instances of the abstract class {@code SourceEntryImpl} implement the behavior common to all{@link SourceEntry source entries}.
+ * Instances of the abstract class `SourceEntryImpl` implement the behavior common to all[SourceEntry source entries].
* @coverage dart.engine
*/
abstract class SourceEntryImpl implements SourceEntry {
@@ -1725,7 +1725,7 @@
CacheState _lineInfoState = CacheState.INVALID;
/**
- * The line information computed for the source, or {@code null} if the line information is not
+ * The line information computed for the source, or `null` if the line information is not
* currently cached.
*/
LineInfo _lineInfo;
@@ -1810,8 +1810,8 @@
}
}
/**
- * Instances of the class {@code AnalysisContextImpl} implement an {@link AnalysisContext analysis
- * context}.
+ * Instances of the class `AnalysisContextImpl` implement an [AnalysisContext analysis
+ * context].
* @coverage dart.engine
*/
class AnalysisContextImpl implements InternalAnalysisContext {
@@ -1884,7 +1884,7 @@
_sourceMap[source] = info;
}
void applyChanges(ChangeSet changeSet) {
- if (changeSet.isEmpty()) {
+ if (changeSet.isEmpty) {
return;
}
{
@@ -1906,7 +1906,7 @@
}
if (addedDartSource) {
for (MapEntry<Source, SourceEntry> mapEntry in getMapEntrySet(_sourceMap)) {
- if (!mapEntry.getKey().isInSystemLibrary() && mapEntry.getValue() is DartEntry) {
+ if (!mapEntry.getKey().isInSystemLibrary && mapEntry.getValue() is DartEntry) {
DartEntryImpl dartCopy = ((mapEntry.getValue() as DartEntry)).writableCopy;
dartCopy.invalidateAllResolutionInformation();
mapEntry.setValue(dartCopy);
@@ -2172,7 +2172,7 @@
for (MapEntry<Source, SourceEntry> entry in getMapEntrySet(_sourceMap)) {
Source source = entry.getKey();
SourceEntry sourceEntry = entry.getValue();
- if (identical(sourceEntry.kind, SourceKind.LIBRARY) && !source.isInSystemLibrary()) {
+ if (identical(sourceEntry.kind, SourceKind.LIBRARY) && !source.isInSystemLibrary) {
sources.add(source);
}
}
@@ -2185,7 +2185,7 @@
for (MapEntry<Source, SourceEntry> entry in getMapEntrySet(_sourceMap)) {
Source source = entry.getKey();
SourceEntry sourceEntry = entry.getValue();
- if (identical(sourceEntry.kind, SourceKind.LIBRARY) && !source.isInSystemLibrary()) {
+ if (identical(sourceEntry.kind, SourceKind.LIBRARY) && !source.isInSystemLibrary) {
sources.add(source);
}
}
@@ -2496,9 +2496,9 @@
}
/**
- * Return a list of the sources that would be processed by {@link #performAnalysisTask()}. This
+ * Return a list of the sources that would be processed by [performAnalysisTask]. This
* method is intended to be used for testing purposes only.
- * @return a list of the sources that would be processed by {@link #performAnalysisTask()}
+ * @return a list of the sources that would be processed by [performAnalysisTask]
*/
List<Source> get sourcesNeedingProcessing {
List<Source> sources = new List<Source>();
@@ -2527,8 +2527,8 @@
/**
* Record that the given source was just accessed for some unspecified purpose.
- * <p>
- * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * Note: This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source that was accessed
*/
void accessed(Source source) {
@@ -2559,8 +2559,8 @@
/**
* Add all of the sources contained in the given source container to the given list of sources.
- * <p>
- * Note: This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * Note: This method must only be invoked while we are synchronized on [cacheLock].
* @param sources the list to which sources are to be added
* @param container the source container containing the sources to be added to the list
*/
@@ -2573,10 +2573,10 @@
}
/**
- * Return {@code true} if the given array of sources contains the given source.
+ * Return `true` if the given array of sources contains the given source.
* @param sources the sources being searched
* @param targetSource the source being searched for
- * @return {@code true} if the given source is in the array
+ * @return `true` if the given source is in the array
*/
bool contains(List<Source> sources, Source targetSource) {
for (Source source in sources) {
@@ -2588,10 +2588,10 @@
}
/**
- * Return {@code true} if the given array of sources contains any of the given target sources.
+ * Return `true` if the given array of sources contains any of the given target sources.
* @param sources the sources being searched
* @param targetSources the sources being searched for
- * @return {@code true} if any of the given target sources are in the array
+ * @return `true` if any of the given target sources are in the array
*/
bool containsAny(List<Source> sources, List<Source> targetSources) {
for (Source targetSource in targetSources) {
@@ -2604,7 +2604,7 @@
/**
* Create a source information object suitable for the given source. Return the source information
- * object that was created, or {@code null} if the source should not be tracked by this context.
+ * object that was created, or `null` if the source should not be tracked by this context.
* @param source the source for which an information object is being created
* @return the source information object that was created
*/
@@ -2622,7 +2622,7 @@
}
/**
- * Disable flushing information from the cache until {@link #enableCacheRemoval()} has been
+ * Disable flushing information from the cache until [enableCacheRemoval] has been
* called.
*/
void disableCacheRemoval() {
@@ -2659,7 +2659,7 @@
/**
* Search the compilation units that are part of the given library and return the element
- * representing the compilation unit with the given source. Return {@code null} if there is no
+ * representing the compilation unit with the given source. Return `null` if there is no
* such compilation unit.
* @param libraryElement the element representing the library being searched through
* @param unitSource the source for the compilation unit whose element is to be returned
@@ -2679,13 +2679,13 @@
}
/**
- * Return the compilation unit information associated with the given source, or {@code null} if
+ * Return the compilation unit information associated with the given source, or `null` if
* the source is not known to this context. This method should be used to access the compilation
* unit information rather than accessing the compilation unit map directly because sources in the
* SDK are implicitly part of every analysis context and are therefore only added to the map when
* first accessed.
- * <p>
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source for which information is being sought
* @return the compilation unit information associated with the given source
*/
@@ -2702,13 +2702,13 @@
}
/**
- * Return the HTML unit information associated with the given source, or {@code null} if the
+ * Return the HTML unit information associated with the given source, or `null` if the
* source is not known to this context. This method should be used to access the HTML unit
* information rather than accessing the HTML unit map directly because sources in the SDK are
* implicitly part of every analysis context and are therefore only added to the map when first
* accessed.
- * <p>
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source for which information is being sought
* @return the HTML unit information associated with the given source
*/
@@ -2754,7 +2754,7 @@
}
/**
- * Return the cache entry associated with the given source, or {@code null} if there is no entry
+ * Return the cache entry associated with the given source, or `null` if there is no entry
* associated with the source.
* @param source the source for which a cache entry is being sought
* @return the source cache entry associated with the given source
@@ -2766,12 +2766,12 @@
}
/**
- * Return the source information associated with the given source, or {@code null} if the source
+ * Return the source information associated with the given source, or `null` if the source
* is not known to this context. This method should be used to access the source information
* rather than accessing the source map directly because sources in the SDK are implicitly part of
* every analysis context and are therefore only added to the map when first accessed.
- * <p>
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source for which information is being sought
* @return the source information associated with the given source
*/
@@ -2801,10 +2801,10 @@
}
/**
- * Return {@code true} if the given compilation unit has a part-of directive but no library
+ * Return `true` if the given compilation unit has a part-of directive but no library
* directive.
* @param unit the compilation unit being tested
- * @return {@code true} if the compilation unit has a part-of directive
+ * @return `true` if the compilation unit has a part-of directive
*/
bool hasPartOfDirective(CompilationUnit unit) {
bool hasPartOf = false;
@@ -2898,8 +2898,8 @@
/**
* Invalidate all of the results computed by this context.
- * <p>
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
*/
void invalidateAllResults() {
for (MapEntry<Source, SourceEntry> mapEntry in getMapEntrySet(_sourceMap)) {
@@ -2941,11 +2941,11 @@
}
/**
- * Return {@code true} if this library is, or depends on, dart:html.
+ * Return `true` if this library is, or depends on, dart:html.
* @param library the library being tested
* @param visitedLibraries a collection of the libraries that have been visited, used to prevent
* infinite recursion
- * @return {@code true} if this library is, or depends on, dart:html
+ * @return `true` if this library is, or depends on, dart:html
*/
bool isClient(LibraryElement library, Source htmlSource, Set<LibraryElement> visitedLibraries) {
if (visitedLibraries.contains(library)) {
@@ -2970,9 +2970,9 @@
/**
* Perform a single analysis task.
- * <p>
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
- * @return {@code true} if work was done, implying that there might be more work to be done
+ *
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
+ * @return `true` if work was done, implying that there might be more work to be done
*/
bool performSingleAnalysisTask() {
for (MapEntry<Source, SourceEntry> entry in getMapEntrySet(_sourceMap)) {
@@ -3122,12 +3122,12 @@
}
/**
- * Create an entry for the newly added source. Return {@code true} if the new source is a Dart
+ * Create an entry for the newly added source. Return `true` if the new source is a Dart
* file.
- * <p>
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ *
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source that has been added
- * @return {@code true} if the new source is a Dart file
+ * @return `true` if the new source is a Dart file
*/
bool sourceAvailable(Source source) {
SourceEntry sourceEntry = _sourceMap[source];
@@ -3138,7 +3138,7 @@
}
/**
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source that has been changed
*/
void sourceChanged(Source source) {
@@ -3152,28 +3152,21 @@
htmlCopy.setState(HtmlEntry.RESOLVED_UNIT, CacheState.INVALID);
_sourceMap[source] = htmlCopy;
} else if (sourceEntry is DartEntry) {
- Set<Source> librariesToInvalidate = new Set<Source>();
List<Source> containingLibraries = getLibrariesContaining(source);
- for (Source containingLibrary in containingLibraries) {
- javaSetAdd(librariesToInvalidate, containingLibrary);
- for (Source dependentLibrary in getLibrariesDependingOn(containingLibrary)) {
- javaSetAdd(librariesToInvalidate, dependentLibrary);
- }
- }
DartEntryImpl dartCopy = ((sourceEntry as DartEntry)).writableCopy;
dartCopy.setState(SourceEntry.LINE_INFO, CacheState.INVALID);
dartCopy.setState(DartEntry.PARSE_ERRORS, CacheState.INVALID);
dartCopy.setState(DartEntry.PARSED_UNIT, CacheState.INVALID);
dartCopy.setState(DartEntry.SOURCE_KIND, CacheState.INVALID);
_sourceMap[source] = dartCopy;
- for (Source library in librariesToInvalidate) {
+ for (Source library in containingLibraries) {
invalidateLibraryResolution(library);
}
}
}
/**
- * <b>Note:</b> This method must only be invoked while we are synchronized on {@link #cacheLock}.
+ * <b>Note:</b> This method must only be invoked while we are synchronized on [cacheLock].
* @param source the source that has been deleted
*/
void sourceRemoved(Source source) {
@@ -3194,7 +3187,7 @@
}
}
/**
- * Instances of the class {@code ScanResult} represent the results of scanning a source.
+ * Instances of the class `ScanResult` represent the results of scanning a source.
*/
class AnalysisContextImpl_ScanResult {
@@ -3266,18 +3259,18 @@
}
}
/**
- * Instances of the class {@code AnalysisErrorInfoImpl} represent the analysis errors and line info
+ * Instances of the class `AnalysisErrorInfoImpl` represent the analysis errors and line info
* associated with a source.
*/
class AnalysisErrorInfoImpl implements AnalysisErrorInfo {
/**
- * The analysis errors associated with a source, or {@code null} if there are no errors.
+ * The analysis errors associated with a source, or `null` if there are no errors.
*/
List<AnalysisError> _errors;
/**
- * The line information associated with the errors, or {@code null} if there are no errors.
+ * The line information associated with the errors, or `null` if there are no errors.
*/
LineInfo _lineInfo;
@@ -3292,20 +3285,20 @@
}
/**
- * Return the errors of analysis, or {@code null} if there were no errors.
+ * Return the errors of analysis, or `null` if there were no errors.
* @return the errors as a result of the analysis
*/
List<AnalysisError> get errors => _errors;
/**
- * Return the line information associated with the errors, or {@code null} if there were no
+ * Return the line information associated with the errors, or `null` if there were no
* errors.
* @return the line information associated with the errors
*/
LineInfo get lineInfo => _lineInfo;
}
/**
- * Instances of the class {@code AnalysisOptions} represent a set of analysis options used to
+ * Instances of the class `AnalysisOptions` represent a set of analysis options used to
* control the behavior of an analysis context.
*/
class AnalysisOptionsImpl implements AnalysisOptions {
@@ -3317,78 +3310,78 @@
bool _strictMode = false;
/**
- * Return {@code true} if analysis is to use strict mode. In strict mode, error reporting is based
+ * Return `true` if analysis is to use strict mode. In strict mode, error reporting is based
* exclusively on the static type information.
- * @return {@code true} if analysis is to use strict mode
+ * @return `true` if analysis is to use strict mode
*/
bool get strictMode => _strictMode;
/**
* Set whether analysis is to use strict mode to the given value. In strict mode, error reporting
* is based exclusively on the static type information.
- * @param isStrict {@code true} if analysis is to use strict mode
+ * @param isStrict `true` if analysis is to use strict mode
*/
void set strictMode(bool isStrict) {
_strictMode = isStrict;
}
}
/**
- * The enumeration {@code CacheState} defines the possible states of cached data.
+ * The enumeration `CacheState` defines the possible states of cached data.
*/
class CacheState implements Comparable<CacheState> {
/**
* The data is not in the cache and the last time an attempt was made to compute the data an
* exception occurred, making it pointless to attempt.
- * <p>
+ *
* Valid Transitions:
- * <ul>
- * <li>{@link #INVALID} if a source was modified that might cause the data to be computable</li>
- * </ul>
+ *
+ * * [INVALID] if a source was modified that might cause the data to be computable
+ *
*/
static final CacheState ERROR = new CacheState('ERROR', 0);
/**
* The data is not in the cache because it was flushed from the cache in order to control memory
* usage. If the data is recomputed, results do not need to be reported.
- * <p>
+ *
* Valid Transitions:
- * <ul>
- * <li>{@link #IN_PROCESS} if the data is being recomputed</li>
- * <li>{@link #INVALID} if a source was modified that causes the data to need to be recomputed</li>
- * </ul>
+ *
+ * * [IN_PROCESS] if the data is being recomputed
+ * * [INVALID] if a source was modified that causes the data to need to be recomputed
+ *
*/
static final CacheState FLUSHED = new CacheState('FLUSHED', 1);
/**
* The data might or might not be in the cache but is in the process of being recomputed.
- * <p>
+ *
* Valid Transitions:
- * <ul>
- * <li>{@link #ERROR} if an exception occurred while trying to compute the data</li>
- * <li>{@link #VALID} if the data was successfully computed and stored in the cache</li>
- * </ul>
+ *
+ * * [ERROR] if an exception occurred while trying to compute the data
+ * * [VALID] if the data was successfully computed and stored in the cache
+ *
*/
static final CacheState IN_PROCESS = new CacheState('IN_PROCESS', 2);
/**
* The data is not in the cache and needs to be recomputed so that results can be reported.
- * <p>
+ *
* Valid Transitions:
- * <ul>
- * <li>{@link #IN_PROCESS} if an attempt is being made to recompute the data</li>
- * </ul>
+ *
+ * * [IN_PROCESS] if an attempt is being made to recompute the data
+ *
*/
static final CacheState INVALID = new CacheState('INVALID', 3);
/**
* The data is in the cache and up-to-date.
- * <p>
+ *
* Valid Transitions:
- * <ul>
- * <li>{@link #FLUSHED} if the data is removed in order to manage memory usage</li>
- * <li>{@link #INVALID} if a source was modified in such a way as to invalidate the previous data</li>
- * </ul>
+ *
+ * * [FLUSHED] if the data is removed in order to manage memory usage
+ * * [INVALID] if a source was modified in such a way as to invalidate the previous data
+ *
*/
static final CacheState VALID = new CacheState('VALID', 4);
static final List<CacheState> values = [ERROR, FLUSHED, IN_PROCESS, INVALID, VALID];
@@ -3405,7 +3398,7 @@
String toString() => name;
}
/**
- * Instances of the class {@code ChangeNoticeImpl} represent a change to the analysis results
+ * Instances of the class `ChangeNoticeImpl` represent a change to the analysis results
* associated with a given source.
* @coverage dart.engine
*/
@@ -3417,19 +3410,19 @@
Source _source;
/**
- * The fully resolved AST that changed as a result of the analysis, or {@code null} if the AST was
+ * The fully resolved AST that changed as a result of the analysis, or `null` if the AST was
* not changed.
*/
CompilationUnit _compilationUnit;
/**
- * The errors that changed as a result of the analysis, or {@code null} if errors were not
+ * The errors that changed as a result of the analysis, or `null` if errors were not
* changed.
*/
List<AnalysisError> _errors;
/**
- * The line information associated with the source, or {@code null} if errors were not changed.
+ * The line information associated with the source, or `null` if errors were not changed.
*/
LineInfo _lineInfo;
@@ -3447,21 +3440,21 @@
}
/**
- * Return the fully resolved AST that changed as a result of the analysis, or {@code null} if the
+ * Return the fully resolved AST that changed as a result of the analysis, or `null` if the
* AST was not changed.
* @return the fully resolved AST that changed as a result of the analysis
*/
CompilationUnit get compilationUnit => _compilationUnit;
/**
- * Return the errors that changed as a result of the analysis, or {@code null} if errors were not
+ * Return the errors that changed as a result of the analysis, or `null` if errors were not
* changed.
* @return the errors that changed as a result of the analysis
*/
List<AnalysisError> get errors => _errors;
/**
- * Return the line information associated with the source, or {@code null} if errors were not
+ * Return the line information associated with the source, or `null` if errors were not
* changed.
* @return the line information associated with the source
*/
@@ -3493,112 +3486,112 @@
}
}
/**
- * Instances of the class {@code DelegatingAnalysisContextImpl} extend {@link AnalysisContextImplanalysis context} to delegate sources to the appropriate analysis context. For instance, if the
- * source is in a system library then the analysis context from the {@link DartSdk} is used.
+ * Instances of the class `DelegatingAnalysisContextImpl` extend [AnalysisContextImplanalysis context] to delegate sources to the appropriate analysis context. For instance, if the
+ * source is in a system library then the analysis context from the [DartSdk] is used.
* @coverage dart.engine
*/
class DelegatingAnalysisContextImpl extends AnalysisContextImpl {
/**
- * This references the {@link InternalAnalysisContext} held onto by the {@link DartSdk} which is
- * used (instead of this {@link AnalysisContext}) for SDK sources. This field is set when
- * #setSourceFactory(SourceFactory) is called, and references the analysis context in the{@link DartUriResolver} in the {@link SourceFactory}, this analysis context assumes that there
+ * This references the [InternalAnalysisContext] held onto by the [DartSdk] which is
+ * used (instead of this [AnalysisContext]) for SDK sources. This field is set when
+ * #setSourceFactory(SourceFactory) is called, and references the analysis context in the[DartUriResolver] in the [SourceFactory], this analysis context assumes that there
* will be such a resolver.
*/
InternalAnalysisContext _sdkAnalysisContext;
void addSourceInfo(Source source, SourceEntry info) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
_sdkAnalysisContext.addSourceInfo(source, info);
} else {
super.addSourceInfo(source, info);
}
}
List<AnalysisError> computeErrors(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.computeErrors(source);
} else {
return super.computeErrors(source);
}
}
HtmlElement computeHtmlElement(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.computeHtmlElement(source);
} else {
return super.computeHtmlElement(source);
}
}
SourceKind computeKindOf(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.computeKindOf(source);
} else {
return super.computeKindOf(source);
}
}
LibraryElement computeLibraryElement(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.computeLibraryElement(source);
} else {
return super.computeLibraryElement(source);
}
}
LineInfo computeLineInfo(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.computeLineInfo(source);
} else {
return super.computeLineInfo(source);
}
}
CompilationUnit computeResolvableCompilationUnit(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.computeResolvableCompilationUnit(source);
} else {
return super.computeResolvableCompilationUnit(source);
}
}
AnalysisErrorInfo getErrors(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getErrors(source);
} else {
return super.getErrors(source);
}
}
HtmlElement getHtmlElement(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getHtmlElement(source);
} else {
return super.getHtmlElement(source);
}
}
List<Source> getHtmlFilesReferencing(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getHtmlFilesReferencing(source);
} else {
return super.getHtmlFilesReferencing(source);
}
}
SourceKind getKindOf(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getKindOf(source);
} else {
return super.getKindOf(source);
}
}
List<Source> getLibrariesContaining(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getLibrariesContaining(source);
} else {
return super.getLibrariesContaining(source);
}
}
List<Source> getLibrariesDependingOn(Source librarySource) {
- if (librarySource.isInSystemLibrary()) {
+ if (librarySource.isInSystemLibrary) {
return _sdkAnalysisContext.getLibrariesDependingOn(librarySource);
} else {
return super.getLibrariesDependingOn(librarySource);
}
}
LibraryElement getLibraryElement(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getLibraryElement(source);
} else {
return super.getLibraryElement(source);
@@ -3606,7 +3599,7 @@
}
List<Source> get librarySources => ArrayUtils.addAll(super.librarySources, _sdkAnalysisContext.librarySources);
LineInfo getLineInfo(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getLineInfo(source);
} else {
return super.getLineInfo(source);
@@ -3614,56 +3607,56 @@
}
Namespace getPublicNamespace(LibraryElement library) {
Source source = library.source;
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getPublicNamespace(library);
} else {
return super.getPublicNamespace(library);
}
}
Namespace getPublicNamespace2(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.getPublicNamespace2(source);
} else {
return super.getPublicNamespace2(source);
}
}
CompilationUnit getResolvedCompilationUnit(Source unitSource, LibraryElement library) {
- if (unitSource.isInSystemLibrary()) {
+ if (unitSource.isInSystemLibrary) {
return _sdkAnalysisContext.getResolvedCompilationUnit(unitSource, library);
} else {
return super.getResolvedCompilationUnit(unitSource, library);
}
}
CompilationUnit getResolvedCompilationUnit2(Source unitSource, Source librarySource) {
- if (unitSource.isInSystemLibrary()) {
+ if (unitSource.isInSystemLibrary) {
return _sdkAnalysisContext.getResolvedCompilationUnit2(unitSource, librarySource);
} else {
return super.getResolvedCompilationUnit2(unitSource, librarySource);
}
}
bool isClientLibrary(Source librarySource) {
- if (librarySource.isInSystemLibrary()) {
+ if (librarySource.isInSystemLibrary) {
return _sdkAnalysisContext.isClientLibrary(librarySource);
} else {
return super.isClientLibrary(librarySource);
}
}
bool isServerLibrary(Source librarySource) {
- if (librarySource.isInSystemLibrary()) {
+ if (librarySource.isInSystemLibrary) {
return _sdkAnalysisContext.isServerLibrary(librarySource);
} else {
return super.isServerLibrary(librarySource);
}
}
CompilationUnit parseCompilationUnit(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.parseCompilationUnit(source);
} else {
return super.parseCompilationUnit(source);
}
}
HtmlUnit parseHtmlUnit(Source source) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.parseHtmlUnit(source);
} else {
return super.parseHtmlUnit(source);
@@ -3674,35 +3667,35 @@
return;
}
Source source = new JavaIterator(elementMap.keys.toSet()).next();
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
_sdkAnalysisContext.recordLibraryElements(elementMap);
} else {
super.recordLibraryElements(elementMap);
}
}
CompilationUnit resolveCompilationUnit(Source source, LibraryElement library) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
return _sdkAnalysisContext.resolveCompilationUnit(source, library);
} else {
return super.resolveCompilationUnit(source, library);
}
}
CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) {
- if (unitSource.isInSystemLibrary()) {
+ if (unitSource.isInSystemLibrary) {
return _sdkAnalysisContext.resolveCompilationUnit2(unitSource, librarySource);
} else {
return super.resolveCompilationUnit2(unitSource, librarySource);
}
}
HtmlUnit resolveHtmlUnit(Source unitSource) {
- if (unitSource.isInSystemLibrary()) {
+ if (unitSource.isInSystemLibrary) {
return _sdkAnalysisContext.resolveHtmlUnit(unitSource);
} else {
return super.resolveHtmlUnit(unitSource);
}
}
void setContents(Source source, String contents) {
- if (source.isInSystemLibrary()) {
+ if (source.isInSystemLibrary) {
_sdkAnalysisContext.setContents(source, contents);
} else {
super.setContents(source, contents);
@@ -3723,7 +3716,7 @@
}
}
/**
- * Instances of the class {@code InstrumentedAnalysisContextImpl} implement an{@link AnalysisContext analysis context} by recording instrumentation data and delegating to
+ * Instances of the class `InstrumentedAnalysisContextImpl` implement an[AnalysisContext analysis context] by recording instrumentation data and delegating to
* another analysis context to do the non-instrumentation work.
* @coverage dart.engine
*/
@@ -3749,7 +3742,7 @@
InternalAnalysisContext _basis;
/**
- * Create a new {@link InstrumentedAnalysisContextImpl} which wraps a new{@link AnalysisContextImpl} as the basis context.
+ * Create a new [InstrumentedAnalysisContextImpl] which wraps a new[AnalysisContextImpl] as the basis context.
*/
InstrumentedAnalysisContextImpl() {
_jtd_constructor_183_impl();
@@ -3759,9 +3752,9 @@
}
/**
- * Create a new {@link InstrumentedAnalysisContextImpl} with a specified basis context, aka the
+ * Create a new [InstrumentedAnalysisContextImpl] with a specified basis context, aka the
* context to wrap and instrument.
- * @param context some {@link InstrumentedAnalysisContext} to wrap and instrument
+ * @param context some [InstrumentedAnalysisContext] to wrap and instrument
*/
InstrumentedAnalysisContextImpl.con1(InternalAnalysisContext context) {
_jtd_constructor_184_impl(context);
@@ -3870,7 +3863,7 @@
}
/**
- * @return the underlying {@link AnalysisContext}.
+ * @return the underlying [AnalysisContext].
*/
AnalysisContext get basis => _basis;
Element getElement(ElementLocation location) {
@@ -4195,7 +4188,7 @@
}
}
/**
- * The interface {@code InternalAnalysisContext} defines additional behavior for an analysis context
+ * The interface `InternalAnalysisContext` defines additional behavior for an analysis context
* that is required by internal users of the context.
*/
abstract class InternalAnalysisContext implements AnalysisContext {
@@ -4253,7 +4246,7 @@
void recordLibraryElements(Map<Source, LibraryElement> elementMap);
}
/**
- * Instances of the class {@code RecordingErrorListener} implement an error listener that will
+ * Instances of the class `RecordingErrorListener` implement an error listener that will
* record the errors that are reported to it in a way that is appropriate for caching those errors
* within an analysis context.
* @coverage dart.engine
@@ -4261,7 +4254,7 @@
class RecordingErrorListener implements AnalysisErrorListener {
/**
- * A HashMap of lists containing the errors that were collected, keyed by each {@link Source}.
+ * A HashMap of lists containing the errors that were collected, keyed by each [Source].
*/
Map<Source, List<AnalysisError>> _errors = new Map<Source, List<AnalysisError>>();
@@ -4277,7 +4270,7 @@
/**
* Answer the errors collected by the listener.
- * @return an array of errors (not {@code null}, contains no {@code null}s)
+ * @return an array of errors (not `null`, contains no `null`s)
*/
List<AnalysisError> get errors {
Iterable<MapEntry<Source, List<AnalysisError>>> entrySet = getMapEntrySet(_errors);
@@ -4293,10 +4286,10 @@
}
/**
- * Answer the errors collected by the listener for some passed {@link Source}.
- * @param source some {@link Source} for which the caller wants the set of {@link AnalysisError}s
+ * Answer the errors collected by the listener for some passed [Source].
+ * @param source some [Source] for which the caller wants the set of [AnalysisError]s
* collected by this listener
- * @return the errors collected by the listener for the passed {@link Source}
+ * @return the errors collected by the listener for the passed [Source]
*/
List<AnalysisError> getErrors2(Source source) {
List<AnalysisError> errorsForSource = _errors[source];
@@ -4317,7 +4310,7 @@
}
}
/**
- * Instances of the class {@code ResolutionEraser} remove any resolution information from an AST
+ * Instances of the class `ResolutionEraser` remove any resolution information from an AST
* structure when used to visit that structure.
*/
class ResolutionEraser extends GeneralizingASTVisitor<Object> {
@@ -4388,7 +4381,7 @@
}
}
/**
- * The interface {@code Logger} defines the behavior of objects that can be used to receive
+ * The interface `Logger` defines the behavior of objects that can be used to receive
* information about errors within the analysis engine. Implementations usually write this
* information to a file, but can also record the information for later use (such as during testing)
* or even ignore the information.
@@ -4431,7 +4424,7 @@
void logInformation2(String message, Exception exception);
}
/**
- * Implementation of {@link Logger} that does nothing.
+ * Implementation of [Logger] that does nothing.
*/
class Logger_NullLogger implements Logger {
void logError(String message) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index 6061cb0..a330e1e 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -6,7 +6,7 @@
import 'ast.dart' show ASTNode;
import 'scanner.dart' show Token;
/**
- * Instances of the enumeration {@code ErrorSeverity} represent the severity of an {@link ErrorCode}.
+ * Instances of the enumeration `ErrorSeverity` represent the severity of an [ErrorCode].
* @coverage dart.engine.error
*/
class ErrorSeverity implements Comparable<ErrorSeverity> {
@@ -24,7 +24,7 @@
static final ErrorSeverity SUGGESTION = new ErrorSeverity('SUGGESTION', 1, "S", "suggestion");
/**
- * The severity representing a warning. Warnings can become errors if the {@code -Werror} command
+ * The severity representing a warning. Warnings can become errors if the `-Werror` command
* line flag is specified.
*/
static final ErrorSeverity WARNING = new ErrorSeverity('WARNING', 2, "W", "warning");
@@ -84,7 +84,7 @@
String toString() => name;
}
/**
- * Instances of the class {@code AnalysisErrorWithProperties}
+ * Instances of the class `AnalysisErrorWithProperties`
*/
class AnalysisErrorWithProperties extends AnalysisError {
@@ -122,7 +122,7 @@
Object getProperty(ErrorProperty property) => _propertyMap[property];
/**
- * Set the value of the given property to the given value. Using a value of {@code null} will
+ * Set the value of the given property to the given value. Using a value of `null` will
* effectively remove the property from this error.
* @param property the property whose value is to be returned
* @param value the new value of the given property
@@ -132,7 +132,7 @@
}
}
/**
- * Instances of the class {@code ErrorReporter} wrap an error listener with utility methods used to
+ * Instances of the class `ErrorReporter` wrap an error listener with utility methods used to
* create the errors being reported.
* @coverage dart.engine.error
*/
@@ -217,7 +217,7 @@
}
/**
- * Set the source to be used when reporting errors. Setting the source to {@code null} will cause
+ * Set the source to be used when reporting errors. Setting the source to `null` will cause
* the default source to be used.
* @param source the source to be used when reporting errors
*/
@@ -226,7 +226,7 @@
}
}
/**
- * Instances of the class {@code AnalysisError} represent an error discovered during the analysis of
+ * Instances of the class `AnalysisError` represent an error discovered during the analysis of
* some Dart code.
* @see AnalysisErrorListener
* @coverage dart.engine.error
@@ -239,13 +239,13 @@
static List<AnalysisError> NO_ERRORS = new List<AnalysisError>(0);
/**
- * A {@link Comparator} that sorts by the name of the file that the {@link AnalysisError} was
+ * A [Comparator] that sorts by the name of the file that the [AnalysisError] was
* found.
*/
static Comparator<AnalysisError> FILE_COMPARATOR = (AnalysisError o1, AnalysisError o2) => o1.source.shortName.compareTo(o2.source.shortName);
/**
- * A {@link Comparator} that sorts error codes first by their severity (errors first, warnings
+ * A [Comparator] that sorts error codes first by their severity (errors first, warnings
* second), and then by the the error code type.
*/
static Comparator<AnalysisError> ERROR_CODE_COMPARATOR = (AnalysisError o1, AnalysisError o2) {
@@ -273,7 +273,7 @@
String _message;
/**
- * The source in which the error occurred, or {@code null} if unknown.
+ * The source in which the error occurred, or `null` if unknown.
*/
Source _source;
@@ -350,7 +350,7 @@
int get offset => _offset;
/**
- * Return the value of the given property, or {@code null} if the given property is not defined
+ * Return the value of the given property, or `null` if the given property is not defined
* for this error.
* @param property the property whose value is to be returned
* @return the value of the given property
@@ -358,7 +358,7 @@
Object getProperty(ErrorProperty property) => null;
/**
- * Return the source in which the error occurred, or {@code null} if unknown.
+ * Return the source in which the error occurred, or `null` if unknown.
* @return the source in which the error occurred
*/
Source get source => _source;
@@ -389,12 +389,12 @@
}
}
/**
- * The enumeration {@code ErrorProperty} defines the properties that can be associated with an{@link AnalysisError}.
+ * The enumeration `ErrorProperty` defines the properties that can be associated with an[AnalysisError].
*/
class ErrorProperty implements Comparable<ErrorProperty> {
/**
- * A property whose value is an array of {@link ExecutableElement executable elements} that should
+ * A property whose value is an array of [ExecutableElement executable elements] that should
* be but are not implemented by a concrete class.
*/
static final ErrorProperty UNIMPLEMENTED_METHODS = new ErrorProperty('UNIMPLEMENTED_METHODS', 0);
@@ -412,8 +412,8 @@
String toString() => name;
}
/**
- * The interface {@code ErrorCode} defines the behavior common to objects representing error codes
- * associated with {@link AnalysisError analysis errors}.
+ * The interface `ErrorCode` defines the behavior common to objects representing error codes
+ * associated with [AnalysisError analysis errors].
* @coverage dart.engine.error
*/
abstract class ErrorCode {
@@ -437,7 +437,7 @@
ErrorType get type;
}
/**
- * Instances of the enumeration {@code ErrorType} represent the type of an {@link ErrorCode}.
+ * Instances of the enumeration `ErrorType` represent the type of an [ErrorCode].
* @coverage dart.engine.error
*/
class ErrorType implements Comparable<ErrorType> {
@@ -501,7 +501,7 @@
String toString() => name;
}
/**
- * The enumeration {@code CompileTimeErrorCode} defines the error codes used for compile time
+ * The enumeration `CompileTimeErrorCode` defines the error codes used for compile time
* errors. The convention for this class is for the name of the error code to indicate the problem
* that caused the error to be generated and for the error message to explain what is wrong and,
* when appropriate, how the problem can be corrected.
@@ -523,10 +523,10 @@
* 14.1 Imports: If a name <i>N</i> is referenced by a library <i>L</i> and <i>N</i> is introduced
* into the top level scope <i>L</i> by more than one import then:
* <ol>
- * <li>It is a static warning if <i>N</i> is used as a type annotation.
- * <li>In checked mode, it is a dynamic error if <i>N</i> is used as a type annotation and
+ * * It is a static warning if <i>N</i> is used as a type annotation.
+ * * In checked mode, it is a dynamic error if <i>N</i> is used as a type annotation and
* referenced during a subtype test.
- * <li>Otherwise, it is a compile-time error.
+ * * Otherwise, it is a compile-time error.
* </ol>
* @param ambiguousElementName the name of the ambiguous element
* @param firstLibraryName the name of the first library that the type is found
@@ -602,7 +602,7 @@
/**
* 7.6.3 Constant Constructors: It is a compile-time error if a constant constructor is declared
* by a class that has a non-final instance variable.
- * <p>
+ *
* The above refers to both locally declared and inherited instance variables.
*/
static final CompileTimeErrorCode CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD = new CompileTimeErrorCode('CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD', 12, "Cannot define the 'const' constructor for a class with non-final fields");
@@ -611,7 +611,7 @@
* 7.6.1 Generative Constructors: In checked mode, it is a dynamic type error if o is not
* <b>null</b> and the interface of the class of <i>o</i> is not a subtype of the static type of
* the field <i>v</i>.
- * <p>
+ *
* 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
* uncaught exception being thrown.
* @param initializerType the name of the type of the initializer expression
@@ -696,7 +696,7 @@
/**
* 12.11.2 Const: It is a compile-time error if <i>T</i> is not a class accessible in the current
* scope, optionally followed by type arguments.
- * <p>
+ *
* 12.11.2 Const: If <i>e</i> is of the form <i>const T.id(a<sub>1</sub>, …, a<sub>n</sub>,
* x<sub>n+1</sub>: a<sub>n+1</sub>, … x<sub>n+k</sub>: a<sub>n+k</sub>)</i> it is a
* compile-time error if <i>T</i> is not a class accessible in the current scope, optionally
@@ -791,16 +791,16 @@
/**
* 12.2 Null: It is a compile-time error for a class to attempt to extend or implement Null.
- * <p>
+ *
* 12.3 Numbers: It is a compile-time error for a class to attempt to extend or implement int.
- * <p>
+ *
* 12.3 Numbers: It is a compile-time error for a class to attempt to extend or implement double.
- * <p>
+ *
* 12.3 Numbers: It is a compile-time error for any type other than the types int and double to
* attempt to extend or implement num.
- * <p>
+ *
* 12.4 Booleans: It is a compile-time error for a class to attempt to extend or implement bool.
- * <p>
+ *
* 12.5 Strings: It is a compile-time error for a class to attempt to extend or implement String.
* @param typeName the name of the type that cannot be extended
* @see #IMPLEMENTS_DISALLOWED_CLASS
@@ -809,7 +809,7 @@
/**
* 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m < h</i> or if <i>m > n</i>.
- * <p>
+ *
* 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
* uncaught exception being thrown.
* @param requiredCount the maximum number of positional arguments
@@ -819,16 +819,16 @@
/**
* 12.2 Null: It is a compile-time error for a class to attempt to extend or implement Null.
- * <p>
+ *
* 12.3 Numbers: It is a compile-time error for a class to attempt to extend or implement int.
- * <p>
+ *
* 12.3 Numbers: It is a compile-time error for a class to attempt to extend or implement double.
- * <p>
+ *
* 12.3 Numbers: It is a compile-time error for any type other than the types int and double to
* attempt to extend or implement num.
- * <p>
+ *
* 12.4 Booleans: It is a compile-time error for a class to attempt to extend or implement bool.
- * <p>
+ *
* 12.5 Strings: It is a compile-time error for a class to attempt to extend or implement String.
* @param typeName the name of the type that cannot be implemented
* @see #EXTENDS_DISALLOWED_CLASS
@@ -886,7 +886,7 @@
/**
* 7.6.1 Generative Constructors: A generative constructor may be redirecting, in which case its
* only action is to invoke another generative constructor.
- * <p>
+ *
* 7.6.1 Generative Constructors: It is a compile-time error if an initializing formal is used by
* a function other than a non-redirecting generative constructor.
*/
@@ -923,7 +923,7 @@
/**
* 7.6.1 Generative Constructors: Note that this is not in scope on the right hand side of an
* initializer.
- * <p>
+ *
* 12.10 This: It is a compile-time error if this appears in a top-level function or variable
* initializer, in a factory constructor, or in a static method or variable initializer, or in the
* initializer of an instance variable.
@@ -1076,10 +1076,10 @@
/**
* 14.2 Exports: It is a compile-time error if the compilation unit found at the specified URI is
* not a library declaration.
- * <p>
+ *
* 14.1 Imports: It is a compile-time error if the compilation unit found at the specified URI is
* not a library declaration.
- * <p>
+ *
* 14.3 Parts: It is a compile time error if the contents of the URI are not a valid part
* declaration.
* @param uri the URI that is invalid
@@ -1090,7 +1090,7 @@
/**
* 13.13 Break: It is a compile-time error if no such statement <i>s<sub>E</sub></i> exists within
* the innermost function in which <i>s<sub>b</sub></i> occurs.
- * <p>
+ *
* 13.14 Continue: It is a compile-time error if no such statement or case clause
* <i>s<sub>E</sub></i> exists within the innermost function in which <i>s<sub>c</sub></i> occurs.
* @param labelName the name of the unresolvable label
@@ -1100,7 +1100,7 @@
/**
* 13.13 Break: It is a compile-time error if no such statement <i>s<sub>E</sub></i> exists within
* the innermost function in which <i>s<sub>b</sub></i> occurs.
- * <p>
+ *
* 13.14 Continue: It is a compile-time error if no such statement or case clause
* <i>s<sub>E</sub></i> exists within the innermost function in which <i>s<sub>c</sub></i> occurs.
* @param labelName the name of the unresolvable label
@@ -1231,7 +1231,7 @@
/**
* 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m < h</i> or if <i>m > n</i>.
- * <p>
+ *
* 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
* uncaught exception being thrown.
* @param requiredCount the expected number of required arguments
@@ -1285,10 +1285,10 @@
/**
* 7.6.1 Generative Constructors: A generative constructor may be redirecting, in which case its
* only action is to invoke another generative constructor.
- * <p>
+ *
* TODO(scheglov) review this later, there are no explicit "it is a compile-time error" in
* specification. But it was added to the co19 and there is same error for factories.
- * <p>
+ *
* https://code.google.com/p/dart/issues/detail?id=954
*/
static final CompileTimeErrorCode RECURSIVE_CONSTRUCTOR_REDIRECT = new CompileTimeErrorCode('RECURSIVE_CONSTRUCTOR_REDIRECT', 103, "Cycle in redirecting generative constructors");
@@ -1308,9 +1308,9 @@
/**
* 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
* superinterface of itself.
- * <p>
+ *
* 8.1 Superinterfaces: It is a compile-time error if an interface is a superinterface of itself.
- * <p>
+ *
* 7.9 Superclasses: It is a compile-time error if a class <i>C</i> is a superclass of itself.
* @param className the name of the class that implements itself recursively
* @param strImplementsPath a string representation of the implements loop
@@ -1320,9 +1320,9 @@
/**
* 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
* superinterface of itself.
- * <p>
+ *
* 8.1 Superinterfaces: It is a compile-time error if an interface is a superinterface of itself.
- * <p>
+ *
* 7.9 Superclasses: It is a compile-time error if a class <i>C</i> is a superclass of itself.
* @param className the name of the class that implements itself recursively
*/
@@ -1331,9 +1331,9 @@
/**
* 7.10 Superinterfaces: It is a compile-time error if the interface of a class <i>C</i> is a
* superinterface of itself.
- * <p>
+ *
* 8.1 Superinterfaces: It is a compile-time error if an interface is a superinterface of itself.
- * <p>
+ *
* 7.9 Superclasses: It is a compile-time error if a class <i>C</i> is a superclass of itself.
* @param className the name of the class that implements itself recursively
*/
@@ -1404,20 +1404,10 @@
static final CompileTimeErrorCode SUPER_INITIALIZER_IN_OBJECT = new CompileTimeErrorCode('SUPER_INITIALIZER_IN_OBJECT', 118, "");
/**
- * 12.11 Instance Creation: It is a compile-time error if a constructor of a non-generic type
- * invoked by a new expression or a constant object expression is passed any type arguments.
- * <p>
- * 12.32 Type Cast: It is a compile-time error if <i>T</i> is a parameterized type of the form
- * <i>G<T<sub>1</sub>, …, T<sub>n</sub>></i> and <i>G</i> is not a generic type with
- * <i>n</i> type parameters.
- */
- static final CompileTimeErrorCode TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS = new CompileTimeErrorCode('TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS', 119, "");
-
- /**
* 12.11.2 Const: It is a compile-time error if <i>T</i> is not a class accessible in the current
* scope, optionally followed by type arguments.
*/
- static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode('UNDEFINED_CLASS', 120, "Undefined class '%s'");
+ static final CompileTimeErrorCode UNDEFINED_CLASS = new CompileTimeErrorCode('UNDEFINED_CLASS', 119, "Undefined class '%s'");
/**
* 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1425,7 +1415,7 @@
* a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
* (respectively <i>S.id</i>)
*/
- static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 121, "The class '%s' does not have a generative constructor '%s'");
+ static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER = new CompileTimeErrorCode('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER', 120, "The class '%s' does not have a generative constructor '%s'");
/**
* 7.6.1 Generative Constructors: Let <i>C</i> be the class in which the superinitializer appears
@@ -1433,7 +1423,7 @@
* a compile-time error if class <i>S</i> does not declare a generative constructor named <i>S</i>
* (respectively <i>S.id</i>)
*/
- static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT = new CompileTimeErrorCode('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT', 122, "The class '%s' does not have a default generative constructor");
+ static final CompileTimeErrorCode UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT = new CompileTimeErrorCode('UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT', 121, "The class '%s' does not have a default generative constructor");
/**
* 7.6.1 Generative Constructors: Let <i>k</i> be a generative constructor. Each final instance
@@ -1441,49 +1431,49 @@
* <i>k</i>'s initializer list unless it has already been initialized by one of the following
* means:
* <ol>
- * <li>Initialization at the declaration of <i>f</i>.
- * <li>Initialization by means of an initializing formal of <i>k</i>.
+ * * Initialization at the declaration of <i>f</i>.
+ * * Initialization by means of an initializing formal of <i>k</i>.
* </ol>
* or a compile-time error occurs.
*/
- static final CompileTimeErrorCode UNINITIALIZED_FINAL_FIELD = new CompileTimeErrorCode('UNINITIALIZED_FINAL_FIELD', 123, "");
+ static final CompileTimeErrorCode UNINITIALIZED_FINAL_FIELD = new CompileTimeErrorCode('UNINITIALIZED_FINAL_FIELD', 122, "");
/**
* 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
* must have a corresponding named parameter in the set {<i>p<sub>n+1</sub></i> ...
* <i>p<sub>n+k</sub></i>} or a static warning occurs.
- * <p>
+ *
* 12.11.2 Const: It is a compile-time error if evaluation of a constant object results in an
* uncaught exception being thrown.
* @param name the name of the requested named parameter
*/
- static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode('UNDEFINED_NAMED_PARAMETER', 124, "The named parameter '%s' is not defined");
+ static final CompileTimeErrorCode UNDEFINED_NAMED_PARAMETER = new CompileTimeErrorCode('UNDEFINED_NAMED_PARAMETER', 123, "The named parameter '%s' is not defined");
/**
* 14.2 Exports: It is a compile-time error if the compilation unit found at the specified URI is
* not a library declaration.
- * <p>
+ *
* 14.1 Imports: It is a compile-time error if the compilation unit found at the specified URI is
* not a library declaration.
- * <p>
+ *
* 14.3 Parts: It is a compile time error if the contents of the URI are not a valid part
* declaration.
* @param uri the URI pointing to a non-existent file
* @see #INVALID_URI
*/
- static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode('URI_DOES_NOT_EXIST', 125, "Target of URI does not exist: '%s'");
+ static final CompileTimeErrorCode URI_DOES_NOT_EXIST = new CompileTimeErrorCode('URI_DOES_NOT_EXIST', 124, "Target of URI does not exist: '%s'");
/**
* 14.1 Imports: It is a compile-time error if <i>x</i> is not a compile-time constant, or if
* <i>x</i> involves string interpolation.
- * <p>
+ *
* 14.3 Parts: It is a compile-time error if <i>s</i> is not a compile-time constant, or if
* <i>s</i> involves string interpolation.
- * <p>
+ *
* 14.5 URIs: It is a compile-time error if the string literal <i>x</i> that describes a URI is
* not a compile-time constant, or if <i>x</i> involves string interpolation.
*/
- static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode('URI_WITH_INTERPOLATION', 126, "URIs cannot use string interpolation");
+ static final CompileTimeErrorCode URI_WITH_INTERPOLATION = new CompileTimeErrorCode('URI_WITH_INTERPOLATION', 125, "URIs cannot use string interpolation");
/**
* 7.1.1 Operators: It is a compile-time error if the arity of the user-declared operator \[\]= is
@@ -1495,33 +1485,33 @@
* @param expectedNumberOfParameters the number of parameters expected
* @param actualNumberOfParameters the number of parameters found in the operator declaration
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 127, "Operator '%s' should declare exactly %d parameter(s), but %d found");
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR', 126, "Operator '%s' should declare exactly %d parameter(s), but %d found");
/**
* 7.1.1 Operators: It is a compile time error if the arity of the user-declared operator - is not
* 0 or 1.
* @param actualNumberOfParameters the number of parameters found in the operator declaration
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS', 128, "Operator '-' should declare 0 or 1 parameter, but %d found");
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS', 127, "Operator '-' should declare 0 or 1 parameter, but %d found");
/**
* 7.3 Setters: It is a compile-time error if a setter's formal parameter list does not include
* exactly one required formal parameter <i>p</i>.
* @param numberOfParameters the number of parameters found in the setter
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 129, "Setters should declare exactly one parameter, %d found");
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER = new CompileTimeErrorCode('WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER', 128, "Setters should declare exactly one parameter, %d found");
/**
* 12.11 Instance Creation: It is a compile-time error if a constructor of a generic type with
* <i>n</i> type parameters invoked by a new expression or a constant object expression is passed
* <i>m</i> type arguments where <i>m != n</i>.
- * <p>
+ *
* 12.31 Type Test: It is a compile-time error if <i>T</i> is a parameterized type of the form
* <i>G<T<sub>1</sub>, …, T<sub>n</sub>></i> and <i>G</i> is not a generic type with
* <i>n</i> type parameters.
*/
- static final CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new CompileTimeErrorCode('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 130, "");
- static final List<CompileTimeErrorCode> values = [AMBIGUOUS_EXPORT, AMBIGUOUS_IMPORT, ARGUMENT_DEFINITION_TEST_NON_PARAMETER, BUILT_IN_IDENTIFIER_AS_TYPE, BUILT_IN_IDENTIFIER_AS_TYPE_NAME, BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME, CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, COMPILE_TIME_CONSTANT_RAISES_EXCEPTION, CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, CONST_CONSTRUCTOR_THROWS_EXCEPTION, CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, CONST_FORMAL_PARAMETER, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, CONST_INSTANCE_FIELD, CONST_EVAL_TYPE_BOOL, CONST_EVAL_TYPE_BOOL_NUM_STRING, CONST_EVAL_TYPE_INT, CONST_EVAL_TYPE_NUM, CONST_EVAL_THROWS_EXCEPTION, CONST_WITH_INVALID_TYPE_PARAMETERS, CONST_WITH_NON_CONST, CONST_WITH_NON_CONSTANT_ARGUMENT, CONST_WITH_NON_TYPE, CONST_WITH_TYPE_PARAMETERS, CONST_WITH_UNDEFINED_CONSTRUCTOR, CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, DUPLICATE_CONSTRUCTOR_DEFAULT, DUPLICATE_CONSTRUCTOR_NAME, DUPLICATE_DEFINITION, DUPLICATE_MEMBER_NAME, DUPLICATE_MEMBER_NAME_INSTANCE_STATIC, DUPLICATE_NAMED_ARGUMENT, EXPORT_INTERNAL_LIBRARY, EXPORT_OF_NON_LIBRARY, EXTENDS_NON_CLASS, EXTENDS_DISALLOWED_CLASS, EXTRA_POSITIONAL_ARGUMENTS, IMPLEMENTS_DISALLOWED_CLASS, FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION, FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER, FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, FINAL_INITIALIZED_MULTIPLE_TIMES, FIELD_INITIALIZER_FACTORY_CONSTRUCTOR, FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, GETTER_AND_METHOD_WITH_SAME_NAME, IMPLEMENTS_DYNAMIC, IMPLEMENTS_NON_CLASS, IMPLEMENTS_REPEATED, IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, IMPORT_INTERNAL_LIBRARY, IMPORT_OF_NON_LIBRARY, INCONSISTENT_CASE_EXPRESSION_TYPES, INITIALIZER_FOR_NON_EXISTANT_FIELD, INITIALIZER_FOR_STATIC_FIELD, INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD, INITIALIZING_FORMAL_FOR_STATIC_FIELD, INVALID_CONSTANT, INVALID_CONSTRUCTOR_NAME, INVALID_FACTORY_NAME_NOT_A_CLASS, INVALID_OVERRIDE_DEFAULT_VALUE, INVALID_OVERRIDE_NAMED, INVALID_OVERRIDE_POSITIONAL, INVALID_OVERRIDE_REQUIRED, INVALID_REFERENCE_TO_THIS, INVALID_TYPE_ARGUMENT_FOR_KEY, INVALID_TYPE_ARGUMENT_IN_CONST_LIST, INVALID_TYPE_ARGUMENT_IN_CONST_MAP, INVALID_URI, LABEL_IN_OUTER_SCOPE, LABEL_UNDEFINED, MEMBER_WITH_CLASS_NAME, METHOD_AND_GETTER_WITH_SAME_NAME, MISSING_CONST_IN_LIST_LITERAL, MISSING_CONST_IN_MAP_LITERAL, MIXIN_DECLARES_CONSTRUCTOR, MIXIN_INHERITS_FROM_NOT_OBJECT, MIXIN_OF_NON_CLASS, MIXIN_REFERENCES_SUPER, MIXIN_WITH_NON_CLASS_SUPERCLASS, MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS, MULTIPLE_SUPER_INITIALIZERS, NEW_WITH_INVALID_TYPE_PARAMETERS, NON_CONST_MAP_AS_EXPRESSION_STATEMENT, NON_CONSTANT_CASE_EXPRESSION, NON_CONSTANT_DEFAULT_VALUE, NON_CONSTANT_LIST_ELEMENT, NON_CONSTANT_MAP_KEY, NON_CONSTANT_MAP_VALUE, NON_CONSTANT_VALUE_IN_INITIALIZER, NOT_ENOUGH_REQUIRED_ARGUMENTS, NON_GENERATIVE_CONSTRUCTOR, OBJECT_CANNOT_EXTEND_ANOTHER_CLASS, OPTIONAL_PARAMETER_IN_OPERATOR, PART_OF_NON_PART, PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, PRIVATE_OPTIONAL_PARAMETER, RECURSIVE_COMPILE_TIME_CONSTANT, RECURSIVE_CONSTRUCTOR_REDIRECT, RECURSIVE_FACTORY_REDIRECT, RECURSIVE_FUNCTION_TYPE_ALIAS, RECURSIVE_INTERFACE_INHERITANCE, RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS, RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS, REDIRECT_TO_NON_CONST_CONSTRUCTOR, REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER, RESERVED_WORD_AS_IDENTIFIER, RETHROW_OUTSIDE_CATCH, RETURN_IN_GENERATIVE_CONSTRUCTOR, STATIC_TOP_LEVEL_FUNCTION, STATIC_TOP_LEVEL_VARIABLE, SUPER_IN_INVALID_CONTEXT, SUPER_IN_REDIRECTING_CONSTRUCTOR, SUPER_INITIALIZER_IN_OBJECT, TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS, UNDEFINED_CLASS, UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, UNINITIALIZED_FINAL_FIELD, UNDEFINED_NAMED_PARAMETER, URI_DOES_NOT_EXIST, URI_WITH_INTERPOLATION, WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS, WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, WRONG_NUMBER_OF_TYPE_ARGUMENTS];
+ static final CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS = new CompileTimeErrorCode('WRONG_NUMBER_OF_TYPE_ARGUMENTS', 129, "");
+ static final List<CompileTimeErrorCode> values = [AMBIGUOUS_EXPORT, AMBIGUOUS_IMPORT, ARGUMENT_DEFINITION_TEST_NON_PARAMETER, BUILT_IN_IDENTIFIER_AS_TYPE, BUILT_IN_IDENTIFIER_AS_TYPE_NAME, BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME, CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS, COMPILE_TIME_CONSTANT_RAISES_EXCEPTION, CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD, CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD, CONST_CONSTRUCTOR_THROWS_EXCEPTION, CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, CONST_FORMAL_PARAMETER, CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, CONST_INSTANCE_FIELD, CONST_EVAL_TYPE_BOOL, CONST_EVAL_TYPE_BOOL_NUM_STRING, CONST_EVAL_TYPE_INT, CONST_EVAL_TYPE_NUM, CONST_EVAL_THROWS_EXCEPTION, CONST_WITH_INVALID_TYPE_PARAMETERS, CONST_WITH_NON_CONST, CONST_WITH_NON_CONSTANT_ARGUMENT, CONST_WITH_NON_TYPE, CONST_WITH_TYPE_PARAMETERS, CONST_WITH_UNDEFINED_CONSTRUCTOR, CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS, DUPLICATE_CONSTRUCTOR_DEFAULT, DUPLICATE_CONSTRUCTOR_NAME, DUPLICATE_DEFINITION, DUPLICATE_MEMBER_NAME, DUPLICATE_MEMBER_NAME_INSTANCE_STATIC, DUPLICATE_NAMED_ARGUMENT, EXPORT_INTERNAL_LIBRARY, EXPORT_OF_NON_LIBRARY, EXTENDS_NON_CLASS, EXTENDS_DISALLOWED_CLASS, EXTRA_POSITIONAL_ARGUMENTS, IMPLEMENTS_DISALLOWED_CLASS, FIELD_INITIALIZED_BY_MULTIPLE_INITIALIZERS, FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION, FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER, FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, FINAL_INITIALIZED_MULTIPLE_TIMES, FIELD_INITIALIZER_FACTORY_CONSTRUCTOR, FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR, FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR, GETTER_AND_METHOD_WITH_SAME_NAME, IMPLEMENTS_DYNAMIC, IMPLEMENTS_NON_CLASS, IMPLEMENTS_REPEATED, IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, IMPORT_INTERNAL_LIBRARY, IMPORT_OF_NON_LIBRARY, INCONSISTENT_CASE_EXPRESSION_TYPES, INITIALIZER_FOR_NON_EXISTANT_FIELD, INITIALIZER_FOR_STATIC_FIELD, INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD, INITIALIZING_FORMAL_FOR_STATIC_FIELD, INVALID_CONSTANT, INVALID_CONSTRUCTOR_NAME, INVALID_FACTORY_NAME_NOT_A_CLASS, INVALID_OVERRIDE_DEFAULT_VALUE, INVALID_OVERRIDE_NAMED, INVALID_OVERRIDE_POSITIONAL, INVALID_OVERRIDE_REQUIRED, INVALID_REFERENCE_TO_THIS, INVALID_TYPE_ARGUMENT_FOR_KEY, INVALID_TYPE_ARGUMENT_IN_CONST_LIST, INVALID_TYPE_ARGUMENT_IN_CONST_MAP, INVALID_URI, LABEL_IN_OUTER_SCOPE, LABEL_UNDEFINED, MEMBER_WITH_CLASS_NAME, METHOD_AND_GETTER_WITH_SAME_NAME, MISSING_CONST_IN_LIST_LITERAL, MISSING_CONST_IN_MAP_LITERAL, MIXIN_DECLARES_CONSTRUCTOR, MIXIN_INHERITS_FROM_NOT_OBJECT, MIXIN_OF_NON_CLASS, MIXIN_REFERENCES_SUPER, MIXIN_WITH_NON_CLASS_SUPERCLASS, MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS, MULTIPLE_SUPER_INITIALIZERS, NEW_WITH_INVALID_TYPE_PARAMETERS, NON_CONST_MAP_AS_EXPRESSION_STATEMENT, NON_CONSTANT_CASE_EXPRESSION, NON_CONSTANT_DEFAULT_VALUE, NON_CONSTANT_LIST_ELEMENT, NON_CONSTANT_MAP_KEY, NON_CONSTANT_MAP_VALUE, NON_CONSTANT_VALUE_IN_INITIALIZER, NOT_ENOUGH_REQUIRED_ARGUMENTS, NON_GENERATIVE_CONSTRUCTOR, OBJECT_CANNOT_EXTEND_ANOTHER_CLASS, OPTIONAL_PARAMETER_IN_OPERATOR, PART_OF_NON_PART, PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, PRIVATE_OPTIONAL_PARAMETER, RECURSIVE_COMPILE_TIME_CONSTANT, RECURSIVE_CONSTRUCTOR_REDIRECT, RECURSIVE_FACTORY_REDIRECT, RECURSIVE_FUNCTION_TYPE_ALIAS, RECURSIVE_INTERFACE_INHERITANCE, RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS, RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS, REDIRECT_TO_NON_CONST_CONSTRUCTOR, REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER, RESERVED_WORD_AS_IDENTIFIER, RETHROW_OUTSIDE_CATCH, RETURN_IN_GENERATIVE_CONSTRUCTOR, STATIC_TOP_LEVEL_FUNCTION, STATIC_TOP_LEVEL_VARIABLE, SUPER_IN_INVALID_CONTEXT, SUPER_IN_REDIRECTING_CONSTRUCTOR, SUPER_INITIALIZER_IN_OBJECT, UNDEFINED_CLASS, UNDEFINED_CONSTRUCTOR_IN_INITIALIZER, UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, UNINITIALIZED_FINAL_FIELD, UNDEFINED_NAMED_PARAMETER, URI_DOES_NOT_EXIST, URI_WITH_INTERPOLATION, WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR, WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS, WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER, WRONG_NUMBER_OF_TYPE_ARGUMENTS];
/// The name of this enum constant, as declared in the enum declaration.
final String name;
@@ -1549,7 +1539,7 @@
String toString() => name;
}
/**
- * The enumeration {@code PubSuggestionCode} defines the suggestions used for reporting deviations
+ * The enumeration `PubSuggestionCode` defines the suggestions used for reporting deviations
* from pub best practices. The convention for this class is for the name of the bad practice to
* indicate the problem that caused the suggestion to be generated and for the message to explain
* what is wrong and, when appropriate, how the situation can be corrected.
@@ -1559,7 +1549,7 @@
/**
* It is a bad practice for a source file in a package "lib" directory hierarchy to traverse
* outside that directory hierarchy. For example, a source file in the "lib" directory should not
- * contain a directive such as {@code import '../web/some.dart'} which references a file outside
+ * contain a directive such as `import '../web/some.dart'` which references a file outside
* the lib directory.
*/
static final PubSuggestionCode FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE = new PubSuggestionCode('FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE', 0, "A file in the 'lib' directory hierarchy should not reference a file outside that hierarchy");
@@ -1567,7 +1557,7 @@
/**
* It is a bad practice for a source file ouside a package "lib" directory hierarchy to traverse
* into that directory hierarchy. For example, a source file in the "web" directory should not
- * contain a directive such as {@code import '../lib/some.dart'} which references a file inside
+ * contain a directive such as `import '../lib/some.dart'` which references a file inside
* the lib directory.
*/
static final PubSuggestionCode FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE = new PubSuggestionCode('FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE', 1, "A file outside the 'lib' directory hierarchy should not reference a file inside that hierarchy. Use a package: reference instead.");
@@ -1575,7 +1565,7 @@
/**
* It is a bad practice for a package import to reference anything outside the given package, or
* more generally, it is bad practice for a package import to contain a "..". For example, a
- * source file should not contain a directive such as {@code import 'package:foo/../some.dart'}.
+ * source file should not contain a directive such as `import 'package:foo/../some.dart'`.
*/
static final PubSuggestionCode PACKAGE_IMPORT_CONTAINS_DOT_DOT = new PubSuggestionCode('PACKAGE_IMPORT_CONTAINS_DOT_DOT', 2, "A package import should not contain '..'");
static final List<PubSuggestionCode> values = [FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE, FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE, PACKAGE_IMPORT_CONTAINS_DOT_DOT];
@@ -1606,7 +1596,7 @@
String toString() => name;
}
/**
- * The enumeration {@code StaticWarningCode} defines the error codes used for static warnings. The
+ * The enumeration `StaticWarningCode` defines the error codes used for static warnings. The
* convention for this class is for the name of the error code to indicate the problem that caused
* the error to be generated and for the error message to explain what is wrong and, when
* appropriate, how the problem can be corrected.
@@ -1618,10 +1608,10 @@
* 14.1 Imports: If a name <i>N</i> is referenced by a library <i>L</i> and <i>N</i> is introduced
* into the top level scope <i>L</i> by more than one import then:
* <ol>
- * <li>It is a static warning if <i>N</i> is used as a type annotation.
- * <li>In checked mode, it is a dynamic error if <i>N</i> is used as a type annotation and
+ * * It is a static warning if <i>N</i> is used as a type annotation.
+ * * In checked mode, it is a dynamic error if <i>N</i> is used as a type annotation and
* referenced during a subtype test.
- * <li>Otherwise, it is a compile-time error.
+ * * Otherwise, it is a compile-time error.
* </ol>
* @param ambiguousTypeName the name of the ambiguous type
* @param firstLibraryName the name of the first library that the type is found
@@ -1633,17 +1623,17 @@
* 12.11.1 New: It is a static warning if the static type of <i>a<sub>i</sub>, 1 <= i <= n+
* k</i> may not be assigned to the type of the corresponding formal parameter of the constructor
* <i>T.id</i> (respectively <i>T</i>).
- * <p>
+ *
* 12.11.2 Const: It is a static warning if the static type of <i>a<sub>i</sub>, 1 <= i <=
* n+ k</i> may not be assigned to the type of the corresponding formal parameter of the
* constructor <i>T.id</i> (respectively <i>T</i>).
- * <p>
+ *
* 12.14.2 Binding Actuals to Formals: Let <i>T<sub>i</sub></i> be the static type of
* <i>a<sub>i</sub></i>, let <i>S<sub>i</sub></i> be the type of <i>p<sub>i</sub>, 1 <= i <=
* n+k</i> and let <i>S<sub>q</sub></i> be the type of the named parameter <i>q</i> of <i>f</i>.
* It is a static warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1 <=
* j <= m</i>.
- * <p>
+ *
* 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub>, 1 <= i <= l</i>,
* must have a corresponding named parameter in the set <i>{p<sub>n+1</sub>, …
* p<sub>n+k</sub>}</i> or a static warning occurs. It is a static warning if
@@ -1774,7 +1764,7 @@
* <i>e</i> proceeds as follows: First, the expression <i>e</i> is evaluated to an object
* <i>o</i>. Then, the instance variable <i>v</i> of the object denoted by this is bound to
* <i>o</i>.
- * <p>
+ *
* 12.14.2 Binding Actuals to Formals: Let <i>T<sub>i</sub></i> be the static type of
* <i>a<sub>i</sub></i>, let <i>S<sub>i</sub></i> be the type of <i>p<sub>i</sub>, 1 <= i <=
* n+k</i> and let <i>S<sub>q</sub></i> be the type of the named parameter <i>q</i> of <i>f</i>.
@@ -1813,7 +1803,7 @@
* … m<sub>k</sub></i> with the same name <i>n</i> that would be inherited (because
* identically named members existed in several superinterfaces) then at most one member is
* inherited.
- * <p>
+ *
* If some but not all of the <i>m<sub>i</sub>, 1 <= i <= k</i>, are getters, or if some but
* not all of the <i>m<sub>i</sub></i> are setters, none of the <i>m<sub>i</sub></i> are
* inherited, and a static warning is issued.
@@ -1899,7 +1889,15 @@
* a formal parameter <i>p</i> and the signature of <i>m1</i> specifies a different default value
* for <i>p</i>.
*/
- static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES = new StaticWarningCode('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES', 32, "");
+ static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED = new StaticWarningCode('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED', 32, "Parameters cannot override default values, this method overrides '%s.%s' where '%s' has a different value");
+
+ /**
+ * 7.1 Instance Methods: It is a static warning if an instance method <i>m1</i> overrides an
+ * instance member <i>m2</i>, the signature of <i>m2</i> explicitly specifies a default value for
+ * a formal parameter <i>p</i> and the signature of <i>m1</i> specifies a different default value
+ * for <i>p</i>.
+ */
+ static final StaticWarningCode INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL = new StaticWarningCode('INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL', 33, "Parameters cannot override default values, this method overrides '%s.%s' where this positional parameter has a different value");
/**
* 7.3 Setters: It is a static warning if a setter <i>m1</i> overrides a setter <i>m2</i> and the
@@ -1910,7 +1908,7 @@
* @param className the name of the class where the overridden setter is declared
* @see #INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
*/
- static final StaticWarningCode INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE = new StaticWarningCode('INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE', 33, "The parameter type '%s' is not assignable to '%s' as required by the setter it is overriding from '%s'");
+ static final StaticWarningCode INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE = new StaticWarningCode('INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE', 34, "The parameter type '%s' is not assignable to '%s' as required by the setter it is overriding from '%s'");
/**
* 12.15.4 Super Invocation: A super method invocation <i>i</i> has the form
@@ -1918,27 +1916,27 @@
* x<sub>n+k</sub>: a<sub>n+k</sub>)</i>. If <i>S.m</i> exists, it is a static warning if the type
* <i>F</i> of <i>S.m</i> may not be assigned to a function type.
*/
- static final StaticWarningCode INVOCATION_OF_NON_FUNCTION = new StaticWarningCode('INVOCATION_OF_NON_FUNCTION', 34, "");
+ static final StaticWarningCode INVOCATION_OF_NON_FUNCTION = new StaticWarningCode('INVOCATION_OF_NON_FUNCTION', 35, "");
/**
* 7.3 Setters: It is a static warning if a class has a setter named <i>v=</i> with argument type
* <i>T</i> and a getter named <i>v</i> with return type <i>S</i>, and <i>T</i> may not be
* assigned to <i>S</i>.
*/
- static final StaticWarningCode MISMATCHED_GETTER_AND_SETTER_TYPES = new StaticWarningCode('MISMATCHED_GETTER_AND_SETTER_TYPES', 35, "The parameter type for setter '%s' is %s which is not assignable to its getter (of type %s)");
+ static final StaticWarningCode MISMATCHED_GETTER_AND_SETTER_TYPES = new StaticWarningCode('MISMATCHED_GETTER_AND_SETTER_TYPES', 36, "The parameter type for setter '%s' is %s which is not assignable to its getter (of type %s)");
/**
* 12.11.1 New: It is a static warning if <i>q</i> is a constructor of an abstract class and
* <i>q</i> is not a factory constructor.
*/
- static final StaticWarningCode NEW_WITH_ABSTRACT_CLASS = new StaticWarningCode('NEW_WITH_ABSTRACT_CLASS', 36, "Abstract classes cannot be created with a 'new' expression");
+ static final StaticWarningCode NEW_WITH_ABSTRACT_CLASS = new StaticWarningCode('NEW_WITH_ABSTRACT_CLASS', 37, "Abstract classes cannot be created with a 'new' expression");
/**
* 12.11.1 New: It is a static warning if <i>T</i> is not a class accessible in the current scope,
* optionally followed by type arguments.
* @param name the name of the non-type element
*/
- static final StaticWarningCode NEW_WITH_NON_TYPE = new StaticWarningCode('NEW_WITH_NON_TYPE', 37, "The name '%s' is not a class");
+ static final StaticWarningCode NEW_WITH_NON_TYPE = new StaticWarningCode('NEW_WITH_NON_TYPE', 38, "The name '%s' is not a class");
/**
* 12.11.1 New: If <i>T</i> is a class or parameterized type accessible in the current scope then:
@@ -1949,7 +1947,7 @@
* a<sub>n+1</sub>, … x<sub>n+k</sub>: a<sub>n+kM/sub>)</i> it is a static warning if the
* type <i>T</i> does not declare a constructor with the same name as the declaration of <i>T</i>.
*/
- static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR = new StaticWarningCode('NEW_WITH_UNDEFINED_CONSTRUCTOR', 38, "The class '%s' does not have a constructor '%s'");
+ static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR = new StaticWarningCode('NEW_WITH_UNDEFINED_CONSTRUCTOR', 39, "The class '%s' does not have a constructor '%s'");
/**
* 12.11.1 New: If <i>T</i> is a class or parameterized type accessible in the current scope then:
@@ -1960,12 +1958,25 @@
* a<sub>n+1</sub>, … x<sub>n+k</sub>: a<sub>n+kM/sub>)</i> it is a static warning if the
* type <i>T</i> does not declare a constructor with the same name as the declaration of <i>T</i>.
*/
- static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT = new StaticWarningCode('NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT', 39, "The class '%s' does not have a default constructor");
+ static final StaticWarningCode NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT = new StaticWarningCode('NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT', 40, "The class '%s' does not have a default constructor");
+
+ /**
+ * 7.6.1 Generative Constructors: If no superinitializer is provided, an implicit superinitializer
+ * of the form <b>super</b>() is added at the end of <i>k</i>'s initializer list, unless the
+ * enclosing class is class <i>Object</i>.
+ */
+ static final StaticWarningCode NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT = new StaticWarningCode('NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT', 41, "The class '%s' does not have a default constructor");
+
+ /**
+ * 7.6 Constructors: Iff no constructor is specified for a class <i>C</i>, it implicitly has a
+ * default constructor C() : <b>super<b>() {}, unless <i>C</i> is class <i>Object</i>.
+ */
+ static final StaticWarningCode NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT = new StaticWarningCode('NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT', 42, "The class '%s' does not have a default constructor");
/**
* 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
* abstract method.
- * <p>
+ *
* 7.10 Superinterfaces: It is a static warning if the implicit interface of a non-abstract class
* <i>C</i> includes an instance member <i>m</i> and <i>C</i> does not declare or inherit a
* corresponding instance member <i>m</i>.
@@ -1987,12 +1998,12 @@
* @param name fourth member name
* @param additionalCount the number of additional missing members that aren't listed
*/
- static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS', 40, "Missing inherited members: %s'%s.%s', %s'%s.%s', %s'%s.%s', %s'%s.%s' and %d more");
+ static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS', 43, "Missing inherited members: %s'%s.%s', %s'%s.%s', %s'%s.%s', %s'%s.%s' and %d more");
/**
* 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
* abstract method.
- * <p>
+ *
* 7.10 Superinterfaces: It is a static warning if the implicit interface of a non-abstract class
* <i>C</i> includes an instance member <i>m</i> and <i>C</i> does not declare or inherit a
* corresponding instance member <i>m</i>.
@@ -2013,12 +2024,12 @@
* @param enclosingClass enclosing class of the fourth missing member
* @param name fourth member name
*/
- static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR', 41, "Missing inherited members: %s'%s.%s', %s'%s.%s', %s'%s.%s' and %s'%s.%s'");
+ static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR', 44, "Missing inherited members: %s'%s.%s', %s'%s.%s', %s'%s.%s' and %s'%s.%s'");
/**
* 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
* abstract method.
- * <p>
+ *
* 7.10 Superinterfaces: It is a static warning if the implicit interface of a non-abstract class
* <i>C</i> includes an instance member <i>m</i> and <i>C</i> does not declare or inherit a
* corresponding instance member <i>m</i>.
@@ -2026,12 +2037,12 @@
* @param enclosingClass enclosing class of the missing member
* @param name member name
*/
- static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE', 42, "Missing inherited member %s'%s.%s'");
+ static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE', 45, "Missing inherited member %s'%s.%s'");
/**
* 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
* abstract method.
- * <p>
+ *
* 7.10 Superinterfaces: It is a static warning if the implicit interface of a non-abstract class
* <i>C</i> includes an instance member <i>m</i> and <i>C</i> does not declare or inherit a
* corresponding instance member <i>m</i>.
@@ -2048,12 +2059,12 @@
* @param enclosingClass enclosing class of the third missing member
* @param name third member name
*/
- static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE', 43, "Missing inherited members: %s'%s.%s', %s'%s.%s' and %s'%s.%s'");
+ static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE', 46, "Missing inherited members: %s'%s.%s', %s'%s.%s' and %s'%s.%s'");
/**
* 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract class inherits an
* abstract method.
- * <p>
+ *
* 7.10 Superinterfaces: It is a static warning if the implicit interface of a non-abstract class
* <i>C</i> includes an instance member <i>m</i> and <i>C</i> does not declare or inherit a
* corresponding instance member <i>m</i>.
@@ -2066,7 +2077,7 @@
* @param enclosingClass enclosing class of the second missing member
* @param name second member name
*/
- static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO', 44, "Missing inherited members: %s'%s.%s' and %s'%s.%s'");
+ static final StaticWarningCode NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO = new StaticWarningCode('NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO', 47, "Missing inherited members: %s'%s.%s' and %s'%s.%s'");
/**
* 13.11 Try: An on-catch clause of the form <i>on T catch (p<sub>1</sub>, p<sub>2</sub>) s</i> or
@@ -2075,38 +2086,38 @@
* catch clause.
* @param name the name of the non-type element
*/
- static final StaticWarningCode NON_TYPE_IN_CATCH_CLAUSE = new StaticWarningCode('NON_TYPE_IN_CATCH_CLAUSE', 45, "The name '%s' is not a type and cannot be used in an on-catch clause");
+ static final StaticWarningCode NON_TYPE_IN_CATCH_CLAUSE = new StaticWarningCode('NON_TYPE_IN_CATCH_CLAUSE', 48, "The name '%s' is not a type and cannot be used in an on-catch clause");
/**
* 7.1.1 Operators: It is a static warning if the return type of the user-declared operator \[\]= is
* explicitly declared and not void.
*/
- static final StaticWarningCode NON_VOID_RETURN_FOR_OPERATOR = new StaticWarningCode('NON_VOID_RETURN_FOR_OPERATOR', 46, "The return type of the operator []= must be 'void'");
+ static final StaticWarningCode NON_VOID_RETURN_FOR_OPERATOR = new StaticWarningCode('NON_VOID_RETURN_FOR_OPERATOR', 49, "The return type of the operator []= must be 'void'");
/**
* 7.3 Setters: It is a static warning if a setter declares a return type other than void.
*/
- static final StaticWarningCode NON_VOID_RETURN_FOR_SETTER = new StaticWarningCode('NON_VOID_RETURN_FOR_SETTER', 47, "The return type of the setter must be 'void'");
+ static final StaticWarningCode NON_VOID_RETURN_FOR_SETTER = new StaticWarningCode('NON_VOID_RETURN_FOR_SETTER', 50, "The return type of the setter must be 'void'");
/**
- * 15.1 Static Types: A type <i>T</i> is malformed iff: <li><i>T</i> has the form <i>id</i> or the
+ * 15.1 Static Types: A type <i>T</i> is malformed iff: * <i>T</i> has the form <i>id</i> or the
* form <i>prefix.id</i>, and in the enclosing lexical scope, the name <i>id</i> (respectively
- * <i>prefix.id</i>) does not denote a type.</li> <li><i>T</i> denotes a type variable in the
- * enclosing lexical scope, but occurs in the signature or body of a static member.</li> <li>
+ * <i>prefix.id</i>) does not denote a type. * <i>T</i> denotes a type variable in the
+ * enclosing lexical scope, but occurs in the signature or body of a static member. *
* <i>T</i> is a parameterized type of the form <i>G<S<sub>1</sub>, .., S<sub>n</sub>></i>,
- * and <i>G</i> is malformed.</li></ul>
- * <p>
+ * and <i>G</i> is malformed.
+ *
* Any use of a malformed type gives rise to a static warning.
* @param nonTypeName the name that is not a type
*/
- static final StaticWarningCode NOT_A_TYPE = new StaticWarningCode('NOT_A_TYPE', 48, "%s is not a type");
+ static final StaticWarningCode NOT_A_TYPE = new StaticWarningCode('NOT_A_TYPE', 51, "%s is not a type");
/**
* 12.14.2 Binding Actuals to Formals: It is a static warning if <i>m < h</i> or if <i>m > n</i>.
* @param requiredCount the expected number of required arguments
* @param argumentCount the actual number of positional arguments given
*/
- static final StaticWarningCode NOT_ENOUGH_REQUIRED_ARGUMENTS = new StaticWarningCode('NOT_ENOUGH_REQUIRED_ARGUMENTS', 49, "%d required argument(s) expected, but %d found");
+ static final StaticWarningCode NOT_ENOUGH_REQUIRED_ARGUMENTS = new StaticWarningCode('NOT_ENOUGH_REQUIRED_ARGUMENTS', 52, "%d required argument(s) expected, but %d found");
/**
* 14.3 Parts: It is a static warning if the referenced part declaration <i>p</i> names a library
@@ -2114,7 +2125,7 @@
* @param expectedLibraryName the name of expected library name
* @param actualLibraryName the non-matching actual library name from the "part of" declaration
*/
- static final StaticWarningCode PART_OF_DIFFERENT_LIBRARY = new StaticWarningCode('PART_OF_DIFFERENT_LIBRARY', 50, "Expected this library to be part of '%s', not '%s'");
+ static final StaticWarningCode PART_OF_DIFFERENT_LIBRARY = new StaticWarningCode('PART_OF_DIFFERENT_LIBRARY', 53, "Expected this library to be part of '%s', not '%s'");
/**
* 7.6.2 Factories: It is a static warning if the function type of <i>k'</i> is not a subtype of
@@ -2122,7 +2133,7 @@
* @param redirectedName the name of the redirected constructor
* @param redirectingName the name of the redirecting constructor
*/
- static final StaticWarningCode REDIRECT_TO_INVALID_FUNCTION_TYPE = new StaticWarningCode('REDIRECT_TO_INVALID_FUNCTION_TYPE', 51, "The redirected constructor '%s' has incompatible parameters with '%s'");
+ static final StaticWarningCode REDIRECT_TO_INVALID_FUNCTION_TYPE = new StaticWarningCode('REDIRECT_TO_INVALID_FUNCTION_TYPE', 54, "The redirected constructor '%s' has incompatible parameters with '%s'");
/**
* 7.6.2 Factories: It is a static warning if the function type of <i>k'</i> is not a subtype of
@@ -2130,62 +2141,62 @@
* @param redirectedName the name of the redirected constructor return type
* @param redirectingName the name of the redirecting constructor return type
*/
- static final StaticWarningCode REDIRECT_TO_INVALID_RETURN_TYPE = new StaticWarningCode('REDIRECT_TO_INVALID_RETURN_TYPE', 52, "The return type '%s' of the redirected constructor is not a subclass of '%s'");
+ static final StaticWarningCode REDIRECT_TO_INVALID_RETURN_TYPE = new StaticWarningCode('REDIRECT_TO_INVALID_RETURN_TYPE', 55, "The return type '%s' of the redirected constructor is not a subclass of '%s'");
/**
* 7.6.2 Factories: It is a static warning if type does not denote a class accessible in the
* current scope; if type does denote such a class <i>C</i> it is a static warning if the
* referenced constructor (be it <i>type</i> or <i>type.id</i>) is not a constructor of <i>C</i>.
*/
- static final StaticWarningCode REDIRECT_TO_MISSING_CONSTRUCTOR = new StaticWarningCode('REDIRECT_TO_MISSING_CONSTRUCTOR', 53, "The constructor '%s' could not be found in '%s'");
+ static final StaticWarningCode REDIRECT_TO_MISSING_CONSTRUCTOR = new StaticWarningCode('REDIRECT_TO_MISSING_CONSTRUCTOR', 56, "The constructor '%s' could not be found in '%s'");
/**
* 7.6.2 Factories: It is a static warning if type does not denote a class accessible in the
* current scope; if type does denote such a class <i>C</i> it is a static warning if the
* referenced constructor (be it <i>type</i> or <i>type.id</i>) is not a constructor of <i>C</i>.
*/
- static final StaticWarningCode REDIRECT_TO_NON_CLASS = new StaticWarningCode('REDIRECT_TO_NON_CLASS', 54, "The name '%s' is not a type and cannot be used in a redirected constructor");
+ static final StaticWarningCode REDIRECT_TO_NON_CLASS = new StaticWarningCode('REDIRECT_TO_NON_CLASS', 57, "The name '%s' is not a type and cannot be used in a redirected constructor");
/**
* 13.11 Return: Let <i>f</i> be the function immediately enclosing a return statement of the form
* <i>return;</i> It is a static warning if both of the following conditions hold:
* <ol>
- * <li><i>f</i> is not a generative constructor.
- * <li>The return type of <i>f</i> may not be assigned to void.
+ * * <i>f</i> is not a generative constructor.
+ * * The return type of <i>f</i> may not be assigned to void.
* </ol>
*/
- static final StaticWarningCode RETURN_WITHOUT_VALUE = new StaticWarningCode('RETURN_WITHOUT_VALUE', 55, "Missing return value after 'return'");
+ static final StaticWarningCode RETURN_WITHOUT_VALUE = new StaticWarningCode('RETURN_WITHOUT_VALUE', 58, "Missing return value after 'return'");
/**
* 12.15.3 Static Invocation: It is a static warning if <i>C</i> does not declare a static method
* or getter <i>m</i>.
* @param memberName the name of the instance member
*/
- static final StaticWarningCode STATIC_ACCESS_TO_INSTANCE_MEMBER = new StaticWarningCode('STATIC_ACCESS_TO_INSTANCE_MEMBER', 56, "Instance member '%s' cannot be accessed using static access");
+ static final StaticWarningCode STATIC_ACCESS_TO_INSTANCE_MEMBER = new StaticWarningCode('STATIC_ACCESS_TO_INSTANCE_MEMBER', 59, "Instance member '%s' cannot be accessed using static access");
/**
* 13.9 Switch: It is a static warning if the type of <i>e</i> may not be assigned to the type of
* <i>e<sub>k</sub></i>.
*/
- static final StaticWarningCode SWITCH_EXPRESSION_NOT_ASSIGNABLE = new StaticWarningCode('SWITCH_EXPRESSION_NOT_ASSIGNABLE', 57, "Type '%s' of the switch expression is not assignable to the type '%s' of case expressions");
+ static final StaticWarningCode SWITCH_EXPRESSION_NOT_ASSIGNABLE = new StaticWarningCode('SWITCH_EXPRESSION_NOT_ASSIGNABLE', 60, "Type '%s' of the switch expression is not assignable to the type '%s' of case expressions");
/**
* 12.31 Type Test: It is a static warning if <i>T</i> does not denote a type available in the
* current lexical scope.
*/
- static final StaticWarningCode TYPE_TEST_NON_TYPE = new StaticWarningCode('TYPE_TEST_NON_TYPE', 58, "The name '%s' is not a type and cannot be used in an 'is' expression");
+ static final StaticWarningCode TYPE_TEST_NON_TYPE = new StaticWarningCode('TYPE_TEST_NON_TYPE', 61, "The name '%s' is not a type and cannot be used in an 'is' expression");
/**
- * 15.1 Static Types: A type <i>T</i> is malformed iff: <li><i>T</i> has the form <i>id</i> or the
+ * 15.1 Static Types: A type <i>T</i> is malformed iff: * <i>T</i> has the form <i>id</i> or the
* form <i>prefix.id</i>, and in the enclosing lexical scope, the name <i>id</i> (respectively
- * <i>prefix.id</i>) does not denote a type.</li> <li><i>T</i> denotes a type variable in the
- * enclosing lexical scope, but occurs in the signature or body of a static member.</li> <li>
+ * <i>prefix.id</i>) does not denote a type. * <i>T</i> denotes a type variable in the
+ * enclosing lexical scope, but occurs in the signature or body of a static member. *
* <i>T</i> is a parameterized type of the form <i>G<S<sub>1</sub>, .., S<sub>n</sub>></i>,
- * and <i>G</i> is malformed.</li></ul>
- * <p>
+ * and <i>G</i> is malformed.
+ *
* Any use of a malformed type gives rise to a static warning.
*/
- static final StaticWarningCode TYPE_VARIABLE_IN_STATIC_SCOPE = new StaticWarningCode('TYPE_VARIABLE_IN_STATIC_SCOPE', 59, "");
+ static final StaticWarningCode TYPE_VARIABLE_IN_STATIC_SCOPE = new StaticWarningCode('TYPE_VARIABLE_IN_STATIC_SCOPE', 62, "");
/**
* 12.15.3 Static Invocation: A static method invocation <i>i</i> has the form
@@ -2193,12 +2204,12 @@
* x<sub>n+k</sub>: a<sub>n+k</sub>)</i>. It is a static warning if <i>C</i> does not denote a
* class in the current scope.
*/
- static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode('UNDEFINED_CLASS', 60, "Undefined class '%s'");
+ static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode('UNDEFINED_CLASS', 63, "Undefined class '%s'");
/**
- * Same as {@link #UNDEFINED_CLASS}, but to catch using "boolean" instead of "bool".
+ * Same as [UNDEFINED_CLASS], but to catch using "boolean" instead of "bool".
*/
- static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode('UNDEFINED_CLASS_BOOLEAN', 61, "Undefined class 'boolean'; did you mean 'bool'?");
+ static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode('UNDEFINED_CLASS_BOOLEAN', 64, "Undefined class 'boolean'; did you mean 'bool'?");
/**
* 12.17 Getter Invocation: It is a static warning if there is no class <i>C</i> in the enclosing
@@ -2207,7 +2218,7 @@
* @param getterName the name of the getter
* @param enclosingType the name of the enclosing type where the getter is being looked for
*/
- static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode('UNDEFINED_GETTER', 62, "There is no such getter '%s' in '%s'");
+ static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode('UNDEFINED_GETTER', 65, "There is no such getter '%s' in '%s'");
/**
* 12.30 Identifier Reference: It is as static warning if an identifier expression of the form
@@ -2215,7 +2226,7 @@
* setter) or variable initializer and there is no declaration <i>d</i> with name <i>id</i> in the
* lexical scope enclosing the expression.
*/
- static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode('UNDEFINED_IDENTIFIER', 63, "Undefined name '%s'");
+ static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode('UNDEFINED_IDENTIFIER', 66, "Undefined name '%s'");
/**
* 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
@@ -2223,21 +2234,21 @@
* <i>p<sub>n+k</sub></i>} or a static warning occurs.
* @param name the name of the requested named parameter
*/
- static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode('UNDEFINED_NAMED_PARAMETER', 64, "The named parameter '%s' is not defined");
+ static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode('UNDEFINED_NAMED_PARAMETER', 67, "The named parameter '%s' is not defined");
/**
* 12.18 Assignment: It is as static warning if an assignment of the form <i>v = e</i> occurs
* inside a top level or static function (be it function, method, getter, or setter) or variable
* initializer and there is no declaration <i>d</i> with name <i>v=</i> in the lexical scope
* enclosing the assignment.
- * <p>
+ *
* 12.18 Assignment: It is a static warning if there is no class <i>C</i> in the enclosing lexical
* scope of the assignment, or if <i>C</i> does not declare, implicitly or explicitly, a setter
* <i>v=</i>.
* @param setterName the name of the getter
* @param enclosingType the name of the enclosing type where the setter is being looked for
*/
- static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode('UNDEFINED_SETTER', 65, "There is no such setter '%s' in '%s'");
+ static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode('UNDEFINED_SETTER', 68, "There is no such setter '%s' in '%s'");
/**
* 12.15.3 Static Invocation: It is a static warning if <i>C</i> does not declare a static method
@@ -2245,8 +2256,8 @@
* @param methodName the name of the method
* @param enclosingType the name of the enclosing type where the method is being looked for
*/
- static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode('UNDEFINED_STATIC_METHOD_OR_GETTER', 66, "There is no such static method '%s' in '%s'");
- static final List<StaticWarningCode> values = [AMBIGUOUS_IMPORT, ARGUMENT_TYPE_NOT_ASSIGNABLE, ASSIGNMENT_TO_FINAL, CASE_BLOCK_NOT_TERMINATED, CAST_TO_NON_TYPE, COMMENT_REFERENCE_CONSTRUCTOR_NOT_VISIBLE, COMMENT_REFERENCE_IDENTIFIER_NOT_VISIBLE, COMMENT_REFERENCE_UNDECLARED_CONSTRUCTOR, COMMENT_REFERENCE_UNDECLARED_IDENTIFIER, COMMENT_REFERENCE_URI_NOT_LIBRARY, CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER, CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER, CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER, CONST_WITH_ABSTRACT_CLASS, EQUAL_KEYS_IN_MAP, EXPORT_DUPLICATED_LIBRARY_NAME, EXTRA_POSITIONAL_ARGUMENTS, FIELD_INITIALIZER_NOT_ASSIGNABLE, FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, FINAL_NOT_INITIALIZED, IMPORT_DUPLICATED_LIBRARY_NAME, INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD, INCORRECT_NUMBER_OF_ARGUMENTS, INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, INVALID_FACTORY_NAME, INVALID_GETTER_OVERRIDE_RETURN_TYPE, INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE, INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE, INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE, INVALID_METHOD_OVERRIDE_RETURN_TYPE, INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES, INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE, INVOCATION_OF_NON_FUNCTION, MISMATCHED_GETTER_AND_SETTER_TYPES, NEW_WITH_ABSTRACT_CLASS, NEW_WITH_NON_TYPE, NEW_WITH_UNDEFINED_CONSTRUCTOR, NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, NON_TYPE_IN_CATCH_CLAUSE, NON_VOID_RETURN_FOR_OPERATOR, NON_VOID_RETURN_FOR_SETTER, NOT_A_TYPE, NOT_ENOUGH_REQUIRED_ARGUMENTS, PART_OF_DIFFERENT_LIBRARY, REDIRECT_TO_INVALID_FUNCTION_TYPE, REDIRECT_TO_INVALID_RETURN_TYPE, REDIRECT_TO_MISSING_CONSTRUCTOR, REDIRECT_TO_NON_CLASS, RETURN_WITHOUT_VALUE, STATIC_ACCESS_TO_INSTANCE_MEMBER, SWITCH_EXPRESSION_NOT_ASSIGNABLE, TYPE_TEST_NON_TYPE, TYPE_VARIABLE_IN_STATIC_SCOPE, UNDEFINED_CLASS, UNDEFINED_CLASS_BOOLEAN, UNDEFINED_GETTER, UNDEFINED_IDENTIFIER, UNDEFINED_NAMED_PARAMETER, UNDEFINED_SETTER, UNDEFINED_STATIC_METHOD_OR_GETTER];
+ static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode('UNDEFINED_STATIC_METHOD_OR_GETTER', 69, "There is no such static method '%s' in '%s'");
+ static final List<StaticWarningCode> values = [AMBIGUOUS_IMPORT, ARGUMENT_TYPE_NOT_ASSIGNABLE, ASSIGNMENT_TO_FINAL, CASE_BLOCK_NOT_TERMINATED, CAST_TO_NON_TYPE, COMMENT_REFERENCE_CONSTRUCTOR_NOT_VISIBLE, COMMENT_REFERENCE_IDENTIFIER_NOT_VISIBLE, COMMENT_REFERENCE_UNDECLARED_CONSTRUCTOR, COMMENT_REFERENCE_UNDECLARED_IDENTIFIER, COMMENT_REFERENCE_URI_NOT_LIBRARY, CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER, CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER, CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER, CONST_WITH_ABSTRACT_CLASS, EQUAL_KEYS_IN_MAP, EXPORT_DUPLICATED_LIBRARY_NAME, EXTRA_POSITIONAL_ARGUMENTS, FIELD_INITIALIZER_NOT_ASSIGNABLE, FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, FINAL_NOT_INITIALIZED, IMPORT_DUPLICATED_LIBRARY_NAME, INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD, INCORRECT_NUMBER_OF_ARGUMENTS, INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, INVALID_FACTORY_NAME, INVALID_GETTER_OVERRIDE_RETURN_TYPE, INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE, INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE, INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE, INVALID_METHOD_OVERRIDE_RETURN_TYPE, INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED, INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL, INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE, INVOCATION_OF_NON_FUNCTION, MISMATCHED_GETTER_AND_SETTER_TYPES, NEW_WITH_ABSTRACT_CLASS, NEW_WITH_NON_TYPE, NEW_WITH_UNDEFINED_CONSTRUCTOR, NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE, NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, NON_TYPE_IN_CATCH_CLAUSE, NON_VOID_RETURN_FOR_OPERATOR, NON_VOID_RETURN_FOR_SETTER, NOT_A_TYPE, NOT_ENOUGH_REQUIRED_ARGUMENTS, PART_OF_DIFFERENT_LIBRARY, REDIRECT_TO_INVALID_FUNCTION_TYPE, REDIRECT_TO_INVALID_RETURN_TYPE, REDIRECT_TO_MISSING_CONSTRUCTOR, REDIRECT_TO_NON_CLASS, RETURN_WITHOUT_VALUE, STATIC_ACCESS_TO_INSTANCE_MEMBER, SWITCH_EXPRESSION_NOT_ASSIGNABLE, TYPE_TEST_NON_TYPE, TYPE_VARIABLE_IN_STATIC_SCOPE, UNDEFINED_CLASS, UNDEFINED_CLASS_BOOLEAN, UNDEFINED_GETTER, UNDEFINED_IDENTIFIER, UNDEFINED_NAMED_PARAMETER, UNDEFINED_SETTER, UNDEFINED_STATIC_METHOD_OR_GETTER];
/// The name of this enum constant, as declared in the enum declaration.
final String name;
@@ -2274,7 +2285,7 @@
String toString() => name;
}
/**
- * The interface {@code AnalysisErrorListener} defines the behavior of objects that listen for{@link AnalysisError analysis errors} being produced by the analysis engine.
+ * The interface `AnalysisErrorListener` defines the behavior of objects that listen for[AnalysisError analysis errors] being produced by the analysis engine.
* @coverage dart.engine.error
*/
abstract class AnalysisErrorListener {
@@ -2286,7 +2297,7 @@
/**
* This method is invoked when an error has been found by the analysis engine.
- * @param error the error that was just found (not {@code null})
+ * @param error the error that was just found (not `null`)
*/
void onError(AnalysisError error);
}
@@ -2295,7 +2306,7 @@
}
}
/**
- * The enumeration {@code HtmlWarningCode} defines the error codes used for warnings in HTML files.
+ * The enumeration `HtmlWarningCode` defines the error codes used for warnings in HTML files.
* The convention for this class is for the name of the error code to indicate the problem that
* caused the error to be generated and for the error message to explain what is wrong and, when
* appropriate, how the problem can be corrected.
@@ -2344,7 +2355,7 @@
String toString() => name;
}
/**
- * The enumeration {@code StaticTypeWarningCode} defines the error codes used for static type
+ * The enumeration `StaticTypeWarningCode` defines the error codes used for static type
* warnings. The convention for this class is for the name of the error code to indicate the problem
* that caused the error to be generated and for the error message to explain what is wrong and,
* when appropriate, how the problem can be corrected.
@@ -2364,19 +2375,19 @@
* … m<sub>k</sub></i> with the same name <i>n</i> that would be inherited (because
* identically named members existed in several superinterfaces) then at most one member is
* inherited.
- * <p>
+ *
* If the static types <i>T<sub>1</sub>, …, T<sub>k</sub></i> of the members
* <i>m<sub>1</sub>, …, m<sub>k</sub></i> are not identical, then there must be a member
* <i>m<sub>x</sub></i> such that <i>T<sub>x</sub> < T<sub>i</sub>, 1 <= x <= k</i> for
* all <i>i, 1 <= i < k</i>, or a static type warning occurs. The member that is inherited
* is <i>m<sub>x</sub></i>, if it exists; otherwise:
* <ol>
- * <li>If all of <i>m<sub>1</sub>, … m<sub>k</sub></i> have the same number <i>r</i> of
+ * * If all of <i>m<sub>1</sub>, … m<sub>k</sub></i> have the same number <i>r</i> of
* required parameters and the same set of named parameters <i>s</i>, then let <i>h = max(
* numberOfOptionalPositionals( m<sub>i</sub> ) ), 1 <= i <= k</i>. <i>I</i> has a method
* named <i>n</i>, with <i>r</i> required parameters of type dynamic, <i>h</i> optional positional
* parameters of type dynamic, named parameters <i>s</i> of type dynamic and return type dynamic.
- * <li>Otherwise none of the members <i>m<sub>1</sub>, …, m<sub>k</sub></i> is inherited.
+ * * Otherwise none of the members <i>m<sub>1</sub>, …, m<sub>k</sub></i> is inherited.
* </ol>
*/
static final StaticTypeWarningCode INCONSISTENT_METHOD_INHERITANCE = new StaticTypeWarningCode('INCONSISTENT_METHOD_INHERITANCE', 1, "'%s' is inherited by at least two interfaces inconsistently");
@@ -2385,11 +2396,11 @@
* 12.18 Assignment: It is a static type warning if the static type of <i>e</i> may not be
* assigned to the static type of <i>v</i>. The static type of the expression <i>v = e</i> is the
* static type of <i>e</i>.
- * <p>
+ *
* 12.18 Assignment: It is a static type warning if the static type of <i>e</i> may not be
* assigned to the static type of <i>C.v</i>. The static type of the expression <i>C.v = e</i> is
* the static type of <i>e</i>.
- * <p>
+ *
* 12.18 Assignment: Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static type
* warning if the static type of <i>e<sub>2</sub></i> may not be assigned to <i>T</i>.
* @param rhsTypeName the name of the right hand side type
@@ -2401,19 +2412,19 @@
* 12.14.4 Function Expression Invocation: A function expression invocation <i>i</i> has the form
* <i>e<sub>f</sub>(a<sub>1</sub>, … a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
* …, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>, where <i>e<sub>f</sub></i> is an expression.
- * <p>
+ *
* It is a static type warning if the static type <i>F</i> of <i>e<sub>f</sub></i> may not be
* assigned to a function type.
- * <p>
+ *
* 12.15.1 Ordinary Invocation: An ordinary method invocation <i>i</i> has the form
* <i>o.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>, …
* x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
- * <p>
+ *
* Let <i>T</i> be the static type of <i>o</i>. It is a static type warning if <i>T</i> does not
* have an accessible instance member named <i>m</i>. If <i>T.m</i> exists, it is a static warning
* if the type <i>F</i> of <i>T.m</i> may not be assigned to a function type. If <i>T.m</i> does
* not exist, or if <i>F</i> is not a function type, the static type of <i>i</i> is dynamic.
- * <p>
+ *
* 12.15.3 Static Invocation: It is a static type warning if the type <i>F</i> of <i>C.m</i> may
* not be assigned to a function type.
* @param nonFunctionIdentifier the name of the identifier that is not a function type
@@ -2423,12 +2434,12 @@
/**
* 12.19 Conditional: It is a static type warning if the type of <i>e<sub>1</sub></i> may not be
* assigned to bool.
- * <p>
+ *
* 13.5 If: It is a static type warning if the type of the expression <i>b</i> may not be assigned
* to bool.
- * <p>
+ *
* 13.7 While: It is a static type warning if the type of <i>e</i> may not be assigned to bool.
- * <p>
+ *
* 13.8 Do: It is a static type warning if the type of <i>e</i> cannot be assigned to bool.
*/
static final StaticTypeWarningCode NON_BOOL_CONDITION = new StaticTypeWarningCode('NON_BOOL_CONDITION', 4, "Conditions must have a static type of 'bool'");
@@ -2473,7 +2484,7 @@
/**
* 10 Generics: It is a static type warning if a type parameter is a supertype of its upper bound.
- * <p>
+ *
* 15.8 Parameterized Types: If <i>S</i> is the static type of a member <i>m</i> of <i>G</i>, then
* the static type of the member <i>m</i> of <i>G<A<sub>1</sub>, … A<sub>n</sub>></i>
* is <i>\[A<sub>1</sub>, …, A<sub>n</sub>/T<sub>1</sub>, …, T<sub>n</sub>\]S</i>
@@ -2485,7 +2496,7 @@
static final StaticTypeWarningCode TYPE_ARGUMENT_VIOLATES_BOUNDS = new StaticTypeWarningCode('TYPE_ARGUMENT_VIOLATES_BOUNDS', 10, "");
/**
- * Specification reference needed. This is equivalent to {@link #UNDEFINED_METHOD}, but for
+ * Specification reference needed. This is equivalent to [UNDEFINED_METHOD], but for
* top-level functions.
* @param methodName the name of the method that is undefined
*/
@@ -2512,11 +2523,11 @@
* <i>e<sub>1</sub></i>\[<i>e<sub>2</sub></i>\] = <i>e<sub>3</sub></i> is equivalent to the
* evaluation of the expression (a, i, e){a.\[\]=(i, e); return e;} (<i>e<sub>1</sub></i>,
* <i>e<sub>2</sub></i>, <i>e<sub>2</sub></i>).
- * <p>
+ *
* 12.29 Assignable Expressions: An assignable expression of the form
* <i>e<sub>1</sub></i>\[<i>e<sub>2</sub></i>\] is evaluated as a method invocation of the operator
* method \[\] on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.
- * <p>
+ *
* 12.15.1 Ordinary Invocation: Let <i>T</i> be the static type of <i>o</i>. It is a static type
* warning if <i>T</i> does not have an accessible instance member named <i>m</i>.
* @param operator the name of the operator
diff --git a/pkg/analyzer_experimental/lib/src/generated/html.dart b/pkg/analyzer_experimental/lib/src/generated/html.dart
index 02ca349..c667f7b 100644
--- a/pkg/analyzer_experimental/lib/src/generated/html.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/html.dart
@@ -10,7 +10,7 @@
import 'element.dart' show HtmlElementImpl;
import 'engine.dart' show AnalysisEngine;
/**
- * Instances of the class {@code Token} represent a token that was scanned from the input. Each
+ * Instances of the class `Token` represent a token that was scanned from the input. Each
* token knows which token follows it, acting as the head of a linked list of tokens.
* @coverage dart.engine.html
*/
@@ -43,7 +43,7 @@
/**
* Initialize a newly created token.
- * @param type the token type (not {@code null})
+ * @param type the token type (not `null`)
* @param offset the offset from the beginning of the file to the first character in the token
*/
Token.con1(TokenType type, int offset) {
@@ -55,9 +55,9 @@
/**
* Initialize a newly created token.
- * @param type the token type (not {@code null})
+ * @param type the token type (not `null`)
* @param offset the offset from the beginning of the file to the first character in the token
- * @param value the lexeme represented by this token (not {@code null})
+ * @param value the lexeme represented by this token (not `null`)
*/
Token.con2(TokenType type2, int offset2, String value2) {
_jtd_constructor_156_impl(type2, offset2, value2);
@@ -84,7 +84,7 @@
/**
* Return the lexeme that represents this token.
- * @return the lexeme (not {@code null})
+ * @return the lexeme (not `null`)
*/
String get lexeme => _value;
@@ -108,17 +108,17 @@
/**
* Answer the token type for the receiver.
- * @return the token type (not {@code null})
+ * @return the token type (not `null`)
*/
TokenType get type => _type;
/**
- * Return {@code true} if this token is a synthetic token. A synthetic token is a token that was
+ * Return `true` if this token is a synthetic token. A synthetic token is a token that was
* introduced by the parser in order to recover from an error in the code. Synthetic tokens always
- * have a length of zero ({@code 0}).
- * @return {@code true} if this token is a synthetic token
+ * have a length of zero (`0`).
+ * @return `true` if this token is a synthetic token
*/
- bool isSynthetic() => length == 0;
+ bool get isSynthetic => length == 0;
/**
* Set the next token in the token stream to the given token. This has the side-effect of setting
@@ -142,13 +142,13 @@
}
}
/**
- * Instances of {@code HtmlParseResult} hold the result of parsing an HTML file.
+ * Instances of `HtmlParseResult` hold the result of parsing an HTML file.
* @coverage dart.engine.html
*/
class HtmlParseResult extends HtmlScanResult {
/**
- * The unit containing the parsed information (not {@code null}).
+ * The unit containing the parsed information (not `null`).
*/
HtmlUnit _unit;
HtmlParseResult(int modificationTime, Token token, List<int> lineStarts, HtmlUnit unit) : super(modificationTime, token, lineStarts) {
@@ -157,15 +157,15 @@
/**
* Answer the unit generated by parsing the source
- * @return the unit (not {@code null})
+ * @return the unit (not `null`)
*/
HtmlUnit get htmlUnit => _unit;
}
/**
- * Instances of the class {@code RecursiveXmlVisitor} implement an XML visitor that will recursively
+ * Instances of the class `RecursiveXmlVisitor` implement an XML visitor that will recursively
* visit all of the nodes in an XML structure. For example, using an instance of this class to visit
- * a {@link XmlTagNode} will also cause all of the contained {@link XmlAttributeNode}s and{@link XmlTagNode}s to be visited.
- * <p>
+ * a [XmlTagNode] will also cause all of the contained [XmlAttributeNode]s and[XmlTagNode]s to be visited.
+ *
* Subclasses that override a visit method must either invoke the overridden visit method or must
* explicitly ask the visited node to visit its children. Failure to do so will cause the children
* of the visited node to not be visited.
@@ -186,13 +186,13 @@
}
}
/**
- * The abstract class {@code XmlNode} defines behavior common to all XML/HTML nodes.
+ * The abstract class `XmlNode` defines behavior common to all XML/HTML nodes.
* @coverage dart.engine.html
*/
abstract class XmlNode {
/**
- * The parent of the node, or {@code null} if the node is the root of an AST structure.
+ * The parent of the node, or `null` if the node is the root of an AST structure.
*/
XmlNode _parent;
@@ -205,13 +205,13 @@
/**
* Return the first token included in this node's source range.
- * @return the first token or {@code null} if none
+ * @return the first token or `null` if none
*/
Token get beginToken;
/**
* Return the offset of the character immediately following the last character of this node's
- * source range. This is equivalent to {@code node.getOffset() + node.getLength()}. For an html
+ * source range. This is equivalent to `node.getOffset() + node.getLength()`. For an html
* unit this will be equal to the length of the unit's source.
* @return the offset of the character just past the node's source range
*/
@@ -219,7 +219,7 @@
/**
* Return the last token included in this node's source range.
- * @return the last token or {@code null} if none
+ * @return the last token or `null` if none
*/
Token get endToken;
@@ -251,11 +251,11 @@
}
/**
- * Return this node's parent node, or {@code null} if this node is the root of an AST structure.
- * <p>
+ * Return this node's parent node, or `null` if this node is the root of an AST structure.
+ *
* Note that the relationship between an AST node and its parent node may change over the lifetime
* of a node.
- * @return the parent of this node, or {@code null} if none
+ * @return the parent of this node, or `null` if none
*/
XmlNode get parent => _parent;
String toString() {
@@ -353,7 +353,7 @@
}
}
/**
- * Instances of the class {@code SimpleXmlVisitor} implement an AST visitor that will do nothing
+ * Instances of the class `SimpleXmlVisitor` implement an AST visitor that will do nothing
* when visiting an AST node. It is intended to be a superclass for classes that use the visitor
* pattern primarily as a dispatch mechanism (and hence don't need to recursively visit a whole
* structure) and that only need to visit a small number of node types.
@@ -364,7 +364,7 @@
R visitXmlTagNode(XmlTagNode xmlTagNode) => null;
}
/**
- * The abstract class {@code AbstractScanner} implements a scanner for HTML code. Subclasses are
+ * The abstract class `AbstractScanner` implements a scanner for HTML code. Subclasses are
* required to implement the interface used to access the characters being scanned.
* @coverage dart.engine.html
*/
@@ -424,7 +424,7 @@
/**
* Answer the source being scanned.
- * @return the source or {@code null} if undefined
+ * @return the source or `null` if undefined
*/
Source get source => _source;
@@ -638,7 +638,7 @@
}
}
/**
- * Instances of {@code HtmlScanResult} hold the result of scanning an HTML file.
+ * Instances of `HtmlScanResult` hold the result of scanning an HTML file.
* @coverage dart.engine.html
*/
class HtmlScanResult {
@@ -649,7 +649,7 @@
int _modificationTime = 0;
/**
- * The first token in the token stream (not {@code null}).
+ * The first token in the token stream (not `null`).
*/
Token _token;
@@ -665,7 +665,7 @@
/**
* Answer the line start information that was produced.
- * @return an array of line starts (not {@code null})
+ * @return an array of line starts (not `null`)
*/
List<int> get lineStarts => _lineStarts;
@@ -677,12 +677,12 @@
/**
* Answer the first token in the token stream.
- * @return the token (not {@code null})
+ * @return the token (not `null`)
*/
Token get token => _token;
}
/**
- * Instances of the class {@code StringScanner} implement a scanner that reads from a string. The
+ * Instances of the class `StringScanner` implement a scanner that reads from a string. The
* scanning logic is in the superclass.
* @coverage dart.engine.html
*/
@@ -733,7 +733,7 @@
}
}
/**
- * Instances of the class {@code CharBufferScanner} implement a scanner that reads from a character
+ * Instances of the class `CharBufferScanner` implement a scanner that reads from a character
* buffer. The scanning logic is in the superclass.
* @coverage dart.engine.html
*/
@@ -781,7 +781,7 @@
}
}
/**
- * Instances of the class {@code ToSourceVisitor} write a source representation of a visited XML
+ * Instances of the class `ToSourceVisitor` write a source representation of a visited XML
* node (and all of it's children) to a writer.
* @coverage dart.engine.html
*/
@@ -853,7 +853,7 @@
}
}
/**
- * The enumeration {@code TokenType} defines the types of tokens that can be returned by the
+ * The enumeration `TokenType` defines the types of tokens that can be returned by the
* scanner.
* @coverage dart.engine.html
*/
@@ -883,7 +883,7 @@
final int ordinal;
/**
- * The lexeme that defines this type of token, or {@code null} if there is more than one possible
+ * The lexeme that defines this type of token, or `null` if there is more than one possible
* lexeme for this type of token.
*/
String _lexeme;
@@ -892,7 +892,7 @@
}
/**
- * Return the lexeme that defines this type of token, or {@code null} if there is more than one
+ * Return the lexeme that defines this type of token, or `null` if there is more than one
* possible lexeme for this type of token.
* @return the lexeme that defines this type of token
*/
@@ -906,7 +906,7 @@
String toString() => "-eof-";
}
/**
- * Instances of {@code XmlAttributeNode} represent name/value pairs owned by an {@link XmlTagNode}.
+ * Instances of `XmlAttributeNode` represent name/value pairs owned by an [XmlTagNode].
* @coverage dart.engine.html
*/
class XmlAttributeNode extends XmlNode {
@@ -916,10 +916,10 @@
/**
* Construct a new instance representing an XML attribute.
- * @param name the name token (not {@code null}). This may be a zero length token if the attribute
+ * @param name the name token (not `null`). This may be a zero length token if the attribute
* is badly formed.
- * @param equals the equals sign or {@code null} if none
- * @param value the value token (not {@code null})
+ * @param equals the equals sign or `null` if none
+ * @param value the value token (not `null`)
*/
XmlAttributeNode(Token name, Token equals, Token value) {
this._name = name;
@@ -931,20 +931,20 @@
Token get endToken => _value;
/**
- * Answer the equals sign token that appears between the name and value tokens. This may be{@code null} if the attribute is badly formed.
- * @return the token or {@code null} if there is no equals sign between the name and value
+ * Answer the equals sign token that appears between the name and value tokens. This may be`null` if the attribute is badly formed.
+ * @return the token or `null` if there is no equals sign between the name and value
*/
Token get equals => _equals;
/**
* Answer the attribute name. This may be a zero length token if the attribute is badly formed.
- * @return the name (not {@code null})
+ * @return the name (not `null`)
*/
Token get name => _name;
/**
* Answer the lexeme for the value token without the leading and trailing quotes.
- * @return the text or {@code null} if the value is not specified
+ * @return the text or `null` if the value is not specified
*/
String get text {
if (_value == null) {
@@ -973,14 +973,14 @@
/**
* Answer the attribute value. A properly formed value will start and end with matching quote
* characters, but the value returned may not be properly formed.
- * @return the value or {@code null} if this represents a badly formed attribute
+ * @return the value or `null` if this represents a badly formed attribute
*/
Token get value => _value;
void visitChildren(XmlVisitor<Object> visitor) {
}
}
/**
- * The interface {@code XmlVisitor} defines the behavior of objects that can be used to visit an{@link XmlNode} structure.
+ * The interface `XmlVisitor` defines the behavior of objects that can be used to visit an[XmlNode] structure.
* @coverage dart.engine.html
*/
abstract class XmlVisitor<R> {
@@ -989,7 +989,7 @@
R visitXmlTagNode(XmlTagNode xmlTagNode);
}
/**
- * Instances of {@code HtmlScanner} receive and scan HTML content from a {@link Source}.<br/>
+ * Instances of `HtmlScanner` receive and scan HTML content from a [Source].<br/>
* For example, the following code scans HTML source and returns the result:
* <pre>
* HtmlScanner scanner = new HtmlScanner(source);
@@ -1002,7 +1002,7 @@
List<String> _SCRIPT_TAG = <String> ["script"];
/**
- * The source being scanned (not {@code null})
+ * The source being scanned (not `null`)
*/
Source _source;
@@ -1023,7 +1023,7 @@
/**
* Construct a new instance to scan the specified source.
- * @param source the source to be scanned (not {@code null})
+ * @param source the source to be scanned (not `null`)
*/
HtmlScanner(Source source) {
this._source = source;
@@ -1043,13 +1043,13 @@
/**
* Answer the result of scanning the source
- * @return the result (not {@code null})
+ * @return the result (not `null`)
*/
HtmlScanResult get result => new HtmlScanResult(_modificationTime, _token, _scanner.lineStarts);
}
/**
- * Instances of the class {@code XmlParser} are used to parse tokens into a AST structure comprised
- * of {@link XmlNode}s.
+ * Instances of the class `XmlParser` are used to parse tokens into a AST structure comprised
+ * of [XmlNode]s.
* @coverage dart.engine.html
*/
class XmlParser {
@@ -1079,17 +1079,17 @@
Source get source => _source;
/**
- * Answer {@code true} if the specified tag is self closing and thus should never have content or
+ * Answer `true` if the specified tag is self closing and thus should never have content or
* child tag nodes.
- * @param tag the tag (not {@code null})
- * @return {@code true} if self closing
+ * @param tag the tag (not `null`)
+ * @return `true` if self closing
*/
bool isSelfClosing(Token tag) => false;
/**
* Parse the entire token stream and in the process, advance the current token to the end of the
* token stream.
- * @return the list of tag nodes found (not {@code null}, contains no {@code null})
+ * @return the list of tag nodes found (not `null`, contains no `null`)
*/
List<XmlTagNode> parseTopTagNodes(Token firstToken) {
_currentToken = firstToken;
@@ -1119,8 +1119,8 @@
/**
* Insert a synthetic token of the specified type before the current token
- * @param type the type of token to be inserted (not {@code null})
- * @return the synthetic token that was inserted (not {@code null})
+ * @param type the type of token to be inserted (not `null`)
+ * @return the synthetic token that was inserted (not `null`)
*/
Token insertSyntheticToken(TokenType type) {
Token token = new Token.con2(type, _currentToken.offset, "");
@@ -1131,8 +1131,8 @@
/**
* Parse the token stream for an attribute. This method advances the current token over the
- * attribute, but should not be called if the {@link #currentToken} is not {@link TokenType#TAG}.
- * @return the attribute (not {@code null})
+ * attribute, but should not be called if the [currentToken] is not [TokenType#TAG].
+ * @return the attribute (not `null`)
*/
XmlAttributeNode parseAttribute() {
Token name = _currentToken;
@@ -1158,8 +1158,8 @@
/**
* Parse the stream for a sequence of attributes. This method advances the current token to the
- * next {@link TokenType#GT}, {@link TokenType#SLASH_GT}, or {@link TokenType#EOF}.
- * @return a collection of zero or more attributes (not {@code null}, contains no {@code null}s)
+ * next [TokenType#GT], [TokenType#SLASH_GT], or [TokenType#EOF].
+ * @return a collection of zero or more attributes (not `null`, contains no `null`s)
*/
List<XmlAttributeNode> parseAttributes() {
TokenType type = _currentToken.type;
@@ -1184,8 +1184,8 @@
/**
* Parse the stream for a sequence of tag nodes existing within a parent tag node. This method
- * advances the current token to the next {@link TokenType#LT_SLASH} or {@link TokenType#EOF}.
- * @return a list of nodes (not {@code null}, contains no {@code null}s)
+ * advances the current token to the next [TokenType#LT_SLASH] or [TokenType#EOF].
+ * @return a list of nodes (not `null`, contains no `null`s)
*/
List<XmlTagNode> parseChildTagNodes() {
TokenType type = _currentToken.type;
@@ -1212,8 +1212,8 @@
/**
* Parse the token stream for the next tag node. This method advances current token over the
- * parsed tag node, but should only be called if the current token is {@link TokenType#LT}
- * @return the tag node or {@code null} if none found
+ * parsed tag node, but should only be called if the current token is [TokenType#LT]
+ * @return the tag node or `null` if none found
*/
XmlTagNode parseTagNode() {
Token nodeStart = _currentToken;
@@ -1273,7 +1273,7 @@
}
}
/**
- * Instances of {@code XmlTagNode} represent XML or HTML elements such as {@code <p>} and{@code <body foo="bar"> ... </body>}.
+ * Instances of `XmlTagNode` represent XML or HTML elements such as `` and`<body foo="bar"> ... </body>`.
* @coverage dart.engine.html
*/
class XmlTagNode extends XmlNode {
@@ -1289,75 +1289,75 @@
static List<XmlTagNode> NO_TAG_NODES = new UnmodifiableListView(new List<XmlTagNode>());
/**
- * The starting {@link TokenType#LT} token (not {@code null}).
+ * The starting [TokenType#LT] token (not `null`).
*/
Token _nodeStart;
/**
- * The {@link TokenType#TAG} token after the starting '<' (not {@code null}).
+ * The [TokenType#TAG] token after the starting '<' (not `null`).
*/
Token _tag;
/**
- * The attributes contained by the receiver (not {@code null}, contains no {@code null}s).
+ * The attributes contained by the receiver (not `null`, contains no `null`s).
*/
List<XmlAttributeNode> _attributes;
/**
- * The {@link TokenType#GT} or {@link TokenType#SLASH_GT} token after the attributes (not{@code null}). The token may be the same token as {@link #nodeEnd} if there are no child{@link #tagNodes}.
+ * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not`null`). The token may be the same token as [nodeEnd] if there are no child[tagNodes].
*/
Token _attributeEnd;
/**
- * The tag nodes contained in the receiver (not {@code null}, contains no {@code null}s).
+ * The tag nodes contained in the receiver (not `null`, contains no `null`s).
*/
List<XmlTagNode> _tagNodes;
/**
- * The token (not {@code null}) after the content, which may be
- * <ul>
- * <li>(1) {@link TokenType#LT_SLASH} for nodes with open and close tags, or</li>
- * <li>(2) the {@link TokenType#LT} nodeStart of the next sibling node if this node is self
- * closing or the attributeEnd is {@link TokenType#SLASH_GT}, or</li>
- * <li>(3) {@link TokenType#EOF} if the node does not have a closing tag and is the last node in
- * the stream {@link TokenType#LT_SLASH} token after the content, or {@code null} if there is no
- * content and the attributes ended with {@link TokenType#SLASH_GT}.</li>
- * </ul>
+ * The token (not `null`) after the content, which may be
+ *
+ * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or
+ * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is self
+ * closing or the attributeEnd is [TokenType#SLASH_GT], or
+ * * (3) [TokenType#EOF] if the node does not have a closing tag and is the last node in
+ * the stream [TokenType#LT_SLASH] token after the content, or `null` if there is no
+ * content and the attributes ended with [TokenType#SLASH_GT].
+ *
*/
Token _contentEnd;
/**
- * The closing {@link TokenType#TAG} after the child elements or {@code null} if there is no
- * content and the attributes ended with {@link TokenType#SLASH_GT}
+ * The closing [TokenType#TAG] after the child elements or `null` if there is no
+ * content and the attributes ended with [TokenType#SLASH_GT]
*/
Token _closingTag;
/**
- * The ending {@link TokenType#GT} or {@link TokenType#SLASH_GT} token (not {@code null}).
+ * The ending [TokenType#GT] or [TokenType#SLASH_GT] token (not `null`).
*/
Token _nodeEnd;
/**
* Construct a new instance representing an XML or HTML element
- * @param nodeStart the starting {@link TokenType#LT} token (not {@code null})
- * @param tag the {@link TokenType#TAG} token after the starting '<' (not {@code null}).
- * @param attributes the attributes associated with this element or {@link #NO_ATTRIBUTES} (not{@code null}, contains no {@code null}s)
- * @param attributeEnd The {@link TokenType#GT} or {@link TokenType#SLASH_GT} token after the
- * attributes (not {@code null}). The token may be the same token as {@link #nodeEnd} if
- * there are no child {@link #tagNodes}.
- * @param tagNodes child tag nodes of the receiver or {@link #NO_TAG_NODES} (not {@code null},
- * contains no {@code null}s)
- * @param contentEnd the token (not {@code null}) after the content, which may be
- * <ul>
- * <li>(1) {@link TokenType#LT_SLASH} for nodes with open and close tags, or</li>
- * <li>(2) the {@link TokenType#LT} nodeStart of the next sibling node if this node is
- * self closing or the attributeEnd is {@link TokenType#SLASH_GT}, or</li>
- * <li>(3) {@link TokenType#EOF} if the node does not have a closing tag and is the last
- * node in the stream {@link TokenType#LT_SLASH} token after the content, or {@code null}if there is no content and the attributes ended with {@link TokenType#SLASH_GT}.</li>
- * </ul>
- * @param closingTag the closing {@link TokenType#TAG} after the child elements or {@code null} if
- * there is no content and the attributes ended with {@link TokenType#SLASH_GT}
- * @param nodeEnd the ending {@link TokenType#GT} or {@link TokenType#SLASH_GT} token (not{@code null})
+ * @param nodeStart the starting [TokenType#LT] token (not `null`)
+ * @param tag the [TokenType#TAG] token after the starting '<' (not `null`).
+ * @param attributes the attributes associated with this element or [NO_ATTRIBUTES] (not`null`, contains no `null`s)
+ * @param attributeEnd The [TokenType#GT] or [TokenType#SLASH_GT] token after the
+ * attributes (not `null`). The token may be the same token as [nodeEnd] if
+ * there are no child [tagNodes].
+ * @param tagNodes child tag nodes of the receiver or [NO_TAG_NODES] (not `null`,
+ * contains no `null`s)
+ * @param contentEnd the token (not `null`) after the content, which may be
+ *
+ * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or
+ * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is
+ * self closing or the attributeEnd is [TokenType#SLASH_GT], or
+ * * (3) [TokenType#EOF] if the node does not have a closing tag and is the last
+ * node in the stream [TokenType#LT_SLASH] token after the content, or `null`if there is no content and the attributes ended with [TokenType#SLASH_GT].
+ *
+ * @param closingTag the closing [TokenType#TAG] after the child elements or `null` if
+ * there is no content and the attributes ended with [TokenType#SLASH_GT]
+ * @param nodeEnd the ending [TokenType#GT] or [TokenType#SLASH_GT] token (not`null`)
*/
XmlTagNode(Token nodeStart, Token tag, List<XmlAttributeNode> attributes, Token attributeEnd, List<XmlTagNode> tagNodes, Token contentEnd, Token closingTag, Token nodeEnd) {
this._nodeStart = nodeStart;
@@ -1374,7 +1374,7 @@
/**
* Answer the attribute with the specified name.
* @param name the attribute name
- * @return the attribute or {@code null} if no matching attribute is found
+ * @return the attribute or `null` if no matching attribute is found
*/
XmlAttributeNode getAttribute(String name2) {
for (XmlAttributeNode attribute in _attributes) {
@@ -1386,23 +1386,23 @@
}
/**
- * The {@link TokenType#GT} or {@link TokenType#SLASH_GT} token after the attributes (not{@code null}). The token may be the same token as {@link #nodeEnd} if there are no child{@link #tagNodes}.
- * @return the token (not {@code null})
+ * The [TokenType#GT] or [TokenType#SLASH_GT] token after the attributes (not`null`). The token may be the same token as [nodeEnd] if there are no child[tagNodes].
+ * @return the token (not `null`)
*/
Token get attributeEnd => _attributeEnd;
/**
* Answer the receiver's attributes. Callers should not manipulate the returned list to edit the
* AST structure.
- * @return the attributes (not {@code null}, contains no {@code null}s)
+ * @return the attributes (not `null`, contains no `null`s)
*/
List<XmlAttributeNode> get attributes => _attributes;
/**
- * Find the attribute with the given name (see {@link #getAttribute(String)} and answer the lexeme
- * for the attribute's value token without the leading and trailing quotes (see{@link XmlAttributeNode#getText()}).
+ * Find the attribute with the given name (see [getAttribute] and answer the lexeme
+ * for the attribute's value token without the leading and trailing quotes (see[XmlAttributeNode#getText]).
* @param name the attribute name
- * @return the attribute text or {@code null} if no matching attribute is found
+ * @return the attribute text or `null` if no matching attribute is found
*/
String getAttributeText(String name) {
XmlAttributeNode attribute = getAttribute(name);
@@ -1411,17 +1411,17 @@
Token get beginToken => _nodeStart;
/**
- * The the closing {@link TokenType#TAG} after the child elements or {@code null} if there is no
- * content and the attributes ended with {@link TokenType#SLASH_GT}
- * @return the closing tag or {@code null}
+ * The the closing [TokenType#TAG] after the child elements or `null` if there is no
+ * content and the attributes ended with [TokenType#SLASH_GT]
+ * @return the closing tag or `null`
*/
Token get closingTag => _closingTag;
/**
* Answer a string representing the content contained in the receiver. This includes the textual
- * representation of any child tag nodes ({@link #getTagNodes()}). Whitespace between '<',
+ * representation of any child tag nodes ([getTagNodes]). Whitespace between '<',
* '</', and '>', '/>' is discarded, but all other whitespace is preserved.
- * @return the content (not {@code null})
+ * @return the content (not `null`)
*/
String get content {
Token token = _attributeEnd.next;
@@ -1442,16 +1442,16 @@
}
/**
- * Answer the token (not {@code null}) after the content, which may be
- * <ul>
- * <li>(1) {@link TokenType#LT_SLASH} for nodes with open and close tags, or</li>
- * <li>(2) the {@link TokenType#LT} nodeStart of the next sibling node if this node is self
- * closing or the attributeEnd is {@link TokenType#SLASH_GT}, or</li>
- * <li>(3) {@link TokenType#EOF} if the node does not have a closing tag and is the last node in
- * the stream {@link TokenType#LT_SLASH} token after the content, or {@code null} if there is no
- * content and the attributes ended with {@link TokenType#SLASH_GT}.</li>
- * </ul>
- * @return the token (not {@code null})
+ * Answer the token (not `null`) after the content, which may be
+ *
+ * * (1) [TokenType#LT_SLASH] for nodes with open and close tags, or
+ * * (2) the [TokenType#LT] nodeStart of the next sibling node if this node is self
+ * closing or the attributeEnd is [TokenType#SLASH_GT], or
+ * * (3) [TokenType#EOF] if the node does not have a closing tag and is the last node in
+ * the stream [TokenType#LT_SLASH] token after the content, or `null` if there is no
+ * content and the attributes ended with [TokenType#SLASH_GT].
+ *
+ * @return the token (not `null`)
*/
Token get contentEnd => _contentEnd;
Token get endToken {
@@ -1477,27 +1477,27 @@
}
/**
- * Answer the ending {@link TokenType#GT} or {@link TokenType#SLASH_GT} token.
- * @return the token (not {@code null})
+ * Answer the ending [TokenType#GT] or [TokenType#SLASH_GT] token.
+ * @return the token (not `null`)
*/
Token get nodeEnd => _nodeEnd;
/**
- * Answer the starting {@link TokenType#LT} token.
- * @return the token (not {@code null})
+ * Answer the starting [TokenType#LT] token.
+ * @return the token (not `null`)
*/
Token get nodeStart => _nodeStart;
/**
- * Answer the {@link TokenType#TAG} token after the starting '<'.
- * @return the token (not {@code null})
+ * Answer the [TokenType#TAG] token after the starting '<'.
+ * @return the token (not `null`)
*/
Token get tag => _tag;
/**
* Answer the tag nodes contained in the receiver. Callers should not manipulate the returned list
* to edit the AST structure.
- * @return the children (not {@code null}, contains no {@code null}s)
+ * @return the children (not `null`, contains no `null`s)
*/
List<XmlTagNode> get tagNodes => _tagNodes;
void visitChildren(XmlVisitor<Object> visitor) {
@@ -1510,7 +1510,7 @@
}
/**
- * Same as {@link #becomeParentOf(List)}, but returns given "ifEmpty" if "children" is empty
+ * Same as [becomeParentOf], but returns given "ifEmpty" if "children" is empty
*/
List becomeParentOfEmpty(List children, List ifEmpty) {
if (children != null && children.isEmpty) {
@@ -1520,8 +1520,8 @@
}
}
/**
- * Instances of the class {@code HtmlParser} are used to parse tokens into a AST structure comprised
- * of {@link XmlNode}s.
+ * Instances of the class `HtmlParser` are used to parse tokens into a AST structure comprised
+ * of [XmlNode]s.
* @coverage dart.engine.html
*/
class HtmlParser extends XmlParser {
@@ -1536,8 +1536,8 @@
/**
* Parse the tokens specified by the given scan result.
- * @param scanResult the result of scanning an HTML source (not {@code null})
- * @return the parse result (not {@code null})
+ * @param scanResult the result of scanning an HTML source (not `null`)
+ * @return the parse result (not `null`)
*/
HtmlParseResult parse(HtmlScanResult scanResult) {
Token firstToken = scanResult.token;
@@ -1548,8 +1548,8 @@
/**
* Scan then parse the specified source.
- * @param source the source to be scanned and parsed (not {@code null})
- * @return the parse result (not {@code null})
+ * @param source the source to be scanned and parsed (not `null`)
+ * @return the parse result (not `null`)
*/
HtmlParseResult parse2(Source source) {
HtmlScanner scanner = new HtmlScanner(source);
@@ -1559,7 +1559,7 @@
bool isSelfClosing(Token tag) => SELF_CLOSING.contains(tag.lexeme);
}
/**
- * Instances of the class {@code HtmlUnit} represent the contents of an HTML file.
+ * Instances of the class `HtmlUnit` represent the contents of an HTML file.
* @coverage dart.engine.html
*/
class HtmlUnit extends XmlNode {
@@ -1571,25 +1571,25 @@
/**
* The last token in the token stream that was parsed to form this compilation unit. This token
- * should always have a type of {@link TokenType.EOF}.
+ * should always have a type of [TokenType.EOF].
*/
Token _endToken;
/**
- * The tag nodes contained in the receiver (not {@code null}, contains no {@code null}s).
+ * The tag nodes contained in the receiver (not `null`, contains no `null`s).
*/
List<XmlTagNode> _tagNodes;
/**
- * The element associated with this HTML unit or {@code null} if the receiver is not resolved.
+ * The element associated with this HTML unit or `null` if the receiver is not resolved.
*/
HtmlElementImpl _element;
/**
* Construct a new instance representing the content of an HTML file.
- * @param beginToken the first token in the file (not {@code null})
- * @param tagNodes child tag nodes of the receiver (not {@code null}, contains no {@code null}s)
- * @param endToken the last token in the token stream which should be of type{@link TokenType.EOF}
+ * @param beginToken the first token in the file (not `null`)
+ * @param tagNodes child tag nodes of the receiver (not `null`, contains no `null`s)
+ * @param endToken the last token in the token stream which should be of type[TokenType.EOF]
*/
HtmlUnit(Token beginToken, List<XmlTagNode> tagNodes, Token endToken) {
this._beginToken = beginToken;
@@ -1601,7 +1601,7 @@
/**
* Return the element associated with this HTML unit.
- * @return the element or {@code null} if the receiver is not resolved
+ * @return the element or `null` if the receiver is not resolved
*/
HtmlElementImpl get element => _element;
Token get endToken => _endToken;
@@ -1609,7 +1609,7 @@
/**
* Answer the tag nodes contained in the receiver. Callers should not manipulate the returned list
* to edit the AST structure.
- * @return the children (not {@code null}, contains no {@code null}s)
+ * @return the children (not `null`, contains no `null`s)
*/
List<XmlTagNode> get tagNodes => _tagNodes;
diff --git a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
index 0f62806..7da792e 100644
--- a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
@@ -3,17 +3,17 @@
library engine.instrumentation;
import 'java_core.dart';
/**
- * The class {@code Instrumentation} implements support for logging instrumentation information.
- * <p>
+ * The class `Instrumentation` implements support for logging instrumentation information.
+ *
* Instrumentation information consists of information about specific operations. Those operations
* can range from user-facing operations, such as saving the changes to a file, to internal
- * operations, such as tokenizing source code. The information to be logged is gathered by{@link InstrumentationBuilder instrumentation builder}, created by one of the static methods on
- * this class such as {@link #builder(Class)} or {@link #builder(String)}.
- * <p>
- * Note, however, that until an instrumentation logger is installed using the method{@link #setLogger(InstrumentationLogger)}, all instrumentation data will be lost.
- * <p>
+ * operations, such as tokenizing source code. The information to be logged is gathered by[InstrumentationBuilder instrumentation builder], created by one of the static methods on
+ * this class such as [builder] or [builder].
+ *
+ * Note, however, that until an instrumentation logger is installed using the method[setLogger], all instrumentation data will be lost.
+ *
* <b>Example</b>
- * <p>
+ *
* To collect metrics about how long it took to save a file, you would write something like the
* following:
* <pre>
@@ -21,9 +21,9 @@
* // save the file
* instrumentation.metric("chars", fileLength).log();
* </pre>
- * The {@code Instrumentation.builder} method creates a new {@link InstrumentationBuilderinstrumentation builder} and records the time at which it was created. The{@link InstrumentationBuilder#metric(String,long)} appends the information specified by the
+ * The `Instrumentation.builder` method creates a new [InstrumentationBuilderinstrumentation builder] and records the time at which it was created. The[InstrumentationBuilder#metric] appends the information specified by the
* arguments and records the time at which the method is called so that the time to complete the
- * save operation can be calculated. The {@code log} method tells the builder that all of the data
+ * save operation can be calculated. The `log` method tells the builder that all of the data
* has been collected and that the resulting information should be logged.
* @coverage dart.engine.utilities
*/
@@ -47,15 +47,15 @@
/**
* Create a builder that can collect the data associated with an operation.
- * @param clazz the class performing the operation (not {@code null})
- * @return the builder that was created (not {@code null})
+ * @param clazz the class performing the operation (not `null`)
+ * @return the builder that was created (not `null`)
*/
static InstrumentationBuilder builder(Type clazz) => _CURRENT_LOGGER.createBuilder(clazz.toString());
/**
* Create a builder that can collect the data associated with an operation.
- * @param name the name used to uniquely identify the operation (not {@code null})
- * @return the builder that was created (not {@code null})
+ * @param name the name used to uniquely identify the operation (not `null`)
+ * @return the builder that was created (not `null`)
*/
static InstrumentationBuilder builder2(String name) => _CURRENT_LOGGER.createBuilder(name);
@@ -66,7 +66,7 @@
/**
* Return a builder that will silently ignore all data and logging requests.
- * @return the builder (not {@code null})
+ * @return the builder (not `null`)
*/
static InstrumentationBuilder get nullBuilder => _NULL_INSTRUMENTATION_BUILDER;
@@ -75,7 +75,7 @@
* it?
* @return
*/
- static bool isNullLogger() => identical(_CURRENT_LOGGER, _NULL_LOGGER);
+ static bool get isNullLogger => identical(_CURRENT_LOGGER, _NULL_LOGGER);
/**
* Set the logger that should receive instrumentation information to the given logger.
@@ -103,10 +103,10 @@
InstrumentationBuilder createBuilder(String name) => Instrumentation._NULL_INSTRUMENTATION_BUILDER;
}
/**
- * The interface {@code InstrumentationBuilder} defines the behavior of objects used to collect data
+ * The interface `InstrumentationBuilder` defines the behavior of objects used to collect data
* about an operation that has occurred and record that data through an instrumentation logger.
- * <p>
- * For an example of using objects that implement this interface, see {@link Instrumentation}.
+ *
+ * For an example of using objects that implement this interface, see [Instrumentation].
* @coverage dart.engine.utilities
*/
abstract class InstrumentationBuilder {
@@ -152,8 +152,8 @@
InstrumentationBuilder data4(String name, List<String> value);
/**
- * Answer the {@link InstrumentationLevel} of this {@code InstrumentationBuilder}.
- * @return one of {@link InstrumentationLevel#EVERYTHING}, {@link InstrumentationLevel#METRICS},{@link InstrumentationLevel#OFF}
+ * Answer the [InstrumentationLevel] of this `InstrumentationBuilder`.
+ * @return one of [InstrumentationLevel#EVERYTHING], [InstrumentationLevel#METRICS],[InstrumentationLevel#OFF]
*/
InstrumentationLevel get instrumentationLevel;
@@ -206,17 +206,17 @@
/**
* Append the given exception to the information being collected by this builder. The exception's
- * class name is captured using {@link #metric(String,String)}. Other aspects of the exception
+ * class name is captured using [metric]. Other aspects of the exception
* may contain either user identifiable or contains user intellectual property (but is not
- * guaranteed to contain either) and thus are captured using the various data methods such as{@link #data(String,String)}.
- * @param exception the exception (may be {@code null})
+ * guaranteed to contain either) and thus are captured using the various data methods such as[data].
+ * @param exception the exception (may be `null`)
*/
InstrumentationBuilder record(Exception exception);
}
/**
- * The instrumentation recording level representing (1) recording {@link #EVERYTHING} recording of
- * all instrumentation data, (2) recording only {@link #METRICS} information, or (3) recording
- * turned {@link #OFF} in which case nothing is recorded.
+ * The instrumentation recording level representing (1) recording [EVERYTHING] recording of
+ * all instrumentation data, (2) recording only [METRICS] information, or (3) recording
+ * turned [OFF] in which case nothing is recorded.
* @coverage dart.engine.utilities
*/
class InstrumentationLevel implements Comparable<InstrumentationLevel> {
@@ -261,10 +261,10 @@
String toString() => name;
}
/**
- * The interface {@code InstrumentationLogger} defines the behavior of objects that are used to log
+ * The interface `InstrumentationLogger` defines the behavior of objects that are used to log
* instrumentation data.
- * <p>
- * For an example of using objects that implement this interface, see {@link Instrumentation}.
+ *
+ * For an example of using objects that implement this interface, see [Instrumentation].
* @coverage dart.engine.utilities
*/
abstract class InstrumentationLogger {
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_core.dart b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
index 7e90245..01ffd5d 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_core.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_core.dart
@@ -154,6 +154,16 @@
}
});
}
+ static int indexOf(String target, String str, int fromIndex) {
+ if (fromIndex > target.length) return -1;
+ if (fromIndex < 0) fromIndex = 0;
+ return target.indexOf(str, fromIndex);
+ }
+ static int lastIndexOf(String target, String str, int fromIndex) {
+ if (fromIndex > target.length) return -1;
+ if (fromIndex < 0) fromIndex = 0;
+ return target.lastIndexOf(str, fromIndex);
+ }
static bool startsWithBefore(String s, String other, int start) {
return s.indexOf(other, start) != -1;
}
diff --git a/pkg/analyzer_experimental/lib/src/generated/java_io.dart b/pkg/analyzer_experimental/lib/src/generated/java_io.dart
index b1cced8..fbbe65f 100644
--- a/pkg/analyzer_experimental/lib/src/generated/java_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/java_io.dart
@@ -28,7 +28,7 @@
}
}
if (name == 'com.google.dart.sdk') {
- String exec = new Options().executable;
+ String exec = Platform.executable;
if (exec.length != 0) {
String sdkPath;
// may be "xcodebuild/ReleaseIA32/dart" with "dart-sdk" sibling
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart
index bd5a1dc..32c04c8 100644
--- a/pkg/analyzer_experimental/lib/src/generated/parser.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -11,14 +11,14 @@
import 'ast.dart';
import 'utilities_dart.dart';
/**
- * Instances of the class {@code CommentAndMetadata} implement a simple data-holder for a method
+ * Instances of the class `CommentAndMetadata` implement a simple data-holder for a method
* that needs to return multiple values.
* @coverage dart.engine.parser
*/
class CommentAndMetadata {
/**
- * The documentation comment that was parsed, or {@code null} if none was given.
+ * The documentation comment that was parsed, or `null` if none was given.
*/
Comment _comment;
@@ -38,7 +38,7 @@
}
/**
- * Return the documentation comment that was parsed, or {@code null} if none was given.
+ * Return the documentation comment that was parsed, or `null` if none was given.
* @return the documentation comment that was parsed
*/
Comment get comment => _comment;
@@ -50,19 +50,19 @@
List<Annotation> get metadata => _metadata;
}
/**
- * Instances of the class {@code FinalConstVarOrType} implement a simple data-holder for a method
+ * Instances of the class `FinalConstVarOrType` implement a simple data-holder for a method
* that needs to return multiple values.
* @coverage dart.engine.parser
*/
class FinalConstVarOrType {
/**
- * The 'final', 'const' or 'var' keyword, or {@code null} if none was given.
+ * The 'final', 'const' or 'var' keyword, or `null` if none was given.
*/
Token _keyword;
/**
- * The type, of {@code null} if no type was specified.
+ * The type, of `null` if no type was specified.
*/
TypeName _type;
@@ -77,103 +77,103 @@
}
/**
- * Return the 'final', 'const' or 'var' keyword, or {@code null} if none was given.
+ * Return the 'final', 'const' or 'var' keyword, or `null` if none was given.
* @return the 'final', 'const' or 'var' keyword
*/
Token get keyword => _keyword;
/**
- * Return the type, of {@code null} if no type was specified.
+ * Return the type, of `null` if no type was specified.
* @return the type
*/
TypeName get type => _type;
}
/**
- * Instances of the class {@code Modifiers} implement a simple data-holder for a method that needs
+ * Instances of the class `Modifiers` implement a simple data-holder for a method that needs
* to return multiple values.
* @coverage dart.engine.parser
*/
class Modifiers {
/**
- * The token representing the keyword 'abstract', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'abstract', or `null` if the keyword was not found.
*/
Token _abstractKeyword;
/**
- * The token representing the keyword 'const', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'const', or `null` if the keyword was not found.
*/
Token _constKeyword;
/**
- * The token representing the keyword 'external', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'external', or `null` if the keyword was not found.
*/
Token _externalKeyword;
/**
- * The token representing the keyword 'factory', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'factory', or `null` if the keyword was not found.
*/
Token _factoryKeyword;
/**
- * The token representing the keyword 'final', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'final', or `null` if the keyword was not found.
*/
Token _finalKeyword;
/**
- * The token representing the keyword 'static', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'static', or `null` if the keyword was not found.
*/
Token _staticKeyword;
/**
- * The token representing the keyword 'var', or {@code null} if the keyword was not found.
+ * The token representing the keyword 'var', or `null` if the keyword was not found.
*/
Token _varKeyword;
/**
- * Return the token representing the keyword 'abstract', or {@code null} if the keyword was not
+ * Return the token representing the keyword 'abstract', or `null` if the keyword was not
* found.
* @return the token representing the keyword 'abstract'
*/
Token get abstractKeyword => _abstractKeyword;
/**
- * Return the token representing the keyword 'const', or {@code null} if the keyword was not
+ * Return the token representing the keyword 'const', or `null` if the keyword was not
* found.
* @return the token representing the keyword 'const'
*/
Token get constKeyword => _constKeyword;
/**
- * Return the token representing the keyword 'external', or {@code null} if the keyword was not
+ * Return the token representing the keyword 'external', or `null` if the keyword was not
* found.
* @return the token representing the keyword 'external'
*/
Token get externalKeyword => _externalKeyword;
/**
- * Return the token representing the keyword 'factory', or {@code null} if the keyword was not
+ * Return the token representing the keyword 'factory', or `null` if the keyword was not
* found.
* @return the token representing the keyword 'factory'
*/
Token get factoryKeyword => _factoryKeyword;
/**
- * Return the token representing the keyword 'final', or {@code null} if the keyword was not
+ * Return the token representing the keyword 'final', or `null` if the keyword was not
* found.
* @return the token representing the keyword 'final'
*/
Token get finalKeyword => _finalKeyword;
/**
- * Return the token representing the keyword 'static', or {@code null} if the keyword was not
+ * Return the token representing the keyword 'static', or `null` if the keyword was not
* found.
* @return the token representing the keyword 'static'
*/
Token get staticKeyword => _staticKeyword;
/**
- * Return the token representing the keyword 'var', or {@code null} if the keyword was not found.
+ * Return the token representing the keyword 'var', or `null` if the keyword was not found.
* @return the token representing the keyword 'var'
*/
Token get varKeyword => _varKeyword;
@@ -246,12 +246,12 @@
}
/**
- * If the given keyword is not {@code null}, append it to the given builder, prefixing it with a
+ * If the given keyword is not `null`, append it to the given builder, prefixing it with a
* space if needed.
* @param builder the builder to which the keyword will be appended
- * @param needsSpace {@code true} if the keyword needs to be prefixed with a space
+ * @param needsSpace `true` if the keyword needs to be prefixed with a space
* @param keyword the keyword to be appended
- * @return {@code true} if subsequent keywords need to be prefixed with a space
+ * @return `true` if subsequent keywords need to be prefixed with a space
*/
bool appendKeyword(JavaStringBuilder builder, bool needsSpace, Token keyword) {
if (keyword != null) {
@@ -265,7 +265,7 @@
}
}
/**
- * Instances of the class {@code Parser} are used to parse tokens into an AST structure.
+ * Instances of the class `Parser` are used to parse tokens into an AST structure.
* @coverage dart.engine.parser
*/
class Parser {
@@ -329,7 +329,7 @@
/**
* Parse an expression, starting with the given token.
* @param token the first token of the expression
- * @return the expression that was parsed, or {@code null} if the tokens do not represent a
+ * @return the expression that was parsed, or `null` if the tokens do not represent a
* recognizable expression
*/
Expression parseExpression(Token token) {
@@ -345,7 +345,7 @@
/**
* Parse a statement, starting with the given token.
* @param token the first token of the statement
- * @return the statement that was parsed, or {@code null} if the tokens do not represent a
+ * @return the statement that was parsed, or `null` if the tokens do not represent a
* recognizable statement
*/
Statement parseStatement(Token token) {
@@ -361,7 +361,7 @@
/**
* Parse a sequence of statements, starting with the given token.
* @param token the first token of the sequence of statement
- * @return the statements that were parsed, or {@code null} if the tokens do not represent a
+ * @return the statements that were parsed, or `null` if the tokens do not represent a
* recognizable sequence of statements
*/
List<Statement> parseStatements(Token token) {
@@ -450,10 +450,10 @@
FunctionDeclaration convertToFunctionDeclaration(MethodDeclaration method) => new FunctionDeclaration.full(method.documentationComment, method.metadata, method.externalKeyword, method.returnType, method.propertyKeyword, method.name, new FunctionExpression.full(method.parameters, method.body));
/**
- * Return {@code true} if the current token could be the start of a compilation unit member. This
+ * Return `true` if the current token could be the start of a compilation unit member. This
* method is used for recovery purposes to decide when to stop skipping tokens after finding an
* error while parsing a compilation unit member.
- * @return {@code true} if the current token could be the start of a compilation unit member
+ * @return `true` if the current token could be the start of a compilation unit member
*/
bool couldBeStartOfCompilationUnitMember() {
if ((matches(Keyword.IMPORT) || matches(Keyword.EXPORT) || matches(Keyword.LIBRARY) || matches(Keyword.PART)) && !matches4(peek(), TokenType.PERIOD) && !matches4(peek(), TokenType.LT)) {
@@ -517,7 +517,7 @@
* @param expression the expression being checked
*/
void ensureAssignable(Expression expression) {
- if (expression != null && !expression.isAssignable()) {
+ if (expression != null && !expression.isAssignable) {
reportError7(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, []);
}
}
@@ -556,7 +556,7 @@
/**
* Search the given list of ranges for a range that contains the given index. Return the range
- * that was found, or {@code null} if none of the ranges contain the index.
+ * that was found, or `null` if none of the ranges contain the index.
* @param ranges the ranges to be searched
* @param index the index contained in the returned range
* @return the range that was found
@@ -611,7 +611,7 @@
index = end;
}
} else if (JavaString.startsWithBefore(comment, "[:", index)) {
- int end = comment.indexOf(":]", index + 2);
+ int end = JavaString.indexOf(comment, ":]", index + 2);
if (end < 0) {
end = length;
}
@@ -625,7 +625,7 @@
}
/**
- * Return the end token associated with the given begin token, or {@code null} if either the given
+ * Return the end token associated with the given begin token, or `null` if either the given
* token is not a begin token or it does not have an end token associated with it.
* @param beginToken the token that is expected to have an end token associated with it
* @return the end token associated with the begin token
@@ -638,11 +638,11 @@
}
/**
- * Return {@code true} if the current token is the first token of a return type that is followed
+ * Return `true` if the current token is the first token of a return type that is followed
* by an identifier, possibly followed by a list of type parameters, followed by a
* left-parenthesis. This is used by parseTypeAlias to determine whether or not to parse a return
* type.
- * @return {@code true} if we can successfully parse the rest of a type alias if we first parse a
+ * @return `true` if we can successfully parse the rest of a type alias if we first parse a
* return type.
*/
bool hasReturnTypeInTypeAlias() {
@@ -654,8 +654,8 @@
}
/**
- * Return {@code true} if the current token appears to be the beginning of a function declaration.
- * @return {@code true} if the current token appears to be the beginning of a function declaration
+ * Return `true` if the current token appears to be the beginning of a function declaration.
+ * @return `true` if the current token appears to be the beginning of a function declaration
*/
bool isFunctionDeclaration() {
if (matches(Keyword.VOID)) {
@@ -676,9 +676,9 @@
}
/**
- * Return {@code true} if the given token appears to be the beginning of a function expression.
+ * Return `true` if the given token appears to be the beginning of a function expression.
* @param startToken the token that might be the start of a function expression
- * @return {@code true} if the given token appears to be the beginning of a function expression
+ * @return `true` if the given token appears to be the beginning of a function expression
*/
bool isFunctionExpression(Token startToken) {
Token afterParameters = skipFormalParameterList(startToken);
@@ -689,14 +689,14 @@
}
/**
- * Return {@code true} if the given character is a valid hexadecimal digit.
+ * Return `true` if the given character is a valid hexadecimal digit.
* @param character the character being tested
- * @return {@code true} if the character is a valid hexadecimal digit
+ * @return `true` if the character is a valid hexadecimal digit
*/
bool isHexDigit(int character) => (0x30 <= character && character <= 0x39) || (0x41 <= character && character <= 0x46) || (0x61 <= character && character <= 0x66);
/**
- * Return {@code true} if the current token is the first token in an initialized variable
+ * Return `true` if the current token is the first token in an initialized variable
* declaration rather than an expression. This method assumes that we have already skipped past
* any metadata that might be associated with the declaration.
* <pre>
@@ -714,7 +714,7 @@
* initializedIdentifier ::=
* identifier ('=' expression)?
* </pre>
- * @return {@code true} if the current token is the first token in an initialized variable
+ * @return `true` if the current token is the first token in an initialized variable
* declaration
*/
bool isInitializedVariableDeclaration() {
@@ -740,12 +740,12 @@
* Given that we have just found bracketed text within a comment, look to see whether that text is
* (a) followed by a parenthesized link address, (b) followed by a colon, or (c) followed by
* optional whitespace and another square bracket.
- * <p>
+ *
* This method uses the syntax described by the <a
* href="http://daringfireball.net/projects/markdown/syntax">markdown</a> project.
* @param comment the comment text in which the bracketed text was found
* @param rightIndex the index of the right bracket
- * @return {@code true} if the bracketed text is followed by a link address
+ * @return `true` if the bracketed text is followed by a link address
*/
bool isLinkText(String comment, int rightIndex) {
int length = comment.length;
@@ -768,14 +768,14 @@
}
/**
- * Return {@code true} if the given token appears to be the beginning of an operator declaration.
+ * Return `true` if the given token appears to be the beginning of an operator declaration.
* @param startToken the token that might be the start of an operator declaration
- * @return {@code true} if the given token appears to be the beginning of an operator declaration
+ * @return `true` if the given token appears to be the beginning of an operator declaration
*/
bool isOperator(Token startToken) {
- if (startToken.isOperator()) {
+ if (startToken.isOperator) {
Token token = startToken.next;
- while (token.isOperator()) {
+ while (token.isOperator) {
token = token.next;
}
return matches4(token, TokenType.OPEN_PAREN);
@@ -784,8 +784,8 @@
}
/**
- * Return {@code true} if the current token appears to be the beginning of a switch member.
- * @return {@code true} if the current token appears to be the beginning of a switch member
+ * Return `true` if the current token appears to be the beginning of a switch member.
+ * @return `true` if the current token appears to be the beginning of a switch member
*/
bool isSwitchMember() {
Token token = _currentToken;
@@ -801,9 +801,9 @@
/**
* Compare the given tokens to find the token that appears first in the source being parsed. That
- * is, return the left-most of all of the tokens. The arguments are allowed to be {@code null}.
- * Return the token with the smallest offset, or {@code null} if there are no arguments or if all
- * of the arguments are {@code null}.
+ * is, return the left-most of all of the tokens. The arguments are allowed to be `null`.
+ * Return the token with the smallest offset, or `null` if there are no arguments or if all
+ * of the arguments are `null`.
* @param tokens the tokens being compared
* @return the token with the smallest offset
*/
@@ -823,42 +823,42 @@
}
/**
- * Return {@code true} if the current token matches the given keyword.
+ * Return `true` if the current token matches the given keyword.
* @param keyword the keyword that can optionally appear in the current location
- * @return {@code true} if the current token matches the given keyword
+ * @return `true` if the current token matches the given keyword
*/
bool matches(Keyword keyword) => matches3(_currentToken, keyword);
/**
- * Return {@code true} if the current token matches the given identifier.
+ * Return `true` if the current token matches the given identifier.
* @param identifier the identifier that can optionally appear in the current location
- * @return {@code true} if the current token matches the given identifier
+ * @return `true` if the current token matches the given identifier
*/
bool matches2(String identifier) => identical(_currentToken.type, TokenType.IDENTIFIER) && _currentToken.lexeme == identifier;
/**
- * Return {@code true} if the given token matches the given keyword.
+ * Return `true` if the given token matches the given keyword.
* @param token the token being tested
* @param keyword the keyword that is being tested for
- * @return {@code true} if the given token matches the given keyword
+ * @return `true` if the given token matches the given keyword
*/
bool matches3(Token token, Keyword keyword2) => identical(token.type, TokenType.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword2);
/**
- * Return {@code true} if the given token has the given type.
+ * Return `true` if the given token has the given type.
* @param token the token being tested
* @param type the type of token that is being tested for
- * @return {@code true} if the given token has the given type
+ * @return `true` if the given token has the given type
*/
bool matches4(Token token, TokenType type2) => identical(token.type, type2);
/**
- * Return {@code true} if the current token has the given type. Note that this method, unlike
+ * Return `true` if the current token has the given type. Note that this method, unlike
* other variants, will modify the token stream if possible to match a wider range of tokens. In
* particular, if we are attempting to match a '>' and the next token is either a '>>' or '>>>',
- * the token stream will be re-written and {@code true} will be returned.
+ * the token stream will be re-written and `true` will be returned.
* @param type the type of token that can optionally appear in the current location
- * @return {@code true} if the current token has the given type
+ * @return `true` if the current token has the given type
*/
bool matches5(TokenType type2) {
TokenType currentType = _currentToken.type;
@@ -901,10 +901,10 @@
}
/**
- * Return {@code true} if the given token has any one of the given types.
+ * Return `true` if the given token has any one of the given types.
* @param token the token being tested
* @param types the types of token that are being tested for
- * @return {@code true} if the given token has any of the given types
+ * @return `true` if the given token has any of the given types
*/
bool matchesAny(Token token, List<TokenType> types) {
TokenType actualType = token.type;
@@ -917,23 +917,23 @@
}
/**
- * Return {@code true} if the current token is a valid identifier. Valid identifiers include
+ * Return `true` if the current token is a valid identifier. Valid identifiers include
* built-in identifiers (pseudo-keywords).
- * @return {@code true} if the current token is a valid identifier
+ * @return `true` if the current token is a valid identifier
*/
bool matchesIdentifier() => matchesIdentifier2(_currentToken);
/**
- * Return {@code true} if the given token is a valid identifier. Valid identifiers include
+ * Return `true` if the given token is a valid identifier. Valid identifiers include
* built-in identifiers (pseudo-keywords).
- * @return {@code true} if the given token is a valid identifier
+ * @return `true` if the given token is a valid identifier
*/
- bool matchesIdentifier2(Token token) => matches4(token, TokenType.IDENTIFIER) || (matches4(token, TokenType.KEYWORD) && ((token as KeywordToken)).keyword.isPseudoKeyword());
+ bool matchesIdentifier2(Token token) => matches4(token, TokenType.IDENTIFIER) || (matches4(token, TokenType.KEYWORD) && ((token as KeywordToken)).keyword.isPseudoKeyword);
/**
- * If the current token has the given type, then advance to the next token and return {@code true}. Otherwise, return {@code false} without advancing.
+ * If the current token has the given type, then advance to the next token and return `true`. Otherwise, return `false` without advancing.
* @param type the type of token that can optionally appear in the current location
- * @return {@code true} if the current token has the given type
+ * @return `true` if the current token has the given type
*/
bool optional(TokenType type) {
if (matches5(type)) {
@@ -954,12 +954,12 @@
*/
Expression parseAdditiveExpression() {
Expression expression;
- if (matches(Keyword.SUPER) && _currentToken.next.type.isAdditiveOperator()) {
+ if (matches(Keyword.SUPER) && _currentToken.next.type.isAdditiveOperator) {
expression = new SuperExpression.full(andAdvance);
} else {
expression = parseMultiplicativeExpression();
}
- while (_currentToken.type.isAdditiveOperator()) {
+ while (_currentToken.type.isAdditiveOperator) {
Token operator = andAdvance;
expression = new BinaryExpression.full(expression, operator, parseMultiplicativeExpression());
}
@@ -1087,7 +1087,7 @@
* | 'super' assignableSelector
* | identifier
* </pre>
- * @param primaryAllowed {@code true} if the expression is allowed to be a primary without any
+ * @param primaryAllowed `true` if the expression is allowed to be a primary without any
* assignable selector
* @return the assignable expression that was parsed
*/
@@ -1136,7 +1136,7 @@
* | '.' identifier
* </pre>
* @param prefix the expression preceding the selector
- * @param optional {@code true} if the selector is optional
+ * @param optional `true` if the selector is optional
* @return the assignable selector that was parsed
*/
Expression parseAssignableSelector(Expression prefix, bool optional) {
@@ -1330,7 +1330,7 @@
}
}
}
- if (_currentToken.type.isAssignmentOperator()) {
+ if (_currentToken.type.isAssignmentOperator) {
Token operator = andAdvance;
ensureAssignable(expression);
expression = new AssignmentExpression.full(expression, operator, parseExpressionWithoutCascade());
@@ -1345,7 +1345,7 @@
* metadata 'abstract'? 'class' name typeParameterList? (extendsClause withClause?)? implementsClause? '{' classMembers '}'
* </pre>
* @param commentAndMetadata the metadata to be associated with the member
- * @param abstractKeyword the token for the keyword 'abstract', or {@code null} if the keyword was
+ * @param abstractKeyword the token for the keyword 'abstract', or `null` if the keyword was
* not given
* @return the class declaration that was parsed
*/
@@ -1425,7 +1425,7 @@
* | methodSignature functionBody
* </pre>
* @param className the name of the class containing the member being parsed
- * @return the class member that was parsed, or {@code null} if what was found was not a valid
+ * @return the class member that was parsed, or `null` if what was found was not a valid
* class member
*/
ClassMember parseClassMember(String className) {
@@ -1533,7 +1533,7 @@
* (metadata memberDefinition)
* </pre>
* @param className the name of the class whose members are being parsed
- * @param closingBracket the closing bracket for the class, or {@code null} if the closing bracket
+ * @param closingBracket the closing bracket for the class, or `null` if the closing bracket
* is missing
* @return the list of class members that were parsed
*/
@@ -1664,7 +1664,7 @@
* @param referenceSource the source occurring between the square brackets within a documentation
* comment
* @param sourceOffset the offset of the first character of the reference source
- * @return the comment reference that was parsed, or {@code null} if no reference could be found
+ * @return the comment reference that was parsed, or `null` if no reference could be found
*/
CommentReference parseCommentReference(String referenceSource, int sourceOffset) {
if (referenceSource.length == 0) {
@@ -1729,7 +1729,7 @@
while (leftIndex >= 0 && leftIndex + 1 < length) {
List<int> range = findRange(codeBlockRanges, leftIndex);
if (range == null) {
- int rightIndex = comment.indexOf(']', leftIndex);
+ int rightIndex = JavaString.indexOf(comment, ']', leftIndex);
if (rightIndex >= 0) {
int firstChar = comment.codeUnitAt(leftIndex + 1);
if (firstChar != 0x27 && firstChar != 0x22) {
@@ -1744,9 +1744,9 @@
} else {
rightIndex = leftIndex + 1;
}
- leftIndex = comment.indexOf('[', rightIndex);
+ leftIndex = JavaString.indexOf(comment, '[', rightIndex);
} else {
- leftIndex = comment.indexOf('[', range[1] + 1);
+ leftIndex = JavaString.indexOf(comment, '[', range[1] + 1);
}
}
}
@@ -1755,7 +1755,7 @@
/**
* Parse a compilation unit.
- * <p>
+ *
* Specified:
* <pre>
* compilationUnit ::=
@@ -1861,7 +1861,7 @@
* | variableDeclaration ';'
* </pre>
* @param commentAndMetadata the metadata to be associated with the member
- * @return the compilation unit member that was parsed, or {@code null} if what was parsed could
+ * @return the compilation unit member that was parsed, or `null` if what was parsed could
* not be represented as a compilation unit member
*/
CompilationUnitMember parseCompilationUnitMember(CommentAndMetadata commentAndMetadata) {
@@ -2129,7 +2129,7 @@
* multiLineComment?
* | singleLineComment
* </pre>
- * @return the documentation comment that was parsed, or {@code null} if there was no comment
+ * @return the documentation comment that was parsed, or `null` if there was no comment
*/
Comment parseDocumentationComment() {
List<Token> commentTokens = new List<Token>();
@@ -2204,12 +2204,12 @@
*/
Expression parseEqualityExpression() {
Expression expression;
- if (matches(Keyword.SUPER) && _currentToken.next.type.isEqualityOperator()) {
+ if (matches(Keyword.SUPER) && _currentToken.next.type.isEqualityOperator) {
expression = new SuperExpression.full(andAdvance);
} else {
expression = parseRelationalExpression();
}
- while (_currentToken.type.isEqualityOperator()) {
+ while (_currentToken.type.isEqualityOperator) {
Token operator = andAdvance;
expression = new BinaryExpression.full(expression, operator, parseRelationalExpression());
}
@@ -2261,7 +2261,7 @@
tokenType = _currentToken.type;
}
return new CascadeExpression.full(expression, cascadeSections);
- } else if (tokenType.isAssignmentOperator()) {
+ } else if (tokenType.isAssignmentOperator) {
Token operator = andAdvance;
ensureAssignable(expression);
return new AssignmentExpression.full(expression, operator, parseExpression2());
@@ -2303,7 +2303,7 @@
return parseRethrowExpression();
}
Expression expression = parseConditionalExpression();
- if (_currentToken.type.isAssignmentOperator()) {
+ if (_currentToken.type.isAssignmentOperator) {
Token operator = andAdvance;
ensureAssignable(expression);
expression = new AssignmentExpression.full(expression, operator, parseExpressionWithoutCascade());
@@ -2334,7 +2334,7 @@
* | 'var'
* | type
* </pre>
- * @param optional {@code true} if the keyword and type are optional
+ * @param optional `true` if the keyword and type are optional
* @return the 'final', 'const', 'var' or type that was parsed
*/
FinalConstVarOrType parseFinalConstVarOrType(bool optional) {
@@ -2358,7 +2358,7 @@
}
/**
- * Parse a formal parameter. At most one of {@code isOptional} and {@code isNamed} can be{@code true}.
+ * Parse a formal parameter. At most one of `isOptional` and `isNamed` can be`true`.
* <pre>
* defaultFormalParameter ::=
* normalFormalParameter ('=' expression)?
@@ -2603,9 +2603,9 @@
* '=>' expression
* | block
* </pre>
- * @param mayBeEmpty {@code true} if the function body is allowed to be empty
+ * @param mayBeEmpty `true` if the function body is allowed to be empty
* @param emptyErrorCode the error code to report if function body expecte, but not found
- * @param inExpression {@code true} if the function body is being parsed as part of an expression
+ * @param inExpression `true` if the function body is being parsed as part of an expression
* and therefore does not have a terminating semicolon
* @return the function body that was parsed
*/
@@ -2656,9 +2656,9 @@
* </pre>
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
- * @param externalKeyword the 'external' keyword, or {@code null} if the function is not external
- * @param returnType the return type, or {@code null} if there is no return type
- * @param isStatement {@code true} if the function declaration is being parsed as a statement
+ * @param externalKeyword the 'external' keyword, or `null` if the function is not external
+ * @param returnType the return type, or `null` if there is no return type
+ * @param isStatement `true` if the function declaration is being parsed as a statement
* @return the function declaration that was parsed
*/
FunctionDeclaration parseFunctionDeclaration(CommentAndMetadata commentAndMetadata, Token externalKeyword, TypeName returnType) {
@@ -2710,7 +2710,7 @@
* </pre>
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
- * @param returnType the return type, or {@code null} if there is no return type
+ * @param returnType the return type, or `null` if there is no return type
* @return the function declaration statement that was parsed
*/
Statement parseFunctionDeclarationStatement2(CommentAndMetadata commentAndMetadata, TypeName returnType) => new FunctionDeclarationStatement.full(parseFunctionDeclaration(commentAndMetadata, null, returnType));
@@ -2778,8 +2778,8 @@
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
* @param externalKeyword the 'external' token
- * @param staticKeyword the static keyword, or {@code null} if the getter is not static
- * @param the return type that has already been parsed, or {@code null} if there was no return
+ * @param staticKeyword the static keyword, or `null` if the getter is not static
+ * @param the return type that has already been parsed, or `null` if there was no return
* type
* @return the getter that was parsed
*/
@@ -2893,10 +2893,10 @@
* </pre>
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
- * @param staticKeyword the static keyword, or {@code null} if the getter is not static
- * @param keyword the token representing the 'final', 'const' or 'var' keyword, or {@code null} if
+ * @param staticKeyword the static keyword, or `null` if the getter is not static
+ * @param keyword the token representing the 'final', 'const' or 'var' keyword, or `null` if
* there is no keyword
- * @param type the type that has already been parsed, or {@code null} if 'var' was provided
+ * @param type the type that has already been parsed, or `null` if 'var' was provided
* @return the getter that was parsed
*/
FieldDeclaration parseInitializedIdentifierList(CommentAndMetadata commentAndMetadata, Token staticKeyword, Token keyword, TypeName type) {
@@ -2984,9 +2984,9 @@
* listLiteral ::=
* 'const'? typeArguments? '\[' (expressionList ','?)? '\]'
* </pre>
- * @param modifier the 'const' modifier appearing before the literal, or {@code null} if there is
+ * @param modifier the 'const' modifier appearing before the literal, or `null` if there is
* no modifier
- * @param typeArguments the type arguments appearing before the literal, or {@code null} if there
+ * @param typeArguments the type arguments appearing before the literal, or `null` if there
* are no type arguments
* @return the list literal that was parsed
*/
@@ -3024,7 +3024,7 @@
* listLiteral
* | mapLiteral
* </pre>
- * @param modifier the 'const' modifier appearing before the literal, or {@code null} if there is
+ * @param modifier the 'const' modifier appearing before the literal, or `null` if there is
* no modifier
* @return the list or map literal that was parsed
*/
@@ -3082,9 +3082,9 @@
* mapLiteral ::=
* 'const'? typeArguments? '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
* </pre>
- * @param modifier the 'const' modifier appearing before the literal, or {@code null} if there is
+ * @param modifier the 'const' modifier appearing before the literal, or `null` if there is
* no modifier
- * @param typeArguments the type arguments that were declared, or {@code null} if there are no
+ * @param typeArguments the type arguments that were declared, or `null` if there are no
* type arguments
* @return the map literal that was parsed
*/
@@ -3136,7 +3136,7 @@
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
* @param externalKeyword the 'external' token
- * @param staticKeyword the static keyword, or {@code null} if the getter is not static
+ * @param staticKeyword the static keyword, or `null` if the getter is not static
* @param returnType the return type of the method
* @return the method declaration that was parsed
*/
@@ -3157,7 +3157,7 @@
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
* @param externalKeyword the 'external' token
- * @param staticKeyword the static keyword, or {@code null} if the getter is not static
+ * @param staticKeyword the static keyword, or `null` if the getter is not static
* @param returnType the return type of the method
* @param name the name of the method
* @param parameters the parameters to the method
@@ -3181,7 +3181,7 @@
* Parse the modifiers preceding a declaration. This method allows the modifiers to appear in any
* order but does generate errors for duplicated modifiers. Checks for other problems, such as
* having the modifiers appear in the wrong order or specifying both 'const' and 'final', are
- * reported in one of the methods whose name is prefixed with {@code validateModifiersFor}.
+ * reported in one of the methods whose name is prefixed with `validateModifiersFor`.
* <pre>
* modifiers ::=
* ('abstract' | 'const' | 'external' | 'factory' | 'final' | 'static' | 'var')
@@ -3259,12 +3259,12 @@
*/
Expression parseMultiplicativeExpression() {
Expression expression;
- if (matches(Keyword.SUPER) && _currentToken.next.type.isMultiplicativeOperator()) {
+ if (matches(Keyword.SUPER) && _currentToken.next.type.isMultiplicativeOperator) {
expression = new SuperExpression.full(andAdvance);
} else {
expression = parseUnaryExpression();
}
- while (_currentToken.type.isMultiplicativeOperator()) {
+ while (_currentToken.type.isMultiplicativeOperator) {
Token operator = andAdvance;
expression = new BinaryExpression.full(expression, operator, parseUnaryExpression());
}
@@ -3312,7 +3312,7 @@
}
}
return parseBlock();
- } else if (matches5(TokenType.KEYWORD) && !((_currentToken as KeywordToken)).keyword.isPseudoKeyword()) {
+ } else if (matches5(TokenType.KEYWORD) && !((_currentToken as KeywordToken)).keyword.isPseudoKeyword) {
Keyword keyword = ((_currentToken as KeywordToken)).keyword;
if (identical(keyword, Keyword.ASSERT)) {
return parseAssertStatement();
@@ -3442,7 +3442,7 @@
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
* @param externalKeyword the 'external' token
- * @param the return type that has already been parsed, or {@code null} if there was no return
+ * @param the return type that has already been parsed, or `null` if there was no return
* type
* @return the operator declaration that was parsed
*/
@@ -3454,7 +3454,7 @@
reportError8(ParserErrorCode.MISSING_KEYWORD_OPERATOR, _currentToken, []);
operatorKeyword = createSyntheticToken(Keyword.OPERATOR);
}
- if (!_currentToken.isUserDefinableOperator()) {
+ if (!_currentToken.isUserDefinableOperator) {
reportError7(ParserErrorCode.NON_USER_DEFINABLE_OPERATOR, [_currentToken.lexeme]);
}
SimpleIdentifier name = new SimpleIdentifier.full(andAdvance);
@@ -3475,7 +3475,7 @@
}
/**
- * Parse a return type if one is given, otherwise return {@code null} without advancing.
+ * Parse a return type if one is given, otherwise return `null` without advancing.
* @return the return type that was parsed
*/
TypeName parseOptionalReturnType() {
@@ -3543,7 +3543,7 @@
} while (matches5(TokenType.OPEN_SQUARE_BRACKET) || matches5(TokenType.PERIOD) || matches5(TokenType.OPEN_PAREN));
return operand;
}
- if (!_currentToken.type.isIncrementOperator()) {
+ if (!_currentToken.type.isIncrementOperator) {
return operand;
}
if (operand is FunctionExpressionInvocation) {
@@ -3693,7 +3693,7 @@
* @return the relational expression that was parsed
*/
Expression parseRelationalExpression() {
- if (matches(Keyword.SUPER) && _currentToken.next.type.isRelationalOperator()) {
+ if (matches(Keyword.SUPER) && _currentToken.next.type.isRelationalOperator) {
Expression expression = new SuperExpression.full(andAdvance);
Token operator = andAdvance;
expression = new BinaryExpression.full(expression, operator, parseShiftExpression());
@@ -3710,7 +3710,7 @@
notOperator = andAdvance;
}
expression = new IsExpression.full(expression, isOperator, notOperator, parseTypeName());
- } else if (_currentToken.type.isRelationalOperator()) {
+ } else if (_currentToken.type.isRelationalOperator) {
Token operator = andAdvance;
expression = new BinaryExpression.full(expression, operator, parseShiftExpression());
}
@@ -3773,8 +3773,8 @@
* @param commentAndMetadata the documentation comment and metadata to be associated with the
* declaration
* @param externalKeyword the 'external' token
- * @param staticKeyword the static keyword, or {@code null} if the setter is not static
- * @param the return type that has already been parsed, or {@code null} if there was no return
+ * @param staticKeyword the static keyword, or `null` if the setter is not static
+ * @param the return type that has already been parsed, or `null` if there was no return
* type
* @return the setter that was parsed
*/
@@ -3801,12 +3801,12 @@
*/
Expression parseShiftExpression() {
Expression expression;
- if (matches(Keyword.SUPER) && _currentToken.next.type.isShiftOperator()) {
+ if (matches(Keyword.SUPER) && _currentToken.next.type.isShiftOperator) {
expression = new SuperExpression.full(andAdvance);
} else {
expression = parseAdditiveExpression();
}
- while (_currentToken.type.isShiftOperator()) {
+ while (_currentToken.type.isShiftOperator) {
Token operator = andAdvance;
expression = new BinaryExpression.full(expression, operator, parseAdditiveExpression());
}
@@ -4256,7 +4256,7 @@
return new PrefixExpression.full(operator, new SuperExpression.full(andAdvance));
}
return new PrefixExpression.full(operator, parseUnaryExpression());
- } else if (_currentToken.type.isIncrementOperator()) {
+ } else if (_currentToken.type.isIncrementOperator) {
Token operator = andAdvance;
if (matches(Keyword.SUPER)) {
if (matches4(peek(), TokenType.OPEN_SQUARE_BRACKET) || matches4(peek(), TokenType.PERIOD)) {
@@ -4323,8 +4323,8 @@
* variableDeclarationList ::=
* finalConstVarOrType variableDeclaration (',' variableDeclaration)
* </pre>
- * @param commentAndMetadata the metadata to be associated with the variable declaration list, or{@code null} if there is no attempt at parsing the comment and metadata
- * @param keyword the token representing the 'final', 'const' or 'var' keyword, or {@code null} if
+ * @param commentAndMetadata the metadata to be associated with the variable declaration list, or`null` if there is no attempt at parsing the comment and metadata
+ * @param keyword the token representing the 'final', 'const' or 'var' keyword, or `null` if
* there is no keyword
* @param type the type of the variables in the list
* @return the variable declaration list that was parsed
@@ -4346,7 +4346,7 @@
* variableDeclarationList ';'
* </pre>
* @param commentAndMetadata the metadata to be associated with the variable declaration
- * statement, or {@code null} if there is no attempt at parsing the comment and metadata
+ * statement, or `null` if there is no attempt at parsing the comment and metadata
* @return the variable declaration statement that was parsed
*/
VariableDeclarationStatement parseVariableDeclarationStatement(CommentAndMetadata commentAndMetadata) {
@@ -4362,8 +4362,8 @@
* variableDeclarationList ';'
* </pre>
* @param commentAndMetadata the metadata to be associated with the variable declaration
- * statement, or {@code null} if there is no attempt at parsing the comment and metadata
- * @param keyword the token representing the 'final', 'const' or 'var' keyword, or {@code null} if
+ * statement, or `null` if there is no attempt at parsing the comment and metadata
+ * @param keyword the token representing the 'final', 'const' or 'var' keyword, or `null` if
* there is no keyword
* @param type the type of the variables in the list
* @return the variable declaration statement that was parsed
@@ -4416,14 +4416,14 @@
}
/**
- * Return the token that is immediately after the current token. This is equivalent to{@link #peek(int) peek(1)}.
+ * Return the token that is immediately after the current token. This is equivalent to[peek].
* @return the token that is immediately after the current token
*/
Token peek() => _currentToken.next;
/**
* Return the token that is the given distance after the current token.
- * @param distance the number of tokens to look ahead, where {@code 0} is the current token,{@code 1} is the next token, etc.
+ * @param distance the number of tokens to look ahead, where `0` is the current token,`1` is the next token, etc.
* @return the token that is the given distance after the current token
*/
Token peek2(int distance) {
@@ -4466,7 +4466,7 @@
/**
* Parse the 'final', 'const', 'var' or type preceding a variable declaration, starting at the
* given token, without actually creating a type or changing the current token. Return the token
- * following the type that was parsed, or {@code null} if the given token is not the first token
+ * following the type that was parsed, or `null` if the given token is not the first token
* in a valid type.
* <pre>
* finalConstVarOrType ::=
@@ -4498,16 +4498,16 @@
/**
* Parse a list of formal parameters, starting at the given token, without actually creating a
* formal parameter list or changing the current token. Return the token following the formal
- * parameter list that was parsed, or {@code null} if the given token is not the first token in a
+ * parameter list that was parsed, or `null` if the given token is not the first token in a
* valid list of formal parameter.
- * <p>
+ *
* Note that unlike other skip methods, this method uses a heuristic. In the worst case, the
* parameters could be prefixed by metadata, which would require us to be able to skip arbitrary
* expressions. Rather than duplicate the logic of most of the parse methods we simply look for
* something that is likely to be a list of parameters and then skip to returning the token after
* the closing parenthesis.
- * <p>
- * This method must be kept in sync with {@link #parseFormalParameterList()}.
+ *
+ * This method must be kept in sync with [parseFormalParameterList].
* <pre>
* formalParameterList ::=
* '(' ')'
@@ -4555,7 +4555,7 @@
/**
* If the given token is a begin token with an associated end token, then return the token
- * following the end token. Otherwise, return {@code null}.
+ * following the end token. Otherwise, return `null`.
* @param startToken the token that is assumed to be a being token
* @return the token following the matching end token
*/
@@ -4573,10 +4573,10 @@
/**
* Parse a prefixed identifier, starting at the given token, without actually creating a prefixed
* identifier or changing the current token. Return the token following the prefixed identifier
- * that was parsed, or {@code null} if the given token is not the first token in a valid prefixed
+ * that was parsed, or `null` if the given token is not the first token in a valid prefixed
* identifier.
- * <p>
- * This method must be kept in sync with {@link #parsePrefixedIdentifier()}.
+ *
+ * This method must be kept in sync with [parsePrefixedIdentifier].
* <pre>
* prefixedIdentifier ::=
* identifier ('.' identifier)?
@@ -4596,9 +4596,9 @@
/**
* Parse a return type, starting at the given token, without actually creating a return type or
- * changing the current token. Return the token following the return type that was parsed, or{@code null} if the given token is not the first token in a valid return type.
- * <p>
- * This method must be kept in sync with {@link #parseReturnType()}.
+ * changing the current token. Return the token following the return type that was parsed, or`null` if the given token is not the first token in a valid return type.
+ *
+ * This method must be kept in sync with [parseReturnType].
* <pre>
* returnType ::=
* 'void'
@@ -4618,10 +4618,10 @@
/**
* Parse a simple identifier, starting at the given token, without actually creating a simple
* identifier or changing the current token. Return the token following the simple identifier that
- * was parsed, or {@code null} if the given token is not the first token in a valid simple
+ * was parsed, or `null` if the given token is not the first token in a valid simple
* identifier.
- * <p>
- * This method must be kept in sync with {@link #parseSimpleIdentifier()}.
+ *
+ * This method must be kept in sync with [parseSimpleIdentifier].
* <pre>
* identifier ::=
* IDENTIFIER
@@ -4630,7 +4630,7 @@
* @return the token following the simple identifier that was parsed
*/
Token skipSimpleIdentifier(Token startToken) {
- if (matches4(startToken, TokenType.IDENTIFIER) || (matches4(startToken, TokenType.KEYWORD) && ((startToken as KeywordToken)).keyword.isPseudoKeyword())) {
+ if (matches4(startToken, TokenType.IDENTIFIER) || (matches4(startToken, TokenType.KEYWORD) && ((startToken as KeywordToken)).keyword.isPseudoKeyword)) {
return startToken.next;
}
return null;
@@ -4639,10 +4639,10 @@
/**
* Parse a string literal that contains interpolations, starting at the given token, without
* actually creating a string literal or changing the current token. Return the token following
- * the string literal that was parsed, or {@code null} if the given token is not the first token
+ * the string literal that was parsed, or `null` if the given token is not the first token
* in a valid string literal.
- * <p>
- * This method must be kept in sync with {@link #parseStringInterpolation(Token)}.
+ *
+ * This method must be kept in sync with [parseStringInterpolation].
* @param startToken the token at which parsing is to begin
* @return the string literal that was parsed
*/
@@ -4692,9 +4692,9 @@
/**
* Parse a string literal, starting at the given token, without actually creating a string literal
* or changing the current token. Return the token following the string literal that was parsed,
- * or {@code null} if the given token is not the first token in a valid string literal.
- * <p>
- * This method must be kept in sync with {@link #parseStringLiteral()}.
+ * or `null` if the given token is not the first token in a valid string literal.
+ *
+ * This method must be kept in sync with [parseStringLiteral].
* <pre>
* stringLiteral ::=
* MULTI_LINE_STRING+
@@ -4721,9 +4721,9 @@
/**
* Parse a list of type arguments, starting at the given token, without actually creating a type argument list
* or changing the current token. Return the token following the type argument list that was parsed,
- * or {@code null} if the given token is not the first token in a valid type argument list.
- * <p>
- * This method must be kept in sync with {@link #parseTypeArgumentList()}.
+ * or `null` if the given token is not the first token in a valid type argument list.
+ *
+ * This method must be kept in sync with [parseTypeArgumentList].
* <pre>
* typeArguments ::=
* '<' typeList '>'
@@ -4760,9 +4760,9 @@
/**
* Parse a type name, starting at the given token, without actually creating a type name or
- * changing the current token. Return the token following the type name that was parsed, or{@code null} if the given token is not the first token in a valid type name.
- * <p>
- * This method must be kept in sync with {@link #parseTypeName()}.
+ * changing the current token. Return the token following the type name that was parsed, or`null` if the given token is not the first token in a valid type name.
+ *
+ * This method must be kept in sync with [parseTypeName].
* <pre>
* type ::=
* qualified typeArguments?
@@ -4784,10 +4784,10 @@
/**
* Parse a list of type parameters, starting at the given token, without actually creating a type
* parameter list or changing the current token. Return the token following the type parameter
- * list that was parsed, or {@code null} if the given token is not the first token in a valid type
+ * list that was parsed, or `null` if the given token is not the first token in a valid type
* parameter list.
- * <p>
- * This method must be kept in sync with {@link #parseTypeParameterList()}.
+ *
+ * This method must be kept in sync with [parseTypeParameterList].
* <pre>
* typeParameterList ::=
* '<' typeParameter (',' typeParameter)* '>'
@@ -5199,7 +5199,7 @@
}
}
/**
- * The enumeration {@code ParserErrorCode} defines the error codes used for errors detected by the
+ * The enumeration `ParserErrorCode` defines the error codes used for errors detected by the
* parser. The convention for this class is for the name of the error code to indicate the problem
* that caused the error to be generated and for the error message to explain what is wrong and,
* when appropriate, how the problem can be corrected.
@@ -5530,7 +5530,7 @@
for (String line in StringUtils.split(token.lexeme, "\n")) {
if (firstLine) {
firstLine = false;
- if (node.isDocumentation()) {
+ if (node.isDocumentation) {
nl2();
}
} else {
@@ -5790,7 +5790,7 @@
return null;
}
Object visitIndexExpression(IndexExpression node) {
- if (node.isCascaded()) {
+ if (node.isCascaded) {
_writer.print("..");
} else {
visit(node.array);
@@ -5892,7 +5892,7 @@
visit8(node.propertyKeyword, " ");
visit8(node.operatorKeyword, " ");
visit(node.name);
- if (!node.isGetter()) {
+ if (!node.isGetter) {
visit(node.parameters);
}
if (node.body is! EmptyFunctionBody) {
@@ -5902,7 +5902,7 @@
return null;
}
Object visitMethodInvocation(MethodInvocation node) {
- if (node.isCascaded()) {
+ if (node.isCascaded) {
_writer.print("..");
} else {
visit6(node.target, ".");
@@ -5961,7 +5961,7 @@
return null;
}
Object visitPropertyAccess(PropertyAccess node) {
- if (node.isCascaded()) {
+ if (node.isCascaded) {
_writer.print("..");
} else {
visit6(node.target, ".");
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index 3a052ac..dc5fb59 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -17,7 +17,7 @@
import 'engine.dart';
import 'constant.dart';
/**
- * Instances of the class {@code CompilationUnitBuilder} build an element model for a single
+ * Instances of the class `CompilationUnitBuilder` build an element model for a single
* compilation unit.
* @coverage dart.engine.resolver
*/
@@ -49,7 +49,7 @@
}
}
/**
- * Instances of the class {@code ElementBuilder} traverse an AST structure and build the element
+ * Instances of the class `ElementBuilder` traverse an AST structure and build the element
* model representing the AST structure.
* @coverage dart.engine.resolver
*/
@@ -76,6 +76,13 @@
bool _isValidMixin = false;
/**
+ * A collection holding the function types defined in a class that need to have their type
+ * arguments set to the types of the type parameters for the class, or `null` if we are not
+ * currently processing nodes within a class.
+ */
+ List<FunctionTypeImpl> _functionTypesToFix = null;
+
+ /**
* Initialize a newly created element builder to build the elements for a compilation unit.
* @param initialHolder the element holder associated with the compilation unit being built
*/
@@ -110,12 +117,14 @@
Object visitClassDeclaration(ClassDeclaration node) {
ElementHolder holder = new ElementHolder();
_isValidMixin = true;
+ _functionTypesToFix = new List<FunctionTypeImpl>();
visitChildren(holder, node);
SimpleIdentifier className = node.name;
ClassElementImpl element = new ClassElementImpl(className);
List<TypeVariableElement> typeVariables = holder.typeVariables;
+ List<Type2> typeArguments = createTypeVariableTypes(typeVariables);
InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
- interfaceType.typeArguments = createTypeVariableTypes(typeVariables);
+ interfaceType.typeArguments = typeArguments;
element.type = interfaceType;
List<ConstructorElement> constructors = holder.constructors;
if (constructors.length == 0) {
@@ -128,12 +137,18 @@
element.methods = holder.methods;
element.typeVariables = typeVariables;
element.validMixin = _isValidMixin;
+ for (FunctionTypeImpl functionType in _functionTypesToFix) {
+ functionType.typeArguments = typeArguments;
+ }
+ _functionTypesToFix = null;
_currentHolder.addType(element);
className.element = element;
+ holder.validate();
return null;
}
Object visitClassTypeAlias(ClassTypeAlias node) {
ElementHolder holder = new ElementHolder();
+ _functionTypesToFix = new List<FunctionTypeImpl>();
visitChildren(holder, node);
SimpleIdentifier className = node.name;
ClassElementImpl element = new ClassElementImpl(className);
@@ -141,12 +156,18 @@
element.typedef = true;
List<TypeVariableElement> typeVariables = holder.typeVariables;
element.typeVariables = typeVariables;
+ List<Type2> typeArguments = createTypeVariableTypes(typeVariables);
InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
- interfaceType.typeArguments = createTypeVariableTypes(typeVariables);
+ interfaceType.typeArguments = typeArguments;
element.type = interfaceType;
element.constructors = createDefaultConstructors(interfaceType);
+ for (FunctionTypeImpl functionType in _functionTypesToFix) {
+ functionType.typeArguments = typeArguments;
+ }
+ _functionTypesToFix = null;
_currentHolder.addType(element);
className.element = element;
+ holder.validate();
return null;
}
Object visitConstructorDeclaration(ConstructorDeclaration node) {
@@ -179,6 +200,7 @@
} else {
constructorName.element = element;
}
+ holder.validate();
return null;
}
Object visitDeclaredIdentifier(DeclaredIdentifier node) {
@@ -205,15 +227,13 @@
initializer.parameters = holder.parameters;
SimpleIdentifier parameterName = node.parameter.identifier;
ParameterElementImpl parameter;
- if (node.isConst()) {
- parameter = new ConstParameterElementImpl(parameterName);
- parameter.const3 = true;
- } else if (node.parameter is FieldFormalParameter) {
- parameter = new FieldFormalParameterElementImpl(parameterName);
+ if (node.parameter is FieldFormalParameter) {
+ parameter = new DefaultFieldFormalParameterElementImpl(parameterName);
} else {
- parameter = new ParameterElementImpl(parameterName);
+ parameter = new DefaultParameterElementImpl(parameterName);
}
- parameter.final2 = node.isFinal();
+ parameter.const3 = node.isConst;
+ parameter.final2 = node.isFinal;
parameter.initializer = initializer;
parameter.parameterKind = node.kind;
Expression defaultValue = node.defaultValue;
@@ -227,6 +247,7 @@
_currentHolder.addParameter(parameter);
parameterName.element = parameter;
node.parameter.accept(this);
+ holder.validate();
return null;
}
Object visitFieldDeclaration(FieldDeclaration node) {
@@ -243,8 +264,8 @@
if (node.parent is! DefaultFormalParameter) {
SimpleIdentifier parameterName = node.identifier;
FieldFormalParameterElementImpl parameter = new FieldFormalParameterElementImpl(parameterName);
- parameter.const3 = node.isConst();
- parameter.final2 = node.isFinal();
+ parameter.const3 = node.isConst;
+ parameter.final2 = node.isFinal;
parameter.parameterKind = node.kind;
_currentHolder.addParameter(parameter);
parameterName.element = parameter;
@@ -270,8 +291,6 @@
element.labels = holder.labels;
element.localVariables = holder.localVariables;
element.parameters = holder.parameters;
- FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
- element.type = type;
_currentHolder.addFunction(element);
expression.element = element;
functionName.element = element;
@@ -314,6 +333,7 @@
propertyNameNode.element = setter;
}
}
+ holder.validate();
}
return null;
}
@@ -340,9 +360,13 @@
}
}
FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
+ if (_functionTypesToFix != null) {
+ _functionTypesToFix.add(type);
+ }
element.type = type;
_currentHolder.addFunction(element);
node.element = element;
+ holder.validate();
return null;
}
Object visitFunctionTypeAlias(FunctionTypeAlias node) {
@@ -359,6 +383,7 @@
element.type = type;
_currentHolder.addTypeAlias(element);
aliasName.element = element;
+ holder.validate();
return null;
}
Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
@@ -372,6 +397,7 @@
ElementHolder holder = new ElementHolder();
visitChildren(holder, node);
((node.element as ParameterElementImpl)).parameters = holder.parameters;
+ holder.validate();
return null;
}
Object visitLabeledStatement(LabeledStatement node) {
@@ -393,7 +419,7 @@
} finally {
_inFunction = wasInFunction;
}
- bool isStatic = node.isStatic();
+ bool isStatic = node.isStatic;
sc.Token property = node.propertyKeyword;
if (property == null) {
SimpleIdentifier methodName = node.name;
@@ -402,7 +428,7 @@
nameOfMethod = "unary-";
}
MethodElementImpl element = new MethodElementImpl.con2(nameOfMethod, methodName.offset);
- element.abstract = node.isAbstract();
+ element.abstract = node.isAbstract;
element.functions = holder.functions;
element.labels = holder.labels;
element.localVariables = holder.localVariables;
@@ -448,14 +474,15 @@
propertyNameNode.element = setter;
}
}
+ holder.validate();
return null;
}
Object visitSimpleFormalParameter(SimpleFormalParameter node) {
if (node.parent is! DefaultFormalParameter) {
SimpleIdentifier parameterName = node.identifier;
ParameterElementImpl parameter = new ParameterElementImpl(parameterName);
- parameter.const3 = node.isConst();
- parameter.final2 = node.isFinal();
+ parameter.const3 = node.isConst;
+ parameter.final2 = node.isFinal;
parameter.parameterKind = node.kind;
_currentHolder.addParameter(parameter);
parameterName.element = parameter;
@@ -554,6 +581,7 @@
initializer.localVariables = holder.localVariables;
initializer.synthetic = true;
element.initializer = initializer;
+ holder.validate();
}
if (element is PropertyInducingElementImpl) {
PropertyInducingElementImpl variable = element as PropertyInducingElementImpl;
@@ -562,13 +590,13 @@
}
PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(variable);
getter.getter = true;
- getter.static = variable.isStatic();
+ getter.static = variable.isStatic;
_currentHolder.addAccessor(getter);
variable.getter = getter;
if (!isFinal) {
PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(variable);
setter.setter = true;
- setter.static = variable.isStatic();
+ setter.static = variable.isStatic;
_currentHolder.addAccessor(setter);
variable.setter = setter;
}
@@ -577,18 +605,26 @@
}
/**
- * Creates the {@link ConstructorElement}s array with the single default constructor element.
+ * Creates the [ConstructorElement]s array with the single default constructor element.
* @param interfaceType the interface type for which to create a default constructor
- * @return the {@link ConstructorElement}s array with the single default constructor element
+ * @return the [ConstructorElement]s array with the single default constructor element
*/
List<ConstructorElement> createDefaultConstructors(InterfaceTypeImpl interfaceType) {
ConstructorElementImpl constructor = new ConstructorElementImpl(null);
constructor.synthetic = true;
+ constructor.returnType = interfaceType;
FunctionTypeImpl type = new FunctionTypeImpl.con1(constructor);
- type.returnType = interfaceType;
+ _functionTypesToFix.add(type);
constructor.type = type;
return <ConstructorElement> [constructor];
}
+
+ /**
+ * Create the types associated with the given type variables, setting the type of each type
+ * variable, and return an array of types corresponding to the given variables.
+ * @param typeVariables the type variables for which types are to be created
+ * @return
+ */
List<Type2> createTypeVariableTypes(List<TypeVariableElement> typeVariables) {
int typeVariableCount = typeVariables.length;
List<Type2> typeArguments = new List<Type2>(typeVariableCount);
@@ -602,7 +638,7 @@
}
/**
- * Return the body of the function that contains the given parameter, or {@code null} if no
+ * Return the body of the function that contains the given parameter, or `null` if no
* function body could be found.
* @param node the parameter contained in the function whose body is to be returned
* @return the body of the function that contains the given parameter
@@ -621,10 +657,10 @@
}
/**
- * Return {@code true} if the given token is a token for the given keyword.
+ * Return `true` if the given token is a token for the given keyword.
* @param token the token being tested
* @param keyword the keyword being tested for
- * @return {@code true} if the given token is a token for the given keyword
+ * @return `true` if the given token is a token for the given keyword
*/
bool matches(sc.Token token, sc.Keyword keyword2) => token != null && identical(token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).keyword, keyword2);
@@ -663,72 +699,115 @@
}
}
/**
- * Instances of the class {@code ElementHolder} hold on to elements created while traversing an AST
+ * Instances of the class `ElementHolder` hold on to elements created while traversing an AST
* structure so that they can be accessed when creating their enclosing element.
* @coverage dart.engine.resolver
*/
class ElementHolder {
- List<PropertyAccessorElement> _accessors = new List<PropertyAccessorElement>();
- List<ConstructorElement> _constructors = new List<ConstructorElement>();
- List<FieldElement> _fields = new List<FieldElement>();
- List<FunctionElement> _functions = new List<FunctionElement>();
- List<LabelElement> _labels = new List<LabelElement>();
- List<VariableElement> _localVariables = new List<VariableElement>();
- List<MethodElement> _methods = new List<MethodElement>();
- List<FunctionTypeAliasElement> _typeAliases = new List<FunctionTypeAliasElement>();
- List<ParameterElement> _parameters = new List<ParameterElement>();
- List<VariableElement> _topLevelVariables = new List<VariableElement>();
- List<ClassElement> _types = new List<ClassElement>();
- List<TypeVariableElement> _typeVariables = new List<TypeVariableElement>();
+ List<PropertyAccessorElement> _accessors;
+ List<ConstructorElement> _constructors;
+ List<FieldElement> _fields;
+ List<FunctionElement> _functions;
+ List<LabelElement> _labels;
+ List<VariableElement> _localVariables;
+ List<MethodElement> _methods;
+ List<ParameterElement> _parameters;
+ List<VariableElement> _topLevelVariables;
+ List<ClassElement> _types;
+ List<FunctionTypeAliasElement> _typeAliases;
+ List<TypeVariableElement> _typeVariables;
void addAccessor(PropertyAccessorElement element) {
+ if (_accessors == null) {
+ _accessors = new List<PropertyAccessorElement>();
+ }
_accessors.add(element);
}
void addConstructor(ConstructorElement element) {
+ if (_constructors == null) {
+ _constructors = new List<ConstructorElement>();
+ }
_constructors.add(element);
}
void addField(FieldElement element) {
+ if (_fields == null) {
+ _fields = new List<FieldElement>();
+ }
_fields.add(element);
}
void addFunction(FunctionElement element) {
+ if (_functions == null) {
+ _functions = new List<FunctionElement>();
+ }
_functions.add(element);
}
void addLabel(LabelElement element) {
+ if (_labels == null) {
+ _labels = new List<LabelElement>();
+ }
_labels.add(element);
}
void addLocalVariable(LocalVariableElement element) {
+ if (_localVariables == null) {
+ _localVariables = new List<VariableElement>();
+ }
_localVariables.add(element);
}
void addMethod(MethodElement element) {
+ if (_methods == null) {
+ _methods = new List<MethodElement>();
+ }
_methods.add(element);
}
void addParameter(ParameterElement element) {
+ if (_parameters == null) {
+ _parameters = new List<ParameterElement>();
+ }
_parameters.add(element);
}
void addTopLevelVariable(TopLevelVariableElement element) {
+ if (_topLevelVariables == null) {
+ _topLevelVariables = new List<VariableElement>();
+ }
_topLevelVariables.add(element);
}
void addType(ClassElement element) {
+ if (_types == null) {
+ _types = new List<ClassElement>();
+ }
_types.add(element);
}
void addTypeAlias(FunctionTypeAliasElement element) {
+ if (_typeAliases == null) {
+ _typeAliases = new List<FunctionTypeAliasElement>();
+ }
_typeAliases.add(element);
}
void addTypeVariable(TypeVariableElement element) {
+ if (_typeVariables == null) {
+ _typeVariables = new List<TypeVariableElement>();
+ }
_typeVariables.add(element);
}
List<PropertyAccessorElement> get accessors {
- if (_accessors.isEmpty) {
+ if (_accessors == null) {
return PropertyAccessorElementImpl.EMPTY_ARRAY;
}
- return new List.from(_accessors);
+ List<PropertyAccessorElement> result = new List.from(_accessors);
+ _accessors = null;
+ return result;
}
List<ConstructorElement> get constructors {
- if (_constructors.isEmpty) {
+ if (_constructors == null) {
return ConstructorElementImpl.EMPTY_ARRAY;
}
- return new List.from(_constructors);
+ List<ConstructorElement> result = new List.from(_constructors);
+ _constructors = null;
+ return result;
}
FieldElement getField(String fieldName) {
+ if (_fields == null) {
+ return null;
+ }
for (FieldElement field in _fields) {
if (field.name == fieldName) {
return field;
@@ -737,68 +816,175 @@
return null;
}
List<FieldElement> get fields {
- if (_fields.isEmpty) {
+ if (_fields == null) {
return FieldElementImpl.EMPTY_ARRAY;
}
- return new List.from(_fields);
+ List<FieldElement> result = new List.from(_fields);
+ _fields = null;
+ return result;
}
List<FunctionElement> get functions {
- if (_functions.isEmpty) {
+ if (_functions == null) {
return FunctionElementImpl.EMPTY_ARRAY;
}
- return new List.from(_functions);
+ List<FunctionElement> result = new List.from(_functions);
+ _functions = null;
+ return result;
}
List<LabelElement> get labels {
- if (_labels.isEmpty) {
+ if (_labels == null) {
return LabelElementImpl.EMPTY_ARRAY;
}
- return new List.from(_labels);
+ List<LabelElement> result = new List.from(_labels);
+ _labels = null;
+ return result;
}
List<LocalVariableElement> get localVariables {
- if (_localVariables.isEmpty) {
+ if (_localVariables == null) {
return LocalVariableElementImpl.EMPTY_ARRAY;
}
- return new List.from(_localVariables);
+ List<LocalVariableElement> result = new List.from(_localVariables);
+ _localVariables = null;
+ return result;
}
List<MethodElement> get methods {
- if (_methods.isEmpty) {
+ if (_methods == null) {
return MethodElementImpl.EMPTY_ARRAY;
}
- return new List.from(_methods);
+ List<MethodElement> result = new List.from(_methods);
+ _methods = null;
+ return result;
}
List<ParameterElement> get parameters {
- if (_parameters.isEmpty) {
+ if (_parameters == null) {
return ParameterElementImpl.EMPTY_ARRAY;
}
- return new List.from(_parameters);
+ List<ParameterElement> result = new List.from(_parameters);
+ _parameters = null;
+ return result;
}
List<TopLevelVariableElement> get topLevelVariables {
- if (_topLevelVariables.isEmpty) {
+ if (_topLevelVariables == null) {
return TopLevelVariableElementImpl.EMPTY_ARRAY;
}
- return new List.from(_topLevelVariables);
+ List<TopLevelVariableElement> result = new List.from(_topLevelVariables);
+ _topLevelVariables = null;
+ return result;
}
List<FunctionTypeAliasElement> get typeAliases {
- if (_typeAliases.isEmpty) {
+ if (_typeAliases == null) {
return FunctionTypeAliasElementImpl.EMPTY_ARRAY;
}
- return new List.from(_typeAliases);
+ List<FunctionTypeAliasElement> result = new List.from(_typeAliases);
+ _typeAliases = null;
+ return result;
}
List<ClassElement> get types {
- if (_types.isEmpty) {
+ if (_types == null) {
return ClassElementImpl.EMPTY_ARRAY;
}
- return new List.from(_types);
+ List<ClassElement> result = new List.from(_types);
+ _types = null;
+ return result;
}
List<TypeVariableElement> get typeVariables {
- if (_typeVariables.isEmpty) {
+ if (_typeVariables == null) {
return TypeVariableElementImpl.EMPTY_ARRAY;
}
- return new List.from(_typeVariables);
+ List<TypeVariableElement> result = new List.from(_typeVariables);
+ _typeVariables = null;
+ return result;
+ }
+ void validate() {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ if (_accessors != null) {
+ builder.append(_accessors.length);
+ builder.append(" accessors");
+ }
+ if (_constructors != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_constructors.length);
+ builder.append(" constructors");
+ }
+ if (_fields != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_fields.length);
+ builder.append(" fields");
+ }
+ if (_functions != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_functions.length);
+ builder.append(" functions");
+ }
+ if (_labels != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_labels.length);
+ builder.append(" labels");
+ }
+ if (_localVariables != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_localVariables.length);
+ builder.append(" local variables");
+ }
+ if (_methods != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_methods.length);
+ builder.append(" methods");
+ }
+ if (_parameters != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_parameters.length);
+ builder.append(" parameters");
+ }
+ if (_topLevelVariables != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_topLevelVariables.length);
+ builder.append(" top-level variables");
+ }
+ if (_types != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_types.length);
+ builder.append(" types");
+ }
+ if (_typeAliases != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_typeAliases.length);
+ builder.append(" type aliases");
+ }
+ if (_typeVariables != null) {
+ if (builder.length > 0) {
+ builder.append("; ");
+ }
+ builder.append(_typeVariables.length);
+ builder.append(" type variables");
+ }
+ if (builder.length > 0) {
+ AnalysisEngine.instance.logger.logError("Failed to capture elements: ${builder.toString()}");
+ }
}
}
/**
- * Instances of the class {@code HtmlUnitBuilder} build an element model for a single HTML unit.
+ * Instances of the class `HtmlUnitBuilder` build an element model for a single HTML unit.
*/
class HtmlUnitBuilder implements ht.XmlVisitor<Object> {
static String _APPLICATION_DART_IN_DOUBLE_QUOTES = "\"application/dart\"";
@@ -818,7 +1004,7 @@
RecordingErrorListener _errorListener;
/**
- * The line information associated with the source for which an element is being built, or{@code null} if we are not building an element.
+ * The line information associated with the source for which an element is being built, or`null` if we are not building an element.
*/
LineInfo _lineInfo;
@@ -977,7 +1163,7 @@
}
/**
- * Return the first source attribute for the given tag node, or {@code null} if it does not exist.
+ * Return the first source attribute for the given tag node, or `null` if it does not exist.
* @param node the node containing attributes
* @return the source attribute contained in the given tag
*/
@@ -992,8 +1178,8 @@
/**
* Determine if the specified node is a Dart script.
- * @param node the node to be tested (not {@code null})
- * @return {@code true} if the node is a Dart script
+ * @param node the node to be tested (not `null`)
+ * @return `true` if the node is a Dart script
*/
bool isScriptNode(ht.XmlTagNode node) {
if (node.tagNodes.length != 0 || node.tag.lexeme != _SCRIPT) {
@@ -1026,7 +1212,7 @@
}
}
/**
- * Instances of the class {@code DeclarationResolver} are used to resolve declarations in an AST
+ * Instances of the class `DeclarationResolver` are used to resolve declarations in an AST
* structure to already built elements.
*/
class DeclarationResolver extends RecursiveASTVisitor<Object> {
@@ -1037,25 +1223,25 @@
CompilationUnitElement _enclosingUnit;
/**
- * The function type alias containing the AST nodes being visited, or {@code null} if we are not
+ * The function type alias containing the AST nodes being visited, or `null` if we are not
* in the scope of a function type alias.
*/
FunctionTypeAliasElement _enclosingAlias;
/**
- * The class containing the AST nodes being visited, or {@code null} if we are not in the scope of
+ * The class containing the AST nodes being visited, or `null` if we are not in the scope of
* a class.
*/
ClassElement _enclosingClass;
/**
- * The method or function containing the AST nodes being visited, or {@code null} if we are not in
+ * The method or function containing the AST nodes being visited, or `null` if we are not in
* the scope of a method or function.
*/
ExecutableElement _enclosingExecutable;
/**
- * The parameter containing the AST nodes being visited, or {@code null} if we are not in the
+ * The parameter containing the AST nodes being visited, or `null` if we are not in the
* scope of a parameter.
*/
ParameterElement _enclosingParameter;
@@ -1401,7 +1587,7 @@
}
/**
- * Return the element for the part with the given source, or {@code null} if there is no element
+ * Return the element for the part with the given source, or `null` if there is no element
* for the given source.
* @param parts the elements for the parts
* @param partSource the source for the part whose element is to be returned
@@ -1456,7 +1642,7 @@
}
/**
- * Return the export element from the given array whose library has the given source, or{@code null} if there is no such export.
+ * Return the export element from the given array whose library has the given source, or`null` if there is no such export.
* @param exports the export elements being searched
* @param source the source of the library associated with the export element to being searched
* for
@@ -1473,7 +1659,7 @@
/**
* Return the import element from the given array whose library has the given source and that has
- * the given prefix, or {@code null} if there is no such import.
+ * the given prefix, or `null` if there is no such import.
* @param imports the import elements being searched
* @param source the source of the library associated with the import element to being searched
* for
@@ -1499,7 +1685,7 @@
}
/**
- * Return the value of the given string literal, or {@code null} if the string is not a constant
+ * Return the value of the given string literal, or `null` if the string is not a constant
* string without any string interpolation.
* @param literal the string literal whose value is to be returned
* @return the value of the given string literal
@@ -1518,45 +1704,45 @@
}
}
/**
- * Instances of the class {@code ElementResolver} are used by instances of {@link ResolverVisitor}to resolve references within the AST structure to the elements being referenced. The requirements
+ * Instances of the class `ElementResolver` are used by instances of [ResolverVisitor]to resolve references within the AST structure to the elements being referenced. The requirements
* for the element resolver are:
* <ol>
- * <li>Every {@link SimpleIdentifier} should be resolved to the element to which it refers.
+ * * Every [SimpleIdentifier] should be resolved to the element to which it refers.
* Specifically:
- * <ul>
- * <li>An identifier within the declaration of that name should resolve to the element being
- * declared.</li>
- * <li>An identifier denoting a prefix should resolve to the element representing the import that
- * defines the prefix (an {@link ImportElement}).</li>
- * <li>An identifier denoting a variable should resolve to the element representing the variable (a{@link VariableElement}).</li>
- * <li>An identifier denoting a parameter should resolve to the element representing the parameter
- * (a {@link ParameterElement}).</li>
- * <li>An identifier denoting a field should resolve to the element representing the getter or
- * setter being invoked (a {@link PropertyAccessorElement}).</li>
- * <li>An identifier denoting the name of a method or function being invoked should resolve to the
- * element representing the method or function (a {@link ExecutableElement}).</li>
- * <li>An identifier denoting a label should resolve to the element representing the label (a{@link LabelElement}).</li>
- * </ul>
- * The identifiers within directives are exceptions to this rule and are covered below.</li>
- * <li>Every node containing a token representing an operator that can be overridden ({@link BinaryExpression}, {@link PrefixExpression}, {@link PostfixExpression}) should resolve to
- * the element representing the method invoked by that operator (a {@link MethodElement}).</li>
- * <li>Every {@link FunctionExpressionInvocation} should resolve to the element representing the
- * function being invoked (a {@link FunctionElement}). This will be the same element as that to
+ *
+ * * An identifier within the declaration of that name should resolve to the element being
+ * declared.
+ * * An identifier denoting a prefix should resolve to the element representing the import that
+ * defines the prefix (an [ImportElement]).
+ * * An identifier denoting a variable should resolve to the element representing the variable (a[VariableElement]).
+ * * An identifier denoting a parameter should resolve to the element representing the parameter
+ * (a [ParameterElement]).
+ * * An identifier denoting a field should resolve to the element representing the getter or
+ * setter being invoked (a [PropertyAccessorElement]).
+ * * An identifier denoting the name of a method or function being invoked should resolve to the
+ * element representing the method or function (a [ExecutableElement]).
+ * * An identifier denoting a label should resolve to the element representing the label (a[LabelElement]).
+ *
+ * The identifiers within directives are exceptions to this rule and are covered below.
+ * * Every node containing a token representing an operator that can be overridden ([BinaryExpression], [PrefixExpression], [PostfixExpression]) should resolve to
+ * the element representing the method invoked by that operator (a [MethodElement]).
+ * * Every [FunctionExpressionInvocation] should resolve to the element representing the
+ * function being invoked (a [FunctionElement]). This will be the same element as that to
* which the name is resolved if the function has a name, but is provided for those cases where an
- * unnamed function is being invoked.</li>
- * <li>Every {@link LibraryDirective} and {@link PartOfDirective} should resolve to the element
- * representing the library being specified by the directive (a {@link LibraryElement}) unless, in
- * the case of a part-of directive, the specified library does not exist.</li>
- * <li>Every {@link ImportDirective} and {@link ExportDirective} should resolve to the element
+ * unnamed function is being invoked.
+ * * Every [LibraryDirective] and [PartOfDirective] should resolve to the element
+ * representing the library being specified by the directive (a [LibraryElement]) unless, in
+ * the case of a part-of directive, the specified library does not exist.
+ * * Every [ImportDirective] and [ExportDirective] should resolve to the element
* representing the library being specified by the directive unless the specified library does not
- * exist (an {@link ImportElement} or {@link ExportElement}).</li>
- * <li>The identifier representing the prefix in an {@link ImportDirective} should resolve to the
- * element representing the prefix (a {@link PrefixElement}).</li>
- * <li>The identifiers in the hide and show combinators in {@link ImportDirective}s and{@link ExportDirective}s should resolve to the elements that are being hidden or shown,
+ * exist (an [ImportElement] or [ExportElement]).
+ * * The identifier representing the prefix in an [ImportDirective] should resolve to the
+ * element representing the prefix (a [PrefixElement]).
+ * * The identifiers in the hide and show combinators in [ImportDirective]s and[ExportDirective]s should resolve to the elements that are being hidden or shown,
* respectively, unless those names are not defined in the specified library (or the specified
- * library does not exist).</li>
- * <li>Every {@link PartDirective} should resolve to the element representing the compilation unit
- * being specified by the string unless the specified compilation unit does not exist (a{@link CompilationUnitElement}).</li>
+ * library does not exist).
+ * * Every [PartDirective] should resolve to the element representing the compilation unit
+ * being specified by the string unless the specified compilation unit does not exist (a[CompilationUnitElement]).
* </ol>
* Note that AST nodes that would represent elements that are not defined are not resolved to
* anything. This includes such things as references to undeclared variables (which is an error) and
@@ -1567,7 +1753,7 @@
class ElementResolver extends SimpleASTVisitor<Object> {
/**
- * @return {@code true} if the given identifier is the return type of a constructor declaration.
+ * @return `true` if the given identifier is the return type of a constructor declaration.
*/
static bool isConstructorReturnType(SimpleIdentifier node) {
ASTNode parent = node.parent;
@@ -1579,7 +1765,7 @@
}
/**
- * @return {@code true} if the given identifier is the return type of a factory constructor
+ * @return `true` if the given identifier is the return type of a factory constructor
* declaration.
*/
static bool isFactoryConstructorReturnType(SimpleIdentifier node) {
@@ -1594,7 +1780,7 @@
/**
* Checks if the given 'super' expression is used in the valid context.
* @param node the 'super' expression to analyze
- * @return {@code true} if the given 'super' expression is in the valid context
+ * @return `true` if the given 'super' expression is in the valid context
*/
static bool isSuperInValidContext(SuperExpression node) {
for (ASTNode n = node; n != null; n = n.parent) {
@@ -1610,7 +1796,7 @@
}
if (n is MethodDeclaration) {
MethodDeclaration method = n as MethodDeclaration;
- return !method.isStatic();
+ return !method.isStatic;
}
}
return false;
@@ -1660,7 +1846,7 @@
node.staticElement = staticMethod;
Type2 propagatedType = getPropagatedType(leftHandSide);
MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedType, methodName);
- node.element = select3(staticMethod, propagatedMethod);
+ node.element = select2(staticMethod, propagatedMethod);
if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
_resolver.reportError6(StaticTypeWarningCode.UNDEFINED_METHOD, operator, [methodName, staticType.displayName]);
}
@@ -1670,7 +1856,7 @@
}
Object visitBinaryExpression(BinaryExpression node) {
sc.Token operator = node.operator;
- if (operator.isUserDefinableOperator()) {
+ if (operator.isUserDefinableOperator) {
Expression leftOperand = node.leftOperand;
if (leftOperand != null) {
String methodName = operator.lexeme;
@@ -1679,7 +1865,7 @@
node.staticElement = staticMethod;
Type2 propagatedType = getPropagatedType(leftOperand);
MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedType, methodName);
- node.element = select3(staticMethod, propagatedMethod);
+ node.element = select2(staticMethod, propagatedMethod);
if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
_resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
}
@@ -1690,7 +1876,7 @@
Object visitBreakStatement(BreakStatement node) {
SimpleIdentifier labelNode = node.label;
LabelElementImpl labelElement = lookupLabel(node, labelNode);
- if (labelElement != null && labelElement.isOnSwitchMember()) {
+ if (labelElement != null && labelElement.isOnSwitchMember) {
_resolver.reportError(ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, labelNode, []);
}
return null;
@@ -1716,7 +1902,7 @@
}
if (element == null) {
} else {
- if (element.library != _resolver.definingLibrary) {
+ if (element.library == null || element.library != _resolver.definingLibrary) {
}
recordResolution(simpleIdentifier, element);
if (node.newKeyword != null) {
@@ -1803,21 +1989,21 @@
ClassElement enclosingClass = _resolver.enclosingClass;
FieldElement fieldElement = ((enclosingClass as ClassElementImpl)).getField(fieldName.name);
recordResolution(fieldName, fieldElement);
- if (fieldElement == null || fieldElement.isSynthetic()) {
+ if (fieldElement == null || fieldElement.isSynthetic) {
_resolver.reportError(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTANT_FIELD, node, [fieldName]);
- } else if (fieldElement.isStatic()) {
+ } else if (fieldElement.isStatic) {
_resolver.reportError(CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, node, [fieldName]);
}
return null;
}
Object visitConstructorName(ConstructorName node) {
Type2 type = node.type.type;
- if (type != null && type.isDynamic()) {
+ if (type != null && type.isDynamic) {
return null;
} else if (type is! InterfaceType) {
ASTNode parent = node.parent;
if (parent is InstanceCreationExpression) {
- if (((parent as InstanceCreationExpression)).isConst()) {
+ if (((parent as InstanceCreationExpression)).isConst) {
} else {
}
} else {
@@ -1842,7 +2028,7 @@
Object visitContinueStatement(ContinueStatement node) {
SimpleIdentifier labelNode = node.label;
LabelElementImpl labelElement = lookupLabel(node, labelNode);
- if (labelElement != null && labelElement.isOnSwitchStatement()) {
+ if (labelElement != null && labelElement.isOnSwitchStatement) {
_resolver.reportError(ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, labelNode, []);
}
return null;
@@ -1876,17 +2062,17 @@
if (node.type == null) {
fieldFormal.type = fieldType;
}
- if (fieldElement.isSynthetic()) {
+ if (fieldElement.isSynthetic) {
_resolver.reportError(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD, node, [fieldName]);
- } else if (fieldElement.isStatic()) {
+ } else if (fieldElement.isStatic) {
_resolver.reportError(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD, node, [fieldName]);
} else if (declaredType != null && fieldType != null && !declaredType.isAssignableTo(fieldType)) {
_resolver.reportError(StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE, node, [declaredType.displayName, fieldType.displayName]);
}
} else {
- if (fieldElement.isSynthetic()) {
+ if (fieldElement.isSynthetic) {
_resolver.reportError(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD, node, [fieldName]);
- } else if (fieldElement.isStatic()) {
+ } else if (fieldElement.isStatic) {
_resolver.reportError(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD, node, [fieldName]);
}
}
@@ -1947,7 +2133,7 @@
node.staticElement = invokedConstructor;
node.element = invokedConstructor;
ArgumentList argumentList = node.argumentList;
- List<ParameterElement> parameters = resolveArgumentsToParameters(node.isConst(), argumentList, invokedConstructor);
+ List<ParameterElement> parameters = resolveArgumentsToParameters(node.isConst, argumentList, invokedConstructor);
if (parameters != null) {
argumentList.correspondingStaticParameters = parameters;
}
@@ -1993,20 +2179,7 @@
argumentList.correspondingParameters = parameters;
}
}
- ErrorCode errorCode;
- if (staticElement == null) {
- if (propagatedElement == null) {
- errorCode = checkForInvocationError(target, staticElement);
- } else {
- errorCode = checkForInvocationError(target, propagatedElement);
- }
- } else {
- errorCode = checkForInvocationError(target, staticElement);
- if (propagatedElement != null) {
- ErrorCode propagatedError = checkForInvocationError(target, propagatedElement);
- errorCode = select(errorCode, propagatedError);
- }
- }
+ ErrorCode errorCode = checkForInvocationError(target, staticElement);
if (identical(errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) {
_resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName, [methodName.name]);
} else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
@@ -2050,7 +2223,7 @@
node.staticElement = staticMethod;
Type2 propagatedType = getPropagatedType(operand);
MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName);
- node.element = select3(staticMethod, propagatedMethod);
+ node.element = select2(staticMethod, propagatedMethod);
if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
_resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [methodName, staticType.displayName]);
}
@@ -2083,7 +2256,7 @@
Object visitPrefixExpression(PrefixExpression node) {
sc.Token operator = node.operator;
sc.TokenType operatorType = operator.type;
- if (operatorType.isUserDefinableOperator() || identical(operatorType, sc.TokenType.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) {
+ if (operatorType.isUserDefinableOperator || identical(operatorType, sc.TokenType.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) {
Expression operand = node.operand;
String methodName = getPrefixOperator(node);
Type2 staticType = getStaticType(operand);
@@ -2091,7 +2264,7 @@
node.staticElement = staticMethod;
Type2 propagatedType = getPropagatedType(operand);
MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName);
- node.element = select3(staticMethod, propagatedMethod);
+ node.element = select2(staticMethod, propagatedMethod);
if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
_resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
}
@@ -2175,7 +2348,7 @@
}
return null;
} else {
- if (element.isFactory()) {
+ if (element.isFactory) {
_resolver.reportError(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node, [element]);
}
}
@@ -2230,8 +2403,8 @@
/**
* Given that we have found code to invoke the given element, return the error code that should be
- * reported, or {@code null} if no error should be reported.
- * @param target the target of the invocation, or {@code null} if there was no target
+ * reported, or `null` if no error should be reported.
+ * @param target the target of the invocation, or `null` if there was no target
* @param element the element to be invoked
* @return the error code that should be reported
*/
@@ -2282,7 +2455,7 @@
Type2 targetType = getStaticType(target);
if (targetType == null) {
return StaticTypeWarningCode.UNDEFINED_FUNCTION;
- } else if (!targetType.isDynamic() && !classDeclaresNoSuchMethod2(targetType.element)) {
+ } else if (!targetType.isDynamic && !classDeclaresNoSuchMethod2(targetType.element)) {
return StaticTypeWarningCode.UNDEFINED_METHOD;
}
}
@@ -2292,10 +2465,10 @@
}
/**
- * Return {@code true} if the given class declares a method named "noSuchMethod" and is not the
+ * Return `true` if the given class declares a method named "noSuchMethod" and is not the
* class 'Object'.
* @param element the class being tested
- * @return {@code true} if the given class declares a method named "noSuchMethod"
+ * @return `true` if the given class declares a method named "noSuchMethod"
*/
bool classDeclaresNoSuchMethod(ClassElement classElement) {
if (classElement == null) {
@@ -2306,10 +2479,10 @@
}
/**
- * Return {@code true} if the given element represents a class that declares a method named
+ * Return `true` if the given element represents a class that declares a method named
* "noSuchMethod" and is not the class 'Object'.
* @param element the element being tested
- * @return {@code true} if the given element represents a class that declares a method named
+ * @return `true` if the given element represents a class that declares a method named
* "noSuchMethod"
*/
bool classDeclaresNoSuchMethod2(Element element) {
@@ -2322,7 +2495,7 @@
/**
* Given a list of arguments and the element that will be invoked using those argument, compute
* the list of parameters that correspond to the list of arguments. Return the parameters that
- * correspond to the arguments, or {@code null} if no correspondence could be computed.
+ * correspond to the arguments, or `null` if no correspondence could be computed.
* @param argumentList the list of arguments being passed to the element
* @param executableElement the element that will be invoked with the arguments
* @return the parameters that correspond to the arguments
@@ -2379,7 +2552,7 @@
/**
* Look for any declarations of the given identifier that are imported using a prefix. Return the
- * element that was found, or {@code null} if the name is not imported using a prefix.
+ * element that was found, or `null` if the name is not imported using a prefix.
* @param identifier the identifier that might have been imported using a prefix
* @return the element that was found
*/
@@ -2473,13 +2646,13 @@
}
/**
- * Return {@code true} if the given type represents an object that could be invoked using the call
+ * Return `true` if the given type represents an object that could be invoked using the call
* operator '()'.
* @param type the type being tested
- * @return {@code true} if the given type represents an object that could be invoked
+ * @return `true` if the given type represents an object that could be invoked
*/
bool isExecutableType(Type2 type) {
- if (type.isDynamic() || (type is FunctionType) || type.isDartCoreFunction()) {
+ if (type.isDynamic || (type is FunctionType) || type.isDartCoreFunction) {
return true;
} else if (type is InterfaceType) {
ClassElement classElement = ((type as InterfaceType)).element;
@@ -2490,32 +2663,32 @@
}
/**
- * Return {@code true} if the given element is a static element.
+ * Return `true` if the given element is a static element.
* @param element the element being tested
- * @return {@code true} if the given element is a static element
+ * @return `true` if the given element is a static element
*/
bool isStatic(Element element) {
if (element is ExecutableElement) {
- return ((element as ExecutableElement)).isStatic();
+ return ((element as ExecutableElement)).isStatic;
} else if (element is PropertyInducingElement) {
- return ((element as PropertyInducingElement)).isStatic();
+ return ((element as PropertyInducingElement)).isStatic;
}
return false;
}
/**
- * Looks up the method element with the given name for index expression, reports{@link StaticWarningCode#UNDEFINED_OPERATOR} if not found.
+ * Looks up the method element with the given name for index expression, reports[StaticWarningCode#UNDEFINED_OPERATOR] if not found.
* @param node the index expression to resolve
* @param target the target of the expression
* @param methodName the name of the operator associated with the context of using of the given
* index expression
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
*/
bool lookUpCheckIndexOperator(IndexExpression node, Expression target, String methodName, Type2 staticType, Type2 propagatedType) {
MethodElement staticMethod = lookUpMethod(target, staticType, methodName);
MethodElement propagatedMethod = lookUpMethod(target, propagatedType, methodName);
node.staticElement = staticMethod;
- node.element = select3(staticMethod, propagatedMethod);
+ node.element = select2(staticMethod, propagatedMethod);
if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) {
sc.Token leftBracket = node.leftBracket;
sc.Token rightBracket = node.rightBracket;
@@ -2534,8 +2707,8 @@
/**
* Look up the getter with the given name in the given type. Return the element representing the
- * getter that was found, or {@code null} if there is no getter with the given name.
- * @param target the target of the invocation, or {@code null} if there is no target
+ * getter that was found, or `null` if there is no getter with the given name.
+ * @param target the target of the invocation, or `null` if there is no target
* @param type the type in which the getter is defined
* @param getterName the name of the getter being looked up
* @return the element representing the getter that was found
@@ -2560,9 +2733,9 @@
/**
* Look up the getter with the given name in the interfaces implemented by the given type, either
- * directly or indirectly. Return the element representing the getter that was found, or{@code null} if there is no getter with the given name.
+ * directly or indirectly. Return the element representing the getter that was found, or`null` if there is no getter with the given name.
* @param targetType the type in which the getter might be defined
- * @param includeTargetType {@code true} if the search should include the target type
+ * @param includeTargetType `true` if the search should include the target type
* @param getterName the name of the getter being looked up
* @param visitedInterfaces a set containing all of the interfaces that have been examined, used
* to prevent infinite recursion and to optimize the search
@@ -2601,7 +2774,7 @@
/**
* Look up the method or getter with the given name in the given type. Return the element
- * representing the method or getter that was found, or {@code null} if there is no method or
+ * representing the method or getter that was found, or `null` if there is no method or
* getter with the given name.
* @param type the type in which the method or getter is defined
* @param memberName the name of the method or getter being looked up
@@ -2627,9 +2800,9 @@
/**
* Look up the method or getter with the given name in the interfaces implemented by the given
* type, either directly or indirectly. Return the element representing the method or getter that
- * was found, or {@code null} if there is no method or getter with the given name.
+ * was found, or `null` if there is no method or getter with the given name.
* @param targetType the type in which the method or getter might be defined
- * @param includeTargetType {@code true} if the search should include the target type
+ * @param includeTargetType `true` if the search should include the target type
* @param memberName the name of the method or getter being looked up
* @param visitedInterfaces a set containing all of the interfaces that have been examined, used
* to prevent infinite recursion and to optimize the search
@@ -2711,8 +2884,8 @@
/**
* Look up the method with the given name in the given type. Return the element representing the
- * method that was found, or {@code null} if there is no method with the given name.
- * @param target the target of the invocation, or {@code null} if there is no target
+ * method that was found, or `null` if there is no method with the given name.
+ * @param target the target of the invocation, or `null` if there is no target
* @param type the type in which the method is defined
* @param methodName the name of the method being looked up
* @return the element representing the method that was found
@@ -2737,9 +2910,9 @@
/**
* Look up the method with the given name in the interfaces implemented by the given type, either
- * directly or indirectly. Return the element representing the method that was found, or{@code null} if there is no method with the given name.
+ * directly or indirectly. Return the element representing the method that was found, or`null` if there is no method with the given name.
* @param targetType the type in which the member might be defined
- * @param includeTargetType {@code true} if the search should include the target type
+ * @param includeTargetType `true` if the search should include the target type
* @param methodName the name of the method being looked up
* @param visitedInterfaces a set containing all of the interfaces that have been examined, used
* to prevent infinite recursion and to optimize the search
@@ -2778,8 +2951,8 @@
/**
* Look up the setter with the given name in the given type. Return the element representing the
- * setter that was found, or {@code null} if there is no setter with the given name.
- * @param target the target of the invocation, or {@code null} if there is no target
+ * setter that was found, or `null` if there is no setter with the given name.
+ * @param target the target of the invocation, or `null` if there is no target
* @param type the type in which the setter is defined
* @param setterName the name of the setter being looked up
* @return the element representing the setter that was found
@@ -2804,9 +2977,9 @@
/**
* Look up the setter with the given name in the interfaces implemented by the given type, either
- * directly or indirectly. Return the element representing the setter that was found, or{@code null} if there is no setter with the given name.
+ * directly or indirectly. Return the element representing the setter that was found, or`null` if there is no setter with the given name.
* @param targetType the type in which the setter might be defined
- * @param includeTargetType {@code true} if the search should include the target type
+ * @param includeTargetType `true` if the search should include the target type
* @param setterName the name of the setter being looked up
* @param visitedInterfaces a set containing all of the interfaces that have been examined, used
* to prevent infinite recursion and to optimize the search
@@ -2906,8 +3079,8 @@
/**
* Given a list of arguments and the element that will be invoked using those argument, compute
* the list of parameters that correspond to the list of arguments. Return the parameters that
- * correspond to the arguments, or {@code null} if no correspondence could be computed.
- * @param reportError if {@code true} then compile-time error should be reported; if {@code false}then compile-time warning
+ * correspond to the arguments, or `null` if no correspondence could be computed.
+ * @param reportError if `true` then compile-time error should be reported; if `false`then compile-time warning
* @param argumentList the list of arguments being passed to the element
* @param executableElement the element that will be invoked with the arguments
* @return the parameters that correspond to the arguments
@@ -2924,7 +3097,7 @@
* Given a list of arguments and the parameters related to the element that will be invoked using
* those argument, compute the list of parameters that correspond to the list of arguments. Return
* the parameters that correspond to the arguments.
- * @param reportError if {@code true} then compile-time error should be reported; if {@code false}then compile-time warning
+ * @param reportError if `true` then compile-time error should be reported; if `false`then compile-time warning
* @param argumentList the list of arguments being passed to the element
* @param parameters the of the function that will be invoked with the arguments
* @return the parameters that correspond to the arguments
@@ -3093,7 +3266,7 @@
propertyName.staticElement = staticElement;
Type2 propagatedType = getPropagatedType(target);
ExecutableElement propagatedElement = resolveProperty(target, propagatedType, propertyName);
- Element selectedElement = select2(staticElement, propagatedElement);
+ Element selectedElement = select(staticElement, propagatedElement);
propertyName.element = selectedElement;
if (shouldReportMissingMember(staticType, staticElement) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedElement))) {
bool staticNoSuchMethod = staticType != null && classDeclaresNoSuchMethod2(staticType.element);
@@ -3121,7 +3294,7 @@
/**
* Resolve the given simple identifier if possible. Return the element to which it could be
- * resolved, or {@code null} if it could not be resolved. This does not record the results of the
+ * resolved, or `null` if it could not be resolved. This does not record the results of the
* resolution.
* @param node the identifier to be resolved
* @return the element to which the identifier could be resolved
@@ -3180,35 +3353,20 @@
}
/**
- * Given two possible error codes for the same piece of code, one computed using static type
- * information and the other using propagated type information, return the error code that should
- * be reported, or {@code null} if no error should be reported.
- * @param staticError the error code computed using static type information
- * @param propagatedError the error code computed using propagated type information
- * @return the error code that should be reported
- */
- ErrorCode select(ErrorCode staticError, ErrorCode propagatedError) {
- if (staticError == null || propagatedError == null) {
- return null;
- }
- return propagatedError;
- }
-
- /**
- * Return the propagated element if it is not {@code null}, or the static element if it is.
+ * Return the propagated element if it is not `null`, or the static element if it is.
* @param staticElement the element computed using static type information
* @param propagatedElement the element computed using propagated type information
* @return the more specific of the two elements
*/
- ExecutableElement select2(ExecutableElement staticElement, ExecutableElement propagatedElement) => propagatedElement != null ? propagatedElement : staticElement;
+ ExecutableElement select(ExecutableElement staticElement, ExecutableElement propagatedElement) => propagatedElement != null ? propagatedElement : staticElement;
/**
- * Return the propagated method if it is not {@code null}, or the static method if it is.
+ * Return the propagated method if it is not `null`, or the static method if it is.
* @param staticMethod the method computed using static type information
* @param propagatedMethod the method computed using propagated type information
* @return the more specific of the two methods
*/
- MethodElement select3(MethodElement staticMethod, MethodElement propagatedMethod) => propagatedMethod != null ? propagatedMethod : staticMethod;
+ MethodElement select2(MethodElement staticMethod, MethodElement propagatedMethod) => propagatedMethod != null ? propagatedMethod : staticMethod;
/**
* Given a node that can have annotations associated with it and the element to which that node
@@ -3240,14 +3398,14 @@
}
/**
- * Return {@code true} if we should report an error as a result of looking up a member in the
+ * Return `true` if we should report an error as a result of looking up a member in the
* given type and not finding any member.
* @param type the type in which we attempted to perform the look-up
* @param member the result of the look-up
- * @return {@code true} if we should report an error
+ * @return `true` if we should report an error
*/
bool shouldReportMissingMember(Type2 type, ExecutableElement member) {
- if (member != null || type == null || type.isDynamic()) {
+ if (member != null || type == null || type.isDynamic) {
return false;
}
if (type is InterfaceType) {
@@ -3257,7 +3415,7 @@
}
}
/**
- * Instances of the class {@code SyntheticIdentifier} implement an identifier that can be used to
+ * Instances of the class `SyntheticIdentifier` implement an identifier that can be used to
* look up names in the lexical scope when there is no identifier in the AST structure. There is
* no identifier in the AST when the parser could not distinguish between a method invocation and
* an invocation of a top-level function imported with a prefix.
@@ -3286,31 +3444,31 @@
}
}
/**
- * Instances of the class {@code InheritanceManager} manage the knowledge of where class members
+ * Instances of the class `InheritanceManager` manage the knowledge of where class members
* (methods, getters & setters) are inherited from.
* @coverage dart.engine.resolver
*/
class InheritanceManager {
/**
- * The {@link LibraryElement} that is managed by this manager.
+ * The [LibraryElement] that is managed by this manager.
*/
LibraryElement _library;
/**
- * This is a mapping between each {@link ClassElement} and a map between the {@link String} member
- * names and the associated {@link ExecutableElement} in the mixin and superclass chain.
+ * This is a mapping between each [ClassElement] and a map between the [String] member
+ * names and the associated [ExecutableElement] in the mixin and superclass chain.
*/
Map<ClassElement, Map<String, ExecutableElement>> _classLookup;
/**
- * This is a mapping between each {@link ClassElement} and a map between the {@link String} member
- * names and the associated {@link ExecutableElement} in the interface set.
+ * This is a mapping between each [ClassElement] and a map between the [String] member
+ * names and the associated [ExecutableElement] in the interface set.
*/
Map<ClassElement, Map<String, ExecutableElement>> _interfaceLookup;
/**
- * A map between each visited {@link ClassElement} and the set of {@link AnalysisError}s found on
+ * A map between each visited [ClassElement] and the set of [AnalysisError]s found on
* the class element.
*/
Map<ClassElement, Set<AnalysisError>> _errorsInClassElement = new Map<ClassElement, Set<AnalysisError>>();
@@ -3326,35 +3484,35 @@
}
/**
- * Return the set of {@link AnalysisError}s found on the passed {@link ClassElement}, or{@code null} if there are none.
+ * Return the set of [AnalysisError]s found on the passed [ClassElement], or`null` if there are none.
* @param classElt the class element to query
- * @return the set of {@link AnalysisError}s found on the passed {@link ClassElement}, or{@code null} if there are none
+ * @return the set of [AnalysisError]s found on the passed [ClassElement], or`null` if there are none
*/
Set<AnalysisError> getErrors(ClassElement classElt) => _errorsInClassElement[classElt];
/**
* Get and return a mapping between the set of all string names of the members inherited from the
- * passed {@link ClassElement} superclass hierarchy, and the associated {@link ExecutableElement}.
+ * passed [ClassElement] superclass hierarchy, and the associated [ExecutableElement].
* @param classElt the class element to query
- * @return a mapping between the set of all members inherited from the passed {@link ClassElement}superclass hierarchy, and the associated {@link ExecutableElement}
+ * @return a mapping between the set of all members inherited from the passed [ClassElement]superclass hierarchy, and the associated [ExecutableElement]
*/
Map<String, ExecutableElement> getMapOfMembersInheritedFromClasses(ClassElement classElt) => computeClassChainLookupMap(classElt, new Set<ClassElement>());
/**
* Get and return a mapping between the set of all string names of the members inherited from the
- * passed {@link ClassElement} interface hierarchy, and the associated {@link ExecutableElement}.
+ * passed [ClassElement] interface hierarchy, and the associated [ExecutableElement].
* @param classElt the class element to query
- * @return a mapping between the set of all string names of the members inherited from the passed{@link ClassElement} interface hierarchy, and the associated {@link ExecutableElement}.
+ * @return a mapping between the set of all string names of the members inherited from the passed[ClassElement] interface hierarchy, and the associated [ExecutableElement].
*/
Map<String, ExecutableElement> getMapOfMembersInheritedFromInterfaces(ClassElement classElt) => computeInterfaceLookupMap(classElt, new Set<ClassElement>());
/**
- * Given some {@link ClassElement class element} and some member name, this returns the{@link ExecutableElement executable element} that the class inherits from the mixins,
- * superclasses or interfaces, that has the member name, if no member is inherited {@code null} is
+ * Given some [ClassElement class element] and some member name, this returns the[ExecutableElement executable element] that the class inherits from the mixins,
+ * superclasses or interfaces, that has the member name, if no member is inherited `null` is
* returned.
* @param classElt the class element to query
* @param memberName the name of the executable element to find and return
- * @return the inherited executable element with the member name, or {@code null} if no such
+ * @return the inherited executable element with the member name, or `null` if no such
* member exists
*/
ExecutableElement lookupInheritance(ClassElement classElt, String memberName) {
@@ -3369,11 +3527,11 @@
}
/**
- * Given some {@link ClassElement class element} and some member name, this returns the{@link ExecutableElement executable element} that the class either declares itself, or
- * inherits, that has the member name, if no member is inherited {@code null} is returned.
+ * Given some [ClassElement class element] and some member name, this returns the[ExecutableElement executable element] that the class either declares itself, or
+ * inherits, that has the member name, if no member is inherited `null` is returned.
* @param classElt the class element to query
* @param memberName the name of the executable element to find and return
- * @return the inherited executable element with the member name, or {@code null} if no such
+ * @return the inherited executable element with the member name, or `null` if no such
* member exists
*/
ExecutableElement lookupMember(ClassElement classElt, String memberName) {
@@ -3393,7 +3551,7 @@
}
/**
- * This method takes some inherited {@link FunctionType}, and resolves all the parameterized types
+ * This method takes some inherited [FunctionType], and resolves all the parameterized types
* in the function type, dependent on the class in which it is being overridden.
* @param baseFunctionType the function type that is being overridden
* @param memberName the name of the member, this is used to lookup the inheritance path of the
@@ -3413,9 +3571,9 @@
FunctionType functionTypeToReturn = baseFunctionType;
InterfaceType lastType = inheritancePath.removeLast();
while (inheritancePath.length > 0) {
- List<Type2> paramTypes = TypeVariableTypeImpl.getTypes(lastType.element.typeVariables);
- List<Type2> argTypes = lastType.typeArguments;
- functionTypeToReturn = functionTypeToReturn.substitute2(argTypes, paramTypes);
+ List<Type2> parameterTypes = lastType.element.type.typeArguments;
+ List<Type2> argumentTypes = lastType.typeArguments;
+ functionTypeToReturn = functionTypeToReturn.substitute2(argumentTypes, parameterTypes);
lastType = inheritancePath.removeLast();
}
return functionTypeToReturn;
@@ -3423,11 +3581,11 @@
/**
* Compute and return a mapping between the set of all string names of the members inherited from
- * the passed {@link ClassElement} superclass hierarchy, and the associated{@link ExecutableElement}.
+ * the passed [ClassElement] superclass hierarchy, and the associated[ExecutableElement].
* @param classElt the class element to query
* @param visitedClasses a set of visited classes passed back into this method when it calls
* itself recursively
- * @return a mapping between the set of all string names of the members inherited from the passed{@link ClassElement} superclass hierarchy, and the associated {@link ExecutableElement}
+ * @return a mapping between the set of all string names of the members inherited from the passed[ClassElement] superclass hierarchy, and the associated [ExecutableElement]
*/
Map<String, ExecutableElement> computeClassChainLookupMap(ClassElement classElt, Set<ClassElement> visitedClasses) {
Map<String, ExecutableElement> resultMap = _classLookup[classElt];
@@ -3469,7 +3627,7 @@
* Compute and return the inheritance path given the context of a type and a member that is
* overridden in the inheritance path (for which the type is in the path).
* @param chain the inheritance path that is built up as this method calls itself recursively,
- * when this method is called an empty {@link LinkedList} should be provided
+ * when this method is called an empty [LinkedList] should be provided
* @param currentType the current type in the inheritance path
* @param memberName the name of the member that is being looked up the inheritance path
*/
@@ -3513,11 +3671,11 @@
/**
* Compute and return a mapping between the set of all string names of the members inherited from
- * the passed {@link ClassElement} interface hierarchy, and the associated{@link ExecutableElement}.
+ * the passed [ClassElement] interface hierarchy, and the associated[ExecutableElement].
* @param classElt the class element to query
* @param visitedInterfaces a set of visited classes passed back into this method when it calls
* itself recursively
- * @return a mapping between the set of all string names of the members inherited from the passed{@link ClassElement} interface hierarchy, and the associated {@link ExecutableElement}
+ * @return a mapping between the set of all string names of the members inherited from the passed[ClassElement] interface hierarchy, and the associated [ExecutableElement]
*/
Map<String, ExecutableElement> computeInterfaceLookupMap(ClassElement classElt, Set<ClassElement> visitedInterfaces) {
Map<String, ExecutableElement> resultMap = _interfaceLookup[classElt];
@@ -3529,7 +3687,7 @@
InterfaceType supertype = classElt.supertype;
ClassElement superclassElement = supertype != null ? supertype.element : null;
List<InterfaceType> interfaces = classElt.interfaces;
- if (superclassElement == null || interfaces.length == 0) {
+ if ((superclassElement == null || supertype.isObject) && interfaces.length == 0) {
_interfaceLookup[classElt] = resultMap;
return resultMap;
}
@@ -3593,7 +3751,7 @@
if (superclassElement != null) {
List<MethodElement> methods = superclassElement.methods;
for (MethodElement method in methods) {
- if (method.isAccessibleIn(_library) && !method.isStatic()) {
+ if (method.isAccessibleIn(_library) && !method.isStatic) {
String key = method.name;
if (!unionMap.containsKey(key)) {
Set<ExecutableElement> set = new Set<ExecutableElement>();
@@ -3606,7 +3764,7 @@
}
List<PropertyAccessorElement> accessors = superclassElement.accessors;
for (PropertyAccessorElement accessor in accessors) {
- if (accessor.isAccessibleIn(_library) && !accessor.isStatic()) {
+ if (accessor.isAccessibleIn(_library) && !accessor.isStatic) {
String key = accessor.name;
if (!unionMap.containsKey(key)) {
Set<ExecutableElement> set = new Set<ExecutableElement>();
@@ -3623,7 +3781,7 @@
if (interfaceElement != null) {
List<MethodElement> methods = interfaceElement.methods;
for (MethodElement method in methods) {
- if (method.isAccessibleIn(_library) && !method.isStatic()) {
+ if (method.isAccessibleIn(_library) && !method.isStatic) {
String key = method.name;
if (!unionMap.containsKey(key)) {
Set<ExecutableElement> set = new Set<ExecutableElement>();
@@ -3636,7 +3794,7 @@
}
List<PropertyAccessorElement> accessors = interfaceElement.accessors;
for (PropertyAccessorElement accessor in accessors) {
- if (accessor.isAccessibleIn(_library) && !accessor.isStatic()) {
+ if (accessor.isAccessibleIn(_library) && !accessor.isStatic) {
String key = accessor.name;
if (!unionMap.containsKey(key)) {
Set<ExecutableElement> set = new Set<ExecutableElement>();
@@ -3662,7 +3820,7 @@
for (ExecutableElement executableElement in set) {
if (executableElement is PropertyAccessorElement) {
allMethods = false;
- if (((executableElement as PropertyAccessorElement)).isSetter()) {
+ if (((executableElement as PropertyAccessorElement)).isSetter) {
allGetters = false;
} else {
allSetters = false;
@@ -3715,23 +3873,23 @@
}
/**
- * Given some {@link ClassElement}, this method finds and returns the {@link ExecutableElement} of
+ * Given some [ClassElement], this method finds and returns the [ExecutableElement] of
* the passed name in the class element. Static members, members in super types and members not
* accessible from the current library are not considered.
* @param classElt the class element to query
* @param memberName the name of the member to lookup in the class
- * @return the found {@link ExecutableElement}, or {@code null} if no such member was found
+ * @return the found [ExecutableElement], or `null` if no such member was found
*/
ExecutableElement lookupMemberInClass(ClassElement classElt, String memberName) {
List<MethodElement> methods = classElt.methods;
for (MethodElement method in methods) {
- if (memberName == method.name && method.isAccessibleIn(_library) && !method.isStatic()) {
+ if (memberName == method.name && method.isAccessibleIn(_library) && !method.isStatic) {
return method;
}
}
List<PropertyAccessorElement> accessors = classElt.accessors;
for (PropertyAccessorElement accessor in accessors) {
- if (memberName == accessor.name && accessor.isAccessibleIn(_library) && !accessor.isStatic()) {
+ if (memberName == accessor.name && accessor.isAccessibleIn(_library) && !accessor.isStatic) {
return accessor;
}
}
@@ -3741,19 +3899,19 @@
/**
* Record the passed map with the set of all members (methods, getters and setters) in the class
* into the passed map.
- * @param map some non-{@code null}
+ * @param map some non-`null`
* @param classElt the class element that will be recorded into the passed map
*/
void recordMapWithClassMembers(Map<String, ExecutableElement> map, ClassElement classElt) {
List<MethodElement> methods = classElt.methods;
for (MethodElement method in methods) {
- if (method.isAccessibleIn(_library) && !method.isStatic()) {
+ if (method.isAccessibleIn(_library) && !method.isStatic) {
map[method.name] = method;
}
}
List<PropertyAccessorElement> accessors = classElt.accessors;
for (PropertyAccessorElement accessor in accessors) {
- if (accessor.isAccessibleIn(_library) && !accessor.isStatic()) {
+ if (accessor.isAccessibleIn(_library) && !accessor.isStatic) {
map[accessor.name] = accessor;
}
}
@@ -3761,7 +3919,7 @@
/**
* This method is used to report errors on when they are found computing inheritance information.
- * See {@link ErrorVerifier#checkForInconsistentMethodInheritance()} to see where these generated
+ * See [ErrorVerifier#checkForInconsistentMethodInheritance] to see where these generated
* error codes are reported back into the analysis engine.
* @param classElt the location of the source for which the exception occurred
* @param offset the offset of the location of the error
@@ -3779,7 +3937,7 @@
}
}
/**
- * Instances of the class {@code Library} represent the data about a single library during the
+ * Instances of the class `Library` represent the data about a single library during the
* resolution of some (possibly different) library. They are not intended to be used except during
* the resolution process.
* @coverage dart.engine.resolver
@@ -3902,8 +4060,8 @@
CompilationUnit get definingCompilationUnit => getAST(librarySource);
/**
- * Return {@code true} if this library explicitly imports core.
- * @return {@code true} if this library explicitly imports core
+ * Return `true` if this library explicitly imports core.
+ * @return `true` if this library explicitly imports core
*/
bool get explicitlyImportsCore => _explicitlyImportsCore;
@@ -3998,7 +4156,7 @@
/**
* Return the result of resolving the URI of the given URI-based directive against the URI of the
- * library, or {@code null} if the URI is not valid. If the URI is not valid, report the error.
+ * library, or `null` if the URI is not valid. If the URI is not valid, report the error.
* @param directive the directive which URI should be resolved
* @return the result of resolving the URI against the URI of the library
*/
@@ -4039,7 +4197,7 @@
/**
* Set whether this library explicitly imports core to match the given value.
- * @param explicitlyImportsCore {@code true} if this library explicitly imports core
+ * @param explicitlyImportsCore `true` if this library explicitly imports core
*/
void set explicitlyImportsCore(bool explicitlyImportsCore2) {
this._explicitlyImportsCore = explicitlyImportsCore2;
@@ -4058,7 +4216,7 @@
String toString() => _librarySource.shortName;
/**
- * Return the result of resolving the given URI against the URI of the library, or {@code null} if
+ * Return the result of resolving the given URI against the URI of the library, or `null` if
* the URI is not valid.
* @param uri the URI to be resolved
* @return the result of resolving the given URI against the URI of the library
@@ -4071,7 +4229,7 @@
}
}
/**
- * Instances of the class {@code LibraryElementBuilder} build an element model for a single library.
+ * Instances of the class `LibraryElementBuilder` build an element model for a single library.
* @coverage dart.engine.resolver
*/
class LibraryElementBuilder {
@@ -4175,12 +4333,12 @@
*/
void collectAccessors(Map<String, PropertyAccessorElement> getters, List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
for (PropertyAccessorElement accessor in unit.accessors) {
- if (accessor.isGetter()) {
- if (!accessor.isSynthetic() && accessor.correspondingSetter == null) {
+ if (accessor.isGetter) {
+ if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
getters[accessor.displayName] = accessor;
}
} else {
- if (!accessor.isSynthetic() && accessor.correspondingGetter == null) {
+ if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
setters.add(accessor);
}
}
@@ -4190,7 +4348,7 @@
/**
* Search the top-level functions defined in the given compilation unit for the entry point.
* @param element the compilation unit to be searched
- * @return the entry point that was found, or {@code null} if the compilation unit does not define
+ * @return the entry point that was found, or `null` if the compilation unit does not define
* an entry point
*/
FunctionElement findEntryPoint(CompilationUnitElementImpl element) {
@@ -4203,7 +4361,7 @@
}
/**
- * Return the name of the library that the given part is declared to be a part of, or {@code null}if the part does not contain a part-of directive.
+ * Return the name of the library that the given part is declared to be a part of, or `null`if the part does not contain a part-of directive.
* @param library the library containing the part
* @param partSource the source representing the part
* @param directivesToResolve a list of directives that should be resolved to the library being
@@ -4251,7 +4409,7 @@
}
}
/**
- * Instances of the class {@code LibraryResolver} are used to resolve one or more mutually dependent
+ * Instances of the class `LibraryResolver` are used to resolve one or more mutually dependent
* libraries within a single context.
* @coverage dart.engine.resolver
*/
@@ -4264,7 +4422,7 @@
/**
* The listener to which analysis errors will be reported, this error listener is either
- * references {@link #recordingErrorListener}, or it unions the passed{@link AnalysisErrorListener} with the {@link #recordingErrorListener}.
+ * references [recordingErrorListener], or it unions the passed[AnalysisErrorListener] with the [recordingErrorListener].
*/
RecordingErrorListener _errorListener;
@@ -4327,7 +4485,7 @@
* @param librarySource the source specifying the defining compilation unit of the library to be
* resolved
* @param unit the compilation unit representing the embedded library
- * @param fullAnalysis {@code true} if a full analysis should be performed
+ * @param fullAnalysis `true` if a full analysis should be performed
* @return the element representing the resolved library
* @throws AnalysisException if the library could not be resolved for some reason
*/
@@ -4371,13 +4529,13 @@
/**
* Resolve the library specified by the given source in the given context.
- * <p>
+ *
* Note that because Dart allows circular imports between libraries, it is possible that more than
* one library will need to be resolved. In such cases the error listener can receive errors from
* multiple libraries.
* @param librarySource the source specifying the defining compilation unit of the library to be
* resolved
- * @param fullAnalysis {@code true} if a full analysis should be performed
+ * @param fullAnalysis `true` if a full analysis should be performed
* @return the element representing the resolved library
* @throws AnalysisException if the library could not be resolved for some reason
*/
@@ -4500,7 +4658,7 @@
}
/**
- * Every library now has a corresponding {@link LibraryElement}, so it is now possible to resolve
+ * Every library now has a corresponding [LibraryElement], so it is now possible to resolve
* the import and export directives.
* @throws AnalysisException if the defining compilation unit for any of the libraries could not
* be accessed
@@ -4594,7 +4752,7 @@
* Compute a dependency map of libraries reachable from the given library. A dependency map is a
* table that maps individual libraries to a list of the libraries that either import or export
* those libraries.
- * <p>
+ *
* This map is used to compute all of the libraries involved in a cycle that include the root
* library. Given that we only add libraries that are reachable from the root library, when we
* work backward we are guaranteed to only get libraries in the cycle.
@@ -4622,7 +4780,7 @@
/**
* Recursively traverse the libraries reachable from the given library, creating instances of the
- * class {@link Library} to represent them, and record the references in the library objects.
+ * class [Library] to represent them, and record the references in the library objects.
* @param library the library to be processed to find libraries that have not yet been traversed
* @throws AnalysisException if some portion of the library graph could not be traversed
*/
@@ -4715,7 +4873,7 @@
/**
* Create an object to represent the information about the library defined by the compilation unit
- * with the given source. Return the library object that was created, or {@code null} if the
+ * with the given source. Return the library object that was created, or `null` if the
* source is not valid.
* @param librarySource the source of the library's defining compilation unit
* @return the library object that was created
@@ -4735,9 +4893,9 @@
}
/**
- * Return {@code true} if and only if the passed {@link CompilationUnit} has a part-of directive.
- * @param node the {@link CompilationUnit} to test
- * @return {@code true} if and only if the passed {@link CompilationUnit} has a part-of directive
+ * Return `true` if and only if the passed [CompilationUnit] has a part-of directive.
+ * @param node the [CompilationUnit] to test
+ * @return `true` if and only if the passed [CompilationUnit] has a part-of directive
*/
bool doesCompilationUnitHavePartOfDirective(CompilationUnit node) {
NodeList<Directive> directives = node.directives;
@@ -4808,7 +4966,7 @@
}
/**
- * Run additional analyses, such as the {@link ConstantVerifier} and {@link ErrorVerifier}analysis in the current cycle.
+ * Run additional analyses, such as the [ConstantVerifier] and [ErrorVerifier]analysis in the current cycle.
* @throws AnalysisException if any of the identifiers could not be resolved or if the types in
* the library cannot be analyzed
*/
@@ -4819,7 +4977,7 @@
}
/**
- * Run additional analyses, such as the {@link ConstantVerifier} and {@link ErrorVerifier}analysis in the given library.
+ * Run additional analyses, such as the [ConstantVerifier] and [ErrorVerifier]analysis in the given library.
* @param library the library to have the extra analyses processes run
* @throws AnalysisException if any of the identifiers could not be resolved or if the types in
* the library cannot be analyzed
@@ -4828,16 +4986,15 @@
for (Source source in library.compilationUnitSources) {
ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
CompilationUnit unit = library.getAST(source);
- ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, library.libraryElement, _typeProvider, library.inheritanceManager);
- unit.accept(errorVerifier);
- unit.accept(new PubVerifier(_analysisContext, errorReporter));
ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, _typeProvider);
unit.accept(constantVerifier);
+ ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, library.libraryElement, _typeProvider, library.inheritanceManager);
+ unit.accept(errorVerifier);
}
}
}
/**
- * Instances of the class {@code ResolverVisitor} are used to resolve the nodes within a single
+ * Instances of the class `ResolverVisitor` are used to resolve the nodes within a single
* compilation unit.
* @coverage dart.engine.resolver
*/
@@ -4854,13 +5011,13 @@
StaticTypeAnalyzer _typeAnalyzer;
/**
- * The class element representing the class containing the current node, or {@code null} if the
+ * The class element representing the class containing the current node, or `null` if the
* current node is not contained in a class.
*/
ClassElement _enclosingClass = null;
/**
- * The element representing the function containing the current node, or {@code null} if the
+ * The element representing the function containing the current node, or `null` if the
* current node is not contained in a function.
*/
ExecutableElement _enclosingFunction = null;
@@ -4877,9 +5034,9 @@
* @param typeProvider the object used to access the types from the core library
*/
ResolverVisitor.con1(Library library, Source source, TypeProvider typeProvider) : super.con1(library, source, typeProvider) {
- _jtd_constructor_273_impl(library, source, typeProvider);
+ _jtd_constructor_274_impl(library, source, typeProvider);
}
- _jtd_constructor_273_impl(Library library, Source source, TypeProvider typeProvider) {
+ _jtd_constructor_274_impl(Library library, Source source, TypeProvider typeProvider) {
this._elementResolver = new ElementResolver(this);
this._typeAnalyzer = new StaticTypeAnalyzer(this);
}
@@ -4894,9 +5051,9 @@
* during resolution
*/
ResolverVisitor.con2(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) : super.con2(definingLibrary, source, typeProvider, errorListener) {
- _jtd_constructor_274_impl(definingLibrary, source, typeProvider, errorListener);
+ _jtd_constructor_275_impl(definingLibrary, source, typeProvider, errorListener);
}
- _jtd_constructor_274_impl(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) {
+ _jtd_constructor_275_impl(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) {
this._elementResolver = new ElementResolver(this);
this._typeAnalyzer = new StaticTypeAnalyzer(this);
}
@@ -5275,21 +5432,21 @@
}
/**
- * Return the class element representing the class containing the current node, or {@code null} if
+ * Return the class element representing the class containing the current node, or `null` if
* the current node is not contained in a class.
* @return the class element representing the class containing the current node
*/
ClassElement get enclosingClass => _enclosingClass;
/**
- * Return the element representing the function containing the current node, or {@code null} if
+ * Return the element representing the function containing the current node, or `null` if
* the current node is not contained in a function.
* @return the element representing the function containing the current node
*/
ExecutableElement get enclosingFunction => _enclosingFunction;
/**
- * Return the element associated with the given expression whose type can be overridden, or{@code null} if there is no element whose type can be overridden.
+ * Return the element associated with the given expression whose type can be overridden, or`null` if there is no element whose type can be overridden.
* @param expression the expression with which the element is associated
* @return the element associated with the given expression
*/
@@ -5321,7 +5478,7 @@
}
if (element is PropertyInducingElement) {
PropertyInducingElement variable = element as PropertyInducingElement;
- if (!variable.isConst() && !variable.isFinal()) {
+ if (!variable.isConst && !variable.isFinal) {
return;
}
}
@@ -5388,7 +5545,7 @@
/**
* The given expression is the expression used to compute the iterator for a for-each statement.
* Attempt to compute the type of objects that will be assigned to the loop variable and return
- * that type. Return {@code null} if the type could not be determined.
+ * that type. Return `null` if the type could not be determined.
* @param iterator the iterator for a for-each statement
* @return the type of objects that will be assigned to the loop variable
*/
@@ -5412,10 +5569,10 @@
}
/**
- * Return {@code true} if the given expression terminates abruptly (that is, if any expression
+ * Return `true` if the given expression terminates abruptly (that is, if any expression
* following the given expression will not be reached).
* @param expression the expression being tested
- * @return {@code true} if the given expression terminates abruptly
+ * @return `true` if the given expression terminates abruptly
*/
bool isAbruptTermination(Expression expression2) {
while (expression2 is ParenthesizedExpression) {
@@ -5425,10 +5582,10 @@
}
/**
- * Return {@code true} if the given statement terminates abruptly (that is, if any statement
+ * Return `true` if the given statement terminates abruptly (that is, if any statement
* following the given statement will not be reached).
* @param statement the statement being tested
- * @return {@code true} if the given statement terminates abruptly
+ * @return `true` if the given statement terminates abruptly
*/
bool isAbruptTermination2(Statement statement) {
if (statement is ReturnStatement || statement is BreakStatement || statement is ContinueStatement) {
@@ -5525,7 +5682,7 @@
set enclosingClass_J2DAccessor(__v) => _enclosingClass = __v;
}
/**
- * The abstract class {@code ScopedVisitor} maintains name and label scopes as an AST structure is
+ * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is
* being visited.
* @coverage dart.engine.resolver
*/
@@ -5557,7 +5714,7 @@
TypeProvider _typeProvider;
/**
- * The scope used to resolve labels for {@code break} and {@code continue} statements, or{@code null} if no labels have been defined in the current context.
+ * The scope used to resolve labels for `break` and `continue` statements, or`null` if no labels have been defined in the current context.
*/
LabelScope _labelScope;
@@ -5568,9 +5725,9 @@
* @param typeProvider the object used to access the types from the core library
*/
ScopedVisitor.con1(Library library, Source source2, TypeProvider typeProvider2) {
- _jtd_constructor_275_impl(library, source2, typeProvider2);
+ _jtd_constructor_276_impl(library, source2, typeProvider2);
}
- _jtd_constructor_275_impl(Library library, Source source2, TypeProvider typeProvider2) {
+ _jtd_constructor_276_impl(Library library, Source source2, TypeProvider typeProvider2) {
this._definingLibrary = library.libraryElement;
this._source = source2;
LibraryScope libraryScope = library.libraryScope;
@@ -5589,9 +5746,9 @@
* during resolution
*/
ScopedVisitor.con2(LibraryElement definingLibrary2, Source source2, TypeProvider typeProvider2, AnalysisErrorListener errorListener2) {
- _jtd_constructor_276_impl(definingLibrary2, source2, typeProvider2, errorListener2);
+ _jtd_constructor_277_impl(definingLibrary2, source2, typeProvider2, errorListener2);
}
- _jtd_constructor_276_impl(LibraryElement definingLibrary2, Source source2, TypeProvider typeProvider2, AnalysisErrorListener errorListener2) {
+ _jtd_constructor_277_impl(LibraryElement definingLibrary2, Source source2, TypeProvider typeProvider2, AnalysisErrorListener errorListener2) {
this._definingLibrary = definingLibrary2;
this._source = source2;
this._errorListener = errorListener2;
@@ -5924,12 +6081,12 @@
}
}
/**
- * Instances of the class {@code StaticTypeAnalyzer} perform two type-related tasks. First, they
+ * Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. First, they
* compute the static type of every expression. Second, they look for any static type errors or
* warnings that might need to be generated. The requirements for the type analyzer are:
* <ol>
- * <li>Every element that refers to types should be fully populated.
- * <li>Every node representing an expression should be resolved to the Type of the expression.</li>
+ * * Every element that refers to types should be fully populated.
+ * * Every node representing an expression should be resolved to the Type of the expression.
* </ol>
* @coverage dart.engine.resolver
*/
@@ -6019,7 +6176,7 @@
Type2 _dynamicType;
/**
- * The type representing the class containing the nodes being analyzed, or {@code null} if the
+ * The type representing the class containing the nodes being analyzed, or `null` if the
* nodes are not within a class.
*/
InterfaceType _thisType;
@@ -6055,7 +6212,7 @@
}
/**
- * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is{@code String}.</blockquote>
+ * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is`String`.</blockquote>
*/
Object visitAdjacentStrings(AdjacentStrings node) {
recordStaticType(node, _typeProvider.stringType);
@@ -6064,7 +6221,7 @@
/**
* The Dart Language Specification, 12.33: <blockquote>The static type of an argument definition
- * test is {@code bool}.</blockquote>
+ * test is `bool`.</blockquote>
*/
Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
recordStaticType(node, _typeProvider.boolType);
@@ -6073,10 +6230,10 @@
/**
* The Dart Language Specification, 12.32: <blockquote>... the cast expression <i>e as T</i> ...
- * <p>
+ *
* It is a static warning if <i>T</i> does not denote a type available in the current lexical
* scope.
- * <p>
+ *
* The static type of a cast expression <i>e as T</i> is <i>T</i>.</blockquote>
*/
Object visitAsExpression(AsExpression node) {
@@ -6087,33 +6244,33 @@
/**
* The Dart Language Specification, 12.18: <blockquote>... an assignment <i>a</i> of the form <i>v
* = e</i> ...
- * <p>
+ *
* It is a static type warning if the static type of <i>e</i> may not be assigned to the static
* type of <i>v</i>.
- * <p>
+ *
* The static type of the expression <i>v = e</i> is the static type of <i>e</i>.
- * <p>
+ *
* ... an assignment of the form <i>C.v = e</i> ...
- * <p>
+ *
* It is a static type warning if the static type of <i>e</i> may not be assigned to the static
* type of <i>C.v</i>.
- * <p>
+ *
* The static type of the expression <i>C.v = e</i> is the static type of <i>e</i>.
- * <p>
+ *
* ... an assignment of the form <i>e<sub>1</sub>.v = e<sub>2</sub></i> ...
- * <p>
+ *
* Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static type warning if
* <i>T</i> does not have an accessible instance setter named <i>v=</i>. It is a static type
* warning if the static type of <i>e<sub>2</sub></i> may not be assigned to <i>T</i>.
- * <p>
+ *
* The static type of the expression <i>e<sub>1</sub>.v = e<sub>2</sub></i> is the static type of
* <i>e<sub>2</sub></i>.
- * <p>
+ *
* ... an assignment of the form <i>e<sub>1</sub>\[e<sub>2</sub>\] = e<sub>3</sub></i> ...
- * <p>
+ *
* The static type of the expression <i>e<sub>1</sub>\[e<sub>2</sub>\] = e<sub>3</sub></i> is the
* static type of <i>e<sub>3</sub></i>.
- * <p>
+ *
* A compound assignment of the form <i>v op= e</i> is equivalent to <i>v = v op e</i>. A compound
* assignment of the form <i>C.v op= e</i> is equivalent to <i>C.v = C.v op e</i>. A compound
* assignment of the form <i>e<sub>1</sub>.v op= e<sub>2</sub></i> is equivalent to <i>((x) => x.v
@@ -6158,35 +6315,35 @@
/**
* The Dart Language Specification, 12.20: <blockquote>The static type of a logical boolean
- * expression is {@code bool}.</blockquote>
- * <p>
+ * expression is `bool`.</blockquote>
+ *
* The Dart Language Specification, 12.21:<blockquote>A bitwise expression of the form
* <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocation
* <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A bitwise expression of the form <i>super op
* e<sub>2</sub></i> is equivalent to the method invocation
* <i>super.op(e<sub>2</sub>)</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 12.22: <blockquote>The static type of an equality expression
- * is {@code bool}.</blockquote>
- * <p>
+ * is `bool`.</blockquote>
+ *
* The Dart Language Specification, 12.23: <blockquote>A relational expression of the form
* <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocation
* <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A relational expression of the form <i>super op
* e<sub>2</sub></i> is equivalent to the method invocation
* <i>super.op(e<sub>2</sub>)</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 12.24: <blockquote>A shift expression of the form
* <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocation
* <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A shift expression of the form <i>super op
* e<sub>2</sub></i> is equivalent to the method invocation
* <i>super.op(e<sub>2</sub>)</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 12.25: <blockquote>An additive expression of the form
* <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocation
* <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. An additive expression of the form <i>super op
* e<sub>2</sub></i> is equivalent to the method invocation
* <i>super.op(e<sub>2</sub>)</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 12.26: <blockquote>A multiplicative expression of the form
* <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocation
* <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A multiplicative expression of the form <i>super op
@@ -6231,9 +6388,9 @@
/**
* The Dart Language Specification, 12.19: <blockquote> ... a conditional expression <i>c</i> of
* the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub></i> ...
- * <p>
- * It is a static type warning if the type of e<sub>1</sub> may not be assigned to {@code bool}.
- * <p>
+ *
+ * It is a static type warning if the type of e<sub>1</sub> may not be assigned to `bool`.
+ *
* The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i>
* and the static type of <i>e<sub>3</sub></i>.</blockquote>
*/
@@ -6278,8 +6435,10 @@
}
Object visitFunctionDeclaration(FunctionDeclaration node) {
FunctionExpression function = node.functionExpression;
- FunctionTypeImpl functionType = node.element.type as FunctionTypeImpl;
- setTypeInformation(functionType, computeReturnType2(node), function.parameters);
+ ExecutableElementImpl functionElement = node.element as ExecutableElementImpl;
+ functionElement.returnType = computeReturnType2(node);
+ FunctionTypeImpl functionType = functionElement.type as FunctionTypeImpl;
+ setTypeInformation(functionType, function.parameters);
recordStaticType(function, functionType);
return null;
}
@@ -6292,21 +6451,21 @@
* x<sub>n+k</sub>\]) → T<sub>0</sub></i>, where <i>T<sub>0</sub></i> is the static type of
* <i>e</i>. In any case where <i>T<sub>i</sub>, 1 <= i <= n</i>, is not specified, it is
* considered to have been specified as dynamic.
- * <p>
+ *
* The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1</sub>, …,
* T<sub>n</sub> a<sub>n</sub>, {T<sub>n+1</sub> x<sub>n+1</sub> : d1, …, T<sub>n+k</sub>
* x<sub>n+k</sub> : dk}) => e</i> is <i>(T<sub>1</sub>, …, T<sub>n</sub>, {T<sub>n+1</sub>
* x<sub>n+1</sub>, …, T<sub>n+k</sub> x<sub>n+k</sub>}) → T<sub>0</sub></i>, where
* <i>T<sub>0</sub></i> is the static type of <i>e</i>. In any case where <i>T<sub>i</sub>, 1
* <= i <= n</i>, is not specified, it is considered to have been specified as dynamic.
- * <p>
+ *
* The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1</sub>, …,
* T<sub>n</sub> a<sub>n</sub>, \[T<sub>n+1</sub> x<sub>n+1</sub> = d1, …, T<sub>n+k</sub>
* x<sub>n+k</sub> = dk\]) {s}</i> is <i>(T<sub>1</sub>, …, T<sub>n</sub>, \[T<sub>n+1</sub>
* x<sub>n+1</sub>, …, T<sub>n+k</sub> x<sub>n+k</sub>\]) → dynamic</i>. In any case
* where <i>T<sub>i</sub>, 1 <= i <= n</i>, is not specified, it is considered to have been
* specified as dynamic.
- * <p>
+ *
* The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1</sub>, …,
* T<sub>n</sub> a<sub>n</sub>, {T<sub>n+1</sub> x<sub>n+1</sub> : d1, …, T<sub>n+k</sub>
* x<sub>n+k</sub> : dk}) {s}</i> is <i>(T<sub>1</sub>, …, T<sub>n</sub>, {T<sub>n+1</sub>
@@ -6318,8 +6477,10 @@
if (node.parent is FunctionDeclaration) {
return null;
}
+ ExecutableElementImpl functionElement = node.element as ExecutableElementImpl;
+ functionElement.returnType = computeReturnType3(node);
FunctionTypeImpl functionType = node.element.type as FunctionTypeImpl;
- setTypeInformation(functionType, computeReturnType3(node), node.parameters);
+ setTypeInformation(functionType, node.parameters);
recordStaticType(node, functionType);
return null;
}
@@ -6329,10 +6490,10 @@
* has the form <i>e<sub>f</sub>(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>:
* a<sub>n+1</sub>, …, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>, where <i>e<sub>f</sub></i> is
* an expression.
- * <p>
+ *
* It is a static type warning if the static type <i>F</i> of <i>e<sub>f</sub></i> may not be
* assigned to a function type.
- * <p>
+ *
* If <i>F</i> is not a function type, the static type of <i>i</i> is dynamic. Otherwise the
* static type of <i>i</i> is the declared return type of <i>F</i>.</blockquote>
*/
@@ -6386,7 +6547,7 @@
* The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
* either the form <i>new T.id(a<sub>1</sub>, …, a<sub>n</sub>)</i> or the form <i>new
* T(a<sub>1</sub>, …, a<sub>n</sub>)</i> is <i>T</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 12.11.2: <blockquote>The static type of a constant object
* expression of either the form <i>const T.id(a<sub>1</sub>, …, a<sub>n</sub>)</i> or the
* form <i>const T(a<sub>1</sub>, …, a<sub>n</sub>)</i> is <i>T</i>. </blockquote>
@@ -6407,7 +6568,7 @@
}
/**
- * The Dart Language Specification, 12.3: <blockquote>The static type of an integer literal is{@code int}.</blockquote>
+ * The Dart Language Specification, 12.3: <blockquote>The static type of an integer literal is`int`.</blockquote>
*/
Object visitIntegerLiteral(IntegerLiteral node) {
recordStaticType(node, _typeProvider.intType);
@@ -6417,8 +6578,8 @@
/**
* The Dart Language Specification, 12.31: <blockquote>It is a static warning if <i>T</i> does not
* denote a type available in the current lexical scope.
- * <p>
- * The static type of an is-expression is {@code bool}.</blockquote>
+ *
+ * The static type of an is-expression is `bool`.</blockquote>
*/
Object visitIsExpression(IsExpression node) {
recordStaticType(node, _typeProvider.boolType);
@@ -6428,9 +6589,9 @@
/**
* The Dart Language Specification, 12.6: <blockquote>The static type of a list literal of the
* form <i><b>const</b> <E>\[e<sub>1</sub>, …, e<sub>n</sub>\]</i> or the form
- * <i><E>\[e<sub>1</sub>, …, e<sub>n</sub>\]</i> is {@code List<E>}. The static
+ * <i><E>\[e<sub>1</sub>, …, e<sub>n</sub>\]</i> is `List<E>`. The static
* type a list literal of the form <i><b>const</b> \[e<sub>1</sub>, …, e<sub>n</sub>\]</i> or
- * the form <i>\[e<sub>1</sub>, …, e<sub>n</sub>\]</i> is {@code List<dynamic>}.</blockquote>
+ * the form <i>\[e<sub>1</sub>, …, e<sub>n</sub>\]</i> is `List<dynamic>`.</blockquote>
*/
Object visitListLiteral(ListLiteral node) {
Type2 staticType = _dynamicType;
@@ -6472,11 +6633,11 @@
* The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
* <i><b>const</b> <String, V> {k<sub>1</sub>:e<sub>1</sub>, …,
* k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i><String, V> {k<sub>1</sub>:e<sub>1</sub>,
- * …, k<sub>n</sub>:e<sub>n</sub>}</i> is {@code Map<String, V>}. The static type a
+ * …, k<sub>n</sub>:e<sub>n</sub>}</i> is `Map<String, V>`. The static type a
* map literal of the form <i><b>const</b> {k<sub>1</sub>:e<sub>1</sub>, …,
* k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>{k<sub>1</sub>:e<sub>1</sub>, …,
- * k<sub>n</sub>:e<sub>n</sub>}</i> is {@code Map<String, dynamic>}.
- * <p>
+ * k<sub>n</sub>:e<sub>n</sub>}</i> is `Map<String, dynamic>`.
+ *
* It is a compile-time error if the first type argument to a map literal is not
* <i>String</i>.</blockquote>
*/
@@ -6546,34 +6707,34 @@
* The Dart Language Specification, 12.15.1: <blockquote>An ordinary method invocation <i>i</i>
* has the form <i>o.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
* …, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
- * <p>
+ *
* Let <i>T</i> be the static type of <i>o</i>. It is a static type warning if <i>T</i> does not
* have an accessible instance member named <i>m</i>. If <i>T.m</i> exists, it is a static warning
* if the type <i>F</i> of <i>T.m</i> may not be assigned to a function type.
- * <p>
+ *
* If <i>T.m</i> does not exist, or if <i>F</i> is not a function type, the static type of
* <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of
* <i>F</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 11.15.3: <blockquote>A static method invocation <i>i</i> has
* the form <i>C.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
* …, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
- * <p>
+ *
* It is a static type warning if the type <i>F</i> of <i>C.m</i> may not be assigned to a
* function type.
- * <p>
+ *
* If <i>F</i> is not a function type, or if <i>C.m</i> does not exist, the static type of i is
* dynamic. Otherwise the static type of <i>i</i> is the declared return type of
* <i>F</i>.</blockquote>
- * <p>
+ *
* The Dart Language Specification, 11.15.4: <blockquote>A super method invocation <i>i</i> has
* the form <i>super.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>,
* …, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
- * <p>
+ *
* It is a static type warning if <i>S</i> does not have an accessible instance member named m. If
* <i>S.m</i> exists, it is a static warning if the type <i>F</i> of <i>S.m</i> may not be
* assigned to a function type.
- * <p>
+ *
* If <i>S.m</i> does not exist, or if <i>F</i> is not a function type, the static type of
* <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of
* <i>F</i>.</blockquote>
@@ -6662,7 +6823,7 @@
}
/**
- * The Dart Language Specification, 12.2: <blockquote>The static type of {@code null} is bottom.
+ * The Dart Language Specification, 12.2: <blockquote>The static type of `null` is bottom.
* </blockquote>
*/
Object visitNullLiteral(NullLiteral node) {
@@ -6680,25 +6841,25 @@
* The Dart Language Specification, 12.28: <blockquote>A postfix expression of the form
* <i>v++</i>, where <i>v</i> is an identifier, is equivalent to <i>(){var r = v; v = r + 1;
* return r}()</i>.
- * <p>
+ *
* A postfix expression of the form <i>C.v++</i> is equivalent to <i>(){var r = C.v; C.v = r + 1;
* return r}()</i>.
- * <p>
+ *
* A postfix expression of the form <i>e1.v++</i> is equivalent to <i>(x){var r = x.v; x.v = r +
* 1; return r}(e1)</i>.
- * <p>
+ *
* A postfix expression of the form <i>e1\[e2\]++</i> is equivalent to <i>(a, i){var r = a\[i\]; a\[i\]
* = r + 1; return r}(e1, e2)</i>
- * <p>
+ *
* A postfix expression of the form <i>v--</i>, where <i>v</i> is an identifier, is equivalent to
* <i>(){var r = v; v = r - 1; return r}()</i>.
- * <p>
+ *
* A postfix expression of the form <i>C.v--</i> is equivalent to <i>(){var r = C.v; C.v = r - 1;
* return r}()</i>.
- * <p>
+ *
* A postfix expression of the form <i>e1.v--</i> is equivalent to <i>(x){var r = x.v; x.v = r -
* 1; return r}(e1)</i>.
- * <p>
+ *
* A postfix expression of the form <i>e1\[e2\]--</i> is equivalent to <i>(a, i){var r = a\[i\]; a\[i\]
* = r - 1; return r}(e1, e2)</i></blockquote>
*/
@@ -6718,7 +6879,7 @@
}
/**
- * See {@link #visitSimpleIdentifier(SimpleIdentifier)}.
+ * See [visitSimpleIdentifier].
*/
Object visitPrefixedIdentifier(PrefixedIdentifier node) {
SimpleIdentifier prefixedIdentifier = node.identifier;
@@ -6787,43 +6948,43 @@
* The Dart Language Specification, 12.13: <blockquote> Property extraction allows for a member of
* an object to be concisely extracted from the object. If <i>o</i> is an object, and if <i>m</i>
* is the name of a method member of <i>o</i>, then
- * <ul>
- * <li><i>o.m</i> is defined to be equivalent to: <i>(r<sub>1</sub>, …, r<sub>n</sub>,
+ *
+ * * <i>o.m</i> is defined to be equivalent to: <i>(r<sub>1</sub>, …, r<sub>n</sub>,
* {p<sub>1</sub> : d<sub>1</sub>, …, p<sub>k</sub> : d<sub>k</sub>}){return
* o.m(r<sub>1</sub>, …, r<sub>n</sub>, p<sub>1</sub>: p<sub>1</sub>, …,
* p<sub>k</sub>: p<sub>k</sub>);}</i> if <i>m</i> has required parameters <i>r<sub>1</sub>,
* …, r<sub>n</sub></i>, and named parameters <i>p<sub>1</sub> … p<sub>k</sub></i>
- * with defaults <i>d<sub>1</sub>, …, d<sub>k</sub></i>.</li>
- * <li><i>(r<sub>1</sub>, …, r<sub>n</sub>, \[p<sub>1</sub> = d<sub>1</sub>, …,
+ * with defaults <i>d<sub>1</sub>, …, d<sub>k</sub></i>.
+ * * <i>(r<sub>1</sub>, …, r<sub>n</sub>, \[p<sub>1</sub> = d<sub>1</sub>, …,
* p<sub>k</sub> = d<sub>k</sub>\]){return o.m(r<sub>1</sub>, …, r<sub>n</sub>,
* p<sub>1</sub>, …, p<sub>k</sub>);}</i> if <i>m</i> has required parameters
* <i>r<sub>1</sub>, …, r<sub>n</sub></i>, and optional positional parameters
* <i>p<sub>1</sub> … p<sub>k</sub></i> with defaults <i>d<sub>1</sub>, …,
- * d<sub>k</sub></i>.</li>
- * </ul>
+ * d<sub>k</sub></i>.
+ *
* Otherwise, if <i>m</i> is the name of a getter member of <i>o</i> (declared implicitly or
* explicitly) then <i>o.m</i> evaluates to the result of invoking the getter. </blockquote>
- * <p>
+ *
* The Dart Language Specification, 12.17: <blockquote> ... a getter invocation <i>i</i> of the
* form <i>e.m</i> ...
- * <p>
+ *
* Let <i>T</i> be the static type of <i>e</i>. It is a static type warning if <i>T</i> does not
* have a getter named <i>m</i>.
- * <p>
+ *
* The static type of <i>i</i> is the declared return type of <i>T.m</i>, if <i>T.m</i> exists;
* otherwise the static type of <i>i</i> is dynamic.
- * <p>
+ *
* ... a getter invocation <i>i</i> of the form <i>C.m</i> ...
- * <p>
+ *
* It is a static warning if there is no class <i>C</i> in the enclosing lexical scope of
* <i>i</i>, or if <i>C</i> does not declare, implicitly or explicitly, a getter named <i>m</i>.
- * <p>
+ *
* The static type of <i>i</i> is the declared return type of <i>C.m</i> if it exists or dynamic
* otherwise.
- * <p>
+ *
* ... a top-level getter invocation <i>i</i> of the form <i>m</i>, where <i>m</i> is an
* identifier ...
- * <p>
+ *
* The static type of <i>i</i> is the declared return type of <i>m</i>.</blockquote>
*/
Object visitPropertyAccess(PropertyAccess node) {
@@ -6857,43 +7018,43 @@
/**
* The Dart Language Specification, 12.30: <blockquote>Evaluation of an identifier expression
* <i>e</i> of the form <i>id</i> proceeds as follows:
- * <p>
+ *
* Let <i>d</i> be the innermost declaration in the enclosing lexical scope whose name is
* <i>id</i>. If no such declaration exists in the lexical scope, let <i>d</i> be the declaration
* of the inherited member named <i>id</i> if it exists.
- * <ul>
- * <li>If <i>d</i> is a class or type alias <i>T</i>, the value of <i>e</i> is the unique instance
- * of class {@code Type} reifying <i>T</i>.
- * <li>If <i>d</i> is a type parameter <i>T</i>, then the value of <i>e</i> is the value of the
+ *
+ * * If <i>d</i> is a class or type alias <i>T</i>, the value of <i>e</i> is the unique instance
+ * of class `Type` reifying <i>T</i>.
+ * * If <i>d</i> is a type parameter <i>T</i>, then the value of <i>e</i> is the value of the
* actual type argument corresponding to <i>T</i> that was passed to the generative constructor
* that created the current binding of this. We are assured that this is well defined, because if
* we were in a static member the reference to <i>T</i> would be a compile-time error.
- * <li>If <i>d</i> is a library variable then:
- * <ul>
- * <li>If <i>d</i> is of one of the forms <i>var v = e<sub>i</sub>;</i>, <i>T v =
+ * * If <i>d</i> is a library variable then:
+ *
+ * * If <i>d</i> is of one of the forms <i>var v = e<sub>i</sub>;</i>, <i>T v =
* e<sub>i</sub>;</i>, <i>final v = e<sub>i</sub>;</i>, <i>final T v = e<sub>i</sub>;</i>, and no
* value has yet been stored into <i>v</i> then the initializer expression <i>e<sub>i</sub></i> is
* evaluated. If, during the evaluation of <i>e<sub>i</sub></i>, the getter for <i>v</i> is
* referenced, a CyclicInitializationError is thrown. If the evaluation succeeded yielding an
* object <i>o</i>, let <i>r = o</i>, otherwise let <i>r = null</i>. In any case, <i>r</i> is
* stored into <i>v</i>. The value of <i>e</i> is <i>r</i>.
- * <li>If <i>d</i> is of one of the forms <i>const v = e;</i> or <i>const T v = e;</i> the result
+ * * If <i>d</i> is of one of the forms <i>const v = e;</i> or <i>const T v = e;</i> the result
* of the getter is the value of the compile time constant <i>e</i>. Otherwise
- * <li><i>e</i> evaluates to the current binding of <i>id</i>.
- * </ul>
- * <li>If <i>d</i> is a local variable or formal parameter then <i>e</i> evaluates to the current
+ * * <i>e</i> evaluates to the current binding of <i>id</i>.
+ *
+ * * If <i>d</i> is a local variable or formal parameter then <i>e</i> evaluates to the current
* binding of <i>id</i>.
- * <li>If <i>d</i> is a static method, top level function or local function then <i>e</i>
+ * * If <i>d</i> is a static method, top level function or local function then <i>e</i>
* evaluates to the function defined by <i>d</i>.
- * <li>If <i>d</i> is the declaration of a static variable or static getter declared in class
+ * * If <i>d</i> is the declaration of a static variable or static getter declared in class
* <i>C</i>, then <i>e</i> is equivalent to the getter invocation <i>C.id</i>.
- * <li>If <i>d</i> is the declaration of a top level getter, then <i>e</i> is equivalent to the
+ * * If <i>d</i> is the declaration of a top level getter, then <i>e</i> is equivalent to the
* getter invocation <i>id</i>.
- * <li>Otherwise, if <i>e</i> occurs inside a top level or static function (be it function,
+ * * Otherwise, if <i>e</i> occurs inside a top level or static function (be it function,
* method, getter, or setter) or variable initializer, evaluation of e causes a NoSuchMethodError
* to be thrown.
- * <li>Otherwise <i>e</i> is equivalent to the property extraction <i>this.id</i>.
- * </ul>
+ * * Otherwise <i>e</i> is equivalent to the property extraction <i>this.id</i>.
+ *
* </blockquote>
*/
Object visitSimpleIdentifier(SimpleIdentifier node) {
@@ -6931,7 +7092,7 @@
}
/**
- * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is{@code String}.</blockquote>
+ * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is`String`.</blockquote>
*/
Object visitSimpleStringLiteral(SimpleStringLiteral node) {
recordStaticType(node, _typeProvider.stringType);
@@ -6939,7 +7100,7 @@
}
/**
- * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is{@code String}.</blockquote>
+ * The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is`String`.</blockquote>
*/
Object visitStringInterpolation(StringInterpolation node) {
recordStaticType(node, _typeProvider.stringType);
@@ -6955,7 +7116,7 @@
}
/**
- * The Dart Language Specification, 12.10: <blockquote>The static type of {@code this} is the
+ * The Dart Language Specification, 12.10: <blockquote>The static type of `this` is the
* interface of the immediately enclosing class.</blockquote>
*/
Object visitThisExpression(ThisExpression node) {
@@ -7025,7 +7186,7 @@
if (innerReturnType != null) {
return innerReturnType;
}
- } else if (returnType.isDartCoreFunction()) {
+ } else if (returnType.isDartCoreFunction) {
return _dynamicType;
}
if (returnType != null) {
@@ -7048,7 +7209,7 @@
/**
* Given a function declaration, compute the return type of the function. The return type of
- * functions with a block body is {@code dynamicType}, with an expression body it is the type of
+ * functions with a block body is `dynamicType`, with an expression body it is the type of
* the expression.
* @param node the function expression whose return type is to be computed
* @return the return type that was computed
@@ -7063,7 +7224,7 @@
/**
* Given a function expression, compute the return type of the function. The return type of
- * functions with a block body is {@code dynamicType}, with an expression body it is the type of
+ * functions with a block body is `dynamicType`, with an expression body it is the type of
* the expression.
* @param node the function expression whose return type is to be computed
* @return the return type that was computed
@@ -7196,7 +7357,7 @@
/**
* Return the type that should be recorded for a node that resolved to the given accessor.
* @param accessor the accessor that the node resolved to
- * @param context if the accessor element has context \[by being the RHS of a{@link PrefixedIdentifier} or {@link PropertyAccess}\], and the return type of the
+ * @param context if the accessor element has context \[by being the RHS of a[PrefixedIdentifier] or [PropertyAccess]\], and the return type of the
* accessor is a parameter type, then the type of the LHS can be used to get more
* specific type information
* @return the type that should be recorded for a node that resolved to the given accessor
@@ -7206,7 +7367,7 @@
if (functionType == null) {
return _dynamicType;
}
- if (accessor.isSetter()) {
+ if (accessor.isSetter) {
List<Type2> parameterTypes = functionType.normalParameterTypes;
if (parameterTypes != null && parameterTypes.length > 0) {
return parameterTypes[0];
@@ -7250,16 +7411,16 @@
}
/**
- * Return {@code true} if the given library is the 'dart:html' library.
+ * Return `true` if the given library is the 'dart:html' library.
* @param library the library being tested
- * @return {@code true} if the library is 'dart:html'
+ * @return `true` if the library is 'dart:html'
*/
bool isHtmlLibrary(LibraryElement library) => library.name == "dart.dom.html";
/**
- * Return {@code true} if the given node is not a type literal.
+ * Return `true` if the given node is not a type literal.
* @param node the node being tested
- * @return {@code true} if the given node is not a type literal
+ * @return `true` if the given node is not a type literal
*/
bool isNotTypeLiteral(Identifier node) {
ASTNode parent = node.parent;
@@ -7272,7 +7433,7 @@
* @param type the propagated type of the node
*/
void recordPropagatedType(Expression expression, Type2 type) {
- if (type != null && !type.isDynamic()) {
+ if (type != null && !type.isDynamic) {
expression.propagatedType = type;
}
}
@@ -7320,10 +7481,9 @@
* Set the return type and parameter type information for the given function type based on the
* given return type and parameter elements.
* @param functionType the function type to be filled in
- * @param returnType the return type of the function, or {@code null} if no type was declared
* @param parameters the elements representing the parameters to the function
*/
- void setTypeInformation(FunctionTypeImpl functionType, Type2 returnType2, FormalParameterList parameterList) {
+ void setTypeInformation(FunctionTypeImpl functionType, FormalParameterList parameterList) {
List<Type2> normalParameterTypes = new List<Type2>();
List<Type2> optionalParameterTypes = new List<Type2>();
LinkedHashMap<String, Type2> namedParameterTypes = new LinkedHashMap<String, Type2>();
@@ -7344,19 +7504,18 @@
functionType.normalParameterTypes = new List.from(normalParameterTypes);
functionType.optionalParameterTypes = new List.from(optionalParameterTypes);
functionType.namedParameterTypes = namedParameterTypes;
- functionType.returnType = returnType2;
}
get thisType_J2DAccessor => _thisType;
set thisType_J2DAccessor(__v) => _thisType = __v;
}
/**
- * Instances of the class {@code TypeOverrideManager} manage the ability to override the type of an
+ * Instances of the class `TypeOverrideManager` manage the ability to override the type of an
* element within a given context.
*/
class TypeOverrideManager {
/**
- * The current override scope, or {@code null} if no scope has been entered.
+ * The current override scope, or `null` if no scope has been entered.
*/
TypeOverrideManager_TypeOverrideScope _currentScope;
@@ -7414,7 +7573,7 @@
}
/**
- * Return the overridden type of the given element, or {@code null} if the type of the element has
+ * Return the overridden type of the given element, or `null` if the type of the element has
* not been overridden.
* @param element the element whose type might have been overridden
* @return the overridden type of the given element
@@ -7439,7 +7598,7 @@
}
}
/**
- * Instances of the class {@code TypeOverrideScope} represent a scope in which the types of
+ * Instances of the class `TypeOverrideScope` represent a scope in which the types of
* elements can be overridden.
*/
class TypeOverrideManager_TypeOverrideScope {
@@ -7487,7 +7646,7 @@
*/
Map<Element, Type2> captureOverrides(VariableDeclarationList variableList) {
Map<Element, Type2> overrides = new Map<Element, Type2>();
- if (variableList.isConst() || variableList.isFinal()) {
+ if (variableList.isConst || variableList.isFinal) {
for (VariableDeclaration variable in variableList.variables) {
Element element = variable.element;
if (element != null) {
@@ -7502,7 +7661,7 @@
}
/**
- * Return the overridden type of the given element, or {@code null} if the type of the element
+ * Return the overridden type of the given element, or `null` if the type of the element
* has not been overridden.
* @param element the element whose type might have been overridden
* @return the overridden type of the given element
@@ -7530,7 +7689,7 @@
}
}
/**
- * The interface {@code TypeProvider} defines the behavior of objects that provide access to types
+ * The interface `TypeProvider` defines the behavior of objects that provide access to types
* defined by the language.
* @coverage dart.engine.resolver
*/
@@ -7615,7 +7774,7 @@
InterfaceType get typeType;
}
/**
- * Instances of the class {@code TypeProviderImpl} provide access to types defined by the language
+ * Instances of the class `TypeProviderImpl` provide access to types defined by the language
* by looking for those types in the element model for the core library.
* @coverage dart.engine.resolver
*/
@@ -7708,7 +7867,7 @@
InterfaceType get typeType => _typeType;
/**
- * Return the type with the given name from the given namespace, or {@code null} if there is no
+ * Return the type with the given name from the given namespace, or `null` if there is no
* class with the given name.
* @param namespace the namespace in which to search for the given name
* @param typeName the name of the type being searched for
@@ -7745,7 +7904,7 @@
}
}
/**
- * Instances of the class {@code TypeResolverVisitor} are used to resolve the types associated with
+ * Instances of the class `TypeResolverVisitor` are used to resolve the types associated with
* the elements in the element model. This includes the types of superclasses, mixins, interfaces,
* fields, methods, parameters, and local variables. As a side-effect, this also finishes building
* the type hierarchy.
@@ -7770,9 +7929,9 @@
* @param typeProvider the object used to access the types from the core library
*/
TypeResolverVisitor.con1(Library library, Source source, TypeProvider typeProvider) : super.con1(library, source, typeProvider) {
- _jtd_constructor_281_impl(library, source, typeProvider);
+ _jtd_constructor_282_impl(library, source, typeProvider);
}
- _jtd_constructor_281_impl(Library library, Source source, TypeProvider typeProvider) {
+ _jtd_constructor_282_impl(Library library, Source source, TypeProvider typeProvider) {
_dynamicType = typeProvider.dynamicType;
}
@@ -7786,9 +7945,9 @@
* during resolution
*/
TypeResolverVisitor.con2(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) : super.con2(definingLibrary, source, typeProvider, errorListener) {
- _jtd_constructor_282_impl(definingLibrary, source, typeProvider, errorListener);
+ _jtd_constructor_283_impl(definingLibrary, source, typeProvider, errorListener);
}
- _jtd_constructor_282_impl(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) {
+ _jtd_constructor_283_impl(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) {
_dynamicType = typeProvider.dynamicType;
}
Object visitCatchClause(CatchClause node) {
@@ -7857,9 +8016,11 @@
Object visitConstructorDeclaration(ConstructorDeclaration node) {
super.visitConstructorDeclaration(node);
ExecutableElementImpl element = node.element as ExecutableElementImpl;
+ ClassElement definingClass = element.enclosingElement as ClassElement;
+ element.returnType = definingClass.type;
FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
- setTypeInformation(type, null, element.parameters);
- type.returnType = ((element.enclosingElement as ClassElement)).type;
+ type.typeArguments = definingClass.type.typeArguments;
+ setTypeInformation(type, element.parameters);
element.type = type;
return null;
}
@@ -7900,38 +8061,65 @@
Object visitFunctionDeclaration(FunctionDeclaration node) {
super.visitFunctionDeclaration(node);
ExecutableElementImpl element = node.element as ExecutableElementImpl;
+ element.returnType = computeReturnType(node.returnType);
FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
- setTypeInformation(type, node.returnType, element.parameters);
+ ClassElement definingClass = element.getAncestor(ClassElement);
+ if (definingClass != null) {
+ type.typeArguments = definingClass.type.typeArguments;
+ }
+ setTypeInformation(type, element.parameters);
element.type = type;
return null;
}
Object visitFunctionTypeAlias(FunctionTypeAlias node) {
super.visitFunctionTypeAlias(node);
FunctionTypeAliasElementImpl element = node.element as FunctionTypeAliasElementImpl;
+ element.returnType = computeReturnType(node.returnType);
FunctionTypeImpl type = element.type as FunctionTypeImpl;
- setTypeInformation(type, node.returnType, element.parameters);
+ setTypeInformation(type, element.parameters);
return null;
}
Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
super.visitFunctionTypedFormalParameter(node);
ParameterElementImpl element = node.identifier.element as ParameterElementImpl;
- AnonymousFunctionTypeImpl type = new AnonymousFunctionTypeImpl();
List<ParameterElement> parameters = getElements(node.parameters);
- setTypeInformation(type, node.returnType, parameters);
- type.baseParameters = parameters;
+ FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl(null);
+ aliasElement.synthetic = true;
+ aliasElement.parameters = parameters;
+ aliasElement.returnType = computeReturnType(node.returnType);
+ FunctionTypeImpl type = new FunctionTypeImpl.con2(aliasElement);
+ ClassElement definingClass = element.getAncestor(ClassElement);
+ if (definingClass != null) {
+ aliasElement.typeVariables = definingClass.typeVariables;
+ type.typeArguments = definingClass.type.typeArguments;
+ } else {
+ FunctionTypeAliasElement alias = element.getAncestor(FunctionTypeAliasElement);
+ if (alias != null) {
+ aliasElement.typeVariables = alias.typeVariables;
+ type.typeArguments = alias.type.typeArguments;
+ } else {
+ type.typeArguments = TypeVariableTypeImpl.EMPTY_ARRAY;
+ }
+ }
+ setTypeInformation(type, parameters);
element.type = type;
return null;
}
Object visitMethodDeclaration(MethodDeclaration node) {
super.visitMethodDeclaration(node);
ExecutableElementImpl element = node.element as ExecutableElementImpl;
+ element.returnType = computeReturnType(node.returnType);
FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
- setTypeInformation(type, node.returnType, element.parameters);
+ ClassElement definingClass = element.getAncestor(ClassElement);
+ if (definingClass != null) {
+ type.typeArguments = definingClass.type.typeArguments;
+ }
+ setTypeInformation(type, element.parameters);
element.type = type;
if (element is PropertyAccessorElement) {
PropertyAccessorElement accessor = element as PropertyAccessorElement;
PropertyInducingElementImpl variable = accessor.variable as PropertyInducingElementImpl;
- if (accessor.isGetter()) {
+ if (accessor.isGetter) {
variable.type = type.returnType;
} else if (variable.type == null) {
List<Type2> parameterTypes = type.normalParameterTypes;
@@ -8005,7 +8193,7 @@
if (elementValid && element is! ClassElement && isTypeNameInInstanceCreationExpression(node)) {
SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
InstanceCreationExpression creation = node.parent.parent as InstanceCreationExpression;
- if (creation.isConst()) {
+ if (creation.isConst) {
if (element == null) {
reportError(CompileTimeErrorCode.UNDEFINED_CLASS, typeNameSimple, [typeName]);
} else {
@@ -8143,13 +8331,20 @@
if (element is PropertyInducingElement) {
PropertyInducingElement variableElement = element as PropertyInducingElement;
PropertyAccessorElementImpl getter = variableElement.getter as PropertyAccessorElementImpl;
+ getter.returnType = declaredType;
FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
- getterType.returnType = declaredType;
+ ClassElement definingClass = element.getAncestor(ClassElement);
+ if (definingClass != null) {
+ getterType.typeArguments = definingClass.type.typeArguments;
+ }
getter.type = getterType;
PropertyAccessorElementImpl setter = variableElement.setter as PropertyAccessorElementImpl;
if (setter != null) {
+ setter.returnType = VoidTypeImpl.instance;
FunctionTypeImpl setterType = new FunctionTypeImpl.con1(setter);
- setterType.returnType = VoidTypeImpl.instance;
+ if (definingClass != null) {
+ setterType.typeArguments = definingClass.type.typeArguments;
+ }
setterType.normalParameterTypes = <Type2> [declaredType];
setter.type = setterType;
}
@@ -8160,6 +8355,20 @@
}
/**
+ * Given a type name representing the return type of a function, compute the return type of the
+ * function.
+ * @param returnType the type name representing the return type of the function
+ * @return the return type that was computed
+ */
+ Type2 computeReturnType(TypeName returnType) {
+ if (returnType == null) {
+ return _dynamicType;
+ } else {
+ return returnType.type;
+ }
+ }
+
+ /**
* Return the class element that represents the class whose name was provided.
* @param identifier the name from the declaration of a class
* @return the class element that represents the class
@@ -8205,7 +8414,7 @@
if (parent is ConstructorName) {
parent = parent.parent;
if (parent is InstanceCreationExpression) {
- if (((parent as InstanceCreationExpression)).isConst()) {
+ if (((parent as InstanceCreationExpression)).isConst) {
return CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS;
} else {
return CompileTimeErrorCode.NEW_WITH_INVALID_TYPE_PARAMETERS;
@@ -8217,7 +8426,7 @@
/**
* Given the multiple elements to which a single name could potentially be resolved, return the
- * single interface type that should be used, or {@code null} if there is no clear choice.
+ * single interface type that should be used, or `null` if there is no clear choice.
* @param elements the elements to which a single name could potentially be resolved
* @return the single interface type that should be used for the type name
*/
@@ -8277,7 +8486,7 @@
/**
* Checks if the given type name is used as the type in an as expression.
* @param typeName the type name to analyzer
- * @return {@code true} if the given type name is used as the type in an as expression
+ * @return `true` if the given type name is used as the type in an as expression
*/
bool isTypeNameInAsExpression(TypeName typeName) {
ASTNode parent = typeName.parent;
@@ -8291,7 +8500,7 @@
/**
* Checks if the given type name is used as the exception type in a catch clause.
* @param typeName the type name to analyzer
- * @return {@code true} if the given type name is used as the exception type in a catch clause
+ * @return `true` if the given type name is used as the exception type in a catch clause
*/
bool isTypeNameInCatchClause(TypeName typeName) {
ASTNode parent = typeName.parent;
@@ -8305,7 +8514,7 @@
/**
* Checks if the given type name is used as the type in an instance creation expression.
* @param typeName the type name to analyzer
- * @return {@code true} if the given type name is used as the type in an instance creation
+ * @return `true` if the given type name is used as the type in an instance creation
* expression
*/
bool isTypeNameInInstanceCreationExpression(TypeName typeName) {
@@ -8320,7 +8529,7 @@
/**
* Checks if the given type name is used as the type in an is expression.
* @param typeName the type name to analyzer
- * @return {@code true} if the given type name is used as the type in an is expression
+ * @return `true` if the given type name is used as the type in an is expression
*/
bool isTypeNameInIsExpression(TypeName typeName) {
ASTNode parent = typeName.parent;
@@ -8334,7 +8543,7 @@
/**
* Checks if the given type name is the target in a redirected constructor.
* @param typeName the type name to analyzer
- * @return {@code true} if the given type name is used as the type in a redirected constructor
+ * @return `true` if the given type name is used as the type in a redirected constructor
*/
bool isTypeNameTargetInRedirectedConstructor(TypeName typeName) {
ASTNode parent = typeName.parent;
@@ -8472,10 +8681,9 @@
* Set the return type and parameter type information for the given function type based on the
* given return type and parameter elements.
* @param functionType the function type to be filled in
- * @param returnType the return type of the function, or {@code null} if no type was declared
* @param parameters the elements representing the parameters to the function
*/
- void setTypeInformation(FunctionTypeImpl functionType, TypeName returnType2, List<ParameterElement> parameters) {
+ void setTypeInformation(FunctionTypeImpl functionType, List<ParameterElement> parameters) {
List<Type2> normalParameterTypes = new List<Type2>();
List<Type2> optionalParameterTypes = new List<Type2>();
LinkedHashMap<String, Type2> namedParameterTypes = new LinkedHashMap<String, Type2>();
@@ -8500,15 +8708,10 @@
if (!namedParameterTypes.isEmpty) {
functionType.namedParameterTypes = namedParameterTypes;
}
- if (returnType2 == null) {
- functionType.returnType = _dynamicType;
- } else {
- functionType.returnType = returnType2.type;
- }
}
}
/**
- * Instances of the class {@code ClassScope} implement the scope defined by a class.
+ * Instances of the class `ClassScope` implement the scope defined by a class.
* @coverage dart.engine.resolver
*/
class ClassScope extends EnclosedScope {
@@ -8558,7 +8761,7 @@
}
}
/**
- * Instances of the class {@code EnclosedScope} implement a scope that is lexically enclosed in
+ * Instances of the class `EnclosedScope` implement a scope that is lexically enclosed in
* another scope.
* @coverage dart.engine.resolver
*/
@@ -8593,7 +8796,7 @@
}
}
/**
- * Instances of the class {@code FunctionScope} implement the scope defined by a function.
+ * Instances of the class `FunctionScope` implement the scope defined by a function.
* @coverage dart.engine.resolver
*/
class FunctionScope extends EnclosedScope {
@@ -8620,14 +8823,14 @@
}
}
for (ParameterElement parameter in functionElement.parameters) {
- if (!parameter.isInitializingFormal()) {
+ if (!parameter.isInitializingFormal) {
parameterScope.define(parameter);
}
}
}
}
/**
- * Instances of the class {@code FunctionTypeScope} implement the scope defined by a function type
+ * Instances of the class `FunctionTypeScope` implement the scope defined by a function type
* alias.
* @coverage dart.engine.resolver
*/
@@ -8665,7 +8868,7 @@
}
}
/**
- * Instances of the class {@code LabelScope} represent a scope in which a single label is defined.
+ * Instances of the class `LabelScope` represent a scope in which a single label is defined.
* @coverage dart.engine.resolver
*/
class LabelScope {
@@ -8686,26 +8889,26 @@
LabelElement _element;
/**
- * The marker used to look up a label element for an unlabeled {@code break} or {@code continue}.
+ * The marker used to look up a label element for an unlabeled `break` or `continue`.
*/
static String EMPTY_LABEL = "";
/**
- * The label element returned for scopes that can be the target of an unlabeled {@code break} or{@code continue}.
+ * The label element returned for scopes that can be the target of an unlabeled `break` or`continue`.
*/
static SimpleIdentifier _EMPTY_LABEL_IDENTIFIER = new SimpleIdentifier.full(new sc.StringToken(sc.TokenType.IDENTIFIER, "", 0));
/**
- * Initialize a newly created scope to represent the potential target of an unlabeled{@code break} or {@code continue}.
+ * Initialize a newly created scope to represent the potential target of an unlabeled`break` or `continue`.
* @param outerScope the label scope enclosing the new label scope
- * @param onSwitchStatement {@code true} if this label is associated with a {@code switch}statement
- * @param onSwitchMember {@code true} if this label is associated with a {@code switch} member
+ * @param onSwitchStatement `true` if this label is associated with a `switch`statement
+ * @param onSwitchMember `true` if this label is associated with a `switch` member
*/
LabelScope.con1(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMember) {
- _jtd_constructor_287_impl(outerScope, onSwitchStatement, onSwitchMember);
+ _jtd_constructor_288_impl(outerScope, onSwitchStatement, onSwitchMember);
}
- _jtd_constructor_287_impl(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMember) {
- _jtd_constructor_288_impl(outerScope, EMPTY_LABEL, new LabelElementImpl(_EMPTY_LABEL_IDENTIFIER, onSwitchStatement, onSwitchMember));
+ _jtd_constructor_288_impl(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMember) {
+ _jtd_constructor_289_impl(outerScope, EMPTY_LABEL, new LabelElementImpl(_EMPTY_LABEL_IDENTIFIER, onSwitchStatement, onSwitchMember));
}
/**
@@ -8715,16 +8918,16 @@
* @param element the element to which the label resolves
*/
LabelScope.con2(LabelScope outerScope2, String label2, LabelElement element2) {
- _jtd_constructor_288_impl(outerScope2, label2, element2);
+ _jtd_constructor_289_impl(outerScope2, label2, element2);
}
- _jtd_constructor_288_impl(LabelScope outerScope2, String label2, LabelElement element2) {
+ _jtd_constructor_289_impl(LabelScope outerScope2, String label2, LabelElement element2) {
this._outerScope = outerScope2;
this._label = label2;
this._element = element2;
}
/**
- * Return the label element corresponding to the given label, or {@code null} if the given label
+ * Return the label element corresponding to the given label, or `null` if the given label
* is not defined in this scope.
* @param targetLabel the label being looked up
* @return the label element corresponding to the given label
@@ -8732,7 +8935,7 @@
LabelElement lookup(SimpleIdentifier targetLabel) => lookup2(targetLabel.name);
/**
- * Return the label element corresponding to the given label, or {@code null} if the given label
+ * Return the label element corresponding to the given label, or `null` if the given label
* is not defined in this scope.
* @param targetLabel the label being looked up
* @return the label element corresponding to the given label
@@ -8748,14 +8951,14 @@
}
}
/**
- * Instances of the class {@code LibraryImportScope} represent the scope containing all of the names
+ * Instances of the class `LibraryImportScope` represent the scope containing all of the names
* available from imported libraries.
* @coverage dart.engine.resolver
*/
class LibraryImportScope extends Scope {
/**
- * @return {@code true} if the given {@link Identifier} is the part of type annotation.
+ * @return `true` if the given [Identifier] is the part of type annotation.
*/
static bool isTypeAnnotation(Identifier identifier) {
ASTNode parent = identifier.parent;
@@ -8884,7 +9087,7 @@
}
}
/**
- * Instances of the class {@code LibraryScope} implement a scope containing all of the names defined
+ * Instances of the class `LibraryScope` implement a scope containing all of the names defined
* in a given library.
* @coverage dart.engine.resolver
*/
@@ -8903,7 +9106,7 @@
int offset = duplicate.nameOffset;
if (duplicate is PropertyAccessorElement) {
PropertyAccessorElement accessor = duplicate as PropertyAccessorElement;
- if (accessor.isSynthetic()) {
+ if (accessor.isSynthetic) {
offset = accessor.variable.nameOffset;
}
}
@@ -8949,7 +9152,7 @@
}
}
/**
- * Instances of the class {@code Namespace} implement a mapping of identifiers to the elements
+ * Instances of the class `Namespace` implement a mapping of identifiers to the elements
* represented by those identifiers. Namespaces are the building blocks for scopes.
* @coverage dart.engine.resolver
*/
@@ -8990,14 +9193,14 @@
Map<String, Element> get definedNames => new Map<String, Element>.from(_definedNames);
}
/**
- * Instances of the class {@code NamespaceBuilder} are used to build a {@code Namespace}. Namespace
+ * Instances of the class `NamespaceBuilder` are used to build a `Namespace`. Namespace
* builders are thread-safe and re-usable.
* @coverage dart.engine.resolver
*/
class NamespaceBuilder {
/**
- * Create a namespace representing the export namespace of the given {@link ExportElement}.
+ * Create a namespace representing the export namespace of the given [ExportElement].
* @param element the export element whose export namespace is to be created
* @return the export namespace that was created
*/
@@ -9202,7 +9405,7 @@
}
}
/**
- * The abstract class {@code Scope} defines the behavior common to name scopes used by the resolver
+ * The abstract class `Scope` defines the behavior common to name scopes used by the resolver
* to determine which names are visible at any given point in the code.
* @coverage dart.engine.resolver
*/
@@ -9226,9 +9429,9 @@
static String UNARY_MINUS = "unary-";
/**
- * Return {@code true} if the given name is a library-private name.
+ * Return `true` if the given name is a library-private name.
* @param name the name being tested
- * @return {@code true} if the given name is a library-private name
+ * @return `true` if the given name is a library-private name
*/
static bool isPrivateName(String name) => name != null && name.startsWith(PRIVATE_NAME_PREFIX);
@@ -9257,7 +9460,7 @@
}
/**
- * Return the element with which the given identifier is associated, or {@code null} if the name
+ * Return the element with which the given identifier is associated, or `null` if the name
* is not defined within this scope.
* @param identifier the identifier associated with the element to be returned
* @param referencingLibrary the library that contains the reference to the name, used to
@@ -9318,7 +9521,7 @@
Source get source => definingLibrary.definingCompilationUnit.source;
/**
- * Return the element with which the given name is associated, or {@code null} if the name is not
+ * Return the element with which the given name is associated, or `null` if the name is not
* defined within this scope. This method only returns elements that are directly defined within
* this scope, not elements that are defined in an enclosing scope.
* @param name the name associated with the element to be returned
@@ -9329,7 +9532,7 @@
Element localLookup(String name, LibraryElement referencingLibrary) => _definedNames[name];
/**
- * Return the element with which the given name is associated, or {@code null} if the name is not
+ * Return the element with which the given name is associated, or `null` if the name is not
* defined within this scope.
* @param identifier the identifier node to lookup element for, used to report correct kind of a
* problem and associate problem with
@@ -9356,7 +9559,7 @@
}
}
/**
- * Instances of the class {@code ConstantVerifier} traverse an AST structure looking for additional
+ * Instances of the class `ConstantVerifier` traverse an AST structure looking for additional
* errors and warnings not covered by the parser and resolver. In particular, it looks for errors
* and warnings related to constant expressions.
* @coverage dart.engine.resolver
@@ -9403,6 +9606,7 @@
if (node.constKeyword != null) {
validateInitializers(node);
}
+ validateDefaultValues(node.parameters);
return super.visitConstructorDeclaration(node);
}
Object visitFunctionExpression(FunctionExpression node) {
@@ -9476,7 +9680,7 @@
Object visitVariableDeclaration(VariableDeclaration node) {
super.visitVariableDeclaration(node);
Expression initializer = node.initializer;
- if (initializer != null && node.isConst()) {
+ if (initializer != null && node.isConst) {
VariableElementImpl element = node.element as VariableElementImpl;
EvaluationResultImpl result = element.evaluationResult;
if (result == null) {
@@ -9490,11 +9694,11 @@
}
/**
- * Return {@code true} if the given value is the result of evaluating an expression whose value is
+ * Return `true` if the given value is the result of evaluating an expression whose value is
* a valid key in a const map literal. Keys in const map literals must be either a string, number,
* boolean, list, map, or null.
* @param value
- * @return {@code true} if the given value is a valid key in a const map literal
+ * @return `true` if the given value is a valid key in a const map literal
*/
bool isValidConstMapKey(Object value) => true;
@@ -9519,7 +9723,7 @@
/**
* Validate that the given expression is a compile time constant. Return the value of the compile
- * time constant, or {@code null} if the expression is not a compile time constant.
+ * time constant, or `null` if the expression is not a compile time constant.
* @param expression the expression to be validated
* @param errorCode the error code to be used if the expression is not a compile time constant
* @return the value of the compile time constant
@@ -9536,7 +9740,7 @@
* @param node the instance creation evaluate
*/
void validateConstantArguments(InstanceCreationExpression node) {
- if (!node.isConst()) {
+ if (!node.isConst) {
return;
}
ArgumentList argumentList = node.argumentList;
@@ -9566,10 +9770,8 @@
Expression defaultValue = defaultParameter.defaultValue;
if (defaultValue != null) {
EvaluationResultImpl result = validate(defaultValue, CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE);
- if (defaultParameter.isConst()) {
- VariableElementImpl element = parameter.element as VariableElementImpl;
- element.evaluationResult = result;
- }
+ VariableElementImpl element = parameter.element as VariableElementImpl;
+ element.evaluationResult = result;
}
}
}
@@ -9635,7 +9837,7 @@
if (identical(parameterElement, element) && parameterElement != null) {
Type2 type = parameterElement.type;
if (type != null) {
- if (type.isDynamic()) {
+ if (type.isDynamic) {
return ValidResult.RESULT_DYNAMIC;
}
if (type.isSubtypeOf(ConstantVerifier_this._boolType)) {
@@ -9658,7 +9860,7 @@
}
}
/**
- * Instances of the class {@code ErrorVerifier} traverse an AST structure looking for additional
+ * Instances of the class `ErrorVerifier` traverse an AST structure looking for additional
* errors and warnings not covered by the parser and resolver.
* @coverage dart.engine.resolver
*/
@@ -9667,7 +9869,7 @@
/**
* Checks if the given expression is the reference to the type.
* @param expr the expression to evaluate
- * @return {@code true} if the given expression is the reference to the type
+ * @return `true` if the given expression is the reference to the type
*/
static bool isTypeReference(Expression expr) {
if (expr is Identifier) {
@@ -9709,47 +9911,47 @@
bool _strictMode = false;
/**
- * This is set to {@code true} iff the visitor is currently visiting children nodes of a{@link ConstructorDeclaration} and the constructor is 'const'.
+ * This is set to `true` iff the visitor is currently visiting children nodes of a[ConstructorDeclaration] and the constructor is 'const'.
* @see #visitConstructorDeclaration(ConstructorDeclaration)
*/
bool _isEnclosingConstructorConst = false;
/**
- * This is set to {@code true} iff the visitor is currently visiting children nodes of a{@link CatchClause}.
+ * This is set to `true` iff the visitor is currently visiting children nodes of a[CatchClause].
* @see #visitCatchClause(CatchClause)
*/
bool _isInCatchClause = false;
/**
- * This is set to {@code true} iff the visitor is currently visiting a{@link ConstructorInitializer}.
+ * This is set to `true` iff the visitor is currently visiting a[ConstructorInitializer].
*/
bool _isInConstructorInitializer = false;
/**
- * This is set to {@code true} iff the visitor is currently visiting code in the SDK.
+ * This is set to `true` iff the visitor is currently visiting code in the SDK.
*/
bool _isInSystemLibrary = false;
/**
- * The class containing the AST nodes being visited, or {@code null} if we are not in the scope of
+ * The class containing the AST nodes being visited, or `null` if we are not in the scope of
* a class.
*/
ClassElement _enclosingClass;
/**
- * The method or function that we are currently visiting, or {@code null} if we are not inside a
+ * The method or function that we are currently visiting, or `null` if we are not inside a
* method or function.
*/
ExecutableElement _enclosingFunction;
/**
* This map is initialized when visiting the contents of a class declaration. If the visitor is
- * not in an enclosing class declaration, then the map is set to {@code null}.
- * <p>
- * When set the map maps the set of {@link FieldElement}s in the class to an{@link INIT_STATE#NOT_INIT} or {@link INIT_STATE#INIT_IN_DECLARATION}. <code>checkFor*</code>
- * methods, specifically {@link #checkForAllFinalInitializedErrorCodes(ConstructorDeclaration)},
+ * not in an enclosing class declaration, then the map is set to `null`.
+ *
+ * When set the map maps the set of [FieldElement]s in the class to an[INIT_STATE#NOT_INIT] or [INIT_STATE#INIT_IN_DECLARATION]. <code>checkFor*</code>
+ * methods, specifically [checkForAllFinalInitializedErrorCodes],
* can make a copy of the map to compute error code states. <code>checkFor*</code> methods should
- * only ever make a copy, or read from this map after it has been set in{@link #visitClassDeclaration(ClassDeclaration)}.
+ * only ever make a copy, or read from this map after it has been set in[visitClassDeclaration].
* @see #visitClassDeclaration(ClassDeclaration)
* @see #checkForAllFinalInitializedErrorCodes(ConstructorDeclaration)
*/
@@ -9776,13 +9978,13 @@
Set<String> _namesForReferenceToDeclaredVariableInInitializer = new Set<String>();
/**
- * A list of types used by the {@link CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS} and{@link CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS} error codes.
+ * A list of types used by the [CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS] and[CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS] error codes.
*/
List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT;
ErrorVerifier(ErrorReporter errorReporter, LibraryElement currentLibrary, TypeProvider typeProvider, InheritanceManager inheritanceManager) {
this._errorReporter = errorReporter;
this._currentLibrary = currentLibrary;
- this._isInSystemLibrary = currentLibrary.source.isInSystemLibrary();
+ this._isInSystemLibrary = currentLibrary.source.isInSystemLibrary;
this._typeProvider = typeProvider;
this._inheritanceManager = inheritanceManager;
_strictMode = currentLibrary.context.analysisOptions.strictMode;
@@ -9836,6 +10038,7 @@
ExtendsClause extendsClause = node.extendsClause;
checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
checkForMemberWithClassName();
+ checkForNoDefaultSuperConstructorImplicit(node);
checkForAllMixinErrorCodes(withClause);
if (implementsClause != null || extendsClause != null) {
if (!checkForImplementsDisallowedClass(implementsClause) && !checkForExtendsDisallowedClass(extendsClause)) {
@@ -9849,7 +10052,7 @@
List<FieldElement> fieldElements = classElement.fields;
_initialFieldElementsMap = new Map<FieldElement, INIT_STATE>();
for (FieldElement fieldElement in fieldElements) {
- if (!fieldElement.isSynthetic()) {
+ if (!fieldElement.isSynthetic) {
_initialFieldElementsMap[fieldElement] = fieldElement.initializer == null ? INIT_STATE.NOT_INIT : INIT_STATE.INIT_IN_DECLARATION;
}
}
@@ -9921,10 +10124,16 @@
checkForExportInternalLibrary(node);
return super.visitExportDirective(node);
}
+ Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ FunctionType functionType = _enclosingFunction == null ? null : _enclosingFunction.type;
+ Type2 expectedReturnType = functionType == null ? DynamicTypeImpl.instance : functionType.returnType;
+ checkForReturnOfInvalidType(node.expression, expectedReturnType);
+ return super.visitExpressionFunctionBody(node);
+ }
Object visitFieldDeclaration(FieldDeclaration node) {
- if (!node.isStatic()) {
+ if (!node.isStatic) {
VariableDeclarationList variables = node.fields;
- if (variables.isConst()) {
+ if (variables.isConst) {
_errorReporter.reportError4(CompileTimeErrorCode.CONST_INSTANCE_FIELD, variables.keyword, []);
}
}
@@ -9939,14 +10148,14 @@
ExecutableElement outerFunction = _enclosingFunction;
try {
SimpleIdentifier identifier = node.name;
- String methoName = "";
+ String methodName = "";
if (identifier != null) {
- methoName = identifier.name;
+ methodName = identifier.name;
}
_enclosingFunction = node.element;
- if (node.isSetter() || node.isGetter()) {
- checkForMismatchedAccessorTypes(node, methoName);
- if (node.isSetter()) {
+ if (node.isSetter || node.isGetter) {
+ checkForMismatchedAccessorTypes(node, methodName);
+ if (node.isSetter) {
FunctionExpression functionExpression = node.functionExpression;
if (functionExpression != null) {
checkForWrongNumberOfParametersForSetter(node.name, functionExpression.parameters);
@@ -9961,12 +10170,16 @@
}
}
Object visitFunctionExpression(FunctionExpression node) {
- ExecutableElement outerFunction = _enclosingFunction;
- try {
- _enclosingFunction = node.element;
+ if (node.parent is! FunctionDeclaration) {
+ ExecutableElement outerFunction = _enclosingFunction;
+ try {
+ _enclosingFunction = node.element;
+ return super.visitFunctionExpression(node);
+ } finally {
+ _enclosingFunction = outerFunction;
+ }
+ } else {
return super.visitFunctionExpression(node);
- } finally {
- _enclosingFunction = outerFunction;
}
}
Object visitFunctionTypeAlias(FunctionTypeAlias node) {
@@ -9994,7 +10207,7 @@
if (type is InterfaceType) {
InterfaceType interfaceType = type as InterfaceType;
checkForConstOrNewWithAbstractClass(node, typeName, interfaceType);
- if (node.isConst()) {
+ if (node.isConst) {
checkForConstWithNonConst(node);
checkForConstWithUndefinedConstructor(node);
checkForConstWithTypeParameters(node);
@@ -10040,17 +10253,17 @@
if (identifier != null) {
methoName = identifier.name;
}
- if (node.isSetter() || node.isGetter()) {
+ if (node.isSetter || node.isGetter) {
checkForMismatchedAccessorTypes(node, methoName);
checkForConflictingInstanceGetterAndSuperclassMember(node);
}
- if (node.isGetter()) {
+ if (node.isGetter) {
checkForConflictingStaticGetterAndInstanceSetter(node);
- } else if (node.isSetter()) {
+ } else if (node.isSetter) {
checkForWrongNumberOfParametersForSetter(node.name, node.parameters);
checkForNonVoidReturnTypeForSetter(node.returnType);
checkForConflictingStaticSetterAndInstanceMember(node);
- } else if (node.isOperator()) {
+ } else if (node.isOperator) {
checkForOptionalParameterInOperator(node);
checkForWrongNumberOfParametersForOperator(node);
checkForNonVoidReturnTypeForOperator(node);
@@ -10079,7 +10292,7 @@
return super.visitPrefixedIdentifier(node);
}
Object visitPrefixExpression(PrefixExpression node) {
- if (node.operator.type.isIncrementOperator()) {
+ if (node.operator.type.isIncrementOperator) {
checkForAssignmentToFinal2(node.operand);
}
return super.visitPrefixExpression(node);
@@ -10176,8 +10389,8 @@
/**
* This verifies that the passed constructor declaration does not violate any of the error codes
* relating to the initialization of fields in the enclosing class.
- * @param node the {@link ConstructorDeclaration} to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param node the [ConstructorDeclaration] to evaluate
+ * @return `true` if and only if an error code is generated on the passed node
* @see #initialFieldElementsMap
* @see CompileTimeErrorCode#FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR
* @see CompileTimeErrorCode#FINAL_INITIALIZED_MULTIPLE_TIMES
@@ -10200,12 +10413,12 @@
if (identical(state, INIT_STATE.NOT_INIT)) {
fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_FIELD_FORMAL;
} else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) {
- if (fieldElement.isFinal() || fieldElement.isConst()) {
+ if (fieldElement.isFinal || fieldElement.isConst) {
_errorReporter.reportError2(CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, formalParameter.identifier, [fieldElement.displayName]);
foundError = true;
}
} else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) {
- if (fieldElement.isFinal() || fieldElement.isConst()) {
+ if (fieldElement.isFinal || fieldElement.isConst) {
_errorReporter.reportError2(CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES, formalParameter.identifier, [fieldElement.displayName]);
foundError = true;
}
@@ -10224,7 +10437,7 @@
if (identical(state, INIT_STATE.NOT_INIT)) {
fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS;
} else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) {
- if (fieldElement.isFinal() || fieldElement.isConst()) {
+ if (fieldElement.isFinal || fieldElement.isConst) {
_errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION, fieldName, []);
foundError = true;
}
@@ -10243,8 +10456,8 @@
/**
* This checks the passed method declaration against override-error codes.
- * @param node the {@link MethodDeclaration} to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param node the [MethodDeclaration] to evaluate
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
* @see CompileTimeErrorCode#INVALID_OVERRIDE_REQUIRED
* @see CompileTimeErrorCode#INVALID_OVERRIDE_POSITIONAL
@@ -10255,9 +10468,10 @@
* @see StaticWarningCode#INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE
* @see StaticWarningCode#INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE
* @see StaticWarningCode#INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE
+ * @see StaticWarningCode#INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES
*/
bool checkForAllInvalidOverrideErrorCodes(MethodDeclaration node) {
- if (_enclosingClass == null || node.isStatic() || node.body is NativeFunctionBody) {
+ if (_enclosingClass == null || node.isStatic || node.body is NativeFunctionBody) {
return false;
}
ExecutableElement executableElement = node.element;
@@ -10265,13 +10479,13 @@
return false;
}
SimpleIdentifier methodName = node.name;
- if (methodName.isSynthetic()) {
+ if (methodName.isSynthetic) {
return false;
}
String methodNameStr = methodName.name;
ExecutableElement overriddenExecutable = _inheritanceManager.lookupInheritance(_enclosingClass, executableElement.name);
if (overriddenExecutable == null) {
- if (!node.isGetter() && !node.isSetter() && !node.isOperator()) {
+ if (!node.isGetter && !node.isSetter && !node.isOperator) {
Set<ClassElement> visitedClasses = new Set<ClassElement>();
InterfaceType superclassType = _enclosingClass.supertype;
ClassElement superclassElement = superclassType == null ? null : superclassType.element;
@@ -10279,21 +10493,21 @@
javaSetAdd(visitedClasses, superclassElement);
List<FieldElement> fieldElts = superclassElement.fields;
for (FieldElement fieldElt in fieldElts) {
- if (fieldElt.name == methodNameStr && fieldElt.isStatic()) {
+ if (fieldElt.name == methodNameStr && fieldElt.isStatic) {
_errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, methodName, [methodNameStr, fieldElt.enclosingElement.displayName]);
return true;
}
}
List<PropertyAccessorElement> propertyAccessorElts = superclassElement.accessors;
for (PropertyAccessorElement accessorElt in propertyAccessorElts) {
- if (accessorElt.name == methodNameStr && accessorElt.isStatic()) {
+ if (accessorElt.name == methodNameStr && accessorElt.isStatic) {
_errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, methodName, [methodNameStr, accessorElt.enclosingElement.displayName]);
return true;
}
}
List<MethodElement> methodElements = superclassElement.methods;
for (MethodElement methodElement in methodElements) {
- if (methodElement.name == methodNameStr && methodElement.isStatic()) {
+ if (methodElement.name == methodNameStr && methodElement.isStatic) {
_errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, methodName, [methodNameStr, methodElement.enclosingElement.displayName]);
return true;
}
@@ -10337,7 +10551,7 @@
}
}
if (overriddenFTReturnType != VoidTypeImpl.instance && !overridingFTReturnType.isAssignableTo(overriddenFTReturnType)) {
- _errorReporter.reportError2(!node.isGetter() ? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, methodName, [overridingFTReturnType.displayName, overriddenFTReturnType.displayName, overriddenExecutable.enclosingElement.displayName]);
+ _errorReporter.reportError2(!node.isGetter ? StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, methodName, [overridingFTReturnType.displayName, overriddenFTReturnType.displayName, overriddenExecutable.enclosingElement.displayName]);
return true;
}
FormalParameterList formalParameterList = node.parameters;
@@ -10348,7 +10562,7 @@
int parameterIndex = 0;
for (int i = 0; i < overridingNormalPT.length; i++) {
if (!overridingNormalPT[i].isAssignableTo(overriddenNormalPT[i])) {
- _errorReporter.reportError2(!node.isSetter() ? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE, parameterNodeList[parameterIndex], [overridingNormalPT[i].displayName, overriddenNormalPT[i].displayName, overriddenExecutable.enclosingElement.displayName]);
+ _errorReporter.reportError2(!node.isSetter ? StaticWarningCode.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE, parameterNodeList[parameterIndex], [overridingNormalPT[i].displayName, overriddenNormalPT[i].displayName, overriddenExecutable.enclosingElement.displayName]);
return true;
}
parameterIndex++;
@@ -10385,13 +10599,72 @@
}
}
}
- return false;
+ bool foundError = false;
+ List<FormalParameter> formalParameters = new List<FormalParameter>();
+ List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>();
+ List<ParameterElementImpl> overriddenParameterElts = new List<ParameterElementImpl>();
+ List<ParameterElement> overriddenPEs = overriddenExecutable.parameters;
+ for (FormalParameter formalParameter in parameterNodeList) {
+ if (formalParameter.kind.isOptional) {
+ formalParameters.add(formalParameter);
+ parameterElts.add((formalParameter.element as ParameterElementImpl));
+ }
+ }
+ for (ParameterElement parameterElt in overriddenPEs) {
+ if (parameterElt.parameterKind.isOptional) {
+ overriddenParameterElts.add((parameterElt as ParameterElementImpl));
+ }
+ }
+ if (parameterElts.length > 0) {
+ if (identical(parameterElts[0].parameterKind, ParameterKind.NAMED)) {
+ for (int i = 0; i < parameterElts.length; i++) {
+ ParameterElementImpl parameterElt = parameterElts[i];
+ EvaluationResultImpl result = parameterElt.evaluationResult;
+ if (result == null || identical(result, ValidResult.RESULT_OBJECT)) {
+ continue;
+ }
+ String parameterName = parameterElt.name;
+ for (int j = 0; j < overriddenParameterElts.length; j++) {
+ ParameterElementImpl overriddenParameterElt = overriddenParameterElts[j];
+ String overriddenParameterName = overriddenParameterElt.name;
+ if (parameterName != null && parameterName == overriddenParameterName) {
+ EvaluationResultImpl overriddenResult = overriddenParameterElt.evaluationResult;
+ if (overriddenResult == null || identical(result, ValidResult.RESULT_OBJECT)) {
+ break;
+ }
+ if (!result.equalValues(overriddenResult)) {
+ _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED, formalParameters[i], [overriddenExecutable.enclosingElement.displayName, overriddenExecutable.displayName, parameterName]);
+ foundError = true;
+ }
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < parameterElts.length && i < overriddenParameterElts.length; i++) {
+ ParameterElementImpl parameterElt = parameterElts[i];
+ EvaluationResultImpl result = parameterElt.evaluationResult;
+ if (result == null || identical(result, ValidResult.RESULT_OBJECT)) {
+ continue;
+ }
+ ParameterElementImpl overriddenParameterElt = overriddenParameterElts[i];
+ EvaluationResultImpl overriddenResult = overriddenParameterElt.evaluationResult;
+ if (overriddenResult == null || identical(result, ValidResult.RESULT_OBJECT)) {
+ continue;
+ }
+ if (!result.equalValues(overriddenResult)) {
+ _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL, formalParameters[i], [overriddenExecutable.enclosingElement.displayName, overriddenExecutable.displayName]);
+ foundError = true;
+ }
+ }
+ }
+ }
+ return foundError;
}
/**
* This verifies that all classes of the passed 'with' clause are valid.
* @param node the 'with' clause to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MIXIN_DECLARES_CONSTRUCTOR
* @see CompileTimeErrorCode#MIXIN_INHERITS_FROM_NOT_OBJECT
* @see CompileTimeErrorCode#MIXIN_REFERENCES_SUPER
@@ -10417,7 +10690,7 @@
/**
* This checks error related to the redirected constructors.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#REDIRECT_TO_INVALID_RETURN_TYPE
* @see StaticWarningCode#REDIRECT_TO_INVALID_FUNCTION_TYPE
* @see StaticWarningCode#REDIRECT_TO_MISSING_CONSTRUCTOR
@@ -10459,15 +10732,15 @@
/**
* This checks that the return statement of the form <i>return e;</i> is not in a generative
* constructor.
- * <p>
+ *
* This checks that return statements without expressions are not in a generative constructor and
- * the return type is not assignable to {@code null}; that is, we don't have {@code return;} if
+ * the return type is not assignable to `null`; that is, we don't have `return;` if
* the enclosing method has a return type.
- * <p>
+ *
* This checks that the return type matches the type of the declared return type in the enclosing
* method or function.
* @param node the return statement to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR
* @see StaticWarningCode#RETURN_WITHOUT_VALUE
* @see StaticTypeWarningCode#RETURN_OF_INVALID_TYPE
@@ -10476,7 +10749,7 @@
FunctionType functionType = _enclosingFunction == null ? null : _enclosingFunction.type;
Type2 expectedReturnType = functionType == null ? DynamicTypeImpl.instance : functionType.returnType;
Expression returnExpression = node.expression;
- bool isGenerativeConstructor = _enclosingFunction is ConstructorElement && !((_enclosingFunction as ConstructorElement)).isFactory();
+ bool isGenerativeConstructor = _enclosingFunction is ConstructorElement && !((_enclosingFunction as ConstructorElement)).isFactory;
if (isGenerativeConstructor) {
if (returnExpression == null) {
return false;
@@ -10491,37 +10764,14 @@
_errorReporter.reportError2(StaticWarningCode.RETURN_WITHOUT_VALUE, node, []);
return true;
}
- Type2 staticReturnType = getStaticType(returnExpression);
- if (expectedReturnType.isVoid()) {
- if (staticReturnType.isVoid() || staticReturnType.isDynamic() || identical(staticReturnType, BottomTypeImpl.instance)) {
- return false;
- }
- _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [staticReturnType.displayName, expectedReturnType.displayName, _enclosingFunction.displayName]);
- return true;
- }
- bool isStaticAssignable = staticReturnType.isAssignableTo(expectedReturnType);
- Type2 propagatedReturnType = getPropagatedType(returnExpression);
- if (_strictMode || propagatedReturnType == null) {
- if (isStaticAssignable) {
- return false;
- }
- _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [staticReturnType.displayName, expectedReturnType.displayName, _enclosingFunction.displayName]);
- return true;
- } else {
- bool isPropagatedAssignable = propagatedReturnType.isAssignableTo(expectedReturnType);
- if (isStaticAssignable || isPropagatedAssignable) {
- return false;
- }
- _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [staticReturnType.displayName, expectedReturnType.displayName, _enclosingFunction.displayName]);
- return true;
- }
+ return checkForReturnOfInvalidType(returnExpression, expectedReturnType);
}
/**
* This verifies that the export namespace of the passed export directive does not export any name
* already exported by other export directive.
* @param node the export directive node to report problem on
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#AMBIGUOUS_EXPORT
*/
bool checkForAmbiguousExport(ExportDirective node) {
@@ -10549,8 +10799,8 @@
/**
* This verifies that the passed argument definition test identifier is a parameter.
- * @param node the {@link ArgumentDefinitionTest} to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param node the [ArgumentDefinitionTest] to evaluate
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#ARGUMENT_DEFINITION_TEST_NON_PARAMETER
*/
bool checkForArgumentDefinitionTestNonParameter(ArgumentDefinitionTest node) {
@@ -10566,7 +10816,7 @@
/**
* This verifies that the passed arguments can be assigned to their corresponding parameters.
* @param node the arguments to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
*/
bool checkForArgumentTypeNotAssignable(ArgumentList argumentList) {
@@ -10583,7 +10833,7 @@
/**
* This verifies that the passed argument can be assigned to their corresponding parameters.
* @param node the argument to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
*/
bool checkForArgumentTypeNotAssignable2(Expression argument) {
@@ -10623,7 +10873,7 @@
/**
* This verifies that left hand side of the passed assignment expression is not final.
* @param node the assignment expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#ASSIGNMENT_TO_FINAL
*/
bool checkForAssignmentToFinal(AssignmentExpression node) {
@@ -10634,7 +10884,7 @@
/**
* This verifies that the passed expression is not final.
* @param node the expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#ASSIGNMENT_TO_FINAL
*/
bool checkForAssignmentToFinal2(Expression expression) {
@@ -10647,7 +10897,7 @@
}
if (element is VariableElement) {
VariableElement leftVar = element as VariableElement;
- if (leftVar.isFinal()) {
+ if (leftVar.isFinal) {
_errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_FINAL, expression, []);
return true;
}
@@ -10655,7 +10905,7 @@
}
if (element is PropertyAccessorElement) {
PropertyAccessorElement leftAccessor = element as PropertyAccessorElement;
- if (!leftAccessor.isSetter()) {
+ if (!leftAccessor.isSetter) {
_errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_FINAL, expression, []);
return true;
}
@@ -10669,8 +10919,8 @@
* on the identifier if it is a keyword.
* @param identifier the identifier to check to ensure that it is not a keyword
* @param errorCode if the passed identifier is a keyword then this error code is created on the
- * identifier, the error code will be one of{@link CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_NAME},{@link CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME} or{@link CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME}
- * @return {@code true} if and only if an error code is generated on the passed node
+ * identifier, the error code will be one of[CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_NAME],[CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME] or[CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_NAME
* @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_VARIABLE_NAME
* @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME
@@ -10687,7 +10937,7 @@
/**
* This verifies that the passed variable declaration list does not have a built-in identifier.
* @param node the variable declaration list to check
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE
*/
bool checkForBuiltInIdentifierAsName2(VariableDeclarationList node) {
@@ -10712,7 +10962,7 @@
* This verifies that the given switch case is terminated with 'break', 'continue', 'return' or
* 'throw'.
* @param node the switch case to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CASE_BLOCK_NOT_TERMINATED
*/
bool checkForCaseBlockNotTerminated(SwitchCase node) {
@@ -10747,7 +10997,7 @@
* This verifies that the switch cases in the given switch statement is terminated with 'break',
* 'continue', 'return' or 'throw'.
* @param node the switch statement containing the cases to be checked
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CASE_BLOCK_NOT_TERMINATED
*/
bool checkForCaseBlocksNotTerminated(SwitchStatement node) {
@@ -10767,7 +11017,7 @@
* This verifies that the passed switch statement does not have a case expression with the
* operator '==' overridden.
* @param node the switch statement to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
*/
bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node) {
@@ -10791,11 +11041,11 @@
* This verifies that the passed method declaration is abstract only if the enclosing class is
* also abstract.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CONCRETE_CLASS_WITH_ABSTRACT_MEMBER
*/
bool checkForConcreteClassWithAbstractMember(MethodDeclaration node) {
- if (node.isAbstract() && _enclosingClass != null && !_enclosingClass.isAbstract()) {
+ if (node.isAbstract && _enclosingClass != null && !_enclosingClass.isAbstract) {
SimpleIdentifier methodName = node.name;
_errorReporter.reportError2(StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER, methodName, [methodName.name, _enclosingClass.displayName]);
return true;
@@ -10807,7 +11057,7 @@
* This verifies all possible conflicts of the constructor name with other constructors and
* members of the same class.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_DEFAULT
* @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_NAME
* @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD
@@ -10832,7 +11082,7 @@
return true;
}
}
- if (constructorName != null && constructorElement != null && !constructorName.isSynthetic()) {
+ if (constructorName != null && constructorElement != null && !constructorName.isSynthetic) {
List<FieldElement> fields = classElement.fields;
for (FieldElement field in fields) {
if (field.name == name) {
@@ -10855,12 +11105,12 @@
* This verifies that the superclass of the enclosing class does not declare accessible static
* member with the same name as the passed instance getter/setter method declaration.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER
* @see StaticWarningCode#CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER
*/
bool checkForConflictingInstanceGetterAndSuperclassMember(MethodDeclaration node) {
- if (node.isStatic()) {
+ if (node.isStatic) {
return false;
}
SimpleIdentifier nameNode = node.name;
@@ -10883,12 +11133,12 @@
if (superElement == null) {
return false;
}
- if (!superElement.isStatic()) {
+ if (!superElement.isStatic) {
return false;
}
ClassElement superElementClass = superElement.enclosingElement as ClassElement;
InterfaceType superElementType = superElementClass.type;
- if (node.isGetter()) {
+ if (node.isGetter) {
_errorReporter.reportError2(StaticWarningCode.CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER, nameNode, [superElementType.displayName]);
} else {
_errorReporter.reportError2(StaticWarningCode.CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER, nameNode, [superElementType.displayName]);
@@ -10900,11 +11150,11 @@
* This verifies that the enclosing class does not have an instance member with the same name as
* the passed static getter method declaration.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER
*/
bool checkForConflictingStaticGetterAndInstanceSetter(MethodDeclaration node) {
- if (!node.isStatic()) {
+ if (!node.isStatic) {
return false;
}
SimpleIdentifier nameNode = node.name;
@@ -10920,7 +11170,7 @@
if (setter == null) {
return false;
}
- if (setter.isStatic()) {
+ if (setter.isStatic) {
return false;
}
ClassElement setterClass = setter.enclosingElement as ClassElement;
@@ -10933,11 +11183,11 @@
* This verifies that the enclosing class does not have an instance member with the same name as
* the passed static getter method declaration.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER
*/
bool checkForConflictingStaticSetterAndInstanceMember(MethodDeclaration node) {
- if (!node.isStatic()) {
+ if (!node.isStatic) {
return false;
}
SimpleIdentifier nameNode = node.name;
@@ -10960,7 +11210,7 @@
if (member == null) {
return false;
}
- if (member.isStatic()) {
+ if (member.isStatic) {
return false;
}
ClassElement memberClass = member.enclosingElement as ClassElement;
@@ -10973,7 +11223,7 @@
* This verifies that the passed constructor declaration is 'const' then there are no non-final
* instance variable.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
*/
bool checkForConstConstructorWithNonFinalField(ConstructorDeclaration node) {
@@ -10993,7 +11243,7 @@
* This verifies that the passed throw expression is not enclosed in a 'const' constructor
* declaration.
* @param node the throw expression expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_CONSTRUCTOR_THROWS_EXCEPTION
*/
bool checkForConstEvalThrowsException(ThrowExpression node) {
@@ -11007,11 +11257,11 @@
/**
* This verifies that the passed normal formal parameter is not 'const'.
* @param node the normal formal parameter to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_FORMAL_PARAMETER
*/
bool checkForConstFormalParameter(NormalFormalParameter node) {
- if (node.isConst()) {
+ if (node.isConst) {
_errorReporter.reportError2(CompileTimeErrorCode.CONST_FORMAL_PARAMETER, node, []);
return true;
}
@@ -11022,16 +11272,16 @@
* This verifies that the passed instance creation expression is not being invoked on an abstract
* class.
* @param node the instance creation expression to evaluate
- * @param typeName the {@link TypeName} of the {@link ConstructorName} from the{@link InstanceCreationExpression}, this is the AST node that the error is attached to
- * @param type the type being constructed with this {@link InstanceCreationExpression}
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param typeName the [TypeName] of the [ConstructorName] from the[InstanceCreationExpression], this is the AST node that the error is attached to
+ * @param type the type being constructed with this [InstanceCreationExpression]
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#CONST_WITH_ABSTRACT_CLASS
* @see StaticWarningCode#NEW_WITH_ABSTRACT_CLASS
*/
bool checkForConstOrNewWithAbstractClass(InstanceCreationExpression node, TypeName typeName, InterfaceType type) {
- if (type.element.isAbstract()) {
+ if (type.element.isAbstract) {
ConstructorElement element = node.element;
- if (element != null && !element.isFactory()) {
+ if (element != null && !element.isFactory) {
if (identical(((node.keyword as sc.KeywordToken)).keyword, sc.Keyword.CONST)) {
_errorReporter.reportError2(StaticWarningCode.CONST_WITH_ABSTRACT_CLASS, typeName, []);
} else {
@@ -11046,15 +11296,15 @@
/**
* This verifies that the passed 'const' instance creation expression is not being invoked on a
* constructor that is not 'const'.
- * <p>
+ *
* This method assumes that the instance creation was tested to be 'const' before being called.
* @param node the instance creation expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_WITH_NON_CONST
*/
bool checkForConstWithNonConst(InstanceCreationExpression node) {
ConstructorElement constructorElement = node.element;
- if (constructorElement != null && !constructorElement.isConst()) {
+ if (constructorElement != null && !constructorElement.isConst) {
_errorReporter.reportError2(CompileTimeErrorCode.CONST_WITH_NON_CONST, node, []);
return true;
}
@@ -11064,10 +11314,10 @@
/**
* This verifies that the passed 'const' instance creation expression does not reference any type
* parameters.
- * <p>
+ *
* This method assumes that the instance creation was tested to be 'const' before being called.
* @param node the instance creation expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_WITH_TYPE_PARAMETERS
*/
bool checkForConstWithTypeParameters(InstanceCreationExpression node) {
@@ -11082,7 +11332,7 @@
/**
* This verifies that the passed type name does not reference any type parameters.
* @param typeName the type name to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_WITH_TYPE_PARAMETERS
*/
bool checkForConstWithTypeParameters2(TypeName typeName) {
@@ -11110,10 +11360,10 @@
/**
* This verifies that if the passed 'const' instance creation expression is being invoked on the
* resolved constructor.
- * <p>
+ *
* This method assumes that the instance creation was tested to be 'const' before being called.
* @param node the instance creation expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR
* @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
*/
@@ -11142,7 +11392,7 @@
/**
* This verifies that there are no default parameters in the passed function type alias.
* @param node the function type alias to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS
*/
bool checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias node) {
@@ -11164,7 +11414,7 @@
/**
* This verifies the passed import has unique name among other exported libraries.
* @param node the export directive to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#EXPORT_DUPLICATED_LIBRARY_NAME
*/
bool checkForExportDuplicateLibraryName(ExportDirective node) {
@@ -11194,7 +11444,7 @@
* Check that if the visiting library is not system, then any passed library should not be SDK
* internal library.
* @param node the export directive to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#EXPORT_INTERNAL_LIBRARY
*/
bool checkForExportInternalLibrary(ExportDirective node) {
@@ -11212,7 +11462,7 @@
if (sdkLibrary == null) {
return false;
}
- if (!sdkLibrary.isInternal()) {
+ if (!sdkLibrary.isInternal) {
return false;
}
_errorReporter.reportError2(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, node, [node.uri]);
@@ -11222,7 +11472,7 @@
/**
* This verifies that the passed extends clause does not extend classes such as num or String.
* @param node the extends clause to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
*/
bool checkForExtendsDisallowedClass(ExtendsClause extendsClause) {
@@ -11236,14 +11486,14 @@
* This verifies that the passed type name does not extend or implement classes such as 'num' or
* 'String'.
* @param node the type name to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see #checkForExtendsDisallowedClass(ExtendsClause)
* @see #checkForImplementsDisallowedClass(ImplementsClause)
* @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
* @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
*/
bool checkForExtendsOrImplementsDisallowedClass(TypeName typeName, ErrorCode errorCode) {
- if (typeName.isSynthetic()) {
+ if (typeName.isSynthetic) {
return false;
}
Type2 superType = typeName.type;
@@ -11270,7 +11520,7 @@
* This verifies that the passed constructor field initializer has compatible field and
* initializer expression types.
* @param node the constructor field initializer to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE
* @see StaticWarningCode#FIELD_INITIALIZER_NOT_ASSIGNABLE
*/
@@ -11314,7 +11564,7 @@
/**
* This verifies that the passed field formal parameter is in a constructor declaration.
* @param node the field formal parameter to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
*/
bool checkForFieldInitializingFormalRedirectingConstructor(FieldFormalParameter node) {
@@ -11339,9 +11589,9 @@
/**
* This verifies that final fields that are declared, without any constructors in the enclosing
* class, are initialized. Cases in which there is at least one constructor are handled at the end
- * of {@link #checkForAllFinalInitializedErrorCodes(ConstructorDeclaration)}.
+ * of [checkForAllFinalInitializedErrorCodes].
* @param node the class declaration to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#FINAL_NOT_INITIALIZED
*/
bool checkForFinalNotInitialized(ClassDeclaration node) {
@@ -11363,14 +11613,14 @@
/**
* This verifies that the passed variable declaration list has only initialized variables if the
- * list is final or const. This method is called by{@link #checkForFinalNotInitialized(ClassDeclaration)},{@link #visitTopLevelVariableDeclaration(TopLevelVariableDeclaration)} and{@link #visitVariableDeclarationStatement(VariableDeclarationStatement)}.
+ * list is final or const. This method is called by[checkForFinalNotInitialized],[visitTopLevelVariableDeclaration] and[visitVariableDeclarationStatement].
* @param node the class declaration to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#FINAL_NOT_INITIALIZED
*/
bool checkForFinalNotInitialized2(VariableDeclarationList node) {
bool foundError = false;
- if (!node.isSynthetic() && (node.isConst() || node.isFinal())) {
+ if (!node.isSynthetic && (node.isConst || node.isFinal)) {
NodeList<VariableDeclaration> variables = node.variables;
for (VariableDeclaration variable in variables) {
if (variable.initializer == null) {
@@ -11386,7 +11636,7 @@
* This verifies that the passed implements clause does not implement classes such as 'num' or
* 'String'.
* @param node the implements clause to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
*/
bool checkForImplementsDisallowedClass(ImplementsClause implementsClause) {
@@ -11404,7 +11654,7 @@
* This verifies that if the passed identifier is part of constructor initializer, then it does
* not reference implicitly 'this' expression.
* @param node the simple identifier to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
*/
bool checkForImplicitThisReferenceInInitializer(SimpleIdentifier node) {
@@ -11416,7 +11666,7 @@
return false;
}
ExecutableElement executableElement = element as ExecutableElement;
- if (executableElement.isStatic()) {
+ if (executableElement.isStatic) {
return false;
}
Element enclosingElement = element.enclosingElement;
@@ -11451,7 +11701,7 @@
/**
* This verifies the passed import has unique name among other imported libraries.
* @param node the import directive to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#IMPORT_DUPLICATED_LIBRARY_NAME
*/
bool checkForImportDuplicateLibraryName(ImportDirective node) {
@@ -11481,7 +11731,7 @@
* Check that if the visiting library is not system, then any passed library should not be SDK
* internal library.
* @param node the import directive to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#IMPORT_INTERNAL_LIBRARY
*/
bool checkForImportInternalLibrary(ImportDirective node) {
@@ -11499,7 +11749,7 @@
if (sdkLibrary == null) {
return false;
}
- if (!sdkLibrary.isInternal()) {
+ if (!sdkLibrary.isInternal) {
return false;
}
_errorReporter.reportError2(CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, node, [node.uri]);
@@ -11509,7 +11759,7 @@
/**
* This verifies that the passed switch statement case expressions all have the same type.
* @param node the switch statement to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#INCONSISTENT_CASE_EXPRESSION_TYPES
*/
bool checkForInconsistentCaseExpressionTypes(SwitchStatement node) {
@@ -11537,7 +11787,7 @@
/**
* For each class declaration, this method is called which verifies that all inherited members are
* inherited consistently.
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticTypeWarningCode#INCONSISTENT_METHOD_INHERITANCE
*/
bool checkForInconsistentMethodInheritance() {
@@ -11556,7 +11806,7 @@
* Given an assignment using a compound assignment operator, this verifies that the given
* assignment is valid.
* @param node the assignment expression being tested
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticTypeWarningCode#INVALID_ASSIGNMENT
*/
bool checkForInvalidAssignment(AssignmentExpression node) {
@@ -11585,7 +11835,7 @@
* This verifies that the passed left hand side and right hand side represent a valid assignment.
* @param lhs the left hand side expression
* @param rhs the right hand side expression
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticTypeWarningCode#INVALID_ASSIGNMENT
*/
bool checkForInvalidAssignment2(Expression lhs, Expression rhs) {
@@ -11615,7 +11865,7 @@
/**
* This verifies that the usage of the passed 'this' is valid.
* @param node the 'this' expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#INVALID_REFERENCE_TO_THIS
*/
bool checkForInvalidReferenceToThis(ThisExpression node) {
@@ -11628,8 +11878,8 @@
/**
* Checks to ensure that first type argument to a map literal must be the 'String' type.
- * @param arguments a non-{@code null}, non-empty {@link TypeName} node list from the respective{@link MapLiteral}
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param arguments a non-`null`, non-empty [TypeName] node list from the respective[MapLiteral]
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_FOR_KEY
*/
bool checkForInvalidTypeArgumentForKey(NodeList<TypeName> arguments) {
@@ -11643,11 +11893,11 @@
}
/**
- * Checks to ensure that the passed {@link ListLiteral} or {@link MapLiteral} does not have a type
+ * Checks to ensure that the passed [ListLiteral] or [MapLiteral] does not have a type
* parameter as a type argument.
- * @param arguments a non-{@code null}, non-empty {@link TypeName} node list from the respective{@link ListLiteral} or {@link MapLiteral}
- * @param errorCode either {@link CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_IN_CONST_LIST} or{@link CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_IN_CONST_MAP}
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param arguments a non-`null`, non-empty [TypeName] node list from the respective[ListLiteral] or [MapLiteral]
+ * @param errorCode either [CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_IN_CONST_LIST] or[CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_IN_CONST_MAP]
+ * @return `true` if and only if an error code is generated on the passed node
*/
bool checkForInvalidTypeArgumentInConstTypedLiteral(NodeList<TypeName> arguments, ErrorCode errorCode) {
bool foundError = false;
@@ -11661,9 +11911,9 @@
}
/**
- * This verifies that the {@link #enclosingClass} does not define members with the same name as
+ * This verifies that the [enclosingClass] does not define members with the same name as
* the enclosing class.
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MEMBER_WITH_CLASS_NAME
*/
bool checkForMemberWithClassName() {
@@ -11702,10 +11952,10 @@
}
Type2 getterType = null;
Type2 setterType = null;
- if (propertyAccessorElement.isGetter()) {
+ if (propertyAccessorElement.isGetter) {
getterType = getGetterType(propertyAccessorElement);
setterType = getSetterType(counterpartAccessor);
- } else if (propertyAccessorElement.isSetter()) {
+ } else if (propertyAccessorElement.isSetter) {
setterType = getSetterType(propertyAccessorElement);
counterpartAccessor = propertyAccessorElement.correspondingGetter;
getterType = getGetterType(counterpartAccessor);
@@ -11719,12 +11969,12 @@
* This verifies that the passed mixin does not have an explicitly declared constructor.
* @param mixinName the node to report problem on
* @param mixinElement the mixing to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MIXIN_DECLARES_CONSTRUCTOR
*/
bool checkForMixinDeclaresConstructor(TypeName mixinName, ClassElement mixinElement) {
for (ConstructorElement constructor in mixinElement.constructors) {
- if (!constructor.isSynthetic() && !constructor.isFactory()) {
+ if (!constructor.isSynthetic && !constructor.isFactory) {
_errorReporter.reportError2(CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR, mixinName, [mixinElement.name]);
return true;
}
@@ -11736,13 +11986,13 @@
* This verifies that the passed mixin has the 'Object' superclass.
* @param mixinName the node to report problem on
* @param mixinElement the mixing to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MIXIN_INHERITS_FROM_NOT_OBJECT
*/
bool checkForMixinInheritsNotFromObject(TypeName mixinName, ClassElement mixinElement) {
InterfaceType mixinSupertype = mixinElement.supertype;
if (mixinSupertype != null) {
- if (!mixinSupertype.isObject() || !mixinElement.isTypedef() && mixinElement.mixins.length != 0) {
+ if (!mixinSupertype.isObject || !mixinElement.isTypedef && mixinElement.mixins.length != 0) {
_errorReporter.reportError2(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, mixinName, [mixinElement.name]);
return true;
}
@@ -11754,7 +12004,7 @@
* This verifies that the passed mixin does not reference 'super'.
* @param mixinName the node to report problem on
* @param mixinElement the mixing to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MIXIN_REFERENCES_SUPER
*/
bool checkForMixinReferencesSuper(TypeName mixinName, ClassElement mixinElement) {
@@ -11767,7 +12017,7 @@
/**
* This verifies that the passed constructor has at most one 'super' initializer.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MULTIPLE_SUPER_INITIALIZERS
*/
bool checkForMultipleSuperInitializers(ConstructorDeclaration node) {
@@ -11786,7 +12036,7 @@
/**
* Checks to ensure that native function bodies can only in SDK code.
* @param node the native function body to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see ParserErrorCode#NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
*/
bool checkForNativeFunctionBodyInNonSDKCode(NativeFunctionBody node) {
@@ -11799,10 +12049,10 @@
/**
* This verifies that the passed 'new' instance creation expression invokes existing constructor.
- * <p>
+ *
* This method assumes that the instance creation was tested to be 'new' before being called.
* @param node the instance creation expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#NEW_WITH_UNDEFINED_CONSTRUCTOR
*/
bool checkForNewWithUndefinedConstructor(InstanceCreationExpression node) {
@@ -11828,10 +12078,34 @@
}
/**
+ * This checks that passed if the passed class declaration implicitly calls default constructor of
+ * its superclass, there should be such default constructor - implicit or explicit.
+ * @param node the [ClassDeclaration] to evaluate
+ * @return `true` if and only if an error code is generated on the passed node
+ * @see StaticWarningCode#NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
+ */
+ bool checkForNoDefaultSuperConstructorImplicit(ClassDeclaration node) {
+ List<ConstructorElement> constructors = _enclosingClass.constructors;
+ if (!constructors[0].isSynthetic) {
+ return false;
+ }
+ InterfaceType superType = _enclosingClass.supertype;
+ if (superType == null) {
+ return false;
+ }
+ ClassElement superClass = superType.element;
+ if (superClass.hasDefaultConstructor()) {
+ return false;
+ }
+ _errorReporter.reportError2(StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, node.name, [superType.displayName]);
+ return true;
+ }
+
+ /**
* This checks that passed class declaration overrides all members required by its superclasses
* and interfaces.
- * @param node the {@link ClassDeclaration} to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param node the [ClassDeclaration] to evaluate
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE
* @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO
* @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE
@@ -11839,7 +12113,7 @@
* @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS
*/
bool checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration node) {
- if (_enclosingClass.isAbstract()) {
+ if (_enclosingClass.isAbstract) {
return false;
}
Set<ExecutableElement> missingOverrides = new Set<ExecutableElement>();
@@ -11858,7 +12132,7 @@
ExecutableElement executableElt = entry.getValue();
if (executableElt is MethodElement) {
MethodElement methodElt = executableElt as MethodElement;
- if (methodElt.isAbstract()) {
+ if (methodElt.isAbstract) {
String methodName = entry.getKey();
if (!methodsInEnclosingClass.contains(methodName)) {
javaSetAdd(missingOverrides, executableElt);
@@ -11866,7 +12140,7 @@
}
} else if (executableElt is PropertyAccessorElement) {
PropertyAccessorElement propertyAccessorElt = executableElt as PropertyAccessorElement;
- if (propertyAccessorElt.isAbstract()) {
+ if (propertyAccessorElt.isAbstract) {
String accessorName = entry.getKey();
if (!accessorsInEnclosingClass.contains(accessorName)) {
javaSetAdd(missingOverrides, executableElt);
@@ -11879,9 +12153,9 @@
ExecutableElement executableElt = entry.getValue();
ExecutableElement elt = membersInheritedFromSuperclasses[executableElt.name];
if (elt != null) {
- if (elt is MethodElement && !((elt as MethodElement)).isAbstract()) {
+ if (elt is MethodElement && !((elt as MethodElement)).isAbstract) {
continue;
- } else if (elt is PropertyAccessorElement && !((elt as PropertyAccessorElement)).isAbstract()) {
+ } else if (elt is PropertyAccessorElement && !((elt as PropertyAccessorElement)).isAbstract) {
continue;
}
}
@@ -11908,7 +12182,7 @@
for (int i = 0; i < stringTypeArray.length; i++) {
stringTypeArray[i] = StringUtilities.EMPTY;
if (missingOverridesArray[i] is PropertyAccessorElement) {
- stringTypeArray[i] = ((missingOverridesArray[i] as PropertyAccessorElement)).isGetter() ? GET : SET;
+ stringTypeArray[i] = ((missingOverridesArray[i] as PropertyAccessorElement)).isGetter ? GET : SET;
}
}
AnalysisErrorWithProperties analysisError;
@@ -11932,7 +12206,7 @@
* Checks to ensure that the expressions that need to be of type bool, are. Otherwise an error is
* reported on the expression.
* @param condition the conditional expression to test
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticTypeWarningCode#NON_BOOL_CONDITION
*/
bool checkForNonBoolCondition(Expression condition) {
@@ -11947,7 +12221,7 @@
/**
* This verifies that the passed assert statement has either a 'bool' or '() -> bool' input.
* @param node the assert statement to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticTypeWarningCode#NON_BOOL_EXPRESSION
*/
bool checkForNonBoolExpression(AssertStatement node) {
@@ -11970,13 +12244,13 @@
/**
* This verifies the passed map literal either:
- * <ul>
- * <li>has {@code const modifier}</li>
- * <li>has explicit type arguments</li>
- * <li>is not start of the statement</li>
- * <ul>
+ *
+ * * has `const modifier`
+ * * has explicit type arguments
+ * * is not start of the statement
+ *
* @param node the map literal to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#NON_CONST_MAP_AS_EXPRESSION_STATEMENT
*/
bool checkForNonConstMapAsExpressionStatement(MapLiteral node) {
@@ -11998,10 +12272,10 @@
}
/**
- * This verifies the passed method declaration of operator {@code \[\]=}, has {@code void} return
+ * This verifies the passed method declaration of operator `\[\]=`, has `void` return
* type.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#NON_VOID_RETURN_FOR_OPERATOR
*/
bool checkForNonVoidReturnTypeForOperator(MethodDeclaration node) {
@@ -12012,7 +12286,7 @@
TypeName typeName = node.returnType;
if (typeName != null) {
Type2 type = typeName.type;
- if (type != null && !type.isVoid()) {
+ if (type != null && !type.isVoid) {
_errorReporter.reportError2(StaticWarningCode.NON_VOID_RETURN_FOR_OPERATOR, typeName, []);
}
}
@@ -12020,15 +12294,15 @@
}
/**
- * This verifies the passed setter has no return type or the {@code void} return type.
+ * This verifies the passed setter has no return type or the `void` return type.
* @param typeName the type name to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#NON_VOID_RETURN_FOR_SETTER
*/
bool checkForNonVoidReturnTypeForSetter(TypeName typeName) {
if (typeName != null) {
Type2 type = typeName.type;
- if (type != null && !type.isVoid()) {
+ if (type != null && !type.isVoid) {
_errorReporter.reportError2(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, typeName, []);
}
}
@@ -12037,11 +12311,11 @@
/**
* This verifies the passed operator-method declaration, does not have an optional parameter.
- * <p>
+ *
* This method assumes that the method declaration was tested to be an operator declaration before
* being called.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#OPTIONAL_PARAMETER_IN_OPERATOR
*/
bool checkForOptionalParameterInOperator(MethodDeclaration node) {
@@ -12052,7 +12326,7 @@
bool foundError = false;
NodeList<FormalParameter> formalParameters = parameterList.parameters;
for (FormalParameter formalParameter in formalParameters) {
- if (formalParameter.kind.isOptional()) {
+ if (formalParameter.kind.isOptional) {
_errorReporter.reportError2(CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR, formalParameter, []);
foundError = true;
}
@@ -12063,7 +12337,7 @@
/**
* This checks for named optional parameters that begin with '_'.
* @param node the default formal parameter to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#PRIVATE_OPTIONAL_PARAMETER
*/
bool checkForPrivateOptionalParameter(DefaultFormalParameter node) {
@@ -12071,7 +12345,7 @@
if (separator != null && separator.lexeme == ":") {
NormalFormalParameter parameter = node.parameter;
SimpleIdentifier name = parameter.identifier;
- if (!name.isSynthetic() && name.name.startsWith("_")) {
+ if (!name.isSynthetic && name.name.startsWith("_")) {
_errorReporter.reportError2(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, node, []);
return true;
}
@@ -12083,7 +12357,7 @@
* This checks if the passed constructor declaration is the redirecting generative constructor and
* references itself directly or indirectly.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#RECURSIVE_CONSTRUCTOR_REDIRECT
*/
bool checkForRecursiveConstructorRedirect(ConstructorDeclaration node) {
@@ -12107,7 +12381,7 @@
* This checks if the passed constructor declaration has redirected constructor and references
* itself directly or indirectly.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#RECURSIVE_FACTORY_REDIRECT
*/
bool checkForRecursiveFactoryRedirect(ConstructorDeclaration node) {
@@ -12127,7 +12401,7 @@
* This checks the class declaration is not a superinterface to itself.
* @param classElt the class element to test
* @param list a list containing the potentially cyclic implements path
- * @return {@code true} if and only if an error code is generated on the passed element
+ * @return `true` if and only if an error code is generated on the passed element
* @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE
* @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS
* @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS
@@ -12166,7 +12440,7 @@
}
List<ClassElement> interfaceElements;
List<InterfaceType> interfaceTypes = classElt.interfaces;
- if (supertype != null && !supertype.isObject()) {
+ if (supertype != null && !supertype.isObject) {
interfaceElements = new List<ClassElement>(interfaceTypes.length + 1);
interfaceElements[0] = supertype.element;
for (int i = 0; i < interfaceTypes.length; i++) {
@@ -12191,7 +12465,7 @@
* This checks the passed constructor declaration has a valid combination of redirected
* constructor invocation(s), super constructor invocations and field initializers.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS
* @see CompileTimeErrorCode#SUPER_IN_REDIRECTING_CONSTRUCTOR
* @see CompileTimeErrorCode#FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
@@ -12227,7 +12501,7 @@
* This checks if the passed constructor declaration has redirected constructor and references
* itself directly or indirectly. TODO(scheglov)
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#REDIRECT_TO_NON_CONST_CONSTRUCTOR
*/
bool checkForRedirectToNonConstConstructor(ConstructorDeclaration node) {
@@ -12239,14 +12513,14 @@
if (element == null) {
return false;
}
- if (!element.isConst()) {
+ if (!element.isConst) {
return false;
}
ConstructorElement redirectedConstructor = element.redirectedConstructor;
if (redirectedConstructor == null) {
return false;
}
- if (redirectedConstructor.isConst()) {
+ if (redirectedConstructor.isConst) {
return false;
}
_errorReporter.reportError2(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, redirectedConstructorNode, []);
@@ -12257,7 +12531,7 @@
* This checks if the passed identifier is banned because it is part of the variable declaration
* with the same name.
* @param node the identifier to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER
*/
bool checkForReferenceToDeclaredVariableInInitializer(SimpleIdentifier node) {
@@ -12303,7 +12577,7 @@
/**
* This checks that the rethrow is inside of a catch clause.
* @param node the rethrow expression to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#RETHROW_OUTSIDE_CATCH
*/
bool checkForRethrowOutsideCatch(RethrowExpression node) {
@@ -12315,11 +12589,48 @@
}
/**
+ * This checks that a type mis-match between the return type and the expressed return type by the
+ * enclosing method or function.
+ *
+ * This method is called both by [checkForAllReturnStatementErrorCodes]and [visitExpressionFunctionBody].
+ * @param returnExpression the returned expression to evaluate
+ * @param expectedReturnType the expressed return type by the enclosing method or function
+ * @return `true` if and only if an error code is generated on the passed node
+ * @see StaticTypeWarningCode#RETURN_OF_INVALID_TYPE
+ */
+ bool checkForReturnOfInvalidType(Expression returnExpression, Type2 expectedReturnType) {
+ Type2 staticReturnType = getStaticType(returnExpression);
+ if (expectedReturnType.isVoid) {
+ if (staticReturnType.isVoid || staticReturnType.isDynamic || identical(staticReturnType, BottomTypeImpl.instance)) {
+ return false;
+ }
+ _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [staticReturnType.displayName, expectedReturnType.displayName, _enclosingFunction.displayName]);
+ return true;
+ }
+ bool isStaticAssignable = staticReturnType.isAssignableTo(expectedReturnType);
+ Type2 propagatedReturnType = getPropagatedType(returnExpression);
+ if (_strictMode || propagatedReturnType == null) {
+ if (isStaticAssignable) {
+ return false;
+ }
+ _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [staticReturnType.displayName, expectedReturnType.displayName, _enclosingFunction.displayName]);
+ return true;
+ } else {
+ bool isPropagatedAssignable = propagatedReturnType.isAssignableTo(expectedReturnType);
+ if (isStaticAssignable || isPropagatedAssignable) {
+ return false;
+ }
+ _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [staticReturnType.displayName, expectedReturnType.displayName, _enclosingFunction.displayName]);
+ return true;
+ }
+ }
+
+ /**
* This checks that if the given "target" is the type reference then the "name" is not the
* reference to a instance member.
* @param target the target of the name access to evaluate
* @param name the accessed name to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER
*/
bool checkForStaticAccessToInstanceMember(Expression target, SimpleIdentifier name2) {
@@ -12328,7 +12639,7 @@
return false;
}
ExecutableElement memberElement = element as ExecutableElement;
- if (memberElement.isStatic()) {
+ if (memberElement.isStatic) {
return false;
}
if (!isTypeReference(target)) {
@@ -12342,7 +12653,7 @@
* This checks that the type of the passed 'switch' expression is assignable to the type of the
* 'case' members.
* @param node the 'switch' statement to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticWarningCode#SWITCH_EXPRESSION_NOT_ASSIGNABLE
*/
bool checkForSwitchExpressionNotAssignable(SwitchStatement node) {
@@ -12373,9 +12684,9 @@
* their bounds as specified by the class element where the constructor \[that is being invoked\] is
* declared.
* @param node the instance creation expression to evaluate
- * @param typeName the {@link TypeName} of the {@link ConstructorName} from the{@link InstanceCreationExpression}, this is the AST node that the error is attached to
- * @param constructorElement the {@link ConstructorElement} from the instance creation expression
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param typeName the [TypeName] of the [ConstructorName] from the[InstanceCreationExpression], this is the AST node that the error is attached to
+ * @param constructorElement the [ConstructorElement] from the instance creation expression
+ * @return `true` if and only if an error code is generated on the passed node
* @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
*/
bool checkForTypeArgumentNotMatchingBounds(InstanceCreationExpression node, ConstructorElement constructorElement, TypeName typeName) {
@@ -12403,9 +12714,10 @@
* invocation nor a redirecting constructor invocation, that the superclass has a default
* generative constructor.
* @param node the constructor declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
* @see CompileTimeErrorCode#NON_GENERATIVE_CONSTRUCTOR
+ * @see StaticWarningCode#NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT
*/
bool checkForUndefinedConstructorInInitializerImplicit(ConstructorDeclaration node) {
if (node.factoryKeyword != null) {
@@ -12424,12 +12736,23 @@
return false;
}
ClassElement superElement = superType.element;
- ConstructorElement superDefaultConstructor = superElement.unnamedConstructor;
- if (superDefaultConstructor != null) {
- if (superDefaultConstructor.isFactory()) {
- _errorReporter.reportError2(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node.returnType, [superDefaultConstructor]);
+ ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor;
+ if (superUnnamedConstructor != null) {
+ if (superUnnamedConstructor.isFactory) {
+ _errorReporter.reportError2(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node.returnType, [superUnnamedConstructor]);
return true;
}
+ if (!superUnnamedConstructor.isDefaultConstructor) {
+ int offset;
+ int length;
+ {
+ Identifier returnType = node.returnType;
+ SimpleIdentifier name = node.name;
+ offset = returnType.offset;
+ length = (name != null ? name.end : returnType.end) - offset;
+ }
+ _errorReporter.reportError3(StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, offset, length, [superType.displayName]);
+ }
return false;
}
_errorReporter.reportError2(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT, node.returnType, [superElement.name]);
@@ -12438,11 +12761,11 @@
/**
* This verifies the passed operator-method declaration, has correct number of parameters.
- * <p>
+ *
* This method assumes that the method declaration was tested to be an operator declaration before
* being called.
* @param node the method declaration to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
*/
bool checkForWrongNumberOfParametersForOperator(MethodDeclaration node) {
@@ -12477,11 +12800,11 @@
/**
* This verifies if the passed setter parameter list have only one parameter.
- * <p>
+ *
* This method assumes that the method declaration was tested to be a setter before being called.
* @param setterName the name of the setter to report problems on
* @param parameterList the parameter list to evaluate
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @return `true` if and only if an error code is generated on the passed node
* @see CompileTimeErrorCode#WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER
*/
bool checkForWrongNumberOfParametersForSetter(SimpleIdentifier setterName, FormalParameterList parameterList) {
@@ -12561,7 +12884,7 @@
}
/**
- * Return the variable element represented by the given expression, or {@code null} if there is no
+ * Return the variable element represented by the given expression, or `null` if there is no
* such element.
* @param expression the expression whose element is to be returned
* @return the variable element represented by the expression
@@ -12577,7 +12900,7 @@
}
/**
- * @return {@code true} if the given constructor redirects to itself, directly or indirectly
+ * @return `true` if the given constructor redirects to itself, directly or indirectly
*/
bool hasRedirectingFactoryConstructorCycle(ConstructorElement element) {
Set<ConstructorElement> constructors = new Set<ConstructorElement>();
@@ -12597,7 +12920,7 @@
/**
* @param node the 'this' expression to analyze
- * @return {@code true} if the given 'this' expression is in the valid context
+ * @return `true` if the given 'this' expression is in the valid context
*/
bool isThisInValidContext(ThisExpression node) {
for (ASTNode n = node; n != null; n = n.parent) {
@@ -12613,7 +12936,7 @@
}
if (n is MethodDeclaration) {
MethodDeclaration method = n as MethodDeclaration;
- return !method.isStatic();
+ return !method.isStatic;
}
}
return false;
@@ -12644,7 +12967,7 @@
String toString() => name;
}
/**
- * Instances of the class {@code PubVerifier} traverse an AST structure looking for deviations from
+ * Instances of the class `PubVerifier` traverse an AST structure looking for deviations from
* pub best practices.
*/
class PubVerifier extends RecursiveASTVisitor<Object> {
@@ -12671,9 +12994,9 @@
* This verifies that the passed file import directive is not contained in a source inside a
* package "lib" directory hierarchy referencing a source outside that package "lib" directory
* hierarchy.
- * @param uriLiteral the import URL (not {@code null})
- * @param path the file path being verified (not {@code null})
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param uriLiteral the import URL (not `null`)
+ * @param path the file path being verified (not `null`)
+ * @return `true` if and only if an error code is generated on the passed node
* @see PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE
*/
bool checkForFileImportInsideLibReferencesFileOutside(StringLiteral uriLiteral, String path) {
@@ -12683,7 +13006,7 @@
int pathIndex = 0;
int fullNameIndex = fullName.length;
while (pathIndex < path.length && JavaString.startsWithBefore(path, "../", pathIndex)) {
- fullNameIndex = fullName.lastIndexOf('/', fullNameIndex);
+ fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex);
if (fullNameIndex < 4) {
return false;
}
@@ -12705,9 +13028,9 @@
* This verifies that the passed file import directive is not contained in a source outside a
* package "lib" directory hierarchy referencing a source inside that package "lib" directory
* hierarchy.
- * @param uriLiteral the import URL (not {@code null})
- * @param path the file path being verified (not {@code null})
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param uriLiteral the import URL (not `null`)
+ * @param path the file path being verified (not `null`)
+ * @return `true` if and only if an error code is generated on the passed node
* @see PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE
*/
bool checkForFileImportOutsideLibReferencesFileInside(StringLiteral uriLiteral, String path) {
@@ -12721,7 +13044,7 @@
if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, pathIndex + 1)) {
return true;
}
- pathIndex = path.indexOf("/lib/", pathIndex + 4);
+ pathIndex = JavaString.indexOf(path, "/lib/", pathIndex + 4);
}
return false;
}
@@ -12744,9 +13067,9 @@
/**
* This verifies that the passed package import directive does not contain ".."
- * @param uriLiteral the import URL (not {@code null})
- * @param path the path to be validated (not {@code null})
- * @return {@code true} if and only if an error code is generated on the passed node
+ * @param uriLiteral the import URL (not `null`)
+ * @param path the path to be validated (not `null`)
+ * @return `true` if and only if an error code is generated on the passed node
* @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
*/
bool checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String path) {
@@ -12759,8 +13082,8 @@
/**
* Answer the source associated with the compilation unit containing the given AST node.
- * @param node the node (not {@code null})
- * @return the source or {@code null} if it could not be determined
+ * @param node the node (not `null`)
+ * @return the source or `null` if it could not be determined
*/
Source getSource(ASTNode node) {
Source source = null;
@@ -12775,9 +13098,9 @@
}
/**
- * Answer the full name of the given source. The returned value will have all{@link File#separatorChar} replace by '/'.
+ * Answer the full name of the given source. The returned value will have all[File#separatorChar] replace by '/'.
* @param source the source
- * @return the full name or {@code null} if it could not be determined
+ * @return the full name or `null` if it could not be determined
*/
String getSourceFullName(Source source) {
if (source != null) {
@@ -12790,7 +13113,7 @@
}
}
/**
- * The enumeration {@code ResolverErrorCode} defines the error codes used for errors detected by the
+ * The enumeration `ResolverErrorCode` defines the error codes used for errors detected by the
* resolver. The convention for this class is for the name of the error code to indicate the problem
* that caused the error to be generated and for the error message to explain what is wrong and,
* when appropriate, how the problem can be corrected.
diff --git a/pkg/analyzer_experimental/lib/src/generated/scanner.dart b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
index 7c3c523..24464e6 100644
--- a/pkg/analyzer_experimental/lib/src/generated/scanner.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
@@ -8,7 +8,7 @@
import 'error.dart';
import 'instrumentation.dart';
/**
- * Instances of the abstract class {@code KeywordState} represent a state in a state machine used to
+ * Instances of the abstract class `KeywordState` represent a state in a state machine used to
* scan keywords.
* @coverage dart.engine.parser
*/
@@ -87,12 +87,12 @@
/**
* A table mapping characters to the states to which those characters will transition. (The index
- * into the array is the offset from the character {@code 'a'} to the transitioning character.)
+ * into the array is the offset from the character `'a'` to the transitioning character.)
*/
List<KeywordState> _table;
/**
- * The keyword that is recognized by this state, or {@code null} if this state is not a terminal
+ * The keyword that is recognized by this state, or `null` if this state is not a terminal
* state.
*/
Keyword _keyword2;
@@ -109,21 +109,21 @@
}
/**
- * Return the keyword that was recognized by this state, or {@code null} if this state does not
+ * Return the keyword that was recognized by this state, or `null` if this state does not
* recognized a keyword.
* @return the keyword that was matched by reaching this state
*/
Keyword keyword() => _keyword2;
/**
- * Return the state that follows this state on a transition of the given character, or{@code null} if there is no valid state reachable from this state with such a transition.
+ * Return the state that follows this state on a transition of the given character, or`null` if there is no valid state reachable from this state with such a transition.
* @param c the character used to transition from this state to another state
* @return the state that follows this state on a transition of the given character
*/
KeywordState next(int c) => _table[c - 0x61];
}
/**
- * The enumeration {@code ScannerErrorCode} defines the error codes used for errors detected by the
+ * The enumeration `ScannerErrorCode` defines the error codes used for errors detected by the
* scanner.
* @coverage dart.engine.parser
*/
@@ -162,7 +162,7 @@
String toString() => name;
}
/**
- * Instances of the class {@code TokenWithComment} represent a string token that is preceded by
+ * Instances of the class `TokenWithComment` represent a string token that is preceded by
* comments.
* @coverage dart.engine.parser
*/
@@ -186,7 +186,7 @@
Token get precedingComments => _precedingComment;
}
/**
- * The enumeration {@code Keyword} defines the keywords in the Dart programming language.
+ * The enumeration `Keyword` defines the keywords in the Dart programming language.
* @coverage dart.engine.parser
*/
class Keyword implements Comparable<Keyword> {
@@ -288,9 +288,9 @@
/**
* Initialize a newly created keyword to have the given syntax. The keyword is a pseudo-keyword if
- * the given flag is {@code true}.
+ * the given flag is `true`.
* @param syntax the lexeme for the keyword
- * @param isPseudoKeyword {@code true} if this keyword is a pseudo-keyword
+ * @param isPseudoKeyword `true` if this keyword is a pseudo-keyword
*/
Keyword.con2(this.name, this.ordinal, String syntax2, bool isPseudoKeyword) {
_jtd_constructor_319_impl(syntax2, isPseudoKeyword);
@@ -307,19 +307,19 @@
String get syntax => _syntax;
/**
- * Return {@code true} if this keyword is a pseudo-keyword. Pseudo keywords can be used as
+ * Return `true` if this keyword is a pseudo-keyword. Pseudo keywords can be used as
* identifiers.
- * @return {@code true} if this keyword is a pseudo-keyword
+ * @return `true` if this keyword is a pseudo-keyword
*/
- bool isPseudoKeyword() => _isPseudoKeyword2;
+ bool get isPseudoKeyword => _isPseudoKeyword2;
int compareTo(Keyword other) => ordinal - other.ordinal;
int get hashCode => ordinal;
String toString() => name;
}
/**
- * The abstract class {@code AbstractScanner} implements a scanner for Dart code. Subclasses are
+ * The abstract class `AbstractScanner` implements a scanner for Dart code. Subclasses are
* required to implement the interface used to access the characters being scanned.
- * <p>
+ *
* The lexical structure of Dart is ambiguous without knowledge of the context in which a token is
* being scanned. For example, without context we cannot determine whether source of the form "<<"
* should be scanned as a single left-shift operator or as two left angle brackets. This scanner
@@ -415,8 +415,8 @@
int get offset;
/**
- * Return {@code true} if any unmatched groups were found during the parse.
- * @return {@code true} if any unmatched groups were found during the parse
+ * Return `true` if any unmatched groups were found during the parse.
+ * @return `true` if any unmatched groups were found during the parse
*/
bool hasUnmatchedGroups() => _hasUnmatchedGroups2;
@@ -764,7 +764,7 @@
return next;
}
}
- int select4(int choice, TokenType yesType, TokenType noType, int offset) {
+ int select3(int choice, TokenType yesType, TokenType noType, int offset) {
int next = advance();
if (next == choice) {
appendToken2(yesType, offset);
@@ -871,7 +871,7 @@
if (!hasDigit) {
appendStringToken(TokenType.INT, getString(start, -2));
if (0x2E == next) {
- return select4(0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD, offset - 1);
+ return select3(0x2E, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD, offset - 1);
}
appendToken2(TokenType.PERIOD, offset - 1);
return bigSwitch(next);
@@ -1272,7 +1272,7 @@
}
}
/**
- * Instances of the class {@code StringToken} represent a token whose value is independent of it's
+ * Instances of the class `StringToken` represent a token whose value is independent of it's
* type.
* @coverage dart.engine.parser
*/
@@ -1296,7 +1296,7 @@
String value() => _value2;
}
/**
- * Instances of the class {@code CharBufferScanner} implement a scanner that reads from a character
+ * Instances of the class `CharBufferScanner` implement a scanner that reads from a character
* buffer. The scanning logic is in the superclass.
* @coverage dart.engine.parser
*/
@@ -1344,7 +1344,7 @@
}
}
/**
- * Instances of the class {@code TokenWithComment} represent a normal token that is preceded by
+ * Instances of the class `TokenWithComment` represent a normal token that is preceded by
* comments.
* @coverage dart.engine.parser
*/
@@ -1368,7 +1368,7 @@
Token get precedingComments => _precedingComment;
}
/**
- * Instances of the class {@code Token} represent a token that was scanned from the input. Each
+ * Instances of the class `Token` represent a token that was scanned from the input. Each
* token knows which token follows it, acting as the head of a linked list of tokens.
* @coverage dart.engine.parser
*/
@@ -1437,9 +1437,9 @@
int get offset => _offset;
/**
- * Return the first comment in the list of comments that precede this token, or {@code null} if
+ * Return the first comment in the list of comments that precede this token, or `null` if
* there are no comments preceding this token. Additional comments can be reached by following the
- * token stream using {@link #getNext()} until {@code null} is returned.
+ * token stream using [getNext] until `null` is returned.
* @return the first comment in the list of comments that precede this token
*/
Token get precedingComments => null;
@@ -1457,24 +1457,24 @@
TokenType get type => _type;
/**
- * Return {@code true} if this token represents an operator.
- * @return {@code true} if this token represents an operator
+ * Return `true` if this token represents an operator.
+ * @return `true` if this token represents an operator
*/
- bool isOperator() => _type.isOperator();
+ bool get isOperator => _type.isOperator;
/**
- * Return {@code true} if this token is a synthetic token. A synthetic token is a token that was
+ * Return `true` if this token is a synthetic token. A synthetic token is a token that was
* introduced by the parser in order to recover from an error in the code. Synthetic tokens always
- * have a length of zero ({@code 0}).
- * @return {@code true} if this token is a synthetic token
+ * have a length of zero (`0`).
+ * @return `true` if this token is a synthetic token
*/
- bool isSynthetic() => length == 0;
+ bool get isSynthetic => length == 0;
/**
- * Return {@code true} if this token represents an operator that can be defined by users.
- * @return {@code true} if this token represents an operator that can be defined by users
+ * Return `true` if this token represents an operator that can be defined by users.
+ * @return `true` if this token represents an operator that can be defined by users
*/
- bool isUserDefinableOperator() => _type.isUserDefinableOperator();
+ bool get isUserDefinableOperator => _type.isUserDefinableOperator;
/**
* Set the next token in the token stream to the given token. This has the side-effect of setting
@@ -1525,7 +1525,7 @@
}
}
/**
- * Instances of the class {@code StringScanner} implement a scanner that reads from a string. The
+ * Instances of the class `StringScanner` implement a scanner that reads from a string. The
* scanning logic is in the superclass.
* @coverage dart.engine.parser
*/
@@ -1568,7 +1568,7 @@
/**
* Record that the source begins on the given line and column at the given offset. The line starts
* for lines before the given line will not be correct.
- * <p>
+ *
* This method must be invoked at most one time and must be invoked before scanning begins. The
* values provided must be sensible. The results are undefined if these conditions are violated.
* @param line the one-based index of the line containing the first character of the source
@@ -1604,7 +1604,7 @@
}
}
/**
- * Instances of the class {@code BeginTokenWithComment} represent a begin token that is preceded by
+ * Instances of the class `BeginTokenWithComment` represent a begin token that is preceded by
* comments.
* @coverage dart.engine.parser
*/
@@ -1628,7 +1628,7 @@
Token get precedingComments => _precedingComment;
}
/**
- * Instances of the class {@code KeywordToken} represent a keyword in the language.
+ * Instances of the class `KeywordToken` represent a keyword in the language.
* @coverage dart.engine.parser
*/
class KeywordToken extends Token {
@@ -1656,7 +1656,7 @@
Keyword value() => _keyword;
}
/**
- * Instances of the class {@code BeginToken} represent the opening half of a grouping pair of
+ * Instances of the class `BeginToken` represent the opening half of a grouping pair of
* tokens. This is used for curly brackets ('{'), parentheses ('('), and square brackets ('\[').
* @coverage dart.engine.parser
*/
@@ -1691,7 +1691,7 @@
}
}
/**
- * The enumeration {@code TokenClass} represents classes (or groups) of tokens with a similar use.
+ * The enumeration `TokenClass` represents classes (or groups) of tokens with a similar use.
* @coverage dart.engine.parser
*/
class TokenClass implements Comparable<TokenClass> {
@@ -1784,7 +1784,7 @@
final int ordinal;
/**
- * The precedence of tokens of this class, or {@code 0} if the such tokens do not represent an
+ * The precedence of tokens of this class, or `0` if the such tokens do not represent an
* operator.
*/
int _precedence = 0;
@@ -1802,7 +1802,7 @@
}
/**
- * Return the precedence of tokens of this class, or {@code 0} if the such tokens do not represent
+ * Return the precedence of tokens of this class, or `0` if the such tokens do not represent
* an operator.
* @return the precedence of tokens of this class
*/
@@ -1812,7 +1812,7 @@
String toString() => name;
}
/**
- * Instances of the class {@code KeywordTokenWithComment} implement a keyword token that is preceded
+ * Instances of the class `KeywordTokenWithComment` implement a keyword token that is preceded
* by comments.
* @coverage dart.engine.parser
*/
@@ -1836,7 +1836,7 @@
Token get precedingComments => _precedingComment;
}
/**
- * The enumeration {@code TokenType} defines the types of tokens that can be returned by the
+ * The enumeration `TokenType` defines the types of tokens that can be returned by the
* scanner.
* @coverage dart.engine.parser
*/
@@ -1927,7 +1927,7 @@
TokenClass _tokenClass;
/**
- * The lexeme that defines this type of token, or {@code null} if there is more than one possible
+ * The lexeme that defines this type of token, or `null` if there is more than one possible
* lexeme for this type of token.
*/
String _lexeme;
@@ -1946,95 +1946,95 @@
}
/**
- * Return the lexeme that defines this type of token, or {@code null} if there is more than one
+ * Return the lexeme that defines this type of token, or `null` if there is more than one
* possible lexeme for this type of token.
* @return the lexeme that defines this type of token
*/
String get lexeme => _lexeme;
/**
- * Return the precedence of the token, or {@code 0} if the token does not represent an operator.
+ * Return the precedence of the token, or `0` if the token does not represent an operator.
* @return the precedence of the token
*/
int get precedence => _tokenClass.precedence;
/**
- * Return {@code true} if this type of token represents an additive operator.
- * @return {@code true} if this type of token represents an additive operator
+ * Return `true` if this type of token represents an additive operator.
+ * @return `true` if this type of token represents an additive operator
*/
- bool isAdditiveOperator() => identical(_tokenClass, TokenClass.ADDITIVE_OPERATOR);
+ bool get isAdditiveOperator => identical(_tokenClass, TokenClass.ADDITIVE_OPERATOR);
/**
- * Return {@code true} if this type of token represents an assignment operator.
- * @return {@code true} if this type of token represents an assignment operator
+ * Return `true` if this type of token represents an assignment operator.
+ * @return `true` if this type of token represents an assignment operator
*/
- bool isAssignmentOperator() => identical(_tokenClass, TokenClass.ASSIGNMENT_OPERATOR);
+ bool get isAssignmentOperator => identical(_tokenClass, TokenClass.ASSIGNMENT_OPERATOR);
/**
- * Return {@code true} if this type of token represents an associative operator. An associative
- * operator is an operator for which the following equality is true:{@code (a * b) * c == a * (b * c)}. In other words, if the result of applying the operator to
+ * Return `true` if this type of token represents an associative operator. An associative
+ * operator is an operator for which the following equality is true:`(a * b) * c == a * (b * c)`. In other words, if the result of applying the operator to
* multiple operands does not depend on the order in which those applications occur.
- * <p>
+ *
* Note: This method considers the logical-and and logical-or operators to be associative, even
* though the order in which the application of those operators can have an effect because
* evaluation of the right-hand operand is conditional.
- * @return {@code true} if this type of token represents an associative operator
+ * @return `true` if this type of token represents an associative operator
*/
- bool isAssociativeOperator() => identical(this, AMPERSAND) || identical(this, AMPERSAND_AMPERSAND) || identical(this, BAR) || identical(this, BAR_BAR) || identical(this, CARET) || identical(this, PLUS) || identical(this, STAR);
+ bool get isAssociativeOperator => identical(this, AMPERSAND) || identical(this, AMPERSAND_AMPERSAND) || identical(this, BAR) || identical(this, BAR_BAR) || identical(this, CARET) || identical(this, PLUS) || identical(this, STAR);
/**
- * Return {@code true} if this type of token represents an equality operator.
- * @return {@code true} if this type of token represents an equality operator
+ * Return `true` if this type of token represents an equality operator.
+ * @return `true` if this type of token represents an equality operator
*/
- bool isEqualityOperator() => identical(_tokenClass, TokenClass.EQUALITY_OPERATOR);
+ bool get isEqualityOperator => identical(_tokenClass, TokenClass.EQUALITY_OPERATOR);
/**
- * Return {@code true} if this type of token represents an increment operator.
- * @return {@code true} if this type of token represents an increment operator
+ * Return `true` if this type of token represents an increment operator.
+ * @return `true` if this type of token represents an increment operator
*/
- bool isIncrementOperator() => identical(_lexeme, "++") || identical(_lexeme, "--");
+ bool get isIncrementOperator => identical(_lexeme, "++") || identical(_lexeme, "--");
/**
- * Return {@code true} if this type of token represents a multiplicative operator.
- * @return {@code true} if this type of token represents a multiplicative operator
+ * Return `true` if this type of token represents a multiplicative operator.
+ * @return `true` if this type of token represents a multiplicative operator
*/
- bool isMultiplicativeOperator() => identical(_tokenClass, TokenClass.MULTIPLICATIVE_OPERATOR);
+ bool get isMultiplicativeOperator => identical(_tokenClass, TokenClass.MULTIPLICATIVE_OPERATOR);
/**
- * Return {@code true} if this token type represents an operator.
- * @return {@code true} if this token type represents an operator
+ * Return `true` if this token type represents an operator.
+ * @return `true` if this token type represents an operator
*/
- bool isOperator() => _tokenClass != TokenClass.NO_CLASS && this != OPEN_PAREN && this != OPEN_SQUARE_BRACKET && this != PERIOD;
+ bool get isOperator => _tokenClass != TokenClass.NO_CLASS && this != OPEN_PAREN && this != OPEN_SQUARE_BRACKET && this != PERIOD;
/**
- * Return {@code true} if this type of token represents a relational operator.
- * @return {@code true} if this type of token represents a relational operator
+ * Return `true` if this type of token represents a relational operator.
+ * @return `true` if this type of token represents a relational operator
*/
- bool isRelationalOperator() => identical(_tokenClass, TokenClass.RELATIONAL_OPERATOR);
+ bool get isRelationalOperator => identical(_tokenClass, TokenClass.RELATIONAL_OPERATOR);
/**
- * Return {@code true} if this type of token represents a shift operator.
- * @return {@code true} if this type of token represents a shift operator
+ * Return `true` if this type of token represents a shift operator.
+ * @return `true` if this type of token represents a shift operator
*/
- bool isShiftOperator() => identical(_tokenClass, TokenClass.SHIFT_OPERATOR);
+ bool get isShiftOperator => identical(_tokenClass, TokenClass.SHIFT_OPERATOR);
/**
- * Return {@code true} if this type of token represents a unary postfix operator.
- * @return {@code true} if this type of token represents a unary postfix operator
+ * Return `true` if this type of token represents a unary postfix operator.
+ * @return `true` if this type of token represents a unary postfix operator
*/
- bool isUnaryPostfixOperator() => identical(_tokenClass, TokenClass.UNARY_POSTFIX_OPERATOR);
+ bool get isUnaryPostfixOperator => identical(_tokenClass, TokenClass.UNARY_POSTFIX_OPERATOR);
/**
- * Return {@code true} if this type of token represents a unary prefix operator.
- * @return {@code true} if this type of token represents a unary prefix operator
+ * Return `true` if this type of token represents a unary prefix operator.
+ * @return `true` if this type of token represents a unary prefix operator
*/
- bool isUnaryPrefixOperator() => identical(_tokenClass, TokenClass.UNARY_PREFIX_OPERATOR);
+ bool get isUnaryPrefixOperator => identical(_tokenClass, TokenClass.UNARY_PREFIX_OPERATOR);
/**
- * Return {@code true} if this token type represents an operator that can be defined by users.
- * @return {@code true} if this token type represents an operator that can be defined by users
+ * Return `true` if this token type represents an operator that can be defined by users.
+ * @return `true` if this token type represents an operator that can be defined by users
*/
- bool isUserDefinableOperator() => identical(_lexeme, "==") || identical(_lexeme, "~") || identical(_lexeme, "[]") || identical(_lexeme, "[]=") || identical(_lexeme, "*") || identical(_lexeme, "/") || identical(_lexeme, "%") || identical(_lexeme, "~/") || identical(_lexeme, "+") || identical(_lexeme, "-") || identical(_lexeme, "<<") || identical(_lexeme, ">>") || identical(_lexeme, ">=") || identical(_lexeme, ">") || identical(_lexeme, "<=") || identical(_lexeme, "<") || identical(_lexeme, "&") || identical(_lexeme, "^") || identical(_lexeme, "|");
+ bool get isUserDefinableOperator => identical(_lexeme, "==") || identical(_lexeme, "~") || identical(_lexeme, "[]") || identical(_lexeme, "[]=") || identical(_lexeme, "*") || identical(_lexeme, "/") || identical(_lexeme, "%") || identical(_lexeme, "~/") || identical(_lexeme, "+") || identical(_lexeme, "-") || identical(_lexeme, "<<") || identical(_lexeme, ">>") || identical(_lexeme, ">=") || identical(_lexeme, ">") || identical(_lexeme, "<=") || identical(_lexeme, "<") || identical(_lexeme, "&") || identical(_lexeme, "^") || identical(_lexeme, "|");
int compareTo(TokenType other) => ordinal - other.ordinal;
int get hashCode => ordinal;
String toString() => name;
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
index ca85cf4..4f1cc08 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -17,67 +17,67 @@
String get category;
/**
- * Return the path to the file defining the library. The path is relative to the {@code lib}directory within the SDK.
+ * Return the path to the file defining the library. The path is relative to the `lib`directory within the SDK.
* @return the path to the file defining the library
*/
String get path;
/**
- * Return the short name of the library. This is the name used after {@code dart:} in a URI.
+ * Return the short name of the library. This is the name used after `dart:` in a URI.
* @return the short name of the library
*/
String get shortName;
/**
- * Return {@code true} if this library can be compiled to JavaScript by dart2js.
- * @return {@code true} if this library can be compiled to JavaScript by dart2js
+ * Return `true` if this library can be compiled to JavaScript by dart2js.
+ * @return `true` if this library can be compiled to JavaScript by dart2js
*/
- bool isDart2JsLibrary();
+ bool get isDart2JsLibrary;
/**
- * Return {@code true} if the library is documented.
- * @return {@code true} if the library is documented
+ * Return `true` if the library is documented.
+ * @return `true` if the library is documented
*/
- bool isDocumented();
+ bool get isDocumented;
/**
- * Return {@code true} if the library is an implementation library.
- * @return {@code true} if the library is an implementation library
+ * Return `true` if the library is an implementation library.
+ * @return `true` if the library is an implementation library
*/
- bool isImplementation();
+ bool get isImplementation;
/**
- * Return {@code true} if library is internal can be used only by other SDK libraries.
- * @return {@code true} if library is internal can be used only by other SDK libraries
+ * Return `true` if library is internal can be used only by other SDK libraries.
+ * @return `true` if library is internal can be used only by other SDK libraries
*/
- bool isInternal();
+ bool get isInternal;
/**
- * Return {@code true} if library can be used for both client and server.
- * @return {@code true} if this library can be used for both client and server.
+ * Return `true` if library can be used for both client and server.
+ * @return `true` if this library can be used for both client and server.
*/
- bool isShared();
+ bool get isShared;
/**
- * Return {@code true} if this library can be run on the VM.
- * @return {@code true} if this library can be run on the VM
+ * Return `true` if this library can be run on the VM.
+ * @return `true` if this library can be run on the VM
*/
- bool isVmLibrary();
+ bool get isVmLibrary;
}
/**
- * Instances of the class {@code SdkLibrary} represent the information known about a single library
+ * Instances of the class `SdkLibrary` represent the information known about a single library
* within the SDK.
* @coverage dart.engine.sdk
*/
class SdkLibraryImpl implements SdkLibrary {
/**
- * The short name of the library. This is the name used after {@code dart:} in a URI.
+ * The short name of the library. This is the name used after `dart:` in a URI.
*/
String _shortName = null;
/**
- * The path to the file defining the library. The path is relative to the {@code lib} directory
+ * The path to the file defining the library. The path is relative to the `lib` directory
* within the SDK.
*/
String _path = null;
@@ -125,21 +125,21 @@
String get category => _category;
String get path => _path;
String get shortName => _shortName;
- bool isDart2JsLibrary() => (_platforms & DART2JS_PLATFORM) != 0;
- bool isDocumented() => _documented;
- bool isImplementation() => _implementation;
- bool isInternal() => "Internal" == _category;
+ bool get isDart2JsLibrary => (_platforms & DART2JS_PLATFORM) != 0;
+ bool get isDocumented => _documented;
+ bool get isImplementation => _implementation;
+ bool get isInternal => "Internal" == _category;
/**
- * Return {@code true} if library can be used for both client and server
+ * Return `true` if library can be used for both client and server
*/
- bool isShared() => _category == "Shared";
+ bool get isShared => _category == "Shared";
/**
- * Return {@code true} if this library can be run on the VM.
- * @return {@code true} if this library can be run on the VM
+ * Return `true` if this library can be run on the VM.
+ * @return `true` if this library can be run on the VM
*/
- bool isVmLibrary() => (_platforms & VM_PLATFORM) != 0;
+ bool get isVmLibrary => (_platforms & VM_PLATFORM) != 0;
/**
* Set the name of the category containing the library to the given name.
@@ -158,7 +158,7 @@
/**
* Set whether the library is documented to match the given value.
- * @param documented {@code true} if the library is documented
+ * @param documented `true` if the library is documented
*/
void set documented(bool documented2) {
this._documented = documented2;
@@ -166,14 +166,14 @@
/**
* Set whether the library is an implementation library to match the given value.
- * @param implementation {@code true} if the library is an implementation library
+ * @param implementation `true` if the library is an implementation library
*/
void set implementation(bool implementation2) {
this._implementation = implementation2;
}
/**
- * Set the path to the file defining the library to the given path. The path is relative to the{@code lib} directory within the SDK.
+ * Set the path to the file defining the library to the given path. The path is relative to the`lib` directory within the SDK.
* @param path the path to the file defining the library
*/
void set path(String path2) {
@@ -188,7 +188,7 @@
}
}
/**
- * Instances of the class {@code LibraryMap} map Dart library URI's to the {@link SdkLibraryImpllibrary}.
+ * Instances of the class `LibraryMap` map Dart library URI's to the [SdkLibraryImpllibrary].
* @coverage dart.engine.sdk
*/
class LibraryMap {
@@ -199,14 +199,14 @@
Map<String, SdkLibraryImpl> _libraryMap = new Map<String, SdkLibraryImpl>();
/**
- * Return the library with the given URI, or {@code null} if the URI does not map to a library.
+ * Return the library with the given URI, or `null` if the URI does not map to a library.
* @param dartUri the URI of the library to be returned
* @return the library with the given URI
*/
SdkLibrary getLibrary(String dartUri) => _libraryMap[dartUri];
/**
- * Return an array containing all the sdk libraries {@link SdkLibraryImpl} in the mapping
+ * Return an array containing all the sdk libraries [SdkLibraryImpl] in the mapping
* @return the sdk libraries in the mapping
*/
List<SdkLibrary> get sdkLibraries => new List.from(_libraryMap.values);
@@ -218,7 +218,7 @@
List<String> get uris => new List.from(_libraryMap.keys.toSet());
/**
- * Return the library with the given URI, or {@code null} if the URI does not map to a library.
+ * Return the library with the given URI, or `null` if the URI does not map to a library.
* @param dartUri the URI of the library to be returned
* @param library the library with the given URI
*/
@@ -233,7 +233,7 @@
int size() => _libraryMap.length;
}
/**
- * Instances of the class {@code DartSdk} represent a Dart SDK installed in a specified location.
+ * Instances of the class `DartSdk` represent a Dart SDK installed in a specified location.
* @coverage dart.engine.sdk
*/
abstract class DartSdk {
@@ -264,8 +264,8 @@
Source fromEncoding(ContentCache contentCache, UriKind kind, Uri uri);
/**
- * Return the {@link AnalysisContext} used for all of the sources in this {@link DartSdk}.
- * @return the {@link AnalysisContext} used for all of the sources in this {@link DartSdk}
+ * Return the [AnalysisContext] used for all of the sources in this [DartSdk].
+ * @return the [AnalysisContext] used for all of the sources in this [DartSdk]
*/
AnalysisContext get context;
@@ -276,14 +276,14 @@
List<SdkLibrary> get sdkLibraries;
/**
- * Return the library representing the library with the given {@code dart:} URI, or {@code null}if the given URI does not denote a library in this SDK.
+ * Return the library representing the library with the given `dart:` URI, or `null`if the given URI does not denote a library in this SDK.
* @param dartUri the URI of the library to be returned
* @return the SDK library object
*/
SdkLibrary getSdkLibrary(String dartUri);
/**
- * Return the revision number of this SDK, or {@code "0"} if the revision number cannot be
+ * Return the revision number of this SDK, or `"0"` if the revision number cannot be
* discovered.
* @return the revision number of this SDK
*/
@@ -296,7 +296,7 @@
List<String> get uris;
/**
- * Return the source representing the library with the given {@code dart:} URI, or {@code null} if
+ * Return the source representing the library with the given `dart:` URI, or `null` if
* the given URI does not denote a library in this SDK.
* @param contentCache the content cache used to access the contents of the mapped source
* @param dartUri the URI of the library to be returned
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
index baf26d7..5bcead2 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
@@ -14,14 +14,14 @@
import 'sdk.dart';
import 'engine.dart';
/**
- * Instances of the class {@code DirectoryBasedDartSdk} represent a Dart SDK installed in a
+ * Instances of the class `DirectoryBasedDartSdk` represent a Dart SDK installed in a
* specified directory.
* @coverage dart.engine.sdk
*/
class DirectoryBasedDartSdk implements DartSdk {
/**
- * The {@link AnalysisContext} which is used for all of the sources in this {@link DartSdk}.
+ * The [AnalysisContext] which is used for all of the sources in this [DartSdk].
*/
InternalAnalysisContext _analysisContext;
@@ -31,7 +31,7 @@
JavaFile _sdkDirectory;
/**
- * The revision number of this SDK, or {@code "0"} if the revision number cannot be discovered.
+ * The revision number of this SDK, or `"0"` if the revision number cannot be discovered.
*/
String _sdkVersion;
@@ -81,7 +81,7 @@
static String _DARTIUM_EXECUTABLE_NAME_WIN = "Chrome.exe";
/**
- * The name of the {@link System} property whose value is the path to the default Dart SDK
+ * The name of the [System] property whose value is the path to the default Dart SDK
* directory.
*/
static String _DEFAULT_DIRECTORY_PROPERTY_NAME = "com.google.dart.sdk";
@@ -129,7 +129,7 @@
static String _VM_EXECUTABLE_NAME = "dart";
/**
- * Return the default Dart SDK, or {@code null} if the directory containing the default SDK cannot
+ * Return the default Dart SDK, or `null` if the directory containing the default SDK cannot
* be determined (or does not exist).
* @return the default Dart SDK
*/
@@ -142,10 +142,10 @@
}
/**
- * Return the default directory for the Dart SDK, or {@code null} if the directory cannot be
- * determined (or does not exist). The default directory is provided by a {@link System} property
- * named {@code com.google.dart.sdk}, or, if the property is not defined, an environment variable
- * named {@code DART_SDK}.
+ * Return the default directory for the Dart SDK, or `null` if the directory cannot be
+ * determined (or does not exist). The default directory is provided by a [System] property
+ * named `com.google.dart.sdk`, or, if the property is not defined, an environment variable
+ * named `DART_SDK`.
* @return the default directory for the Dart SDK
*/
static JavaFile get defaultSdkDirectory {
@@ -184,7 +184,7 @@
AnalysisContext get context => _analysisContext;
/**
- * Return the file containing the Dartium executable, or {@code null} if it does not exist.
+ * Return the file containing the Dartium executable, or `null` if it does not exist.
* @return the file containing the Dartium executable
*/
JavaFile get dartiumExecutable {
@@ -219,7 +219,7 @@
JavaFile get docDirectory => new JavaFile.relative(_sdkDirectory, _DOCS_DIRECTORY_NAME);
/**
- * Return the auxiliary documentation file for the given library, or {@code null} if no such file
+ * Return the auxiliary documentation file for the given library, or `null` if no such file
* exists.
* @param libraryName the name of the library associated with the documentation file to be
* returned
@@ -247,7 +247,7 @@
SdkLibrary getSdkLibrary(String dartUri) => _libraryMap.getLibrary(dartUri);
/**
- * Return the revision number of this SDK, or {@code "0"} if the revision number cannot be
+ * Return the revision number of this SDK, or `"0"` if the revision number cannot be
* discovered.
* @return the revision number of this SDK
*/
@@ -275,7 +275,7 @@
List<String> get uris => _libraryMap.uris;
/**
- * Return the file containing the VM executable, or {@code null} if it does not exist.
+ * Return the file containing the VM executable, or `null` if it does not exist.
* @return the file containing the VM executable
*/
JavaFile get vmExecutable {
@@ -291,16 +291,16 @@
}
/**
- * Return {@code true} if this SDK includes documentation.
- * @return {@code true} if this installation of the SDK has documentation
+ * Return `true` if this SDK includes documentation.
+ * @return `true` if this installation of the SDK has documentation
*/
bool hasDocumentation() => docDirectory.exists();
/**
- * Return {@code true} if the Dartium binary is available.
- * @return {@code true} if the Dartium binary is available
+ * Return `true` if the Dartium binary is available.
+ * @return `true` if the Dartium binary is available
*/
- bool isDartiumInstalled() => dartiumExecutable != null;
+ bool get isDartiumInstalled => dartiumExecutable != null;
Source mapDartUri(ContentCache contentCache, String dartUri) {
SdkLibrary library = getSdkLibrary(dartUri);
if (library == null) {
@@ -366,7 +366,7 @@
}
}
/**
- * Instances of the class {@code SdkLibrariesReader} read and parse the libraries file
+ * Instances of the class `SdkLibrariesReader` read and parse the libraries file
* (dart-sdk/lib/_internal/libraries.dart) for information about the libraries in an SDK. The
* library information is represented as a Dart file containing a single top-level variable whose
* value is a const map. The keys of the map are the names of libraries defined in the SDK and the
@@ -438,7 +438,7 @@
static String _PLATFORMS = "platforms";
/**
- * The value of the {@link #PLATFORMS platforms} parameter used to specify that the library can
+ * The value of the [PLATFORMS platforms] parameter used to specify that the library can
* be used on the VM.
*/
static String _VM_PLATFORM = "VM_PLATFORM";
diff --git a/pkg/analyzer_experimental/lib/src/generated/source.dart b/pkg/analyzer_experimental/lib/src/generated/source.dart
index da272e9..d149b4b 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source.dart
@@ -5,7 +5,7 @@
import 'sdk.dart' show DartSdk;
import 'engine.dart' show AnalysisContext;
/**
- * Instances of the class {@code SourceFactory} resolve possibly relative URI's against an existing{@link Source source}.
+ * Instances of the class `SourceFactory` resolve possibly relative URI's against an existing[Source source].
* @coverage dart.engine.source
*/
class SourceFactory {
@@ -50,7 +50,7 @@
}
/**
- * Return a source object representing the given absolute URI, or {@code null} if the URI is not a
+ * Return a source object representing the given absolute URI, or `null` if the URI is not a
* valid URI or if it is not an absolute URI.
* @param absoluteUri the absolute URI to be resolved
* @return a source object representing the absolute URI
@@ -108,9 +108,9 @@
AnalysisContext get context => _context;
/**
- * Return the {@link DartSdk} associated with this {@link SourceFactory}, or {@code null} if there
+ * Return the [DartSdk] associated with this [SourceFactory], or `null` if there
* is no such SDK.
- * @return the {@link DartSdk} associated with this {@link SourceFactory}, or {@code null} if
+ * @return the [DartSdk] associated with this [SourceFactory], or `null` if
* there is no such SDK
*/
DartSdk get dartSdk {
@@ -125,7 +125,7 @@
/**
* Return a source object representing the URI that results from resolving the given (possibly
- * relative) contained URI against the URI associated with an existing source object, or{@code null} if either the contained URI is invalid or if it cannot be resolved against the
+ * relative) contained URI against the URI associated with an existing source object, or`null` if either the contained URI is invalid or if it cannot be resolved against the
* source object's URI.
* @param containingSource the source containing the given URI
* @param containedUri the (possibly relative) URI to be resolved against the containing source
@@ -142,7 +142,7 @@
/**
* Return an absolute URI that represents the given source.
* @param source the source to get URI for
- * @return the absolute URI representing the given source, may be {@code null}
+ * @return the absolute URI representing the given source, may be `null`
*/
Uri restoreUri(Source source) {
for (UriResolver resolver in _resolvers) {
@@ -156,7 +156,7 @@
/**
* Set the contents of the given source to the given contents. This has the effect of overriding
- * the default contents of the source. If the contents are {@code null} the override is removed so
+ * the default contents of the source. If the contents are `null` the override is removed so
* that the default contents will be returned.
* @param source the source whose contents are being overridden
* @param contents the new contents of the source
@@ -167,8 +167,8 @@
/**
* Set the analysis context that this source factory is associated with to the given context.
- * <p>
- * <b>Note:</b> This method should only be invoked by{@link AnalysisContextImpl#setSourceFactory(SourceFactory)} and is only public out of
+ *
+ * <b>Note:</b> This method should only be invoked by[AnalysisContextImpl#setSourceFactory] and is only public out of
* necessity.
* @param context the analysis context that this source factory is associated with
*/
@@ -177,20 +177,20 @@
}
/**
- * Return the contents of the given source, or {@code null} if this factory does not override the
+ * Return the contents of the given source, or `null` if this factory does not override the
* contents of the source.
- * <p>
- * <b>Note:</b> This method is not intended to be used except by{@link FileBasedSource#getContents(com.google.dart.engine.source.Source.ContentReceiver)}.
+ *
+ * <b>Note:</b> This method is not intended to be used except by[FileBasedSource#getContents].
* @param source the source whose content is to be returned
* @return the contents of the given source
*/
String getContents(Source source) => _contentCache.getContents(source);
/**
- * Return the modification stamp of the given source, or {@code null} if this factory does not
+ * Return the modification stamp of the given source, or `null` if this factory does not
* override the contents of the source.
- * <p>
- * <b>Note:</b> This method is not intended to be used except by{@link FileBasedSource#getModificationStamp()}.
+ *
+ * <b>Note:</b> This method is not intended to be used except by[FileBasedSource#getModificationStamp].
* @param source the source whose modification stamp is to be returned
* @return the modification stamp of the given source
*/
@@ -198,7 +198,7 @@
/**
* Return a source object representing the URI that results from resolving the given (possibly
- * relative) contained URI against the URI associated with an existing source object, or{@code null} if either the contained URI is invalid or if it cannot be resolved against the
+ * relative) contained URI against the URI associated with an existing source object, or`null` if either the contained URI is invalid or if it cannot be resolved against the
* source object's URI.
* @param containingSource the source containing the given URI
* @param containedUri the (possibly relative) URI to be resolved against the containing source
@@ -219,7 +219,7 @@
}
}
/**
- * The abstract class {@code UriResolver} defines the behavior of objects that are used to resolve
+ * The abstract class `UriResolver` defines the behavior of objects that are used to resolve
* URI's for a source factory. Subclasses of this class are expected to resolve a single scheme of
* absolute URI.
* @coverage dart.engine.source
@@ -228,34 +228,34 @@
/**
* If this resolver should be used for URI's of the given kind, resolve the given absolute URI.
- * The URI does not need to have the scheme handled by this resolver if the kind matches. Return a{@link Source source} representing the file to which it was resolved, or {@code null} if it
+ * The URI does not need to have the scheme handled by this resolver if the kind matches. Return a[Source source] representing the file to which it was resolved, or `null` if it
* could not be resolved.
* @param contentCache the content cache used to access the contents of the returned source
* @param kind the kind of URI that was originally resolved in order to produce an encoding with
* the given URI
* @param uri the URI to be resolved
- * @return a {@link Source source} representing the file to which given URI was resolved
+ * @return a [Source source] representing the file to which given URI was resolved
*/
Source fromEncoding(ContentCache contentCache, UriKind kind, Uri uri);
/**
- * Resolve the given absolute URI. Return a {@link Source source} representing the file to which
- * it was resolved, or {@code null} if it could not be resolved.
+ * Resolve the given absolute URI. Return a [Source source] representing the file to which
+ * it was resolved, or `null` if it could not be resolved.
* @param contentCache the content cache used to access the contents of the returned source
* @param uri the URI to be resolved
- * @return a {@link Source source} representing the file to which given URI was resolved
+ * @return a [Source source] representing the file to which given URI was resolved
*/
Source resolveAbsolute(ContentCache contentCache, Uri uri);
/**
* Return an absolute URI that represents the given source.
* @param source the source to get URI for
- * @return the absolute URI representing the given source, may be {@code null}
+ * @return the absolute URI representing the given source, may be `null`
*/
Uri restoreAbsolute(Source source) => null;
}
/**
- * The interface {@code Source} defines the behavior of objects representing source code that can be
+ * The interface `Source` defines the behavior of objects representing source code that can be
* compiled.
* @coverage dart.engine.source
*/
@@ -267,18 +267,18 @@
static final List<Source> EMPTY_ARRAY = new List<Source>(0);
/**
- * Return {@code true} if the given object is a source that represents the same source code as
+ * Return `true` if the given object is a source that represents the same source code as
* this source.
* @param object the object to be compared with this object
- * @return {@code true} if the given object is a source that represents the same source code as
+ * @return `true` if the given object is a source that represents the same source code as
* this source
* @see Object#equals(Object)
*/
bool operator ==(Object object);
/**
- * Return {@code true} if this source exists.
- * @return {@code true} if this source exists
+ * Return `true` if this source exists.
+ * @return `true` if this source exists
*/
bool exists();
@@ -342,27 +342,27 @@
int get hashCode;
/**
- * Return {@code true} if this source is in one of the system libraries.
- * @return {@code true} if this is in a system library
+ * Return `true` if this source is in one of the system libraries.
+ * @return `true` if this is in a system library
*/
- bool isInSystemLibrary();
+ bool get isInSystemLibrary;
/**
- * Resolve the relative URI against the URI associated with this source object. Return a{@link Source source} representing the URI to which it was resolved, or {@code null} if it
+ * Resolve the relative URI against the URI associated with this source object. Return a[Source source] representing the URI to which it was resolved, or `null` if it
* could not be resolved.
- * <p>
+ *
* Note: This method is not intended for public use, it is only visible out of necessity. It is
- * only intended to be invoked by a {@link SourceFactory source factory}. Source factories will
+ * only intended to be invoked by a [SourceFactory source factory]. Source factories will
* only invoke this method if the URI is relative, so implementations of this method are not
* required to, and generally do not, verify the argument. The result of invoking this method with
* an absolute URI is intentionally left unspecified.
* @param relativeUri the relative URI to be resolved against the containing source
- * @return a {@link Source source} representing the URI to which given URI was resolved
+ * @return a [Source source] representing the URI to which given URI was resolved
*/
Source resolveRelative(Uri relativeUri);
}
/**
- * The interface {@code ContentReceiver} defines the behavior of objects that can receive the
+ * The interface `ContentReceiver` defines the behavior of objects that can receive the
* content of a source.
*/
abstract class Source_ContentReceiver {
@@ -382,7 +382,7 @@
void accept2(String contents, int modificationTime);
}
/**
- * The enumeration {@code SourceKind} defines the different kinds of sources that are known to the
+ * The enumeration `SourceKind` defines the different kinds of sources that are known to the
* analysis engine.
* @coverage dart.engine.source
*/
@@ -424,7 +424,7 @@
String toString() => name;
}
/**
- * The enumeration {@code UriKind} defines the different kinds of URI's that are known to the
+ * The enumeration `UriKind` defines the different kinds of URI's that are known to the
* analysis engine. These are used to keep track of the kind of URI associated with a given source.
* @coverage dart.engine.source
*/
@@ -466,7 +466,7 @@
}
/**
- * Return the URI kind represented by the given encoding, or {@code null} if there is no kind with
+ * Return the URI kind represented by the given encoding, or `null` if there is no kind with
* the given encoding.
* @param encoding the single character encoding used to identify the URI kind to be returned
* @return the URI kind represented by the given encoding
@@ -495,7 +495,7 @@
String toString() => name;
}
/**
- * A source range defines an {@link Element}'s source coordinates relative to its {@link Source}.
+ * A source range defines an [Element]'s source coordinates relative to its [Source].
* @coverage dart.engine.utilities
*/
class SourceRange {
@@ -523,27 +523,27 @@
}
/**
- * @return {@code true} if <code>x</code> is in \[offset, offset + length) interval.
+ * @return `true` if <code>x</code> is in \[offset, offset + length) interval.
*/
bool contains(int x) => _offset <= x && x < _offset + _length;
/**
- * @return {@code true} if <code>x</code> is in (offset, offset + length) interval.
+ * @return `true` if <code>x</code> is in (offset, offset + length) interval.
*/
bool containsExclusive(int x) => _offset < x && x < _offset + _length;
/**
- * @return {@code true} if <code>otherRange</code> covers this {@link SourceRange}.
+ * @return `true` if <code>otherRange</code> covers this [SourceRange].
*/
bool coveredBy(SourceRange otherRange) => otherRange.covers(this);
/**
- * @return {@code true} if this {@link SourceRange} covers <code>otherRange</code>.
+ * @return `true` if this [SourceRange] covers <code>otherRange</code>.
*/
bool covers(SourceRange otherRange) => offset <= otherRange.offset && otherRange.end <= end;
/**
- * @return {@code true} if this {@link SourceRange} ends in <code>otherRange</code>.
+ * @return `true` if this [SourceRange] ends in <code>otherRange</code>.
*/
bool endsIn(SourceRange otherRange) {
int thisEnd = end;
@@ -564,7 +564,7 @@
int get end => _offset + _length;
/**
- * @return the expanded instance of {@link SourceRange}, which has the same center.
+ * @return the expanded instance of [SourceRange], which has the same center.
*/
SourceRange getExpanded(int delta) => new SourceRange(_offset - delta, delta + _length + delta);
@@ -577,7 +577,7 @@
int get length => _length;
/**
- * @return the instance of {@link SourceRange} with end moved on "delta".
+ * @return the instance of [SourceRange] with end moved on "delta".
*/
SourceRange getMoveEnd(int delta) => new SourceRange(_offset, _length + delta);
@@ -590,13 +590,13 @@
int get offset => _offset;
/**
- * @return the expanded translated of {@link SourceRange}, with moved start and the same length.
+ * @return the expanded translated of [SourceRange], with moved start and the same length.
*/
SourceRange getTranslated(int delta) => new SourceRange(_offset + delta, _length);
int get hashCode => 31 * _offset + _length;
/**
- * @return {@code true} if this {@link SourceRange} intersects with given.
+ * @return `true` if this [SourceRange] intersects with given.
*/
bool intersects(SourceRange other) {
if (other == null) {
@@ -612,7 +612,7 @@
}
/**
- * @return {@code true} if this {@link SourceRange} starts in <code>otherRange</code>.
+ * @return `true` if this [SourceRange] starts in <code>otherRange</code>.
*/
bool startsIn(SourceRange otherRange) => otherRange.contains(_offset);
String toString() {
@@ -626,8 +626,8 @@
}
}
/**
- * The interface {@code SourceContainer} is used by clients to define a collection of sources
- * <p>
+ * The interface `SourceContainer` is used by clients to define a collection of sources
+ *
* Source containers are not used within analysis engine, but can be used by clients to group
* sources for the purposes of accessing composite dependency information. For example, the Eclipse
* client uses source containers to represent Eclipse projects, which allows it to easily compute
@@ -639,12 +639,12 @@
/**
* Determine if the specified source is part of the receiver's collection of sources.
* @param source the source in question
- * @return {@code true} if the receiver contains the source, else {@code false}
+ * @return `true` if the receiver contains the source, else `false`
*/
bool contains(Source source);
}
/**
- * Instances of the class {@code DartUriResolver} resolve {@code dart} URI's.
+ * Instances of the class `DartUriResolver` resolve `dart` URI's.
* @coverage dart.engine.source
*/
class DartUriResolver extends UriResolver {
@@ -655,14 +655,14 @@
DartSdk _sdk;
/**
- * The name of the {@code dart} scheme.
+ * The name of the `dart` scheme.
*/
static String _DART_SCHEME = "dart";
/**
- * Return {@code true} if the given URI is a {@code dart:} URI.
+ * Return `true` if the given URI is a `dart:` URI.
* @param uri the URI being tested
- * @return {@code true} if the given URI is a {@code dart:} URI
+ * @return `true` if the given URI is a `dart:` URI
*/
static bool isDartUri(Uri uri) => _DART_SCHEME == uri.scheme;
@@ -682,8 +682,8 @@
}
/**
- * Return the {@link DartSdk} against which URIs are to be resolved.
- * @return the {@link DartSdk} against which URIs are to be resolved.
+ * Return the [DartSdk] against which URIs are to be resolved.
+ * @return the [DartSdk] against which URIs are to be resolved.
*/
DartSdk get dartSdk => _sdk;
Source resolveAbsolute(ContentCache contentCache, Uri uri) {
@@ -694,7 +694,7 @@
}
}
/**
- * Instances of the class {@code LineInfo} encapsulate information about line and column information
+ * Instances of the class `LineInfo` encapsulate information about line and column information
* within a source file.
* @coverage dart.engine.utilities
*/
@@ -735,7 +735,7 @@
}
}
/**
- * Instances of the class {@code Location} represent the location of a character as a line and
+ * Instances of the class `Location` represent the location of a character as a line and
* column pair.
*/
class LineInfo_Location {
@@ -774,7 +774,7 @@
int get lineNumber => _lineNumber;
}
/**
- * Instances of class {@code ContentCache} hold content used to override the default content of a{@link Source}.
+ * Instances of class `ContentCache` hold content used to override the default content of a[Source].
* @coverage dart.engine.source
*/
class ContentCache {
@@ -792,20 +792,20 @@
Map<Source, int> _stampMap = new Map<Source, int>();
/**
- * Return the contents of the given source, or {@code null} if this cache does not override the
+ * Return the contents of the given source, or `null` if this cache does not override the
* contents of the source.
- * <p>
- * <b>Note:</b> This method is not intended to be used except by{@link SourceFactory#getContents(com.google.dart.engine.source.Source.ContentReceiver)}.
+ *
+ * <b>Note:</b> This method is not intended to be used except by[SourceFactory#getContents].
* @param source the source whose content is to be returned
* @return the contents of the given source
*/
String getContents(Source source) => _contentMap[source];
/**
- * Return the modification stamp of the given source, or {@code null} if this cache does not
+ * Return the modification stamp of the given source, or `null` if this cache does not
* override the contents of the source.
- * <p>
- * <b>Note:</b> This method is not intended to be used except by{@link SourceFactory#getModificationStamp(com.google.dart.engine.source.Source)}.
+ *
+ * <b>Note:</b> This method is not intended to be used except by[SourceFactory#getModificationStamp].
* @param source the source whose modification stamp is to be returned
* @return the modification stamp of the given source
*/
@@ -813,7 +813,7 @@
/**
* Set the contents of the given source to the given contents. This has the effect of overriding
- * the default contents of the source. If the contents are {@code null} the override is removed so
+ * the default contents of the source. If the contents are `null` the override is removed so
* that the default contents will be returned.
* @param source the source whose contents are being overridden
* @param contents the new contents of the source
diff --git a/pkg/analyzer_experimental/lib/src/generated/source_io.dart b/pkg/analyzer_experimental/lib/src/generated/source_io.dart
index 98d8fc0..513f77f 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source_io.dart
@@ -9,7 +9,7 @@
import 'engine.dart' show AnalysisContext, AnalysisEngine;
export 'source.dart';
/**
- * Instances of the class {@code FileBasedSource} implement a source that represents a file.
+ * Instances of the class `FileBasedSource` implement a source that represents a file.
* @coverage dart.engine.source
*/
class FileBasedSource implements Source {
@@ -52,7 +52,7 @@
* Initialize a newly created source object.
* @param contentCache the content cache used to access the contents of this source
* @param file the file represented by this source
- * @param flags {@code true} if this source is in one of the system libraries
+ * @param flags `true` if this source is in one of the system libraries
*/
FileBasedSource.con2(ContentCache contentCache2, JavaFile file2, UriKind uriKind2) {
_jtd_constructor_339_impl(contentCache2, file2, uriKind2);
@@ -87,7 +87,7 @@
String get shortName => _file.getName();
UriKind get uriKind => _uriKind;
int get hashCode => _file.hashCode;
- bool isInSystemLibrary() => identical(_uriKind, UriKind.DART_URI);
+ bool get isInSystemLibrary => identical(_uriKind, UriKind.DART_URI);
Source resolveRelative(Uri containedUri) {
try {
Uri resolvedUri = file.toURI().resolveUri(containedUri);
@@ -105,15 +105,15 @@
/**
* Return the file represented by this source. This is an internal method that is only intended to
- * be used by {@link UriResolver}.
+ * be used by [UriResolver].
* @return the file represented by this source
*/
JavaFile get file => _file;
}
/**
- * Instances of the class {@code PackageUriResolver} resolve {@code package} URI's in the context of
+ * Instances of the class `PackageUriResolver` resolve `package` URI's in the context of
* an application.
- * <p>
+ *
* For the purposes of sharing analysis, the path to each package under the "packages" directory
* should be canonicalized, but to preserve relative links within a package, the remainder of the
* path from the package directory to the leaf should not.
@@ -122,12 +122,12 @@
class PackageUriResolver extends UriResolver {
/**
- * The package directories that {@code package} URI's are assumed to be relative to.
+ * The package directories that `package` URI's are assumed to be relative to.
*/
List<JavaFile> _packagesDirectories;
/**
- * The name of the {@code package} scheme.
+ * The name of the `package` scheme.
*/
static String PACKAGE_SCHEME = "package";
@@ -137,16 +137,16 @@
static bool _CanLogRequiredKeyIoException = true;
/**
- * Return {@code true} if the given URI is a {@code package} URI.
+ * Return `true` if the given URI is a `package` URI.
* @param uri the URI being tested
- * @return {@code true} if the given URI is a {@code package} URI
+ * @return `true` if the given URI is a `package` URI
*/
static bool isPackageUri(Uri uri) => PACKAGE_SCHEME == uri.scheme;
/**
- * Initialize a newly created resolver to resolve {@code package} URI's relative to the given
+ * Initialize a newly created resolver to resolve `package` URI's relative to the given
* package directories.
- * @param packagesDirectories the package directories that {@code package} URI's are assumed to be
+ * @param packagesDirectories the package directories that `package` URI's are assumed to be
* relative to
*/
PackageUriResolver(List<JavaFile> packagesDirectories) {
@@ -216,11 +216,11 @@
/**
* Answer the canonical file for the specified package.
- * @param packagesDirectory the "packages" directory (not {@code null})
- * @param pkgName the package name (not {@code null}, not empty)
- * @param relPath the path relative to the package directory (not {@code null}, no leading slash,
+ * @param packagesDirectory the "packages" directory (not `null`)
+ * @param pkgName the package name (not `null`, not empty)
+ * @param relPath the path relative to the package directory (not `null`, no leading slash,
* but may be empty string)
- * @return the file (not {@code null})
+ * @return the file (not `null`)
*/
JavaFile getCanonicalFile(JavaFile packagesDirectory, String pkgName, String relPath) {
JavaFile pkgDir = new JavaFile.relative(packagesDirectory, pkgName);
@@ -238,7 +238,7 @@
}
}
/**
- * Instances of the class {@link DirectoryBasedSourceContainer} represent a source container that
+ * Instances of the class [DirectoryBasedSourceContainer] represent a source container that
* contains all sources within a given directory.
* @coverage dart.engine.source
*/
@@ -258,14 +258,14 @@
}
/**
- * The container's path (not {@code null}).
+ * The container's path (not `null`).
*/
String _path;
/**
- * Construct a container representing the specified directory and containing any sources whose{@link Source#getFullName()} starts with the directory's path. This is a convenience method,
- * fully equivalent to {@link DirectoryBasedSourceContainer#DirectoryBasedSourceContainer(String)}.
- * @param directory the directory (not {@code null})
+ * Construct a container representing the specified directory and containing any sources whose[Source#getFullName] starts with the directory's path. This is a convenience method,
+ * fully equivalent to [DirectoryBasedSourceContainer#DirectoryBasedSourceContainer].
+ * @param directory the directory (not `null`)
*/
DirectoryBasedSourceContainer.con1(JavaFile directory) {
_jtd_constructor_336_impl(directory);
@@ -275,8 +275,8 @@
}
/**
- * Construct a container representing the specified path and containing any sources whose{@link Source#getFullName()} starts with the specified path.
- * @param path the path (not {@code null} and not empty)
+ * Construct a container representing the specified path and containing any sources whose[Source#getFullName] starts with the specified path.
+ * @param path the path (not `null` and not empty)
*/
DirectoryBasedSourceContainer.con2(String path2) {
_jtd_constructor_337_impl(path2);
@@ -289,27 +289,27 @@
/**
* Answer the receiver's path, used to determine if a source is contained in the receiver.
- * @return the path (not {@code null}, not empty)
+ * @return the path (not `null`, not empty)
*/
String get path => _path;
int get hashCode => _path.hashCode;
String toString() => "SourceContainer[${_path}]";
}
/**
- * Instances of the class {@code FileUriResolver} resolve {@code file} URI's.
+ * Instances of the class `FileUriResolver` resolve `file` URI's.
* @coverage dart.engine.source
*/
class FileUriResolver extends UriResolver {
/**
- * The name of the {@code file} scheme.
+ * The name of the `file` scheme.
*/
static String FILE_SCHEME = "file";
/**
- * Return {@code true} if the given URI is a {@code file} URI.
+ * Return `true` if the given URI is a `file` URI.
* @param uri the URI being tested
- * @return {@code true} if the given URI is a {@code file} URI
+ * @return `true` if the given URI is a `file` URI
*/
static bool isFileUri(Uri uri) => uri.scheme == FILE_SCHEME;
Source fromEncoding(ContentCache contentCache, UriKind kind, Uri uri) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/utilities_dart.dart b/pkg/analyzer_experimental/lib/src/generated/utilities_dart.dart
index 80804cd..0a331cb 100644
--- a/pkg/analyzer_experimental/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/utilities_dart.dart
@@ -2,7 +2,7 @@
// significant change. Please see the README file for more information.
library engine.utilities.dart;
/**
- * The enumeration {@code ParameterKind} defines the different kinds of parameters. There are two
+ * The enumeration `ParameterKind` defines the different kinds of parameters. There are two
* basic kinds of parameters: required and optional. Optional parameters are further divided into
* two kinds: positional optional and named optional.
* @coverage dart.engine.utilities
@@ -26,17 +26,17 @@
/**
* Initialize a newly created kind with the given state.
- * @param isOptional {@code true} if this is an optional parameter
+ * @param isOptional `true` if this is an optional parameter
*/
ParameterKind(this.name, this.ordinal, bool isOptional) {
this._isOptional2 = isOptional;
}
/**
- * Return {@code true} if this is an optional parameter.
- * @return {@code true} if this is an optional parameter
+ * Return `true` if this is an optional parameter.
+ * @return `true` if this is an optional parameter
*/
- bool isOptional() => _isOptional2;
+ bool get isOptional => _isOptional2;
int compareTo(ParameterKind other) => ordinal - other.ordinal;
int get hashCode => ordinal;
String toString() => name;
diff --git a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
index 72288144..410d5b0 100644
--- a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
@@ -83,22 +83,23 @@
class CodeFormatterImpl implements CodeFormatter, AnalysisErrorListener {
final FormatterOptions options;
- final List<AnalysisError> errors = <AnalysisError>[];
+ final EditRecorder recorder;
+ final errors = <AnalysisError>[];
- CodeFormatterImpl(this.options);
+ CodeFormatterImpl(FormatterOptions options) : this.options = options,
+ recorder = new EditRecorder(options);
String format(CodeKind kind, String source, {int offset, int end,
int indentationLevel:0}) {
var start = tokenize(source);
- _checkForErrors();
+ checkForErrors();
var node = parse(kind, start);
- _checkForErrors();
+ checkForErrors();
- // To be continued...
-
- return source;
+ var formatter = new FormattingEngine(options);
+ return formatter.format(source, node, start, kind, recorder);
}
ASTNode parse(CodeKind kind, Token start) {
@@ -115,7 +116,7 @@
throw new FormatterException('Unsupported format kind: $kind');
}
- _checkForErrors() {
+ checkForErrors() {
if (errors.length > 0) {
throw new FormatterException.forError(errors);
}
@@ -132,18 +133,13 @@
}
-/// Placeholder class to hold a reference to the Class object representing
-/// the Dart keyword void.
-class Void extends Object {
-
-}
-
/// Records a sequence of edits to a source string that will cause the string
/// to be formatted when applied.
class EditRecorder {
final FormatterOptions options;
+ final EditStore editStore;
int column = 0;
@@ -152,12 +148,105 @@
Token currentToken;
- int indentationLevel = 0;
int numberOfIndentations = 0;
- bool isIndentNeeded = false;
+ bool needsIndent = false;
- EditRecorder(this.options);
+ EditRecorder(this.options): editStore = new EditStore();
+
+ /// Add an [Edit] that describes a textual [replacement] of a text
+ /// interval starting at the given [offset] spanning the given [length].
+ void addEdit(int offset, int length, String replacement) {
+ editStore.addEdit(offset, length, replacement);
+ }
+
+ /// Advance past the given expected [token] (or fail if not matched).
+ void advance(Token token) {
+ if (currentToken.lexeme == token.lexeme) {
+
+ // TODO(pquitslund) emit comments
+// if (needsIndent) {
+// advanceIndent();
+// needsIndent = false;
+// }
+ // Record writing a token at the current edit location
+ advanceChars(token.length);
+ currentToken = currentToken.next;
+ } else {
+ wrongToken(token.lexeme);
+ }
+ }
+
+ /// Move indices past indent, adding an edit if needed to adjust indentation
+ void advanceIndent() {
+// var indentWidth = options.indentPerLevel * indentationLevel;
+// var indentString = getIndentString(indentWidth);
+// var sourceIndentWidth = 0;
+// for (var i = 0; i < source.length; i++) {
+// if (isIndentChar(source[sourceIndex + i])) {
+// sourceIndentWidth += 1;
+// } else {
+// break;
+// }
+// }
+// var hasSameIndent = sourceIndentWidth == indentWidth;
+// if (hasSameIndent) {
+// for (var i = 0; i < indentWidth; i++) {
+// if (source[sourceIndex + i] != indentString[i]) {
+// hasSameIndent = false;
+// break;
+// }
+// }
+// if (hasSameIndent) {
+// advanceChars(indentWidth);
+// return;
+// }
+// }
+// addEdit(sourceIndex, sourceIndentWidth, indentString);
+// column += indentWidth;
+// sourceIndex += sourceIndentWidth;
+
+ var indent = options.indentPerLevel * numberOfIndentations;
+
+ spaces(indent);
+ }
+
+ String getIndentString(int indentWidth) {
+
+ // TODO(pquitslund) a temporary workaround
+ if (indentWidth < 0) {
+ return '';
+ }
+
+ // TODO(pquitslund) allow indent with tab chars
+
+ // Fetch a precomputed indent string
+ if (indentWidth < SPACES.length) {
+ return SPACES[indentWidth];
+ }
+
+ // Build un-precomputed strings dynamically
+ var sb = new StringBuffer();
+ for (var i = 0; i < indentWidth; ++i) {
+ sb.write(' ');
+ }
+ return sb.toString();
+ }
+
+ /// Advance past the given expected [token] (or fail if not matched).
+ void advanceToken(String token) {
+ if (currentToken.lexeme == token) {
+ advance(currentToken);
+ } else {
+ wrongToken(token);
+ }
+ }
+
+ /// Advance [column] and [sourceIndex] indices by [len] characters.
+ void advanceChars(int len) {
+ column += len;
+ sourceIndex += len;
+ }
/// Count the number of whitespace chars beginning at the current
/// [sourceIndex].
@@ -173,9 +262,8 @@
return count;
}
- /// Indent.
+ /// Update indent indices.
void indent() {
- indentationLevel += options.indentPerLevel;
numberOfIndentations++;
}
@@ -192,9 +280,89 @@
return true;
}
+ /// Newline.
+ void newline() {
+ // TODO(pquitslund) emit comments
+ needsIndent = true;
+ // If there is a newline before the edit location, do nothing.
+ if (isNewlineAt(sourceIndex - NEW_LINE.length)) {
+ return;
+ }
+ // If there is a newline after the edit location, advance over it.
+ if (isNewlineAt(sourceIndex)) {
+ advanceChars(NEW_LINE.length);
+ return;
+ }
+ // Otherwise, replace whitespace with a newline.
+ var charsToReplace = countWhitespace();
+ if (isNewlineAt(sourceIndex + charsToReplace)) {
+ charsToReplace += NEW_LINE.length;
+ }
+ addEdit(sourceIndex, charsToReplace, NEW_LINE);
+ advanceChars(charsToReplace);
+ }
+
+
+ /// Un-indent.
+ void unindent() {
+ numberOfIndentations--;
+ }
+
+ /// Space.
+ void space() {
+ // TODO(pquitslund) emit comments
+// // If there is a space before the edit location, do nothing.
+// if (isSpaceAt(sourceIndex - 1)) {
+// return;
+// }
+// // If there is a space after the edit location, advance over it.
+// if (isSpaceAt(sourceIndex)) {
+// advance(1);
+// return;
+// }
+ // Otherwise, replace spaces with a single space.
+ spaces(1);
+ }
+
+ /// Spaces.
+ void spaces(int num) {
+ var charsToReplace = countWhitespace();
+ addEdit(sourceIndex, charsToReplace, SPACES[num]);
+ advanceChars(charsToReplace);
+ }
+
+ wrongToken(String token) {
+ throw new FormatterException('expected token: "${token}", '
+ 'actual: "${currentToken}"');
+ }
+
+ String toString() =>
+ new EditOperation().apply(editStore.edits,
+ source.substring(0, sourceIndex));
+
}
const SPACE = ' ';
+final SPACES = [
+ '',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+ ' ',
+];
+
bool isIndentChar(String ch) => ch == SPACE; // TODO(pquitslund) also check tab
@@ -202,6 +370,8 @@
/// Manages stored [Edit]s.
class EditStore {
+ const EditStore();
+
/// The underlying sequence of [Edit]s.
final edits = <Edit>[];
@@ -239,7 +409,6 @@
}
-
/// Describes a text edit.
class Edit {
@@ -264,11 +433,155 @@
}
+/// Applies a sequence of [edits] to a [document].
+class EditOperation {
+
+ String apply(List<Edit> edits, String document) {
+
+ var edit;
+ for (var i = edits.length - 1; i >= 0; --i) {
+ edit = edits[i];
+ document = replace(document, edit.offset,
+ edit.offset + edit.length, edit.replacement);
+ }
+
+ return document;
+ }
+
+}
+
+
+String replace(String str, int start, int end, String replacement) =>
+ str.substring(0, start) + replacement + str.substring(end);
+
+
/// An AST visitor that drives formatting heuristics.
-class FormattingEngine extends RecursiveASTVisitor<Void> {
+class FormattingEngine extends RecursiveASTVisitor {
final FormatterOptions options;
+ CodeKind kind;
+ EditRecorder recorder;
+
FormattingEngine(this.options);
+ String format(String source, ASTNode node, Token start, CodeKind kind,
+ EditRecorder recorder) {
+
+ this.kind = kind;
+ this.recorder = recorder;
+
+ recorder..source = source
+ ..currentToken = start;
+
+ node.accept(this);
+
+ var editor = new EditOperation();
+ return editor.apply(recorder.editStore.edits, source);
+ }
+
+
+ visitClassDeclaration(ClassDeclaration node) {
+
+ recorder.advanceIndent();
+
+ if (node.documentationComment != null) {
+ node.documentationComment.accept(this);
+ }
+
+ recorder..advance(node.classKeyword)..space();
+
+ node.name.accept(this);
+
+ if (node.typeParameters != null) {
+ node.typeParameters.accept(this);
+ }
+ recorder.space();
+
+ if (node.extendsClause != null) {
+ node.extendsClause.accept(this);
+ recorder.space();
+ }
+
+ if (node.implementsClause != null) {
+ node.implementsClause.accept(this);
+ recorder.space();
+ }
+
+ recorder..advance(node.leftBracket)
+ ..indent();
+
+ for (var member in node.members) {
+ recorder..newline()
+ ..advanceIndent();
+ member.accept(this);
+ }
+
+ recorder..unindent()
+ ..newline()
+ ..advanceIndent()
+ ..advance(node.rightBracket);
+ }
+
+
+ visitBlockFunctionBody(BlockFunctionBody node) {
+ node.block.accept(this);
+ }
+
+
+ visitBlock(Block block) {
+ recorder..advance(block.leftBracket)
+ ..indent()
+ ..newline();
+ // ...
+ recorder..unindent()
+ ..advanceIndent()
+ ..advance(block.rightBracket);
+ }
+
+
+ visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ recorder..advance(node.functionDefinition)
+ ..indent()
+ ..newline();
+ node.expression.accept(this);
+ recorder..unindent()
+ ..advanceIndent()
+ ..advance(node.semicolon);
+ }
+
+
+ visitMethodDeclaration(MethodDeclaration node) {
+
+ if (node.modifierKeyword != null) {
+ recorder.advance(node.modifierKeyword);
+ recorder.space();
+ }
+
+ if (node.returnType != null) {
+ node.returnType.accept(this);
+ recorder.space();
+ }
+
+ recorder.advance(node.name.beginToken);
+
+ node.parameters.accept(this);
+
+ recorder.space();
+
+ node.body.accept(this);
+ }
+
+
+ visitFormalParameterList(FormalParameterList node) {
+ recorder.advance(node.beginToken);
+ //...
+ recorder.advance(node.endToken);
+ }
+
+
+ visitSimpleIdentifier(SimpleIdentifier node) {
+ recorder.advance(node.token);
+ }
+
}
diff --git a/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart b/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart
index bc6b7cf..f747ce6 100644
--- a/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/services/runtime/coverage/coverage_impl.dart
@@ -193,7 +193,7 @@
String rewritePathContent(String path) {
if (path.endsWith('__coverage_lib.dart')) {
String implPath = pathos.joinAll([
- pathos.dirname(new Options().script),
+ pathos.dirname(Platform.script),
'..', 'lib', 'src', 'services', 'runtime', 'coverage',
'coverage_lib.dart']);
var content = new File(implPath).readAsStringSync();
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart
index ae71ad1b..bd06fba 100644
--- a/pkg/analyzer_experimental/test/generated/ast_test.dart
+++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -212,11 +212,11 @@
}
}
/**
- * The class {@code ASTFactory} defines utility methods that can be used to create AST nodes. The
+ * The class `ASTFactory` defines utility methods that can be used to create AST nodes. The
* nodes that are created are complete in the sense that all of the tokens that would have been
* associated with the nodes by a parser are also created, but the token stream is not constructed.
* None of the nodes are resolved.
- * <p>
+ *
* The general pattern is for the name of the factory method to be the same as the name of the class
* of AST node being created. There are two notable exceptions. The first is for methods creating
* nodes that are part of a cascade expression. These methods are all prefixed with 'cascaded'. The
@@ -402,7 +402,7 @@
/**
* Create a type name whose name has been resolved to the given element and whose type has been
* resolved to the type of the given element.
- * <p>
+ *
* <b>Note:</b> This method does not correctly handle class elements that have type parameters.
* @param element the element defining the type represented by the type name
* @return the type name that was created
@@ -1950,7 +1950,7 @@
}
/**
- * Assert that a {@code ToSourceVisitor} will produce the expected source when visiting the given
+ * Assert that a `ToSourceVisitor` will produce the expected source when visiting the given
* node.
* @param expectedSource the source string that the visitor is expected to produce
* @param node the AST node being visited to produce the actual source
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart
index a89b723..4625b78 100644
--- a/pkg/analyzer_experimental/test/generated/element_test.dart
+++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -347,6 +347,7 @@
String getterName = "g";
PropertyAccessorElement getterG = ElementFactory.getterElement(getterName, false, typeE);
classA.accessors = <PropertyAccessorElement> [getterG];
+ ((getterG.type as FunctionTypeImpl)).typeArguments = classA.type.typeArguments;
InterfaceType typeI = ElementFactory.classElement2("I", []).type;
InterfaceTypeImpl typeAI = new InterfaceTypeImpl.con1(classA);
typeAI.typeArguments = <Type2> [typeI];
@@ -588,6 +589,7 @@
String methodName = "m";
MethodElementImpl methodM = ElementFactory.methodElement(methodName, typeE, [typeE]);
classA.methods = <MethodElement> [methodM];
+ ((methodM.type as FunctionTypeImpl)).typeArguments = classA.type.typeArguments;
InterfaceType typeI = ElementFactory.classElement2("I", []).type;
InterfaceTypeImpl typeAI = new InterfaceTypeImpl.con1(classA);
typeAI.typeArguments = <Type2> [typeI];
@@ -650,6 +652,7 @@
String setterName = "s";
PropertyAccessorElement setterS = ElementFactory.setterElement(setterName, false, typeE);
classA.accessors = <PropertyAccessorElement> [setterS];
+ ((setterS.type as FunctionTypeImpl)).typeArguments = classA.type.typeArguments;
InterfaceType typeI = ElementFactory.classElement2("I", []).type;
InterfaceTypeImpl typeAI = new InterfaceTypeImpl.con1(classA);
typeAI.typeArguments = <Type2> [typeI];
@@ -1023,6 +1026,7 @@
String methodName = "m";
MethodElementImpl methodM = ElementFactory.methodElement(methodName, typeE, [typeE]);
classA.methods = <MethodElement> [methodM];
+ ((methodM.type as FunctionTypeImpl)).typeArguments = classA.type.typeArguments;
ClassElementImpl classB = ElementFactory.classElement2("B", ["F"]);
InterfaceType typeB = classB.type;
InterfaceTypeImpl typeAF = new InterfaceTypeImpl.con1(classA);
@@ -1555,7 +1559,7 @@
}
}
/**
- * The class {@code ElementFactory} defines utility methods used to create elements for testing
+ * The class `ElementFactory` defines utility methods used to create elements for testing
* purposes. The elements that are created are complete in the sense that as much of the element
* model as can be created, given the provided information, has been created.
*/
@@ -1586,12 +1590,11 @@
return element;
}
static ClassElementImpl classElement2(String typeName, List<String> parameterNames) => classElement(typeName, object.type, parameterNames);
- static ConstructorElementImpl constructorElement(ClassElement clazz, String name) {
- Type2 type = clazz.type;
+ static ConstructorElementImpl constructorElement(ClassElement definingClass, String name) {
+ Type2 type = definingClass.type;
ConstructorElementImpl constructor = new ConstructorElementImpl(name == null ? null : ASTFactory.identifier3(name));
+ constructor.returnType = type;
FunctionTypeImpl constructorType = new FunctionTypeImpl.con1(constructor);
- constructorType.normalParameterTypes = <Type2> [type];
- constructorType.returnType = type;
constructor.type = constructorType;
return constructor;
}
@@ -1612,9 +1615,9 @@
getter.static = isStatic;
getter.synthetic = true;
getter.variable = field;
+ getter.returnType = type2;
field.getter = getter;
FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
- getterType.returnType = type2;
getter.type = getterType;
if (!isConst && !isFinal) {
PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(field);
@@ -1622,10 +1625,10 @@
setter.static = isStatic;
setter.synthetic = true;
setter.variable = field;
+ setter.returnType = VoidTypeImpl.instance;
field.setter = setter;
FunctionTypeImpl setterType = new FunctionTypeImpl.con1(getter);
setterType.normalParameterTypes = <Type2> [type2];
- setterType.returnType = VoidTypeImpl.instance;
setter.type = setterType;
}
return field;
@@ -1637,8 +1640,10 @@
FunctionElementImpl functionElement = new FunctionElementImpl.con1(ASTFactory.identifier3(functionName));
FunctionTypeImpl functionType = new FunctionTypeImpl.con1(functionElement);
functionElement.type = functionType;
- if (returnElement != null) {
- functionType.returnType = returnElement.type;
+ if (returnElement == null) {
+ functionElement.returnType = VoidTypeImpl.instance;
+ } else {
+ functionElement.returnType = returnElement.type;
}
int normalCount = normalParameters == null ? 0 : normalParameters.length;
if (normalCount > 0) {
@@ -1676,8 +1681,10 @@
FunctionElementImpl functionElement = new FunctionElementImpl.con1(ASTFactory.identifier3(functionName));
FunctionTypeImpl functionType = new FunctionTypeImpl.con1(functionElement);
functionElement.type = functionType;
- if (returnElement != null) {
- functionType.returnType = returnElement.type;
+ if (returnElement == null) {
+ functionElement.returnType = VoidTypeImpl.instance;
+ } else {
+ functionElement.returnType = returnElement.type;
}
int count = normalParameters == null ? 0 : normalParameters.length;
if (count > 0) {
@@ -1716,9 +1723,9 @@
getter.getter = true;
getter.static = isStatic;
getter.variable = field;
+ getter.returnType = type2;
field.getter = getter;
FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
- getterType.returnType = type2;
getter.type = getterType;
return getter;
}
@@ -1751,9 +1758,9 @@
parameters[i] = parameter;
}
method.parameters = parameters;
+ method.returnType = returnType2;
FunctionTypeImpl methodType = new FunctionTypeImpl.con1(method);
methodType.normalParameterTypes = argumentTypes;
- methodType.returnType = returnType2;
method.type = methodType;
return method;
}
@@ -1782,19 +1789,19 @@
getter.getter = true;
getter.static = isStatic;
getter.variable = field;
+ getter.returnType = type2;
field.getter = getter;
FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
- getterType.returnType = type2;
getter.type = getterType;
PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(field);
setter.setter = true;
setter.static = isStatic;
setter.synthetic = true;
setter.variable = field;
+ setter.returnType = VoidTypeImpl.instance;
field.setter = setter;
- FunctionTypeImpl setterType = new FunctionTypeImpl.con1(getter);
+ FunctionTypeImpl setterType = new FunctionTypeImpl.con1(setter);
setterType.normalParameterTypes = <Type2> [type2];
- setterType.returnType = VoidTypeImpl.instance;
setter.type = setterType;
return setter;
}
@@ -1808,9 +1815,9 @@
getter.static = true;
getter.synthetic = true;
getter.variable = variable;
+ getter.returnType = type2;
variable.getter = getter;
FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
- getterType.returnType = type2;
getter.type = getterType;
if (!isFinal) {
PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(variable);
@@ -1818,10 +1825,10 @@
setter.static = true;
setter.synthetic = true;
setter.variable = variable;
+ setter.returnType = VoidTypeImpl.instance;
variable.setter = setter;
FunctionTypeImpl setterType = new FunctionTypeImpl.con1(getter);
setterType.normalParameterTypes = <Type2> [type2];
- setterType.returnType = VoidTypeImpl.instance;
setter.type = setterType;
}
return variable;
@@ -2207,9 +2214,12 @@
EngineTestCase.assertLength(0, types);
}
void test_getReturnType() {
- FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier3("f")));
+ Type2 expectedReturnType = VoidTypeImpl.instance;
+ FunctionElementImpl functionElement = new FunctionElementImpl.con1(ASTFactory.identifier3("f"));
+ functionElement.returnType = expectedReturnType;
+ FunctionTypeImpl type = new FunctionTypeImpl.con1(functionElement);
Type2 returnType = type.returnType;
- JUnitTestCase.assertEquals(VoidTypeImpl.instance, returnType);
+ JUnitTestCase.assertEquals(expectedReturnType, returnType);
}
void test_getTypeArguments() {
FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier3("f")));
@@ -2420,15 +2430,15 @@
variableS.bound = stringType;
TypeVariableTypeImpl typeS = new TypeVariableTypeImpl(variableS);
FunctionElementImpl functionAliasElement = new FunctionElementImpl.con1(ASTFactory.identifier3("func"));
+ functionAliasElement.returnType = stringType;
FunctionTypeImpl functionAliasType = new FunctionTypeImpl.con1(functionAliasElement);
functionAliasElement.type = functionAliasType;
- functionAliasType.returnType = stringType;
functionAliasType.normalParameterTypes = <Type2> [typeB];
functionAliasType.optionalParameterTypes = <Type2> [typeS];
FunctionElementImpl functionElement = new FunctionElementImpl.con1(ASTFactory.identifier3("f"));
+ functionElement.returnType = provider.dynamicType;
FunctionTypeImpl functionType = new FunctionTypeImpl.con1(functionElement);
functionElement.type = functionType;
- functionType.returnType = provider.dynamicType;
functionType.normalParameterTypes = <Type2> [boolType];
functionType.optionalParameterTypes = <Type2> [stringType];
JUnitTestCase.assertTrue(functionType.isAssignableTo(functionAliasType));
@@ -2463,26 +2473,33 @@
JUnitTestCase.assertEquals(expectedTypes, types);
}
void test_setReturnType() {
- FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier3("f")));
Type2 expectedType = new InterfaceTypeImpl.con1(new ClassElementImpl(ASTFactory.identifier3("C")));
- type.returnType = expectedType;
- Type2 returnType = type.returnType;
- JUnitTestCase.assertEquals(expectedType, returnType);
+ FunctionElementImpl functionElement = new FunctionElementImpl.con1(ASTFactory.identifier3("f"));
+ functionElement.returnType = expectedType;
+ FunctionTypeImpl type = new FunctionTypeImpl.con1(functionElement);
+ JUnitTestCase.assertEquals(expectedType, type.returnType);
}
void test_setTypeArguments() {
- FunctionTypeImpl type = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier3("f")));
- Type2 expectedType = new TypeVariableTypeImpl(new TypeVariableElementImpl(ASTFactory.identifier3("C")));
+ ClassElementImpl enclosingClass = ElementFactory.classElement2("C", ["E"]);
+ MethodElementImpl methodElement = new MethodElementImpl.con1(ASTFactory.identifier3("m"));
+ enclosingClass.methods = <MethodElement> [methodElement];
+ FunctionTypeImpl type = new FunctionTypeImpl.con1(methodElement);
+ Type2 expectedType = enclosingClass.typeVariables[0].type;
type.typeArguments = <Type2> [expectedType];
List<Type2> arguments = type.typeArguments;
EngineTestCase.assertLength(1, arguments);
JUnitTestCase.assertEquals(expectedType, arguments[0]);
}
void test_substitute2_equal() {
- FunctionTypeImpl functionType = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier3("f")));
- TypeVariableTypeImpl parameterType = new TypeVariableTypeImpl(new TypeVariableElementImpl(ASTFactory.identifier3("E")));
- functionType.returnType = parameterType;
+ ClassElementImpl definingClass = ElementFactory.classElement2("C", ["E"]);
+ TypeVariableType parameterType = definingClass.typeVariables[0].type;
+ MethodElementImpl functionElement = new MethodElementImpl.con1(ASTFactory.identifier3("m"));
+ functionElement.returnType = parameterType;
+ definingClass.methods = <MethodElement> [functionElement];
+ FunctionTypeImpl functionType = new FunctionTypeImpl.con1(functionElement);
functionType.normalParameterTypes = <Type2> [parameterType];
functionType.optionalParameterTypes = <Type2> [parameterType];
+ functionType.typeArguments = <Type2> [parameterType];
LinkedHashMap<String, Type2> namedParameterTypes = new LinkedHashMap<String, Type2>();
String namedParameterName = "c";
namedParameterTypes[namedParameterName] = parameterType;
@@ -2501,12 +2518,13 @@
JUnitTestCase.assertEquals(argumentType, namedParameters[namedParameterName]);
}
void test_substitute2_notEqual() {
- FunctionTypeImpl functionType = new FunctionTypeImpl.con1(new FunctionElementImpl.con1(ASTFactory.identifier3("f")));
Type2 returnType = new InterfaceTypeImpl.con1(new ClassElementImpl(ASTFactory.identifier3("R")));
Type2 normalParameterType = new InterfaceTypeImpl.con1(new ClassElementImpl(ASTFactory.identifier3("A")));
Type2 optionalParameterType = new InterfaceTypeImpl.con1(new ClassElementImpl(ASTFactory.identifier3("B")));
Type2 namedParameterType = new InterfaceTypeImpl.con1(new ClassElementImpl(ASTFactory.identifier3("C")));
- functionType.returnType = returnType;
+ FunctionElementImpl functionElement = new FunctionElementImpl.con1(ASTFactory.identifier3("f"));
+ functionElement.returnType = returnType;
+ FunctionTypeImpl functionType = new FunctionTypeImpl.con1(functionElement);
functionType.normalParameterTypes = <Type2> [normalParameterType];
functionType.optionalParameterTypes = <Type2> [optionalParameterType];
LinkedHashMap<String, Type2> namedParameterTypes = new LinkedHashMap<String, Type2>();
@@ -2714,7 +2732,7 @@
}
class InterfaceTypeImpl_18 extends InterfaceTypeImpl {
InterfaceTypeImpl_18(ClassElement arg0) : super.con1(arg0);
- bool isDartCoreFunction() => true;
+ bool get isDartCoreFunction => true;
}
main() {
ElementKindTest.dartSuite();
diff --git a/pkg/analyzer_experimental/test/generated/parser_test.dart b/pkg/analyzer_experimental/test/generated/parser_test.dart
index 9c5f3d8..41f6646 100644
--- a/pkg/analyzer_experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer_experimental/test/generated/parser_test.dart
@@ -16,11 +16,11 @@
import 'scanner_test.dart' show TokenFactory;
import 'ast_test.dart' show ASTFactory;
/**
- * The class {@code SimpleParserTest} defines parser tests that test individual parsing method. The
+ * The class `SimpleParserTest` defines parser tests that test individual parsing method. The
* code fragments should be as minimal as possible in order to test the method, but should not test
* the interactions between the method under test and other methods.
- * <p>
- * More complex tests should be defined in the class {@link ComplexParserTest}.
+ *
+ * More complex tests should be defined in the class [ComplexParserTest].
*/
class SimpleParserTest extends ParserTestCase {
void fail_parseCommentReference_this() {
@@ -83,11 +83,11 @@
}
void test_createSyntheticIdentifier() {
SimpleIdentifier identifier = createSyntheticIdentifier();
- JUnitTestCase.assertTrue(identifier.isSynthetic());
+ JUnitTestCase.assertTrue(identifier.isSynthetic);
}
void test_createSyntheticStringLiteral() {
SimpleStringLiteral literal = createSyntheticStringLiteral();
- JUnitTestCase.assertTrue(literal.isSynthetic());
+ JUnitTestCase.assertTrue(literal.isSynthetic);
}
void test_isFunctionDeclaration_nameButNoReturn_block() {
JUnitTestCase.assertTrue(isFunctionDeclaration("f() {}"));
@@ -1508,15 +1508,15 @@
}
void test_parseDocumentationComment_block() {
Comment comment = ParserTestCase.parse5("parseDocumentationComment", "/** */ class", []);
- JUnitTestCase.assertFalse(comment.isBlock());
- JUnitTestCase.assertTrue(comment.isDocumentation());
- JUnitTestCase.assertFalse(comment.isEndOfLine());
+ JUnitTestCase.assertFalse(comment.isBlock);
+ JUnitTestCase.assertTrue(comment.isDocumentation);
+ JUnitTestCase.assertFalse(comment.isEndOfLine);
}
void test_parseDocumentationComment_block_withReference() {
Comment comment = ParserTestCase.parse5("parseDocumentationComment", "/** [a] */ class", []);
- JUnitTestCase.assertFalse(comment.isBlock());
- JUnitTestCase.assertTrue(comment.isDocumentation());
- JUnitTestCase.assertFalse(comment.isEndOfLine());
+ JUnitTestCase.assertFalse(comment.isBlock);
+ JUnitTestCase.assertTrue(comment.isDocumentation);
+ JUnitTestCase.assertFalse(comment.isEndOfLine);
NodeList<CommentReference> references = comment.references;
EngineTestCase.assertSize(1, references);
CommentReference reference = references[0];
@@ -1525,9 +1525,9 @@
}
void test_parseDocumentationComment_endOfLine() {
Comment comment = ParserTestCase.parse5("parseDocumentationComment", "/// \n/// \n class", []);
- JUnitTestCase.assertFalse(comment.isBlock());
- JUnitTestCase.assertTrue(comment.isDocumentation());
- JUnitTestCase.assertFalse(comment.isEndOfLine());
+ JUnitTestCase.assertFalse(comment.isBlock);
+ JUnitTestCase.assertTrue(comment.isDocumentation);
+ JUnitTestCase.assertFalse(comment.isEndOfLine);
}
void test_parseDoStatement() {
DoStatement statement = ParserTestCase.parse5("parseDoStatement", "do {} while (x);", []);
@@ -2870,7 +2870,7 @@
}
void test_parsePrimaryExpression_string() {
SimpleStringLiteral literal = ParserTestCase.parse5("parsePrimaryExpression", "\"string\"", []);
- JUnitTestCase.assertFalse(literal.isMultiline());
+ JUnitTestCase.assertFalse(literal.isMultiline);
JUnitTestCase.assertEquals("string", literal.value);
}
void test_parsePrimaryExpression_super() {
@@ -3668,7 +3668,7 @@
}
/**
- * Invoke the method {@link Parser#computeStringValue(String)} with the given argument.
+ * Invoke the method [Parser#computeStringValue] with the given argument.
* @param lexeme the argument to the method
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
@@ -3680,7 +3680,7 @@
}
/**
- * Invoke the method {@link Parser#createSyntheticIdentifier()} with the parser set to the token
+ * Invoke the method [Parser#createSyntheticIdentifier] with the parser set to the token
* stream produced by scanning the given source.
* @param source the source to be scanned to produce the token stream being tested
* @return the result of invoking the method
@@ -3692,7 +3692,7 @@
}
/**
- * Invoke the method {@link Parser#createSyntheticIdentifier()} with the parser set to the token
+ * Invoke the method [Parser#createSyntheticIdentifier] with the parser set to the token
* stream produced by scanning the given source.
* @param source the source to be scanned to produce the token stream being tested
* @return the result of invoking the method
@@ -3704,7 +3704,7 @@
}
/**
- * Invoke the method {@link Parser#isFunctionDeclaration()} with the parser set to the token
+ * Invoke the method [Parser#isFunctionDeclaration] with the parser set to the token
* stream produced by scanning the given source.
* @param source the source to be scanned to produce the token stream being tested
* @return the result of invoking the method
@@ -3716,7 +3716,7 @@
}
/**
- * Invoke the method {@link Parser#isFunctionExpression()} with the parser set to the token stream
+ * Invoke the method [Parser#isFunctionExpression] with the parser set to the token stream
* produced by scanning the given source.
* @param source the source to be scanned to produce the token stream being tested
* @return the result of invoking the method
@@ -3731,7 +3731,7 @@
}
/**
- * Invoke the method {@link Parser#isInitializedVariableDeclaration()} with the parser set to the
+ * Invoke the method [Parser#isInitializedVariableDeclaration] with the parser set to the
* token stream produced by scanning the given source.
* @param source the source to be scanned to produce the token stream being tested
* @return the result of invoking the method
@@ -3743,7 +3743,7 @@
}
/**
- * Invoke the method {@link Parser#isSwitchMember()} with the parser set to the token stream
+ * Invoke the method [Parser#isSwitchMember] with the parser set to the token stream
* produced by scanning the given source.
* @param source the source to be scanned to produce the token stream being tested
* @return the result of invoking the method
@@ -3755,13 +3755,13 @@
}
/**
- * Invoke a "skip" method in {@link Parser}. The method is assumed to take a token as it's
+ * Invoke a "skip" method in [Parser]. The method is assumed to take a token as it's
* parameter and is given the first token in the scanned source.
* @param methodName the name of the method that should be invoked
* @param source the source to be processed by the method
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null}
+ * @throws AssertionFailedError if the result is `null`
*/
Token skip(String methodName, String source) {
GatheringErrorListener listener = new GatheringErrorListener();
@@ -5853,11 +5853,11 @@
}
}
/**
- * The class {@code ComplexParserTest} defines parser tests that test the parsing of more complex
+ * The class `ComplexParserTest` defines parser tests that test the parsing of more complex
* code fragments or the interactions between multiple parsing methods. For example, tests to ensure
* that the precedence of operations is being handled correctly should be defined in this class.
- * <p>
- * Simpler tests should be defined in the class {@link SimpleParserTest}.
+ *
+ * Simpler tests should be defined in the class [SimpleParserTest].
*/
class ComplexParserTest extends ParserTestCase {
void test_additiveExpression_normal() {
@@ -5979,7 +5979,7 @@
Expression lhs = ((section as AssignmentExpression)).leftHandSide;
EngineTestCase.assertInstanceOf(IndexExpression, lhs);
IndexExpression index = lhs as IndexExpression;
- JUnitTestCase.assertTrue(index.isCascaded());
+ JUnitTestCase.assertTrue(index.isCascaded);
JUnitTestCase.assertSame(target, index.realTarget);
}
}
@@ -6263,7 +6263,7 @@
}
}
/**
- * Instances of the class {@code ASTValidator} are used to validate the correct construction of an
+ * Instances of the class `ASTValidator` are used to validate the correct construction of an
* AST structure.
*/
class ASTValidator extends GeneralizingASTVisitor<Object> {
@@ -6340,9 +6340,9 @@
static List<Object> _EMPTY_ARGUMENTS = new List<Object>(0);
/**
- * Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
+ * Invoke a parse method in [Parser]. The method is assumed to have the given number and
* type of parameters and will be invoked with the given arguments.
- * <p>
+ *
* The given source is scanned and the parser is initialized to start with the first token in the
* source before the parse method is invoked.
* @param methodName the name of the parse method that should be invoked to parse the source
@@ -6350,14 +6350,14 @@
* @param source the source to be parsed by the parse method
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null} or if any errors are produced
+ * @throws AssertionFailedError if the result is `null` or if any errors are produced
*/
static Object parse(String methodName, List<Object> objects, String source) => parse3(methodName, objects, source, new List<AnalysisError>(0));
/**
- * Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
+ * Invoke a parse method in [Parser]. The method is assumed to have the given number and
* type of parameters and will be invoked with the given arguments.
- * <p>
+ *
* The given source is scanned and the parser is initialized to start with the first token in the
* source before the parse method is invoked.
* @param methodName the name of the parse method that should be invoked to parse the source
@@ -6366,7 +6366,7 @@
* @param errorCodes the error codes of the errors that should be generated
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null} or the errors produced while
+ * @throws AssertionFailedError if the result is `null` or the errors produced while
* scanning and parsing the source do not match the expected errors
*/
static Object parse3(String methodName, List<Object> objects, String source, List<AnalysisError> errors) {
@@ -6377,9 +6377,9 @@
}
/**
- * Invoke a parse method in {@link Parser}. The method is assumed to have the given number and
+ * Invoke a parse method in [Parser]. The method is assumed to have the given number and
* type of parameters and will be invoked with the given arguments.
- * <p>
+ *
* The given source is scanned and the parser is initialized to start with the first token in the
* source before the parse method is invoked.
* @param methodName the name of the parse method that should be invoked to parse the source
@@ -6388,7 +6388,7 @@
* @param errorCodes the error codes of the errors that should be generated
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null} or the errors produced while
+ * @throws AssertionFailedError if the result is `null` or the errors produced while
* scanning and parsing the source do not match the expected errors
*/
static Object parse4(String methodName, List<Object> objects, String source, List<ErrorCode> errorCodes) {
@@ -6399,8 +6399,8 @@
}
/**
- * Invoke a parse method in {@link Parser}. The method is assumed to have no arguments.
- * <p>
+ * Invoke a parse method in [Parser]. The method is assumed to have no arguments.
+ *
* The given source is scanned and the parser is initialized to start with the first token in the
* source before the parse method is invoked.
* @param methodName the name of the parse method that should be invoked to parse the source
@@ -6408,7 +6408,7 @@
* @param errorCodes the error codes of the errors that should be generated
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null} or the errors produced while
+ * @throws AssertionFailedError if the result is `null` or the errors produced while
* scanning and parsing the source do not match the expected errors
*/
static Object parse5(String methodName, String source, List<ErrorCode> errorCodes) => parse4(methodName, _EMPTY_ARGUMENTS, source, errorCodes);
@@ -6419,7 +6419,7 @@
* @param errorCodes the error codes of the errors that are expected to be found
* @return the compilation unit that was parsed
* @throws Exception if the source could not be parsed, if the compilation errors in the source do
- * not match those that are expected, or if the result would have been {@code null}
+ * not match those that are expected, or if the result would have been `null`
*/
static CompilationUnit parseCompilationUnit(String source, List<ErrorCode> errorCodes) {
GatheringErrorListener listener = new GatheringErrorListener();
@@ -6439,7 +6439,7 @@
* @param errorCodes the error codes of the errors that are expected to be found
* @return the expression that was parsed
* @throws Exception if the source could not be parsed, if the compilation errors in the source do
- * not match those that are expected, or if the result would have been {@code null}
+ * not match those that are expected, or if the result would have been `null`
*/
static Expression parseExpression(String source, List<ErrorCode> errorCodes) {
GatheringErrorListener listener = new GatheringErrorListener();
@@ -6459,7 +6459,7 @@
* @param errorCodes the error codes of the errors that are expected to be found
* @return the statement that was parsed
* @throws Exception if the source could not be parsed, if the compilation errors in the source do
- * not match those that are expected, or if the result would have been {@code null}
+ * not match those that are expected, or if the result would have been `null`
*/
static Statement parseStatement(String source, List<ErrorCode> errorCodes) {
GatheringErrorListener listener = new GatheringErrorListener();
@@ -6481,7 +6481,7 @@
* @return the statements that were parsed
* @throws Exception if the source could not be parsed, if the number of statements does not match
* the expected count, if the compilation errors in the source do not match those that
- * are expected, or if the result would have been {@code null}
+ * are expected, or if the result would have been `null`
*/
static List<Statement> parseStatements(String source, int expectedCount, List<ErrorCode> errorCodes) {
GatheringErrorListener listener = new GatheringErrorListener();
@@ -6496,9 +6496,9 @@
}
/**
- * Invoke a method in {@link Parser}. The method is assumed to have the given number and type of
+ * Invoke a method in [Parser]. The method is assumed to have the given number and type of
* parameters and will be invoked with the given arguments.
- * <p>
+ *
* The given source is scanned and the parser is initialized to start with the first token in the
* source before the method is invoked.
* @param methodName the name of the method that should be invoked
@@ -6507,7 +6507,7 @@
* @param listener the error listener that will be used for both scanning and parsing
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null} or the errors produced while
+ * @throws AssertionFailedError if the result is `null` or the errors produced while
* scanning and parsing the source do not match the expected errors
*/
static Object invokeParserMethod(String methodName, List<Object> objects, String source, GatheringErrorListener listener) {
@@ -6523,8 +6523,8 @@
}
/**
- * Invoke a method in {@link Parser}. The method is assumed to have no arguments.
- * <p>
+ * Invoke a method in [Parser]. The method is assumed to have no arguments.
+ *
* The given source is scanned and the parser is initialized to start with the first token in the
* source before the method is invoked.
* @param methodName the name of the method that should be invoked
@@ -6532,7 +6532,7 @@
* @param listener the error listener that will be used for both scanning and parsing
* @return the result of invoking the method
* @throws Exception if the method could not be invoked or throws an exception
- * @throws AssertionFailedError if the result is {@code null} or the errors produced while
+ * @throws AssertionFailedError if the result is `null` or the errors produced while
* scanning and parsing the source do not match the expected errors
*/
static Object invokeParserMethod2(String methodName, String source, GatheringErrorListener listener) => invokeParserMethod(methodName, _EMPTY_ARGUMENTS, source, listener);
@@ -6562,7 +6562,7 @@
}
}
/**
- * The class {@code RecoveryParserTest} defines parser tests that test the parsing of invalid code
+ * The class `RecoveryParserTest` defines parser tests that test the parsing of invalid code
* sequences to ensure that the correct recovery steps are taken in the parser.
*/
class RecoveryParserTest extends ParserTestCase {
@@ -6572,24 +6572,24 @@
void test_additiveExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("+ y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_additiveExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("+", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_additiveExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x +", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_additiveExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super +", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_additiveExpression_precedence_multiplicative_left() {
BinaryExpression expression = ParserTestCase.parseExpression("* +", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6607,51 +6607,51 @@
AssignmentExpression expression = ParserTestCase.parseExpression("= y = 0", [ParserErrorCode.MISSING_IDENTIFIER]);
Expression syntheticExpression = expression.leftHandSide;
EngineTestCase.assertInstanceOf(SimpleIdentifier, syntheticExpression);
- JUnitTestCase.assertTrue(syntheticExpression.isSynthetic());
+ JUnitTestCase.assertTrue(syntheticExpression.isSynthetic);
}
void test_assignmentExpression_missing_compound2() {
AssignmentExpression expression = ParserTestCase.parseExpression("x = = 0", [ParserErrorCode.MISSING_IDENTIFIER]);
Expression syntheticExpression = ((expression.rightHandSide as AssignmentExpression)).leftHandSide;
EngineTestCase.assertInstanceOf(SimpleIdentifier, syntheticExpression);
- JUnitTestCase.assertTrue(syntheticExpression.isSynthetic());
+ JUnitTestCase.assertTrue(syntheticExpression.isSynthetic);
}
void test_assignmentExpression_missing_compound3() {
AssignmentExpression expression = ParserTestCase.parseExpression("x = y =", [ParserErrorCode.MISSING_IDENTIFIER]);
Expression syntheticExpression = ((expression.rightHandSide as AssignmentExpression)).rightHandSide;
EngineTestCase.assertInstanceOf(SimpleIdentifier, syntheticExpression);
- JUnitTestCase.assertTrue(syntheticExpression.isSynthetic());
+ JUnitTestCase.assertTrue(syntheticExpression.isSynthetic);
}
void test_assignmentExpression_missing_LHS() {
AssignmentExpression expression = ParserTestCase.parseExpression("= 0", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftHandSide);
- JUnitTestCase.assertTrue(expression.leftHandSide.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftHandSide.isSynthetic);
}
void test_assignmentExpression_missing_RHS() {
AssignmentExpression expression = ParserTestCase.parseExpression("x =", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftHandSide);
- JUnitTestCase.assertTrue(expression.rightHandSide.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightHandSide.isSynthetic);
}
void test_bitwiseAndExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("& y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_bitwiseAndExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("&", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseAndExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x &", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseAndExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super &", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseAndExpression_precedence_equality_left() {
BinaryExpression expression = ParserTestCase.parseExpression("== &", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6668,24 +6668,24 @@
void test_bitwiseOrExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("| y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_bitwiseOrExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("|", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseOrExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x |", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseOrExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super |", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseOrExpression_precedence_xor_left() {
BinaryExpression expression = ParserTestCase.parseExpression("^ |", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6702,24 +6702,24 @@
void test_bitwiseXorExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("^ y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_bitwiseXorExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("^", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseXorExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x ^", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseXorExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super ^", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_bitwiseXorExpression_precedence_and_left() {
BinaryExpression expression = ParserTestCase.parseExpression("& ^", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6739,34 +6739,34 @@
void test_conditionalExpression_missingElse() {
ConditionalExpression expression = ParserTestCase.parse5("parseConditionalExpression", "x ? y :", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.elseExpression);
- JUnitTestCase.assertTrue(expression.elseExpression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.elseExpression.isSynthetic);
}
void test_conditionalExpression_missingThen() {
ConditionalExpression expression = ParserTestCase.parse5("parseConditionalExpression", "x ? : z", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.thenExpression);
- JUnitTestCase.assertTrue(expression.thenExpression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.thenExpression.isSynthetic);
}
void test_equalityExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("== y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_equalityExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("==", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_equalityExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x ==", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_equalityExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super ==", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_equalityExpression_precedence_relational_left() {
BinaryExpression expression = ParserTestCase.parseExpression("is ==", [ParserErrorCode.EXPECTED_TYPE_NAME, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6785,21 +6785,21 @@
EngineTestCase.assertSize(4, result);
Expression syntheticExpression = result[0];
EngineTestCase.assertInstanceOf(SimpleIdentifier, syntheticExpression);
- JUnitTestCase.assertTrue(syntheticExpression.isSynthetic());
+ JUnitTestCase.assertTrue(syntheticExpression.isSynthetic);
}
void test_expressionList_multiple_middle() {
List<Expression> result = ParserTestCase.parse5("parseExpressionList", "1, 2, , 4", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertSize(4, result);
Expression syntheticExpression = result[2];
EngineTestCase.assertInstanceOf(SimpleIdentifier, syntheticExpression);
- JUnitTestCase.assertTrue(syntheticExpression.isSynthetic());
+ JUnitTestCase.assertTrue(syntheticExpression.isSynthetic);
}
void test_expressionList_multiple_start() {
List<Expression> result = ParserTestCase.parse5("parseExpressionList", "1, 2, 3,", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertSize(4, result);
Expression syntheticExpression = result[3];
EngineTestCase.assertInstanceOf(SimpleIdentifier, syntheticExpression);
- JUnitTestCase.assertTrue(syntheticExpression.isSynthetic());
+ JUnitTestCase.assertTrue(syntheticExpression.isSynthetic);
}
void test_isExpression_noType() {
CompilationUnit unit = ParserTestCase.parseCompilationUnit("class Bar<T extends Foo> {m(x){if (x is ) return;if (x is !)}}", [ParserErrorCode.EXPECTED_TYPE_NAME, ParserErrorCode.EXPECTED_TYPE_NAME, ParserErrorCode.MISSING_STATEMENT]);
@@ -6813,25 +6813,25 @@
JUnitTestCase.assertNotNull(expression.notOperator);
TypeName type = expression.type;
JUnitTestCase.assertNotNull(type);
- JUnitTestCase.assertTrue(type.name.isSynthetic());
+ JUnitTestCase.assertTrue(type.name.isSynthetic);
EngineTestCase.assertInstanceOf(EmptyStatement, ifStatement.thenStatement);
}
void test_logicalAndExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("&& y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_logicalAndExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("&&", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_logicalAndExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x &&", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_logicalAndExpression_precedence_bitwiseOr_left() {
BinaryExpression expression = ParserTestCase.parseExpression("| &&", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6844,19 +6844,19 @@
void test_logicalOrExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("|| y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_logicalOrExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("||", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_logicalOrExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x ||", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_logicalOrExpression_precedence_logicalAnd_left() {
BinaryExpression expression = ParserTestCase.parseExpression("&& ||", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6869,24 +6869,24 @@
void test_multiplicativeExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("* y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_multiplicativeExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("*", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_multiplicativeExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x *", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_multiplicativeExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super *", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_multiplicativeExpression_precedence_unary_left() {
BinaryExpression expression = ParserTestCase.parseExpression("-x *", [ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6903,25 +6903,25 @@
void test_prefixExpression_missing_operand_minus() {
PrefixExpression expression = ParserTestCase.parseExpression("-", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.operand);
- JUnitTestCase.assertTrue(expression.operand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.operand.isSynthetic);
JUnitTestCase.assertEquals(TokenType.MINUS, expression.operator.type);
}
void test_relationalExpression_missing_LHS() {
IsExpression expression = ParserTestCase.parseExpression("is y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.expression);
- JUnitTestCase.assertTrue(expression.expression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.expression.isSynthetic);
}
void test_relationalExpression_missing_LHS_RHS() {
IsExpression expression = ParserTestCase.parseExpression("is", [ParserErrorCode.EXPECTED_TYPE_NAME, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.expression);
- JUnitTestCase.assertTrue(expression.expression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.expression.isSynthetic);
EngineTestCase.assertInstanceOf(TypeName, expression.type);
- JUnitTestCase.assertTrue(expression.type.isSynthetic());
+ JUnitTestCase.assertTrue(expression.type.isSynthetic);
}
void test_relationalExpression_missing_RHS() {
IsExpression expression = ParserTestCase.parseExpression("x is", [ParserErrorCode.EXPECTED_TYPE_NAME]);
EngineTestCase.assertInstanceOf(TypeName, expression.type);
- JUnitTestCase.assertTrue(expression.type.isSynthetic());
+ JUnitTestCase.assertTrue(expression.type.isSynthetic);
}
void test_relationalExpression_precedence_shift_right() {
IsExpression expression = ParserTestCase.parseExpression("<< is", [ParserErrorCode.EXPECTED_TYPE_NAME, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -6930,24 +6930,24 @@
void test_shiftExpression_missing_LHS() {
BinaryExpression expression = ParserTestCase.parseExpression("<< y", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
}
void test_shiftExpression_missing_LHS_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("<<", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.leftOperand);
- JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.leftOperand.isSynthetic);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_shiftExpression_missing_RHS() {
BinaryExpression expression = ParserTestCase.parseExpression("x <<", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_shiftExpression_missing_RHS_super() {
BinaryExpression expression = ParserTestCase.parseExpression("super <<", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression.rightOperand);
- JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic());
+ JUnitTestCase.assertTrue(expression.rightOperand.isSynthetic);
}
void test_shiftExpression_precedence_unary_left() {
BinaryExpression expression = ParserTestCase.parseExpression("+ <<", [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.MISSING_IDENTIFIER]);
@@ -7282,13 +7282,13 @@
}
}
/**
- * The class {@code ErrorParserTest} defines parser tests that test the parsing of code to ensure
+ * The class `ErrorParserTest` defines parser tests that test the parsing of code to ensure
* that errors are correctly reported, and in some cases, not reported.
*/
class ErrorParserTest extends ParserTestCase {
void fail_expectedListOrMapLiteral() {
TypedLiteral literal = ParserTestCase.parse4("parseListOrMapLiteral", <Object> [null], "1", [ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL]);
- JUnitTestCase.assertTrue(literal.isSynthetic());
+ JUnitTestCase.assertTrue(literal.isSynthetic);
}
void fail_illegalAssignmentToNonAssignable_superAssigned() {
ParserTestCase.parseExpression("super = x;", [ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE]);
@@ -7490,7 +7490,7 @@
}
void test_expectedStringLiteral() {
StringLiteral expression = ParserTestCase.parse5("parseStringLiteral", "1", [ParserErrorCode.EXPECTED_STRING_LITERAL]);
- JUnitTestCase.assertTrue(expression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.isSynthetic);
}
void test_expectedToken_commaMissingInArgumentList() {
ParserTestCase.parse5("parseArgumentList", "(x, y z)", [ParserErrorCode.EXPECTED_TOKEN]);
@@ -7718,7 +7718,7 @@
}
void test_missingIdentifier_number() {
SimpleIdentifier expression = ParserTestCase.parse5("parseSimpleIdentifier", "1", [ParserErrorCode.MISSING_IDENTIFIER]);
- JUnitTestCase.assertTrue(expression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.isSynthetic);
}
void test_missingKeywordOperator() {
ParserTestCase.parse4("parseOperator", <Object> [emptyCommentAndMetadata(), null, null], "+(x) {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
@@ -7871,7 +7871,7 @@
void test_useOfUnaryPlusOperator() {
SimpleIdentifier expression = ParserTestCase.parse5("parseUnaryExpression", "+x", [ParserErrorCode.MISSING_IDENTIFIER]);
EngineTestCase.assertInstanceOf(SimpleIdentifier, expression);
- JUnitTestCase.assertTrue(expression.isSynthetic());
+ JUnitTestCase.assertTrue(expression.isSynthetic);
}
void test_varAsTypeName_as() {
ParserTestCase.parseExpression("x as var", [ParserErrorCode.VAR_AS_TYPE_NAME]);
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index c365a79..81a1c44 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -201,7 +201,7 @@
void test_is_subclass() {
Source source = addSource(EngineTestCase.createSource(["class A {}", "class B extends A {", " B m() => this;", "}", "A f(A p) {", " if (p is B) {", " return p.m();", " }", "}"]));
LibraryElement library = resolve(source);
- assertNoErrors();
+ assertErrors([StaticTypeWarningCode.UNDEFINED_METHOD]);
verify([source]);
CompilationUnit unit = resolveCompilationUnit(source, library);
FunctionDeclaration function = unit.declarations[2] as FunctionDeclaration;
@@ -953,6 +953,30 @@
assertNoErrors();
verify([source]);
}
+ void test_invalidMethodOverrideNamedParamType() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m({int a}) {}", "}", "class B implements A {", " m({int a, int b}) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_invalidOverrideDifferentDefaultValues_named() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m({int p : 0}) {}", "}", "class B extends A {", " m({int p : 0}) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_invalidOverrideDifferentDefaultValues_positional() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m([int p = 0]) {}", "}", "class B extends A {", " m([int p = 0]) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_invalidOverrideDifferentDefaultValues_positional_changedOrder() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m([int a = 0, String b = '0']) {}", "}", "class B extends A {", " m([int b = 0, String a = '0']) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
void test_invalidOverrideNamed_unorderedNamedParameter() {
Source source = addSource(EngineTestCase.createSource(["class A {", " m({a, b}) {}", "}", "class B extends A {", " m({b, a}) {}", "}"]));
resolve(source);
@@ -1157,6 +1181,42 @@
assertNoErrors();
verify([source]);
}
+ void test_nonConstantDefaultValue_function_named() {
+ Source source = addSource(EngineTestCase.createSource(["f({x : 2 + 3}) {}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_function_positional() {
+ Source source = addSource(EngineTestCase.createSource(["f([x = 2 + 3]) {}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_inConstructor_named() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " A({x : 2 + 3}) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_inConstructor_positional() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " A([x = 2 + 3]) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_method_named() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m({x : 2 + 3}) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_method_positional() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m([x = 2 + 3]) {}", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
void test_nonConstCaseExpression() {
Source source = addSource(EngineTestCase.createSource(["f(Type t) {", " switch (t) {", " case bool:", " case int:", " return true;", " default:", " return false;", " }", "}"]));
resolve(source);
@@ -1445,6 +1505,12 @@
assertNoErrors();
verify([source]);
}
+ void test_undefinedConstructorInInitializer_hasOptionalParameters() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " A([p]) {}", "}", "class B extends A {", " B();", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
void test_undefinedConstructorInInitializer_implicit() {
Source source = addSource(EngineTestCase.createSource(["class A {", " A() {}", "}", "class B extends A {", " B();", "}"]));
resolve(source);
@@ -1869,6 +1935,22 @@
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_invalidFactoryNameNotAClass);
});
+ _ut.test('test_invalidMethodOverrideNamedParamType', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_invalidMethodOverrideNamedParamType);
+ });
+ _ut.test('test_invalidOverrideDifferentDefaultValues_named', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_invalidOverrideDifferentDefaultValues_named);
+ });
+ _ut.test('test_invalidOverrideDifferentDefaultValues_positional', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_invalidOverrideDifferentDefaultValues_positional);
+ });
+ _ut.test('test_invalidOverrideDifferentDefaultValues_positional_changedOrder', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_invalidOverrideDifferentDefaultValues_positional_changedOrder);
+ });
_ut.test('test_invalidOverrideNamed_unorderedNamedParameter', () {
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_invalidOverrideNamed_unorderedNamedParameter);
@@ -2053,6 +2135,30 @@
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_nonConstValueInInitializer_unary);
});
+ _ut.test('test_nonConstantDefaultValue_function_named', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_function_named);
+ });
+ _ut.test('test_nonConstantDefaultValue_function_positional', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_function_positional);
+ });
+ _ut.test('test_nonConstantDefaultValue_inConstructor_named', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_inConstructor_named);
+ });
+ _ut.test('test_nonConstantDefaultValue_inConstructor_positional', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_inConstructor_positional);
+ });
+ _ut.test('test_nonConstantDefaultValue_method_named', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_method_named);
+ });
+ _ut.test('test_nonConstantDefaultValue_method_positional', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_method_positional);
+ });
_ut.test('test_nonGenerativeConstructor', () {
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_nonGenerativeConstructor);
@@ -2197,6 +2303,10 @@
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_undefinedConstructorInInitializer_explicit_unnamed);
});
+ _ut.test('test_undefinedConstructorInInitializer_hasOptionalParameters', () {
+ final __test = new NonErrorResolverTest();
+ runJUnitTest(__test, __test.test_undefinedConstructorInInitializer_hasOptionalParameters);
+ });
_ut.test('test_undefinedConstructorInInitializer_implicit', () {
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_undefinedConstructorInInitializer_implicit);
@@ -2548,12 +2658,48 @@
assertErrors([StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
verify([source]);
}
+ void test_returnOfInvalidType_expressionFunctionBody_function() {
+ Source source = addSource(EngineTestCase.createSource(["int f() => '0';"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+ verify([source]);
+ }
+ void test_returnOfInvalidType_expressionFunctionBody_getter() {
+ Source source = addSource(EngineTestCase.createSource(["int get g => '0';"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+ verify([source]);
+ }
+ void test_returnOfInvalidType_expressionFunctionBody_localFunction() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " String m() {", " int f() => '0';", " }", "}"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+ verify([source]);
+ }
+ void test_returnOfInvalidType_expressionFunctionBody_method() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int f() => '0';", "}"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+ verify([source]);
+ }
+ void test_returnOfInvalidType_expressionFunctionBody_void() {
+ Source source = addSource(EngineTestCase.createSource(["void f() => 42;"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+ verify([source]);
+ }
void test_returnOfInvalidType_function() {
Source source = addSource(EngineTestCase.createSource(["int f() { return '0'; }"]));
resolve(source);
assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
verify([source]);
}
+ void test_returnOfInvalidType_getter() {
+ Source source = addSource(EngineTestCase.createSource(["int get g { return '0'; }"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
+ verify([source]);
+ }
void test_returnOfInvalidType_localFunction() {
Source source = addSource(EngineTestCase.createSource(["class A {", " String m() {", " int f() { return '0'; }", " }", "}"]));
resolve(source);
@@ -2604,6 +2750,11 @@
resolve(source);
assertErrors([StaticTypeWarningCode.UNDEFINED_METHOD]);
}
+ void test_undefinedMethod_ignoreTypePropagation() {
+ Source source = addSource(EngineTestCase.createSource(["class A {}", "class B extends A {", " m() {}", "}", "class C {", "f() {", " A a = new B();", " a.m();", " }", "}"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.UNDEFINED_METHOD]);
+ }
void test_undefinedOperator_indexBoth() {
Source source = addSource(EngineTestCase.createSource(["class A {}", "f(A a) {", " a[0]++;", "}"]));
resolve(source);
@@ -2725,10 +2876,34 @@
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_nonBoolExpression);
});
+ _ut.test('test_returnOfInvalidType_expressionFunctionBody_function', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_returnOfInvalidType_expressionFunctionBody_function);
+ });
+ _ut.test('test_returnOfInvalidType_expressionFunctionBody_getter', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_returnOfInvalidType_expressionFunctionBody_getter);
+ });
+ _ut.test('test_returnOfInvalidType_expressionFunctionBody_localFunction', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_returnOfInvalidType_expressionFunctionBody_localFunction);
+ });
+ _ut.test('test_returnOfInvalidType_expressionFunctionBody_method', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_returnOfInvalidType_expressionFunctionBody_method);
+ });
+ _ut.test('test_returnOfInvalidType_expressionFunctionBody_void', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_returnOfInvalidType_expressionFunctionBody_void);
+ });
_ut.test('test_returnOfInvalidType_function', () {
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_returnOfInvalidType_function);
});
+ _ut.test('test_returnOfInvalidType_getter', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_returnOfInvalidType_getter);
+ });
_ut.test('test_returnOfInvalidType_localFunction', () {
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_returnOfInvalidType_localFunction);
@@ -2765,6 +2940,10 @@
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_undefinedMethod);
});
+ _ut.test('test_undefinedMethod_ignoreTypePropagation', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_undefinedMethod_ignoreTypePropagation);
+ });
_ut.test('test_undefinedOperator_indexBoth', () {
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_undefinedOperator_indexBoth);
@@ -3115,7 +3294,7 @@
class ResolverTestCase extends EngineTestCase {
/**
- * The source factory used to create {@link Source sources}.
+ * The source factory used to create [Source sources].
*/
SourceFactory _sourceFactory;
@@ -3194,7 +3373,7 @@
}
/**
- * Create a library element that represents a library named {@code "test"} containing a single
+ * Create a library element that represents a library named `"test"` containing a single
* empty compilation unit.
* @return the library element that was created
*/
@@ -3251,7 +3430,7 @@
/**
* Given a library and all of its parts, resolve the contents of the library and the contents of
* the parts. This assumes that the sources for the library and its parts have already been added
- * to the content provider using the method {@link #addSource(String,String)}.
+ * to the content provider using the method [addSource].
* @param librarySource the source for the compilation unit that defines the library
* @return the element representing the resolved library
* @throws AnalysisException if the analysis could not be performed
@@ -3880,18 +4059,6 @@
assertErrors([CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
verify([source]);
}
- void fail_nonConstantDefaultValue_named() {
- Source source = addSource(EngineTestCase.createSource(["f({x : 2 + 3}) {}"]));
- resolve(source);
- assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
- verify([source]);
- }
- void fail_nonConstantDefaultValue_positional() {
- Source source = addSource(EngineTestCase.createSource(["f([x = 2 + 3]) {}"]));
- resolve(source);
- assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
- verify([source]);
- }
void fail_objectCannotExtendAnotherClass() {
Source source = addSource(EngineTestCase.createSource([]));
resolve(source);
@@ -3940,24 +4107,6 @@
assertErrors([CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT]);
verify([source]);
}
- void fail_typeArgumentsForNonGenericClass_creation_const() {
- Source source = addSource(EngineTestCase.createSource(["class A {}", "f(p) {", " return const A<int>();", "}"]));
- resolve(source);
- assertErrors([CompileTimeErrorCode.TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS]);
- verify([source]);
- }
- void fail_typeArgumentsForNonGenericClass_creation_new() {
- Source source = addSource(EngineTestCase.createSource(["class A {}", "f(p) {", " return new A<int>();", "}"]));
- resolve(source);
- assertErrors([CompileTimeErrorCode.TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS]);
- verify([source]);
- }
- void fail_typeArgumentsForNonGenericClass_typeCast() {
- Source source = addSource(EngineTestCase.createSource(["class A {}", "f(p) {", " return p as A<int>;", "}"]));
- resolve(source);
- assertErrors([CompileTimeErrorCode.TYPE_ARGUMENTS_FOR_NON_GENERIC_CLASS]);
- verify([source]);
- }
void fail_uninitializedFinalField() {
Source source = addSource(EngineTestCase.createSource(["class A {", " final int i;", "}"]));
resolve(source);
@@ -4364,31 +4513,31 @@
void test_extendsOrImplementsDisallowedClass_extends_bool() {
Source source = addSource(EngineTestCase.createSource(["class A extends bool {}"]));
resolve(source);
- assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+ assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
verify([source]);
}
void test_extendsOrImplementsDisallowedClass_extends_double() {
Source source = addSource(EngineTestCase.createSource(["class A extends double {}"]));
resolve(source);
- assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+ assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
verify([source]);
}
void test_extendsOrImplementsDisallowedClass_extends_int() {
Source source = addSource(EngineTestCase.createSource(["class A extends int {}"]));
resolve(source);
- assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+ assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
verify([source]);
}
void test_extendsOrImplementsDisallowedClass_extends_num() {
Source source = addSource(EngineTestCase.createSource(["class A extends num {}"]));
resolve(source);
- assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+ assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
verify([source]);
}
void test_extendsOrImplementsDisallowedClass_extends_String() {
Source source = addSource(EngineTestCase.createSource(["class A extends String {}"]));
resolve(source);
- assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]);
+ assertErrors([CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
verify([source]);
}
void test_extendsOrImplementsDisallowedClass_implements_bool() {
@@ -4504,7 +4653,7 @@
* This test doesn't test the FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR code, but tests the
* FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION code instead. It is provided here to show
* coverage over all of the permutations of initializers in constructor declarations.
- * <p>
+ *
* Note: FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION covers a subset of
* FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR, since it more specific, we use it instead of
* the broader code
@@ -4532,7 +4681,7 @@
* This test doesn't test the FINAL_INITIALIZED_MULTIPLE_TIMES code, but tests the
* FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER code instead. It is provided here to show
* coverage over all of the permutations of initializers in constructor declarations.
- * <p>
+ *
* Note: FIELD_INITIALIZED_IN_PARAMETER_AND_INITIALIZER covers a subset of
* FINAL_INITIALIZED_MULTIPLE_TIMES, since it more specific, we use it instead of the broader code
*/
@@ -4926,6 +5075,42 @@
assertErrors([CompileTimeErrorCode.NEW_WITH_INVALID_TYPE_PARAMETERS]);
verify([source]);
}
+ void test_nonConstantDefaultValue_function_named() {
+ Source source = addSource(EngineTestCase.createSource(["int y;", "f({x : y}) {}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_function_positional() {
+ Source source = addSource(EngineTestCase.createSource(["int y;", "f([x = y]) {}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_inConstructor_named() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int y;", " A({x : y}) {}", "}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_inConstructor_positional() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int y;", " A([x = y]) {}", "}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_method_named() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int y;", " m({x : y}) {}", "}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+ verify([source]);
+ }
+ void test_nonConstantDefaultValue_method_positional() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int y;", " m([x = y]) {}", "}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE]);
+ verify([source]);
+ }
void test_nonConstCaseExpression() {
Source source = addSource(EngineTestCase.createSource(["f(int p, int q) {", " switch (p) {", " case 3 + q:", " break;", " }", "}"]));
resolve(source);
@@ -6076,6 +6261,30 @@
final __test = new CompileTimeErrorCodeTest();
runJUnitTest(__test, __test.test_nonConstValueInInitializer_super);
});
+ _ut.test('test_nonConstantDefaultValue_function_named', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_function_named);
+ });
+ _ut.test('test_nonConstantDefaultValue_function_positional', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_function_positional);
+ });
+ _ut.test('test_nonConstantDefaultValue_inConstructor_named', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_inConstructor_named);
+ });
+ _ut.test('test_nonConstantDefaultValue_inConstructor_positional', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_inConstructor_positional);
+ });
+ _ut.test('test_nonConstantDefaultValue_method_named', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_method_named);
+ });
+ _ut.test('test_nonConstantDefaultValue_method_positional', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_nonConstantDefaultValue_method_positional);
+ });
_ut.test('test_nonGenerativeConstructor_explicit', () {
final __test = new CompileTimeErrorCodeTest();
runJUnitTest(__test, __test.test_nonGenerativeConstructor_explicit);
@@ -6324,7 +6533,7 @@
}
}
/**
- * Instances of the class {@code StaticTypeVerifier} verify that all of the nodes in an AST
+ * Instances of the class `StaticTypeVerifier` verify that all of the nodes in an AST
* structure that should have a static type associated with them do have a static type.
*/
class StaticTypeVerifier extends GeneralizingASTVisitor<Object> {
@@ -6458,7 +6667,7 @@
}
}
/**
- * The class {@code StrictModeTest} contains tests to ensure that the correct errors and warnings
+ * The class `StrictModeTest` contains tests to ensure that the correct errors and warnings
* are reported when the analysis engine is run in strict mode.
*/
class StrictModeTest extends ResolverTestCase {
@@ -6960,7 +7169,7 @@
resolveInClass(node, classA);
Element element = node.element;
EngineTestCase.assertInstanceOf(PropertyAccessorElement, element);
- JUnitTestCase.assertTrue(((element as PropertyAccessorElement)).isSetter());
+ JUnitTestCase.assertTrue(((element as PropertyAccessorElement)).isSetter);
_listener.assertNoErrors();
}
void test_visitSuperConstructorInvocation() {
@@ -7538,12 +7747,6 @@
assertErrors([StaticWarningCode.INVALID_FACTORY_NAME]);
verify([source]);
}
- void fail_invalidOverrideDifferentDefaultValues() {
- Source source = addSource(EngineTestCase.createSource(["class A {", " m([int p = 0]) {}", "}", "class B extends A {", " m([int p = 1]) {}", "}"]));
- resolve(source);
- assertErrors([StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES]);
- verify([source]);
- }
void fail_invocationOfNonFunction() {
Source source = addSource(EngineTestCase.createSource([]));
resolve(source);
@@ -8041,6 +8244,18 @@
assertErrors([StaticWarningCode.INVALID_METHOD_OVERRIDE_RETURN_TYPE]);
verify([source]);
}
+ void test_invalidOverrideDifferentDefaultValues_named() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m({int p : 0}) {}", "}", "class B extends A {", " m({int p : 1}) {}", "}"]));
+ resolve(source);
+ assertErrors([StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED]);
+ verify([source]);
+ }
+ void test_invalidOverrideDifferentDefaultValues_positional() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " m([int p = 0]) {}", "}", "class B extends A {", " m([int p = 1]) {}", "}"]));
+ resolve(source);
+ assertErrors([StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL]);
+ verify([source]);
+ }
void test_invalidSetterOverrideNormalParamType() {
Source source = addSource(EngineTestCase.createSource(["class A {", " void set s(int v) {}", "}", "class B extends A {", " void set s(String v) {}", "}"]));
resolve(source);
@@ -8082,6 +8297,24 @@
assertErrors([StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT]);
verify([source]);
}
+ void test_noDefaultSuperConstructorExplicit() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " A(p);", "}", "class B extends A {", " B() {}", "}"]));
+ resolve(source);
+ assertErrors([StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT]);
+ verify([source]);
+ }
+ void test_noDefaultSuperConstructorImplicit_superHasParameters() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " A(p);", "}", "class B extends A {", "}"]));
+ resolve(source);
+ assertErrors([StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
+ verify([source]);
+ }
+ void test_noDefaultSuperConstructorImplicit_superOnlyNamed() {
+ Source source = addSource(EngineTestCase.createSource(["class A { A.named() {} }", "class B extends A {}"]));
+ resolve(source);
+ assertErrors([StaticWarningCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT]);
+ verify([source]);
+ }
void test_nonAbstractClassInheritsAbstractMemberFivePlus() {
Source source = addSource(EngineTestCase.createSource(["abstract class A {", " m();", " n();", " o();", " p();", " q();", "}", "class C extends A {", "}"]));
resolve(source);
@@ -8136,6 +8369,12 @@
assertErrors([StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
verify([source]);
}
+ void test_nonAbstractClassInheritsAbstractMemberOne_superclasses_interface() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " get a => 'a';", "}", "abstract class B implements A {", " get b => 'b';", "}", "class C extends B {", "}"]));
+ resolve(source);
+ assertErrors([StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE]);
+ verify([source]);
+ }
void test_nonAbstractClassInheritsAbstractMemberThree() {
Source source = addSource(EngineTestCase.createSource(["abstract class A {", " m();", " n();", " o();", "}", "class C extends A {", "}"]));
resolve(source);
@@ -8602,6 +8841,14 @@
final __test = new StaticWarningCodeTest();
runJUnitTest(__test, __test.test_invalidMethodOverrideReturnType_void);
});
+ _ut.test('test_invalidOverrideDifferentDefaultValues_named', () {
+ final __test = new StaticWarningCodeTest();
+ runJUnitTest(__test, __test.test_invalidOverrideDifferentDefaultValues_named);
+ });
+ _ut.test('test_invalidOverrideDifferentDefaultValues_positional', () {
+ final __test = new StaticWarningCodeTest();
+ runJUnitTest(__test, __test.test_invalidOverrideDifferentDefaultValues_positional);
+ });
_ut.test('test_invalidSetterOverrideNormalParamType', () {
final __test = new StaticWarningCodeTest();
runJUnitTest(__test, __test.test_invalidSetterOverrideNormalParamType);
@@ -8630,6 +8877,18 @@
final __test = new StaticWarningCodeTest();
runJUnitTest(__test, __test.test_newWithUndefinedConstructorDefault);
});
+ _ut.test('test_noDefaultSuperConstructorExplicit', () {
+ final __test = new StaticWarningCodeTest();
+ runJUnitTest(__test, __test.test_noDefaultSuperConstructorExplicit);
+ });
+ _ut.test('test_noDefaultSuperConstructorImplicit_superHasParameters', () {
+ final __test = new StaticWarningCodeTest();
+ runJUnitTest(__test, __test.test_noDefaultSuperConstructorImplicit_superHasParameters);
+ });
+ _ut.test('test_noDefaultSuperConstructorImplicit_superOnlyNamed', () {
+ final __test = new StaticWarningCodeTest();
+ runJUnitTest(__test, __test.test_noDefaultSuperConstructorImplicit_superOnlyNamed);
+ });
_ut.test('test_nonAbstractClassInheritsAbstractMemberFivePlus', () {
final __test = new StaticWarningCodeTest();
runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberFivePlus);
@@ -8666,6 +8925,10 @@
final __test = new StaticWarningCodeTest();
runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberOne_setter_fromSuperclass);
});
+ _ut.test('test_nonAbstractClassInheritsAbstractMemberOne_superclasses_interface', () {
+ final __test = new StaticWarningCodeTest();
+ runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberOne_superclasses_interface);
+ });
_ut.test('test_nonAbstractClassInheritsAbstractMemberThree', () {
final __test = new StaticWarningCodeTest();
runJUnitTest(__test, __test.test_nonAbstractClassInheritsAbstractMemberThree);
@@ -8816,7 +9079,7 @@
}
}
/**
- * Instances of the class {@code TestTypeProvider} implement a type provider that can be used by
+ * Instances of the class `TestTypeProvider` implement a type provider that can be used by
* tests without creating the element model for the core library.
*/
class TestTypeProvider implements TypeProvider {
@@ -8937,6 +9200,7 @@
_iterableType = iterableElement.type;
Type2 eType = iterableElement.typeVariables[0].type;
iterableElement.accessors = <PropertyAccessorElement> [ElementFactory.getterElement("iterator", false, iteratorType.substitute5(<Type2> [eType])), ElementFactory.getterElement("last", false, eType)];
+ propagateTypeArguments(iterableElement);
}
return _iterableType;
}
@@ -8946,6 +9210,7 @@
_iteratorType = iteratorElement.type;
Type2 eType = iteratorElement.typeVariables[0].type;
iteratorElement.accessors = <PropertyAccessorElement> [ElementFactory.getterElement("current", false, eType)];
+ propagateTypeArguments(iteratorElement);
}
return _iteratorType;
}
@@ -8958,7 +9223,8 @@
InterfaceType supertype = iterableType.substitute5(<Type2> [eType]);
listElement.supertype = supertype;
listElement.accessors = <PropertyAccessorElement> [ElementFactory.getterElement("length", false, intType)];
- listElement.methods = <MethodElement> [ElementFactory.methodElement("[]", eType, [intType]), ElementFactory.methodElement("[]=", VoidTypeImpl.instance, [intType, eType])];
+ listElement.methods = <MethodElement> [ElementFactory.methodElement("[]", eType, [intType]), ElementFactory.methodElement("[]=", VoidTypeImpl.instance, [intType, eType]), ElementFactory.methodElement("add", VoidTypeImpl.instance, [eType])];
+ propagateTypeArguments(listElement);
}
return _listType;
}
@@ -8967,6 +9233,7 @@
ClassElementImpl mapElement = ElementFactory.classElement2("Map", ["K", "V"]);
_mapType = mapElement.type;
mapElement.accessors = <PropertyAccessorElement> [ElementFactory.getterElement("length", false, intType)];
+ propagateTypeArguments(mapElement);
}
return _mapType;
}
@@ -9035,9 +9302,30 @@
doubleElement.accessors = accessors;
doubleElement.methods = <MethodElement> [ElementFactory.methodElement("remainder", _doubleType, [_numType]), ElementFactory.methodElement("+", _doubleType, [_numType]), ElementFactory.methodElement("-", _doubleType, [_numType]), ElementFactory.methodElement("*", _doubleType, [_numType]), ElementFactory.methodElement("%", _doubleType, [_numType]), ElementFactory.methodElement("/", _doubleType, [_numType]), ElementFactory.methodElement("~/", _doubleType, [_numType]), ElementFactory.methodElement("-", _doubleType, []), ElementFactory.methodElement("abs", _doubleType, []), ElementFactory.methodElement("round", _doubleType, []), ElementFactory.methodElement("floor", _doubleType, []), ElementFactory.methodElement("ceil", _doubleType, []), ElementFactory.methodElement("truncate", _doubleType, []), ElementFactory.methodElement("toString", _stringType, [])];
}
+
+ /**
+ * Given a class element representing a class with type parameters, propagate those type
+ * parameters to all of the accessors, methods and constructors defined for the class.
+ * @param classElement the element representing the class with type parameters
+ */
+ void propagateTypeArguments(ClassElementImpl classElement) {
+ List<Type2> typeArguments = TypeVariableTypeImpl.getTypes(classElement.typeVariables);
+ for (PropertyAccessorElement accessor in classElement.accessors) {
+ FunctionTypeImpl functionType = accessor.type as FunctionTypeImpl;
+ functionType.typeArguments = typeArguments;
+ }
+ for (MethodElement method in classElement.methods) {
+ FunctionTypeImpl functionType = method.type as FunctionTypeImpl;
+ functionType.typeArguments = typeArguments;
+ }
+ for (ConstructorElement constructor in classElement.constructors) {
+ FunctionTypeImpl functionType = constructor.type as FunctionTypeImpl;
+ functionType.typeArguments = typeArguments;
+ }
+ }
}
/**
- * The class {@code AnalysisContextFactory} defines utility methods used to create analysis contexts
+ * The class `AnalysisContextFactory` defines utility methods used to create analysis contexts
* for testing purposes.
*/
class AnalysisContextFactory {
@@ -9210,7 +9498,7 @@
}
}
/**
- * Instances of the class {@code ResolutionVerifier} verify that all of the nodes in an AST
+ * Instances of the class `ResolutionVerifier` verify that all of the nodes in an AST
* structure that should have been resolved were resolved.
*/
class ResolutionVerifier extends RecursiveASTVisitor<Object> {
@@ -9280,7 +9568,7 @@
}
Object visitBinaryExpression(BinaryExpression node) {
node.visitChildren(this);
- if (!node.operator.isUserDefinableOperator()) {
+ if (!node.operator.isUserDefinableOperator) {
return null;
}
return checkResolved2(node, node.element, MethodElement);
@@ -9318,14 +9606,14 @@
Object visitPartOfDirective(PartOfDirective node) => checkResolved2(node, node.element, LibraryElement);
Object visitPostfixExpression(PostfixExpression node) {
node.visitChildren(this);
- if (!node.operator.isUserDefinableOperator()) {
+ if (!node.operator.isUserDefinableOperator) {
return null;
}
return checkResolved2(node, node.element, MethodElement);
}
Object visitPrefixExpression(PrefixExpression node) {
node.visitChildren(this);
- if (!node.operator.isUserDefinableOperator()) {
+ if (!node.operator.isUserDefinableOperator) {
return null;
}
return checkResolved2(node, node.element, MethodElement);
@@ -9771,8 +10059,8 @@
ClassElementImpl classElement = ElementFactory.classElement2("C", []);
String constructorName = "m";
ConstructorElementImpl constructor = ElementFactory.constructorElement(classElement, constructorName);
+ constructor.returnType = classElement.type;
FunctionTypeImpl constructorType = new FunctionTypeImpl.con1(constructor);
- constructorType.returnType = classElement.type;
constructor.type = constructorType;
classElement.constructors = <ConstructorElement> [constructor];
InstanceCreationExpression node = ASTFactory.instanceCreationExpression2(null, ASTFactory.typeName(classElement, []), [ASTFactory.identifier3(constructorName)]);
@@ -9785,8 +10073,8 @@
ClassElementImpl elementI = ElementFactory.classElement2("I", []);
ConstructorElementImpl constructor = ElementFactory.constructorElement(elementC, null);
elementC.constructors = <ConstructorElement> [constructor];
+ constructor.returnType = elementC.type;
FunctionTypeImpl constructorType = new FunctionTypeImpl.con1(constructor);
- constructorType.returnType = elementC.type;
constructor.type = constructorType;
TypeName typeName = ASTFactory.typeName(elementC, [ASTFactory.typeName(elementI, [])]);
typeName.type = elementC.type.substitute5(<Type2> [elementI.type]);
@@ -9801,8 +10089,8 @@
void test_visitInstanceCreationExpression_unnamed() {
ClassElementImpl classElement = ElementFactory.classElement2("C", []);
ConstructorElementImpl constructor = ElementFactory.constructorElement(classElement, null);
+ constructor.returnType = classElement.type;
FunctionTypeImpl constructorType = new FunctionTypeImpl.con1(constructor);
- constructorType.returnType = classElement.type;
constructor.type = constructorType;
classElement.constructors = <ConstructorElement> [constructor];
InstanceCreationExpression node = ASTFactory.instanceCreationExpression2(null, ASTFactory.typeName(classElement, []), []);
@@ -10125,7 +10413,7 @@
/**
* Create a function expression that has an element associated with it, where the element has an
- * incomplete type associated with it (just like the one{@link ElementBuilder#visitFunctionExpression(FunctionExpression)} would have built if we had
+ * incomplete type associated with it (just like the one[ElementBuilder#visitFunctionExpression] would have built if we had
* run it).
* @param parameters the parameters to the function
* @param body the body of the function
@@ -10529,7 +10817,7 @@
class LibraryElementBuilderTest extends EngineTestCase {
/**
- * The source factory used to create {@link Source sources}.
+ * The source factory used to create [Source sources].
*/
SourceFactory _sourceFactory;
void setUp() {
@@ -10964,7 +11252,7 @@
JUnitTestCase.assertNotNull(unit);
List<ClassElement> classes = unit.types;
EngineTestCase.assertLength(2, classes);
- JUnitTestCase.assertFalse(classes[0].isValidMixin());
+ JUnitTestCase.assertFalse(classes[0].isValidMixin);
assertNoErrors();
verify([source]);
}
@@ -10976,7 +11264,7 @@
JUnitTestCase.assertNotNull(unit);
List<ClassElement> classes = unit.types;
EngineTestCase.assertLength(1, classes);
- JUnitTestCase.assertFalse(classes[0].isValidMixin());
+ JUnitTestCase.assertFalse(classes[0].isValidMixin);
assertNoErrors();
verify([source]);
}
@@ -10988,7 +11276,7 @@
JUnitTestCase.assertNotNull(unit);
List<ClassElement> classes = unit.types;
EngineTestCase.assertLength(1, classes);
- JUnitTestCase.assertFalse(classes[0].isValidMixin());
+ JUnitTestCase.assertFalse(classes[0].isValidMixin);
assertNoErrors();
verify([source]);
}
@@ -11000,7 +11288,7 @@
JUnitTestCase.assertNotNull(unit);
List<ClassElement> classes = unit.types;
EngineTestCase.assertLength(1, classes);
- JUnitTestCase.assertTrue(classes[0].isValidMixin());
+ JUnitTestCase.assertTrue(classes[0].isValidMixin);
assertNoErrors();
verify([source]);
}
@@ -11092,7 +11380,7 @@
verify([source]);
}
void test_setter_inherited() {
- Source source = addSource(EngineTestCase.createSource(["class A {", " int get x => 0;", " set x(int p) {}", "}", "class B extends A {", " int get x => super.x == null ? 0 : super.x;", " void f() => x = 1;", "}"]));
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int get x => 0;", " set x(int p) {}", "}", "class B extends A {", " int get x => super.x == null ? 0 : super.x;", " int f() => x = 1;", "}"]));
resolve(source);
assertNoErrors();
verify([source]);
@@ -11107,13 +11395,13 @@
/**
* Resolve the given source and verify that the arguments in a specific method invocation were
* correctly resolved.
- * <p>
+ *
* The source is expected to be source for a compilation unit, the first declaration is expected
* to be a class, the first member of which is expected to be a method with a block body, and the
* first statement in the body is expected to be an expression statement whose expression is a
* method invocation. It is the arguments to that method invocation that are tested. The method
* invocation can contain errors.
- * <p>
+ *
* The arguments were resolved correctly if the number of expressions in the list matches the
* length of the array of indices and if, for each index in the array of indices, the parameter to
* which the argument expression was resolved is the parameter in the invoked method's list of
@@ -11347,7 +11635,6 @@
// CompileTimeErrorCodeTest.dartSuite();
// ErrorResolverTest.dartSuite();
// NonErrorResolverTest.dartSuite();
-// PubSuggestionCodeTest.dartSuite();
// SimpleResolverTest.dartSuite();
// StaticTypeWarningCodeTest.dartSuite();
// StaticWarningCodeTest.dartSuite();
diff --git a/pkg/analyzer_experimental/test/generated/scanner_test.dart b/pkg/analyzer_experimental/test/generated/scanner_test.dart
index e9ff970..b48df5f 100644
--- a/pkg/analyzer_experimental/test/generated/scanner_test.dart
+++ b/pkg/analyzer_experimental/test/generated/scanner_test.dart
@@ -53,67 +53,67 @@
}
class TokenTypeTest extends EngineTestCase {
void test_isOperator() {
- JUnitTestCase.assertTrue(TokenType.AMPERSAND.isOperator());
- JUnitTestCase.assertTrue(TokenType.AMPERSAND_AMPERSAND.isOperator());
- JUnitTestCase.assertTrue(TokenType.AMPERSAND_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.BANG.isOperator());
- JUnitTestCase.assertTrue(TokenType.BANG_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.BAR.isOperator());
- JUnitTestCase.assertTrue(TokenType.BAR_BAR.isOperator());
- JUnitTestCase.assertTrue(TokenType.BAR_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.CARET.isOperator());
- JUnitTestCase.assertTrue(TokenType.CARET_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.EQ_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.GT.isOperator());
- JUnitTestCase.assertTrue(TokenType.GT_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.GT_GT.isOperator());
- JUnitTestCase.assertTrue(TokenType.GT_GT_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.INDEX.isOperator());
- JUnitTestCase.assertTrue(TokenType.INDEX_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.IS.isOperator());
- JUnitTestCase.assertTrue(TokenType.LT.isOperator());
- JUnitTestCase.assertTrue(TokenType.LT_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.LT_LT.isOperator());
- JUnitTestCase.assertTrue(TokenType.LT_LT_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.MINUS.isOperator());
- JUnitTestCase.assertTrue(TokenType.MINUS_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.MINUS_MINUS.isOperator());
- JUnitTestCase.assertTrue(TokenType.PERCENT.isOperator());
- JUnitTestCase.assertTrue(TokenType.PERCENT_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.PERIOD_PERIOD.isOperator());
- JUnitTestCase.assertTrue(TokenType.PLUS.isOperator());
- JUnitTestCase.assertTrue(TokenType.PLUS_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.PLUS_PLUS.isOperator());
- JUnitTestCase.assertTrue(TokenType.QUESTION.isOperator());
- JUnitTestCase.assertTrue(TokenType.SLASH.isOperator());
- JUnitTestCase.assertTrue(TokenType.SLASH_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.STAR.isOperator());
- JUnitTestCase.assertTrue(TokenType.STAR_EQ.isOperator());
- JUnitTestCase.assertTrue(TokenType.TILDE.isOperator());
- JUnitTestCase.assertTrue(TokenType.TILDE_SLASH.isOperator());
- JUnitTestCase.assertTrue(TokenType.TILDE_SLASH_EQ.isOperator());
+ JUnitTestCase.assertTrue(TokenType.AMPERSAND.isOperator);
+ JUnitTestCase.assertTrue(TokenType.AMPERSAND_AMPERSAND.isOperator);
+ JUnitTestCase.assertTrue(TokenType.AMPERSAND_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.BANG.isOperator);
+ JUnitTestCase.assertTrue(TokenType.BANG_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.BAR.isOperator);
+ JUnitTestCase.assertTrue(TokenType.BAR_BAR.isOperator);
+ JUnitTestCase.assertTrue(TokenType.BAR_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.CARET.isOperator);
+ JUnitTestCase.assertTrue(TokenType.CARET_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.EQ_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.GT.isOperator);
+ JUnitTestCase.assertTrue(TokenType.GT_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.GT_GT.isOperator);
+ JUnitTestCase.assertTrue(TokenType.GT_GT_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.INDEX.isOperator);
+ JUnitTestCase.assertTrue(TokenType.INDEX_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.IS.isOperator);
+ JUnitTestCase.assertTrue(TokenType.LT.isOperator);
+ JUnitTestCase.assertTrue(TokenType.LT_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.LT_LT.isOperator);
+ JUnitTestCase.assertTrue(TokenType.LT_LT_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.MINUS.isOperator);
+ JUnitTestCase.assertTrue(TokenType.MINUS_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.MINUS_MINUS.isOperator);
+ JUnitTestCase.assertTrue(TokenType.PERCENT.isOperator);
+ JUnitTestCase.assertTrue(TokenType.PERCENT_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.PERIOD_PERIOD.isOperator);
+ JUnitTestCase.assertTrue(TokenType.PLUS.isOperator);
+ JUnitTestCase.assertTrue(TokenType.PLUS_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.PLUS_PLUS.isOperator);
+ JUnitTestCase.assertTrue(TokenType.QUESTION.isOperator);
+ JUnitTestCase.assertTrue(TokenType.SLASH.isOperator);
+ JUnitTestCase.assertTrue(TokenType.SLASH_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.STAR.isOperator);
+ JUnitTestCase.assertTrue(TokenType.STAR_EQ.isOperator);
+ JUnitTestCase.assertTrue(TokenType.TILDE.isOperator);
+ JUnitTestCase.assertTrue(TokenType.TILDE_SLASH.isOperator);
+ JUnitTestCase.assertTrue(TokenType.TILDE_SLASH_EQ.isOperator);
}
void test_isUserDefinableOperator() {
- JUnitTestCase.assertTrue(TokenType.AMPERSAND.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.BAR.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.CARET.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.EQ_EQ.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.GT.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.GT_EQ.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.GT_GT.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.INDEX.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.INDEX_EQ.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.LT.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.LT_EQ.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.LT_LT.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.MINUS.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.PERCENT.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.PLUS.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.SLASH.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.STAR.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.TILDE.isUserDefinableOperator());
- JUnitTestCase.assertTrue(TokenType.TILDE_SLASH.isUserDefinableOperator());
+ JUnitTestCase.assertTrue(TokenType.AMPERSAND.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.BAR.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.CARET.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.EQ_EQ.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.GT.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.GT_EQ.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.GT_GT.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.INDEX.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.INDEX_EQ.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.LT.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.LT_EQ.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.LT_LT.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.MINUS.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.PERCENT.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.PLUS.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.SLASH.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.STAR.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.TILDE.isUserDefinableOperator);
+ JUnitTestCase.assertTrue(TokenType.TILDE_SLASH.isUserDefinableOperator);
}
static dartSuite() {
_ut.group('TokenTypeTest', () {
@@ -129,7 +129,7 @@
}
}
/**
- * The class {@code TokenFactory} defines utility methods that can be used to create tokens.
+ * The class `TokenFactory` defines utility methods that can be used to create tokens.
*/
class TokenFactory {
static Token token(Keyword keyword) => new KeywordToken(keyword, 0);
@@ -1474,7 +1474,7 @@
}
}
/**
- * Instances of the class {@code TokenStreamValidator} are used to validate the correct construction
+ * Instances of the class `TokenStreamValidator` are used to validate the correct construction
* of a stream of tokens.
*/
class TokenStreamValidator {
@@ -2156,7 +2156,7 @@
}
}
/**
- * Instances of the class {@code ExpectedLocation} encode information about the expected location
+ * Instances of the class `ExpectedLocation` encode information about the expected location
* of a given offset in source code.
*/
class AbstractScannerTest_ExpectedLocation {
diff --git a/pkg/analyzer_experimental/test/generated/test_support.dart b/pkg/analyzer_experimental/test/generated/test_support.dart
index ea44668..6b39ac8 100644
--- a/pkg/analyzer_experimental/test/generated/test_support.dart
+++ b/pkg/analyzer_experimental/test/generated/test_support.dart
@@ -12,7 +12,7 @@
import 'package:analyzer_experimental/src/generated/engine.dart' show AnalysisContext, AnalysisContextImpl, RecordingErrorListener;
import 'package:unittest/unittest.dart' as _ut;
/**
- * Instances of the class {@code GatheringErrorListener} implement an error listener that collects
+ * Instances of the class `GatheringErrorListener` implement an error listener that collects
* all of the errors passed to it for later examination.
*/
class GatheringErrorListener implements AnalysisErrorListener {
@@ -227,7 +227,7 @@
List<AnalysisError> get errors => _errors;
/**
- * Return the line information associated with the given source, or {@code null} if no line
+ * Return the line information associated with the given source, or `null` if no line
* information has been associated with the source.
* @param source the source with which the line information is associated
* @return the line information associated with the source
@@ -235,9 +235,9 @@
LineInfo getLineInfo(Source source) => _lineInfoMap[source];
/**
- * Return {@code true} if an error with the given error code has been gathered.
+ * Return `true` if an error with the given error code has been gathered.
* @param errorCode the error code being searched for
- * @return {@code true} if an error with the given error code has been gathered
+ * @return `true` if an error with the given error code has been gathered
*/
bool hasError(ErrorCode errorCode2) {
for (AnalysisError error in _errors) {
@@ -249,8 +249,8 @@
}
/**
- * Return {@code true} if at least one error has been gathered.
- * @return {@code true} if at least one error has been gathered
+ * Return `true` if at least one error has been gathered.
+ * @return `true` if at least one error has been gathered
*/
bool hasErrors() => _errors.length > 0;
void onError(AnalysisError error) {
@@ -281,18 +281,18 @@
}
/**
- * Return {@code true} if the two errors are equivalent.
+ * Return `true` if the two errors are equivalent.
* @param firstError the first error being compared
* @param secondError the second error being compared
- * @return {@code true} if the two errors are equivalent
+ * @return `true` if the two errors are equivalent
*/
bool equals3(AnalysisError firstError, AnalysisError secondError) => identical(firstError.errorCode, secondError.errorCode) && firstError.offset == secondError.offset && firstError.length == secondError.length && equals4(firstError.source, secondError.source);
/**
- * Return {@code true} if the two sources are equivalent.
+ * Return `true` if the two sources are equivalent.
* @param firstSource the first source being compared
* @param secondSource the second source being compared
- * @return {@code true} if the two sources are equivalent
+ * @return `true` if the two sources are equivalent
*/
bool equals4(Source firstSource, Source secondSource) {
if (firstSource == null) {
@@ -348,10 +348,10 @@
/**
* Search through the given list of errors for an error that is equal to the target error. If one
- * is found, remove it from the list and return {@code true}, otherwise return {@code false}without modifying the list.
+ * is found, remove it from the list and return `true`, otherwise return `false`without modifying the list.
* @param errors the errors through which we are searching
* @param targetError the error being searched for
- * @return {@code true} if the error is found and removed from the list
+ * @return `true` if the error is found and removed from the list
*/
bool foundAndRemoved(List<AnalysisError> errors, AnalysisError targetError) {
for (AnalysisError error in errors) {
@@ -364,7 +364,7 @@
}
}
/**
- * The class {@code EngineTestCase} defines utility methods for making assertions.
+ * The class `EngineTestCase` defines utility methods for making assertions.
*/
class EngineTestCase extends JUnitTestCase {
static int _PRINT_RANGE = 6;
@@ -388,11 +388,11 @@
}
/**
- * Assert that the given array is non-{@code null} and contains the expected elements. The
+ * Assert that the given array is non-`null` and contains the expected elements. The
* elements can appear in any order.
* @param array the array being tested
* @param expectedElements the expected elements
- * @throws AssertionFailedError if the array is {@code null} or does not contain the expected
+ * @throws AssertionFailedError if the array is `null` or does not contain the expected
* elements
*/
static void assertContains(List<Object> array, List<Object> expectedElements) {
@@ -466,10 +466,10 @@
}
/**
- * Assert that the given list is non-{@code null} and has exactly expected elements.
+ * Assert that the given list is non-`null` and has exactly expected elements.
* @param list the list being tested
* @param expectedElements the expected elements
- * @throws AssertionFailedError if the list is {@code null} or does not have the expected elements
+ * @throws AssertionFailedError if the list is `null` or does not have the expected elements
*/
static void assertExactElements(List<Object> list, List<Object> expectedElements) {
int expectedSize = expectedElements.length;
@@ -489,10 +489,10 @@
}
/**
- * Assert that the given array is non-{@code null} and has exactly expected elements.
+ * Assert that the given array is non-`null` and has exactly expected elements.
* @param array the array being tested
* @param expectedElements the expected elements
- * @throws AssertionFailedError if the array is {@code null} or does not have the expected
+ * @throws AssertionFailedError if the array is `null` or does not have the expected
* elements
*/
static void assertExactElements2(List<Object> array, List<Object> expectedElements) {
@@ -513,10 +513,10 @@
}
/**
- * Assert that the given list is non-{@code null} and has exactly expected elements.
+ * Assert that the given list is non-`null` and has exactly expected elements.
* @param set the list being tested
* @param expectedElements the expected elements
- * @throws AssertionFailedError if the list is {@code null} or does not have the expected elements
+ * @throws AssertionFailedError if the list is `null` or does not have the expected elements
*/
static void assertExactElements3(Set<Object> set, List<Object> expectedElements) {
int expectedSize = expectedElements.length;
@@ -549,10 +549,10 @@
}
/**
- * Assert that the given array is non-{@code null} and has the expected number of elements.
+ * Assert that the given array is non-`null` and has the expected number of elements.
* @param expectedLength the expected number of elements
* @param array the array being tested
- * @throws AssertionFailedError if the array is {@code null} or does not have the expected number
+ * @throws AssertionFailedError if the array is `null` or does not have the expected number
* of elements
*/
static void assertLength(int expectedLength, List<Object> array) {
@@ -582,10 +582,10 @@
}
/**
- * Assert that the given list is non-{@code null} and has the expected number of elements.
+ * Assert that the given list is non-`null` and has the expected number of elements.
* @param expectedSize the expected number of elements
* @param list the list being tested
- * @throws AssertionFailedError if the list is {@code null} or does not have the expected number
+ * @throws AssertionFailedError if the list is `null` or does not have the expected number
* of elements
*/
static void assertSize(int expectedSize, List<Object> list) {
@@ -597,10 +597,10 @@
}
/**
- * Assert that the given map is non-{@code null} and has the expected number of elements.
+ * Assert that the given map is non-`null` and has the expected number of elements.
* @param expectedSize the expected number of elements
* @param map the map being tested
- * @throws AssertionFailedError if the map is {@code null} or does not have the expected number of
+ * @throws AssertionFailedError if the map is `null` or does not have the expected number of
* elements
*/
static void assertSize2(int expectedSize, Map<Object, Object> map) {
@@ -612,10 +612,10 @@
}
/**
- * Assert that the given set is non-{@code null} and has the expected number of elements.
+ * Assert that the given set is non-`null` and has the expected number of elements.
* @param expectedSize the expected number of elements
* @param set the set being tested
- * @throws AssertionFailedError if the set is {@code null} or does not have the expected number of
+ * @throws AssertionFailedError if the set is `null` or does not have the expected number of
* elements
*/
static void assertSize3(int expectedSize, Set<Object> set) {
@@ -696,7 +696,7 @@
*/
PropertyAccessorElement getGetter(InterfaceType type, String getterName) {
for (PropertyAccessorElement accessor in type.element.accessors) {
- if (accessor.isGetter() && accessor.name == getterName) {
+ if (accessor.isGetter && accessor.name == getterName) {
return accessor;
}
}
@@ -751,7 +751,7 @@
throw new UnsupportedOperationException();
}
bool exists() => true;
- bool isInSystemLibrary() {
+ bool get isInSystemLibrary {
throw new UnsupportedOperationException();
}
Source resolve(String uri) {
diff --git a/pkg/analyzer_experimental/test/services/formatter_test.dart b/pkg/analyzer_experimental/test/services/formatter_test.dart
index d88d2d9..9bf1395 100644
--- a/pkg/analyzer_experimental/test/services/formatter_test.dart
+++ b/pkg/analyzer_experimental/test/services/formatter_test.dart
@@ -2,10 +2,12 @@
// 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 'package:unittest/unittest.dart';
+
import 'package:analyzer_experimental/src/generated/ast.dart';
+import 'package:analyzer_experimental/src/generated/scanner.dart';
import 'package:analyzer_experimental/src/services/formatter.dart';
import 'package:analyzer_experimental/src/services/formatter_impl.dart';
-import 'package:unittest/unittest.dart';
main() {
@@ -18,35 +20,196 @@
expect(newRecorder(' foo').countWhitespace(), equals(2));
});
- test('indent', (){
- var recorder = newRecorder('');
- expect(recorder.indentationLevel, equals(0));
- expect(recorder.options.indentPerLevel, equals(2));
- recorder.indent();
- expect(recorder.indentationLevel, equals(2));
- expect(recorder.numberOfIndentations, equals(1));
- });
-
test('isNewlineAt', (){
expect(newRecorder('012\n').isNewlineAt(3), isTrue);
expect(newRecorder('012\n3456').isNewlineAt(3), isTrue);
expect(newRecorder('\n').isNewlineAt(0), isTrue);
});
+ test('space advances 1', (){
+ var recorder = newRecorder(' foo');
+ var startColumn = recorder.column;
+ recorder.space();
+ expect(recorder.column, equals(startColumn + 1));
+ });
+
+ test('space eats WS (1)', (){
+ var recorder = newRecorder(' class')
+ ..currentToken = new KeywordToken(Keyword.CLASS, 3)
+ ..space()
+ ..advanceToken('class');
+ expect(doFormat(recorder), equals(' class'));
+ });
+
+ test('space eats WS (2)', (){
+ var src = 'class A';
+ var recorder = newRecorder(src);
+ recorder..currentToken = (classKeyword(0)..setNext(identifier('A', 7)))
+ ..advanceToken('class')
+ ..space()
+ ..advanceToken('A');
+
+ expect(doFormat(recorder), equals('class A'));
+ });
+
+ test('advance string token', (){
+ var recorder = newRecorder('class A')..currentToken = classKeyword(0);
+ expect(recorder.column, equals(0));
+ recorder.advanceToken('class');
+ expect(recorder.column, equals(5));
+ });
+
+ test('advance string token (failure)', (){
+ var recorder = newRecorder('class A')..currentToken = classKeyword(0);
+ expect(() => recorder.advanceToken('static'),
+ throwsA(new isInstanceOf<FormatterException>()));
+ });
+
+ test('advance indent', (){
+ var recorder = newRecorder(' class A')..currentToken = classKeyword(0);
+ recorder.advanceIndent();
+ expect(doFormat(recorder), equals('class A'));
+ });
+
+ test('indent string', (){
+ var recorder = newRecorder('');
+ expect(recorder.getIndentString(0).length, equals(0));
+ expect(recorder.getIndentString(5).length, equals(5));
+ expect(recorder.getIndentString(50).length, equals(50));
+ });
+
+
+ test('newline', (){
+ var recorder = newRecorder('class A { }');
+ recorder..currentToken = chain([classKeyword(0),
+ identifier('A', 6),
+ openParen(8),
+ closeParen(10)])
+ ..advanceToken('class')
+ ..space()
+ ..advanceToken('A')
+ ..space()
+ ..advanceToken('{')
+ ..newline();
+
+ expect(doFormat(recorder)[9], equals(NEW_LINE));
+ });
+
+ test('newline eats trailing WS', (){
+ var src = 'class A {';
+ var recorder = newRecorder(src + ' ');
+ recorder..currentToken = chain([classKeyword(0),
+ identifier('A', 6),
+ openParen(8)])
+ ..advanceToken('class')
+ ..space()
+ ..advanceToken('A')
+ ..space()
+ ..advanceToken('{')
+ ..newline();
+
+ expect(doFormat(recorder).length, equals((src + NEW_LINE).length));
+ });
+
+
+ });
+
+
+ /// Edit operations
+ group('edit operations', () {
+
+ test('replace same length', () {
+ var edits = [new Edit(1, 2, 'oo'),
+ new Edit(4, 5, 'bar')];
+ expect(new EditOperation().apply(edits, 'fun house'), equals('foo bar'));
+ });
+
+ test('replace shorten', () {
+ var edits = [new Edit(0, 2, 'a'),
+ new Edit(2, 2, 'b'),
+ new Edit(4, 2, 'c')];
+ expect(new EditOperation().apply(edits, 'AaBbCc'), equals('abc'));
+ });
+
+
});
/// Formatter tests
group('formatter', () {
- test('failedParse', () {
+ test('failed parse', () {
var formatter = new CodeFormatter();
- expect(() => formatter.format(CodeKind.COMPILATION_UNIT, "~"),
- throwsA(new isInstanceOf<FormatterException>('FE')));
+ expect(() => formatter.format(CodeKind.COMPILATION_UNIT, '~'),
+ throwsA(new isInstanceOf<FormatterException>()));
});
+ test('CU (1)', () {
+ expectCUFormatsTo(
+ 'class A {\n'
+ '}',
+ 'class A {\n'
+ '}'
+ );
+ });
+
+ test('CU (2)', () {
+ expectCUFormatsTo(
+ 'class A { \n'
+ '}',
+ 'class A {\n'
+ '}'
+ );
+ });
+
+ test('CU (3)', () {
+ expectCUFormatsTo(
+ 'class A {\n'
+ ' }',
+ 'class A {\n'
+ '}'
+ );
+ });
+
+ test('CU (4)', () {
+ expectCUFormatsTo(
+ ' class A {\n'
+ '}',
+ 'class A {\n'
+ '}'
+ );
+ });
+
+ test('CU (method indent)', () {
+ expectCUFormatsTo(
+ 'class A {\n'
+ 'void x(){\n'
+ '}\n'
+ '}',
+ 'class A {\n'
+ ' void x() {\n'
+ ' }\n'
+ '}'
+ );
+ });
+
+ test('CU (method indent - 2)', () {
+ expectCUFormatsTo(
+ 'class A {\n'
+ ' static void x(){}\n'
+ ' }',
+ 'class A {\n'
+ ' static void x() {\n'
+ ' }\n'
+ '}'
+ );
+ });
+
+
+
// test('initialIndent', () {
-// var formatter = new CodeFormatter(new Options(initialIndentationLevel:2));
+// var formatter = new CodeFormatter(
+// new FormatterOptions(initialIndentationLevel:2));
// var formattedSource = formatter.format(CodeKind.STATEMENT, 'var x;');
// expect(formattedSource, startsWith(' '));
// });
@@ -55,8 +218,32 @@
}
-EditRecorder newRecorder(String source) {
- var recorder = new EditRecorder(new FormatterOptions());
- recorder.source = source;
- return recorder;
+Token classKeyword(int offset) =>
+ new KeywordToken(Keyword.CLASS, offset);
+
+Token identifier(String value, int offset) =>
+ new StringToken(TokenType.IDENTIFIER, value, offset);
+
+Token openParen(int offset) =>
+ new StringToken(TokenType.OPEN_PAREN, '{', offset);
+
+Token closeParen(int offset) =>
+ new StringToken(TokenType.CLOSE_PAREN, '}', offset);
+
+Token chain(List<Token> tokens) {
+ for (var i = 0; i < tokens.length - 1; ++i) {
+ tokens[i].setNext(tokens[i + 1]);
+ }
+ return tokens[0];
}
+
+EditRecorder newRecorder(source) =>
+ new EditRecorder(new FormatterOptions())..source = source;
+
+String doFormat(recorder) =>
+ new EditOperation().apply(recorder.editStore.edits, recorder.source);
+
+String formatCU(src, {options: const FormatterOptions()}) =>
+ new CodeFormatter(options).format(CodeKind.COMPILATION_UNIT, src);
+
+expectCUFormatsTo(src, expected) => expect(formatCU(src), equals(expected));
diff --git a/pkg/analyzer_experimental/test/services/test_utils.dart b/pkg/analyzer_experimental/test/services/test_utils.dart
index 2128aaa..e8757a4 100644
--- a/pkg/analyzer_experimental/test/services/test_utils.dart
+++ b/pkg/analyzer_experimental/test/services/test_utils.dart
@@ -178,7 +178,7 @@
bool exists() => true;
- bool isInSystemLibrary() => _unsupported();
+ bool get isInSystemLibrary => _unsupported();
Source resolve(String uri) => _unsupported();
diff --git a/pkg/args/lib/args.dart b/pkg/args/lib/args.dart
index 3898b9f..668577c 100644
--- a/pkg/args/lib/args.dart
+++ b/pkg/args/lib/args.dart
@@ -257,6 +257,8 @@
import 'src/parser.dart';
import 'src/usage.dart';
+import 'src/options.dart';
+export 'src/options.dart';
/**
* A class for taking a list of raw command line arguments and parsing out
@@ -345,9 +347,20 @@
/**
* Parses [args], a list of command-line arguments, matches them against the
* flags and options defined by this parser, and returns the result.
+ *
+ * If [allowTrailingOptions] is set, the parser will continue parsing even
+ * after it finds an argument that is neither an option nor a command.
+ * This allows options to be specified after regular arguments.
+ *
+ * [allowTrailingOptions] is false by default, so when a non-option,
+ * non-command argument is encountered, it and all remaining arguments,
+ * even those that look like options are passed to the innermost command.
*/
- ArgResults parse(List<String> args) =>
- new Parser(null, this, args.toList()).parse();
+ ArgResults parse(List<String> args, {bool allowTrailingOptions}) {
+ if (allowTrailingOptions == null) allowTrailingOptions = false;
+ return new Parser(null, this, args.toList(), null, null,
+ allowTrailingOptions: allowTrailingOptions).parse();
+ }
/**
* Generates a string displaying usage information for the defined options.
@@ -377,52 +390,6 @@
}
/**
- * A command-line option. Includes both flags and options which take a value.
- */
-class Option {
- final String name;
- final String abbreviation;
- final List<String> allowed;
- final defaultValue;
- final Function callback;
- final String help;
- final Map<String, String> allowedHelp;
- final bool isFlag;
- final bool negatable;
- final bool allowMultiple;
-
- Option(this.name, this.abbreviation, this.help, this.allowed,
- this.allowedHelp, this.defaultValue, this.callback, {this.isFlag,
- this.negatable, this.allowMultiple: false}) {
-
- if (name.isEmpty) {
- throw new ArgumentError('Name cannot be empty.');
- } else if (name.startsWith('-')) {
- throw new ArgumentError('Name $name cannot start with "-".');
- }
-
- // Ensure name does not contain any invalid characters.
- if (_invalidChars.hasMatch(name)) {
- throw new ArgumentError('Name "$name" contains invalid characters.');
- }
-
- if (abbreviation != null) {
- if (abbreviation.length != 1) {
- throw new ArgumentError('Abbreviation must be null or have length 1.');
- } else if(abbreviation == '-') {
- throw new ArgumentError('Abbreviation cannot be "-".');
- }
-
- if (_invalidChars.hasMatch(abbreviation)) {
- throw new ArgumentError('Abbreviation is an invalid character.');
- }
- }
- }
-
- static final _invalidChars = new RegExp(r'''[ \t\r\n"'\\/]''');
-}
-
-/**
* The results of parsing a series of command line arguments using
* [ArgParser.parse()]. Includes the parsed options and any remaining unparsed
* command line arguments.
diff --git a/pkg/args/lib/src/parser.dart b/pkg/args/lib/src/parser.dart
index d35f9ea..37a8e41 100644
--- a/pkg/args/lib/src/parser.dart
+++ b/pkg/args/lib/src/parser.dart
@@ -28,16 +28,26 @@
*/
final Parser parent;
+ /** If `true`, parsing will continue after a non-option argument. */
+ final bool allowTrailingOptions;
+
/** The grammar being parsed. */
final ArgParser grammar;
/** The arguments being parsed. */
final List<String> args;
+ /** The remaining non-option, non-command arguments. */
+ final rest = <String>[];
+
/** The accumulated parsed options. */
final Map results = {};
- Parser(this.commandName, this.grammar, this.args, [this.parent]);
+ Parser(this.commandName, this.grammar, this.args, this.parent, rest,
+ {this.allowTrailingOptions: false}) {
+ if (rest != null) this.rest.addAll(rest);
+ }
+
/** The current argument being parsed. */
String get current => args[0];
@@ -67,10 +77,15 @@
// options so that commands can have option-like names.
var command = grammar.commands[current];
if (command != null) {
+ validate(rest.isEmpty, 'Cannot specify arguments before a command.');
var commandName = args.removeAt(0);
- var commandParser = new Parser(commandName, command, args, this);
+ var commandParser = new Parser(commandName, command, args, this, rest,
+ allowTrailingOptions: allowTrailingOptions);
commandResults = commandParser.parse();
- continue;
+
+ // All remaining arguments were passed to command so clear them here.
+ rest.clear();
+ break;
}
// Try to parse the current argument as an option. Note that the order
@@ -79,8 +94,10 @@
if (parseAbbreviation(this)) continue;
if (parseLongOption()) continue;
- // If we got here, the argument doesn't look like an option, so stop.
- break;
+ // This argument is neither option nor command, so stop parsing unless
+ // the [allowTrailingOptions] option is set.
+ if (!allowTrailingOptions) break;
+ rest.add(args.removeAt(0));
}
// Set unspecified multivalued arguments to their default value,
@@ -95,7 +112,7 @@
});
// Add in the leftover arguments we didn't parse to the innermost command.
- var rest = args.toList();
+ rest.addAll(args);
args.clear();
return new ArgResults(results, commandName, commandResults, rest);
}
diff --git a/pkg/args/test/parse_all_test.dart b/pkg/args/test/parse_all_test.dart
index a921046..8498ae6 100644
--- a/pkg/args/test/parse_all_test.dart
+++ b/pkg/args/test/parse_all_test.dart
@@ -8,55 +8,56 @@
import 'package:args/args.dart';
main() {
- group('ArgParser.parse() starting with a non-option', () {
+ group('ArgParser.parse(allowTrailingOptions: true) '
+ 'starting with a non-option', () {
test('followed by flag', () {
var parser = new ArgParser()..addFlag('flag');
var args = ['A', '--flag'];
- var results = parser.parse(args);
- expect(results['flag'], isFalse);
- expect(results.rest, orderedEquals(args));
+ var resultsAll = parser.parse(args, allowTrailingOptions: true);
+ expect(resultsAll['flag'], isTrue);
+ expect(resultsAll.rest, equals(['A']));
});
test('followed by option', () {
var parser = new ArgParser()..addOption('opt');
var args = ['A', '--opt'];
- var results = parser.parse(args);
- expect(results['opt'], isNull);
- expect(results.rest, orderedEquals(args));
+ expectThrows(parser, args);
});
test('followed by option and value', () {
var parser = new ArgParser()..addOption('opt');
var args = ['A', '--opt', 'V'];
- var results = parser.parse(args);
- expect(results['opt'], isNull);
- expect(results.rest, orderedEquals(args));
+ var resultsAll = parser.parse(args, allowTrailingOptions: true);
+ expect(resultsAll['opt'], equals('V'));
+ expect(resultsAll.rest, equals(['A']));
});
test('followed by unknown flag', () {
var parser = new ArgParser();
var args = ['A', '--xflag'];
- var results = parser.parse(args);
- expect(results.rest, orderedEquals(args));
+
+ expectThrows(parser, args);
});
test('followed by unknown option and value', () {
var parser = new ArgParser();
var args = ['A', '--xopt', 'V'];
- var results = parser.parse(args);
- expect(results.rest, orderedEquals(args));
+
+ expectThrows(parser, args);
});
test('followed by command', () {
var parser = new ArgParser()..addCommand('com');
var args = ['A', 'com'];
- var results = parser.parse(args);
- expect(results.command, isNull);
- expect(results.rest, orderedEquals(args));
+ expectThrows(parser, args);
});
});
}
+expectThrows(ArgParser parser, List<String> args) =>
+ expect(() => parser.parse(args, allowTrailingOptions: true),
+ throwsFormatException,
+ reason: "with allowTrailingOptions: true");
diff --git a/pkg/barback/lib/barback.dart b/pkg/barback/lib/barback.dart
new file mode 100644
index 0000000..8c3928e
--- /dev/null
+++ b/pkg/barback/lib/barback.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback;
+
+export 'src/asset.dart';
+export 'src/asset_id.dart';
+export 'src/asset_provider.dart';
+export 'src/errors.dart';
+export 'src/transform.dart' show Transform;
+export 'src/transformer.dart';
\ No newline at end of file
diff --git a/pkg/barback/lib/src/asset.dart b/pkg/barback/lib/src/asset.dart
new file mode 100644
index 0000000..2de733f
--- /dev/null
+++ b/pkg/barback/lib/src/asset.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.asset;
+
+import 'dart:async';
+import 'dart:io';
+
+/// A blob of content.
+///
+/// Assets may come from the file system, or as the output of a [Transformer].
+/// They are identified by [AssetId].
+abstract class Asset {
+ factory Asset.fromFile(File file) {
+ return new _FileAsset(file);
+ }
+
+ factory Asset.fromString(String content) {
+ return new _StringAsset(content);
+ }
+
+ factory Asset.fromPath(String path) {
+ return new _FileAsset(new File(path));
+ }
+
+ // TODO(rnystrom): This prevents users from defining their own
+ // implementations of Asset. Use serialization package instead.
+ factory Asset.deserialize(data) {
+ // TODO(rnystrom): Handle errors.
+ switch (data[0]) {
+ case "file": return new _FileAsset(new File(data[1])); break;
+ case "string": return new _StringAsset(data[1]); break;
+ }
+ }
+
+ /// Returns the contents of the asset as a string.
+ // TODO(rnystrom): Figure out how binary assets should be handled.
+ String readAsString();
+
+ /// Streams the contents of the asset.
+ Stream<List<int>> read();
+
+ /// Serializes this [Asset] to an object that can be sent across isolates
+ /// and passed to [deserialize].
+ Object serialize();
+}
+
+/// An asset backed by a file on the local file system.
+class _FileAsset implements Asset {
+ final File _file;
+ _FileAsset(this._file);
+
+ String readAsString() => _file.readAsStringSync();
+ Stream<List<int>> read() => _file.openRead();
+
+ String toString() => 'File "${_file.path}"';
+
+ Object serialize() => ["file", _file.path];
+}
+
+/// An asset whose data is stored in a string.
+// TODO(rnystrom): Have something similar for in-memory binary assets.
+class _StringAsset implements Asset {
+ final String _contents;
+
+ _StringAsset(this._contents);
+
+ String readAsString() => _contents;
+
+ // TODO(rnystrom): Implement this and handle encoding.
+ Stream<List<int>> read() => throw new UnimplementedError();
+
+ String toString() {
+ // Don't show the whole string if it's long.
+ var contents = _contents;
+ if (contents.length > 40) {
+ contents = contents.substring(0, 20) + " ... " +
+ contents.substring(contents.length - 20);
+ }
+
+ contents = _escape(contents);
+ return 'String "$contents"';
+ }
+
+ Object serialize() => ["string", _contents];
+
+ String _escape(String string) {
+ return string
+ .replaceAll("\"", r'\"')
+ .replaceAll("\n", r"\n")
+ .replaceAll("\r", r"\r")
+ .replaceAll("\t", r"\t");
+ }
+}
diff --git a/pkg/barback/lib/src/asset_graph.dart b/pkg/barback/lib/src/asset_graph.dart
new file mode 100644
index 0000000..a73b674
--- /dev/null
+++ b/pkg/barback/lib/src/asset_graph.dart
@@ -0,0 +1,225 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.asset_graph;
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'asset.dart';
+import 'asset_id.dart';
+import 'asset_provider.dart';
+import 'errors.dart';
+import 'change_batch.dart';
+import 'phase.dart';
+import 'transformer.dart';
+
+/// The main build dependency manager.
+///
+/// For any given input file, it can tell which output files are affected by
+/// it, and vice versa.
+class AssetGraph {
+ final AssetProvider _provider;
+
+ final _phases = <Phase>[];
+
+ Stream<ProcessResult> get results => _resultsController.stream;
+ final _resultsController = new StreamController<ProcessResult>.broadcast();
+
+ /// A future that completes when the currently running build process finishes.
+ ///
+ /// If no build it in progress, is `null`.
+ Future _processDone;
+
+ ChangeBatch _sourceChanges;
+
+ /// Creates a new [AssetGraph].
+ ///
+ /// It loads source assets using [provider] and then uses [transformerPhases]
+ /// to generate output files from them.
+ //TODO(rnystrom): Better way of specifying transformers and their ordering.
+ AssetGraph(this._provider,
+ Iterable<Iterable<Transformer>> transformerPhases) {
+ // Flatten the phases to a list so we can traverse backwards to wire up
+ // each phase to its next.
+ transformerPhases = transformerPhases.toList();
+
+ // Each phase writes its outputs as inputs to the next phase after it.
+ // Add a phase at the end for the final outputs of the last phase.
+ transformerPhases.add([]);
+
+ Phase nextPhase = null;
+ for (var transformers in transformerPhases.reversed) {
+ nextPhase = new Phase(this, _phases.length, transformers.toList(),
+ nextPhase);
+ _phases.insert(0, nextPhase);
+ }
+ }
+
+ /// Gets the asset identified by [id].
+ ///
+ /// If [id] is for a generated or transformed asset, this will wait until
+ /// it has been created and return it. If the asset cannot be found, throws
+ /// [AssetNotFoundException].
+ Future<Asset> getAssetById(AssetId id) {
+ // TODO(rnystrom): Waiting for the entire build to complete is unnecessary
+ // in some cases. Should optimize:
+ // * [id] may be generated before the compilation is finished. We should
+ // be able to quickly check whether there are any more in-place
+ // transformations that can be run on it. If not, we can return it early.
+ // * If everything is compiled, something that didn't output [id] is
+ // dirtied, and then [id] is requested, we can return it immediately,
+ // since anything overwriting it at that point is an error.
+ // * If [id] has never been generated and all active transformers provide
+ // metadata about the file names of assets it can emit, we can prove that
+ // none of them can emit [id] and fail early.
+ return _waitForProcess().then((_) {
+ // Each phase's inputs are the outputs of the previous phase. Find the
+ // last phase that contains the asset. Since the last phase has no
+ // transformers, this will find the latest output for that id.
+
+ // TODO(rnystrom): Currently does not omit assets that are actually used
+ // as inputs for transformers. This means you can request and get an
+ // asset that should be "consumed" because it's used to generate the
+ // real asset you care about. Need to figure out how we want to handle
+ // that and what use cases there are related to it.
+ for (var i = _phases.length - 1; i >= 0; i--) {
+ var node = _phases[i].inputs[id];
+ if (node != null) {
+ // By the time we get here, the asset should have been built.
+ assert(node.asset != null);
+ return node.asset;
+ }
+ }
+
+ // Couldn't find it.
+ var error = new AssetNotFoundException(id);
+ reportError(error);
+ throw error;
+ });
+ }
+
+ /// Adds [sources] to the graph's known set of source assets.
+ ///
+ /// Begins applying any transforms that can consume any of the sources. If a
+ /// given source is already known, it is considered modified and all
+ /// transforms that use it will be re-applied.
+ void updateSources(Iterable<AssetId> sources) {
+ if (_sourceChanges == null) _sourceChanges = new ChangeBatch();
+ _sourceChanges.update(sources);
+
+ _waitForProcess();
+ }
+
+ /// Removes [removed] from the graph's known set of source assets.
+ void removeSources(Iterable<AssetId> removed) {
+ if (_sourceChanges == null) _sourceChanges = new ChangeBatch();
+ _sourceChanges.remove(removed);
+
+ _waitForProcess();
+ }
+
+ /// Reports a process result with the given error then throws it.
+ void reportError(error) {
+ _resultsController.add(new ProcessResult(error));
+ }
+
+ /// Starts the build process asynchronously if there is work to be done.
+ ///
+ /// Returns a future that completes with the background processing is done.
+ /// If there is no work to do, returns a future that completes immediately.
+ /// All errors that occur during processing will be caught (and routed to the
+ /// [results] stream) before they get to the returned future, so it is safe
+ /// to discard it.
+ Future _waitForProcess() {
+ if (_processDone != null) return _processDone;
+ return _processDone = _process().catchError((error) {
+ // If we get here, it's an unexpected error. Runtime errors like missing
+ // assets should be handled earlier. Errors from transformers or other
+ // external code that barback calls into should be caught at that API
+ // boundary.
+ //
+ // On the off chance we get here, pipe the error to the results stream
+ // as an error. That will let applications handle it without it appearing
+ // in the same path as "normal" errors that get reported.
+ _resultsController.addError(error);
+ }).whenComplete(() {
+ _processDone = null;
+ // Report the build completion.
+ // TODO(rnystrom): Put some useful data in here.
+ _resultsController.add(new ProcessResult());
+ });
+ }
+
+ /// Starts the background processing.
+ ///
+ /// Returns a future that completes when all assets have been processed.
+ Future _process() {
+ return _processSourceChanges().then((_) {
+ // Find the first phase that has work to do and do it.
+ var future;
+ for (var phase in _phases) {
+ future = phase.process();
+ if (future != null) break;
+ }
+
+ // If all phases are done and no new updates have come in, we're done.
+ if (future == null) {
+ // If changes have come in, start over.
+ if (_sourceChanges != null) return _process();
+
+ // Otherwise, everything is done.
+ return;
+ }
+
+ // Process that phase and then loop onto the next.
+ return future.then((_) => _process());
+ });
+ }
+
+ /// Processes the current batch of changes to source assets.
+ Future _processSourceChanges() {
+ // Always pump the event loop. This ensures a bunch of synchronous source
+ // changes are processed in a single batch even when the first one starts
+ // the build process.
+ return new Future(() {
+ if (_sourceChanges == null) return null;
+
+ // Take the current batch to ensure it doesn't get added to while we're
+ // processing it.
+ var changes = _sourceChanges;
+ _sourceChanges = null;
+
+ var updated = new Map<AssetId, Asset>();
+ var futures = [];
+ for (var id in changes.updated) {
+ // TODO(rnystrom): Catch all errors from provider and route to results.
+ futures.add(_provider.getAsset(id).then((asset) {
+ updated[id] = asset;
+ }).catchError((error) {
+ if (error is AssetNotFoundException) {
+ // Handle missing asset errors like regular missing assets.
+ reportError(error);
+ } else {
+ // It's an unexpected error, so rethrow it.
+ throw error;
+ }
+ }));
+ }
+
+ return Future.wait(futures).then((_) {
+ _phases.first.updateInputs(updated, changes.removed);
+ });
+ });
+ }
+}
+
+/// Used to report build results back from the asynchronous build process
+/// running in the background.
+class ProcessResult {
+ /// The error that occurred, or `null` if the result is not an error.
+ final error;
+
+ ProcessResult([this.error]);
+}
diff --git a/pkg/barback/lib/src/asset_id.dart b/pkg/barback/lib/src/asset_id.dart
new file mode 100644
index 0000000..f9e325c
--- /dev/null
+++ b/pkg/barback/lib/src/asset_id.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.asset_id;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:pathos/path.dart' as pathos;
+
+/// AssetIDs always use POSIX style paths regardless of the host platform.
+final _posix = new pathos.Builder(style: pathos.Style.posix);
+
+/// Identifies an asset within a package.
+class AssetId {
+ /// The name of the package containing this asset.
+ final String package;
+
+ /// The path to the asset relative to the root directory of [package].
+ ///
+ /// Source (i.e. read from disk) and generated (i.e. the output of a
+ /// [Transformer]) assets all have paths. Even intermediate assets that are
+ /// generated and then consumed by later transformations will still have
+ /// a path used to identify it.
+ ///
+ /// Asset paths always use forward slashes as path separators, regardless of
+ /// the host platform.
+ final String path;
+
+ /// Gets the file extension of the asset, if it has one, including the ".".
+ String get extension => pathos.extension(path);
+
+ /// Creates a new AssetId at [path] within [package].
+ AssetId(this.package, String path)
+ : path = _posix.normalize(path);
+
+ /// Parses an [AssetId] string of the form "package|path/to/asset.txt".
+ factory AssetId.parse(String description) {
+ var parts = description.split("|");
+ if (parts.length != 2) {
+ throw new FormatException('Could not parse "$description".');
+ }
+
+ if (parts[0].isEmpty) {
+ throw new FormatException(
+ 'Cannot have empty package name in "$description".');
+ }
+
+ if (parts[1].isEmpty) {
+ throw new FormatException(
+ 'Cannot have empty path in "$description".');
+ }
+
+ return new AssetId(parts[0], parts[1]);
+ }
+
+ /// Deserializes an [AssetId] from [data], which must be the result of
+ /// calling [serialize] on an existing [AssetId].
+ ///
+ /// Note that this is intended for communicating ids across isolates and not
+ /// for persistent storage of asset identifiers. There is no guarantee of
+ /// backwards compatibility in serialization form across versions.
+ AssetId.deserialize(data)
+ : package = data[0],
+ path = data[1];
+
+ /// Returns `true` of [other] is an [AssetId] with the same package and path.
+ operator ==(other) =>
+ other is AssetId &&
+ package == other.package &&
+ path == other.path;
+
+ int get hashCode => package.hashCode ^ path.hashCode;
+
+ /// Returns a new [AssetId] with the same [package] as this one and with the
+ /// [path] extended to include [extension].
+ AssetId addExtension(String extension) =>
+ new AssetId(package, "$path$extension");
+
+ /// Returns a new [AssetId] with the same [package] and [path] as this one
+ /// but with file extension [newExtension].
+ AssetId changeExtension(String newExtension) =>
+ new AssetId(package, pathos.withoutExtension(path) + newExtension);
+
+ String toString() => "$package|$path";
+
+ /// Serializes this [AssetId] to an object that can be sent across isolates
+ /// and passed to [deserialize].
+ serialize() => [package, path];
+}
diff --git a/pkg/barback/lib/src/asset_node.dart b/pkg/barback/lib/src/asset_node.dart
new file mode 100644
index 0000000..6fd86c6
--- /dev/null
+++ b/pkg/barback/lib/src/asset_node.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.asset_node;
+
+import 'dart:async';
+
+import 'asset.dart';
+import 'asset_graph.dart';
+import 'asset_id.dart';
+import 'phase.dart';
+import 'transform_node.dart';
+
+/// Describes an asset and its relationship to the build dependency graph.
+///
+/// Keeps a cache of the last asset that was built for this node (i.e. for this
+/// node's ID and phase) and tracks which transforms depend on it.
+class AssetNode {
+ final AssetId id;
+ Asset asset;
+
+ /// The [TransformNode]s that consume this node's asset as an input.
+ final consumers = new Set<TransformNode>();
+
+ AssetNode(this.id);
+
+ /// Updates this node's generated asset value and marks all transforms that
+ /// use this as dirty.
+ void updateAsset(Asset asset) {
+ this.asset = asset;
+ consumers.forEach((consumer) => consumer.dirty());
+ }
+}
diff --git a/pkg/barback/lib/src/asset_provider.dart b/pkg/barback/lib/src/asset_provider.dart
new file mode 100644
index 0000000..565e5ac
--- /dev/null
+++ b/pkg/barback/lib/src/asset_provider.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.asset_provider;
+
+import 'dart:async';
+
+import 'asset.dart';
+import 'asset_id.dart';
+
+/// API for locating and accessing packages on disk.
+///
+/// Implemented by pub and provided to barback so that it isn't coupled
+/// directly to pub.
+abstract class AssetProvider {
+ /// The names of all packages that can be provided by this provider.
+ ///
+ /// This is equal to the transitive closure of the entrypoint package
+ /// dependencies.
+ Iterable<String> get packages;
+
+ // TODO(rnystrom): Make this async.
+ /// The paths of all available asset files in [package], relative to the
+ /// package's root directory.
+ ///
+ /// You can pass [within], which should be the relative path to a directory
+ /// within the package, to only return the files within that subdirectory.
+ List<AssetId> listAssets(String package, {String within});
+
+ Future<Asset> getAsset(AssetId id);
+}
diff --git a/pkg/barback/lib/src/change_batch.dart b/pkg/barback/lib/src/change_batch.dart
new file mode 100644
index 0000000..aa2a1c4
--- /dev/null
+++ b/pkg/barback/lib/src/change_batch.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.change_batch;
+
+import 'asset.dart';
+import 'asset_id.dart';
+
+/// Represents a batch of source asset changes: additions, removals and
+/// modifications.
+class ChangeBatch {
+ /// The assets that have been added or modified in this batch.
+ final updated = new Set<AssetId>();
+
+ /// The assets that have been removed in this batch.
+ final removed = new Set<AssetId>();
+
+ /// Adds the updated [assets] to this batch.
+ void update(Iterable<AssetId> assets) {
+ updated.addAll(assets);
+
+ // If they were previously removed, they are back now.
+ removed.removeAll(assets);
+ }
+
+ /// Removes [assets] from this batch.
+ void remove(Iterable<AssetId> assets) {
+ removed.addAll(assets);
+
+ // If they were previously updated, they are gone now.
+ updated.removeAll(assets);
+ }
+}
diff --git a/pkg/barback/lib/src/errors.dart b/pkg/barback/lib/src/errors.dart
new file mode 100644
index 0000000..65dcad6
--- /dev/null
+++ b/pkg/barback/lib/src/errors.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.errors;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'asset_id.dart';
+
+/// Error thrown when an asset with [id] cannot be found.
+class AssetNotFoundException implements Exception {
+ final AssetId id;
+
+ AssetNotFoundException(this.id);
+
+ String toString() => "Could not find asset $id.";
+}
+
+/// Error thrown when two transformers both output an asset with [id].
+class AssetCollisionException implements Exception {
+ final AssetId id;
+
+ AssetCollisionException(this.id);
+
+ String toString() => "Got collision on asset $id.";
+}
+
+/// Error thrown when a transformer requests an input [id] which cannot be
+/// found.
+class MissingInputException implements Exception {
+ final AssetId id;
+
+ MissingInputException(this.id);
+
+ String toString() => "Missing input $id.";
+}
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
new file mode 100644
index 0000000..d52ed75
--- /dev/null
+++ b/pkg/barback/lib/src/phase.dart
@@ -0,0 +1,184 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.phase;
+
+import 'dart:async';
+
+import 'asset.dart';
+import 'asset_graph.dart';
+import 'asset_id.dart';
+import 'asset_node.dart';
+import 'errors.dart';
+import 'transform_node.dart';
+import 'transformer.dart';
+
+/// One phase in the ordered series of transformations in an [AssetGraph].
+///
+/// Each phase can access outputs from previous phases and can in turn pass
+/// outputs to later phases. Phases are processed strictly serially. All
+/// transforms in a phase will be complete before moving on to the next phase.
+/// Within a single phase, all transforms will be run in parallel.
+///
+/// Building can be interrupted between phases. For example, a source is added
+/// which starts the background process. Sometime during, say, phase 2 (which
+/// is running asynchronously) that source is modified. When the process queue
+/// goes to advance to phase 3, it will see that modification and start the
+/// waterfall from the beginning again.
+class Phase {
+ /// The graph that owns this phase.
+ final AssetGraph graph;
+
+ /// This phase's position relative to the other phases. Zero-based.
+ final int _index;
+
+ /// The transformers that can access [inputs].
+ ///
+ /// Their outputs will be available to the next phase.
+ final List<Transformer> _transformers;
+
+ /// The inputs that are available for transforms in this phase to consume.
+ ///
+ /// For the first phase, these will be the source assets. For all other
+ /// phases, they will be the outputs from the previous phase.
+ final inputs = new Map<AssetId, AssetNode>();
+
+ /// The transforms currently applicable to assets in [inputs].
+ ///
+ /// These are the transforms that have been "wired up": they represent a
+ /// repeatable transformation of a single concrete set of inputs. "dart2js"
+ /// is a transformer. "dart2js on web/main.dart" is a transform.
+ final _transforms = new Set<TransformNode>();
+
+ /// The nodes that are new in this phase since the last time [process] was
+ /// called.
+ ///
+ /// When we process, we'll check these to see if we can hang new transforms
+ /// off them.
+ final _newInputs = new Set<AssetNode>();
+
+ /// The phase after this one.
+ ///
+ /// Outputs from this phase will be passed to it.
+ final Phase _next;
+
+ Phase(this.graph, this._index, this._transformers, this._next);
+
+ /// Updates the phase's inputs with [updated] and removes [removed].
+ ///
+ /// This marks any affected [transforms] as dirty or discards them if their
+ /// inputs are removed.
+ void updateInputs(Map<AssetId, Asset> updated, Set<AssetId> removed) {
+ // Remove any nodes that are no longer being output. Handle removals first
+ // in case there are assets that were removed by one transform but updated
+ // by another. In that case, the update should win.
+ for (var id in removed) {
+ var node = inputs.remove(id);
+
+ // Every transform that was using it is dirty now.
+ if (node != null) {
+ node.consumers.forEach((consumer) => consumer.dirty());
+ }
+ }
+
+ // Update and new or modified assets.
+ updated.forEach((id, asset) {
+ var node = inputs.putIfAbsent(id, () => new AssetNode(id));
+
+ // If it's a new node, remember that so we can see if any new transforms
+ // will consume it.
+ if (node.asset == null) _newInputs.add(node);
+
+ node.updateAsset(asset);
+ });
+ }
+
+ /// Processes this phase.
+ ///
+ /// For all new inputs, it tries to see if there are transformers that can
+ /// consume them. Then all applicable transforms are applied.
+ ///
+ /// Returns a future that completes when processing is done. If there is
+ /// nothing to process, returns `null`.
+ Future process() {
+ var future = _processNewInputs();
+ if (future == null) {
+ return _processTransforms();
+ }
+
+ return future.then((_) => _processTransforms());
+ }
+
+ /// Creates new transforms for any new inputs that are applicable.
+ Future _processNewInputs() {
+ if (_newInputs.isEmpty) return null;
+
+ var futures = [];
+ for (var node in _newInputs) {
+ for (var transformer in _transformers) {
+ // TODO(rnystrom): Catch all errors from isPrimary() and redirect
+ // to results.
+ futures.add(transformer.isPrimary(node.id).then((isPrimary) {
+ if (!isPrimary) return;
+ var transform = new TransformNode(this, transformer, node);
+ node.consumers.add(transform);
+ _transforms.add(transform);
+ }));
+ }
+ }
+
+ _newInputs.clear();
+
+ return Future.wait(futures);
+ }
+
+ /// Applies all currently wired up and dirty transforms.
+ ///
+ /// Passes their outputs to the next phase.
+ Future _processTransforms() {
+ var dirtyTransforms = _transforms.where((transform) => transform.isDirty);
+ if (dirtyTransforms.isEmpty) return null;
+
+ return Future.wait(dirtyTransforms.map((transform) => transform.apply()))
+ .then((transformOutputs) {
+ // Collect all of the outputs. Since the transforms are run in parallel,
+ // we have to be careful here to ensure that the result is deterministic
+ // and not influenced by the order that transforms complete.
+ var updated = new Map<AssetId, Asset>();
+ var removed = new Set<AssetId>();
+ var collisions = new Set<AssetId>();
+
+ // Handle the generated outputs of all transforms first.
+ for (var outputs in transformOutputs) {
+ // Collect the outputs of all transformers together.
+ outputs.updated.forEach((id, asset) {
+ if (updated.containsKey(id)) {
+ // Report a collision.
+ collisions.add(id);
+ } else {
+ // TODO(rnystrom): In the case of a collision, the asset that
+ // "wins" is chosen non-deterministically. Do something better.
+ updated[id] = asset;
+ }
+ });
+
+ // Track any assets no longer output by this transform. We don't
+ // handle the case where *another* transform generates the asset
+ // no longer generated by this one. updateInputs() handles that.
+ removed.addAll(outputs.removed);
+ }
+
+ // Report any collisions in deterministic order.
+ collisions = collisions.toList();
+ collisions.sort((a, b) => a.toString().compareTo(b.toString()));
+ for (var collision in collisions) {
+ graph.reportError(new AssetCollisionException(collision));
+ // TODO(rnystrom): Define what happens after a collision occurs.
+ }
+
+ // Pass the outputs to the next phase.
+ _next.updateInputs(updated, removed);
+ });
+ }
+}
diff --git a/pkg/barback/lib/src/transform.dart b/pkg/barback/lib/src/transform.dart
new file mode 100644
index 0000000..8023d0e
--- /dev/null
+++ b/pkg/barback/lib/src/transform.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.transform;
+
+import 'dart:async';
+
+import 'asset.dart';
+import 'asset_id.dart';
+import 'asset_node.dart';
+import 'errors.dart';
+import 'transform_node.dart';
+
+/// Creates a [Transform] by forwarding to the private constructor.
+///
+/// Lets [TransformNode] create [Transforms] without giving a [Transform]
+/// itself a public constructor, which would be visible to external users.
+/// Unlike the [Transform] class, this function is not exported by barback.dart.
+Transform createTransform(TransformNode node, Set<AssetNode> inputs,
+ Map<AssetId, Asset> outputs) =>
+ new Transform._(node, inputs, outputs);
+
+/// While a [Transformer] represents a *kind* of transformation, this defines
+/// one specific usage of it on a set of files.
+///
+/// This ephemeral object exists only during an actual transform application to
+/// facilitate communication between the [Transformer] and the code hosting
+/// the transformation. It lets the [Transformer] access inputs and generate
+/// outputs.
+class Transform {
+ final TransformNode _node;
+
+ final Set<AssetNode> _inputs;
+ final Map<AssetId, Asset> _outputs;
+
+ /// Gets the ID of the primary input for this transformation.
+ ///
+ /// While a transformation can use multiple input assets, one must be a
+ /// special "primary" asset. This will be the "entrypoint" or "main" input
+ /// file for a transformation.
+ ///
+ /// For example, with a dart2js transform, the primary input would be the
+ /// entrypoint Dart file. All of the other Dart files that that imports
+ /// would be secondary inputs.
+ AssetId get primaryId => _node.primary.id;
+
+ /// Gets the asset for the primary input.
+ Future<Asset> get primaryInput => getInput(primaryId);
+
+ Transform._(this._node, this._inputs, this._outputs);
+
+ /// Gets the asset for for an input [id].
+ ///
+ /// If an input with that ID cannot be found, throws an
+ /// [AssetNotFoundException].
+ Future<Asset> getInput(AssetId id) {
+ return new Future(() {
+ var node = _node.phase.inputs[id];
+ // TODO(rnystrom): Need to handle passthrough where an asset from a
+ // previous phase can be found.
+
+ // Throw if the input isn't found. This ensures the transformer's apply
+ // is exited. We'll then catch this and report it through the proper
+ // results stream.
+ if (node == null) throw new MissingInputException(id);
+
+ // Keep track of which assets this transform depends on.
+ _inputs.add(node);
+ return node.asset;
+ });
+ }
+
+ /// Stores [output] as the output created by this transformation for asset
+ /// [id]. A transformation can output as many assets as it wants.
+ void addOutput(AssetId id, Asset output) {
+ _outputs[id] = output;
+ }
+}
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
new file mode 100644
index 0000000..49222be
--- /dev/null
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.transform_node;
+
+import 'dart:async';
+
+import 'asset.dart';
+import 'asset_graph.dart';
+import 'asset_id.dart';
+import 'asset_node.dart';
+import 'errors.dart';
+import 'phase.dart';
+import 'transform.dart';
+import 'transformer.dart';
+
+/// Describes a transform on a set of assets and its relationship to the build
+/// dependency graph.
+///
+/// Keeps track of whether it's dirty and needs to be run and which assets it
+/// depends on.
+class TransformNode {
+ /// The [Phase] that this transform runs in.
+ final Phase phase;
+
+ /// The [Transformer] to apply to this node's inputs.
+ final Transformer _transformer;
+
+ /// The node for the primary asset this transform depends on.
+ final AssetNode primary;
+
+ /// True if an input has been modified since the last time this transform
+ /// was run.
+ bool get isDirty => _isDirty;
+ var _isDirty = true;
+
+ /// The inputs read by this transform the last time it was run.
+ ///
+ /// Used to tell if an input was removed in a later run.
+ var _inputs = new Set<AssetNode>();
+
+ /// The outputs created by this transform the last time it was run.
+ ///
+ /// Used to tell if an output was removed in a later run.
+ var _outputs = new Set<AssetId>();
+
+ TransformNode(this.phase, this._transformer, this.primary);
+
+ /// Marks this transform as needing to be run.
+ void dirty() {
+ _isDirty = true;
+ }
+
+ /// Applies this transform.
+ ///
+ /// Returns a [TransformOutputs] describing the resulting outputs compared to
+ /// previous runs.
+ Future<TransformOutputs> apply() {
+ var newInputs = new Set<AssetNode>();
+ var newOutputs = new Map<AssetId, Asset>();
+ var transform = createTransform(this, newInputs, newOutputs);
+ return _transformer.apply(transform).catchError((error) {
+ // Catch all transformer errors and pipe them to the results stream.
+ // This is so a broken transformer doesn't take down the whole graph.
+ phase.graph.reportError(error);
+
+ // Don't allow partial results from a failed transform.
+ newOutputs.clear();
+ }).then((_) {
+ _isDirty = false;
+
+ // Stop watching any inputs that were removed.
+ for (var oldInput in _inputs) {
+ oldInput.consumers.remove(this);
+ }
+
+ // Watch any new inputs so this transform will be re-processed when an
+ // input is modified.
+ for (var newInput in newInputs) {
+ newInput.consumers.add(this);
+ }
+
+ _inputs = newInputs;
+
+ // See which outputs are missing from the last run.
+ var outputIds = newOutputs.keys.toSet();
+ var removed = _outputs.difference(outputIds);
+ _outputs = outputIds;
+
+ return new TransformOutputs(newOutputs, removed);
+ });
+ }
+}
+
+/// The result of running a [Transform], compared to the previous time it was
+/// applied.
+class TransformOutputs {
+ /// The outputs that are new or were modified since the last run.
+ final Map<AssetId, Asset> updated;
+
+ /// The outputs that were created by the previous run but were not generated
+ /// by the most recent run.
+ final Set<AssetId> removed;
+
+ TransformOutputs(this.updated, this.removed);
+}
diff --git a/pkg/barback/lib/src/transformer.dart b/pkg/barback/lib/src/transformer.dart
new file mode 100644
index 0000000..664d2e4
--- /dev/null
+++ b/pkg/barback/lib/src/transformer.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.transformer;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'asset_id.dart';
+import 'transform.dart';
+
+/// A [Transformer] represents a processor that takes in one or more input
+/// assets and uses them to generate one or more output assets.
+///
+/// Dart2js, a SASS->CSS processor, a CSS spriter, and a tool to concatenate
+/// files are all examples of transformers. To define your own transformation
+/// step, extend (or implement) this class.
+abstract class Transformer {
+ /// Returns `true` if [input] can be a primary input for this transformer.
+ ///
+ /// While a transformer can read from multiple input files, one must be the
+ /// "primary" input. This asset determines whether the transformation should
+ /// be run at all. If the primary input is removed, the transformer will no
+ /// longer be run.
+ ///
+ /// A concrete example is dart2js. When you run dart2js, it will traverse
+ /// all of the imports in your Dart source files and use the contents of all
+ /// of those to generate the final JS. However you still run dart2js "on" a
+ /// single file: the entrypoint Dart file that has your `main()` method.
+ /// This entrypoint file would be the primary input.
+ Future<bool> isPrimary(AssetId input);
+
+ /// Run this transformer on on the primary input specified by [transform].
+ ///
+ /// The [transform] is used by the [Transformer] for two purposes (in
+ /// addition to accessing the primary input). It can call `getInput()` to
+ /// request additional input assets. It also calls `addOutput()` to provide
+ /// generated assets back to the system. Either can be called multiple times,
+ /// in any order.
+ ///
+ /// In other words, a Transformer's job is to find all inputs for a
+ /// transform, starting at the primary input, then generate all output assets
+ /// and yield them back to the transform.
+ Future apply(Transform transform);
+
+ String toString() => runtimeType.toString().replaceAll("Transformer", "");
+}
diff --git a/pkg/barback/pubspec.yaml b/pkg/barback/pubspec.yaml
new file mode 100644
index 0000000..903fa41
--- /dev/null
+++ b/pkg/barback/pubspec.yaml
@@ -0,0 +1,17 @@
+name: barback
+author: "Dart Team <misc@dartlang.org>"
+homepage: http://www.dartlang.org
+description: >
+ An asset build system.
+
+ Given a set of input files and a set of transformations (think compilers,
+ preprocessors and the like), will automatically apply the appropriate
+ transforms and generate output files. When inputs are modified, automatically
+ runs the transforms that are affected.
+
+ Runs transforms asynchronously and in parallel when possible to maximize
+ responsiveness.
+dependencies:
+ pathos: any
+dev_dependencies:
+ scheduled_test: any
diff --git a/pkg/barback/test/asset_graph/errors_test.dart b/pkg/barback/test/asset_graph/errors_test.dart
new file mode 100644
index 0000000..45a36de
--- /dev/null
+++ b/pkg/barback/test/asset_graph/errors_test.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.test.asset_graph.source_test;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/asset_graph.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../utils.dart';
+
+main() {
+ initConfig();
+
+ test("errors if two transformers output the same file", () {
+ var provider = new MockProvider(["app|foo.a"]);
+ var graph = new AssetGraph(provider, [
+ [
+ new RewriteTransformer("a", "b"),
+ new RewriteTransformer("a", "b")
+ ]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.a")]);
+
+ expectCollision(graph, "app|foo.b");
+ });
+
+ test("reports asset not found errors in results", () {
+ var provider = new MockProvider([]);
+ var graph = new AssetGraph(provider, []);
+
+ // TODO(rnystrom): This is verbose and ugly. Better would be to have
+ // utils.dart register this on the graph and then have functions to expect
+ // certain build results.
+ var numResults = 0;
+ var gotError = false;
+ graph.results.listen(wrapAsync((result) {
+ numResults++;
+ expect(numResults, lessThan(3));
+
+ if (numResults == 1) {
+ // Should complete the build first.
+ expect(result.error, isNull);
+ } else if (numResults == 2) {
+ // Then have the error.
+ expect(result.error, new isInstanceOf<AssetNotFoundException>());
+ expect(result.error.id, equals(new AssetId.parse("app|foo.txt")));
+ gotError = true;
+ }
+ }));
+
+ expectNoAsset(graph, "app|foo.txt");
+
+ schedule(() {
+ expect(gotError, isTrue);
+ });
+ });
+
+ test("reports an error for an unprovided source", () {
+ var provider = new MockProvider([]);
+ var graph = new AssetGraph(provider, []);
+ var resultFuture = graph.results.first;
+
+ graph.updateSources([new AssetId.parse("app|unknown.txt")]);
+
+ schedule(() {
+ return resultFuture.then((result) {
+ expect(result.error, new isInstanceOf<AssetNotFoundException>());
+ expect(result.error.id, equals(new AssetId.parse("app|unknown.txt")));
+ });
+ });
+ });
+
+ test("reports missing input errors in results", () {
+ var provider = new MockProvider({"app|a.txt": "a.inc"});
+
+ var graph = new AssetGraph(provider, [
+ [new ManyToOneTransformer("txt")]
+ ]);
+
+ var gotError = false;
+ graph.results.listen(wrapAsync((result) {
+ expect(result.error is MissingInputException, isTrue);
+ expect(result.error.id, equals(new AssetId.parse("app|a.inc")));
+ gotError = true;
+ }));
+
+ graph.updateSources([new AssetId.parse("app|a.txt")]);
+
+ expectNoAsset(graph, "app|a.out");
+
+ schedule(() {
+ expect(gotError, isTrue);
+ });
+ });
+
+ test("fails if a non-primary input is removed", () {
+ var provider = new MockProvider({
+ "app|a.txt": "a.inc,b.inc,c.inc",
+ "app|a.inc": "a",
+ "app|b.inc": "b",
+ "app|c.inc": "c"
+ });
+
+ var graph = new AssetGraph(provider, [
+ [new ManyToOneTransformer("txt")]
+ ]);
+
+ // TODO(rnystrom): This is verbose and ugly. Better would be to have
+ // utils.dart register this on the graph and then have functions to expect
+ // certain build results.
+ var numResults = 0;
+ var gotError = false;
+ graph.results.listen(wrapAsync((result) {
+ numResults++;
+ expect(numResults, lessThan(3));
+
+ if (numResults == 1) {
+ // Should complete the build first.
+ expect(result.error, isNull);
+ } else if (numResults == 2) {
+ // Then have the error.
+ expect(result.error is MissingInputException, isTrue);
+ expect(result.error.id, equals(new AssetId.parse("app|b.inc")));
+ gotError = true;
+ }
+ }));
+
+ graph.updateSources([
+ new AssetId.parse("app|a.txt"),
+ new AssetId.parse("app|a.inc"),
+ new AssetId.parse("app|b.inc"),
+ new AssetId.parse("app|c.inc")
+ ]);
+
+ expectAsset(graph, "app|a.out", "abc");
+
+ schedule(() {
+ graph.removeSources([new AssetId.parse("app|b.inc")]);
+ });
+
+ expectNoAsset(graph, "app|a.out");
+
+ schedule(() {
+ expect(gotError, isTrue);
+ });
+ });
+
+ test("catches transformer exceptions and reports them", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [
+ [new BadTransformer(["app|foo.out"])]
+ ]);
+
+ var gotError = false;
+ graph.results.listen(wrapAsync((result) {
+ expect(result.error, equals(BadTransformer.ERROR));
+ gotError = true;
+ }));
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectNoAsset(graph, "app|foo.out");
+
+ schedule(() {
+ expect(gotError, isTrue);
+ });
+ });
+
+ // TODO(rnystrom): Is this the behavior we expect? If a transformer fails
+ // to transform a file, should we just skip past it to the source?
+ test("yields a source if a transform fails on it", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [
+ [new BadTransformer(["app|foo.txt"])]
+ ]);
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectAsset(graph, "app|foo.txt");
+ });
+
+ test("catches errors even if nothing is waiting for process results", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [[new BadTransformer([])]]);
+ var resultFuture = graph.results.first;
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ // Note: No asset requests here.
+
+ schedule(() {
+ return resultFuture.then((result) {
+ expect(result.error, equals(BadTransformer.ERROR));
+ });
+ });
+ });
+
+ test("discards outputs from failed transforms", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [
+ [new BadTransformer(["a.out", "b.out"])]
+ ]);
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectNoAsset(graph, "app|a.out");
+ });
+}
diff --git a/pkg/barback/test/asset_graph/source_test.dart b/pkg/barback/test/asset_graph/source_test.dart
new file mode 100644
index 0000000..32d7f3d
--- /dev/null
+++ b/pkg/barback/test/asset_graph/source_test.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.test.asset_graph.source_test;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/asset_graph.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../utils.dart';
+
+main() {
+ initConfig();
+ test("gets a source asset", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, []);
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ expectAsset(graph, "app|foo.txt");
+ });
+
+ test("doesn't get an unknown source", () {
+ var provider = new MockProvider([]);
+ var graph = new AssetGraph(provider, []);
+
+ expectNoAsset(graph, "app|unknown.txt");
+ });
+
+ test("doesn't get an unprovided source", () {
+ var provider = new MockProvider([]);
+ var graph = new AssetGraph(provider, []);
+
+ graph.updateSources([new AssetId.parse("app|unknown.txt")]);
+ expectNoAsset(graph, "app|unknown.txt");
+ });
+
+ test("doesn't get an asset that isn't an updated source", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, []);
+
+ // Sources must be explicitly made visible to barback by calling
+ // updateSources() on them. It isn't enough for the provider to be able
+ // to provide it.
+ //
+ // This lets you distinguish between sources that you want to be primaries
+ // and the larger set of inputs that those primaries are allowed to pull in.
+ expectNoAsset(graph, "app|foo.txt");
+ });
+
+ test("gets a source asset if not transformed", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("nottxt", "whatever")]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ expectAsset(graph, "app|foo.txt");
+ });
+
+ test("doesn't get a removed source", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [[]]);
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ expectAsset(graph, "app|foo.txt");
+
+ schedule(() {
+ graph.removeSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectNoAsset(graph, "app|foo.txt");
+ });
+
+ test("collapses redundant updates", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var transformer = new RewriteTransformer("blub", "blab");
+ var graph = new AssetGraph(provider, [[transformer]]);
+
+ schedule(() {
+ // Make a bunch of synchronous update calls.
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ });
+
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+
+ schedule(() {
+ expect(transformer.numRuns, equals(1));
+ });
+ });
+
+ test("a removal cancels out an update", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [[]]);
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ graph.removeSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectNoAsset(graph, "app|foo.txt");
+ });
+
+ test("an update cancels out a removal", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [[]]);
+
+ schedule(() {
+ graph.removeSources([new AssetId.parse("app|foo.txt")]);
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectAsset(graph, "app|foo.txt");
+ });
+
+ test("restarts a build if a source is updated while sources are loading", () {
+ var provider = new MockProvider(["app|foo.txt", "app|other.bar"]);
+ var transformer = new RewriteTransformer("txt", "out");
+ var graph = new AssetGraph(provider, [[transformer]]);
+
+ var numBuilds = 0;
+ var buildCompleter = new Completer();
+ graph.results.listen(wrapAsync((result) {
+ expect(result.error, isNull);
+ numBuilds++;
+
+ // There should be two builds, one for each update call.
+ if (numBuilds == 2) buildCompleter.complete();
+ }));
+
+ // Run the whole graph so all nodes are clean.
+ graph.updateSources([
+ new AssetId.parse("app|foo.txt"),
+ new AssetId.parse("app|other.bar")
+ ]);
+ expectAsset(graph, "app|foo.out", "foo.out");
+ expectAsset(graph, "app|other.bar");
+
+ schedule(() {
+ // Make the provider slow to load a source.
+ provider.wait();
+
+ // Update an asset that doesn't trigger any transformers.
+ graph.updateSources([new AssetId.parse("app|other.bar")]);
+ });
+
+ schedule(() {
+ // Now update an asset that does trigger a transformer.
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ schedule(() {
+ provider.complete();
+ });
+
+ schedule(() {
+ // Wait until the build has completed.
+ return buildCompleter.future;
+ });
+
+ schedule(() {
+ expect(transformer.numRuns, equals(2));
+ });
+ });
+}
diff --git a/pkg/barback/test/asset_graph/transform_test.dart b/pkg/barback/test/asset_graph/transform_test.dart
new file mode 100644
index 0000000..198f18e
--- /dev/null
+++ b/pkg/barback/test/asset_graph/transform_test.dart
@@ -0,0 +1,406 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.test.asset_graph.transform_test;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/asset_graph.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../utils.dart';
+
+main() {
+ initConfig();
+ test("gets a transformed asset with a different path", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("blub", "blab")]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+ });
+
+ test("gets a transformed asset with the same path", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("blub", "blub")]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+
+ expectAsset(graph, "app|foo.blub", "foo.blub");
+ });
+
+ test("doesn't find an output from a later phase", () {
+ var provider = new MockProvider(["app|foo.a"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("b", "c")],
+ [new RewriteTransformer("a", "b")]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.a")]);
+
+ expectNoAsset(graph, "app|foo.c");
+ });
+
+ test("doesn't find an output from the same phase", () {
+ var provider = new MockProvider(["app|foo.a"]);
+ var graph = new AssetGraph(provider, [
+ [
+ new RewriteTransformer("a", "b"),
+ new RewriteTransformer("b", "c")
+ ]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.a")]);
+
+ expectAsset(graph, "app|foo.b", "foo.b");
+ expectNoAsset(graph, "app|foo.c");
+ });
+
+ test("finds the latest output before the transformer's phase", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("blub", "blub")],
+ [
+ new RewriteTransformer("blub", "blub"),
+ new RewriteTransformer("blub", "done")
+ ],
+ [new RewriteTransformer("blub", "blub")]
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+
+ expectAsset(graph, "app|foo.done", "foo.blub.done");
+ });
+
+ test("applies multiple transformations to an asset", () {
+ var provider = new MockProvider(["app|foo.a"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("a", "b")],
+ [new RewriteTransformer("b", "c")],
+ [new RewriteTransformer("c", "d")],
+ [new RewriteTransformer("d", "e")],
+ [new RewriteTransformer("e", "f")],
+ [new RewriteTransformer("f", "g")],
+ [new RewriteTransformer("g", "h")],
+ [new RewriteTransformer("h", "i")],
+ [new RewriteTransformer("i", "j")],
+ [new RewriteTransformer("j", "k")],
+ ]);
+ graph.updateSources([new AssetId.parse("app|foo.a")]);
+
+ expectAsset(graph, "app|foo.k", "foo.b.c.d.e.f.g.h.i.j.k");
+ });
+
+ test("only runs a transform once for all of its outputs", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var transformer = new RewriteTransformer("blub", "a b c");
+ var graph = new AssetGraph(provider, [[transformer]]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+
+ expectAsset(graph, "app|foo.a", "foo.a");
+ expectAsset(graph, "app|foo.b", "foo.b");
+ expectAsset(graph, "app|foo.c", "foo.c");
+ schedule(() {
+ expect(transformer.numRuns, equals(1));
+ });
+ });
+
+ test("runs transforms in the same phase in parallel", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var transformerA = new RewriteTransformer("txt", "a");
+ var transformerB = new RewriteTransformer("txt", "b");
+ var graph = new AssetGraph(provider, [[transformerA, transformerB]]);
+
+ transformerA.wait();
+ transformerB.wait();
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ // Wait for them both to start.
+ return Future.wait([transformerA.started, transformerB.started]);
+ });
+
+ schedule(() {
+ // They should both still be running.
+ expect(transformerA.isRunning, isTrue);
+ expect(transformerB.isRunning, isTrue);
+
+ transformerA.complete();
+ transformerB.complete();
+ });
+
+ expectAsset(graph, "app|foo.a", "foo.a");
+ expectAsset(graph, "app|foo.b", "foo.b");
+ });
+
+ test("does not reapply transform when inputs are not modified", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var transformer = new RewriteTransformer("blub", "blab");
+ var graph = new AssetGraph(provider, [[transformer]]);
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+
+ schedule(() {
+ expect(transformer.numRuns, equals(1));
+ });
+ });
+
+ test("reapplies a transform when its input is modified", () {
+ var provider = new MockProvider(["app|foo.blub"]);
+ var transformer = new RewriteTransformer("blub", "blab");
+ var graph = new AssetGraph(provider, [[transformer]]);
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ });
+
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ });
+
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.blub")]);
+ });
+
+ expectAsset(graph, "app|foo.blab", "foo.blab");
+
+ schedule(() {
+ expect(transformer.numRuns, equals(3));
+ });
+ });
+
+ test("does not reapply transform when a removed input is modified", () {
+ var provider = new MockProvider({
+ "app|a.txt": "a.inc,b.inc",
+ "app|a.inc": "a",
+ "app|b.inc": "b"
+ });
+
+ var transformer = new ManyToOneTransformer("txt");
+ var graph = new AssetGraph(provider, [[transformer]]);
+
+ graph.updateSources([
+ new AssetId.parse("app|a.txt"),
+ new AssetId.parse("app|a.inc"),
+ new AssetId.parse("app|b.inc")
+ ]);
+
+ expectAsset(graph, "app|a.out", "ab");
+
+ // Remove the dependency on the non-primary input.
+ schedule(() {
+ provider.modifyAsset("app|a.txt", "a.inc");
+ graph.updateSources([new AssetId.parse("app|a.txt")]);
+ });
+
+ // Process it again.
+ expectAsset(graph, "app|a.out", "a");
+
+ // Now touch the removed input. It should not trigger another build.
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|b.inc")]);
+ });
+
+ expectAsset(graph, "app|a.out", "a");
+
+ schedule(() {
+ expect(transformer.numRuns, equals(2));
+ });
+ });
+
+ test("allows a transform to generate multiple outputs", () {
+ var provider = new MockProvider({"app|foo.txt": "a.out,b.out"});
+ var graph = new AssetGraph(provider, [
+ [new OneToManyTransformer("txt")]
+ ]);
+
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ expectAsset(graph, "app|a.out", "spread txt");
+ expectAsset(graph, "app|b.out", "spread txt");
+ });
+
+ test("does not rebuild transforms that don't use modified source", () {
+ var provider = new MockProvider(["app|foo.a", "app|foo.b"]);
+ var a = new RewriteTransformer("a", "aa");
+ var aa = new RewriteTransformer("aa", "aaa");
+ var b = new RewriteTransformer("b", "bb");
+ var bb = new RewriteTransformer("bb", "bbb");
+
+ var graph = new AssetGraph(provider, [
+ [a, b],
+ [aa, bb],
+ ]);
+
+ graph.updateSources([new AssetId.parse("app|foo.a")]);
+ graph.updateSources([new AssetId.parse("app|foo.b")]);
+
+ expectAsset(graph, "app|foo.aaa", "foo.aa.aaa");
+ expectAsset(graph, "app|foo.bbb", "foo.bb.bbb");
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.a")]);
+ });
+
+ expectAsset(graph, "app|foo.aaa", "foo.aa.aaa");
+ expectAsset(graph, "app|foo.bbb", "foo.bb.bbb");
+
+ schedule(() {
+ expect(aa.numRuns, equals(2));
+ expect(bb.numRuns, equals(1));
+ });
+ });
+
+ test("doesn't get an output from a transform whose primary input is removed",
+ () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var graph = new AssetGraph(provider, [
+ [new RewriteTransformer("txt", "out")]
+ ]);
+
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ expectAsset(graph, "app|foo.out", "foo.out");
+
+ schedule(() {
+ graph.removeSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ expectNoAsset(graph, "app|foo.out");
+ });
+
+ test("reapplies a transform when a non-primary input changes", () {
+ var provider = new MockProvider({
+ "app|a.txt": "a.inc",
+ "app|a.inc": "a"
+ });
+
+ var graph = new AssetGraph(provider, [
+ [new ManyToOneTransformer("txt")]
+ ]);
+
+ graph.updateSources([
+ new AssetId.parse("app|a.txt"),
+ new AssetId.parse("app|a.inc")
+ ]);
+
+ expectAsset(graph, "app|a.out", "a");
+
+ schedule(() {
+ provider.modifyAsset("app|a.inc", "after");
+ graph.updateSources([new AssetId.parse("app|a.inc")]);
+ });
+
+ expectAsset(graph, "app|a.out", "after");
+ });
+
+ test("restarts processing if a change occurs during processing", () {
+ var provider = new MockProvider(["app|foo.txt"]);
+ var transformer = new RewriteTransformer("txt", "out");
+ var graph = new AssetGraph(provider, [[transformer]]);
+
+ transformer.wait();
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ // Wait for the transform to start.
+ return transformer.started;
+ });
+
+ schedule(() {
+ // Now update the graph during it.
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+ });
+
+ schedule(() {
+ transformer.complete();
+ });
+
+ expectAsset(graph, "app|foo.out", "foo.out");
+
+ schedule(() {
+ expect(transformer.numRuns, equals(2));
+ });
+ });
+
+ test("handles an output moving from one transformer to another", () {
+ // In the first run, "shared.out" is created by the "a.a" transformer.
+ var provider = new MockProvider({
+ "app|a.a": "a.out,shared.out",
+ "app|b.b": "b.out"
+ });
+
+ var graph = new AssetGraph(provider, [
+ [new OneToManyTransformer("a"), new OneToManyTransformer("b")]
+ ]);
+
+ graph.updateSources([
+ new AssetId.parse("app|a.a"),
+ new AssetId.parse("app|b.b")
+ ]);
+
+ expectAsset(graph, "app|a.out", "spread a");
+ expectAsset(graph, "app|b.out", "spread b");
+ expectAsset(graph, "app|shared.out", "spread a");
+
+ // Now switch their contents so that "shared.out" will be output by "b.b"'s
+ // transformer.
+ schedule(() {
+ provider.modifyAsset("app|a.a", "a.out");
+ provider.modifyAsset("app|b.b", "b.out,shared.out");
+ graph.updateSources([
+ new AssetId.parse("app|a.a"),
+ new AssetId.parse("app|b.b")
+ ]);
+ });
+
+ expectAsset(graph, "app|a.out", "spread a");
+ expectAsset(graph, "app|b.out", "spread b");
+ expectAsset(graph, "app|shared.out", "spread b");
+ });
+
+ test("restarts before finishing later phases when a change occurs", () {
+ var provider = new MockProvider(["app|foo.txt", "app|bar.txt"]);
+
+ var txtToInt = new RewriteTransformer("txt", "int");
+ var intToOut = new RewriteTransformer("int", "out");
+ var graph = new AssetGraph(provider, [[txtToInt], [intToOut]]);
+
+ txtToInt.wait();
+
+ schedule(() {
+ graph.updateSources([new AssetId.parse("app|foo.txt")]);
+
+ // Wait for the first transform to start.
+ return txtToInt.started;
+ });
+
+ schedule(() {
+ // Now update the graph during it.
+ graph.updateSources([new AssetId.parse("app|bar.txt")]);
+ });
+
+ schedule(() {
+ txtToInt.complete();
+ });
+
+ expectAsset(graph, "app|foo.out", "foo.int.out");
+ expectAsset(graph, "app|bar.out", "bar.int.out");
+
+ schedule(() {
+ // Should only have run each transform once for each primary.
+ expect(txtToInt.numRuns, equals(2));
+ expect(intToOut.numRuns, equals(2));
+ });
+ });
+}
diff --git a/pkg/barback/test/asset_id_test.dart b/pkg/barback/test/asset_id_test.dart
new file mode 100644
index 0000000..6834039
--- /dev/null
+++ b/pkg/barback/test/asset_id_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.test.asset_id_test;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:unittest/unittest.dart';
+
+import 'utils.dart';
+
+main() {
+ initConfig();
+ group("parse", () {
+ test("parses the package and path", () {
+ var id = new AssetId.parse("package|path/to/asset.txt");
+ expect(id.package, equals("package"));
+ expect(id.path, equals("path/to/asset.txt"));
+ });
+
+ test("throws if there are multiple '|'", () {
+ expect(() => new AssetId.parse("app|path|wtf"), throwsFormatException);
+ });
+
+ test("throws if the package name is empty '|'", () {
+ expect(() => new AssetId.parse("|asset.txt"), throwsFormatException);
+ });
+
+ test("throws if the path is empty '|'", () {
+ expect(() => new AssetId.parse("app|"), throwsFormatException);
+ });
+ });
+}
diff --git a/pkg/barback/test/utils.dart b/pkg/barback/test/utils.dart
new file mode 100644
index 0000000..23f8e2a
--- /dev/null
+++ b/pkg/barback/test/utils.dart
@@ -0,0 +1,342 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library barback.test.utils;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/asset_graph.dart';
+import 'package:pathos/path.dart' as pathos;
+import 'package:scheduled_test/scheduled_test.dart';
+
+// TODO(rnystrom): Get rid of this or find a better path for it.
+import '../../../sdk/lib/_internal/pub/test/command_line_config.dart';
+
+var _configured = false;
+
+void initConfig() {
+ if (_configured) return;
+ _configured = true;
+ unittestConfiguration = new CommandLineConfiguration();
+}
+
+/// Expects that [graph] will return an asset matching [name] and [contents].
+void expectAsset(AssetGraph graph, String name, [String contents]) {
+ var id = new AssetId.parse(name);
+
+ if (contents == null) {
+ contents = pathos.basenameWithoutExtension(id.path);
+ }
+
+ schedule(() {
+ return graph.getAssetById(id).then((asset) {
+ // TODO(rnystrom): Make an actual Matcher class for this.
+ expect(asset, new isInstanceOf<MockAsset>());
+ expect(asset._id.package, equals(id.package));
+ expect(asset._id.path, equals(id.path));
+ expect(asset._contents, equals(contents));
+ });
+ }, "get asset $name");
+}
+
+/// Expects that [graph] will not find an asset matching [name].
+void expectNoAsset(AssetGraph graph, String name) {
+ var id = new AssetId.parse(name);
+
+ // Make sure the future gets the error.
+ schedule(() {
+ return graph.getAssetById(id).then((asset) {
+ fail("Should have thrown error but got $asset.");
+ }).catchError((error) {
+ expect(error, new isInstanceOf<AssetNotFoundException>());
+ expect(error.id, equals(id));
+ });
+ }, "get asset $name");
+}
+
+/// Expects that [graph] will have an output file collision error on an asset
+/// matching [name].
+Future expectCollision(AssetGraph graph, String name) {
+ var id = new AssetId.parse(name);
+ return schedule(() {
+ return graph.results.first.then((result) {
+ expect(result.error, new isInstanceOf<AssetCollisionException>());
+ expect(result.error.id, equals(id));
+ });
+ }, "get collision on $name");
+}
+
+/// Expects that [graph] will have an error on an asset matching [name] for
+/// missing [input].
+Future expectMissingInput(AssetGraph graph, String name, String input) {
+ var missing = new AssetId.parse(input);
+
+ // Make sure the future gets the error.
+ schedule(() {
+ return graph.getAssetById(new AssetId.parse(name)).then((asset) {
+ fail("Should have thrown error but got $asset.");
+ }).catchError((error) {
+ expect(error, new isInstanceOf<MissingInputException>());
+ expect(error.id, equals(missing));
+ });
+ }, "get missing input on $name");
+}
+
+/// An [AssetProvider] that provides the given set of assets.
+class MockProvider implements AssetProvider {
+ Iterable<String> get packages => _packages.keys;
+
+ final _packages = new Map<String, List<MockAsset>>();
+
+ /// The completer that [getAsset()] is waiting on to complete.
+ ///
+ /// If `null` it will return the asset immediately.
+ Completer _wait;
+
+ /// Tells the provider to wait during [getAsset] until [complete()]
+ /// is called.
+ ///
+ /// Lets you test the asynchronous behavior of loading.
+ void wait() {
+ _wait = new Completer();
+ }
+
+ void complete() {
+ _wait.complete();
+ _wait = null;
+ }
+
+ MockProvider(assets) {
+ if (assets is Map) {
+ assets.forEach((asset, contents) {
+ var id = new AssetId.parse(asset);
+ var package = _packages.putIfAbsent(id.package, () => []);
+ package.add(new MockAsset(id, contents));
+ });
+ } else if (assets is Iterable) {
+ for (var asset in assets) {
+ var id = new AssetId.parse(asset);
+ var package = _packages.putIfAbsent(id.package, () => []);
+ var contents = pathos.basenameWithoutExtension(id.path);
+ package.add(new MockAsset(id, contents));
+ }
+ }
+ }
+
+ void modifyAsset(String name, String contents) {
+ var id = new AssetId.parse(name);
+ var asset = _packages[id.package].firstWhere((a) => a._id == id);
+ asset._contents = contents;
+ }
+
+ List<AssetId> listAssets(String package, {String within}) {
+ if (within != null) {
+ throw new UnimplementedError("Doesn't handle 'within' yet.");
+ }
+
+ return _packages[package].map((asset) => asset.id);
+ }
+
+ Future<Asset> getAsset(AssetId id) {
+ var future;
+ if (_wait != null) {
+ future = _wait.future;
+ } else {
+ future = new Future.value();
+ }
+
+ return future.then((_) {
+ var package = _packages[id.package];
+ if (package == null) throw new AssetNotFoundException(id);
+
+ return package.firstWhere((asset) => asset._id == id,
+ orElse: () => throw new AssetNotFoundException(id));
+ });
+ }
+}
+
+/// A [Transformer] that takes assets ending with one extension and generates
+/// assets with a given extension.
+///
+/// Appends the output extension to the contents of the input file.
+class RewriteTransformer extends Transformer {
+ final String from;
+ final String to;
+
+ /// The number of times the transformer has been applied.
+ int numRuns = 0;
+
+ /// The number of currently running transforms.
+ int _runningTransforms = 0;
+
+ /// The completer that the transform is waiting on to complete.
+ ///
+ /// If `null` the transform will complete immediately.
+ Completer _wait;
+
+ /// A future that completes when the first apply of this transformer begins.
+ Future get started => _started.future;
+ final _started = new Completer();
+
+ /// Creates a transformer that rewrites assets whose extension is [from] to
+ /// one whose extension is [to].
+ ///
+ /// [to] may be a space-separated list in which case multiple outputs will be
+ /// created for each input.
+ RewriteTransformer(this.from, this.to);
+
+ /// `true` if any transforms are currently running.
+ bool get isRunning => _runningTransforms > 0;
+
+ /// Tells the transform to wait during its transformation until [complete()]
+ /// is called.
+ ///
+ /// Lets you test the asynchronous behavior of transformers.
+ void wait() {
+ _wait = new Completer();
+ }
+
+ void complete() {
+ _wait.complete();
+ _wait = null;
+ }
+
+ Future<bool> isPrimary(AssetId asset) {
+ return new Future.value(asset.extension == ".$from");
+ }
+
+ Future apply(Transform transform) {
+ numRuns++;
+ if (!_started.isCompleted) _started.complete();
+ _runningTransforms++;
+ return transform.primaryInput.then((input) {
+ for (var extension in to.split(" ")) {
+ var id = transform.primaryId.changeExtension(".$extension");
+ var content = input.readAsString() + ".$extension";
+ transform.addOutput(id, new MockAsset(id, content));
+
+ }
+
+ if (_wait != null) return _wait.future;
+ }).whenComplete(() {
+ _runningTransforms--;
+ });
+ }
+
+ String toString() => "$from->$to";
+}
+
+/// A [Transformer] that takes an input asset that contains a comma-separated
+/// list of paths and outputs a file for each path.
+class OneToManyTransformer extends Transformer {
+ final String extension;
+
+ /// The number of times the transformer has been applied.
+ int numRuns = 0;
+
+ /// Creates a transformer that consumes assets with [extension].
+ ///
+ /// That file contains a comma-separated list of paths and it will output
+ /// files at each of those paths.
+ OneToManyTransformer(this.extension);
+
+ Future<bool> isPrimary(AssetId asset) {
+ return new Future.value(asset.extension == ".$extension");
+ }
+
+ Future apply(Transform transform) {
+ numRuns++;
+ return transform.primaryInput.then((input) {
+ for (var line in input.readAsString().split(",")) {
+ var id = new AssetId(transform.primaryId.package, line);
+ transform.addOutput(id, new MockAsset(id, "spread $extension"));
+ }
+ });
+ }
+
+ String toString() => "1->many $extension";
+}
+
+/// A transformer that uses the contents of a file to define the other inputs.
+///
+/// Outputs a file with the same name as the primary but with an "out"
+/// extension containing the concatenated contents of all non-primary inputs.
+class ManyToOneTransformer extends Transformer {
+ final String extension;
+
+ /// The number of times the transformer has been applied.
+ int numRuns = 0;
+
+ /// Creates a transformer that consumes assets with [extension].
+ ///
+ /// That file contains a comma-separated list of paths and it will input
+ /// files at each of those paths.
+ ManyToOneTransformer(this.extension);
+
+ Future<bool> isPrimary(AssetId asset) {
+ return new Future.value(asset.extension == ".$extension");
+ }
+
+ Future apply(Transform transform) {
+ numRuns++;
+ return transform.primaryInput.then((primary) {
+ // Get all of the included inputs.
+ var inputs = primary.readAsString().split(",").map((path) {
+ var id = new AssetId(transform.primaryId.package, path);
+ return transform.getInput(id);
+ });
+
+ // Concatenate them to one output.
+ return Future.wait(inputs).then((inputs) {
+ var id = transform.primaryId.changeExtension(".out");
+ var contents = inputs.map((input) => input.readAsString()).join();
+ transform.addOutput(id, new MockAsset(id, contents));
+ });
+ });
+ }
+
+ String toString() => "many->1 $extension";
+}
+
+/// A transformer that throws an exception when run, after generating the
+/// given outputs.
+class BadTransformer extends Transformer {
+ /// The error it throws.
+ static const ERROR = "I am a bad transformer!";
+
+ /// The list of asset names that it should output.
+ final List<String> outputs;
+
+ BadTransformer(this.outputs);
+
+ Future<bool> isPrimary(AssetId asset) => new Future.value(true);
+ Future apply(Transform transform) {
+ return new Future(() {
+ // Create the outputs first.
+ for (var output in outputs) {
+ var id = new AssetId.parse(output);
+ transform.addOutput(id, new MockAsset(id, output));
+ }
+
+ // Then fail.
+ throw ERROR;
+ });
+ }
+}
+
+/// An implementation of [Asset] that never hits the file system.
+class MockAsset implements Asset {
+ final AssetId _id;
+ String _contents;
+
+ MockAsset(this._id, this._contents);
+
+ String readAsString() => _contents;
+ Stream<List<int>> read() => throw new UnimplementedError();
+
+ serialize() => throw new UnimplementedError();
+
+ String toString() => "MockAsset $_id $_contents";
+}
\ No newline at end of file
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
index 308df28..6222b0f 100644
--- a/pkg/docgen/bin/docgen.dart
+++ b/pkg/docgen/bin/docgen.dart
@@ -2,392 +2,56 @@
// 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.
-/**
- * The docgen tool takes in a library as input and produces documentation
- * for the library as well as all libraries it imports and uses. The tool can
- * be run by passing in the path to a .dart file like this:
- *
- * ./dart docgen.dart path/to/file.dart
- *
- * This outputs information about all classes, variables, functions, and
- * methods defined in the library and its imported libraries.
- */
-library docgen;
-
-// TODO(tmandel): Use 'package:' references for imports with relative paths.
import 'dart:io';
-import 'dart:json';
-import 'dart:async';
-import '../lib/dart2yaml.dart';
-import '../lib/src/dart2js_mirrors.dart';
-import 'package:markdown/markdown.dart' as markdown;
-import '../../args/lib/args.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';
+
+import 'package:args/args.dart';
+import 'package:logging/logging.dart';
+
+import '../lib/docgen.dart';
/**
- * Entry function to create YAML documentation from Dart files.
+ * Analyzes Dart files and generates a representation of included libraries,
+ * classes, and members.
*/
void main() {
- // TODO(tmandel): Use args library once flags are clear.
- Options opts = new Options();
- Docgen docgen = new Docgen();
-
- if (opts.arguments.length > 0) {
- List<Path> libraries = [new Path(opts.arguments[0])];
- Path sdkDirectory = new Path("../../../sdk/");
- var workingMirrors = analyze(libraries, sdkDirectory,
- options: ['--preserve-comments', '--categories=Client,Server']);
- workingMirrors.then( (MirrorSystem mirrorSystem) {
- var mirrors = mirrorSystem.libraries.values;
- if (mirrors.isEmpty) {
- print("no LibraryMirrors");
- } else {
- docgen.libraries = mirrors;
- docgen.documentLibraries();
- }
- });
- }
+ logger.onRecord.listen((record) => print(record.message));
+ var results = initArgParser().parse(new Options().arguments);
+ if (results['help']) return;
+ new Docgen(results);
}
/**
- * This class documents a list of libraries.
+ * Creates parser for docgen command line arguments.
*/
-class Docgen {
-
- /// Libraries to be documented.
- List<LibraryMirror> _libraries;
+ArgParser initArgParser() {
+ var parser = new ArgParser();
+ parser.addFlag('help', abbr: 'h',
+ help: 'Prints help and usage information.',
+ negatable: false,
+ callback: (help) {
+ if (help) {
+ logger.info(parser.getUsage());
+ logger.info(usage);
+ }
+ });
+ parser.addFlag('verbose', abbr: 'v',
+ help: 'Output more logging information.', negatable: false,
+ callback: (verbose) {
+ if (verbose) Logger.root.level = Level.FINEST;
+ });
+ parser.addOption('output-format', abbr: 'o',
+ help: 'Sets the output format.',
+ allowed: ['yaml', 'json'],
+ allowedHelp: {'yaml' : 'Outputs to YAML. (Default)',
+ 'json' : 'Outputs to JSON.'});
+ parser.addFlag('yaml', abbr: 'y',
+ help: 'Same as output-format=yaml.', negatable: false);
+ parser.addFlag('json', abbr: 'j',
+ help: 'Same as output-format=json.', negatable: false);
+ parser.addFlag('include-private',
+ help: 'Flag to include private declarations.', negatable: false);
+ parser.addFlag('include-sdk',
+ help: 'Flag to parse SDK Library files.', negatable: false);
- /// Saves list of libraries for Docgen object.
- void set libraries(value) => _libraries = value;
-
- /// Current library being documented to be used for comment links.
- LibraryMirror _currentLibrary;
-
- /// Current class being documented to be used for comment links.
- ClassMirror _currentClass;
-
- /// Current member being documented to be used for comment links.
- MemberMirror _currentMember;
-
- /// Should the output file type be JSON?
- // TODO(tmandel): Add flag to allow for output to JSON.
- bool outputToJson = false;
-
- /// Resolves reference links
- markdown.Resolver linkResolver;
-
- /**
- * Docgen constructor initializes the link resolver for markdown parsing.
- */
- Docgen() {
- this.linkResolver = (name) =>
- fixReference(name, _currentLibrary, _currentClass, _currentMember);
- }
-
- /**
- * Creates documentation for filtered libraries.
- */
- void documentLibraries() {
- //TODO(tmandel): Filter libraries and determine output type using flags.
- _libraries.forEach((library) {
- _currentLibrary = library;
- var result = new Library(library.qualifiedName, _getComment(library),
- _getVariables(library.variables), _getMethods(library.functions),
- _getClasses(library.classes));
- if (outputToJson) {
- _writeToFile(stringify(result.toMap()), "${result.name}.json");
- } else {
- _writeToFile(getYamlString(result.toMap()), "${result.name}.yaml");
- }
- });
- }
-
- /**
- * Returns any documentation comments associated with a mirror with
- * simple markdown converted to html.
- */
- String _getComment(DeclarationMirror mirror) {
- String commentText;
- mirror.metadata.forEach((metadata) {
- if (metadata is CommentInstanceMirror) {
- CommentInstanceMirror comment = metadata;
- if (comment.isDocComment) {
- if (commentText == null) {
- commentText = comment.trimmedText;
- } else {
- commentText = "$commentText ${comment.trimmedText}";
- }
- }
- }
- });
- return commentText == null ? "" :
- markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver);
- }
-
- /**
- * Converts all [_] references in comments to <code>_</code>.
- */
- // TODO(tmandel): Create proper links for [_] style markdown based
- // on scope once layout of viewer is finished.
- markdown.Node fixReference(String name, LibraryMirror currentLibrary,
- ClassMirror currentClass, MemberMirror currentMember) {
- return new markdown.Element.text('code', name);
- }
-
- /**
- * Returns a map of [Variable] objects constructed from inputted mirrors.
- */
- Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) {
- var data = {};
- mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
- _currentMember = mirror;
- data[mirrorName] = new Variable(mirrorName, mirror.isFinal,
- mirror.isStatic, mirror.type.toString(), _getComment(mirror));
- });
- return data;
- }
-
- /**
- * Returns a map of [Method] objects constructed from inputted mirrors.
- */
- Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) {
- var data = {};
- mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
- _currentMember = mirror;
- data[mirrorName] = new Method(mirrorName, mirror.isSetter,
- mirror.isGetter, mirror.isConstructor, mirror.isOperator,
- mirror.isStatic, mirror.returnType.toString(), _getComment(mirror),
- _getParameters(mirror.parameters));
- });
- return data;
- }
-
- /**
- * Returns a map of [Class] objects constructed from inputted mirrors.
- */
- Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) {
- var data = {};
- mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
- _currentClass = mirror;
- var superclass;
- if (mirror.superclass != null) {
- superclass = mirror.superclass.qualifiedName;
- }
- var interfaces =
- mirror.superinterfaces.map((interface) => interface.qualifiedName);
- data[mirrorName] = new Class(mirrorName, superclass, mirror.isAbstract,
- mirror.isTypedef, _getComment(mirror), interfaces,
- _getVariables(mirror.variables), _getMethods(mirror.methods));
- });
- return data;
- }
-
- /**
- * Returns a map of [Parameter] objects constructed from inputted mirrors.
- */
- Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) {
- var data = {};
- mirrorList.forEach((ParameterMirror mirror) {
- _currentMember = mirror;
- data[mirror.simpleName] = new Parameter(mirror.simpleName,
- mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue,
- mirror.type.toString(), mirror.defaultValue);
- });
- return data;
- }
+ return parser;
}
-
-/**
- * Transforms the map by calling toMap on each value in it.
- */
-Map recurseMap(Map inputMap) {
- var outputMap = {};
- inputMap.forEach((key, value) {
- outputMap[key] = value.toMap();
- });
- return outputMap;
-}
-
-/**
- * A class containing contents of a Dart library.
- */
-class Library {
-
- /// Documentation comment with converted markdown.
- String comment;
-
- /// Top-level variables in the library.
- Map<String, Variable> variables;
-
- /// Top-level functions in the library.
- Map<String, Method> functions;
-
- /// Classes defined within the library
- Map<String, Class> classes;
-
- String name;
-
- Library(this.name, this.comment, this.variables,
- this.functions, this.classes);
-
- /// Generates a map describing the [Library] object.
- Map toMap() {
- var libraryMap = {};
- libraryMap["name"] = name;
- libraryMap["comment"] = comment;
- libraryMap["variables"] = recurseMap(variables);
- libraryMap["functions"] = recurseMap(functions);
- libraryMap["classes"] = recurseMap(classes);
- return libraryMap;
- }
-}
-
-/**
- * A class containing contents of a Dart class.
- */
-// TODO(tmandel): Figure out how to do typedefs (what is needed)
-class Class {
-
- /// Documentation comment with converted markdown.
- String comment;
-
- /// List of the names of interfaces that this class implements.
- List<String> interfaces;
-
- /// Top-level variables in the class.
- Map<String, Variable> variables;
-
- /// Methods in the class.
- Map<String, Method> methods;
-
- String name;
- String superclass;
- bool isAbstract;
- bool isTypedef;
-
- Class(this.name, this.superclass, this.isAbstract, this.isTypedef,
- this.comment, this.interfaces, this.variables, this.methods);
-
- /// Generates a map describing the [Class] object.
- Map toMap() {
- var classMap = {};
- classMap["name"] = name;
- classMap["comment"] = comment;
- classMap["superclass"] = superclass;
- classMap["abstract"] = isAbstract.toString();
- classMap["typedef"] = isTypedef.toString();
- classMap["implements"] = new List.from(interfaces);
- classMap["variables"] = recurseMap(variables);
- classMap["methods"] = recurseMap(methods);
- return classMap;
- }
-}
-
-/**
- * A class containing properties of a Dart variable.
- */
-class Variable {
-
- /// Documentation comment with converted markdown.
- String comment;
-
- String name;
- bool isFinal;
- bool isStatic;
- String type;
-
- Variable(this.name, this.isFinal, this.isStatic, this.type, this.comment);
-
- /// Generates a map describing the [Variable] object.
- Map toMap() {
- var variableMap = {};
- variableMap["name"] = name;
- variableMap["comment"] = comment;
- variableMap["final"] = isFinal.toString();
- variableMap["static"] = isStatic.toString();
- variableMap["type"] = type;
- return variableMap;
- }
-}
-
-/**
- * A class containing properties of a Dart method.
- */
-class Method {
-
- /// Documentation comment with converted markdown.
- String comment;
-
- /// Parameters for this method.
- Map<String, Parameter> parameters;
-
- String name;
- bool isSetter;
- bool isGetter;
- bool isConstructor;
- bool isOperator;
- bool isStatic;
- String returnType;
-
- Method(this.name, this.isSetter, this.isGetter, this.isConstructor,
- this.isOperator, this.isStatic, this.returnType, this.comment,
- this.parameters);
-
- /// Generates a map describing the [Method] object.
- Map toMap() {
- var methodMap = {};
- methodMap["name"] = name;
- methodMap["comment"] = comment;
- methodMap["type"] = isSetter ? "setter" : isGetter ? "getter" :
- isOperator ? "operator" : isConstructor ? "constructor" : "method";
- methodMap["static"] = isStatic.toString();
- methodMap["return"] = returnType;
- methodMap["parameters"] = recurseMap(parameters);
- return methodMap;
- }
-}
-
-/**
- * A class containing properties of a Dart method/function parameter.
- */
-class Parameter {
-
- String name;
- bool isOptional;
- bool isNamed;
- bool hasDefaultValue;
- String type;
- String defaultValue;
-
- Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue,
- this.type, this.defaultValue);
-
- /// Generates a map describing the [Parameter] object.
- Map toMap() {
- var parameterMap = {};
- parameterMap["name"] = name;
- parameterMap["optional"] = isOptional.toString();
- parameterMap["named"] = isNamed.toString();
- parameterMap["default"] = hasDefaultValue.toString();
- parameterMap["type"] = type;
- parameterMap["value"] = defaultValue;
- return parameterMap;
- }
-}
-
-/**
- * Writes text to a file in the 'docs' directory.
- */
-void _writeToFile(String text, String filename) {
- Directory dir = new Directory('docs');
- if (!dir.existsSync()) {
- dir.createSync();
- }
- File file = new File('docs/$filename');
- if (!file.exists()) {
- file.createSync();
- }
- file.openSync();
- file.writeAsString(text);
-}
\ No newline at end of file
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
new file mode 100644
index 0000000..52d10d2
--- /dev/null
+++ b/pkg/docgen/lib/docgen.dart
@@ -0,0 +1,508 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/**
+ * **docgen** is a tool for creating machine readable representations of Dart
+ * code metadata, including: classes, members, comments and annotations.
+ *
+ * docgen is run on a `.dart` file or a directory containing `.dart` files.
+ *
+ * $ dart docgen.dart [OPTIONS] [FILE/DIR]
+ *
+ * This creates files called `docs/<library_name>.yaml` in your current
+ * working directory.
+ */
+library docgen;
+
+import 'dart:io';
+import 'dart:json';
+import 'dart:async';
+
+import 'package:args/args.dart';
+import 'package:logging/logging.dart';
+import 'package:markdown/markdown.dart' as markdown;
+import 'package:pathos/path.dart' as path;
+
+import 'dart2yaml.dart';
+import 'src/io.dart';
+import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
+import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart'
+ as dart2js;
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
+
+var logger = new Logger('Docgen');
+
+const String usage = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]';
+
+/**
+ * This class documents a list of libraries.
+ */
+class Docgen {
+
+ /// Libraries to be documented.
+ List<LibraryMirror> _libraries;
+
+ /// Current library being documented to be used for comment links.
+ LibraryMirror _currentLibrary;
+
+ /// Current class being documented to be used for comment links.
+ ClassMirror _currentClass;
+
+ /// Current member being documented to be used for comment links.
+ MemberMirror _currentMember;
+
+ /// Resolves reference links in doc comments.
+ markdown.Resolver linkResolver;
+
+ /// Package directory of directory being analyzed.
+ String packageDir;
+
+ bool outputToYaml;
+ bool outputToJson;
+ bool includePrivate;
+ /// State for whether or not the SDK libraries should also be outputted.
+ bool includeSdk;
+
+ /**
+ * Docgen constructor initializes the link resolver for markdown parsing.
+ * Also initializes the command line arguments.
+ */
+ Docgen(ArgResults argResults) {
+ if (argResults['output-format'] == null) {
+ outputToYaml =
+ (argResults['yaml'] == false && argResults['json'] == false) ?
+ true : argResults['yaml'];
+ } else {
+ if ((argResults['output-format'] == 'yaml' &&
+ argResults['json'] == true) ||
+ (argResults['output-format'] == 'json' &&
+ argResults['yaml'] == true)) {
+ throw new UnsupportedError('Cannot have contradictory output flags.');
+ }
+ outputToYaml = argResults['output-format'] == 'yaml' ? true : false;
+ }
+ outputToJson = !outputToYaml;
+ includePrivate = argResults['include-private'];
+ includeSdk = argResults['include-sdk'];
+
+ this.linkResolver = (name) =>
+ fixReference(name, _currentLibrary, _currentClass, _currentMember);
+
+ analyze(argResults.rest);
+ }
+
+ List<String> listLibraries(List<String> args) {
+ // TODO(janicejl): At the moment, only have support to have either one file,
+ // or one directory. This is because there can only be one package directory
+ // since only one docgen is created per run.
+ if (args.length != 1) throw new UnsupportedError(usage);
+ var libraries = new List<String>();
+ var type = FileSystemEntity.typeSync(args[0]);
+
+ if (type == FileSystemEntityType.FILE) {
+ libraries.add(path.absolute(args[0]));
+ logger.info('Added to libraries: ${libraries.last}');
+ } else {
+ libraries.addAll(listDartFromDir(args[0]));
+ }
+ logger.info('Package Directory: $packageDir');
+ return libraries;
+ }
+
+ List<String> listDartFromDir(String args) {
+ var files = listDir(args, recursive: true);
+ packageDir = files.firstWhere((f) =>
+ f.endsWith('/pubspec.yaml'), orElse: () => '');
+ if (packageDir != '') packageDir = path.dirname(packageDir) + '/packages';
+ return files.where((f) =>
+ f.endsWith('.dart') && !f.contains('/packages')).toList()
+ ..forEach((lib) => logger.info('Added to libraries: $lib'));
+ }
+
+ /**
+ * Analyzes set of libraries by getting a mirror system and triggers the
+ * documentation of the libraries.
+ */
+ void analyze(List<String> args) {
+ var libraries = listLibraries(args);
+ if (libraries.isEmpty) throw new StateError('No Libraries.');
+ // DART_SDK should be set to the root of the SDK library.
+ var sdkRoot = Platform.environment['DART_SDK'];
+ if (sdkRoot != null) {
+ logger.info('Using DART_SDK to find SDK at $sdkRoot');
+ } else {
+ // If DART_SDK is not defined in the environment,
+ // assuming the dart executable is from the Dart SDK folder inside bin.
+ sdkRoot = path.dirname(path.dirname(new Options().executable));
+ logger.info('SDK Root: ${sdkRoot}');
+ }
+
+ getMirrorSystem(libraries, sdkRoot, packageRoot: packageDir)
+ .then((MirrorSystem mirrorSystem) {
+ if (mirrorSystem.libraries.values.isEmpty) {
+ throw new UnsupportedError('No Library Mirrors.');
+ }
+ this.libraries = mirrorSystem.libraries.values;
+ documentLibraries();
+ });
+ }
+
+ /**
+ * Analyzes set of libraries and provides a mirror system which can be used
+ * for static inspection of the source code.
+ */
+ Future<MirrorSystem> getMirrorSystem(List<String> libraries,
+ String libraryRoot, {String packageRoot}) {
+ SourceFileProvider provider = new SourceFileProvider();
+ api.DiagnosticHandler diagnosticHandler =
+ new FormattingDiagnosticHandler(provider).diagnosticHandler;
+ Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot'));
+ Uri packageUri = null;
+ if (packageRoot != null) {
+ packageUri = currentDirectory.resolve(appendSlash('$packageRoot'));
+ }
+ List<Uri> librariesUri = <Uri>[];
+ libraries.forEach((library) {
+ librariesUri.add(currentDirectory.resolve(library));
+ });
+ return dart2js.analyze(librariesUri, libraryUri, packageUri,
+ provider.readStringFromUri, diagnosticHandler,
+ ['--preserve-comments', '--categories=Client,Server']);
+ }
+
+ /**
+ * Creates documentation for filtered libraries.
+ */
+ void documentLibraries() {
+ _libraries.forEach((library) {
+ // Files belonging to the SDK have a uri that begins with 'dart:'.
+ if (includeSdk || !library.uri.toString().startsWith('dart:')) {
+ _currentLibrary = library;
+ var result = new Library(library.qualifiedName, _getComment(library),
+ _getVariables(library.variables), _getMethods(library.functions),
+ _getClasses(library.classes));
+ if (outputToJson) {
+ _writeToFile(stringify(result.toMap()), '${result.name}.json');
+ }
+ if (outputToYaml) {
+ _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml');
+ }
+ }
+ });
+ }
+
+ /// Saves list of libraries for Docgen object.
+ void set libraries(value){
+ _libraries = value;
+ }
+
+ /**
+ * Returns any documentation comments associated with a mirror with
+ * simple markdown converted to html.
+ */
+ String _getComment(DeclarationMirror mirror) {
+ String commentText;
+ mirror.metadata.forEach((metadata) {
+ if (metadata is CommentInstanceMirror) {
+ CommentInstanceMirror comment = metadata;
+ if (comment.isDocComment) {
+ if (commentText == null) {
+ commentText = comment.trimmedText;
+ } else {
+ commentText = '$commentText ${comment.trimmedText}';
+ }
+ }
+ }
+ });
+ commentText = commentText == null ? '' :
+ markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver)
+ .replaceAll('\n', '');
+ return commentText;
+ }
+
+ /**
+ * Converts all [_] references in comments to <code>_</code>.
+ */
+ // TODO(tmandel): Create proper links for [_] style markdown based
+ // on scope once layout of viewer is finished.
+ markdown.Node fixReference(String name, LibraryMirror currentLibrary,
+ ClassMirror currentClass, MemberMirror currentMember) {
+ return new markdown.Element.text('code', name);
+ }
+
+ /**
+ * Returns a map of [Variable] objects constructed from inputted mirrors.
+ */
+ Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) {
+ var data = {};
+ mirrorMap.forEach((String mirrorName, VariableMirror mirror) {
+ if (includePrivate || !mirror.isPrivate) {
+ _currentMember = mirror;
+ data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName,
+ mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName,
+ _getComment(mirror));
+ }
+ });
+ return data;
+ }
+
+ /**
+ * Returns a map of [Method] objects constructed from inputted mirrors.
+ */
+ Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) {
+ var data = {};
+ mirrorMap.forEach((String mirrorName, MethodMirror mirror) {
+ if (includePrivate || !mirror.isPrivate) {
+ _currentMember = mirror;
+ data[mirrorName] = new Method(mirrorName, mirror.qualifiedName,
+ mirror.isSetter, mirror.isGetter, mirror.isConstructor,
+ mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName,
+ _getComment(mirror), _getParameters(mirror.parameters));
+ }
+ });
+ return data;
+ }
+
+ /**
+ * Returns a map of [Class] objects constructed from inputted mirrors.
+ */
+ Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) {
+ var data = {};
+ mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
+ if (includePrivate || !mirror.isPrivate) {
+ _currentClass = mirror;
+ var superclass = (mirror.superclass != null) ?
+ mirror.superclass.qualifiedName : '';
+ var interfaces =
+ mirror.superinterfaces.map((interface) => interface.qualifiedName);
+ data[mirrorName] = new Class(mirrorName, mirror.qualifiedName,
+ superclass, mirror.isAbstract, mirror.isTypedef,
+ _getComment(mirror), interfaces.toList(),
+ _getVariables(mirror.variables), _getMethods(mirror.methods));
+ }
+ });
+ return data;
+ }
+
+ /**
+ * Returns a map of [Parameter] objects constructed from inputted mirrors.
+ */
+ Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) {
+ var data = {};
+ mirrorList.forEach((ParameterMirror mirror) {
+ _currentMember = mirror;
+ data[mirror.simpleName] = new Parameter(mirror.simpleName,
+ mirror.qualifiedName, mirror.isOptional, mirror.isNamed,
+ mirror.hasDefaultValue, mirror.type.qualifiedName,
+ mirror.defaultValue);
+ });
+ return data;
+ }
+}
+
+/**
+ * Transforms the map by calling toMap on each value in it.
+ */
+Map recurseMap(Map inputMap) {
+ var outputMap = {};
+ inputMap.forEach((key, value) {
+ outputMap[key] = value.toMap();
+ });
+ return outputMap;
+}
+
+/**
+ * A class containing contents of a Dart library.
+ */
+class Library {
+
+ /// Documentation comment with converted markdown.
+ String comment;
+
+ /// Top-level variables in the library.
+ Map<String, Variable> variables;
+
+ /// Top-level functions in the library.
+ Map<String, Method> functions;
+
+ /// Classes defined within the library
+ Map<String, Class> classes;
+
+ String name;
+
+ Library(this.name, this.comment, this.variables,
+ this.functions, this.classes);
+
+ /// Generates a map describing the [Library] object.
+ Map toMap() {
+ var libraryMap = {};
+ libraryMap['name'] = name;
+ libraryMap['comment'] = comment;
+ libraryMap['variables'] = recurseMap(variables);
+ libraryMap['functions'] = recurseMap(functions);
+ libraryMap['classes'] = recurseMap(classes);
+ return libraryMap;
+ }
+}
+
+/**
+ * A class containing contents of a Dart class.
+ */
+// TODO(tmandel): Figure out how to do typedefs (what is needed)
+class Class {
+
+ /// Documentation comment with converted markdown.
+ String comment;
+
+ /// List of the names of interfaces that this class implements.
+ List<String> interfaces;
+
+ /// Top-level variables in the class.
+ Map<String, Variable> variables;
+
+ /// Methods in the class.
+ Map<String, Method> methods;
+
+ String name;
+ String qualifiedName;
+ String superclass;
+ bool isAbstract;
+ bool isTypedef;
+
+ Class(this.name, this.qualifiedName, this.superclass, this.isAbstract, this.isTypedef,
+ this.comment, this.interfaces, this.variables, this.methods);
+
+ /// Generates a map describing the [Class] object.
+ Map toMap() {
+ var classMap = {};
+ classMap['name'] = name;
+ classMap['qualifiedname'] = qualifiedName;
+ classMap['comment'] = comment;
+ classMap['superclass'] = superclass;
+ classMap['abstract'] = isAbstract.toString();
+ classMap['typedef'] = isTypedef.toString();
+ classMap['implements'] = new List.from(interfaces);
+ classMap['variables'] = recurseMap(variables);
+ classMap['methods'] = recurseMap(methods);
+ return classMap;
+ }
+}
+
+/**
+ * A class containing properties of a Dart variable.
+ */
+class Variable {
+
+ /// Documentation comment with converted markdown.
+ String comment;
+
+ String name;
+ String qualifiedName;
+ bool isFinal;
+ bool isStatic;
+ String type;
+
+ Variable(this.name, this.qualifiedName, this.isFinal, this.isStatic,
+ this.type, this.comment);
+
+ /// Generates a map describing the [Variable] object.
+ Map toMap() {
+ var variableMap = {};
+ variableMap['name'] = name;
+ variableMap['qualifiedname'] = qualifiedName;
+ variableMap['comment'] = comment;
+ variableMap['final'] = isFinal.toString();
+ variableMap['static'] = isStatic.toString();
+ variableMap['type'] = type;
+ return variableMap;
+ }
+}
+
+/**
+ * A class containing properties of a Dart method.
+ */
+class Method {
+
+ /// Documentation comment with converted markdown.
+ String comment;
+
+ /// Parameters for this method.
+ Map<String, Parameter> parameters;
+
+ String name;
+ String qualifiedName;
+ bool isSetter;
+ bool isGetter;
+ bool isConstructor;
+ bool isOperator;
+ bool isStatic;
+ String returnType;
+
+ Method(this.name, this.qualifiedName, this.isSetter, this.isGetter,
+ this.isConstructor, this.isOperator, this.isStatic, this.returnType,
+ this.comment, this.parameters);
+
+ /// Generates a map describing the [Method] object.
+ Map toMap() {
+ var methodMap = {};
+ methodMap['name'] = name;
+ methodMap['qualifiedname'] = qualifiedName;
+ methodMap['comment'] = comment;
+ methodMap['type'] = isSetter ? 'setter' : isGetter ? 'getter' :
+ isOperator ? 'operator' : isConstructor ? 'constructor' : 'method';
+ methodMap['static'] = isStatic.toString();
+ methodMap['return'] = returnType;
+ methodMap['parameters'] = recurseMap(parameters);
+ return methodMap;
+ }
+}
+
+/**
+ * A class containing properties of a Dart method/function parameter.
+ */
+class Parameter {
+
+ String name;
+ String qualifiedName;
+ bool isOptional;
+ bool isNamed;
+ bool hasDefaultValue;
+ String type;
+ String defaultValue;
+
+ Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed, this.hasDefaultValue,
+ this.type, this.defaultValue);
+
+ /// Generates a map describing the [Parameter] object.
+ Map toMap() {
+ var parameterMap = {};
+ parameterMap['name'] = name;
+ parameterMap['qualifiedname'] = qualifiedName;
+ parameterMap['optional'] = isOptional.toString();
+ parameterMap['named'] = isNamed.toString();
+ parameterMap['default'] = hasDefaultValue.toString();
+ parameterMap['type'] = type;
+ parameterMap['value'] = defaultValue;
+ return parameterMap;
+ }
+}
+
+/**
+ * Writes text to a file in the 'docs' directory.
+ */
+void _writeToFile(String text, String filename) {
+ Directory dir = new Directory('docs');
+ if (!dir.existsSync()) {
+ dir.createSync();
+ }
+ File file = new File('docs/$filename');
+ if (!file.existsSync()) {
+ file.createSync();
+ }
+ file.openSync();
+ file.writeAsString(text);
+}
\ No newline at end of file
diff --git a/pkg/docgen/lib/src/io.dart b/pkg/docgen/lib/src/io.dart
new file mode 100644
index 0000000..8d1a423
--- /dev/null
+++ b/pkg/docgen/lib/src/io.dart
@@ -0,0 +1,151 @@
+library io;
+/// This is a helper library to make working with io easier.
+// TODO(janicejl): listDir, canonicalize, resolveLink, and linkExists are from
+// pub/lib/src/io.dart. If the io.dart file becomes a package, should remove
+// copy of the functions.
+
+import 'dart:collection';
+import 'dart:io';
+import 'package:pathos/path.dart' as path;
+
+/// Lists the contents of [dir]. If [recursive] is `true`, lists subdirectory
+/// contents (defaults to `false`). If [includeHidden] is `true`, includes files
+/// and directories beginning with `.` (defaults to `false`).
+///
+/// The returned paths are guaranteed to begin with [dir].
+List<String> listDir(String dir, {bool recursive: false,
+ bool includeHidden: false}) {
+ List<String> doList(String dir, Set<String> listedDirectories) {
+ var contents = <String>[];
+
+ // Avoid recursive symlinks.
+ var resolvedPath = canonicalize(dir);
+ if (listedDirectories.contains(resolvedPath)) return [];
+
+ listedDirectories = new Set<String>.from(listedDirectories);
+ listedDirectories.add(resolvedPath);
+
+ var children = <String>[];
+ for (var entity in new Directory(dir).listSync()) {
+ if (!includeHidden && path.basename(entity.path).startsWith('.')) {
+ continue;
+ }
+
+ contents.add(entity.path);
+ if (entity is Directory) {
+ // TODO(nweiz): don't manually recurse once issue 4794 is fixed.
+ // Note that once we remove the manual recursion, we'll need to
+ // explicitly filter out files in hidden directories.
+ if (recursive) {
+ children.addAll(doList(entity.path, listedDirectories));
+ }
+ }
+ }
+
+ contents.addAll(children);
+ return contents;
+ }
+
+ return doList(dir, new Set<String>());
+}
+
+/// Returns the canonical path for [pathString]. This is the normalized,
+/// absolute path, with symlinks resolved. As in [transitiveTarget], broken or
+/// recursive symlinks will not be fully resolved.
+///
+/// This doesn't require [pathString] to point to a path that exists on the
+/// filesystem; nonexistent or unreadable path entries are treated as normal
+/// directories.
+String canonicalize(String pathString) {
+ var seen = new Set<String>();
+ var components = new Queue<String>.from(
+ path.split(path.normalize(path.absolute(pathString))));
+
+ // The canonical path, built incrementally as we iterate through [components].
+ var newPath = components.removeFirst();
+
+ // Move through the components of the path, resolving each one's symlinks as
+ // necessary. A resolved component may also add new components that need to be
+ // resolved in turn.
+ while (!components.isEmpty) {
+ seen.add(path.join(newPath, path.joinAll(components)));
+ var resolvedPath = resolveLink(
+ path.join(newPath, components.removeFirst()));
+ var relative = path.relative(resolvedPath, from: newPath);
+
+ // If the resolved path of the component relative to `newPath` is just ".",
+ // that means component was a symlink pointing to its parent directory. We
+ // can safely ignore such components.
+ if (relative == '.') continue;
+
+ var relativeComponents = new Queue<String>.from(path.split(relative));
+
+ // If the resolved path is absolute relative to `newPath`, that means it's
+ // on a different drive. We need to canonicalize the entire target of that
+ // symlink again.
+ if (path.isAbsolute(relative)) {
+ // If we've already tried to canonicalize the new path, we've encountered
+ // a symlink loop. Avoid going infinite by treating the recursive symlink
+ // as the canonical path.
+ if (seen.contains(relative)) {
+ newPath = relative;
+ } else {
+ newPath = relativeComponents.removeFirst();
+ relativeComponents.addAll(components);
+ components = relativeComponents;
+ }
+ continue;
+ }
+
+ // Pop directories off `newPath` if the component links upwards in the
+ // directory hierarchy.
+ while (relativeComponents.first == '..') {
+ newPath = path.dirname(newPath);
+ relativeComponents.removeFirst();
+ }
+
+ // If there's only one component left, [resolveLink] guarantees that it's
+ // not a link (or is a broken link). We can just add it to `newPath` and
+ // continue resolving the remaining components.
+ if (relativeComponents.length == 1) {
+ newPath = path.join(newPath, relativeComponents.single);
+ continue;
+ }
+
+ // If we've already tried to canonicalize the new path, we've encountered a
+ // symlink loop. Avoid going infinite by treating the recursive symlink as
+ // the canonical path.
+ var newSubPath = path.join(newPath, path.joinAll(relativeComponents));
+ if (seen.contains(newSubPath)) {
+ newPath = newSubPath;
+ continue;
+ }
+
+ // If there are multiple new components to resolve, add them to the
+ // beginning of the queue.
+ relativeComponents.addAll(components);
+ components = relativeComponents;
+ }
+ return newPath;
+}
+
+/// Returns the transitive target of [link] (if A links to B which links to C,
+/// this will return C). If [link] is part of a symlink loop (e.g. A links to B
+/// which links back to A), this returns the path to the first repeated link (so
+/// `transitiveTarget("A")` would return `"A"` and `transitiveTarget("A")` would
+/// return `"B"`).
+///
+/// This accepts paths to non-links or broken links, and returns them as-is.
+String resolveLink(String link) {
+ var seen = new Set<String>();
+ while (linkExists(link) && !seen.contains(link)) {
+ seen.add(link);
+ link = path.normalize(path.join(
+ path.dirname(link), new Link(link).targetSync()));
+ }
+ return link;
+}
+
+/// Returns whether [link] exists on the file system. This will return `true`
+/// for any symlink, regardless of what it points at or whether it's broken.
+bool linkExists(String link) => new Link(link).existsSync();
\ No newline at end of file
diff --git a/pkg/docgen/pubspec.yaml b/pkg/docgen/pubspec.yaml
index 697f405..5a6e7af 100644
--- a/pkg/docgen/pubspec.yaml
+++ b/pkg/docgen/pubspec.yaml
@@ -1,4 +1,8 @@
name: docgen
description: A documentation generator for the Dart repository.
dependencies:
- markdown: any
\ No newline at end of file
+ args: any
+ logging: any
+ markdown: any
+ scheduled_test: any
+ unittest: any
diff --git a/pkg/http_server/lib/http_server.dart b/pkg/http_server/lib/http_server.dart
new file mode 100644
index 0000000..1dd07fc
--- /dev/null
+++ b/pkg/http_server/lib/http_server.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library http_server;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:mime/mime.dart';
+
+part 'src/virtual_directory.dart';
+part 'src/virtual_host.dart';
+
diff --git a/pkg/http_server/lib/src/virtual_directory.dart b/pkg/http_server/lib/src/virtual_directory.dart
new file mode 100644
index 0000000..6ce667b
--- /dev/null
+++ b/pkg/http_server/lib/src/virtual_directory.dart
@@ -0,0 +1,284 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of http_server;
+
+/**
+ * A [VirtualDirectory] can serve files and directory-listing from a root path,
+ * to [HttpRequest]s.
+ *
+ * The [VirtualDirectory] providing secure handling of request uris and
+ * file-system links, correct mime-types and custom error pages.
+ */
+abstract class VirtualDirectory {
+ final String root;
+
+ /**
+ * Set or get if the [VirtualDirectory] should list the content of
+ * directories.
+ */
+ bool allowDirectoryListing = false;
+
+ /**
+ * Set or get if the [VirtualDirectory] should follow links, that point
+ * to other resources within the [root] directory.
+ */
+ bool followLinks = true;
+
+ /*
+ * Create a new [VirtualDirectory] for serving static file content of
+ * the path [root].
+ *
+ * The [root] is not required to exist. If the [root] doesn't exist at time of
+ * a request, a 404 is generated.
+ */
+ factory VirtualDirectory(String root) => new _VirtualDirectory(root);
+
+ /**
+ * Serve a [Stream] of [HttpRequest]s, in this [VirtualDirectory].
+ */
+ void serve(Stream<HttpRequest> requests);
+
+ /**
+ * Serve a single [HttpRequest], in this [VirtualDirectory].
+ */
+ void serveRequest(HttpRequest request);
+
+ /**
+ * Set the [callback] to override the error page handler. When [callback] is
+ * invoked, the `statusCode` property of the response is set.
+ */
+ void setErrorPageHandler(void callback(HttpRequest request));
+}
+
+class _VirtualDirectory implements VirtualDirectory {
+ final String root;
+
+ bool allowDirectoryListing = false;
+ bool followLinks = true;
+
+ Function _errorCallback;
+
+ _VirtualDirectory(this.root);
+
+ void serve(Stream<HttpRequest> requests) {
+ requests.listen(serveRequest);
+ }
+
+ void serveRequest(HttpRequest request) {
+ var path = new Path(request.uri.path).canonicalize();
+
+ if (!path.isAbsolute) {
+ return _serveErrorPage(HttpStatus.NOT_FOUND, request);
+ }
+
+ _locateResource(new Path('.'), path.segments())
+ .then((entity) {
+ if (entity == null) {
+ _serveErrorPage(HttpStatus.NOT_FOUND, request);
+ return;
+ }
+ if (entity is File) {
+ _serveFile(entity, request);
+ } else {
+ _serveErrorPage(HttpStatus.NOT_FOUND, request);
+ }
+ });
+ }
+
+ void setErrorPageHandler(void callback(HttpRequest request)) {
+ _errorCallback = callback;
+ }
+
+ Future<FileSystemEntity> _locateResource(Path path,
+ Iterable<String> segments) {
+ Path fullPath() => new Path(root).join(path);
+ return FileSystemEntity.type(fullPath().toNativePath(), followLinks: false)
+ .then((type) {
+ switch (type) {
+ case FileSystemEntityType.FILE:
+ if (segments.isEmpty) return new File.fromPath(fullPath());
+ break;
+
+ case FileSystemEntityType.DIRECTORY:
+ if (segments.isEmpty) {
+ if (allowDirectoryListing) {
+ return new Directory.fromPath(fullPath());
+ }
+ } else {
+ return _locateResource(path.append(segments.first),
+ segments.skip(1));
+ }
+ break;
+
+ case FileSystemEntityType.LINK:
+ if (followLinks) {
+ return new Link.fromPath(fullPath()).target()
+ .then((target) {
+ var targetPath = new Path(target).canonicalize();
+ if (targetPath.isAbsolute) return null;
+ targetPath = path.directoryPath.join(targetPath)
+ .canonicalize();
+ if (targetPath.segments().isEmpty ||
+ targetPath.segments().first == '..') return null;
+ return _locateResource(targetPath.append(segments.first),
+ segments.skip(1));
+ });
+ }
+ break;
+ }
+ // Return `null` on fall-through, to indicate NOT_FOUND.
+ return null;
+ });
+ }
+
+ void _serveFile(File file, HttpRequest request) {
+ var response = request.response;
+ // TODO(ajohnsen): Set up Zone support for these errors.
+ file.lastModified().then((lastModified) {
+ if (request.headers.ifModifiedSince != null &&
+ !lastModified.isAfter(request.headers.ifModifiedSince)) {
+ response.statusCode = HttpStatus.NOT_MODIFIED;
+ response.close();
+ return;
+ }
+
+ response.headers.set(HttpHeaders.LAST_MODIFIED, lastModified);
+ response.headers.set(HttpHeaders.ACCEPT_RANGES, "bytes");
+
+ if (request.method == 'HEAD') {
+ response.close();
+ return;
+ }
+
+ return file.length().then((length) {
+ String range = request.headers.value("range");
+ if (range != null) {
+ // We only support one range, where the standard support several.
+ Match matches = new RegExp(r"^bytes=(\d*)\-(\d*)$").firstMatch(range);
+ // If the range header have the right format, handle it.
+ if (matches != null) {
+ // Serve sub-range.
+ int start;
+ int end;
+ if (matches[1].isEmpty) {
+ start = matches[2].isEmpty ?
+ length :
+ length - int.parse(matches[2]);
+ end = length;
+ } else {
+ start = int.parse(matches[1]);
+ end = matches[2].isEmpty ? length : int.parse(matches[2]) + 1;
+ }
+
+ // Override Content-Length with the actual bytes sent.
+ response.headers.set(HttpHeaders.CONTENT_LENGTH, end - start);
+
+ // Set 'Partial Content' status code.
+ response.statusCode = HttpStatus.PARTIAL_CONTENT;
+ response.headers.set(HttpHeaders.CONTENT_RANGE,
+ "bytes $start-${end - 1}/$length");
+
+ // Pipe the 'range' of the file.
+ file.openRead(start, end)
+ .pipe(new _VirtualDirectoryFileStream(response, file.path))
+ .catchError((_) {});
+ return;
+ }
+ }
+
+ file.openRead()
+ .pipe(new _VirtualDirectoryFileStream(response, file.path))
+ .catchError((_) {});
+ });
+ }).catchError((_) {
+ response.close();
+ });
+ }
+
+ void _serveErrorPage(int error, HttpRequest request) {
+ var response = request.response;
+ response.statusCode = error;
+ if (_errorCallback != null) {
+ _errorCallback(request);
+ return;
+ }
+ // Default error page.
+ var path = request.uri.path;
+ var reason = response.reasonPhrase;
+ response.write(
+ '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\n');
+ response.writeln(
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');
+ response.writeln('<html xmlns="http://www.w3.org/1999/xhtml">');
+ response.writeln('<head>');
+ response.writeln('<title>$reason: $path</title>');
+ response.writeln('</head>');
+ response.writeln('<body>');
+ response.writeln('<h1>Error $error at \'$path\': $reason</h1>');
+ var server = response.headers.value(HttpHeaders.SERVER);
+ if (server != null) {
+ response.writeln(server);
+ }
+ response.writeln('</body>');
+ response.writeln('</html>');
+ response.close();
+ }
+}
+
+class _VirtualDirectoryFileStream extends StreamConsumer<List<int>> {
+ final HttpResponse response;
+ final String path;
+ var buffer = [];
+
+ _VirtualDirectoryFileStream(HttpResponse this.response, String this.path);
+
+ Future addStream(Stream<List<int>> stream) {
+ stream.listen(
+ (data) {
+ if (buffer == null) {
+ response.add(data);
+ return;
+ }
+ if (buffer.length == 0) {
+ if (data.length >= defaultMagicNumbersMaxLength) {
+ setMimeType(data);
+ response.add(data);
+ buffer = null;
+ } else {
+ buffer.addAll(data);
+ }
+ } else {
+ buffer.addAll(data);
+ if (buffer.length >= defaultMagicNumbersMaxLength) {
+ setMimeType(buffer);
+ response.add(buffer);
+ buffer = null;
+ }
+ }
+ },
+ onDone: () {
+ if (buffer != null) {
+ if (buffer.length == 0) {
+ setMimeType(null);
+ } else {
+ setMimeType(buffer);
+ response.add(buffer);
+ }
+ }
+ response.close();
+ },
+ onError: response.addError);
+ return response.done;
+ }
+
+ Future close() => new Future.value();
+
+ void setMimeType(var bytes) {
+ var mimeType = lookupMimeType(path, headerBytes: bytes);
+ if (mimeType != null) {
+ response.headers.contentType = ContentType.parse(mimeType);
+ }
+ }
+}
diff --git a/pkg/http_server/lib/src/virtual_host.dart b/pkg/http_server/lib/src/virtual_host.dart
new file mode 100644
index 0000000..4c67eca
--- /dev/null
+++ b/pkg/http_server/lib/src/virtual_host.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of http_server;
+
+
+/**
+ * The [VirtualHost] class is a utility class for handling multiple hosts on
+ * multiple sources, by using a named-based approach.
+ */
+abstract class VirtualHost {
+ /**
+ * Get the [Stream] of [HttpRequest]s, not matching any hosts. If unused, the
+ * default implementation will result in a [HttpHeaders.FORBIDDEN] response.
+ */
+ Stream<HttpRequest> get unhandled;
+
+ /**
+ * Construct a new [VirtualHost].
+ *
+ * The optional [source] is a shortcut for calling [addSource].
+ *
+ * Example of usage:
+ *
+ * HttpServer.bind(..., 80).then((server) {
+ * var virtualHost = new VirtualHost(server);
+ * virtualServer.addHost('static.myserver.com')
+ * .listen(...);
+ * virtualServer.addHost('cache.myserver.com')
+ * .listen(...);
+ * })
+ */
+ factory VirtualHost([Stream<HttpRequest> source]) => new _VirtualHost(source);
+
+ /**
+ * Provide another source of [HttpRequest]s in the form of a [Stream].
+ */
+ void addSource(Stream<HttpRequest> source);
+
+
+ /**
+ * Add a host to the [VirtualHost] instance. The host can be either a specific
+ * domain (`my.domain.name`) or a wildcard-based domain name
+ * (`*.domain.name`). The former will only match the specific domain name
+ * while the latter will match any series of sub-domains.
+ *
+ * If both `my.domain.name` and `*.domain.name` is specified, the most
+ * qualified will take precedence, `my.domain.name` in this case.
+ */
+ Stream<HttpRequest> addHost(String host);
+}
+
+
+class _VirtualHostDomain {
+ StreamController<HttpRequest> any;
+ StreamController<HttpRequest> exact;
+ Map<String, _VirtualHostDomain> subDomains = {};
+}
+
+
+class _VirtualHost implements VirtualHost {
+ final _VirtualHostDomain _topDomain = new _VirtualHostDomain();
+ StreamController<HttpRequest> _unhandledController;
+
+ Stream<HttpRequest> get unhandled {
+ if (_unhandledController == null) {
+ _unhandledController = new StreamController<HttpRequest>();
+ }
+ return _unhandledController.stream;
+ }
+
+ _VirtualHost([Stream<HttpRequest> source]) {
+ if (source != null) addSource(source);
+ }
+
+ void addSource(Stream<HttpRequest> source) {
+ source.listen((request) {
+ var host = request.headers.host;
+ if (host == null) {
+ _unhandled(request);
+ return;
+ }
+ var domains = host.split('.');
+ var current = _topDomain;
+ var any;
+ for (var i = domains.length - 1; i >= 0; i--) {
+ if (current.any != null) any = current.any;
+ if (i == 0) {
+ var last = current.subDomains[domains[i]];
+ if (last != null && last.exact != null) {
+ last.exact.add(request);
+ return;
+ }
+ } else {
+ if (!current.subDomains.containsKey(domains[i])) {
+ break;
+ }
+ current = current.subDomains[domains[i]];
+ }
+ }
+ if (any != null) {
+ any.add(request);
+ return;
+ }
+ _unhandled(request);
+ });
+ }
+
+ Stream<HttpRequest> addHost(String host) {
+ if (host.lastIndexOf('*') > 0) {
+ throw new ArgumentError(
+ 'Wildcards are only allowed in the beginning of a host');
+ }
+ var controller = new StreamController<HttpRequest>();
+ var domains = host.split('.');
+ var current = _topDomain;
+ for (var i = domains.length - 1; i >= 0; i--) {
+ if (domains[i] == '*') {
+ if (current.any != null) {
+ throw new ArgumentError('Host is already provided');
+ }
+ current.any = controller;
+ } else {
+ if (!current.subDomains.containsKey(domains[i])) {
+ current.subDomains[domains[i]] = new _VirtualHostDomain();
+ }
+ if (i > 0) {
+ current = current.subDomains[domains[i]];
+ } else {
+ if (current.subDomains[domains[i]].exact != null) {
+ throw new ArgumentError('Host is already provided');
+ }
+ current.subDomains[domains[i]].exact = controller;
+ }
+ }
+ }
+ return controller.stream;
+ }
+
+ void _unhandled(HttpRequest request) {
+ if (_unhandledController != null) {
+ _unhandledController.add(request);
+ return;
+ }
+ request.response.statusCode = HttpStatus.FORBIDDEN;
+ request.response.close();
+ }
+}
diff --git a/pkg/http_server/pubspec.yaml b/pkg/http_server/pubspec.yaml
new file mode 100644
index 0000000..3f29100
--- /dev/null
+++ b/pkg/http_server/pubspec.yaml
@@ -0,0 +1,7 @@
+name: http_server
+author: "Dart Team <misc@dartlang.org>"
+homepage: http://www.dartlang.org
+description: >
+ Library of HTTP server classes.
+dependencies:
+ mime: any
diff --git a/pkg/http_server/test/pkcert/README b/pkg/http_server/test/pkcert/README
new file mode 100644
index 0000000..fe764a9
--- /dev/null
+++ b/pkg/http_server/test/pkcert/README
@@ -0,0 +1,16 @@
+This is a certificate database used by Dart for testing purposes.
+
+It is created as a certificate database by NSS (Network Security Services),
+a library from Mozilla, using the certutil tool. It uses a cert9.db file,
+rather than a cert8.db file, so the database directory must be specified with
+"sql:" in front of the directory path, or the environment variable
+NSS_DEFAULT_DB_TYPE must be set to "sql".
+
+The password for the key database is "dartdart".
+
+The database contains a root certificate from Equifax, used to verify the
+client https connection to www.google.dk. It contains a self-signed
+certificate for a local certificate authority myauthority_cert, and a
+server certificate for localhost called localhost_cert, signed by
+myauthority_cert. It contains the key for localhost_cert, but
+not the key for myauthority_cert.
diff --git a/pkg/http_server/test/pkcert/cert9.db b/pkg/http_server/test/pkcert/cert9.db
new file mode 100644
index 0000000..497fca6
--- /dev/null
+++ b/pkg/http_server/test/pkcert/cert9.db
Binary files differ
diff --git a/pkg/http_server/test/pkcert/key4.db b/pkg/http_server/test/pkcert/key4.db
new file mode 100644
index 0000000..fc06432
--- /dev/null
+++ b/pkg/http_server/test/pkcert/key4.db
Binary files differ
diff --git a/pkg/http_server/test/utils.dart b/pkg/http_server/test/utils.dart
new file mode 100644
index 0000000..fb8e037
--- /dev/null
+++ b/pkg/http_server/test/utils.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library utils;
+
+import 'dart:async';
+import 'dart:io';
+
+
+Future<int> getStatusCode(int port,
+ String path,
+ {String host,
+ bool secure: false,
+ DateTime ifModifiedSince}) {
+ var uri = (secure ?
+ new Uri.https('localhost:$port', path) :
+ new Uri.http('localhost:$port', path));
+ return new HttpClient().getUrl(uri)
+ .then((request) {
+ if (host != null) request.headers.host = host;
+ if (ifModifiedSince != null) {
+ request.headers.ifModifiedSince = ifModifiedSince;
+ }
+ return request.close();
+ })
+ .then((response) => response.drain().then(
+ (_) => response.statusCode));
+}
+
+
+Future<HttpHeaders> getHeaders(int port, String path) {
+ return new HttpClient().get('localhost', port, path)
+ .then((request) => request.close())
+ .then((response) => response.drain().then(
+ (_) => response.headers));
+}
+
+
+Future<String> getAsString(int port, String path) {
+ return new HttpClient().get('localhost', port, path)
+ .then((request) => request.close())
+ .then((response) => StringDecoder.decode(response));
+}
+
+
+const CERTIFICATE = "localhost_cert";
+
+
+setupSecure() {
+ Path scriptDir = new Path(new Options().script).directoryPath;
+ Path certificateDatabase = scriptDir.append('pkcert');
+ SecureSocket.initialize(database: certificateDatabase.toNativePath(),
+ password: 'dartdart');
+}
diff --git a/pkg/http_server/test/virtual_directory_test.dart b/pkg/http_server/test/virtual_directory_test.dart
new file mode 100644
index 0000000..1c579da
--- /dev/null
+++ b/pkg/http_server/test/virtual_directory_test.dart
@@ -0,0 +1,367 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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:async';
+import 'dart:io';
+
+import "package:unittest/unittest.dart";
+import "package:http_server/http_server.dart";
+
+import 'utils.dart';
+
+
+void main() {
+ group('serve-root', () {
+ test('dir-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync();
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+
+ test('dir-not-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ dir.deleteSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/')
+ .whenComplete(() {
+ server.close();
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+ });
+
+ group('serve-file', () {
+ group('top-level', () {
+ test('file-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var file = new File('${dir.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.OK)));
+ });
+
+ test('file-not-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync();
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+ });
+
+ group('in-dir', () {
+ test('file-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var dir2 = new Directory('${dir.path}/dir')..createSync();
+ var file = new File('${dir2.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/dir/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.OK)));
+ });
+
+ test('file-not-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var dir2 = new Directory('${dir.path}/dir')..createSync();
+ var file = new File('${dir.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/dir/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+ });
+ });
+
+ group('links', () {
+ if (!Platform.isWindows) {
+ group('follow-links', () {
+ test('dir-link', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var dir2 = new Directory('${dir.path}/dir2')..createSync();
+ var link = new Link('${dir.path}/dir3')..createSync('dir2');
+ var file = new File('${dir2.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+ virDir.followLinks = true;
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/dir3/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.OK)));
+ });
+
+ test('root-link', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var link = new Link('${dir.path}/dir3')..createSync('.');
+ var file = new File('${dir.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+ virDir.followLinks = true;
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/dir3/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.OK)));
+ });
+
+ group('bad-links', () {
+ test('absolute-link', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var file = new File('${dir.path}/file')..createSync();
+ var link = new Link('${dir.path}/dir3')
+ ..createSync('${dir.path}/file');
+ var virDir = new VirtualDirectory(dir.path);
+ virDir.followLinks = true;
+
+ virDir.serve(server);
+
+ return new HttpClient().get('localhost',
+ server.port,
+ '/dir3/file')
+ .then((request) => request.close())
+ .then((response) => response.drain().then(
+ (_) => response.statusCode))
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+
+ test('relative-parent-link', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var name = new Path(dir.path).filename;
+ var file = new File('${dir.path}/file')..createSync();
+ var link = new Link('${dir.path}/dir3')
+ ..createSync('../$name/file');
+ var virDir = new VirtualDirectory(dir.path);
+ virDir.followLinks = true;
+
+ virDir.serve(server);
+
+ return new HttpClient().get('localhost',
+ server.port,
+ '/dir3/file')
+ .then((request) => request.close())
+ .then((response) => response.drain().then(
+ (_) => response.statusCode))
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+ });
+ });
+
+ group('not-follow-links', () {
+ test('dir-link', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var dir2 = new Directory('${dir.path}/dir2')..createSync();
+ var link = new Link('${dir.path}/dir3')..createSync('dir2');
+ var file = new File('${dir2.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+ virDir.followLinks = false;
+
+ virDir.serve(server);
+
+ return getStatusCode(server.port, '/dir3/file')
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.NOT_FOUND)));
+ });
+ });
+ }
+ });
+
+ group('last-modified', () {
+ group('file', () {
+ test('file-exists', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var file = new File('${dir.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getHeaders(server.port, '/file')
+ .then((headers) {
+ expect(headers.value(HttpHeaders.LAST_MODIFIED), isNotNull);
+ return HttpDate.parse(
+ headers.value(HttpHeaders.LAST_MODIFIED));
+ })
+ .then((lastModified) {
+ return getStatusCode(
+ server.port, '/file', ifModifiedSince: lastModified);
+ })
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.NOT_MODIFIED)));
+ });
+
+ test('file-changes', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var file = new File('${dir.path}/file')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getHeaders(server.port, '/file')
+ .then((headers) {
+ expect(headers.value(HttpHeaders.LAST_MODIFIED), isNotNull);
+ return HttpDate.parse(
+ headers.value(HttpHeaders.LAST_MODIFIED));
+ })
+ .then((lastModified) {
+ // Fake file changed by moving date back in time.
+ lastModified = lastModified.subtract(
+ const Duration(seconds: 10));
+ return getStatusCode(
+ server.port, '/file', ifModifiedSince: lastModified);
+ })
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals(HttpStatus.OK)));
+ });
+ });
+ });
+
+ group('content-type', () {
+ group('mime-type', () {
+ test('from-path', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var file = new File('${dir.path}/file.jpg')..createSync();
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getHeaders(server.port, '/file.jpg')
+ .then((headers) => headers.contentType.toString())
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals('image/jpeg')));
+ });
+
+ test('from-magic-number', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var file = new File('${dir.path}/file.jpg')..createSync();
+ file.writeAsBytesSync(
+ [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
+ var virDir = new VirtualDirectory(dir.path);
+
+ virDir.serve(server);
+
+ return getHeaders(server.port, '/file.jpg')
+ .then((headers) => headers.contentType.toString())
+ .whenComplete(() {
+ server.close();
+ dir.deleteSync(recursive: true);
+ });
+ }), completion(equals('image/png')));
+ });
+ });
+ });
+
+ group('error-page', () {
+ test('default', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var virDir = new VirtualDirectory(dir.path);
+ dir.deleteSync();
+
+ virDir.serve(server);
+
+ return getAsString(server.port, '/')
+ .whenComplete(() {
+ server.close();
+ });
+ }), completion(matches(new RegExp('404.*Not Found'))));
+ });
+
+ test('custom', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var dir = new Directory('').createTempSync();
+ var virDir = new VirtualDirectory(dir.path);
+ dir.deleteSync();
+
+ virDir.setErrorPageHandler((request) {
+ request.response.write('my-page ');
+ request.response.write(request.response.statusCode);
+ request.response.close();
+ });
+ virDir.serve(server);
+
+ return getAsString(server.port, '/')
+ .whenComplete(() {
+ server.close();
+ });
+ }), completion(equals('my-page 404')));
+ });
+ });
+}
+
diff --git a/pkg/http_server/test/virtual_host_test.dart b/pkg/http_server/test/virtual_host_test.dart
new file mode 100644
index 0000000..a08e793
--- /dev/null
+++ b/pkg/http_server/test/virtual_host_test.dart
@@ -0,0 +1,181 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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:async';
+import 'dart:io';
+
+import "package:unittest/unittest.dart";
+import "package:http_server/http_server.dart";
+
+import 'utils.dart';
+
+void main() {
+ setupSecure();
+
+ test('empty-host', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ return getStatusCode(server.port, '/')
+ .whenComplete(server.close);
+ }), completion(equals(HttpStatus.FORBIDDEN)));
+ });
+
+ test('empty-host-unhandled', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.unhandled.first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return getStatusCode(server.port, '/')
+ .whenComplete(server.close);
+ }), completion(equals(HttpStatus.OK)));
+ });
+
+ test('single-host', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.addHost('*.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return getStatusCode(server.port, '/', host: 'my.host.com')
+ .whenComplete(server.close);
+ }), completion(equals(HttpStatus.OK)));
+ });
+
+ test('multiple-host', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.addHost('*.host1.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.host2.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.host3.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return Future.wait([
+ getStatusCode(server.port, '/', host: 'my.host1.com'),
+ getStatusCode(server.port, '/', host: 'my.host2.com'),
+ getStatusCode(server.port, '/', host: 'my.host3.com')])
+ .whenComplete(server.close);
+ }), completion(equals([HttpStatus.OK, HttpStatus.OK, HttpStatus.OK])));
+ });
+
+ test('multiple-source-https', () {
+ expect(Future.wait([
+ HttpServer.bind('localhost', 0),
+ HttpServer.bindSecure('localhost', 0, certificateName: CERTIFICATE)])
+ .then((servers) {
+ var virHost = new VirtualHost();
+ virHost.addSource(servers[0]);
+ virHost.addSource(servers[1]);
+ virHost.unhandled.listen((request) {
+ request.response.close();
+ });
+ return Future.wait([
+ getStatusCode(servers[0].port, '/', host: 'myhost1.com'),
+ getStatusCode(
+ servers[1].port, '/', host: 'myhost2.com', secure: true)])
+ .whenComplete(() => servers.forEach((s) => s.close()));
+ }), completion(equals([HttpStatus.OK, HttpStatus.OK])));
+ });
+
+ group('domain', () {
+ test('specific-sub-domain', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.addHost('my1.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('my2.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('my3.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return Future.wait([
+ getStatusCode(server.port, '/', host: 'my1.host.com'),
+ getStatusCode(server.port, '/', host: 'my2.host.com'),
+ getStatusCode(server.port, '/', host: 'my3.host.com')])
+ .whenComplete(server.close);
+ }), completion(equals([HttpStatus.OK, HttpStatus.OK, HttpStatus.OK])));
+ });
+
+ test('wildcard-sub-domain', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.addHost('*.host1.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.host2.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.host3.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return Future.wait([
+ getStatusCode(server.port, '/', host: 'my.host1.com'),
+ getStatusCode(server.port, '/', host: 'my.host2.com'),
+ getStatusCode(server.port, '/', host: 'my.host3.com')])
+ .whenComplete(server.close);
+ }), completion(equals([HttpStatus.OK, HttpStatus.OK, HttpStatus.OK])));
+ });
+
+ test('mix-sub-domain', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.addHost('my1.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('my2.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return Future.wait([
+ getStatusCode(server.port, '/', host: 'my1.host.com'),
+ getStatusCode(server.port, '/', host: 'my2.host.com'),
+ getStatusCode(server.port, '/', host: 'my3.host.com')])
+ .whenComplete(server.close);
+ }), completion(equals([HttpStatus.OK, HttpStatus.OK, HttpStatus.OK])));
+ });
+
+
+ test('wildcard', () {
+ expect(HttpServer.bind('localhost', 0).then((server) {
+ var virHost = new VirtualHost(server);
+ expect(virHost.addHost('*').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ expect(virHost.addHost('*.host.com').first.then((request) {
+ request.response.close();
+ }), completion(isNull));
+ return Future.wait([
+ getStatusCode(server.port, '/', host: 'some.host.dk'),
+ getStatusCode(server.port, '/', host: 'my.host2.com'),
+ getStatusCode(server.port, '/', host: 'long.sub.of.host.com')])
+ .whenComplete(server.close);
+ }), completion(equals([HttpStatus.OK, HttpStatus.OK, HttpStatus.OK])));
+ });
+
+ test('duplicate-domain', () {
+ var virHost = new VirtualHost();
+ virHost.addHost('my1.host.com');
+ expect(() => (virHost.addHost('my1.host.com')), throwsArgumentError);
+ virHost.addHost('*.host.com');
+ expect(() => (virHost.addHost('*.host.com')), throwsArgumentError);
+ virHost.addHost('my2.host.com');
+ virHost.addHost('my3.host.com');
+ virHost.addHost('*.com');
+ virHost.addHost('*');
+ expect(() => (virHost.addHost('*')), throwsArgumentError);
+ });
+ });
+}
+
diff --git a/pkg/intl/lib/extract_messages.dart b/pkg/intl/lib/extract_messages.dart
index fc8bd09..1ca9e13 100755
--- a/pkg/intl/lib/extract_messages.dart
+++ b/pkg/intl/lib/extract_messages.dart
@@ -201,9 +201,9 @@
void reportErrorLocation(ASTNode node) {
if (origin != null) print(" from $origin");
- LineInfo info = root.lineInfo;
+ var info = root.lineInfo;
if (info != null) {
- LineInfo_Location line = info.getLocation(node.offset);
+ var line = info.getLocation(node.offset);
print(" line: ${line.lineNumber}, column: ${line.columnNumber}");
}
}
diff --git a/pkg/intl/lib/generate_localized.dart b/pkg/intl/lib/generate_localized.dart
index c40d1f6..f6a4225 100644
--- a/pkg/intl/lib/generate_localized.dart
+++ b/pkg/intl/lib/generate_localized.dart
@@ -86,22 +86,22 @@
var result = new StringBuffer();
locale = new IntlMessage().escapeAndValidate(locale, locale);
result.write(prologue(locale));
- for (var each in translations) {
- var message = each.originalMessage;
- if (each.message != null) {
- message.addTranslation(locale, each.message);
- }
+ // Exclude messages with no translation and translations with no matching
+ // original message (e.g. if we're using some messages from a larger catalog)
+ var usableTranslations = translations.where(
+ (each) => each.originalMessage != null && each.message != null).toList();
+ for (var each in usableTranslations) {
+ each.originalMessage.addTranslation(locale, each.message);
}
- var sorted = translations.where((each) => each.message != null).toList();
- sorted.sort((a, b) =>
+ usableTranslations.sort((a, b) =>
a.originalMessage.name.compareTo(b.originalMessage.name));
- for (var each in sorted) {
+ for (var each in usableTranslations) {
result.write(" ");
result.write(each.originalMessage.toCode(locale));
result.write("\n\n");
}
result.write("\n final messages = const {\n");
- var entries = sorted
+ var entries = usableTranslations
.map((translation) => translation.originalMessage.name)
.map((name) => " \"$name\" : $name");
result.write(entries.join(",\n"));
diff --git a/pkg/intl/test/intl_message_basic_example_test.dart b/pkg/intl/test/intl_message_basic_example_test.dart
index d89ccd8..e9281ee 100644
--- a/pkg/intl/test/intl_message_basic_example_test.dart
+++ b/pkg/intl/test/intl_message_basic_example_test.dart
@@ -12,30 +12,28 @@
import 'package:unittest/unittest.dart';
import 'dart:async';
-List list;
-
main() {
- list = [];
- setup(runAllTests, addToList);
-}
+ var list = [];
+ var waitForIt = new Completer();
-var waitForIt = new Completer();
+ addToList(x) {
+ list.add(x);
+ if (list.length == 4) {
+ waitForIt.complete(list);
+ }
+ }
-addToList(x) {
- list.add(x);
- if (list.length == 4) waitForIt.complete(list);
-}
-
-runAllTests(_) {
- setup(runProgram, addToList);
- waitForIt.future.then(actuallyRunTheTests);
-}
-
-actuallyRunTheTests(_) {
test('Verify basic example printing localized messages', () {
- expect(list[0], "Ran at 00:00:00 on Thursday, January 1, 1970");
- expect(list[1], "Ausgedruckt am 00:00:00 am Donnerstag, 1. Januar 1970.");
- expect(list[2], "วิ่ง 0:00:00 on วันพฤหัสบดี 1 มกราคม 1970.");
- expect(list[3], "วิ่ง now on today.");
+ runAllTests(_) {
+ setup(expectAsync1(runProgram), addToList);
+ }
+ setup(expectAsync1(runAllTests), addToList);
+ waitForIt.future.then(expectAsync1((_) {
+ expect(list[0], "Ran at 00:00:00 on Thursday, January 1, 1970");
+ expect(list[1], "Ausgedruckt am 00:00:00 am Donnerstag, 1. Januar 1970.");
+ expect(list[2], "วิ่ง 0:00:00 on วันพฤหัสบดี 1 มกราคม 1970.");
+ expect(list[3], "วิ่ง now on today.");
+ }));
});
}
+
diff --git a/pkg/intl/test/message_extraction/extract_to_json.dart b/pkg/intl/test/message_extraction/extract_to_json.dart
index 5b6f316..ce5c907 100644
--- a/pkg/intl/test/message_extraction/extract_to_json.dart
+++ b/pkg/intl/test/message_extraction/extract_to_json.dart
@@ -34,9 +34,8 @@
parser.addFlag("suppress-warnings", defaultsTo: false,
callback: (x) => suppressWarnings = x);
- void setTargetDir(value) => targetDir = value;
-
- parser.addOption("output-dir", defaultsTo: '.', callback: setTargetDir);
+ parser.addOption("output-dir", defaultsTo: '.',
+ callback: (value) => targetDir = value);
parser.parse(args);
if (args.length == 0) {
print('Usage: extract_to_json [--output-dir=<dir>] [files.dart]');
diff --git a/pkg/intl/test/message_extraction/generate_from_json.dart b/pkg/intl/test/message_extraction/generate_from_json.dart
index 0759507..c991a44 100644
--- a/pkg/intl/test/message_extraction/generate_from_json.dart
+++ b/pkg/intl/test/message_extraction/generate_from_json.dart
@@ -43,8 +43,8 @@
parser.parse(args);
if (args.length == 0) {
print('Usage: generate_from_json [--output-dir=<dir>]'
- ' [generated-file-prefix=<prefix>] file1.dart file2.dart ...'
- ' outputFile.json');
+ ' [--generated-file-prefix=<prefix>] file1.dart file2.dart ...'
+ ' translation1.json translation2.json ...');
exit(0);
}
diff --git a/pkg/intl/test/message_extraction/message_extraction_test.dart b/pkg/intl/test/message_extraction/message_extraction_test.dart
index 85e0323..c8bd55ab 100644
--- a/pkg/intl/test/message_extraction/message_extraction_test.dart
+++ b/pkg/intl/test/message_extraction/message_extraction_test.dart
@@ -10,7 +10,7 @@
import 'package:pathos/path.dart' as path;
import '../data_directory.dart';
-final dart = new Options().executable;
+final dart = Platform.executable;
// TODO(alanknight): We have no way of knowing what the package-root is,
// so when we're running under the test framework, which sets the
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart
index b29f076c..3c841dc 100644
--- a/pkg/logging/lib/logging.dart
+++ b/pkg/logging/lib/logging.dart
@@ -153,10 +153,9 @@
* [Level.INFO], [Level.WARNING], etc) you can use their specialized methods
* instead (e.g. [info], [warning], etc).
*/
- // TODO(sigmund): add support for logging exceptions.
- void log(Level logLevel, String message) {
+ void log(Level logLevel, String message, [exception]) {
if (isLoggable(logLevel)) {
- var record = new LogRecord(logLevel, message, fullName);
+ var record = new LogRecord(logLevel, message, fullName, exception);
if (hierarchicalLoggingEnabled) {
var target = this;
while (target != null) {
@@ -170,28 +169,36 @@
}
/** Log message at level [Level.FINEST]. */
- void finest(String message) => log(Level.FINEST, message);
+ void finest(String message, [exception]) =>
+ log(Level.FINEST, message, exception);
/** Log message at level [Level.FINER]. */
- void finer(String message) => log(Level.FINER, message);
+ void finer(String message, [exception]) =>
+ log(Level.FINER, message, exception);
/** Log message at level [Level.FINE]. */
- void fine(String message) => log(Level.FINE, message);
+ void fine(String message, [exception]) =>
+ log(Level.FINE, message, exception);
/** Log message at level [Level.CONFIG]. */
- void config(String message) => log(Level.CONFIG, message);
+ void config(String message, [exception]) =>
+ log(Level.CONFIG, message, exception);
/** Log message at level [Level.INFO]. */
- void info(String message) => log(Level.INFO, message);
+ void info(String message, [exception]) =>
+ log(Level.INFO, message, exception);
/** Log message at level [Level.WARNING]. */
- void warning(String message) => log(Level.WARNING, message);
+ void warning(String message, [exception]) =>
+ log(Level.WARNING, message, exception);
/** Log message at level [Level.SEVERE]. */
- void severe(String message) => log(Level.SEVERE, message);
+ void severe(String message, [exception]) =>
+ log(Level.SEVERE, message, exception);
/** Log message at level [Level.SHOUT]. */
- void shout(String message) => log(Level.SHOUT, message);
+ void shout(String message, [exception]) =>
+ log(Level.SHOUT, message, exception);
Stream<LogRecord> _getStream() {
if (hierarchicalLoggingEnabled || parent == null) {
@@ -308,14 +315,9 @@
static int _nextNumber = 0;
/** Associated exception (if any) when recording errors messages. */
- Exception exception;
+ var exception;
- /** Associated exception message (if any) when recording errors messages. */
- String exceptionText;
-
- LogRecord(
- this.level, this.message, this.loggerName,
- [time, this.exception, this.exceptionText]) :
- this.time = (time == null) ? new DateTime.now() : time,
- this.sequenceNumber = LogRecord._nextNumber++;
+ LogRecord(this.level, this.message, this.loggerName, [this.exception])
+ : time = new DateTime.now(),
+ sequenceNumber = LogRecord._nextNumber++;
}
diff --git a/pkg/logging/test/logging_test.dart b/pkg/logging/test/logging_test.dart
index 1af342f..a631e8c 100644
--- a/pkg/logging/test/logging_test.dart
+++ b/pkg/logging/test/logging_test.dart
@@ -228,6 +228,49 @@
'SHOUT: 8']));
});
+ test('logging methods store exception', () {
+ root.level = Level.ALL;
+ var rootMessages = [];
+ root.onRecord.listen((r) {
+ rootMessages.add('${r.level}: ${r.message} ${r.exception}');
+ });
+
+ root.finest('1');
+ root.finer('2');
+ root.fine('3');
+ root.config('4');
+ root.info('5');
+ root.warning('6');
+ root.severe('7');
+ root.shout('8');
+ root.finest('1', 'a');
+ root.finer('2', 'b');
+ root.fine('3', ['c']);
+ root.config('4', 'd');
+ root.info('5', 'e');
+ root.warning('6', 'f');
+ root.severe('7', 'g');
+ root.shout('8', 'h');
+
+ expect(rootMessages, equals([
+ 'FINEST: 1 null',
+ 'FINER: 2 null',
+ 'FINE: 3 null',
+ 'CONFIG: 4 null',
+ 'INFO: 5 null',
+ 'WARNING: 6 null',
+ 'SEVERE: 7 null',
+ 'SHOUT: 8 null',
+ 'FINEST: 1 a',
+ 'FINER: 2 b',
+ 'FINE: 3 [c]',
+ 'CONFIG: 4 d',
+ 'INFO: 5 e',
+ 'WARNING: 6 f',
+ 'SEVERE: 7 g',
+ 'SHOUT: 8 h']));
+ });
+
test('message logging - no hierarchy', () {
root.level = Level.WARNING;
var rootMessages = [];
diff --git a/pkg/mdv_observe/lib/src/observable_map.dart b/pkg/mdv_observe/lib/src/observable_map.dart
index ce1e48f..3ce2d82 100644
--- a/pkg/mdv_observe/lib/src/observable_map.dart
+++ b/pkg/mdv_observe/lib/src/observable_map.dart
@@ -94,11 +94,11 @@
bool get isNotEmpty => !isEmpty;
- bool containsValue(V value) => _map.containsValue(value);
+ bool containsValue(Object value) => _map.containsValue(value);
- bool containsKey(K key) => _map.containsKey(key);
+ bool containsKey(Object key) => _map.containsKey(key);
- V operator [](K key) => _map[key];
+ V operator [](Object key) => _map[key];
void operator []=(K key, V value) {
int len = _map.length;
@@ -124,7 +124,7 @@
return result;
}
- V remove(K key) {
+ V remove(Object key) {
int len = _map.length;
V result = _map.remove(key);
if (hasObservers && len != _map.length) {
diff --git a/pkg/mime/lib/mime.dart b/pkg/mime/lib/mime.dart
new file mode 100644
index 0000000..0943de8
--- /dev/null
+++ b/pkg/mime/lib/mime.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library mime;
+
+part 'src/mime_type.dart';
+part 'src/extension_map.dart';
+part 'src/magic_number.dart';
diff --git a/pkg/mime/lib/src/extension_map.dart b/pkg/mime/lib/src/extension_map.dart
new file mode 100644
index 0000000..19286bb
--- /dev/null
+++ b/pkg/mime/lib/src/extension_map.dart
@@ -0,0 +1,993 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of mime;
+
+
+// TODO(ajohnsen): Use sorted list and binary search?
+Map<String, String> _defaultExtensionMap = const <String, String>{
+'123':'application/vnd.lotus-1-2-3',
+'3dml':'text/vnd.in3d.3dml',
+'3ds':'image/x-3ds',
+'3g2':'video/3gpp2',
+'3gp':'video/3gpp',
+'7z':'application/x-7z-compressed',
+'aab':'application/x-authorware-bin',
+'aac':'audio/x-aac',
+'aam':'application/x-authorware-map',
+'aas':'application/x-authorware-seg',
+'abw':'application/x-abiword',
+'ac':'application/pkix-attr-cert',
+'acc':'application/vnd.americandynamics.acc',
+'ace':'application/x-ace-compressed',
+'acu':'application/vnd.acucobol',
+'acutc':'application/vnd.acucorp',
+'adp':'audio/adpcm',
+'aep':'application/vnd.audiograph',
+'afm':'application/x-font-type1',
+'afp':'application/vnd.ibm.modcap',
+'ahead':'application/vnd.ahead.space',
+'ai':'application/postscript',
+'aif':'audio/x-aiff',
+'aifc':'audio/x-aiff',
+'aiff':'audio/x-aiff',
+'air':'application/vnd.adobe.air-application-installer-package+zip',
+'ait':'application/vnd.dvb.ait',
+'ami':'application/vnd.amiga.ami',
+'apk':'application/vnd.android.package-archive',
+'appcache':'text/cache-manifest',
+'application':'application/x-ms-application',
+'apr':'application/vnd.lotus-approach',
+'arc':'application/x-freearc',
+'asc':'application/pgp-signature',
+'asf':'video/x-ms-asf',
+'asm':'text/x-asm',
+'aso':'application/vnd.accpac.simply.aso',
+'asx':'video/x-ms-asf',
+'atc':'application/vnd.acucorp',
+'atom':'application/atom+xml',
+'atomcat':'application/atomcat+xml',
+'atomsvc':'application/atomsvc+xml',
+'atx':'application/vnd.antix.game-component',
+'au':'audio/basic',
+'avi':'video/x-msvideo',
+'aw':'application/applixware',
+'azf':'application/vnd.airzip.filesecure.azf',
+'azs':'application/vnd.airzip.filesecure.azs',
+'azw':'application/vnd.amazon.ebook',
+'bat':'application/x-msdownload',
+'bcpio':'application/x-bcpio',
+'bdf':'application/x-font-bdf',
+'bdm':'application/vnd.syncml.dm+wbxml',
+'bed':'application/vnd.realvnc.bed',
+'bh2':'application/vnd.fujitsu.oasysprs',
+'bin':'application/octet-stream',
+'blb':'application/x-blorb',
+'blorb':'application/x-blorb',
+'bmi':'application/vnd.bmi',
+'bmp':'image/bmp',
+'book':'application/vnd.framemaker',
+'box':'application/vnd.previewsystems.box',
+'boz':'application/x-bzip2',
+'bpk':'application/octet-stream',
+'btif':'image/prs.btif',
+'bz':'application/x-bzip',
+'bz2':'application/x-bzip2',
+'c':'text/x-c',
+'c11amc':'application/vnd.cluetrust.cartomobile-config',
+'c11amz':'application/vnd.cluetrust.cartomobile-config-pkg',
+'c4d':'application/vnd.clonk.c4group',
+'c4f':'application/vnd.clonk.c4group',
+'c4g':'application/vnd.clonk.c4group',
+'c4p':'application/vnd.clonk.c4group',
+'c4u':'application/vnd.clonk.c4group',
+'cab':'application/vnd.ms-cab-compressed',
+'caf':'audio/x-caf',
+'cap':'application/vnd.tcpdump.pcap',
+'car':'application/vnd.curl.car',
+'cat':'application/vnd.ms-pki.seccat',
+'cb7':'application/x-cbr',
+'cba':'application/x-cbr',
+'cbr':'application/x-cbr',
+'cbt':'application/x-cbr',
+'cbz':'application/x-cbr',
+'cc':'text/x-c',
+'cct':'application/x-director',
+'ccxml':'application/ccxml+xml',
+'cdbcmsg':'application/vnd.contact.cmsg',
+'cdf':'application/x-netcdf',
+'cdkey':'application/vnd.mediastation.cdkey',
+'cdmia':'application/cdmi-capability',
+'cdmic':'application/cdmi-container',
+'cdmid':'application/cdmi-domain',
+'cdmio':'application/cdmi-object',
+'cdmiq':'application/cdmi-queue',
+'cdx':'chemical/x-cdx',
+'cdxml':'application/vnd.chemdraw+xml',
+'cdy':'application/vnd.cinderella',
+'cer':'application/pkix-cert',
+'cfs':'application/x-cfs-compressed',
+'cgm':'image/cgm',
+'chat':'application/x-chat',
+'chm':'application/vnd.ms-htmlhelp',
+'chrt':'application/vnd.kde.kchart',
+'cif':'chemical/x-cif',
+'cii':'application/vnd.anser-web-certificate-issue-initiation',
+'cil':'application/vnd.ms-artgalry',
+'cla':'application/vnd.claymore',
+'class':'application/java-vm',
+'clkk':'application/vnd.crick.clicker.keyboard',
+'clkp':'application/vnd.crick.clicker.palette',
+'clkt':'application/vnd.crick.clicker.template',
+'clkw':'application/vnd.crick.clicker.wordbank',
+'clkx':'application/vnd.crick.clicker',
+'clp':'application/x-msclip',
+'cmc':'application/vnd.cosmocaller',
+'cmdf':'chemical/x-cmdf',
+'cml':'chemical/x-cml',
+'cmp':'application/vnd.yellowriver-custom-menu',
+'cmx':'image/x-cmx',
+'cod':'application/vnd.rim.cod',
+'com':'application/x-msdownload',
+'conf':'text/plain',
+'cpio':'application/x-cpio',
+'cpp':'text/x-c',
+'cpt':'application/mac-compactpro',
+'crd':'application/x-mscardfile',
+'crl':'application/pkix-crl',
+'crt':'application/x-x509-ca-cert',
+'cryptonote':'application/vnd.rig.cryptonote',
+'csh':'application/x-csh',
+'csml':'chemical/x-csml',
+'csp':'application/vnd.commonspace',
+'css':'text/css',
+'cst':'application/x-director',
+'csv':'text/csv',
+'cu':'application/cu-seeme',
+'curl':'text/vnd.curl',
+'cww':'application/prs.cww',
+'cxt':'application/x-director',
+'cxx':'text/x-c',
+'dae':'model/vnd.collada+xml',
+'daf':'application/vnd.mobius.daf',
+'dart':'application/dart',
+'dataless':'application/vnd.fdsn.seed',
+'davmount':'application/davmount+xml',
+'dbk':'application/docbook+xml',
+'dcr':'application/x-director',
+'dcurl':'text/vnd.curl.dcurl',
+'dd2':'application/vnd.oma.dd2+xml',
+'ddd':'application/vnd.fujixerox.ddd',
+'deb':'application/x-debian-package',
+'def':'text/plain',
+'deploy':'application/octet-stream',
+'der':'application/x-x509-ca-cert',
+'dfac':'application/vnd.dreamfactory',
+'dgc':'application/x-dgc-compressed',
+'dic':'text/x-c',
+'dir':'application/x-director',
+'dis':'application/vnd.mobius.dis',
+'dist':'application/octet-stream',
+'distz':'application/octet-stream',
+'djv':'image/vnd.djvu',
+'djvu':'image/vnd.djvu',
+'dll':'application/x-msdownload',
+'dmg':'application/x-apple-diskimage',
+'dmp':'application/vnd.tcpdump.pcap',
+'dms':'application/octet-stream',
+'dna':'application/vnd.dna',
+'doc':'application/msword',
+'docm':'application/vnd.ms-word.document.macroenabled.12',
+'docx':'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+'dot':'application/msword',
+'dotm':'application/vnd.ms-word.template.macroenabled.12',
+'dotx':'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+'dp':'application/vnd.osgi.dp',
+'dpg':'application/vnd.dpgraph',
+'dra':'audio/vnd.dra',
+'dsc':'text/prs.lines.tag',
+'dssc':'application/dssc+der',
+'dtb':'application/x-dtbook+xml',
+'dtd':'application/xml-dtd',
+'dts':'audio/vnd.dts',
+'dtshd':'audio/vnd.dts.hd',
+'dump':'application/octet-stream',
+'dvb':'video/vnd.dvb.file',
+'dvi':'application/x-dvi',
+'dwf':'model/vnd.dwf',
+'dwg':'image/vnd.dwg',
+'dxf':'image/vnd.dxf',
+'dxp':'application/vnd.spotfire.dxp',
+'dxr':'application/x-director',
+'ecelp4800':'audio/vnd.nuera.ecelp4800',
+'ecelp7470':'audio/vnd.nuera.ecelp7470',
+'ecelp9600':'audio/vnd.nuera.ecelp9600',
+'ecma':'application/ecmascript',
+'edm':'application/vnd.novadigm.edm',
+'edx':'application/vnd.novadigm.edx',
+'efif':'application/vnd.picsel',
+'ei6':'application/vnd.pg.osasli',
+'elc':'application/octet-stream',
+'emf':'application/x-msmetafile',
+'eml':'message/rfc822',
+'emma':'application/emma+xml',
+'emz':'application/x-msmetafile',
+'eol':'audio/vnd.digital-winds',
+'eot':'application/vnd.ms-fontobject',
+'eps':'application/postscript',
+'epub':'application/epub+zip',
+'es3':'application/vnd.eszigno3+xml',
+'esa':'application/vnd.osgi.subsystem',
+'esf':'application/vnd.epson.esf',
+'et3':'application/vnd.eszigno3+xml',
+'etx':'text/x-setext',
+'eva':'application/x-eva',
+'evy':'application/x-envoy',
+'exe':'application/x-msdownload',
+'exi':'application/exi',
+'ext':'application/vnd.novadigm.ext',
+'ez':'application/andrew-inset',
+'ez2':'application/vnd.ezpix-album',
+'ez3':'application/vnd.ezpix-package',
+'f':'text/x-fortran',
+'f4v':'video/x-f4v',
+'f77':'text/x-fortran',
+'f90':'text/x-fortran',
+'fbs':'image/vnd.fastbidsheet',
+'fcdt':'application/vnd.adobe.formscentral.fcdt',
+'fcs':'application/vnd.isac.fcs',
+'fdf':'application/vnd.fdf',
+'fe_launch':'application/vnd.denovo.fcselayout-link',
+'fg5':'application/vnd.fujitsu.oasysgp',
+'fgd':'application/x-director',
+'fh':'image/x-freehand',
+'fh4':'image/x-freehand',
+'fh5':'image/x-freehand',
+'fh7':'image/x-freehand',
+'fhc':'image/x-freehand',
+'fig':'application/x-xfig',
+'flac':'audio/x-flac',
+'fli':'video/x-fli',
+'flo':'application/vnd.micrografx.flo',
+'flv':'video/x-flv',
+'flw':'application/vnd.kde.kivio',
+'flx':'text/vnd.fmi.flexstor',
+'fly':'text/vnd.fly',
+'fm':'application/vnd.framemaker',
+'fnc':'application/vnd.frogans.fnc',
+'for':'text/x-fortran',
+'fpx':'image/vnd.fpx',
+'frame':'application/vnd.framemaker',
+'fsc':'application/vnd.fsc.weblaunch',
+'fst':'image/vnd.fst',
+'ftc':'application/vnd.fluxtime.clip',
+'fti':'application/vnd.anser-web-funds-transfer-initiation',
+'fvt':'video/vnd.fvt',
+'fxp':'application/vnd.adobe.fxp',
+'fxpl':'application/vnd.adobe.fxp',
+'fzs':'application/vnd.fuzzysheet',
+'g2w':'application/vnd.geoplan',
+'g3':'image/g3fax',
+'g3w':'application/vnd.geospace',
+'gac':'application/vnd.groove-account',
+'gam':'application/x-tads',
+'gbr':'application/rpki-ghostbusters',
+'gca':'application/x-gca-compressed',
+'gdl':'model/vnd.gdl',
+'geo':'application/vnd.dynageo',
+'gex':'application/vnd.geometry-explorer',
+'ggb':'application/vnd.geogebra.file',
+'ggt':'application/vnd.geogebra.tool',
+'ghf':'application/vnd.groove-help',
+'gif':'image/gif',
+'gim':'application/vnd.groove-identity-message',
+'gml':'application/gml+xml',
+'gmx':'application/vnd.gmx',
+'gnumeric':'application/x-gnumeric',
+'gph':'application/vnd.flographit',
+'gpx':'application/gpx+xml',
+'gqf':'application/vnd.grafeq',
+'gqs':'application/vnd.grafeq',
+'gram':'application/srgs',
+'gramps':'application/x-gramps-xml',
+'gre':'application/vnd.geometry-explorer',
+'grv':'application/vnd.groove-injector',
+'grxml':'application/srgs+xml',
+'gsf':'application/x-font-ghostscript',
+'gtar':'application/x-gtar',
+'gtm':'application/vnd.groove-tool-message',
+'gtw':'model/vnd.gtw',
+'gv':'text/vnd.graphviz',
+'gxf':'application/gxf',
+'gxt':'application/vnd.geonext',
+'h':'text/x-c',
+'h261':'video/h261',
+'h263':'video/h263',
+'h264':'video/h264',
+'hal':'application/vnd.hal+xml',
+'hbci':'application/vnd.hbci',
+'hdf':'application/x-hdf',
+'hh':'text/x-c',
+'hlp':'application/winhlp',
+'hpgl':'application/vnd.hp-hpgl',
+'hpid':'application/vnd.hp-hpid',
+'hps':'application/vnd.hp-hps',
+'hqx':'application/mac-binhex40',
+'htke':'application/vnd.kenameaapp',
+'htm':'text/html',
+'html':'text/html',
+'hvd':'application/vnd.yamaha.hv-dic',
+'hvp':'application/vnd.yamaha.hv-voice',
+'hvs':'application/vnd.yamaha.hv-script',
+'i2g':'application/vnd.intergeo',
+'icc':'application/vnd.iccprofile',
+'ice':'x-conference/x-cooltalk',
+'icm':'application/vnd.iccprofile',
+'ico':'image/x-icon',
+'ics':'text/calendar',
+'ief':'image/ief',
+'ifb':'text/calendar',
+'ifm':'application/vnd.shana.informed.formdata',
+'iges':'model/iges',
+'igl':'application/vnd.igloader',
+'igm':'application/vnd.insors.igm',
+'igs':'model/iges',
+'igx':'application/vnd.micrografx.igx',
+'iif':'application/vnd.shana.informed.interchange',
+'imp':'application/vnd.accpac.simply.imp',
+'ims':'application/vnd.ms-ims',
+'in':'text/plain',
+'ink':'application/inkml+xml',
+'inkml':'application/inkml+xml',
+'install':'application/x-install-instructions',
+'iota':'application/vnd.astraea-software.iota',
+'ipfix':'application/ipfix',
+'ipk':'application/vnd.shana.informed.package',
+'irm':'application/vnd.ibm.rights-management',
+'irp':'application/vnd.irepository.package+xml',
+'iso':'application/x-iso9660-image',
+'itp':'application/vnd.shana.informed.formtemplate',
+'ivp':'application/vnd.immervision-ivp',
+'ivu':'application/vnd.immervision-ivu',
+'jad':'text/vnd.sun.j2me.app-descriptor',
+'jam':'application/vnd.jam',
+'jar':'application/java-archive',
+'java':'text/x-java-source',
+'jisp':'application/vnd.jisp',
+'jlt':'application/vnd.hp-jlyt',
+'jnlp':'application/x-java-jnlp-file',
+'joda':'application/vnd.joost.joda-archive',
+'jpe':'image/jpeg',
+'jpeg':'image/jpeg',
+'jpg':'image/jpeg',
+'jpgm':'video/jpm',
+'jpgv':'video/jpeg',
+'jpm':'video/jpm',
+'js':'application/javascript',
+'json':'application/json',
+'jsonml':'application/jsonml+json',
+'kar':'audio/midi',
+'karbon':'application/vnd.kde.karbon',
+'kfo':'application/vnd.kde.kformula',
+'kia':'application/vnd.kidspiration',
+'kml':'application/vnd.google-earth.kml+xml',
+'kmz':'application/vnd.google-earth.kmz',
+'kne':'application/vnd.kinar',
+'knp':'application/vnd.kinar',
+'kon':'application/vnd.kde.kontour',
+'kpr':'application/vnd.kde.kpresenter',
+'kpt':'application/vnd.kde.kpresenter',
+'kpxx':'application/vnd.ds-keypoint',
+'ksp':'application/vnd.kde.kspread',
+'ktr':'application/vnd.kahootz',
+'ktx':'image/ktx',
+'ktz':'application/vnd.kahootz',
+'kwd':'application/vnd.kde.kword',
+'kwt':'application/vnd.kde.kword',
+'lasxml':'application/vnd.las.las+xml',
+'latex':'application/x-latex',
+'lbd':'application/vnd.llamagraphics.life-balance.desktop',
+'lbe':'application/vnd.llamagraphics.life-balance.exchange+xml',
+'les':'application/vnd.hhe.lesson-player',
+'lha':'application/x-lzh-compressed',
+'link66':'application/vnd.route66.link66+xml',
+'list':'text/plain',
+'list3820':'application/vnd.ibm.modcap',
+'listafp':'application/vnd.ibm.modcap',
+'lnk':'application/x-ms-shortcut',
+'log':'text/plain',
+'lostxml':'application/lost+xml',
+'lrf':'application/octet-stream',
+'lrm':'application/vnd.ms-lrm',
+'ltf':'application/vnd.frogans.ltf',
+'lvp':'audio/vnd.lucent.voice',
+'lwp':'application/vnd.lotus-wordpro',
+'lzh':'application/x-lzh-compressed',
+'m13':'application/x-msmediaview',
+'m14':'application/x-msmediaview',
+'m1v':'video/mpeg',
+'m21':'application/mp21',
+'m2a':'audio/mpeg',
+'m2v':'video/mpeg',
+'m3a':'audio/mpeg',
+'m3u':'audio/x-mpegurl',
+'m3u8':'application/vnd.apple.mpegurl',
+'m4u':'video/vnd.mpegurl',
+'m4v':'video/x-m4v',
+'ma':'application/mathematica',
+'mads':'application/mads+xml',
+'mag':'application/vnd.ecowin.chart',
+'maker':'application/vnd.framemaker',
+'man':'text/troff',
+'mar':'application/octet-stream',
+'mathml':'application/mathml+xml',
+'mb':'application/mathematica',
+'mbk':'application/vnd.mobius.mbk',
+'mbox':'application/mbox',
+'mc1':'application/vnd.medcalcdata',
+'mcd':'application/vnd.mcd',
+'mcurl':'text/vnd.curl.mcurl',
+'mdb':'application/x-msaccess',
+'mdi':'image/vnd.ms-modi',
+'me':'text/troff',
+'mesh':'model/mesh',
+'meta4':'application/metalink4+xml',
+'metalink':'application/metalink+xml',
+'mets':'application/mets+xml',
+'mfm':'application/vnd.mfmp',
+'mft':'application/rpki-manifest',
+'mgp':'application/vnd.osgeo.mapguide.package',
+'mgz':'application/vnd.proteus.magazine',
+'mid':'audio/midi',
+'midi':'audio/midi',
+'mie':'application/x-mie',
+'mif':'application/vnd.mif',
+'mime':'message/rfc822',
+'mj2':'video/mj2',
+'mjp2':'video/mj2',
+'mk3d':'video/x-matroska',
+'mka':'audio/x-matroska',
+'mks':'video/x-matroska',
+'mkv':'video/x-matroska',
+'mlp':'application/vnd.dolby.mlp',
+'mmd':'application/vnd.chipnuts.karaoke-mmd',
+'mmf':'application/vnd.smaf',
+'mmr':'image/vnd.fujixerox.edmics-mmr',
+'mng':'video/x-mng',
+'mny':'application/x-msmoney',
+'mobi':'application/x-mobipocket-ebook',
+'mods':'application/mods+xml',
+'mov':'video/quicktime',
+'movie':'video/x-sgi-movie',
+'mp2':'audio/mpeg',
+'mp21':'application/mp21',
+'mp2a':'audio/mpeg',
+'mp3':'audio/mpeg',
+'mp4':'video/mp4',
+'mp4a':'audio/mp4',
+'mp4s':'application/mp4',
+'mp4v':'video/mp4',
+'mpc':'application/vnd.mophun.certificate',
+'mpe':'video/mpeg',
+'mpeg':'video/mpeg',
+'mpg':'video/mpeg',
+'mpg4':'video/mp4',
+'mpga':'audio/mpeg',
+'mpkg':'application/vnd.apple.installer+xml',
+'mpm':'application/vnd.blueice.multipass',
+'mpn':'application/vnd.mophun.application',
+'mpp':'application/vnd.ms-project',
+'mpt':'application/vnd.ms-project',
+'mpy':'application/vnd.ibm.minipay',
+'mqy':'application/vnd.mobius.mqy',
+'mrc':'application/marc',
+'mrcx':'application/marcxml+xml',
+'ms':'text/troff',
+'mscml':'application/mediaservercontrol+xml',
+'mseed':'application/vnd.fdsn.mseed',
+'mseq':'application/vnd.mseq',
+'msf':'application/vnd.epson.msf',
+'msh':'model/mesh',
+'msi':'application/x-msdownload',
+'msl':'application/vnd.mobius.msl',
+'msty':'application/vnd.muvee.style',
+'mts':'model/vnd.mts',
+'mus':'application/vnd.musician',
+'musicxml':'application/vnd.recordare.musicxml+xml',
+'mvb':'application/x-msmediaview',
+'mwf':'application/vnd.mfer',
+'mxf':'application/mxf',
+'mxl':'application/vnd.recordare.musicxml',
+'mxml':'application/xv+xml',
+'mxs':'application/vnd.triscape.mxs',
+'mxu':'video/vnd.mpegurl',
+'n-gage':'application/vnd.nokia.n-gage.symbian.install',
+'n3':'text/n3',
+'nb':'application/mathematica',
+'nbp':'application/vnd.wolfram.player',
+'nc':'application/x-netcdf',
+'ncx':'application/x-dtbncx+xml',
+'nfo':'text/x-nfo',
+'ngdat':'application/vnd.nokia.n-gage.data',
+'nitf':'application/vnd.nitf',
+'nlu':'application/vnd.neurolanguage.nlu',
+'nml':'application/vnd.enliven',
+'nnd':'application/vnd.noblenet-directory',
+'nns':'application/vnd.noblenet-sealer',
+'nnw':'application/vnd.noblenet-web',
+'npx':'image/vnd.net-fpx',
+'nsc':'application/x-conference',
+'nsf':'application/vnd.lotus-notes',
+'ntf':'application/vnd.nitf',
+'nzb':'application/x-nzb',
+'oa2':'application/vnd.fujitsu.oasys2',
+'oa3':'application/vnd.fujitsu.oasys3',
+'oas':'application/vnd.fujitsu.oasys',
+'obd':'application/x-msbinder',
+'obj':'application/x-tgif',
+'oda':'application/oda',
+'odb':'application/vnd.oasis.opendocument.database',
+'odc':'application/vnd.oasis.opendocument.chart',
+'odf':'application/vnd.oasis.opendocument.formula',
+'odft':'application/vnd.oasis.opendocument.formula-template',
+'odg':'application/vnd.oasis.opendocument.graphics',
+'odi':'application/vnd.oasis.opendocument.image',
+'odm':'application/vnd.oasis.opendocument.text-master',
+'odp':'application/vnd.oasis.opendocument.presentation',
+'ods':'application/vnd.oasis.opendocument.spreadsheet',
+'odt':'application/vnd.oasis.opendocument.text',
+'oga':'audio/ogg',
+'ogg':'audio/ogg',
+'ogv':'video/ogg',
+'ogx':'application/ogg',
+'omdoc':'application/omdoc+xml',
+'onepkg':'application/onenote',
+'onetmp':'application/onenote',
+'onetoc':'application/onenote',
+'onetoc2':'application/onenote',
+'opf':'application/oebps-package+xml',
+'opml':'text/x-opml',
+'oprc':'application/vnd.palm',
+'org':'application/vnd.lotus-organizer',
+'osf':'application/vnd.yamaha.openscoreformat',
+'osfpvg':'application/vnd.yamaha.openscoreformat.osfpvg+xml',
+'otc':'application/vnd.oasis.opendocument.chart-template',
+'otf':'application/x-font-otf',
+'otg':'application/vnd.oasis.opendocument.graphics-template',
+'oth':'application/vnd.oasis.opendocument.text-web',
+'oti':'application/vnd.oasis.opendocument.image-template',
+'otp':'application/vnd.oasis.opendocument.presentation-template',
+'ots':'application/vnd.oasis.opendocument.spreadsheet-template',
+'ott':'application/vnd.oasis.opendocument.text-template',
+'oxps':'application/oxps',
+'oxt':'application/vnd.openofficeorg.extension',
+'p':'text/x-pascal',
+'p10':'application/pkcs10',
+'p12':'application/x-pkcs12',
+'p7b':'application/x-pkcs7-certificates',
+'p7c':'application/pkcs7-mime',
+'p7m':'application/pkcs7-mime',
+'p7r':'application/x-pkcs7-certreqresp',
+'p7s':'application/pkcs7-signature',
+'p8':'application/pkcs8',
+'pas':'text/x-pascal',
+'paw':'application/vnd.pawaafile',
+'pbd':'application/vnd.powerbuilder6',
+'pbm':'image/x-portable-bitmap',
+'pcap':'application/vnd.tcpdump.pcap',
+'pcf':'application/x-font-pcf',
+'pcl':'application/vnd.hp-pcl',
+'pclxl':'application/vnd.hp-pclxl',
+'pct':'image/x-pict',
+'pcurl':'application/vnd.curl.pcurl',
+'pcx':'image/x-pcx',
+'pdb':'application/vnd.palm',
+'pdf':'application/pdf',
+'pfa':'application/x-font-type1',
+'pfb':'application/x-font-type1',
+'pfm':'application/x-font-type1',
+'pfr':'application/font-tdpfr',
+'pfx':'application/x-pkcs12',
+'pgm':'image/x-portable-graymap',
+'pgn':'application/x-chess-pgn',
+'pgp':'application/pgp-encrypted',
+'pic':'image/x-pict',
+'pkg':'application/octet-stream',
+'pki':'application/pkixcmp',
+'pkipath':'application/pkix-pkipath',
+'plb':'application/vnd.3gpp.pic-bw-large',
+'plc':'application/vnd.mobius.plc',
+'plf':'application/vnd.pocketlearn',
+'pls':'application/pls+xml',
+'pml':'application/vnd.ctc-posml',
+'png':'image/png',
+'pnm':'image/x-portable-anymap',
+'portpkg':'application/vnd.macports.portpkg',
+'pot':'application/vnd.ms-powerpoint',
+'potm':'application/vnd.ms-powerpoint.template.macroenabled.12',
+'potx':'application/vnd.openxmlformats-officedocument.presentationml.template',
+'ppam':'application/vnd.ms-powerpoint.addin.macroenabled.12',
+'ppd':'application/vnd.cups-ppd',
+'ppm':'image/x-portable-pixmap',
+'pps':'application/vnd.ms-powerpoint',
+'ppsm':'application/vnd.ms-powerpoint.slideshow.macroenabled.12',
+'ppsx':'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+'ppt':'application/vnd.ms-powerpoint',
+'pptm':'application/vnd.ms-powerpoint.presentation.macroenabled.12',
+'pptx':'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+'pqa':'application/vnd.palm',
+'prc':'application/x-mobipocket-ebook',
+'pre':'application/vnd.lotus-freelance',
+'prf':'application/pics-rules',
+'ps':'application/postscript',
+'psb':'application/vnd.3gpp.pic-bw-small',
+'psd':'image/vnd.adobe.photoshop',
+'psf':'application/x-font-linux-psf',
+'pskcxml':'application/pskc+xml',
+'ptid':'application/vnd.pvi.ptid1',
+'pub':'application/x-mspublisher',
+'pvb':'application/vnd.3gpp.pic-bw-var',
+'pwn':'application/vnd.3m.post-it-notes',
+'pya':'audio/vnd.ms-playready.media.pya',
+'pyv':'video/vnd.ms-playready.media.pyv',
+'qam':'application/vnd.epson.quickanime',
+'qbo':'application/vnd.intu.qbo',
+'qfx':'application/vnd.intu.qfx',
+'qps':'application/vnd.publishare-delta-tree',
+'qt':'video/quicktime',
+'qwd':'application/vnd.quark.quarkxpress',
+'qwt':'application/vnd.quark.quarkxpress',
+'qxb':'application/vnd.quark.quarkxpress',
+'qxd':'application/vnd.quark.quarkxpress',
+'qxl':'application/vnd.quark.quarkxpress',
+'qxt':'application/vnd.quark.quarkxpress',
+'ra':'audio/x-pn-realaudio',
+'ram':'audio/x-pn-realaudio',
+'rar':'application/x-rar-compressed',
+'ras':'image/x-cmu-raster',
+'rcprofile':'application/vnd.ipunplugged.rcprofile',
+'rdf':'application/rdf+xml',
+'rdz':'application/vnd.data-vision.rdz',
+'rep':'application/vnd.businessobjects',
+'res':'application/x-dtbresource+xml',
+'rgb':'image/x-rgb',
+'rif':'application/reginfo+xml',
+'rip':'audio/vnd.rip',
+'ris':'application/x-research-info-systems',
+'rl':'application/resource-lists+xml',
+'rlc':'image/vnd.fujixerox.edmics-rlc',
+'rld':'application/resource-lists-diff+xml',
+'rm':'application/vnd.rn-realmedia',
+'rmi':'audio/midi',
+'rmp':'audio/x-pn-realaudio-plugin',
+'rms':'application/vnd.jcp.javame.midlet-rms',
+'rmvb':'application/vnd.rn-realmedia-vbr',
+'rnc':'application/relax-ng-compact-syntax',
+'roa':'application/rpki-roa',
+'roff':'text/troff',
+'rp9':'application/vnd.cloanto.rp9',
+'rpss':'application/vnd.nokia.radio-presets',
+'rpst':'application/vnd.nokia.radio-preset',
+'rq':'application/sparql-query',
+'rs':'application/rls-services+xml',
+'rsd':'application/rsd+xml',
+'rss':'application/rss+xml',
+'rtf':'application/rtf',
+'rtx':'text/richtext',
+'s':'text/x-asm',
+'s3m':'audio/s3m',
+'saf':'application/vnd.yamaha.smaf-audio',
+'sbml':'application/sbml+xml',
+'sc':'application/vnd.ibm.secure-container',
+'scd':'application/x-msschedule',
+'scm':'application/vnd.lotus-screencam',
+'scq':'application/scvp-cv-request',
+'scs':'application/scvp-cv-response',
+'scurl':'text/vnd.curl.scurl',
+'sda':'application/vnd.stardivision.draw',
+'sdc':'application/vnd.stardivision.calc',
+'sdd':'application/vnd.stardivision.impress',
+'sdkd':'application/vnd.solent.sdkm+xml',
+'sdkm':'application/vnd.solent.sdkm+xml',
+'sdp':'application/sdp',
+'sdw':'application/vnd.stardivision.writer',
+'see':'application/vnd.seemail',
+'seed':'application/vnd.fdsn.seed',
+'sema':'application/vnd.sema',
+'semd':'application/vnd.semd',
+'semf':'application/vnd.semf',
+'ser':'application/java-serialized-object',
+'setpay':'application/set-payment-initiation',
+'setreg':'application/set-registration-initiation',
+'sfd-hdstx':'application/vnd.hydrostatix.sof-data',
+'sfs':'application/vnd.spotfire.sfs',
+'sfv':'text/x-sfv',
+'sgi':'image/sgi',
+'sgl':'application/vnd.stardivision.writer-global',
+'sgm':'text/sgml',
+'sgml':'text/sgml',
+'sh':'application/x-sh',
+'shar':'application/x-shar',
+'shf':'application/shf+xml',
+'sid':'image/x-mrsid-image',
+'sig':'application/pgp-signature',
+'sil':'audio/silk',
+'silo':'model/mesh',
+'sis':'application/vnd.symbian.install',
+'sisx':'application/vnd.symbian.install',
+'sit':'application/x-stuffit',
+'sitx':'application/x-stuffitx',
+'skd':'application/vnd.koan',
+'skm':'application/vnd.koan',
+'skp':'application/vnd.koan',
+'skt':'application/vnd.koan',
+'sldm':'application/vnd.ms-powerpoint.slide.macroenabled.12',
+'sldx':'application/vnd.openxmlformats-officedocument.presentationml.slide',
+'slt':'application/vnd.epson.salt',
+'sm':'application/vnd.stepmania.stepchart',
+'smf':'application/vnd.stardivision.math',
+'smi':'application/smil+xml',
+'smil':'application/smil+xml',
+'smv':'video/x-smv',
+'smzip':'application/vnd.stepmania.package',
+'snd':'audio/basic',
+'snf':'application/x-font-snf',
+'so':'application/octet-stream',
+'spc':'application/x-pkcs7-certificates',
+'spf':'application/vnd.yamaha.smaf-phrase',
+'spl':'application/x-futuresplash',
+'spot':'text/vnd.in3d.spot',
+'spp':'application/scvp-vp-response',
+'spq':'application/scvp-vp-request',
+'spx':'audio/ogg',
+'sql':'application/x-sql',
+'src':'application/x-wais-source',
+'srt':'application/x-subrip',
+'sru':'application/sru+xml',
+'srx':'application/sparql-results+xml',
+'ssdl':'application/ssdl+xml',
+'sse':'application/vnd.kodak-descriptor',
+'ssf':'application/vnd.epson.ssf',
+'ssml':'application/ssml+xml',
+'st':'application/vnd.sailingtracker.track',
+'stc':'application/vnd.sun.xml.calc.template',
+'std':'application/vnd.sun.xml.draw.template',
+'stf':'application/vnd.wt.stf',
+'sti':'application/vnd.sun.xml.impress.template',
+'stk':'application/hyperstudio',
+'stl':'application/vnd.ms-pki.stl',
+'str':'application/vnd.pg.format',
+'stw':'application/vnd.sun.xml.writer.template',
+'sub':'image/vnd.dvb.subtitle',
+'sub':'text/vnd.dvb.subtitle',
+'sus':'application/vnd.sus-calendar',
+'susp':'application/vnd.sus-calendar',
+'sv4cpio':'application/x-sv4cpio',
+'sv4crc':'application/x-sv4crc',
+'svc':'application/vnd.dvb.service',
+'svd':'application/vnd.svd',
+'svg':'image/svg+xml',
+'svgz':'image/svg+xml',
+'swa':'application/x-director',
+'swf':'application/x-shockwave-flash',
+'swi':'application/vnd.aristanetworks.swi',
+'sxc':'application/vnd.sun.xml.calc',
+'sxd':'application/vnd.sun.xml.draw',
+'sxg':'application/vnd.sun.xml.writer.global',
+'sxi':'application/vnd.sun.xml.impress',
+'sxm':'application/vnd.sun.xml.math',
+'sxw':'application/vnd.sun.xml.writer',
+'t':'text/troff',
+'t3':'application/x-t3vm-image',
+'taglet':'application/vnd.mynfc',
+'tao':'application/vnd.tao.intent-module-archive',
+'tar':'application/x-tar',
+'tcap':'application/vnd.3gpp2.tcap',
+'tcl':'application/x-tcl',
+'teacher':'application/vnd.smart.teacher',
+'tei':'application/tei+xml',
+'teicorpus':'application/tei+xml',
+'tex':'application/x-tex',
+'texi':'application/x-texinfo',
+'texinfo':'application/x-texinfo',
+'text':'text/plain',
+'tfi':'application/thraud+xml',
+'tfm':'application/x-tex-tfm',
+'tga':'image/x-tga',
+'thmx':'application/vnd.ms-officetheme',
+'tif':'image/tiff',
+'tiff':'image/tiff',
+'tmo':'application/vnd.tmobile-livetv',
+'torrent':'application/x-bittorrent',
+'tpl':'application/vnd.groove-tool-template',
+'tpt':'application/vnd.trid.tpt',
+'tr':'text/troff',
+'tra':'application/vnd.trueapp',
+'trm':'application/x-msterminal',
+'tsd':'application/timestamped-data',
+'tsv':'text/tab-separated-values',
+'ttc':'application/x-font-ttf',
+'ttf':'application/x-font-ttf',
+'ttl':'text/turtle',
+'twd':'application/vnd.simtech-mindmapper',
+'twds':'application/vnd.simtech-mindmapper',
+'txd':'application/vnd.genomatix.tuxedo',
+'txf':'application/vnd.mobius.txf',
+'txt':'text/plain',
+'u32':'application/x-authorware-bin',
+'udeb':'application/x-debian-package',
+'ufd':'application/vnd.ufdl',
+'ufdl':'application/vnd.ufdl',
+'ulx':'application/x-glulx',
+'umj':'application/vnd.umajin',
+'unityweb':'application/vnd.unity',
+'uoml':'application/vnd.uoml+xml',
+'uri':'text/uri-list',
+'uris':'text/uri-list',
+'urls':'text/uri-list',
+'ustar':'application/x-ustar',
+'utz':'application/vnd.uiq.theme',
+'uu':'text/x-uuencode',
+'uva':'audio/vnd.dece.audio',
+'uvd':'application/vnd.dece.data',
+'uvf':'application/vnd.dece.data',
+'uvg':'image/vnd.dece.graphic',
+'uvh':'video/vnd.dece.hd',
+'uvi':'image/vnd.dece.graphic',
+'uvm':'video/vnd.dece.mobile',
+'uvp':'video/vnd.dece.pd',
+'uvs':'video/vnd.dece.sd',
+'uvt':'application/vnd.dece.ttml+xml',
+'uvu':'video/vnd.uvvu.mp4',
+'uvv':'video/vnd.dece.video',
+'uvva':'audio/vnd.dece.audio',
+'uvvd':'application/vnd.dece.data',
+'uvvf':'application/vnd.dece.data',
+'uvvg':'image/vnd.dece.graphic',
+'uvvh':'video/vnd.dece.hd',
+'uvvi':'image/vnd.dece.graphic',
+'uvvm':'video/vnd.dece.mobile',
+'uvvp':'video/vnd.dece.pd',
+'uvvs':'video/vnd.dece.sd',
+'uvvt':'application/vnd.dece.ttml+xml',
+'uvvu':'video/vnd.uvvu.mp4',
+'uvvv':'video/vnd.dece.video',
+'uvvx':'application/vnd.dece.unspecified',
+'uvvz':'application/vnd.dece.zip',
+'uvx':'application/vnd.dece.unspecified',
+'uvz':'application/vnd.dece.zip',
+'vcard':'text/vcard',
+'vcd':'application/x-cdlink',
+'vcf':'text/x-vcard',
+'vcg':'application/vnd.groove-vcard',
+'vcs':'text/x-vcalendar',
+'vcx':'application/vnd.vcx',
+'vis':'application/vnd.visionary',
+'viv':'video/vnd.vivo',
+'vob':'video/x-ms-vob',
+'vor':'application/vnd.stardivision.writer',
+'vox':'application/x-authorware-bin',
+'vrml':'model/vrml',
+'vsd':'application/vnd.visio',
+'vsf':'application/vnd.vsf',
+'vss':'application/vnd.visio',
+'vst':'application/vnd.visio',
+'vsw':'application/vnd.visio',
+'vtu':'model/vnd.vtu',
+'vxml':'application/voicexml+xml',
+'w3d':'application/x-director',
+'wad':'application/x-doom',
+'wav':'audio/x-wav',
+'wax':'audio/x-ms-wax',
+'wbmp':'image/vnd.wap.wbmp',
+'wbs':'application/vnd.criticaltools.wbs+xml',
+'wbxml':'application/vnd.wap.wbxml',
+'wcm':'application/vnd.ms-works',
+'wdb':'application/vnd.ms-works',
+'wdp':'image/vnd.ms-photo',
+'weba':'audio/webm',
+'webm':'video/webm',
+'webp':'image/webp',
+'wg':'application/vnd.pmi.widget',
+'wgt':'application/widget',
+'wks':'application/vnd.ms-works',
+'wm':'video/x-ms-wm',
+'wma':'audio/x-ms-wma',
+'wmd':'application/x-ms-wmd',
+'wmf':'application/x-msmetafile',
+'wml':'text/vnd.wap.wml',
+'wmlc':'application/vnd.wap.wmlc',
+'wmls':'text/vnd.wap.wmlscript',
+'wmlsc':'application/vnd.wap.wmlscriptc',
+'wmv':'video/x-ms-wmv',
+'wmx':'video/x-ms-wmx',
+'wmz':'application/x-ms-wmz',
+'wmz':'application/x-msmetafile',
+'woff':'application/x-font-woff',
+'wpd':'application/vnd.wordperfect',
+'wpl':'application/vnd.ms-wpl',
+'wps':'application/vnd.ms-works',
+'wqd':'application/vnd.wqd',
+'wri':'application/x-mswrite',
+'wrl':'model/vrml',
+'wsdl':'application/wsdl+xml',
+'wspolicy':'application/wspolicy+xml',
+'wtb':'application/vnd.webturbo',
+'wvx':'video/x-ms-wvx',
+'x32':'application/x-authorware-bin',
+'x3d':'model/x3d+xml',
+'x3db':'model/x3d+binary',
+'x3dbz':'model/x3d+binary',
+'x3dv':'model/x3d+vrml',
+'x3dvz':'model/x3d+vrml',
+'x3dz':'model/x3d+xml',
+'xaml':'application/xaml+xml',
+'xap':'application/x-silverlight-app',
+'xar':'application/vnd.xara',
+'xbap':'application/x-ms-xbap',
+'xbd':'application/vnd.fujixerox.docuworks.binder',
+'xbm':'image/x-xbitmap',
+'xdf':'application/xcap-diff+xml',
+'xdm':'application/vnd.syncml.dm+xml',
+'xdp':'application/vnd.adobe.xdp+xml',
+'xdssc':'application/dssc+xml',
+'xdw':'application/vnd.fujixerox.docuworks',
+'xenc':'application/xenc+xml',
+'xer':'application/patch-ops-error+xml',
+'xfdf':'application/vnd.adobe.xfdf',
+'xfdl':'application/vnd.xfdl',
+'xht':'application/xhtml+xml',
+'xhtml':'application/xhtml+xml',
+'xhvml':'application/xv+xml',
+'xif':'image/vnd.xiff',
+'xla':'application/vnd.ms-excel',
+'xlam':'application/vnd.ms-excel.addin.macroenabled.12',
+'xlc':'application/vnd.ms-excel',
+'xlf':'application/x-xliff+xml',
+'xlm':'application/vnd.ms-excel',
+'xls':'application/vnd.ms-excel',
+'xlsb':'application/vnd.ms-excel.sheet.binary.macroenabled.12',
+'xlsm':'application/vnd.ms-excel.sheet.macroenabled.12',
+'xlsx':'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+'xlt':'application/vnd.ms-excel',
+'xltm':'application/vnd.ms-excel.template.macroenabled.12',
+'xltx':'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+'xlw':'application/vnd.ms-excel',
+'xm':'audio/xm',
+'xml':'application/xml',
+'xo':'application/vnd.olpc-sugar',
+'xop':'application/xop+xml',
+'xpi':'application/x-xpinstall',
+'xpl':'application/xproc+xml',
+'xpm':'image/x-xpixmap',
+'xpr':'application/vnd.is-xpr',
+'xps':'application/vnd.ms-xpsdocument',
+'xpw':'application/vnd.intercon.formnet',
+'xpx':'application/vnd.intercon.formnet',
+'xsl':'application/xml',
+'xslt':'application/xslt+xml',
+'xsm':'application/vnd.syncml+xml',
+'xspf':'application/xspf+xml',
+'xul':'application/vnd.mozilla.xul+xml',
+'xvm':'application/xv+xml',
+'xvml':'application/xv+xml',
+'xwd':'image/x-xwindowdump',
+'xyz':'chemical/x-xyz',
+'xz':'application/x-xz',
+'yang':'application/yang',
+'yin':'application/yin+xml',
+'z1':'application/x-zmachine',
+'z2':'application/x-zmachine',
+'z3':'application/x-zmachine',
+'z4':'application/x-zmachine',
+'z5':'application/x-zmachine',
+'z6':'application/x-zmachine',
+'z7':'application/x-zmachine',
+'z8':'application/x-zmachine',
+'zaz':'application/vnd.zzazz.deck+xml',
+'zip':'application/zip',
+'zir':'application/vnd.zul',
+'zirz':'application/vnd.zul',
+'zmm':'application/vnd.handheld-entertainment+xml',
+};
diff --git a/pkg/mime/lib/src/magic_number.dart b/pkg/mime/lib/src/magic_number.dart
new file mode 100644
index 0000000..451a093
--- /dev/null
+++ b/pkg/mime/lib/src/magic_number.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of mime;
+
+
+class _MagicNumber {
+ final String mimeType;
+ final List<int> numbers;
+ final List<int> mask;
+
+ const _MagicNumber(this.mimeType, this.numbers, {this.mask});
+
+ bool matches(List<int> header) {
+ if (header.length < numbers.length) return false;
+
+ for (int i = 0; i < numbers.length; i++) {
+ if (mask != null) {
+ if ((mask[i] & numbers[i]) != (mask[i] & header[i])) return false;
+ } else {
+ if (numbers[i] != header[i]) return false;
+ }
+ }
+
+ return true;
+ }
+
+}
+
+int _defaultMagicNumbersMaxLength = 16;
+
+List<_MagicNumber> _defaultMagicNumbers = const [
+const _MagicNumber('application/pdf', const [0x25, 0x50, 0x44, 0x46]),
+const _MagicNumber('application/postscript', const [0x25, 0x51]),
+const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]),
+const _MagicNumber('image/gif', const [0x47, 0x49, 0x46, 0x38, 0x39, 0x61]),
+const _MagicNumber('image/jpeg', const [0xFF, 0xD8]),
+const _MagicNumber('image/png',
+ const [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
+const _MagicNumber('image/tiff', const [0x49, 0x49, 0x2A, 0x00]),
+const _MagicNumber('image/tiff', const [0x4D, 0x4D, 0x00, 0x2A]),
+const _MagicNumber('video/mp4',
+ const [0x00, 0x00, 0x00, 0x00, 0x66, 0x74,
+ 0x79, 0x70, 0x33, 0x67, 0x70, 0x35],
+ mask: const [0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
+];
+
diff --git a/pkg/mime/lib/src/mime_type.dart b/pkg/mime/lib/src/mime_type.dart
new file mode 100644
index 0000000..cd08cdf
--- /dev/null
+++ b/pkg/mime/lib/src/mime_type.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of mime;
+
+
+MimeTypeResolver _globalResolver = new MimeTypeResolver();
+
+/**
+ * The maximum number of bytes needed, to match all default magic-numbers.
+ */
+int get defaultMagicNumbersMaxLength => _defaultMagicNumbersMaxLength;
+
+/**
+ * Extract the extension from [path] and use that for MIME-type lookup, using
+ * the default extension map.
+ *
+ * If no matching MIME-type was found, `null` is returned.
+ *
+ * If [headerBytes] is present, a match for known magic-numbers will be
+ * performed first. This allows the correct mime-type to be found, even though
+ * a file have been saved using the wrong file-name extension. If less than
+ * [defaultMagicNumbersMaxLength] bytes was provided, some magic-numbers won't
+ * be matched against.
+ */
+String lookupMimeType(String path,
+ {List<int> headerBytes})
+ => _globalResolver.lookup(path, headerBytes: headerBytes);
+
+
+/**
+ * MIME-type resolver class, used to customize the lookup of mime-types.
+ */
+class MimeTypeResolver {
+ final Map<String, String> _extensionMap = {};
+ final List<_MagicNumber> _magicNumbers = [];
+ bool _useDefault;
+ int _magicNumbersMaxLength;
+
+ /**
+ * Create a new empty [MimeTypeResolver].
+ */
+ MimeTypeResolver.empty() : _useDefault = false, _magicNumbersMaxLength = 0;
+
+ /**
+ * Create a new [MimeTypeResolver] containing the default scope.
+ */
+ MimeTypeResolver() :
+ _useDefault = true,
+ _magicNumbersMaxLength = _defaultMagicNumbersMaxLength;
+
+ /**
+ * Get the maximum number of bytes required to match all magic numbers, when
+ * performing [lookup] with headerBytes present.
+ */
+ int get magicNumbersMaxLength => _magicNumbersMaxLength;
+
+ /**
+ * Extract the extension from [path] and use that for MIME-type lookup.
+ *
+ * If no matching MIME-type was found, `null` is returned.
+ *
+ * If [headerBytes] is present, a match for known magic-numbers will be
+ * performed first. This allows the correct mime-type to be found, even though
+ * a file have been saved using the wrong file-name extension. If less than
+ * [magicNumbersMaxLength] bytes was provided, some magic-numbers won't
+ * be matched against.
+ */
+ String lookup(String path,
+ {List<int> headerBytes}) {
+ String result;
+ if (headerBytes != null) {
+ result =_matchMagic(headerBytes, _magicNumbers);
+ if (result != null) return result;
+ if (_useDefault) {
+ result =_matchMagic(headerBytes, _defaultMagicNumbers);
+ if (result != null) return result;
+ }
+ }
+ var ext = _ext(path);
+ result = _extensionMap[ext];
+ if (result != null) return result;
+ if (_useDefault) {
+ result = _defaultExtensionMap[ext];
+ if (result != null) return result;
+ }
+ return null;
+ }
+
+ /**
+ * Add a new MIME-type mapping to the [MimeTypeResolver]. If the [extension]
+ * is already present in the [MimeTypeResolver], it'll be overwritten.
+ */
+ void addExtension(String extension, String mimeType) {
+ _extensionMap[extension] = mimeType;
+ }
+
+ /**
+ * Add a new magic-number mapping to the [MimeTypeResolver].
+ *
+ * If [mask] is present,the [mask] is used to only perform matching on
+ * selective bits. The [mask] must have the same length as [bytes].
+ */
+ void addMagicNumber(List<int> bytes, String mimeType, {List<int> mask}) {
+ if (mask != null && bytes.length != mask.length) {
+ throw new ArgumentError('Bytes and mask are of different lengths');
+ }
+ if (bytes.length > _magicNumbersMaxLength) {
+ _magicNumbersMaxLength = bytes.length;
+ }
+ _magicNumbers.add(new _MagicNumber(mimeType, bytes, mask: mask));
+ }
+
+ static String _matchMagic(List<int> headerBytes,
+ List<_MagicNumber> magicNumbers) {
+ for (var mn in magicNumbers) {
+ if (mn.matches(headerBytes)) return mn.mimeType;
+ }
+ return null;
+ }
+
+ static String _ext(String path) {
+ int index = path.lastIndexOf('.');
+ if (index < 0 || index + 1 >= path.length) return path;
+ return path.substring(index + 1).toLowerCase();
+ }
+}
+
diff --git a/pkg/mime/pubspec.yaml b/pkg/mime/pubspec.yaml
new file mode 100644
index 0000000..82493f8
--- /dev/null
+++ b/pkg/mime/pubspec.yaml
@@ -0,0 +1,5 @@
+name: mime
+author: "Dart Team <misc@dartlang.org>"
+homepage: http://www.dartlang.org
+description: >
+ Helper-package for working with MIME.
diff --git a/pkg/mime/test/mime_type_test.dart b/pkg/mime/test/mime_type_test.dart
new file mode 100644
index 0000000..36c728d
--- /dev/null
+++ b/pkg/mime/test/mime_type_test.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:unittest/unittest.dart";
+import 'package:mime/mime.dart';
+
+void expectMimeType(String path,
+ String expectedMimeType,
+ {List<int> headerBytes,
+ MimeTypeResolver resolver}) {
+ String mimeType;
+ if (resolver == null) {
+ mimeType = lookupMimeType(path, headerBytes: headerBytes);
+ } else {
+ mimeType = resolver.lookup(path, headerBytes: headerBytes);
+ }
+
+ if (mimeType != expectedMimeType) {
+ throw "Expect '$expectedMimeType' but got '$mimeType'";
+ }
+}
+
+void main() {
+ group('global-lookup', () {
+ test('by-path', () {
+ expectMimeType('file.dart', 'application/dart');
+ // Test mixed-case
+ expectMimeType('file.DaRT', 'application/dart');
+ expectMimeType('file.html', 'text/html');
+ expectMimeType('file.xhtml', 'application/xhtml+xml');
+ expectMimeType('file.jpeg', 'image/jpeg');
+ expectMimeType('file.jpg', 'image/jpeg');
+ expectMimeType('file.png', 'image/png');
+ expectMimeType('file.gif', 'image/gif');
+ expectMimeType('file.cc', 'text/x-c');
+ expectMimeType('file.c', 'text/x-c');
+ expectMimeType('file.css', 'text/css');
+ expectMimeType('file.js', 'application/javascript');
+ expectMimeType('file.ps', 'application/postscript');
+ expectMimeType('file.pdf', 'application/pdf');
+ expectMimeType('file.tiff', 'image/tiff');
+ expectMimeType('file.tif', 'image/tiff');
+ });
+
+ test('unknown-mime-type', () {
+ expectMimeType('file.unsupported-extension', null);
+ });
+
+ test('by-header-bytes', () {
+ expectMimeType('file.jpg',
+ 'image/png',
+ headerBytes: [0x89, 0x50, 0x4E, 0x47,
+ 0x0D, 0x0A, 0x1A, 0x0A]);
+ expectMimeType('file.jpg',
+ 'image/gif',
+ headerBytes: [0x47, 0x49, 0x46, 0x38, 0x39,
+ 0x61, 0x0D, 0x0A, 0x1A, 0x0A]);
+ expectMimeType('file.gif',
+ 'image/jpeg',
+ headerBytes: [0xFF, 0xD8, 0x46, 0x38, 0x39,
+ 0x61, 0x0D, 0x0A, 0x1A, 0x0A]);
+ expectMimeType('file.mp4',
+ 'video/mp4',
+ headerBytes: [0x00, 0x00, 0x00, 0x04, 0x66, 0x74,
+ 0x79, 0x70, 0x33, 0x67, 0x70, 0x35]);
+ });
+ });
+
+ group('custom-resolver', () {
+ test('override-extension', () {
+ var resolver = new MimeTypeResolver();
+ resolver.addExtension('jpg', 'my-mime-type');
+ expectMimeType('file.jpg', 'my-mime-type', resolver: resolver);
+ });
+
+ test('fallthrough-extension', () {
+ var resolver = new MimeTypeResolver();
+ resolver.addExtension('jpg2', 'my-mime-type');
+ expectMimeType('file.jpg', 'image/jpeg', resolver: resolver);
+ });
+
+ test('with-mask', () {
+ var resolver = new MimeTypeResolver.empty();
+ resolver.addMagicNumber([0x01, 0x02, 0x03],
+ 'my-mime-type',
+ mask: [0x01, 0xFF, 0xFE]);
+ expectMimeType('file',
+ 'my-mime-type',
+ headerBytes: [0x01, 0x02, 0x03],
+ resolver: resolver);
+ expectMimeType('file',
+ null,
+ headerBytes: [0x01, 0x03, 0x03],
+ resolver: resolver);
+ expectMimeType('file',
+ 'my-mime-type',
+ headerBytes: [0xFF, 0x02, 0x02],
+ resolver: resolver);
+ });
+ });
+}
+
diff --git a/pkg/pathos/README.md b/pkg/pathos/README.md
index e67fc5e..1e50b23 100644
--- a/pkg/pathos/README.md
+++ b/pkg/pathos/README.md
@@ -216,6 +216,44 @@
withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
+### String fromUri(Uri uri)
+
+Returns the path represented by [uri]. For POSIX and Windows styles, [uri] must
+be a `file:` URI. For the URL style, this will just convert [uri] to a string.
+
+ // POSIX
+ path.fromUri(Uri.parse('file:///path/to/foo'))
+ // -> '/path/to/foo'
+
+ // Windows
+ path.fromUri(Uri.parse('file:///C:/path/to/foo'))
+ // -> r'C:\path\to\foo'
+
+ // URL
+ path.fromUri(Uri.parse('http://dartlang.org/path/to/foo'))
+ // -> 'http://dartlang.org/path/to/foo'
+
+### Uri toUri(String path)
+
+Returns the URI that represents [path]. For POSIX and Windows styles, this will
+return a `file:` URI. For the URL style, this will just convert [path] to a
+[Uri].
+
+This will always convert relative paths to absolute ones before converting
+to a URI.
+
+ // POSIX
+ path.toUri('/path/to/foo')
+ // -> Uri.parse('file:///path/to/foo')
+
+ // Windows
+ path.toUri(r'C:\path\to\foo')
+ // -> Uri.parse('file:///C:/path/to/foo')
+
+ // URL
+ path.toUri('http://dartlang.org/path/to/foo')
+ // -> Uri.parse('http://dartlang.org/path/to/foo')
+
## The path.Builder class
In addition to the functions, path exposes a `path.Builder` class. This lets
diff --git a/pkg/pathos/lib/path.dart b/pkg/pathos/lib/path.dart
index 145953f..c33bd87 100644
--- a/pkg/pathos/lib/path.dart
+++ b/pkg/pathos/lib/path.dart
@@ -275,6 +275,45 @@
/// withoutExtension('path/to/foo.dart'); // -> 'path/to/foo'
String withoutExtension(String path) => _builder.withoutExtension(path);
+/// Returns the path represented by [uri].
+///
+/// For POSIX and Windows styles, [uri] must be a `file:` URI. For the URL
+/// style, this will just convert [uri] to a string.
+///
+/// // POSIX
+/// path.fromUri(Uri.parse('file:///path/to/foo'))
+/// // -> '/path/to/foo'
+///
+/// // Windows
+/// path.fromUri(Uri.parse('file:///C:/path/to/foo'))
+/// // -> r'C:\path\to\foo'
+///
+/// // URL
+/// path.fromUri(Uri.parse('http://dartlang.org/path/to/foo'))
+/// // -> 'http://dartlang.org/path/to/foo'
+String fromUri(Uri uri) => _builder.fromUri(uri);
+
+/// Returns the URI that represents [path].
+///
+/// For POSIX and Windows styles, this will return a `file:` URI. For the URL
+/// style, this will just convert [path] to a [Uri].
+///
+/// This will always convert relative paths to absolute ones before converting
+/// to a URI.
+///
+/// // POSIX
+/// path.toUri('/path/to/foo')
+/// // -> Uri.parse('file:///path/to/foo')
+///
+/// // Windows
+/// path.toUri(r'C:\path\to\foo')
+/// // -> Uri.parse('file:///C:/path/to/foo')
+///
+/// // URL
+/// path.toUri('http://dartlang.org/path/to/foo')
+/// // -> Uri.parse('http://dartlang.org/path/to/foo')
+Uri toUri(String path) => _builder.toUri(path);
+
/// Validates that there are no non-null arguments following a null one and
/// throws an appropriate [ArgumentError] on failure.
_validateArgList(String method, List<String> args) {
@@ -436,7 +475,7 @@
/// On POSIX systems, absolute paths start with a `/` (forward slash). On
/// Windows, an absolute path starts with `\\`, or a drive letter followed by
/// `:/` or `:\`.
- bool isRelative(String path) => !isAbsolute(path);
+ bool isRelative(String path) => !this.isAbsolute(path);
/// Returns `true` if [path] is a root-relative path and `false` if it's not.
///
@@ -673,6 +712,48 @@
return parsed.toString();
}
+ /// Returns the path represented by [uri].
+ ///
+ /// For POSIX and Windows styles, [uri] must be a `file:` URI. For the URL
+ /// style, this will just convert [uri] to a string.
+ ///
+ /// // POSIX
+ /// builder.fromUri(Uri.parse('file:///path/to/foo'))
+ /// // -> '/path/to/foo'
+ ///
+ /// // Windows
+ /// builder.fromUri(Uri.parse('file:///C:/path/to/foo'))
+ /// // -> r'C:\path\to\foo'
+ ///
+ /// // URL
+ /// builder.fromUri(Uri.parse('http://dartlang.org/path/to/foo'))
+ /// // -> 'http://dartlang.org/path/to/foo'
+ String fromUri(Uri uri) => style.pathFromUri(uri);
+
+ /// Returns the URI that represents [path].
+ ///
+ /// For POSIX and Windows styles, this will return a `file:` URI. For the URL
+ /// style, this will just convert [path] to a [Uri].
+ ///
+ /// // POSIX
+ /// builder.toUri('/path/to/foo')
+ /// // -> Uri.parse('file:///path/to/foo')
+ ///
+ /// // Windows
+ /// builder.toUri(r'C:\path\to\foo')
+ /// // -> Uri.parse('file:///C:/path/to/foo')
+ ///
+ /// // URL
+ /// builder.toUri('http://dartlang.org/path/to/foo')
+ /// // -> Uri.parse('http://dartlang.org/path/to/foo')
+ Uri toUri(String path) {
+ if (isRelative(path)) {
+ return Uri.parse(path.replaceAll(style.separatorPattern, '/'));
+ } else {
+ return style.pathToUri(join(root, path));
+ }
+ }
+
_ParsedPath _parse(String path) {
var before = path;
@@ -711,18 +792,17 @@
}
/// An enum type describing a "flavor" of path.
-class Style {
+abstract class Style {
/// POSIX-style paths use "/" (forward slash) as separators. Absolute paths
/// start with "/". Used by UNIX, Linux, Mac OS X, and others.
- static final posix = new Style._('posix', '/', '/', r'[^/]$', '/');
+ static final posix = new _PosixStyle();
/// Windows paths use "\" (backslash) as separators. Absolute paths start with
/// a drive letter followed by a colon (example, "C:") or two backslashes
/// ("\\") for UNC paths.
// TODO(rnystrom): The UNC root prefix should include the drive name too, not
// just the "\\".
- static final windows = new Style._('windows', '\\', r'[/\\]', r'[^/\\]$',
- r'\\\\|[a-zA-Z]:[/\\]');
+ static final windows = new _WindowsStyle();
/// URLs aren't filesystem paths, but they're supported by Pathos to make it
/// easier to manipulate URL paths in the browser.
@@ -730,30 +810,19 @@
/// URLs use "/" (forward slash) as separators. Absolute paths either start
/// with a protocol and optional hostname (e.g. `http://dartlang.org`,
/// `file://`) or with "/".
- static final url = new Style._('url', '/', '/',
- r"(^[a-zA-Z][-+.a-zA-Z\d]*://|[^/])$",
- r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*", r"/");
-
- Style._(this.name, this.separator, String separatorPattern,
- String needsSeparatorPattern, String rootPattern,
- [String relativeRootPattern])
- : separatorPattern = new RegExp(separatorPattern),
- needsSeparatorPattern = new RegExp(needsSeparatorPattern),
- _rootPattern = new RegExp('^$rootPattern'),
- _relativeRootPattern = relativeRootPattern == null ? null :
- new RegExp('^$relativeRootPattern');
+ static final url = new _UrlStyle();
/// The name of this path style. Will be "posix" or "windows".
- final String name;
+ String get name;
/// The path separator for this style. On POSIX, this is `/`. On Windows,
/// it's `\`.
- final String separator;
+ String get separator;
/// The [Pattern] that can be used to match a separator for a path in this
- /// style. Windows allows both "/" and "\" as path separators even though
- /// "\" is the canonical one.
- final Pattern separatorPattern;
+ /// style. Windows allows both "/" and "\" as path separators even though "\"
+ /// is the canonical one.
+ Pattern get separatorPattern;
/// The [Pattern] that matches path components that need a separator after
/// them.
@@ -763,24 +832,23 @@
/// separator between the root and the first component, even if the root
/// already ends in a separator character. For example, to join "file://" and
/// "usr", an additional "/" is needed (making "file:///usr").
- final Pattern needsSeparatorPattern;
+ Pattern get needsSeparatorPattern;
- // TODO(nweiz): make this a Pattern when issue 7080 is fixed.
- /// The [RegExp] that can be used to match the root prefix of an absolute
+ /// The [Pattern] that can be used to match the root prefix of an absolute
/// path in this style.
- final RegExp _rootPattern;
+ Pattern get rootPattern;
- /// The [RegExp] that can be used to match the root prefix of a root-relative
+ /// The [Pattern] that can be used to match the root prefix of a root-relative
/// path in this style.
///
/// This can be null to indicate that this style doesn't support root-relative
/// paths.
- final RegExp _relativeRootPattern;
+ final Pattern relativeRootPattern = null;
/// Gets the root prefix of [path] if path is absolute. If [path] is relative,
/// returns `null`.
String getRoot(String path) {
- var match = _rootPattern.firstMatch(path);
+ var match = rootPattern.firstMatch(path);
if (match != null) return match[0];
return getRelativeRoot(path);
}
@@ -789,15 +857,146 @@
///
/// If [path] is relative or absolute and not root-relative, returns `null`.
String getRelativeRoot(String path) {
- if (_relativeRootPattern == null) return null;
- var match = _relativeRootPattern.firstMatch(path);
+ if (relativeRootPattern == null) return null;
+ var match = relativeRootPattern.firstMatch(path);
if (match == null) return null;
return match[0];
}
+ /// Returns the path represented by [uri] in this style.
+ String pathFromUri(Uri uri);
+
+ /// Returns the URI that represents [path].
+ ///
+ /// Pathos will always path an absolute path for [path]. Relative paths are
+ /// handled automatically by [Builder].
+ Uri pathToUri(String path);
+
String toString() => name;
}
+/// The style for POSIX paths.
+class _PosixStyle extends Style {
+ _PosixStyle();
+
+ static final _builder = new Builder(style: Style.posix);
+
+ final name = 'posix';
+ final separator = '/';
+ final separatorPattern = new RegExp(r'/');
+ final needsSeparatorPattern = new RegExp(r'[^/]$');
+ final rootPattern = new RegExp(r'^/');
+
+ String pathFromUri(Uri uri) {
+ if (uri.scheme == '' || uri.scheme == 'file') {
+ return Uri.decodeComponent(uri.path);
+ }
+ throw new ArgumentError("Uri $uri must have scheme 'file:'.");
+ }
+
+ Uri pathToUri(String path) {
+ var parsed = _builder._parse(path);
+
+ if (parsed.parts.isEmpty) {
+ // If the path is a bare root (e.g. "/"), [components] will
+ // currently be empty. We add two empty components so the URL constructor
+ // produces "file:///", with a trailing slash.
+ parsed.parts.addAll(["", ""]);
+ } else if (parsed.hasTrailingSeparator) {
+ // If the path has a trailing slash, add a single empty component so the
+ // URI has a trailing slash as well.
+ parsed.parts.add("");
+ }
+
+ return new Uri(scheme: 'file', pathSegments: parsed.parts);
+ }
+}
+
+/// The style for Windows paths.
+class _WindowsStyle extends Style {
+ _WindowsStyle();
+
+ static final _builder = new Builder(style: Style.windows);
+
+ final name = 'windows';
+ final separator = '\\';
+ final separatorPattern = new RegExp(r'[/\\]');
+ final needsSeparatorPattern = new RegExp(r'[^/\\]$');
+ final rootPattern = new RegExp(r'^(\\\\|[a-zA-Z]:[/\\])');
+
+ String pathFromUri(Uri uri) {
+ if (uri.scheme != '' && uri.scheme != 'file') {
+ throw new ArgumentError("Uri $uri must have scheme 'file:'.");
+ }
+
+ var path = uri.path;
+ if (uri.host == '') {
+ // Drive-letter paths look like "file:///C:/path/to/file". The
+ // replaceFirst removes the extra initial slash.
+ if (path.startsWith('/')) path = path.replaceFirst("/", "");
+ } else {
+ // Network paths look like "file://hostname/path/to/file".
+ path = '\\\\${uri.host}$path';
+ }
+ return Uri.decodeComponent(path.replaceAll("/", "\\"));
+ }
+
+ Uri pathToUri(String path) {
+ var parsed = _builder._parse(path);
+ if (parsed.root == r'\\') {
+ // Network paths become "file://hostname/path/to/file".
+
+ var host = parsed.parts.removeAt(0);
+
+ if (parsed.parts.isEmpty) {
+ // If the path is a bare root (e.g. "\\hostname"), [parsed.parts] will
+ // currently be empty. We add two empty components so the URL
+ // constructor produces "file://hostname/", with a trailing slash.
+ parsed.parts.addAll(["", ""]);
+ } else if (parsed.hasTrailingSeparator) {
+ // If the path has a trailing slash, add a single empty component so the
+ // URI has a trailing slash as well.
+ parsed.parts.add("");
+ }
+
+ return new Uri(scheme: 'file', host: host, pathSegments: parsed.parts);
+ } else {
+ // Drive-letter paths become "file:///C:/path/to/file".
+
+ // If the path is a bare root (e.g. "C:\"), [parsed.parts] will currently
+ // be empty. We add an empty component so the URL constructor produces
+ // "file:///C:/", with a trailing slash. We also add an empty component if
+ // the URL otherwise has a trailing slash.
+ if (parsed.parts.length == 0 || parsed.hasTrailingSeparator) {
+ parsed.parts.add("");
+ }
+
+ // Get rid of the trailing "\" in "C:\" because the URI constructor will
+ // add a separator on its own.
+ parsed.parts.insert(0, parsed.root.replaceAll(separatorPattern, ""));
+
+ return new Uri(scheme: 'file', pathSegments: parsed.parts);
+ }
+ }
+}
+
+/// The style for URL paths.
+class _UrlStyle extends Style {
+ _UrlStyle();
+
+ final name = 'url';
+ final separator = '/';
+ final separatorPattern = new RegExp(r'/');
+ final needsSeparatorPattern = new RegExp(
+ r"(^[a-zA-Z][-+.a-zA-Z\d]*://|[^/])$");
+ final rootPattern = new RegExp(r"[a-zA-Z][-+.a-zA-Z\d]*://[^/]*");
+ final relativeRootPattern = new RegExp(r"^/");
+
+ String pathFromUri(Uri uri) => uri.toString();
+
+ Uri pathToUri(String path) => Uri.parse(path);
+}
+
// TODO(rnystrom): Make this public?
class _ParsedPath {
/// The [Style] that was used to parse this path.
@@ -848,6 +1047,8 @@
return copy._splitExtension()[0];
}
+ bool get hasTrailingSeparator => !parts.isEmpty && (parts.last == '' || separators.last != '');
+
void removeTrailingSeparators() {
while (!parts.isEmpty && parts.last == '') {
parts.removeLast();
diff --git a/pkg/pathos/test/pathos_posix_test.dart b/pkg/pathos/test/pathos_posix_test.dart
index ecdd133..a446f76 100644
--- a/pkg/pathos/test/pathos_posix_test.dart
+++ b/pkg/pathos/test/pathos_posix_test.dart
@@ -399,4 +399,26 @@
expect(builder.withoutExtension('a/b.c/'), 'a/b/');
expect(builder.withoutExtension('a/b.c//'), 'a/b//');
});
+
+ test('fromUri', () {
+ expect(builder.fromUri(Uri.parse('file:///path/to/foo')), '/path/to/foo');
+ expect(builder.fromUri(Uri.parse('file:///path/to/foo/')), '/path/to/foo/');
+ expect(builder.fromUri(Uri.parse('file:///')), '/');
+ expect(builder.fromUri(Uri.parse('foo/bar')), 'foo/bar');
+ expect(builder.fromUri(Uri.parse('/path/to/foo')), '/path/to/foo');
+ expect(builder.fromUri(Uri.parse('///path/to/foo')), '/path/to/foo');
+ expect(builder.fromUri(Uri.parse('file:///path/to/foo%23bar')),
+ '/path/to/foo#bar');
+ expect(() => builder.fromUri(Uri.parse('http://dartlang.org')),
+ throwsArgumentError);
+ });
+
+ test('toUri', () {
+ expect(builder.toUri('/path/to/foo'), Uri.parse('file:///path/to/foo'));
+ expect(builder.toUri('/path/to/foo/'), Uri.parse('file:///path/to/foo/'));
+ expect(builder.toUri('/'), Uri.parse('file:///'));
+ expect(builder.toUri('foo/bar'), Uri.parse('foo/bar'));
+ expect(builder.toUri('/path/to/foo#bar'),
+ Uri.parse('file:///path/to/foo%23bar'));
+ });
}
diff --git a/pkg/pathos/test/pathos_url_test.dart b/pkg/pathos/test/pathos_url_test.dart
index b8c100f..ff1af86 100644
--- a/pkg/pathos/test/pathos_url_test.dart
+++ b/pkg/pathos/test/pathos_url_test.dart
@@ -625,4 +625,29 @@
expect(builder.withoutExtension('a/b.c/'), 'a/b/');
expect(builder.withoutExtension('a/b.c//'), 'a/b//');
});
+
+
+ test('fromUri', () {
+ expect(builder.fromUri(Uri.parse('http://dartlang.org/path/to/foo')),
+ 'http://dartlang.org/path/to/foo');
+ expect(builder.fromUri(Uri.parse('http://dartlang.org/path/to/foo/')),
+ 'http://dartlang.org/path/to/foo/');
+ expect(builder.fromUri(Uri.parse('file:///path/to/foo')),
+ 'file:///path/to/foo');
+ expect(builder.fromUri(Uri.parse('foo/bar')), 'foo/bar');
+ expect(builder.fromUri(Uri.parse('http://dartlang.org/path/to/foo%23bar')),
+ 'http://dartlang.org/path/to/foo%23bar');
+ });
+
+ test('toUri', () {
+ expect(builder.toUri('http://dartlang.org/path/to/foo'),
+ Uri.parse('http://dartlang.org/path/to/foo'));
+ expect(builder.toUri('http://dartlang.org/path/to/foo/'),
+ Uri.parse('http://dartlang.org/path/to/foo/'));
+ expect(builder.toUri('file:///path/to/foo'),
+ Uri.parse('file:///path/to/foo'));
+ expect(builder.toUri('foo/bar'), Uri.parse('foo/bar'));
+ expect(builder.toUri('http://dartlang.org/path/to/foo%23bar'),
+ Uri.parse('http://dartlang.org/path/to/foo%23bar'));
+ });
}
diff --git a/pkg/pathos/test/pathos_windows_test.dart b/pkg/pathos/test/pathos_windows_test.dart
index 6d22742..a7c8182 100644
--- a/pkg/pathos/test/pathos_windows_test.dart
+++ b/pkg/pathos/test/pathos_windows_test.dart
@@ -441,4 +441,38 @@
expect(builder.withoutExtension(r'a.b/c'), r'a.b/c');
expect(builder.withoutExtension(r'a\b.c\'), r'a\b\');
});
+
+ test('fromUri', () {
+ expect(builder.fromUri(Uri.parse('file:///C:/path/to/foo')),
+ r'C:\path\to\foo');
+ expect(builder.fromUri(Uri.parse('file://hostname/path/to/foo')),
+ r'\\hostname\path\to\foo');
+ expect(builder.fromUri(Uri.parse('file:///C:/')), r'C:\');
+ expect(builder.fromUri(Uri.parse('file://hostname/')), r'\\hostname\');
+ expect(builder.fromUri(Uri.parse('foo/bar')), r'foo\bar');
+ expect(builder.fromUri(Uri.parse('/C:/path/to/foo')), r'C:\path\to\foo');
+ expect(builder.fromUri(Uri.parse('///C:/path/to/foo')), r'C:\path\to\foo');
+ expect(builder.fromUri(Uri.parse('//hostname/path/to/foo')),
+ r'\\hostname\path\to\foo');
+ expect(builder.fromUri(Uri.parse('file:///C:/path/to/foo%23bar')),
+ r'C:\path\to\foo#bar');
+ expect(builder.fromUri(Uri.parse('file://hostname/path/to/foo%23bar')),
+ r'\\hostname\path\to\foo#bar');
+ expect(() => builder.fromUri(Uri.parse('http://dartlang.org')),
+ throwsArgumentError);
+ });
+
+ test('toUri', () {
+ expect(builder.toUri(r'C:\path\to\foo'),
+ Uri.parse('file:///C:/path/to/foo'));
+ expect(builder.toUri(r'C:\path\to\foo\'),
+ Uri.parse('file:///C:/path/to/foo/'));
+ expect(builder.toUri(r'C:\'), Uri.parse('file:///C:/'));
+ expect(builder.toUri(r'\\hostname\'), Uri.parse('file://hostname/'));
+ expect(builder.toUri(r'foo\bar'), Uri.parse('foo/bar'));
+ expect(builder.toUri(r'C:\path\to\foo#bar'),
+ Uri.parse('file:///C:/path/to/foo%23bar'));
+ expect(builder.toUri(r'\\hostname\path\to\foo#bar'),
+ Uri.parse('file://hostname/path/to/foo%23bar'));
+ });
}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 1a4e87f..da54056 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -27,6 +27,8 @@
# testing.
webdriver/test/webdriver_test: Skip
+[ $compiler == dart2js && $runtime == ff ]
+unittest/test/unittest_test: Pass, Timeout # http://dartbug.com/11473
[ $runtime == d8 || $runtime == jsshell ]
unittest/test/unittest_test: Pass, Fail # http://dartbug.com/10109
@@ -48,6 +50,8 @@
[ $runtime == safari ]
fixnum/test/int_64_test: Pass, Fail # Bug in JSC.
+crypto/test/hmac_sha1_test: Fail # Issue 11407.
+crypto/test/sha1_test: Fail # Issue 11407.
# Skip browser-specific tests on VM
[ $runtime == vm ]
@@ -64,11 +68,17 @@
analyzer_experimental/test/generated/ast_test: Fail, Slow # Issue 11230
unittest/test/instance_test: Fail # http://dartbug.com/11191
+[ $compiler == dart2js && $checked ]
+mdv_observe/test/observable_map_test: Fail # BUG(11480): Triage.
+
[ $compiler == dartc ]
unittest/test/mock_regexp_negative_test: Fail
unittest/test/mock_stepwise_negative_test: Fail
[ $compiler == dartanalyzer ]
+# test issue https://code.google.com/p/dart/issues/detail?id=11517
+# These tests are not negetive statically.
+# Requested test fix or permission to mark 'fail, OK'
unittest/test/mock_regexp_negative_test: fail
unittest/test/mock_stepwise_negative_test: fail
@@ -83,12 +93,6 @@
serialization/test/no_library_test: Fail # Issue 6490
[ $compiler == dart2js && $minified ]
-# The unittest package relies on getting the original (non-minified) method
-# names in Invocation. You can't get that when minifying.
-# TODO(ahe/erikcorry): But soon you can, now that we use Symbol.
-unittest/test/mock_test: Fail
-unittest/test/mock_regexp_negative_test: Fail
-
serialization/test/serialization_test: Fail # Issue 6490
serialization/test/no_library_test: Fail # Issue 6490
@@ -105,15 +109,13 @@
crypto/test/sha256_test: Slow, Pass
crypto/test/sha1_test: Slow, Pass
-[ $compiler == dart2js && $checked ]
-pathos/test/pathos_dartium_test: Crash
-
[ $browser ]
analyzer_experimental/test/error_test: Fail, OK # Uses dart:io.
analyzer_experimental/test/generated/element_test: Fail, OK # Uses dart:io.
analyzer_experimental/test/generated/resolver_test: Fail, OK # Uses dart:io.
analyzer_experimental/test/options_test: Fail, OK # Uses dart:io.
analyzer_experimental/test/services/formatter_test: Fail, OK # Uses dart:io.
+barback/test/*: Fail, OK # Uses dart:io.
http/test/client_test: Fail, OK # Uses dart:io.
http/test/http_test: Fail, OK # Uses dart:io.
http/test/mock_client_test: Fail, OK # Uses dart:io.
@@ -121,6 +123,7 @@
http/test/request_test: Fail, OK # Uses dart:io.
http/test/response_test: Fail, OK # Uses dart:io.
http/test/streamed_request_test: Fail, OK # Uses dart:io.
+http_server/test/*: Fail, OK # Uses dart:io.
intl/test/date_time_format_file_even_test: Fail, OK # Uses dart:io.
intl/test/date_time_format_file_odd_test: Fail, OK # Uses dart:io.
intl/test/find_default_locale_standalone_test: Fail, OK # Uses dart:io.
diff --git a/pkg/scheduled_test/test/metatest.dart b/pkg/scheduled_test/test/metatest.dart
index 71ad421..9bbd2e4 100644
--- a/pkg/scheduled_test/test/metatest.dart
+++ b/pkg/scheduled_test/test/metatest.dart
@@ -133,9 +133,9 @@
/// describing the results of that test run.
Future<Map> _runInIsolate(String description) {
// TODO(nweiz): Don't use path here once issue 8440 is fixed.
- var future = spawnUri(path.join(path.current, new Options().script)).call({
+ var future = spawnUri(path.join(path.current, Platform.script)).call({
'testToRun': description,
- 'executable': new Options().executable
+ 'executable': Platform.executable
});
// TODO(nweiz): Remove this timeout once issue 8417 is fixed and we can
// capture top-level exceptions.
diff --git a/pkg/scheduled_test/test/scheduled_process_test.dart b/pkg/scheduled_test/test/scheduled_process_test.dart
index f24758c..3f07c66 100644
--- a/pkg/scheduled_test/test/scheduled_process_test.dart
+++ b/pkg/scheduled_test/test/scheduled_process_test.dart
@@ -365,8 +365,7 @@
var dartPath = schedule(() {
return tempDir.then((dir) {
- var utilsPath = path.absolute(path.join(
- new Options().script, 'utils.dart'));
+ var utilsPath = path.absolute(path.join(Platform.script, 'utils.dart'));
return new File(path.join(dir, 'test.dart')).writeAsString('''
import 'dart:async';
import 'dart:io';
diff --git a/pkg/serialization/lib/src/format.dart b/pkg/serialization/lib/src/format.dart
index 93a345b..2c71e42 100644
--- a/pkg/serialization/lib/src/format.dart
+++ b/pkg/serialization/lib/src/format.dart
@@ -67,7 +67,7 @@
* the data also includes rule definitions, then these will replace the rules
* in the [Serialization] for [reader].
*/
- Map<String, dynamic> read(topLevel, Reader reader) {
+ Map<String, dynamic> read(Map<String, dynamic> topLevel, Reader reader) {
var ruleString = topLevel["rules"];
reader.readRules(ruleString);
reader._data = topLevel["data"];
@@ -150,7 +150,7 @@
* the data also includes rule definitions, then these will replace the rules
* in the [Serialization] for [reader].
*/
- Map<String, dynamic> read(topLevel, Reader reader) {
+ Map<String, dynamic> read(Map<String, dynamic> topLevel, Reader reader) {
super.read(topLevel, reader);
forAllStates(reader,
(ref) => ref is Map && ref["__Ref"] != null,
diff --git a/pkg/serialization/lib/src/serialization_helpers.dart b/pkg/serialization/lib/src/serialization_helpers.dart
index 1f86a97..87fe55c 100644
--- a/pkg/serialization/lib/src/serialization_helpers.dart
+++ b/pkg/serialization/lib/src/serialization_helpers.dart
@@ -190,7 +190,7 @@
final List<K> keys = <K>[];
final List<V> values = <V>[];
- V operator [](K key) {
+ V operator [](Object key) {
var index = _indexOf(key);
return (index == -1) ? null : values[index];
}
@@ -205,7 +205,7 @@
}
}
- putIfAbsent(K key, Function ifAbsent) {
+ V putIfAbsent(K key, Function ifAbsent) {
var index = _indexOf(key);
if (index == -1) {
keys.add(key);
@@ -216,7 +216,7 @@
}
}
- _indexOf(K key) {
+ int _indexOf(Object key) {
// Go backwards on the guess that we are most likely to access the most
// recently added.
// Make strings and primitives unique
@@ -228,14 +228,14 @@
return -1;
}
- bool containsKey(K key) => _indexOf(key) != -1;
+ bool containsKey(Object key) => _indexOf(key) != -1;
void forEach(f(K key, V value)) {
for (var i = 0; i < keys.length; i++) {
f(keys[i], values[i]);
}
}
- V remove(K key) {
+ V remove(Object key) {
var index = _indexOf(key);
if (index == -1) return null;
keys.removeAt(index);
@@ -251,5 +251,11 @@
bool get isNotEmpty => !isEmpty;
// Note that this is doing an equality comparison.
- bool containsValue(x) => values.contains(x);
+ bool containsValue(Object x) => values.contains(x);
+
+ void addAll(Map<K, V> other) {
+ other.forEach((K key, V value) {
+ this[key] = value;
+ });
+ }
}
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index aad0aaf..ddfac08 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -546,8 +546,9 @@
}
operator []=(x, y) => _throw();
putIfAbsent(x, y) => _throw();
- remove(x) => _throw();
- clear() => _throw();
+ bool remove(x) => _throw();
+ void clear() => _throw();
+ void addAll(Map other) => _throw();
}
/**
@@ -557,55 +558,20 @@
* looks like it's just a list of objects to a [CustomRule] without needing
* to inflate all the references in advance.
*/
-class _LazyList extends IterableBase implements List {
+class _LazyList extends IterableBase with ListMixin implements List {
_LazyList(this._raw, this._reader);
final List _raw;
final Reader _reader;
- // This is the only operation that really matters.
- operator [](x) => _reader.inflateReference(_raw[x]);
-
+ operator [](int x) => _reader.inflateReference(_raw[x]);
int get length => _raw.length;
- bool get isEmpty => _raw.isEmpty;
- get first => _reader.inflateReference(_raw.first);
- get last => _reader.inflateReference(_raw.last);
- // These operations, and other inherited methods that iterate over the whole
- // list will work, but may be expensive, and are probably
- // best avoided.
- Iterable get _inflated => _raw.map(_reader.inflateReference);
- Iterator get iterator => _inflated.iterator;
- indexOf(x, [pos = 0]) => _inflated.toList().indexOf(x);
- lastIndexOf(x, [pos]) => _inflated.toList().lastIndexOf(x);
- sublist(start, [end]) => _inflated.sublist(start, end);
+ void set length(int value) => _throw();
- Map<int, dynamic> asMap() => _inflated.asMap();
+ void operator []=(int index, value) => _throw();
- // These operations are all invalid
- _throw() {
+ void _throw() {
throw new UnsupportedError("Not modifiable");
}
- operator []=(x, y) => _throw();
- add(x) => _throw();
- addAll(x) => _throw();
- sort([f]) => _throw();
- clear() => _throw();
- insert(x, y) => _throw();
- insertAll(x, y) => _throw();
- fillRange(x, y, [z]) => _throw();
- removeAt(x) => _throw();
- remove(x) => _throw();
- removeLast() => _throw();
- removeAll(x) => _throw();
- retainAll(x) => _throw();
- removeWhere(x) => _throw();
- retainWhere(x) => _throw();
- replaceRange(x, y, z) => _throw();
- getRange(x, y) => _throw();
- setRange(x, y, z, [a = 0]) => _throw();
- setAll(x, y) => _throw();
- removeRange(x, y) => _throw();
- get reversed => _throw();
- void set length(x) => _throw();
}
diff --git a/pkg/serialization/test/serialization_test.dart b/pkg/serialization/test/serialization_test.dart
index 1b79206..1e2d3aa 100644
--- a/pkg/serialization/test/serialization_test.dart
+++ b/pkg/serialization/test/serialization_test.dart
@@ -13,7 +13,7 @@
part 'test_models.dart';
-main() {
+void main() {
var p1 = new Person();
var a1 = new Address();
a1.street = 'N 34th';
@@ -554,14 +554,14 @@
var s = nodeSerializerReflective(n1);
var output = s.write(n2);
var port = spawnFunction(echo);
- port.call(output).then(expectAsync1((input) => verify(input)));
+ return port.call(output).then(verify);
});
}
/**
* Verify serialized output that we have passed to an isolate and back.
*/
-verify(input) {
+void verify(input) {
var s2 = nodeSerializerReflective(new Node("a"));
var reader = new Reader(s2);
var m2 = reader.read(input);
@@ -718,7 +718,7 @@
* Run a round-trip test on a simple tree of nodes, using a serialization
* that's returned by the [serializerSetUp] function.
*/
-runRoundTripTest(Function serializerSetUp) {
+void runRoundTripTest(Function serializerSetUp) {
Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
n1.children = [n2, n3];
n2.parent = n1;
@@ -744,7 +744,7 @@
* Run a round-trip test on a simple of nodes, but using the flat format
* rather than the maps.
*/
-runRoundTripTestFlat(serializerSetUp) {
+void runRoundTripTestFlat(serializerSetUp) {
Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
n1.children = [n2, n3];
n2.parent = n1;
@@ -768,7 +768,7 @@
}
/** Extract the state from [object] using the rules in [s] and return it. */
-states(object, Serialization s) {
+List states(object, Serialization s) {
var rules = s.rulesFor(object, null);
return rules.map((x) => x.extractState(object, doNothing, null)).toList();
}
@@ -816,7 +816,7 @@
* Function used in an isolate to make sure that the output passes through
* isolate serialization properly.
*/
-echo() {
+void echo() {
port.receive((msg, reply) {
reply.send(msg);
});
diff --git a/pkg/stack_trace/lib/src/frame.dart b/pkg/stack_trace/lib/src/frame.dart
index 8f1931b..d750b91 100644
--- a/pkg/stack_trace/lib/src/frame.dart
+++ b/pkg/stack_trace/lib/src/frame.dart
@@ -8,7 +8,6 @@
import 'package:pathos/path.dart' as path;
import 'trace.dart';
-import 'utils.dart';
final _nativeFrameRegExp = new RegExp(
r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$');
@@ -43,12 +42,11 @@
/// Returns a human-friendly description of the library that this stack frame
/// comes from.
///
- /// This will usually be the string form of [uri], but a relative path will be
+ /// This will usually be the string form of [uri], but a relative URI will be
/// used if possible.
String get library {
- // TODO(nweiz): handle relative URIs here as well once pathos supports that.
if (uri.scheme != 'file') return uri.toString();
- return path.relative(fileUriToPath(uri));
+ return path.relative(path.fromUri(uri));
}
/// Returns the name of the package this stack frame comes from, or `null` if
diff --git a/pkg/stack_trace/test/frame_test.dart b/pkg/stack_trace/test/frame_test.dart
index d1f53f6..a140670 100644
--- a/pkg/stack_trace/test/frame_test.dart
+++ b/pkg/stack_trace/test/frame_test.dart
@@ -7,7 +7,6 @@
import 'dart:io';
import 'package:pathos/path.dart' as path;
-import 'package:stack_trace/src/utils.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:unittest/unittest.dart';
@@ -41,7 +40,7 @@
// TODO(nweiz): use URL-style paths when such a thing exists.
var builder = new path.Builder(style: path.Style.posix);
expect(builder.basename(frame.uri.path), equals('frame_test.dart'));
- expect(frame.line, equals(16));
+ expect(frame.line, equals(15));
expect(frame.column, equals(5));
expect(frame.member, equals('getStackFrame'));
});
@@ -115,9 +114,8 @@
});
test('returns the relative path for file URIs', () {
- var uri = pathToFileUri(path.join('foo', 'bar.dart'));
- expect(new Frame.parse('#0 Foo ($uri:0:0)').library,
- equals(path.join('foo', 'bar.dart')));
+ expect(new Frame.parse('#0 Foo (foo/bar.dart:0:0)').library,
+ equals('foo/bar.dart'));
});
});
@@ -127,9 +125,8 @@
expect(new Frame.parse('#0 Foo '
'(http://dartlang.org/thing.dart:5:10)').location,
equals('http://dartlang.org/thing.dart 5:10'));
- var uri = pathToFileUri(path.join('foo', 'bar.dart'));
- expect(new Frame.parse('#0 Foo ($uri:1:2)').location,
- equals('${path.join('foo', 'bar.dart')} 1:2'));
+ expect(new Frame.parse('#0 Foo (foo/bar.dart:1:2)').location,
+ equals('foo/bar.dart 1:2'));
});
});
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index 902ae80..fcf4fe5 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -7,7 +7,6 @@
import 'dart:io';
import 'package:pathos/path.dart' as path;
-import 'package:stack_trace/src/utils.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:unittest/unittest.dart';
@@ -91,15 +90,14 @@
});
test('.toString() nicely formats the stack trace', () {
- var uri = pathToFileUri(path.join('foo', 'bar.dart'));
var trace = new Trace.parse('''
-#0 Foo._bar ($uri:42:21)
+#0 Foo._bar (foo/bar.dart:42:21)
#1 zip.<anonymous closure>.zap (dart:async/future.dart:0:2)
#2 zip.<anonymous closure>.zap (http://pub.dartlang.org/thing.dart:1:100)
''');
expect(trace.toString(), equals('''
-${path.join('foo', 'bar.dart')} 42:21 Foo._bar
+foo/bar.dart 42:21 Foo._bar
dart:async/future.dart 0:2 zip.<fn>.zap
http://pub.dartlang.org/thing.dart 1:100 zip.<fn>.zap
'''));
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 4b5bdbb..ca7cfb6 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -87,7 +87,7 @@
*/
Matcher equals(expected, [limit=100]) =>
expected is String
- ? new _StringEqualsMatcher(expected)
+ ? new _StringEqualsMatcher(expected)
: new _DeepMatcher(expected, limit);
class _DeepMatcher extends BaseMatcher {
@@ -106,8 +106,8 @@
var actualIterator = actual.iterator;
var index = 0;
while (true) {
+ var newLocation = '${location}[${index}]';
if (expectedIterator.moveNext()) {
- var newLocation = '${location}[${index}]';
if (actualIterator.moveNext()) {
var rp = matcher(expectedIterator.current,
actualIterator.current, newLocation,
@@ -220,7 +220,7 @@
Description describeMismatch(item, Description mismatchDescription,
Map matchState, bool verbose) {
var reason = matchState['reason'];
- // If we didn't get a good reason, that would normally be a
+ // If we didn't get a good reason, that would normally be a
// simple 'is <value>' message. We only add that if the mismatch
// description is non empty (so we are supplementing the mismatch
// description).
diff --git a/pkg/unittest/lib/src/interfaces.dart b/pkg/unittest/lib/src/interfaces.dart
index 660c49f..f45e164 100644
--- a/pkg/unittest/lib/src/interfaces.dart
+++ b/pkg/unittest/lib/src/interfaces.dart
@@ -26,6 +26,8 @@
* some cases - e.g. language conversion.
*/
abstract class Description {
+ int get length;
+
/** Change the value of the description. */
Description replace(String text);
diff --git a/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
new file mode 100644
index 0000000..dbdf64d
--- /dev/null
+++ b/pkg/unmodifiable_collection/lib/unmodifiable_collection.dart
@@ -0,0 +1,234 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/**
+ * Unmodifiable wrappers for [List], [Set] and [Map] objects.
+ *
+ * The wrappers allow reading from the source list, but writing is prohibited.
+ *
+ * A non-growable list wrapper allows writing as well, but not changing the
+ * list's length.
+ */
+library unmodifiable_collection;
+
+export "dart:collection" show UnmodifiableListView;
+
+/**
+ * A [List] wrapper that acts as a non-growable list.
+ *
+ * Writes to the list are written through to the source list, but operations
+ * that change the length is not allowed.
+ */
+class NonGrowableListView<E> extends _IterableView<E>
+ implements List<E> {
+ List<E> _source;
+ NonGrowableListView(List<E> source) : _source = source;
+
+ static void _throw() {
+ throw new UnsupportedError(
+ "Cannot change the length of a fixed-length list");
+ }
+
+ int get length => _source.length;
+
+ E operator [](int index) => _source[index];
+
+ int indexOf(E element, [int start = 0]) => _source.indexOf(element, start);
+
+ int lastIndexOf(E element, [int start])
+ => _source.lastIndexOf(element, start);
+
+ Iterable<E> getRange(int start, int end) => _source.getRange(start, end);
+
+ List<E> sublist(int start, [int end]) => _source.sublist(start, end);
+
+ Iterable<E> get reversed => _source.reversed;
+
+ Map<int, E> asMap() => _source.asMap();
+
+
+ void operator []=(int index, E value) { _source[index] = value; }
+
+ void sort([int compare(E a, E b)]) { _source.sort(compare); }
+
+ void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
+ _source.setRange(start, end, iterable, skipCount);
+ }
+
+ void fillRange(int start, int end, [E fillValue]) {
+ _source.fillRange(start, end, fillValue);
+ }
+
+ void setAll(int index, Iterable<E> iterable) {
+ _source.setAll(index, iterable);
+ }
+
+
+ void set length(int newLength) => _throw();
+
+ void add(E value) => _throw();
+
+ void addAll(Iterable<E> iterable) => _throw();
+
+ void insert(int index, E element) => _throw();
+
+ void insertAll(int index, Iterable<E> iterable) => _throw();
+
+ bool remove(Object value) { _throw(); }
+
+ E removeAt(int index) { _throw(); }
+
+ E removeLast() { _throw(); }
+
+ void removeWhere(bool test(E element)) => _throw();
+
+ void retainWhere(bool test(E element)) => _throw();
+
+ void removeRange(int start, int end) => _throw();
+
+ void replaceRange(int start, int end, Iterable<E> iterable) => _throw();
+
+ void clear() => _throw();
+}
+
+/**
+ * A [Set] wrapper that acts as an unmodifiable set.
+ */
+class UnmodifiableSetView<E> extends _IterableView<E>
+ implements Set<E> {
+ Set<E> _source;
+ UnmodifiableSetView(Set<E> source) : _source = source;
+
+ void _throw() {
+ throw new UnsupportedError("Cannot modify an unmodifiable Set");
+ }
+
+ bool containsAll(Iterable<E> other) => _source.containsAll(other);
+
+ Set<E> intersection(Set<E> other) => _source.intersection(other);
+
+ Set<E> union(Set<E> other) => _source.union(other);
+
+ Set<E> difference(Set<E> other) => _source.difference(other);
+
+
+ void add(E value) => _throw();
+
+ void addAll(Iterable<E> elements) => _throw();
+
+ bool remove(Object value) { _throw(); }
+
+ void removeAll(Iterable elements) => _throw();
+
+ void retainAll(Iterable elements) => _throw();
+
+ void removeWhere(bool test(E element)) => _throw();
+
+ void retainWhere(bool test(E element)) => _throw();
+
+ void clear() => _throw();
+}
+
+/**
+ * A [Map] wrapper that acts as an unmodifiable map.
+ */
+class UnmodifiableMapView<K, V> implements Map<K, V> {
+ Map<K, V> _source;
+ UnmodifiableMapView(Map<K, V> source) : _source = source;
+
+ static void _throw() {
+ throw new UnsupportedError("Cannot modify an unmodifiable Map");
+ }
+
+ int get length => _source.length;
+
+ bool get isEmpty => _source.isEmpty;
+
+ bool get isNotEmpty => _source.isNotEmpty;
+
+ V operator [](K key) => _source[key];
+
+ bool containsKey(K key) => _source.containsKey(key);
+
+ bool containsValue(V value) => _source.containsValue(value);
+
+ void forEach(void f(K key, V value)) => _source.forEach(f);
+
+ Iterable<K> get keys => _source.keys;
+
+ Iterable<V> get values => _source.values;
+
+
+ void operator []=(K key, V value) => _throw();
+
+ V putIfAbsent(K key, V ifAbsent()) { _throw(); }
+
+ void addAll(Map<K, V> other) => _throw();
+
+ V remove(K key) { _throw(); }
+
+ void clear() => _throw();
+}
+
+abstract class _IterableView<E> {
+ Iterable<E> get _source;
+
+ bool any(bool test(E element)) => _source.any(test);
+
+ bool contains(E element) => _source.contains(element);
+
+ E elementAt(int index) => _source.elementAt(index);
+
+ bool every(bool test(E element)) => _source.every(test);
+
+ Iterable expand(Iterable f(E element)) => _source.expand(f);
+
+ E get first => _source.first;
+
+ E firstWhere(bool test(E element), { E orElse() })
+ => _source.firstWhere(test, orElse: orElse);
+
+ dynamic fold(var initialValue,
+ dynamic combine(var previousValue, E element))
+ => _source.fold(initialValue, combine);
+
+ void forEach(void f(E element)) => _source.forEach(f);
+
+ bool get isEmpty => _source.isEmpty;
+
+ bool get isNotEmpty => _source.isNotEmpty;
+
+ Iterator<E> get iterator => _source.iterator;
+
+ String join([String separator = ""]) => _source.join(separator);
+
+ E get last => _source.last;
+
+ E lastWhere(bool test(E element), {E orElse()})
+ => _source.lastWhere(test, orElse: orElse);
+
+ int get length => _source.length;
+
+ Iterable map(f(E element)) => _source.map(f);
+
+ E reduce(E combine(E value, E element)) => _source.reduce(combine);
+
+ E get single => _source.single;
+
+ E singleWhere(bool test(E element)) => _source.singleWhere(test);
+
+ Iterable<E> skip(int n) => _source.skip(n);
+
+ Iterable<E> skipWhile(bool test(E value)) => _source.skipWhile(test);
+
+ Iterable<E> take(int n) => _source.take(n);
+
+ Iterable<E> takeWhile(bool test(E value)) => _source.takeWhile(test);
+
+ List<E> toList({ bool growable: true }) => _source.toList(growable: growable);
+
+ Set<E> toSet() => _source.toSet();
+
+ Iterable<E> where(bool test(E element)) => _source.where(test);
+}
diff --git a/pkg/unmodifiable_collection/pubspec.yaml b/pkg/unmodifiable_collection/pubspec.yaml
new file mode 100644
index 0000000..43cbc11
--- /dev/null
+++ b/pkg/unmodifiable_collection/pubspec.yaml
@@ -0,0 +1,7 @@
+name: unmodifiable_collection
+author: "Dart Team <misc@dartlang.org>"
+homepage: http://www.dartlang.org
+description: >
+ Unmodifiable wrappers for base collection types.
+dev_dependencies:
+ unittest: any
diff --git a/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart b/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart
new file mode 100644
index 0000000..2e96e48
--- /dev/null
+++ b/pkg/unmodifiable_collection/test/unmodifiable_collection_test.dart
@@ -0,0 +1,629 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:unmodifiable_collection/unmodifiable_collection.dart";
+import "package:unittest/unittest.dart";
+
+// Test unmodifiable collection views.
+// The collections should pass through the operations that are allowed,
+// an throw on the ones that aren't without affecting the original.
+
+main() {
+ List list = [];
+ testUnmodifiableList(list, new UnmodifiableListView(list), "empty");
+ list = [42];
+ testUnmodifiableList(list, new UnmodifiableListView(list), "single-42");
+ list = [7];
+ testUnmodifiableList(list, new UnmodifiableListView(list), "single!42");
+ list = [1, 42, 10];
+ testUnmodifiableList(list, new UnmodifiableListView(list), "three-42");
+ list = [1, 7, 10];
+ testUnmodifiableList(list, new UnmodifiableListView(list), "three!42");
+
+ list = [];
+ testNonGrowableList(list, new NonGrowableListView(list), "empty");
+ list = [42];
+ testNonGrowableList(list, new NonGrowableListView(list), "single-42");
+ list = [7];
+ testNonGrowableList(list, new NonGrowableListView(list), "single!42");
+ list = [1, 42, 10];
+ testNonGrowableList(list, new NonGrowableListView(list), "three-42");
+ list = [1, 7, 10];
+ testNonGrowableList(list, new NonGrowableListView(list), "three!42");
+
+ Set aSet = new Set();
+ testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "empty");
+ aSet = new Set.from([42]);
+ testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "single-42");
+ aSet = new Set.from([7]);
+ testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "single!42");
+ aSet = new Set.from([1, 42, 10]);
+ testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "three-42");
+ aSet = new Set.from([1, 7, 10]);
+ testUnmodifiableSet(aSet, new UnmodifiableSetView(aSet), "three!42");
+
+ Map map = new Map();
+ testUnmodifiableMap(map, new UnmodifiableMapView(map), "empty");
+ map = new Map()..[0] = 2;
+ testUnmodifiableMap(map, new UnmodifiableMapView(map), "single-0");
+ map = new Map()..[3] = 2;
+ testUnmodifiableMap(map, new UnmodifiableMapView(map), "single!0");
+ map = new Map()..[0] = 2
+ ..[1] = 1
+ ..[2] = 0;
+ testUnmodifiableMap(map, new UnmodifiableMapView(map), "three-0");
+ map = new Map()..[3] = 2
+ ..[1] = 1
+ ..[2] = 3;
+ testUnmodifiableMap(map, new UnmodifiableMapView(map), "three!0");
+}
+
+void testUnmodifiableList(List original, List wrapped, String name) {
+ name = "unmodifiable-list-$name";
+ testIterable(original, wrapped, name);
+ testReadList(original, wrapped, name);
+ testNoWriteList(original, wrapped, name);
+ testNoChangeLengthList(original, wrapped, name);
+}
+
+void testNonGrowableList(List original, List wrapped, String name) {
+ name = "nongrowable-list-$name";
+ testIterable(original, wrapped, name);
+ testReadList(original, wrapped, name);
+ testWriteList(original, wrapped, name);
+ testNoChangeLengthList(original, wrapped, name);
+}
+
+void testUnmodifiableSet(Set original, Set wrapped, String name) {
+ name = "unmodifiable-set-$name";
+ testIterable(original, wrapped, name);
+ testReadSet(original, wrapped, name);
+ testNoChangeSet(original, wrapped, name);
+}
+
+void testUnmodifiableMap(Map original, Map wrapped, name) {
+ name = "unmodifiable-map-$name";
+ testReadMap(original, wrapped, name);
+ testNoChangeMap(original, wrapped, name);
+}
+
+void testIterable(Iterable original, Iterable wrapped, String name) {
+ test("$name - any", () {
+ expect(wrapped.any((x) => true), equals(original.any((x) => true)));
+ expect(wrapped.any((x) => false), equals(original.any((x) => false)));
+ });
+
+ test("$name - contains", () {
+ expect(wrapped.contains(0), equals(original.contains(0)));
+ });
+
+ test("$name - elementAt", () {
+ if (original.isEmpty) {
+ expect(() => wrapped.elementAt(0), throws);
+ } else {
+ expect(wrapped.elementAt(0), equals(original.elementAt(0)));
+ }
+ });
+
+ test("$name - every", () {
+ expect(wrapped.every((x) => true), equals(original.every((x) => true)));
+ expect(wrapped.every((x) => false), equals(original.every((x) => false)));
+ });
+
+ test("$name - expand", () {
+ expect(wrapped.expand((x) => [x, x]),
+ equals(original.expand((x) => [x, x])));
+ });
+
+ test("$name - first", () {
+ if (original.isEmpty) {
+ expect(() => wrapped.first, throws);
+ } else {
+ expect(wrapped.first, equals(original.first));
+ }
+ });
+
+ test("$name - firstWhere", () {
+ if (original.isEmpty) {
+ expect(() => wrapped.firstWhere((_) => true), throws);
+ } else {
+ expect(wrapped.firstWhere((_) => true),
+ equals(original.firstWhere((_) => true)));
+ }
+ expect(() => wrapped.firstWhere((_) => false), throws);
+ });
+
+ test("$name - fold", () {
+ expect(wrapped.fold(0, (x, y) => x + y),
+ equals(original.fold(0, (x, y) => x + y)));
+ });
+
+ test("$name - forEach", () {
+ int wrapCtr = 0;
+ int origCtr = 0;
+ wrapped.forEach((x) { wrapCtr += x; });
+ original.forEach((x) { origCtr += x; });
+ expect(wrapCtr, equals(origCtr));
+ });
+
+ test("$name - isEmpty", () {
+ expect(wrapped.isEmpty, equals(original.isEmpty));
+ });
+
+ test("$name - isNotEmpty", () {
+ expect(wrapped.isNotEmpty, equals(original.isNotEmpty));
+ });
+
+ test("$name - iterator", () {
+ Iterator wrapIter = wrapped.iterator;
+ Iterator origIter = original.iterator;
+ while (origIter.moveNext()) {
+ expect(wrapIter.moveNext(), equals(true));
+ expect(wrapIter.current, equals(origIter.current));
+ }
+ expect(wrapIter.moveNext(), equals(false));
+ });
+
+ test("$name - join", () {
+ expect(wrapped.join(""), equals(original.join("")));
+ expect(wrapped.join("-"), equals(original.join("-")));
+ });
+
+ test("$name - last", () {
+ if (original.isEmpty) {
+ expect(() => wrapped.last, throws);
+ } else {
+ expect(wrapped.last, equals(original.last));
+ }
+ });
+
+ test("$name - lastWhere", () {
+ if (original.isEmpty) {
+ expect(() => wrapped.lastWhere((_) => true), throws);
+ } else {
+ expect(wrapped.lastWhere((_) => true),
+ equals(original.lastWhere((_) => true)));
+ }
+ expect(() => wrapped.lastWhere((_) => false), throws);
+ });
+
+ test("$name - length", () {
+ expect(wrapped.length, equals(original.length));
+ });
+
+ test("$name - map", () {
+ expect(wrapped.map((x) => "[$x]"),
+ equals(original.map((x) => "[$x]")));
+ });
+
+ test("$name - reduce", () {
+ if (original.isEmpty) {
+ expect(() => wrapped.reduce((x, y) => x + y), throws);
+ } else {
+ expect(wrapped.reduce((x, y) => x + y),
+ equals(original.reduce((x, y) => x + y)));
+ }
+ });
+
+ test("$name - single", () {
+ if (original.length != 1) {
+ expect(() => wrapped.single, throws);
+ } else {
+ expect(wrapped.single, equals(original.single));
+ }
+ });
+
+ test("$name - singleWhere", () {
+ if (original.length != 1) {
+ expect(() => wrapped.singleWhere((_) => true), throws);
+ } else {
+ expect(wrapped.singleWhere((_) => true),
+ equals(original.singleWhere((_) => true)));
+ }
+ expect(() => wrapped.singleWhere((_) => false), throws);
+ });
+
+ test("$name - skip", () {
+ expect(wrapped.skip(0), equals(original.skip(0)));
+ expect(wrapped.skip(1), equals(original.skip(1)));
+ expect(wrapped.skip(5), equals(original.skip(5)));
+ });
+
+ test("$name - skipWhile", () {
+ expect(wrapped.skipWhile((x) => true),
+ equals(original.skipWhile((x) => true)));
+ expect(wrapped.skipWhile((x) => false),
+ equals(original.skipWhile((x) => false)));
+ expect(wrapped.skipWhile((x) => x != 42),
+ equals(original.skipWhile((x) => x != 42)));
+ });
+
+ test("$name - take", () {
+ expect(wrapped.take(0), equals(original.take(0)));
+ expect(wrapped.take(1), equals(original.take(1)));
+ expect(wrapped.take(5), equals(original.take(5)));
+ });
+
+ test("$name - takeWhile", () {
+ expect(wrapped.takeWhile((x) => true),
+ equals(original.takeWhile((x) => true)));
+ expect(wrapped.takeWhile((x) => false),
+ equals(original.takeWhile((x) => false)));
+ expect(wrapped.takeWhile((x) => x != 42),
+ equals(original.takeWhile((x) => x != 42)));
+ });
+
+ test("$name - toList", () {
+ expect(wrapped.toList(), equals(original.toList()));
+ expect(wrapped.toList(growable: false),
+ equals(original.toList(growable: false)));
+ });
+
+ test("$name - toSet", () {
+ expect(wrapped.toSet(), equals(original.toSet()));
+ });
+
+ test("$name - where", () {
+ expect(wrapped.where((x) => true),
+ equals(original.where((x) => true)));
+ expect(wrapped.where((x) => false),
+ equals(original.where((x) => false)));
+ expect(wrapped.where((x) => x != 42),
+ equals(original.where((x) => x != 42)));
+ });
+}
+
+void testReadList(List original, List wrapped, String name) {
+ test("$name - length", () {
+ expect(wrapped.length, equals(original.length));
+ });
+
+ test("$name - isEmpty", () {
+ expect(wrapped.isEmpty, equals(original.isEmpty));
+ });
+
+ test("$name - isNotEmpty", () {
+ expect(wrapped.isNotEmpty, equals(original.isNotEmpty));
+ });
+
+ test("$name - []", () {
+ if (original.isEmpty) {
+ expect(() { wrapped[0]; }, throwsRangeError);
+ } else {
+ expect(wrapped[0], equals(original[0]));
+ }
+ });
+
+ test("$name - indexOf", () {
+ expect(wrapped.indexOf(42), equals(original.indexOf(42)));
+ });
+
+ test("$name - lastIndexOf", () {
+ expect(wrapped.lastIndexOf(42), equals(original.lastIndexOf(42)));
+ });
+
+ test("$name - getRange", () {
+ int len = original.length;
+ expect(wrapped.getRange(0, len), equals(original.getRange(0, len)));
+ expect(wrapped.getRange(len ~/ 2, len),
+ equals(original.getRange(len ~/ 2, len)));
+ expect(wrapped.getRange(0, len ~/ 2),
+ equals(original.getRange(0, len ~/ 2)));
+ });
+
+ test("$name - sublist", () {
+ int len = original.length;
+ expect(wrapped.sublist(0), equals(original.sublist(0)));
+ expect(wrapped.sublist(len ~/ 2), equals(original.sublist(len ~/ 2)));
+ expect(wrapped.sublist(0, len ~/ 2),
+ equals(original.sublist(0, len ~/ 2)));
+ });
+
+ test("$name - asMap", () {
+ expect(wrapped.asMap(), equals(original.asMap()));
+ });
+}
+
+void testNoWriteList(List original, List wrapped, String name) {
+ List copy = new List.from(original);
+
+ testThrows(name, thunk) {
+ test(name, () {
+ expect(thunk, throwsUnsupportedError);
+ // No modifications happened.
+ expect(original, equals(copy));
+ });
+ }
+
+ testThrows("$name - []= throws", () { wrapped[0] = 42; });
+
+ testThrows("$name - sort throws", () { wrapped.sort(); });
+
+ testThrows("$name - fillRange throws", () {
+ wrapped.fillRange(0, wrapped.length, 42);
+ });
+
+ testThrows("$name - setRange throws", () {
+ wrapped.setRange(0, wrapped.length,
+ new Iterable.generate(wrapped.length, (i) => i));
+ });
+
+ testThrows("$name - setAll throws", () {
+ wrapped.setAll(0, new Iterable.generate(wrapped.length, (i) => i));
+ });
+}
+
+void testWriteList(List original, List wrapped, String name) {
+ List copy = new List.from(original);
+
+ test("$name - []=", () {
+ if (original.isNotEmpty) {
+ int originalFirst = original[0];
+ wrapped[0] = originalFirst + 1;
+ expect(original[0], equals(originalFirst + 1));
+ original[0] = originalFirst;
+ } else {
+ expect(() { wrapped[0] = 42; }, throws);
+ }
+ });
+
+ test("$name - sort", () {
+ List sortCopy = new List.from(original);
+ sortCopy.sort();
+ wrapped.sort();
+ expect(original, equals(sortCopy));
+ original.setAll(0, copy);
+ });
+
+ test("$name - fillRange", () {
+ wrapped.fillRange(0, wrapped.length, 37);
+ for (int i = 0; i < original.length; i++) {
+ expect(original[i], equals(37));
+ }
+ original.setAll(0, copy);
+ });
+
+ test("$name - setRange", () {
+ List reverseList = original.reversed.toList();
+ wrapped.setRange(0, wrapped.length, reverseList);
+ expect(original, equals(reverseList));
+ original.setAll(0, copy);
+ });
+
+ test("$name - setAll", () {
+ List reverseList = original.reversed.toList();
+ wrapped.setAll(0, reverseList);
+ expect(original, equals(reverseList));
+ original.setAll(0, copy);
+ });
+}
+
+void testNoChangeLengthList(List original, List wrapped, String name) {
+ List copy = new List.from(original);
+
+ testThrows(name, thunk) {
+ test(name, () {
+ expect(thunk, throwsUnsupportedError);
+ // No modifications happened.
+ expect(original, equals(copy));
+ });
+ }
+
+ testThrows("$name - length= throws", () {
+ wrapped.length = 100;
+ });
+
+ testThrows("$name - add throws", () {
+ wrapped.add(42);
+ });
+
+ testThrows("$name - addAll throws", () {
+ wrapped.addAll([42]);
+ });
+
+ testThrows("$name - insert throws", () {
+ wrapped.insert(0, 42);
+ });
+
+ testThrows("$name - insertAll throws", () {
+ wrapped.insertAll(0, [42]);
+ });
+
+ testThrows("$name - remove throws", () {
+ wrapped.remove(42);
+ });
+
+ testThrows("$name - removeAt throws", () {
+ wrapped.removeAt(0);
+ });
+
+ testThrows("$name - removeLast throws", () {
+ wrapped.removeLast();
+ });
+
+ testThrows("$name - removeWhere throws", () {
+ wrapped.removeWhere((E element) => false);
+ });
+
+ testThrows("$name - retainWhere throws", () {
+ wrapped.retainWhere((E element) => true);
+ });
+
+ testThrows("$name - removeRange throws", () {
+ wrapped.removeRange(0, wrapped.length);
+ });
+
+ testThrows("$name - replaceRange throws", () {
+ wrapped.replaceRange(0, wrapped.length, [42]);
+ });
+
+ testThrows("$name - clear throws", () {
+ wrapped.clear();
+ });
+}
+
+void testReadSet(Set original, Set wrapped, String name) {
+ Set copy = new Set.from(original);
+
+ test("$name - containsAll", () {
+ expect(wrapped.containsAll(copy), isTrue);
+ expect(wrapped.containsAll(copy.toList()), isTrue);
+ expect(wrapped.containsAll([]), isTrue);
+ expect(wrapped.containsAll([42]), equals(original.containsAll([42])));
+ });
+
+ test("$name - intersection", () {
+ expect(wrapped.intersection(new Set()), isEmpty);
+ expect(wrapped.intersection(copy), equals(original));
+ expect(wrapped.intersection(new Set.from([42])),
+ new Set.from(original.contains(42) ? [42] : []));
+ });
+
+ test("$name - union", () {
+ expect(wrapped.union(new Set()), equals(original));
+ expect(wrapped.union(copy), equals(original));
+ expect(wrapped.union(new Set.from([42])),
+ equals(original.union(new Set.from([42]))));
+ });
+
+ test("$name - difference", () {
+ expect(wrapped.difference(new Set()), equals(original));
+ expect(wrapped.difference(copy), isEmpty);
+ expect(wrapped.difference(new Set.from([42])),
+ equals(original.difference(new Set.from([42]))));
+ });
+}
+
+void testNoChangeSet(Set original, Set wrapped, String name) {
+ Set copy = new Set.from(original);
+
+ testThrows(name, thunk) {
+ test(name, () {
+ expect(thunk, throwsUnsupportedError);
+ // No modifications happened.
+ expect(original, equals(copy));
+ });
+ }
+
+ testThrows("$name - add throws", () {
+ wrapped.add(42);
+ });
+
+ testThrows("$name - addAll throws", () {
+ wrapped.addAll([42]);
+ });
+
+ testThrows("$name - addAll empty throws", () {
+ wrapped.addAll([]);
+ });
+
+ testThrows("$name - remove throws", () {
+ wrapped.remove(42);
+ });
+
+ testThrows("$name - removeAll throws", () {
+ wrapped.removeAll([42]);
+ });
+
+ testThrows("$name - removeAll empty throws", () {
+ wrapped.removeAll([]);
+ });
+
+ testThrows("$name - retainAll throws", () {
+ wrapped.retainAll([42]);
+ });
+
+ testThrows("$name - removeWhere throws", () {
+ wrapped.removeWhere((_) => false);
+ });
+
+ testThrows("$name - retainWhere throws", () {
+ wrapped.retainWhere((_) => true);
+ });
+
+ testThrows("$name - clear throws", () {
+ wrapped.clear();
+ });
+}
+
+void testReadMap(Map original, Map wrapped, String name) {
+ test("$name length", () {
+ expect(wrapped.length, equals(original.length));
+ });
+
+ test("$name isEmpty", () {
+ expect(wrapped.isEmpty, equals(original.isEmpty));
+ });
+
+ test("$name isNotEmpty", () {
+ expect(wrapped.isNotEmpty, equals(original.isNotEmpty));
+ });
+
+ test("$name operator[]", () {
+ expect(wrapped[0], equals(original[0]));
+ expect(wrapped[999], equals(original[999]));
+ });
+
+ test("$name containsKey", () {
+ expect(wrapped.containsKey(0), equals(original.containsKey(0)));
+ expect(wrapped.containsKey(999), equals(original.containsKey(999)));
+ });
+
+ test("$name containsValue", () {
+ expect(wrapped.containsValue(0), equals(original.containsValue(0)));
+ expect(wrapped.containsValue(999), equals(original.containsValue(999)));
+ });
+
+ test("$name forEach", () {
+ int origCnt = 0;
+ int wrapCnt = 0;
+ wrapped.forEach((k, v) { wrapCnt += 1 << k + 3 * v; });
+ original.forEach((k, v) { origCnt += 1 << k + 3 * v; });
+ expect(wrapCnt, equals(origCnt));
+ });
+
+ test("$name keys", () {
+ expect(wrapped.keys, equals(original.keys));
+ });
+
+ test("$name values", () {
+ expect(wrapped.values, equals(original.values));
+ });
+}
+
+testNoChangeMap(Map original, Map wrapped, String name) {
+ Map copy = new Map.from(original);
+
+ testThrows(name, thunk) {
+ test(name, () {
+ expect(thunk, throwsUnsupportedError);
+ // No modifications happened.
+ expect(original, equals(copy));
+ });
+ }
+
+ testThrows("$name operator[]= throws", () {
+ wrapped[0] = 42;
+ });
+
+ testThrows("$name putIfAbsent throws", () {
+ wrapped.putIfAbsent(0, () => 42);
+ });
+
+ testThrows("$name addAll throws", () {
+ wrapped.addAll(new Map()..[42] = 42);
+ });
+
+ testThrows("$name addAll empty throws", () {
+ wrapped.addAll(new Map());
+ });
+
+ testThrows("$name remove throws", () {
+ wrapped.remove(0);
+ });
+
+ testThrows("$name clear throws", () {
+ wrapped.clear();
+ });
+}
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 22db244..099f6a0 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -4,13 +4,7 @@
{
'variables': {
- # We place most generated source files in LIB_DIR (rather than, say
- # SHARED_INTERMEDIATE_DIR) because it is toolset specific. This avoids
- # two problems. First, if a generated source file has architecture specific
- # code, we'll get two different files in two different directories. Second,
- # if a generated source file is needed to build a target with multiple
- # toolsets, we avoid having duplicate Makefile targets.
- 'gen_source_dir': '<(LIB_DIR)',
+ 'gen_source_dir': '<(SHARED_INTERMEDIATE_DIR)',
'io_cc_file': '<(gen_source_dir)/io_gen.cc',
'io_patch_cc_file': '<(gen_source_dir)/io_patch_gen.cc',
@@ -19,17 +13,13 @@
'snapshot_in_cc_file': 'snapshot_in.cc',
'snapshot_bin_file': '<(gen_source_dir)/snapshot_gen.bin',
'resources_cc_file': '<(gen_source_dir)/resources_gen.cc',
-
- # The program that creates snapshot_gen.cc is only built and run on the
- # host, but it must be available when dart is built for the target. Thus,
- # we keep it in a shared location.
- 'snapshot_cc_file': '<(SHARED_INTERMEDIATE_DIR)/snapshot_gen.cc',
+ 'snapshot_cc_file': '<(gen_source_dir)/snapshot_gen.cc',
},
'targets': [
{
'target_name': 'generate_builtin_cc_file',
'type': 'none',
- 'toolsets':['target','host'],
+ 'toolsets':['host'],
'includes': [
'builtin_sources.gypi',
],
@@ -61,7 +51,7 @@
{
'target_name': 'generate_io_cc_file',
'type': 'none',
- 'toolsets':['target','host'],
+ 'toolsets':['host'],
'sources': [
'../../sdk/lib/io/io.dart',
],
@@ -96,7 +86,7 @@
{
'target_name': 'generate_io_patch_cc_file',
'type': 'none',
- 'toolsets':['target','host'],
+ 'toolsets':['host'],
'includes': [
'io_sources.gypi',
],
@@ -130,9 +120,9 @@
'type': 'static_library',
'toolsets':['target','host'],
'dependencies': [
- 'generate_builtin_cc_file',
- 'generate_io_cc_file',
- 'generate_io_patch_cc_file',
+ 'generate_builtin_cc_file#host',
+ 'generate_io_cc_file#host',
+ 'generate_io_patch_cc_file#host',
],
'include_dirs': [
'..',
@@ -198,6 +188,9 @@
],
}],
['OS=="win"', {
+ 'link_settings': {
+ 'libraries': [ '-liphlpapi.lib' ],
+ },
# TODO(antonm): fix the implementation.
# Current implementation accepts char* strings
# and therefore fails to compile once _UNICODE is
@@ -222,7 +215,7 @@
'libdart_vm',
'libjscre',
'libdouble_conversion',
- 'generate_version_cc_file',
+ 'generate_version_cc_file#host',
],
'include_dirs': [
'..',
@@ -342,6 +335,7 @@
{
'target_name': 'generate_resources_cc_file',
'type': 'none',
+ 'toolsets':['host'],
'includes': [
'vmstats_sources.gypi',
],
@@ -375,7 +369,7 @@
'libdart_builtin',
'libdart_io',
'generate_snapshot_file#host',
- 'generate_resources_cc_file',
+ 'generate_resources_cc_file#host',
],
'include_dirs': [
'..',
@@ -443,7 +437,7 @@
'libdart_withcore',
'libdart_builtin',
'libdart_io',
- 'generate_resources_cc_file',
+ 'generate_resources_cc_file#host',
],
'include_dirs': [
'..',
@@ -524,7 +518,7 @@
'libdart_builtin',
'libdart_io',
'generate_snapshot_file#host',
- 'generate_snapshot_test_dat_file',
+ 'generate_snapshot_test_dat_file#host',
],
'include_dirs': [
'..',
@@ -595,7 +589,7 @@
'libdart_builtin',
'libdart_io',
'generate_snapshot_file#host',
- 'generate_snapshot_test_dat_file',
+ 'generate_snapshot_test_dat_file#host',
],
'include_dirs': [
'..',
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 716ec71..818acaf 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -5,28 +5,56 @@
library builtin;
import 'dart:io';
-int _httpRequestResponseCode = 0;
-String _httpRequestStatusString;
+// Corelib 'print' implementation.
+void _print(arg) {
+ _Logger._printString(arg.toString());
+}
+
+
+class _Logger {
+ static void _printString(String s) native "Logger_PrintString";
+}
+
+
+_getPrintClosure() => _print;
+
+
+void _logResolution(String msg) {
+ final enabled = false;
+ if (enabled) {
+ _Logger._printString(msg);
+ }
+}
+
+
+var _httpRequestResponseCode = 0;
+var _httpRequestStatusString;
var _httpRequestResponse;
+_getHttpRequestResponseCode() => _httpRequestResponseCode;
+_getHttpRequestStatusString() => _httpRequestStatusString;
+_getHttpRequestResponse() => _httpRequestResponse;
+
void _requestCompleted(HttpClientResponseBody body) {
_httpRequestResponseCode = body.statusCode;
_httpRequestStatusString = '${body.statusCode} ${body.reasonPhrase}';
_httpRequestResponse = null;
- if (body.statusCode != 200 || body.type == "json") {
+ if (body.statusCode != 200 || body.type == 'json') {
return;
}
_httpRequestResponse = body.body;
}
+
void _requestFailed(error) {
_httpRequestResponseCode = 0;
_httpRequestStatusString = error.toString();
_httpRequestResponse = null;
}
-HttpClient _client = new HttpClient();
+
void _makeHttpRequest(String uri) {
+ var _client = new HttpClient();
_httpRequestResponseCode = 0;
_httpRequestStatusString = null;
_httpRequestResponse = null;
@@ -41,76 +69,94 @@
});
}
-// Corelib 'print' implementation.
-void _print(arg) {
- _Logger._printString(arg.toString());
-}
-class _Logger {
- static void _printString(String s) native "Logger_PrintString";
-}
-
-_getPrintClosure() => _print;
-
-// The URI that the entrypoint script was loaded from. Remembered so that
+// Are we running on Windows?
+var _isWindows = false;
+// The current working directory
+var _workingDirectoryUri;
+// The URI that the entry point script was loaded from. Remembered so that
// package imports can be resolved relative to it.
-var _entrypoint;
-
+var _entryPointScript;
// The directory to look in to resolve "package:" scheme URIs.
var _packageRoot;
-void _logResolution(String msg) {
- final enabled = false;
- if (enabled) {
- _Logger._printString(msg);
- }
+
+void _setWindows() {
+ _isWindows = true;
}
+
+_sanitizeWindowsPath(path) {
+ // For Windows we need to massage the paths a bit according to
+ // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
+ //
+ // Convert
+ // C:\one\two\three
+ // to
+ // /C:/one/two/three
+
+ if (_isWindows == false) {
+ // Do nothing when not running Windows.
+ return path;
+ }
+
+ var fixedPath = "${path.replaceAll('\\', '/')}";
+
+ if ((path.length > 2) && (path[1] == ':')) {
+ // Path begins with a drive letter.
+ return '/$fixedPath';
+ }
+
+ return fixedPath;
+}
+
+_enforceTrailingSlash(uri) {
+ // Ensure we have a trailing slash character.
+ if (!uri.endsWith('/')) {
+ return '$uri/';
+ }
+ return uri;
+}
+
+
+void _setWorkingDirectory(cwd) {
+ cwd = _sanitizeWindowsPath(cwd);
+ cwd = _enforceTrailingSlash(cwd);
+ _workingDirectoryUri = new Uri(scheme: 'file', path: cwd);
+ _logResolution('# Working Directory: $cwd');
+}
+
+
_setPackageRoot(String packageRoot) {
- // TODO(mattsh) - refactor windows drive and path handling code
- // so it can be used here if needed.
- _packageRoot = packageRoot;
+ packageRoot = _enforceTrailingSlash(packageRoot);
+ _packageRoot = _workingDirectoryUri.resolve(packageRoot);
+ _logResolution('# Package root: $packageRoot -> $_packageRoot');
}
-String _resolveScriptUri(String cwd, String scriptName, bool isWindows) {
+
+String _resolveScriptUri(String scriptName) {
+ if (_workingDirectoryUri == null) {
+ throw 'No current working directory set.';
+ }
+ scriptName = _sanitizeWindowsPath(scriptName);
+
var scriptUri = Uri.parse(scriptName);
- if (scriptUri.scheme == 'http') {
- _entrypoint = scriptUri;
- _logResolution("# Resolved script to: $_entrypoint");
- return _entrypoint.toString();
+ if (scriptUri.scheme != '') {
+ // Script has a scheme, assume that it is fully formed.
+ _entryPointScript = scriptUri;
+ } else {
+ // Script does not have a scheme, assume that it is a path,
+ // resolve it against the working directory.
+ _entryPointScript = _workingDirectoryUri.resolve(scriptName);
}
- _logResolution("# Current working directory: $cwd");
- _logResolution("# ScriptName: $scriptName");
- if (isWindows) {
- // For Windows we need to massage the paths a bit according to
- // http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
- //
- // Convert
- // C:\one\two\three
- // to
- // /C:/one/two/three
- cwd = "/${cwd.replaceAll('\\', '/')}";
- _logResolution("## cwd: $cwd");
- if ((scriptName.length > 2) && (scriptName[1] == ":")) {
- // This is an absolute path.
- scriptName = "/${scriptName.replaceAll('\\', '/')}";
- } else {
- scriptName = scriptName.replaceAll('\\', '/');
- }
- _logResolution("## scriptName: $scriptName");
- }
- var base =
- new Uri(scheme: "file",
- path: cwd.endsWith("/") ? cwd : "$cwd/");
- _entrypoint = base.resolve(scriptName);
- _logResolution("# Resolved script to: $_entrypoint");
-
- return _entrypoint.toString();
+ _logResolution('# Resolved entry point to: $_entryPointScript');
+ return _entryPointScript.toString();
}
+
String _resolveUri(String base, String userString) {
var baseUri = Uri.parse(base);
- _logResolution("# Resolving: $userString from $base");
+ _logResolution('# Resolving: $userString from $base');
var uri = Uri.parse(userString);
var resolved;
@@ -125,18 +171,18 @@
// package URI path part.
path = _filePathFromPackageUri(resolved);
}
- resolved = new Uri(scheme: "dart-ext", path: path);
+ resolved = new Uri(scheme: 'dart-ext', path: path);
} else {
resolved = baseUri.resolve(userString);
}
- _logResolution("# Resolved to: $resolved");
+ _logResolution('# Resolved to: $resolved');
return resolved.toString();
}
-String _filePathFromUri(String userUri, bool isWindows) {
+String _filePathFromUri(String userUri) {
var uri = Uri.parse(userUri);
- _logResolution("# Getting file path from: $uri");
+ _logResolution('# Getting file path from: $uri');
var path;
switch (uri.scheme) {
@@ -154,40 +200,43 @@
break;
default:
// Only handling file and package URIs in standalone binary.
- _logResolution("# Unknown scheme (${uri.scheme}) in $uri.");
- throw "Not a known scheme: $uri";
+ _logResolution('# Unknown scheme (${uri.scheme}) in $uri.');
+ throw 'Not a known scheme: $uri';
}
- if (isWindows && path.startsWith("/")) {
+ if (_isWindows && path.startsWith('/')) {
// For Windows we need to massage the paths a bit according to
// http://blogs.msdn.com/b/ie/archive/2006/12/06/file-uris-in-windows.aspx
//
// Drop the leading / before the drive letter.
path = path.substring(1);
- _logResolution("# path: $path");
+ _logResolution('# Path: Removed leading / -> $path');
}
return path;
}
+
String _filePathFromFileUri(Uri uri) {
if (!uri.host.isEmpty) {
throw "URIs using the 'file:' scheme may not contain a host.";
}
- _logResolution("# Path: ${uri.path}");
+ _logResolution('# Path: $uri -> ${uri.path}');
return uri.path;
}
+
String _filePathFromOtherUri(Uri uri) {
if (!uri.host.isEmpty) {
- throw "URIs whose paths are used as file paths may not contain a host.";
+ throw 'URIs whose paths are used as file paths may not contain a host.';
}
- _logResolution("# Path: ${uri.path}");
+ _logResolution('# Path: $uri -> ${uri.path}');
return uri.path;
}
+
String _filePathFromPackageUri(Uri uri) {
if (!uri.host.isEmpty) {
var path = (uri.path != '') ? '${uri.host}${uri.path}' : uri.host;
@@ -198,22 +247,27 @@
"'$right', not '$wrong'.";
}
+ var packageUri;
var path;
if (_packageRoot != null) {
- path = "${_packageRoot}${uri.path}";
+ // Resolve against package root.
+ packageUri = _packageRoot.resolve(uri.path);
} else {
- if (_entrypoint.scheme == 'http') {
- path = _entrypoint.resolve('packages/${uri.path}').toString();
- } else {
- path = _entrypoint.resolve('packages/${uri.path}').path;
- }
+ // Resolve against working directory.
+ packageUri = _entryPointScript.resolve('packages/${uri.path}');
}
- _logResolution("# Package: $path");
+ if (packageUri.scheme == 'file') {
+ path = packageUri.path;
+ } else {
+ path = packageUri.toString();
+ }
+ _logResolution('# Package: $uri -> $path');
return path;
}
+
String _filePathFromHttpUri(Uri uri) {
- _logResolution('# Path: $uri');
+ _logResolution('# Path: $uri -> $uri');
return uri.toString();
}
diff --git a/runtime/bin/common.cc b/runtime/bin/common.cc
index fd6386e..ce9a9ef 100644
--- a/runtime/bin/common.cc
+++ b/runtime/bin/common.cc
@@ -58,12 +58,5 @@
Dart_ExitScope();
}
-
-void FUNCTION_NAME(Common_GetVersion)(Dart_NativeArguments args) {
- Dart_EnterScope();
- Dart_SetReturnValue(args, Dart_NewStringFromCString(Dart_VersionString()));
- Dart_ExitScope();
-}
-
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/common_patch.dart b/runtime/bin/common_patch.dart
index e1d36f4..8b77d3a 100644
--- a/runtime/bin/common_patch.dart
+++ b/runtime/bin/common_patch.dart
@@ -11,7 +11,3 @@
/* patch */ static Uint8List getRandomBytes(int count)
native "Crypto_GetRandomBytes";
}
-
-patch class _OptionsImpl {
- /* patch */ String get version native "Common_GetVersion";
-}
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 8134848..3e107f8 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -243,8 +243,8 @@
}
-static Dart_Handle SingleArgDart_Invoke(Dart_Handle arg, Dart_Handle lib,
- const char* method) {
+static Dart_Handle SingleArgDart_Invoke(Dart_Handle lib, const char* method,
+ Dart_Handle arg) {
const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
dart_args[0] = arg;
@@ -253,10 +253,10 @@
// TODO(iposva): Allocate from the zone instead of leaking error string
-// here. On the other hand the binary is about the exit anyway.
+// here. On the other hand the binary is about to exit anyway.
#define SET_ERROR_MSG(error_msg, format, ...) \
intptr_t len = snprintf(NULL, 0, format, __VA_ARGS__); \
- char *msg = reinterpret_cast<char*>(malloc(len + 1)); \
+ char* msg = reinterpret_cast<char*>(malloc(len + 1)); \
snprintf(msg, len + 1, format, __VA_ARGS__); \
*error_msg = msg
@@ -267,19 +267,27 @@
ASSERT(buffer != NULL);
ASSERT(buffer_len != NULL);
ASSERT(!Dart_HasLivePorts());
- SingleArgDart_Invoke(uri, builtin_lib, "_makeHttpRequest");
+ SingleArgDart_Invoke(builtin_lib, "_makeHttpRequest", uri);
// Run until all ports to isolate are closed.
Dart_Handle result = Dart_RunLoop();
if (Dart_IsError(result)) {
return result;
}
- intptr_t responseCode =
- DartUtils::GetIntegerField(builtin_lib, "_httpRequestResponseCode");
+ result = Dart_Invoke(builtin_lib,
+ DartUtils::NewString("_getHttpRequestResponseCode"),
+ 0,
+ NULL);
+ if (Dart_IsError(result)) {
+ return result;
+ }
+ intptr_t responseCode = DartUtils::GetIntegerValue(result);
if (responseCode != HttpResponseCodeOK) {
// Return error.
Dart_Handle responseStatus =
- Dart_GetField(builtin_lib,
- DartUtils::NewString("_httpRequestStatusString"));
+ Dart_Invoke(builtin_lib,
+ DartUtils::NewString("_getHttpRequestStatusString"),
+ 0,
+ NULL);
if (Dart_IsError(responseStatus)) {
return responseStatus;
}
@@ -289,7 +297,8 @@
return Dart_Error(DartUtils::GetStringValue(responseStatus));
}
Dart_Handle response =
- Dart_GetField(builtin_lib, DartUtils::NewString("_httpRequestResponse"));
+ Dart_Invoke(builtin_lib, DartUtils::NewString("_getHttpRequestResponse"),
+ 0, NULL);
if (Dart_IsError(response)) {
return response;
}
@@ -384,13 +393,17 @@
}
+Dart_Handle DartUtils::SetWorkingDirectory(Dart_Handle builtin_lib) {
+ Dart_Handle directory = NewString(original_working_directory);
+ return SingleArgDart_Invoke(builtin_lib, "_setWorkingDirectory", directory);
+}
+
+
Dart_Handle DartUtils::ResolveScriptUri(Dart_Handle script_uri,
Dart_Handle builtin_lib) {
- const int kNumArgs = 3;
+ const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
- dart_args[0] = NewString(original_working_directory);
- dart_args[1] = script_uri;
- dart_args[2] = (IsWindowsHost() ? Dart_True() : Dart_False());
+ dart_args[0] = script_uri;
return Dart_Invoke(builtin_lib,
NewString("_resolveScriptUri"),
kNumArgs,
@@ -400,10 +413,9 @@
Dart_Handle DartUtils::FilePathFromUri(Dart_Handle script_uri,
Dart_Handle builtin_lib) {
- const int kNumArgs = 2;
+ const int kNumArgs = 1;
Dart_Handle dart_args[kNumArgs];
dart_args[0] = script_uri;
- dart_args[1] = (IsWindowsHost() ? Dart_True() : Dart_False());
return Dart_Invoke(builtin_lib,
NewString("_filePathFromUri"),
kNumArgs,
@@ -564,9 +576,6 @@
Dart_Handle DartUtils::LoadScript(const char* script_uri,
Dart_Handle builtin_lib) {
- // Always call ResolveScriptUri because as a side effect it sets
- // the script entry path which is used when automatically resolving
- // package root.
Dart_Handle resolved_script_uri =
ResolveScriptUri(NewString(script_uri), builtin_lib);
if (Dart_IsError(resolved_script_uri)) {
@@ -647,7 +656,7 @@
Dart_Handle builtin_lib) {
// Setup the corelib 'print' function.
Dart_Handle print = Dart_Invoke(
- builtin_lib, NewString("_getPrintClosure"), 0, 0);
+ builtin_lib, NewString("_getPrintClosure"), 0, NULL);
Dart_Handle corelib = Dart_LookupLibrary(NewString("dart:core"));
Dart_Handle result = Dart_SetField(corelib,
NewString("_printClosure"),
@@ -666,6 +675,21 @@
DART_CHECK_VALID(Dart_Invoke(
async_lib, NewString("_setTimerFactoryClosure"), 1, args));
+
+ if (IsWindowsHost()) {
+ // Set running on Windows flag.
+ result = Dart_Invoke(builtin_lib, NewString("_setWindows"), 0, NULL);
+ if (Dart_IsError(result)) {
+ return result;
+ }
+ }
+
+ // Set current working directory.
+ result = SetWorkingDirectory(builtin_lib);
+ if (Dart_IsError(result)) {
+ return result;
+ }
+
// Set up package root if specified.
if (package_root != NULL) {
result = NewString(package_root);
@@ -737,10 +761,10 @@
}
-Dart_Handle DartUtils::GetDartClass(const char* library_url,
- const char* class_name) {
- return Dart_GetClass(Dart_LookupLibrary(NewString(library_url)),
- NewString(class_name));
+Dart_Handle DartUtils::GetDartType(const char* library_url,
+ const char* class_name) {
+ return Dart_GetType(Dart_LookupLibrary(NewString(library_url)),
+ NewString(class_name), 0, NULL);
}
@@ -753,22 +777,24 @@
Dart_Handle DartUtils::NewDartOSError(OSError* os_error) {
// Create a dart:io OSError object with the information retrieved from the OS.
- Dart_Handle clazz = GetDartClass(kIOLibURL, "OSError");
+ Dart_Handle type = GetDartType(kIOLibURL, "OSError");
Dart_Handle args[2];
args[0] = NewString(os_error->message());
args[1] = Dart_NewInteger(os_error->code());
- return Dart_New(clazz, Dart_Null(), 2, args);
+ return Dart_New(type, Dart_Null(), 2, args);
}
-Dart_Handle DartUtils::NewDartSocketException(const char* message,
- Dart_Handle os_error) {
- // Create a dart:io SocketException object.
- Dart_Handle clazz = GetDartClass(kIOLibURL, "SocketException");
+Dart_Handle DartUtils::NewDartExceptionWithOSError(const char* library_url,
+ const char* exception_name,
+ const char* message,
+ Dart_Handle os_error) {
+ // Create a Dart Exception object with a message and an OSError.
+ Dart_Handle type = GetDartType(library_url, exception_name);
Dart_Handle args[2];
args[0] = NewString(message);
args[1] = os_error;
- return Dart_New(clazz, Dart_Null(), 2, args);
+ return Dart_New(type, Dart_Null(), 2, args);
}
@@ -776,13 +802,13 @@
const char* exception_name,
const char* message) {
// Create a Dart Exception object with a message.
- Dart_Handle clazz = GetDartClass(library_url, exception_name);
+ Dart_Handle type = GetDartType(library_url, exception_name);
if (message != NULL) {
Dart_Handle args[1];
args[0] = NewString(message);
- return Dart_New(clazz, Dart_Null(), 1, args);
+ return Dart_New(type, Dart_Null(), 1, args);
} else {
- return Dart_New(clazz, Dart_Null(), 0, NULL);
+ return Dart_New(type, Dart_Null(), 0, NULL);
}
}
@@ -794,6 +820,17 @@
}
+Dart_Handle DartUtils::NewDartIOException(const char* exception_name,
+ const char* message,
+ Dart_Handle os_error) {
+ // Create a dart:io exception object of the given type.
+ return NewDartExceptionWithOSError(kIOLibURL,
+ exception_name,
+ message,
+ os_error);
+}
+
+
Dart_Handle DartUtils::NewInternalError(const char* message) {
return NewDartExceptionWithMessage(kCoreLibURL, "InternalError", message);
}
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 026b83a..85b5585 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -135,18 +135,23 @@
static bool PostNull(Dart_Port port_id);
static bool PostInt32(Dart_Port port_id, int32_t value);
- static Dart_Handle GetDartClass(const char* library_url,
- const char* class_name);
+ static Dart_Handle GetDartType(const char* library_url,
+ const char* class_name);
// Create a new Dart OSError object with the current OS error.
static Dart_Handle NewDartOSError();
// Create a new Dart OSError object with the provided OS error.
static Dart_Handle NewDartOSError(OSError* os_error);
- static Dart_Handle NewDartSocketException(const char* message,
- Dart_Handle os_error);
+ static Dart_Handle NewDartExceptionWithOSError(const char* library_url,
+ const char* exception_name,
+ const char* message,
+ Dart_Handle os_error);
static Dart_Handle NewDartExceptionWithMessage(const char* library_url,
const char* exception_name,
const char* message);
static Dart_Handle NewDartArgumentError(const char* message);
+ static Dart_Handle NewDartIOException(const char* exception_name,
+ const char* message,
+ Dart_Handle os_error);
// Create a new Dart String object from a C String.
static Dart_Handle NewString(const char* str) {
@@ -163,6 +168,8 @@
static const char* MapLibraryUrl(CommandLineOptions* url_mapping,
const char* url_string);
+ static Dart_Handle SetWorkingDirectory(Dart_Handle builtin_lib);
+
static Dart_Handle ResolveScriptUri(Dart_Handle script_uri,
Dart_Handle builtin_lib);
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
index 1d722b9..db77a16 100644
--- a/runtime/bin/dbg_connection.cc
+++ b/runtime/bin/dbg_connection.cc
@@ -300,9 +300,11 @@
// debugger commands received on these connections.
ASSERT(listener_fd_ == -1);
OSError *os_error;
- SocketAddresses* addresses = Socket::LookupAddress(address, -1, &os_error);
+ AddressList<SocketAddress>* addresses =
+ Socket::LookupAddress(address, -1, &os_error);
listener_fd_ = ServerSocket::CreateBindListen(
addresses->GetAt(0)->addr(), port_number, 1);
+ delete addresses;
port_number = Socket::GetPort(listener_fd_);
DebuggerConnectionImpl::StartHandler(port_number);
return port_number;
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 7ce1787..3d86916 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -146,7 +146,7 @@
// Create the list to hold the directory listing here, and pass it to the
// SyncDirectoryListing object, which adds elements to it.
Dart_Handle results =
- Dart_New(DartUtils::GetDartClass(DartUtils::kCoreLibURL, "List"),
+ Dart_New(DartUtils::GetDartType(DartUtils::kCoreLibURL, "List"),
Dart_Null(),
0,
NULL);
@@ -413,7 +413,7 @@
bool SyncDirectoryListing::HandleDirectory(char* dir_name) {
Dart_Handle dir_name_dart = DartUtils::NewString(dir_name);
Dart_Handle dir =
- Dart_New(directory_class_, Dart_Null(), 1, &dir_name_dart);
+ Dart_New(directory_type_, Dart_Null(), 1, &dir_name_dart);
Dart_Invoke(results_, add_string_, 1, &dir);
return true;
}
@@ -421,7 +421,7 @@
bool SyncDirectoryListing::HandleLink(char* link_name) {
Dart_Handle link_name_dart = DartUtils::NewString(link_name);
Dart_Handle link =
- Dart_New(link_class_, Dart_Null(), 1, &link_name_dart);
+ Dart_New(link_type_, Dart_Null(), 1, &link_name_dart);
Dart_Invoke(results_, add_string_, 1, &link);
return true;
}
@@ -429,7 +429,7 @@
bool SyncDirectoryListing::HandleFile(char* file_name) {
Dart_Handle file_name_dart = DartUtils::NewString(file_name);
Dart_Handle file =
- Dart_New(file_class_, Dart_Null(), 1, &file_name_dart);
+ Dart_New(file_type_, Dart_Null(), 1, &file_name_dart);
Dart_Invoke(results_, add_string_, 1, &file);
return true;
}
@@ -441,7 +441,7 @@
args[1] = DartUtils::NewString(dir_name);
args[2] = dart_os_error;
Dart_ThrowException(Dart_New(
- DartUtils::GetDartClass(DartUtils::kIOLibURL, "DirectoryException"),
+ DartUtils::GetDartType(DartUtils::kIOLibURL, "DirectoryException"),
Dart_Null(),
3,
args));
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index 89ec90b..a8786bf 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -221,12 +221,12 @@
: DirectoryListing(dir_name, recursive, follow_links),
results_(results) {
add_string_ = DartUtils::NewString("add");
- directory_class_ =
- DartUtils::GetDartClass(DartUtils::kIOLibURL, "Directory");
- file_class_ =
- DartUtils::GetDartClass(DartUtils::kIOLibURL, "File");
- link_class_ =
- DartUtils::GetDartClass(DartUtils::kIOLibURL, "Link");
+ directory_type_ =
+ DartUtils::GetDartType(DartUtils::kIOLibURL, "Directory");
+ file_type_ =
+ DartUtils::GetDartType(DartUtils::kIOLibURL, "File");
+ link_type_ =
+ DartUtils::GetDartType(DartUtils::kIOLibURL, "Link");
}
virtual ~SyncDirectoryListing() {}
virtual bool HandleDirectory(char* dir_name);
@@ -237,9 +237,9 @@
private:
Dart_Handle results_;
Dart_Handle add_string_;
- Dart_Handle directory_class_;
- Dart_Handle file_class_;
- Dart_Handle link_class_;
+ Dart_Handle directory_type_;
+ Dart_Handle file_type_;
+ Dart_Handle link_type_;
DISALLOW_IMPLICIT_CONSTRUCTORS(SyncDirectoryListing);
};
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 87fc2c1..c687cde 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -1180,8 +1180,8 @@
static void FileService(Dart_Port dest_port_id,
- Dart_Port reply_port_id,
- Dart_CObject* message) {
+ Dart_Port reply_port_id,
+ Dart_CObject* message) {
CObject* response = CObject::IllegalArgumentError();
CObjectArray request(message);
if (message->type == Dart_CObject_kArray) {
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index e5172b7..163c4af 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -21,7 +21,6 @@
// builtin_natives.cc instead.
#define IO_NATIVE_LIST(V) \
V(Common_IsBuiltinList, 1) \
- V(Common_GetVersion, 1) \
V(Crypto_GetRandomBytes, 1) \
V(EventHandler_Start, 1) \
V(EventHandler_SendData, 4) \
@@ -36,6 +35,7 @@
V(Platform_PathSeparator, 0) \
V(Platform_LocalHostname, 0) \
V(Platform_Environment, 0) \
+ V(Platform_GetVersion, 0) \
V(Process_Start, 10) \
V(Process_Kill, 3) \
V(Process_SetExitCode, 1) \
@@ -47,7 +47,6 @@
V(Socket_CreateConnect, 3) \
V(Socket_Available, 1) \
V(Socket_Read, 2) \
- V(Socket_ReadList, 4) \
V(Socket_WriteList, 4) \
V(Socket_GetPort, 1) \
V(Socket_GetRemotePeer, 1) \
@@ -56,15 +55,16 @@
V(Socket_NewServicePort, 0) \
V(Socket_GetType, 1) \
V(Socket_SetOption, 3) \
- V(SecureSocket_Connect, 8) \
+ V(SecureSocket_Connect, 9) \
V(SecureSocket_Destroy, 1) \
V(SecureSocket_Handshake, 1) \
V(SecureSocket_Init, 1) \
V(SecureSocket_PeerCertificate, 1) \
- V(SecureSocket_ProcessBuffer, 2) \
V(SecureSocket_RegisterBadCertificateCallback, 2) \
V(SecureSocket_RegisterHandshakeCompleteCallback, 2) \
V(SecureSocket_InitializeLibrary, 3) \
+ V(SecureSocket_NewServicePort, 0) \
+ V(SecureSocket_FilterPointer, 1) \
V(StringToSystemEncoding, 1) \
V(SystemEncodingToString, 1)
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 9081f70..18f7667 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -402,23 +402,21 @@
if (Dart_IsError(io_lib)) {
return io_lib;
}
- Dart_Handle runtime_options_class_name =
- DartUtils::NewString("_OptionsImpl");
- if (Dart_IsError(runtime_options_class_name)) {
- return runtime_options_class_name;
+ Dart_Handle platform_class_name = DartUtils::NewString("Platform");
+ if (Dart_IsError(platform_class_name)) {
+ return platform_class_name;
}
- Dart_Handle runtime_options_class = Dart_GetClass(
- io_lib, runtime_options_class_name);
- if (Dart_IsError(runtime_options_class)) {
- return runtime_options_class;
+ Dart_Handle platform_type =
+ Dart_GetType(io_lib, platform_class_name, 0, NULL);
+ if (Dart_IsError(platform_type)) {
+ return platform_type;
}
- Dart_Handle executable_name_name =
- DartUtils::NewString("_nativeExecutable");
+ Dart_Handle executable_name_name = DartUtils::NewString("_nativeExecutable");
if (Dart_IsError(executable_name_name)) {
return executable_name_name;
}
Dart_Handle set_executable_name =
- Dart_SetField(runtime_options_class,
+ Dart_SetField(platform_type,
executable_name_name,
dart_executable);
if (Dart_IsError(set_executable_name)) {
@@ -429,16 +427,25 @@
return script_name_name;
}
Dart_Handle set_script_name =
- Dart_SetField(runtime_options_class, script_name_name, dart_script);
+ Dart_SetField(platform_type, script_name_name, dart_script);
if (Dart_IsError(set_script_name)) {
return set_script_name;
}
+ Dart_Handle runtime_options_class_name = DartUtils::NewString("_OptionsImpl");
+ if (Dart_IsError(runtime_options_class_name)) {
+ return runtime_options_class_name;
+ }
+ Dart_Handle runtime_options_type = Dart_GetType(
+ io_lib, runtime_options_class_name, 0, NULL);
+ if (Dart_IsError(runtime_options_type)) {
+ return runtime_options_type;
+ }
Dart_Handle native_name = DartUtils::NewString("_nativeArguments");
if (Dart_IsError(native_name)) {
return native_name;
}
- return Dart_SetField(runtime_options_class, native_name, dart_arguments);
+ return Dart_SetField(runtime_options_type, native_name, dart_arguments);
}
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index 850be27..495ffe3 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -79,5 +79,12 @@
Dart_ExitScope();
}
+
+void FUNCTION_NAME(Platform_GetVersion)(Dart_NativeArguments args) {
+ Dart_EnterScope();
+ Dart_SetReturnValue(args, Dart_NewStringFromCString(Dart_VersionString()));
+ Dart_ExitScope();
+}
+
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/platform_patch.dart b/runtime/bin/platform_patch.dart
index 02ba129..9d21d48 100644
--- a/runtime/bin/platform_patch.dart
+++ b/runtime/bin/platform_patch.dart
@@ -10,4 +10,5 @@
native "Platform_OperatingSystem";
/* patch */ static _localHostname() native "Platform_LocalHostname";
/* patch */ static _environment() native "Platform_Environment";
+ /* patch */ static String _version() native "Platform_GetVersion";
}
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index ba50c9f..65d271f 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -20,11 +20,13 @@
List<String> arguments,
{String workingDirectory,
Map<String, String> environment,
- bool runInShell}) {
+ bool includeParentEnvironment: true,
+ bool runInShell: false}) {
_ProcessImpl process = new _ProcessImpl(executable,
arguments,
workingDirectory,
environment,
+ includeParentEnvironment,
runInShell);
return process._start();
}
@@ -34,13 +36,15 @@
List<String> arguments,
{String workingDirectory,
Map<String, String> environment,
- bool runInShell,
+ bool includeParentEnvironment: true,
+ bool runInShell: false,
Encoding stdoutEncoding: Encoding.SYSTEM,
Encoding stderrEncoding: Encoding.SYSTEM}) {
return _runNonInteractiveProcess(executable,
arguments,
workingDirectory,
environment,
+ includeParentEnvironment,
runInShell,
stdoutEncoding,
stderrEncoding);
@@ -68,6 +72,7 @@
List<String> arguments,
String this._workingDirectory,
Map<String, String> environment,
+ bool includeParentEnvironment,
bool runInShell) {
runInShell = identical(runInShell, true);
if (runInShell) {
@@ -92,8 +97,7 @@
}
_arguments[i] = arguments[i];
if (Platform.operatingSystem == 'windows') {
- _arguments[i] = _windowsArgumentEscape(_arguments[i],
- shellEscape: runInShell);
+ _arguments[i] = _windowsArgumentEscape(_arguments[i]);
}
}
@@ -102,20 +106,23 @@
"WorkingDirectory is not a String: $_workingDirectory");
}
- if (environment != null) {
- var env = environment;
- if (env is !Map) {
- throw new ArgumentError("Environment is not a map: $env");
- }
- _environment = [];
- env.forEach((key, value) {
- if (key is !String || value is !String) {
- throw new ArgumentError(
- "Environment key or value is not a string: ($key, $value)");
- }
- _environment.add('$key=$value');
- });
+ _environment = [];
+ if (environment == null) {
+ environment = {};
}
+ if (environment is !Map) {
+ throw new ArgumentError("Environment is not a map: $environment");
+ }
+ if (identical(true, includeParentEnvironment)) {
+ environment = Platform.environment..addAll(environment);
+ }
+ environment.forEach((key, value) {
+ if (key is !String || value is !String) {
+ throw new ArgumentError(
+ "Environment key or value is not a string: ($key, $value)");
+ }
+ _environment.add('$key=$value');
+ });
// stdin going to process.
_stdin = new _StdSink(new _Socket._writePipe());
@@ -158,12 +165,11 @@
return shellArguments;
}
- String _windowsArgumentEscape(String argument, { bool shellEscape: false }) {
+ String _windowsArgumentEscape(String argument) {
var result = argument;
if (argument.contains('\t') ||
argument.contains(' ') ||
- // TODO(ajohnsen): Remove shellEscape.
- (shellEscape && argument.contains('"'))) {
+ argument.contains('"')) {
// Produce something that the C runtime on Windows will parse
// back as this string.
@@ -333,6 +339,7 @@
List<String> arguments,
String workingDirectory,
Map<String, String> environment,
+ bool includeParentEnvironment,
bool runInShell,
Encoding stdoutEncoding,
Encoding stderrEncoding) {
@@ -341,6 +348,7 @@
arguments,
workingDirectory: workingDirectory,
environment: environment,
+ includeParentEnvironment: includeParentEnvironment,
runInShell: runInShell).then((Process p) {
int pid = p.pid;
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index 4310aec..e6aacd7 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -24,6 +24,7 @@
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/net/nss_memio.h"
+#include "bin/socket.h"
#include "bin/thread.h"
#include "bin/utils.h"
#include "platform/utils.h"
@@ -40,8 +41,47 @@
// be null if only secure client sockets are used.
const char* SSLFilter::password_ = NULL;
+// Forward declaration.
+static void ProcessFilter(Dart_Port dest_port_id,
+ Dart_Port reply_port_id,
+ Dart_CObject* message);
+
+NativeService SSLFilter::filter_service_("FilterService", ProcessFilter, 16);
+
static const int kSSLFilterNativeFieldIndex = 0;
+
+/* Handle an error reported from the NSS library. */
+static void ThrowPRException(const char* exception_type,
+ const char* message,
+ bool free_message = false) {
+ PRErrorCode error_code = PR_GetError();
+ const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN);
+ OSError os_error_struct(error_code, error_message, OSError::kNSS);
+ Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
+ Dart_Handle exception =
+ DartUtils::NewDartIOException(exception_type, message, os_error);
+ if (free_message) {
+ free(const_cast<char*>(message));
+ }
+ Dart_ThrowException(exception);
+}
+
+
+static void ThrowCertificateException(const char* format,
+ const char* certificate_name) {
+ int length = strlen(certificate_name);
+ length += strlen(format);
+ char* message = reinterpret_cast<char*>(malloc(length + 1));
+ if (message == NULL) {
+ FATAL("Out of memory formatting CertificateException for throwing");
+ }
+ snprintf(message, length + 1, format, certificate_name);
+ message[length] = '\0';
+ ThrowPRException("CertificateException", message, true);
+}
+
+
static SSLFilter* GetFilter(Dart_NativeArguments args) {
SSLFilter* filter;
Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
@@ -77,21 +117,35 @@
void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
- Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
- bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+ Dart_Handle host_sockaddr_storage_object =
+ ThrowIfError(Dart_GetNativeArgument(args, 2));
+ Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3));
+ bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
Dart_Handle certificate_name_object =
- ThrowIfError(Dart_GetNativeArgument(args, 4));
+ ThrowIfError(Dart_GetNativeArgument(args, 5));
bool request_client_certificate =
- DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
- bool require_client_certificate =
DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6));
- bool send_client_certificate =
+ bool require_client_certificate =
DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7));
+ bool send_client_certificate =
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8));
const char* host_name = NULL;
// TODO(whesse): Is truncating a Dart string containing \0 what we want?
ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
+ RawAddr raw_addr;
+ Dart_TypedData_Type type;
+ uint8_t* buffer = NULL;
+ intptr_t len;
+ ThrowIfError(Dart_TypedDataAcquireData(host_sockaddr_storage_object,
+ &type,
+ reinterpret_cast<void**>(&buffer),
+ &len));
+ ASSERT(static_cast<size_t>(len) <= sizeof(raw_addr));
+ memmove(&raw_addr, buffer, len);
+ Dart_TypedDataReleaseData(host_sockaddr_storage_object);
+
int64_t port;
if (!DartUtils::GetInt64Value(port_object, &port)) {
FATAL("The range of port_object was checked in Dart - it cannot fail here");
@@ -106,6 +160,7 @@
ASSERT(!is_server || certificate_name != NULL);
GetFilter(args)->Connect(host_name,
+ &raw_addr,
static_cast<int>(port),
is_server,
certificate_name,
@@ -161,22 +216,6 @@
}
-void FUNCTION_NAME(SecureSocket_ProcessBuffer)(Dart_NativeArguments args) {
- Dart_EnterScope();
- Dart_Handle buffer_id_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
- int64_t buffer_id = DartUtils::GetIntegerValue(buffer_id_object);
- if (buffer_id < 0 || buffer_id >= SSLFilter::kNumBuffers) {
- Dart_ThrowException(DartUtils::NewDartArgumentError(
- "Illegal argument to ProcessBuffer"));
- }
-
- intptr_t bytes_read =
- GetFilter(args)->ProcessBuffer(static_cast<int>(buffer_id));
- Dart_SetReturnValue(args, Dart_NewInteger(bytes_read));
- Dart_ExitScope();
-}
-
-
void FUNCTION_NAME(SecureSocket_InitializeLibrary)
(Dart_NativeArguments args) {
Dart_EnterScope();
@@ -231,13 +270,142 @@
}
+void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
+ Dart_EnterScope();
+ intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
+ Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
+ Dart_ExitScope();
+}
+
+
+/**
+ * Pushes data through the SSL filter, reading and writing from circular
+ * buffers shared with Dart.
+ *
+ * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
+ * pass encrypted and plaintext data to and from the C++ SSLFilter object.
+ *
+ * ProcessFilter is called with a CObject array containing the pointer to
+ * the SSLFilter, encoded as an int, and the start and end positions of the
+ * valid data in the four circular buffers. The function only reads from
+ * the valid data area of the input buffers, and only writes to the free
+ * area of the output buffers. The function returns the new start and end
+ * positions in the buffers, but it only updates start for input buffers, and
+ * end for output buffers. Therefore, the Dart thread can simultaneously
+ * write to the free space and end pointer of input buffers, and read from
+ * the data space of output buffers, and modify the start pointer.
+ *
+ * When ProcessFilter returns, the Dart thread is responsible for combining
+ * the updated pointers from Dart and C++, to make the new valid state of
+ * the circular buffer.
+ */
+static void ProcessFilter(Dart_Port dest_port_id,
+ Dart_Port reply_port_id,
+ Dart_CObject* message) {
+ CObjectArray args(message);
+ CObjectIntptr filter_object(args[0]);
+ SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+ bool in_handshake = CObjectBool(args[1]).Value();
+ int starts[SSLFilter::kNumBuffers];
+ int ends[SSLFilter::kNumBuffers];
+ for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
+ starts[i] = CObjectInt32(args[2 * i + 2]).Value();
+ ends[i] = CObjectInt32(args[2 * i + 3]).Value();
+ }
+
+ filter->ProcessAllBuffers(starts, ends, in_handshake);
+
+ for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
+ args[2 * i + 2]->AsApiCObject()->value.as_int32 = starts[i];
+ args[2 * i + 3]->AsApiCObject()->value.as_int32 = ends[i];
+ }
+ Dart_PostCObject(reply_port_id, args.AsApiCObject());
+}
+
+
+void SSLFilter::ProcessAllBuffers(int starts[kNumBuffers],
+ int ends[kNumBuffers],
+ bool in_handshake) {
+ for (int i = 0; i < kNumBuffers; ++i) {
+ if (in_handshake && (i == kReadPlaintext || i == kWritePlaintext)) continue;
+ int start = starts[i];
+ int end = ends[i];
+ int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+ if (start < 0 || end < 0 || start >= size || end >= size) {
+ FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
+ }
+ switch (i) {
+ case kReadPlaintext:
+ case kWriteEncrypted:
+ // Write data to the circular buffer's free space. If the buffer
+ // is full, neither if statement is executed and nothing happens.
+ if (start <= end) {
+ // If the free space may be split into two segments,
+ // then the first is [end, size), unless start == 0.
+ // Then, since the last free byte is at position start - 2,
+ // the interval is [end, size - 1).
+ int buffer_end = (start == 0) ? size - 1 : size;
+ int bytes = (i == kReadPlaintext) ?
+ ProcessReadPlaintextBuffer(end, buffer_end) :
+ ProcessWriteEncryptedBuffer(end, buffer_end);
+ end += bytes;
+ ASSERT(end <= size);
+ if (end == size) end = 0;
+ }
+ if (start > end + 1) {
+ int bytes = (i == kReadPlaintext) ?
+ ProcessReadPlaintextBuffer(end, start - 1) :
+ ProcessWriteEncryptedBuffer(end, start - 1);
+ end += bytes;
+ ASSERT(end < start);
+ }
+ ends[i] = end;
+ break;
+ case kReadEncrypted:
+ // Read data from circular buffer.
+ if (end < start) {
+ // Data may be split into two segments. In this case,
+ // the first is [start, size).
+ int bytes = ProcessReadEncryptedBuffer(start, size);
+ start += bytes;
+ ASSERT(start <= size);
+ if (start == size) start = 0;
+ }
+ if (start < end) {
+ int bytes = ProcessReadEncryptedBuffer(start, end);
+ start += bytes;
+ ASSERT(start <= end);
+ }
+ starts[i] = start;
+ break;
+ case kWritePlaintext:
+ if (end < start) {
+ // Data is split into two segments, [start, size) and [0, end).
+ int bytes = ProcessWritePlaintextBuffer(start, size, 0, end);
+ start += bytes;
+ if (start >= size) start -= size;
+ } else {
+ int bytes = ProcessWritePlaintextBuffer(start, end, 0, 0);
+ start += bytes;
+ ASSERT(start <= end);
+ }
+ starts[i] = start;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+
static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
PRTime start_validity;
PRTime end_validity;
SECStatus status =
CERT_GetCertTimes(certificate, &start_validity, &end_validity);
if (status != SECSuccess) {
- ThrowPRException("Cannot get validity times from certificate");
+ ThrowPRException("CertificateException",
+ "Cannot get validity times from certificate");
}
int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
@@ -248,23 +416,23 @@
Dart_Handle start_epoch_ms_int = Dart_NewInteger(start_epoch_ms);
Dart_Handle end_epoch_ms_int = Dart_NewInteger(end_epoch_ms);
- Dart_Handle date_class =
- DartUtils::GetDartClass(DartUtils::kCoreLibURL, "DateTime");
+ Dart_Handle date_type =
+ DartUtils::GetDartType(DartUtils::kCoreLibURL, "DateTime");
Dart_Handle from_milliseconds =
DartUtils::NewString("fromMillisecondsSinceEpoch");
Dart_Handle start_validity_date =
- Dart_New(date_class, from_milliseconds, 1, &start_epoch_ms_int);
+ Dart_New(date_type, from_milliseconds, 1, &start_epoch_ms_int);
Dart_Handle end_validity_date =
- Dart_New(date_class, from_milliseconds, 1, &end_epoch_ms_int);
+ Dart_New(date_type, from_milliseconds, 1, &end_epoch_ms_int);
- Dart_Handle x509_class =
- DartUtils::GetDartClass(DartUtils::kIOLibURL, "X509Certificate");
+ Dart_Handle x509_type =
+ DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
Dart_Handle arguments[] = { subject_name_object,
issuer_name_object,
start_validity_date,
end_validity_date };
- return Dart_New(x509_class, Dart_Null(), 4, arguments);
+ return Dart_New(x509_type, Dart_Null(), 4, arguments);
}
@@ -291,25 +459,21 @@
// Create SSLFilter buffers as ExternalUint8Array objects.
Dart_Handle dart_buffers_object = ThrowIfError(
Dart_GetField(dart_this, DartUtils::NewString("buffers")));
- Dart_Handle dart_buffer_object =
- Dart_ListGetAt(dart_buffers_object, kReadPlaintext);
- Dart_Handle external_buffer_class =
- Dart_InstanceGetClass(dart_buffer_object);
+ Dart_Handle secure_filter_impl_type =
+ Dart_InstanceGetType(dart_this);
Dart_Handle dart_buffer_size = ThrowIfError(
- Dart_GetField(external_buffer_class, DartUtils::NewString("SIZE")));
+ Dart_GetField(secure_filter_impl_type, DartUtils::NewString("SIZE")));
int64_t buffer_size = DartUtils::GetIntegerValue(dart_buffer_size);
Dart_Handle dart_encrypted_buffer_size = ThrowIfError(
- Dart_GetField(external_buffer_class,
+ Dart_GetField(secure_filter_impl_type,
DartUtils::NewString("ENCRYPTED_SIZE")));
int64_t encrypted_buffer_size =
DartUtils::GetIntegerValue(dart_encrypted_buffer_size);
- if (buffer_size <= 0 || buffer_size > 1024 * 1024) {
- Dart_ThrowException(
- DartUtils::NewString("Invalid buffer size in _ExternalBuffer"));
+ if (buffer_size <= 0 || buffer_size > 1 * MB) {
+ FATAL("Invalid buffer size in _ExternalBuffer");
}
- if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1024 * 1024) {
- Dart_ThrowException(DartUtils::NewString(
- "Invalid encrypted buffer size in _ExternalBuffer"));
+ if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
+ FATAL("Invalid encrypted buffer size in _ExternalBuffer");
}
buffer_size_ = static_cast<int>(buffer_size);
encrypted_buffer_size_ = static_cast<int>(encrypted_buffer_size);
@@ -317,7 +481,7 @@
Dart_Handle data_identifier = DartUtils::NewString("data");
for (int i = 0; i < kNumBuffers; ++i) {
- int size = isEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+ int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
dart_buffer_objects_[i] =
Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i));
ASSERT(dart_buffer_objects_[i] != NULL);
@@ -373,14 +537,16 @@
status = NSS_NoDB_Init(NULL);
if (status != SECSuccess) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowPRException("Failed NSS_NoDB_Init call.");
+ ThrowPRException("TlsException",
+ "Failed NSS_NoDB_Init call.");
}
if (use_builtin_root_certificates) {
SECMODModule* module = SECMOD_LoadUserModule(
const_cast<char*>(builtin_roots_module), NULL, PR_FALSE);
if (!module) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowPRException("Failed to load builtin root certificates.");
+ ThrowPRException("TlsException",
+ "Failed to load builtin root certificates.");
}
}
} else {
@@ -395,7 +561,8 @@
init_flags);
if (status != SECSuccess) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowPRException("Failed NSS_Init call.");
+ ThrowPRException("TlsException",
+ "Failed NSS_Init call.");
}
}
library_initialized_ = true;
@@ -403,23 +570,29 @@
status = NSS_SetDomesticPolicy();
if (status != SECSuccess) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowPRException("Failed NSS_SetDomesticPolicy call.");
+ ThrowPRException("TlsException",
+ "Failed NSS_SetDomesticPolicy call.");
}
// Enable TLS, as well as SSL3 and SSL2.
status = SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE);
if (status != SECSuccess) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowPRException("Failed SSL_OptionSetDefault enable TLS call.");
+ ThrowPRException("TlsException",
+ "Failed SSL_OptionSetDefault enable TLS call.");
}
status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
if (status != SECSuccess) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowPRException("Failed SSL_ConfigServerSessionIDCache call.");
+ ThrowPRException("TlsException",
+ "Failed SSL_ConfigServerSessionIDCache call.");
}
} else if (report_duplicate_initialization) {
mutex_.Unlock(); // MutexLocker destructor not called when throwing.
- ThrowException("Called SSLFilter::InitializeLibrary more than once");
+ // Like ThrowPRException, without adding an OSError.
+ Dart_ThrowException(DartUtils::NewDartIOException("TlsException",
+ "Called SecureSocket.initialize more than once",
+ Dart_Null()));
}
}
@@ -457,6 +630,7 @@
void SSLFilter::Connect(const char* host_name,
+ RawAddr* raw_addr,
int port,
bool is_server,
const char* certificate_name,
@@ -465,7 +639,7 @@
bool send_client_certificate) {
is_server_ = is_server;
if (in_handshake_) {
- ThrowException("Connect called while already in handshake state.");
+ FATAL("Connect called twice on the same _SecureFilter.");
}
if (!is_server && certificate_name != NULL) {
@@ -474,9 +648,14 @@
filter_ = SSL_ImportFD(NULL, filter_);
if (filter_ == NULL) {
- ThrowPRException("Failed SSL_ImportFD call");
+ ThrowPRException("TlsException", "Failed SSL_ImportFD call");
}
+ SSLVersionRange vrange;
+ vrange.min = SSL_LIBRARY_VERSION_3_0;
+ vrange.max = SSL_LIBRARY_VERSION_TLS_1_1;
+ SSL_VersionRangeSet(filter_, &vrange);
+
SECStatus status;
if (is_server) {
PK11_SetPasswordFunc(PasswordCallback);
@@ -486,13 +665,15 @@
// Look up certificate using the distinguished name (DN) certificate_name.
CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
if (certificate_database == NULL) {
- ThrowPRException("Certificate database cannot be loaded");
+ ThrowPRException("CertificateException",
+ "Certificate database cannot be loaded");
}
certificate = CERT_FindCertByNameString(certificate_database,
const_cast<char*>(certificate_name));
if (certificate == NULL) {
- ThrowPRException(
- "Cannot find server certificate by distinguished name");
+ ThrowCertificateException(
+ "Cannot find server certificate by distinguished name: %s",
+ certificate_name);
}
} else {
// Look up certificate using the nickname certificate_name.
@@ -500,7 +681,9 @@
const_cast<char*>(certificate_name),
static_cast<void*>(const_cast<char*>(password_)));
if (certificate == NULL) {
- ThrowPRException("Cannot find server certificate by nickname");
+ ThrowCertificateException(
+ "Cannot find server certificate by nickname: %s",
+ certificate_name);
}
}
SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(
@@ -509,10 +692,12 @@
if (key == NULL) {
CERT_DestroyCertificate(certificate);
if (PR_GetError() == -8177) {
- ThrowPRException("Certificate database password incorrect");
+ ThrowPRException("CertificateException",
+ "Certificate database password incorrect");
} else {
- ThrowPRException("Failed PK11_FindKeyByAnyCert call."
- " Cannot find private key for certificate");
+ ThrowCertificateException(
+ "Cannot find private key for certificate %s",
+ certificate_name);
}
}
// kt_rsa (key type RSA) is an enum constant from the NSS libraries.
@@ -521,23 +706,28 @@
CERT_DestroyCertificate(certificate);
SECKEY_DestroyPrivateKey(key);
if (status != SECSuccess) {
- ThrowPRException("Failed SSL_ConfigSecureServer call");
+ ThrowCertificateException(
+ "Failed SSL_ConfigSecureServer call with certificate %s",
+ certificate_name);
}
if (request_client_certificate) {
status = SSL_OptionSet(filter_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
if (status != SECSuccess) {
- ThrowPRException("Failed SSL_OptionSet(REQUEST_CERTIFICATE) call");
+ ThrowPRException("TlsException",
+ "Failed SSL_OptionSet(REQUEST_CERTIFICATE) call");
}
PRBool require_cert = require_client_certificate ? PR_TRUE : PR_FALSE;
status = SSL_OptionSet(filter_, SSL_REQUIRE_CERTIFICATE, require_cert);
if (status != SECSuccess) {
- ThrowPRException("Failed SSL_OptionSet(REQUIRE_CERTIFICATE) call");
+ ThrowPRException("TlsException",
+ "Failed SSL_OptionSet(REQUIRE_CERTIFICATE) call");
}
}
} else { // Client.
if (SSL_SetURL(filter_, host_name) == -1) {
- ThrowPRException("Failed SetURL call");
+ ThrowPRException("TlsException",
+ "Failed SetURL call");
}
// This disables the SSL session cache for client connections.
@@ -545,7 +735,8 @@
// TODO(7230): Reenable session cache, without breaking client connections.
status = SSL_OptionSet(filter_, SSL_NO_CACHE, PR_TRUE);
if (status != SECSuccess) {
- ThrowPRException("Failed SSL_OptionSet(NO_CACHE) call");
+ ThrowPRException("TlsException",
+ "Failed SSL_OptionSet(NO_CACHE) call");
}
if (send_client_certificate) {
@@ -554,7 +745,8 @@
NSS_GetClientAuthData,
static_cast<void*>(client_certificate_name_));
if (status != SECSuccess) {
- ThrowPRException("Failed SSL_GetClientAuthDataHook call");
+ ThrowPRException("TlsException",
+ "Failed SSL_GetClientAuthDataHook call");
}
}
}
@@ -567,22 +759,28 @@
PRBool as_server = is_server ? PR_TRUE : PR_FALSE;
status = SSL_ResetHandshake(filter_, as_server);
if (status != SECSuccess) {
- ThrowPRException("Failed SSL_ResetHandshake call");
+ ThrowPRException("TlsException",
+ "Failed SSL_ResetHandshake call");
}
- // SetPeerAddress
- PRNetAddr host_address;
- PRAddrInfo* info = PR_GetAddrInfoByName(host_name,
- PR_AF_UNSPEC,
- PR_AI_ADDRCONFIG);
- if (info == NULL) {
- ThrowPRException("Failed PR_GetAddrInfoByName call");
- }
+ // Set the peer address from the address passed. The DNS has already
+ // been done in Dart code, so just use that address. This relies on
+ // following about PRNetAddr: "The raw member of the union is
+ // equivalent to struct sockaddr", which is stated in the NSS
+ // documentation.
+ PRNetAddr peername;
+ memset(&peername, 0, sizeof(peername));
+ intptr_t len = SocketAddress::GetAddrLength(raw_addr);
+ ASSERT(static_cast<size_t>(len) <= sizeof(peername));
+ memmove(&peername, &raw_addr->addr, len);
- PR_EnumerateAddrInfo(0, info, port, &host_address);
+ // Adjust the address family field for BSD, whose sockaddr
+ // structure has a one-byte length and one-byte address family
+ // field at the beginning. PRNetAddr has a two-byte address
+ // family field at the beginning.
+ peername.raw.family = raw_addr->addr.sa_family;
- memio_SetPeerName(filter_, &host_address);
- PR_FreeAddrInfo(info);
+ memio_SetPeerName(filter_, &peername);
}
@@ -602,9 +800,11 @@
}
} else {
if (is_server_) {
- ThrowPRException("Unexpected handshake error in server");
+ ThrowPRException("HandshakeException",
+ "Handshake error in server");
} else {
- ThrowPRException("Unexpected handshake error in client");
+ ThrowPRException("HandshakeException",
+ "Handshake error in client");
}
}
}
@@ -626,106 +826,112 @@
}
-intptr_t SSLFilter::ProcessBuffer(int buffer_index) {
- int size = isEncrypted(buffer_index) ? encrypted_buffer_size_ : buffer_size_;
- Dart_Handle buffer_object =
- Dart_HandleFromPersistent(dart_buffer_objects_[buffer_index]);
- Dart_Handle start_object = ThrowIfError(
- Dart_GetField(buffer_object, Dart_HandleFromPersistent(string_start_)));
- Dart_Handle length_object = ThrowIfError(
- Dart_GetField(buffer_object, Dart_HandleFromPersistent(string_length_)));
- int64_t unsafe_start = DartUtils::GetIntegerValue(start_object);
- int64_t unsafe_length = DartUtils::GetIntegerValue(length_object);
- ASSERT(unsafe_start >= 0);
- ASSERT(unsafe_start < size);
- ASSERT(unsafe_length >= 0);
- ASSERT(unsafe_length <= size);
- int start = static_cast<int>(unsafe_start);
- int length = static_cast<int>(unsafe_length);
- uint8_t* buffer = buffers_[buffer_index];
-
+intptr_t SSLFilter::ProcessReadPlaintextBuffer(int start, int end) {
+ int length = end - start;
int bytes_processed = 0;
- switch (buffer_index) {
- case kReadPlaintext: {
- int bytes_free = size - start - length;
- bytes_processed = PR_Read(filter_,
- buffer + start + length,
- bytes_free);
- if (bytes_processed < 0) {
- ASSERT(bytes_processed == -1);
- // TODO(whesse): Handle unexpected errors here.
- PRErrorCode pr_error = PR_GetError();
- if (PR_WOULD_BLOCK_ERROR != pr_error) {
- ThrowPRException("Error reading plaintext from SSLFilter");
- }
- bytes_processed = 0;
+ if (length > 0) {
+ bytes_processed = PR_Read(filter_,
+ buffers_[kReadPlaintext] + start,
+ length);
+ if (bytes_processed < 0) {
+ ASSERT(bytes_processed == -1);
+ PRErrorCode pr_error = PR_GetError();
+ if (PR_WOULD_BLOCK_ERROR != pr_error) {
+ // TODO(11383): Handle unexpected errors here.
+ FATAL("Error reading plaintext from SSLFilter");
}
- break;
- }
-
- case kWriteEncrypted: {
- const uint8_t* buf1;
- const uint8_t* buf2;
- unsigned int len1;
- unsigned int len2;
- int bytes_free = size - start - length;
- memio_Private* secret = memio_GetSecret(filter_);
- memio_GetWriteParams(secret, &buf1, &len1, &buf2, &len2);
- int bytes_to_send =
- dart::Utils::Minimum(len1, static_cast<unsigned>(bytes_free));
- if (bytes_to_send > 0) {
- memmove(buffer + start + length, buf1, bytes_to_send);
- bytes_processed = bytes_to_send;
- }
- bytes_to_send = dart::Utils::Minimum(len2,
- static_cast<unsigned>(bytes_free - bytes_processed));
- if (bytes_to_send > 0) {
- memmove(buffer + start + length + bytes_processed, buf2,
- bytes_to_send);
- bytes_processed += bytes_to_send;
- }
- if (bytes_processed > 0) {
- memio_PutWriteResult(secret, bytes_processed);
- }
- break;
- }
-
- case kReadEncrypted: {
- if (length > 0) {
- bytes_processed = length;
- memio_Private* secret = memio_GetSecret(filter_);
- uint8_t* filter_buf;
- int free_bytes = memio_GetReadParams(secret, &filter_buf);
- if (free_bytes < bytes_processed) bytes_processed = free_bytes;
- memmove(filter_buf,
- buffer + start,
- bytes_processed);
- memio_PutReadResult(secret, bytes_processed);
- }
- break;
- }
-
- case kWritePlaintext: {
- if (length > 0) {
- bytes_processed = PR_Write(filter_,
- buffer + start,
- length);
- }
-
- if (bytes_processed < 0) {
- ASSERT(bytes_processed == -1);
- // TODO(whesse): Handle unexpected errors here.
- PRErrorCode pr_error = PR_GetError();
- if (PR_WOULD_BLOCK_ERROR != pr_error) {
- ThrowPRException("Error reading plaintext from SSLFilter");
- }
- bytes_processed = 0;
- }
- break;
+ bytes_processed = 0;
}
}
return bytes_processed;
}
+
+intptr_t SSLFilter::ProcessWritePlaintextBuffer(int start1, int end1,
+ int start2, int end2) {
+ PRIOVec ranges[2];
+ uint8_t* buffer = buffers_[kWritePlaintext];
+ ranges[0].iov_base = reinterpret_cast<char*>(buffer + start1);
+ ranges[0].iov_len = end1 - start1;
+ ranges[1].iov_base = reinterpret_cast<char*>(buffer + start2);
+ ranges[1].iov_len = end2 - start2;
+ int bytes_processed = PR_Writev(filter_, ranges, 2, PR_INTERVAL_NO_TIMEOUT);
+ if (bytes_processed < 0) {
+ ASSERT(bytes_processed == -1);
+ PRErrorCode pr_error = PR_GetError();
+ if (PR_WOULD_BLOCK_ERROR != pr_error) {
+ // TODO(11383): Handle unexpected errors here.
+ FATAL("Error reading plaintext from SSLFilter");
+ }
+ bytes_processed = 0;
+ }
+ return bytes_processed;
+}
+
+
+intptr_t SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
+ int length = end - start;
+ int bytes_processed = 0;
+ if (length > 0) {
+ memio_Private* secret = memio_GetSecret(filter_);
+ uint8_t* filter_buf;
+ int free_bytes = memio_GetReadParams(secret, &filter_buf);
+ bytes_processed = dart::Utils::Minimum(length, free_bytes);
+ memmove(filter_buf, buffers_[kReadEncrypted] + start, bytes_processed);
+ memio_PutReadResult(secret, bytes_processed);
+ }
+ return bytes_processed;
+}
+
+
+intptr_t SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) {
+ int length = end - start;
+ int bytes_processed = 0;
+ if (length > 0) {
+ uint8_t* buffer = buffers_[kWriteEncrypted];
+ const uint8_t* buf1;
+ const uint8_t* buf2;
+ unsigned int len1;
+ unsigned int len2;
+ memio_Private* secret = memio_GetSecret(filter_);
+ memio_GetWriteParams(secret, &buf1, &len1, &buf2, &len2);
+ int bytes_to_send =
+ dart::Utils::Minimum(len1, static_cast<unsigned>(length));
+ if (bytes_to_send > 0) {
+ memmove(buffer + start, buf1, bytes_to_send);
+ bytes_processed = bytes_to_send;
+ }
+ bytes_to_send = dart::Utils::Minimum(len2,
+ static_cast<unsigned>(length - bytes_processed));
+ if (bytes_to_send > 0) {
+ memmove(buffer + start + bytes_processed, buf2, bytes_to_send);
+ bytes_processed += bytes_to_send;
+ }
+ if (bytes_processed > 0) {
+ memio_PutWriteResult(secret, bytes_processed);
+ }
+ }
+ return bytes_processed;
+}
+
+
+Dart_Port SSLFilter::GetServicePort() {
+ return filter_service_.GetServicePort();
+}
+
+
+void FUNCTION_NAME(SecureSocket_NewServicePort)(Dart_NativeArguments args) {
+ Dart_EnterScope();
+ Dart_SetReturnValue(args, Dart_Null());
+ Dart_Port service_port = SSLFilter::GetServicePort();
+ if (service_port != ILLEGAL_PORT) {
+ // Return a send port for the service port.
+ Dart_Handle send_port = Dart_NewSendPort(service_port);
+ Dart_SetReturnValue(args, send_port);
+ }
+ Dart_ExitScope();
+}
+
+
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 010b5ad..2f8225e 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -20,29 +20,13 @@
#include "bin/builtin.h"
#include "bin/dartutils.h"
+#include "bin/socket.h"
#include "bin/utils.h"
+#include "bin/native_service.h"
namespace dart {
namespace bin {
-static void ThrowException(const char* message) {
- Dart_Handle socket_exception =
- DartUtils::NewDartSocketException(message, Dart_Null());
- Dart_ThrowException(socket_exception);
-}
-
-
-/* Handle an error reported from the NSS library. */
-static void ThrowPRException(const char* message) {
- PRErrorCode error_code = PR_GetError();
- const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN);
- OSError os_error_struct(error_code, error_message, OSError::kNSS);
- Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
- Dart_Handle socket_exception =
- DartUtils::NewDartSocketException(message, os_error);
- Dart_ThrowException(socket_exception);
-}
-
/*
* SSLFilter encapsulates the NSS SSL(TLS) code in a filter, that communicates
* with the containing _SecureFilterImpl Dart object through four shared
@@ -73,6 +57,7 @@
void Init(Dart_Handle dart_this);
void Connect(const char* host,
+ RawAddr* raw_addr,
int port,
bool is_server,
const char* certificate_name,
@@ -86,18 +71,27 @@
Dart_Handle bad_certificate_callback() {
return Dart_HandleFromPersistent(bad_certificate_callback_);
}
+ intptr_t ProcessReadPlaintextBuffer(int start, int end);
+ intptr_t ProcessWritePlaintextBuffer(int start1, int end1,
+ int start2, int end2);
+ intptr_t ProcessReadEncryptedBuffer(int start, int end);
+ intptr_t ProcessWriteEncryptedBuffer(int start, int end);
+ void ProcessAllBuffers(int starts[kNumBuffers],
+ int ends[kNumBuffers],
+ bool in_handshake);
+ Dart_Handle PeerCertificate();
static void InitializeLibrary(const char* certificate_database,
const char* password,
bool use_builtin_root_certificates,
bool report_duplicate_initialization = true);
- intptr_t ProcessBuffer(int bufferIndex);
- Dart_Handle PeerCertificate();
+ static Dart_Port GetServicePort();
private:
static const int kMemioBufferSize = 20 * KB;
static bool library_initialized_;
static const char* password_;
static dart::Mutex mutex_; // To protect library initialization.
+ static NativeService filter_service_;
uint8_t* buffers_[kNumBuffers];
int buffer_size_;
@@ -112,7 +106,7 @@
char* client_certificate_name_;
PRFileDesc* filter_;
- static bool isEncrypted(int i) {
+ static bool isBufferEncrypted(int i) {
return static_cast<BufferIndex>(i) >= kFirstEncrypted;
}
void InitializeBuffers(Dart_Handle dart_this);
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index fdff0d5..4b7c5ab 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -15,6 +15,9 @@
patch class _SecureFilter {
/* patch */ factory _SecureFilter() => new _SecureFilterImpl();
+
+ /* patch */ static SendPort _newServicePort()
+ native "SecureSocket_NewServicePort";
}
@@ -49,14 +52,22 @@
class _SecureFilterImpl
extends NativeFieldWrapperClass1
implements _SecureFilter {
+ // Performance is improved if a full buffer of plaintext fits
+ // in the encrypted buffer, when encrypted.
+ static final int SIZE = 8 * 1024;
+ static final int ENCRYPTED_SIZE = 10 * 1024;
+
_SecureFilterImpl() {
buffers = new List<_ExternalBuffer>(_RawSecureSocket.NUM_BUFFERS);
for (int i = 0; i < _RawSecureSocket.NUM_BUFFERS; ++i) {
- buffers[i] = new _ExternalBuffer();
+ buffers[i] = new _ExternalBuffer(_RawSecureSocket._isBufferEncrypted(i) ?
+ ENCRYPTED_SIZE :
+ SIZE);
}
}
void connect(String hostName,
+ Uint8List sockaddrStorage,
int port,
bool is_server,
String certificateName,
@@ -77,13 +88,14 @@
X509Certificate get peerCertificate native "SecureSocket_PeerCertificate";
- int processBuffer(int bufferIndex) native "SecureSocket_ProcessBuffer";
-
void registerBadCertificateCallback(Function callback)
native "SecureSocket_RegisterBadCertificateCallback";
void registerHandshakeCompleteCallback(Function handshakeCompleteHandler)
native "SecureSocket_RegisterHandshakeCompleteCallback";
+ // This is a security issue, as it exposes a raw pointer to Dart code.
+ int _pointer() native "SecureSocket_FilterPointer";
+
List<_ExternalBuffer> buffers;
}
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 89e6b00..41bcc9e 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -74,7 +74,7 @@
if (Dart_IsError(error)) Dart_PropagateError(error);
Dart_ThrowException(error);
}
- int len = SocketAddress::GetAddrLength(raw);
+ int len = SocketAddress::GetAddrLength(&raw);
Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
if (Dart_IsError(result)) Dart_PropagateError(result);
Dart_ListSetAsBytes(result, 0, reinterpret_cast<uint8_t *>(&raw), len);
@@ -130,6 +130,7 @@
void FUNCTION_NAME(Socket_Read)(Dart_NativeArguments args) {
Dart_EnterScope();
+ static bool short_socket_reads = Dart_IsVMFlagSet("short_socket_read");
Dart_Handle socket_obj = Dart_GetNativeArgument(args, 0);
intptr_t socket = 0;
Dart_Handle err = Socket::GetSocketIdNativeField(socket_obj, &socket);
@@ -142,6 +143,9 @@
if (length == -1 || available < length) {
length = available;
}
+ if (short_socket_reads) {
+ length = (length + 1) / 2;
+ }
uint8_t* buffer = NULL;
Dart_Handle result = IOBuffer::Allocate(length, &buffer);
if (Dart_IsError(result)) Dart_PropagateError(result);
@@ -149,12 +153,19 @@
intptr_t bytes_read = Socket::Read(socket, buffer, length);
if (bytes_read == length) {
Dart_SetReturnValue(args, result);
- } else if (bytes_read == 0) {
- // On MacOS when reading from a tty Ctrl-D will result in one
- // byte reported as available. Attempting to read it out will
- // result in zero bytes read. When that happens there is no
- // data which is indicated by a null return value.
- Dart_SetReturnValue(args, Dart_Null());
+ } else if (bytes_read < length) {
+ // On MacOS when reading from a tty Ctrl-D will result in reading one
+ // less byte then reported as available.
+ if (bytes_read == 0) {
+ Dart_SetReturnValue(args, Dart_Null());
+ } else {
+ uint8_t* new_buffer = NULL;
+ Dart_Handle new_result = IOBuffer::Allocate(bytes_read, &new_buffer);
+ if (Dart_IsError(new_result)) Dart_PropagateError(new_result);
+ ASSERT(new_buffer != NULL);
+ memmove(new_buffer, buffer, bytes_read);
+ Dart_SetReturnValue(args, new_result);
+ }
} else {
ASSERT(bytes_read == -1);
Dart_SetReturnValue(args, DartUtils::NewDartOSError());
@@ -175,57 +186,6 @@
}
-void FUNCTION_NAME(Socket_ReadList)(Dart_NativeArguments args) {
- Dart_EnterScope();
- static bool short_socket_reads = Dart_IsVMFlagSet("short_socket_read");
- Dart_Handle socket_obj = Dart_GetNativeArgument(args, 0);
- intptr_t socket = 0;
- Dart_Handle err = Socket::GetSocketIdNativeField(socket_obj, &socket);
- if (Dart_IsError(err)) Dart_PropagateError(err);
- Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
- int64_t offset = 0;
- int64_t length = 0;
- Dart_Handle offset_obj = Dart_GetNativeArgument(args, 2);
- Dart_Handle length_obj = Dart_GetNativeArgument(args, 3);
- if (Dart_IsList(buffer_obj) &&
- DartUtils::GetInt64Value(offset_obj, &offset) &&
- DartUtils::GetInt64Value(length_obj, &length)) {
- intptr_t buffer_len = 0;
- Dart_Handle result = Dart_ListLength(buffer_obj, &buffer_len);
- if (Dart_IsError(result)) {
- Dart_PropagateError(result);
- }
- ASSERT((offset + length) <= buffer_len);
- if (short_socket_reads) {
- length = (length + 1) / 2;
- }
- uint8_t* buffer = new uint8_t[length];
- intptr_t bytes_read = Socket::Read(socket, buffer, length);
- if (bytes_read > 0) {
- Dart_Handle result =
- Dart_ListSetAsBytes(buffer_obj, offset, buffer, bytes_read);
- if (Dart_IsError(result)) {
- delete[] buffer;
- Dart_PropagateError(result);
- }
- }
- delete[] buffer;
- if (bytes_read >= 0) {
- Dart_SetReturnValue(args, Dart_NewInteger(bytes_read));
- } else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError());
- }
- } else {
- OSError os_error(-1, "Invalid argument", OSError::kUnknown);
- Dart_Handle err = DartUtils::NewDartOSError(&os_error);
- if (Dart_IsError(err)) Dart_PropagateError(err);
- Dart_SetReturnValue(args, err);
- }
-
- Dart_ExitScope();
-}
-
-
void FUNCTION_NAME(Socket_WriteList)(Dart_NativeArguments args) {
Dart_EnterScope();
static bool short_socket_writes = Dart_IsVMFlagSet("short_socket_write");
@@ -446,7 +406,7 @@
CObjectInt32 type(request[2]);
CObject* result = NULL;
OSError* os_error = NULL;
- SocketAddresses* addresses =
+ AddressList<SocketAddress>* addresses =
Socket::LookupAddress(host.CString(), type.Value(), &os_error);
if (addresses != NULL) {
CObjectArray* array = new CObjectArray(
@@ -466,10 +426,10 @@
RawAddr raw = addr->addr();
CObjectUint8Array* data = new CObjectUint8Array(CObject::NewUint8Array(
- SocketAddress::GetAddrLength(raw)));
+ SocketAddress::GetAddrLength(&raw)));
memmove(data->Buffer(),
reinterpret_cast<void *>(&raw),
- SocketAddress::GetAddrLength(raw));
+ SocketAddress::GetAddrLength(&raw));
entry->SetAt(2, data);
array->SetAt(i + 1, entry);
@@ -486,6 +446,81 @@
}
+static CObject* ReverseLookupRequest(const CObjectArray& request) {
+ if (request.Length() == 2 &&
+ request[1]->IsTypedData()) {
+ CObjectUint8Array addr_object(request[1]);
+ RawAddr addr;
+ memmove(reinterpret_cast<void *>(&addr),
+ addr_object.Buffer(),
+ addr_object.Length());
+ OSError* os_error = NULL;
+ const intptr_t kMaxHostLength = 1025;
+ char host[kMaxHostLength];
+ if (Socket::ReverseLookup(addr, host, kMaxHostLength, &os_error)) {
+ return new CObjectString(CObject::NewString(host));
+ } else {
+ CObject* result = CObject::NewOSError(os_error);
+ delete os_error;
+ return result;
+ }
+ }
+ return CObject::IllegalArgumentError();
+}
+
+
+
+static CObject* ListInterfacesRequest(const CObjectArray& request) {
+ if (request.Length() == 2 &&
+ request[1]->IsInt32()) {
+ CObjectInt32 type(request[1]);
+ CObject* result = NULL;
+ OSError* os_error = NULL;
+ AddressList<InterfaceSocketAddress>* addresses = Socket::ListInterfaces(
+ type.Value(), &os_error);
+ if (addresses != NULL) {
+ CObjectArray* array = new CObjectArray(
+ CObject::NewArray(addresses->count() + 1));
+ array->SetAt(0, new CObjectInt32(CObject::NewInt32(0)));
+ for (intptr_t i = 0; i < addresses->count(); i++) {
+ InterfaceSocketAddress* interface = addresses->GetAt(i);
+ SocketAddress* addr = interface->socket_address();
+ CObjectArray* entry = new CObjectArray(CObject::NewArray(4));
+
+ CObjectInt32* type = new CObjectInt32(
+ CObject::NewInt32(addr->GetType()));
+ entry->SetAt(0, type);
+
+ CObjectString* as_string = new CObjectString(CObject::NewString(
+ addr->as_string()));
+ entry->SetAt(1, as_string);
+
+ RawAddr raw = addr->addr();
+ CObjectUint8Array* data = new CObjectUint8Array(CObject::NewUint8Array(
+ SocketAddress::GetAddrLength(&raw)));
+ memmove(data->Buffer(),
+ reinterpret_cast<void *>(&raw),
+ SocketAddress::GetAddrLength(&raw));
+ entry->SetAt(2, data);
+
+ CObjectString* interface_name = new CObjectString(CObject::NewString(
+ interface->interface_name()));
+ entry->SetAt(3, interface_name);
+
+ array->SetAt(i + 1, entry);
+ }
+ result = array;
+ delete addresses;
+ } else {
+ result = CObject::NewOSError(os_error);
+ delete os_error;
+ }
+ return result;
+ }
+ return CObject::IllegalArgumentError();
+}
+
+
void SocketService(Dart_Port dest_port_id,
Dart_Port reply_port_id,
Dart_CObject* message) {
@@ -498,6 +533,12 @@
case Socket::kLookupRequest:
response = LookupRequest(request);
break;
+ case Socket::kListInterfacesRequest:
+ response = ListInterfacesRequest(request);
+ break;
+ case Socket::kReverseLookupRequest:
+ response = ReverseLookupRequest(request);
+ break;
default:
UNREACHABLE();
}
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 46780fc..ffca207 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -51,7 +51,9 @@
ADDRESS_LAST = ADDRESS_ANY_IP_V6,
};
- explicit SocketAddress(struct addrinfo* addrinfo);
+ explicit SocketAddress(struct sockaddr* sockaddr);
+
+ ~SocketAddress() {}
int GetType() {
if (addr_.ss.ss_family == AF_INET6) return TYPE_IPV6;
@@ -61,8 +63,8 @@
const char* as_string() const { return as_string_; }
const RawAddr& addr() const { return addr_; }
- static intptr_t GetAddrLength(const RawAddr& addr) {
- return addr.ss.ss_family == AF_INET6 ?
+ static intptr_t GetAddrLength(const RawAddr* addr) {
+ return addr->ss.ss_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
}
@@ -96,13 +98,36 @@
DISALLOW_COPY_AND_ASSIGN(SocketAddress);
};
-class SocketAddresses {
+class InterfaceSocketAddress {
public:
- explicit SocketAddresses(intptr_t count)
- : count_(count),
- addresses_(new SocketAddress*[count_]) {}
+ explicit InterfaceSocketAddress(struct sockaddr* sockaddr,
+ const char* interface_name)
+ : socket_address_(new SocketAddress(sockaddr)),
+ interface_name_(interface_name) {}
- ~SocketAddresses() {
+ ~InterfaceSocketAddress() {
+ delete socket_address_;
+ free(const_cast<char*>(interface_name_));
+ }
+
+ SocketAddress* socket_address() const { return socket_address_; }
+ const char* interface_name() const { return interface_name_; }
+
+ private:
+ SocketAddress* socket_address_;
+ const char* interface_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(InterfaceSocketAddress);
+};
+
+template<typename T>
+class AddressList {
+ public:
+ explicit AddressList(intptr_t count)
+ : count_(count),
+ addresses_(new T*[count_]) {}
+
+ ~AddressList() {
for (intptr_t i = 0; i < count_; i++) {
delete addresses_[i];
}
@@ -110,20 +135,22 @@
}
intptr_t count() const { return count_; }
- SocketAddress* GetAt(intptr_t i) const { return addresses_[i]; }
- void SetAt(intptr_t i, SocketAddress* addr) { addresses_[i] = addr; }
+ T* GetAt(intptr_t i) const { return addresses_[i]; }
+ void SetAt(intptr_t i, T* addr) { addresses_[i] = addr; }
private:
const intptr_t count_;
- SocketAddress** addresses_;
+ T** addresses_;
- DISALLOW_COPY_AND_ASSIGN(SocketAddresses);
+ DISALLOW_COPY_AND_ASSIGN(AddressList);
};
class Socket {
public:
enum SocketRequest {
kLookupRequest = 0,
+ kListInterfacesRequest = 1,
+ kReverseLookupRequest = 2,
};
static bool Initialize();
@@ -144,10 +171,19 @@
static bool SetBlocking(intptr_t fd);
static bool SetNoDelay(intptr_t fd, bool enabled);
- // Perform a hostname lookup. Returns the SocketAddresses.
- static SocketAddresses* LookupAddress(const char* host,
- int type,
- OSError** os_error);
+ // Perform a hostname lookup. Returns a AddressList of SocketAddress's.
+ static AddressList<SocketAddress>* LookupAddress(const char* host,
+ int type,
+ OSError** os_error);
+ static bool ReverseLookup(RawAddr addr,
+ char* host,
+ intptr_t host_len,
+ OSError** os_error);
+
+ // List interfaces. Returns a AddressList of InterfaceSocketAddress's.
+ static AddressList<InterfaceSocketAddress>* ListInterfaces(
+ int type,
+ OSError** os_error);
static Dart_Port GetServicePort();
@@ -181,6 +217,7 @@
intptr_t backlog,
bool v6_only = false);
+ private:
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(ServerSocket);
};
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index c0fbacd..d837892 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -12,6 +12,7 @@
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
#include <netinet/tcp.h> // NOLINT
+#include <ifaddrs.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -22,17 +23,17 @@
namespace dart {
namespace bin {
-SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
+SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
- RawAddr* raw = reinterpret_cast<RawAddr*>(addrinfo->ai_addr);
- const char* result = inet_ntop(addrinfo->ai_family,
+ RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
+ const char* result = inet_ntop(sockaddr->sa_family,
&raw->in.sin_addr,
as_string_,
INET6_ADDRSTRLEN);
if (result == NULL) as_string_[0] = 0;
memmove(reinterpret_cast<void *>(&addr_),
- addrinfo->ai_addr,
- addrinfo->ai_addrlen);
+ sockaddr,
+ GetAddrLength(raw));
}
@@ -61,7 +62,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd,
&addr.addr,
- SocketAddress::GetAddrLength(addr)));
+ SocketAddress::GetAddrLength(&addr)));
if (result == 0 || errno == EINPROGRESS) {
return fd;
}
@@ -185,9 +186,9 @@
}
-SocketAddresses* Socket::LookupAddress(const char* host,
- int type,
- OSError** os_error) {
+AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
+ int type,
+ OSError** os_error) {
// Perform a name lookup for a host name.
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@@ -208,11 +209,11 @@
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
}
- SocketAddresses* addresses = new SocketAddresses(count);
intptr_t i = 0;
+ AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
- addresses->SetAt(i, new SocketAddress(c));
+ addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
}
@@ -221,6 +222,77 @@
}
+bool Socket::ReverseLookup(RawAddr addr,
+ char* host,
+ intptr_t host_len,
+ OSError** os_error) {
+ ASSERT(host_len >= NI_MAXHOST);
+ int status = TEMP_FAILURE_RETRY(getnameinfo(
+ &addr.addr,
+ SocketAddress::GetAddrLength(&addr),
+ host,
+ host_len,
+ NULL,
+ 0,
+ NI_NAMEREQD));
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error = new OSError(status,
+ gai_strerror(status),
+ OSError::kGetAddressInfo);
+ return false;
+ }
+ return true;
+}
+
+
+static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
+ int family = ifa->ifa_addr->sa_family;
+ if (lookup_family == family) return true;
+ if (lookup_family == AF_UNSPEC &&
+ (family == AF_INET || family == AF_INET6)) {
+ return true;
+ }
+ return false;
+}
+
+
+AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
+ int type,
+ OSError** os_error) {
+ struct ifaddrs* ifaddr;
+
+ int status = getifaddrs(&ifaddr);
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error = new OSError(status,
+ gai_strerror(status),
+ OSError::kGetAddressInfo);
+ return NULL;
+ }
+
+ int lookup_family = SocketAddress::FromType(type);
+
+ intptr_t count = 0;
+ for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) count++;
+ }
+
+ AddressList<InterfaceSocketAddress>* addresses =
+ new AddressList<InterfaceSocketAddress>(count);
+ int i = 0;
+ for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+ addresses->SetAt(i, new InterfaceSocketAddress(
+ ifa->ifa_addr, strdup(ifa->ifa_name)));
+ i++;
+ }
+ }
+ freeifaddrs(ifaddr);
+ return addresses;
+}
+
+
intptr_t ServerSocket::CreateBindListen(RawAddr addr,
intptr_t port,
intptr_t backlog,
@@ -246,7 +318,7 @@
if (TEMP_FAILURE_RETRY(
bind(fd,
&addr.addr,
- SocketAddress::GetAddrLength(addr))) < 0) {
+ SocketAddress::GetAddrLength(&addr))) < 0) {
TEMP_FAILURE_RETRY(close(fd));
return -1;
}
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 04ecbe7..3f97475 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -12,6 +12,7 @@
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
#include <netinet/tcp.h> // NOLINT
+#include <ifaddrs.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -22,17 +23,17 @@
namespace dart {
namespace bin {
-SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
+SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
- RawAddr* raw = reinterpret_cast<RawAddr*>(addrinfo->ai_addr);
- const char* result = inet_ntop(addrinfo->ai_family,
+ RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
+ const char* result = inet_ntop(sockaddr->sa_family,
&raw->in.sin_addr,
as_string_,
INET6_ADDRSTRLEN);
if (result == NULL) as_string_[0] = 0;
memmove(reinterpret_cast<void *>(&addr_),
- addrinfo->ai_addr,
- addrinfo->ai_addrlen);
+ sockaddr,
+ GetAddrLength(raw));
}
@@ -61,7 +62,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd,
&addr.addr,
- SocketAddress::GetAddrLength(addr)));
+ SocketAddress::GetAddrLength(&addr)));
if (result == 0 || errno == EINPROGRESS) {
return fd;
}
@@ -184,9 +185,9 @@
}
-SocketAddresses* Socket::LookupAddress(const char* host,
- int type,
- OSError** os_error) {
+AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
+ int type,
+ OSError** os_error) {
// Perform a name lookup for a host name.
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@@ -207,11 +208,11 @@
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
}
- SocketAddresses* addresses = new SocketAddresses(count);
intptr_t i = 0;
+ AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
- addresses->SetAt(i, new SocketAddress(c));
+ addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
}
@@ -220,6 +221,77 @@
}
+bool Socket::ReverseLookup(RawAddr addr,
+ char* host,
+ intptr_t host_len,
+ OSError** os_error) {
+ ASSERT(host_len >= NI_MAXHOST);
+ int status = TEMP_FAILURE_RETRY(getnameinfo(
+ &addr.addr,
+ SocketAddress::GetAddrLength(&addr),
+ host,
+ host_len,
+ NULL,
+ 0,
+ NI_NAMEREQD));
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error = new OSError(status,
+ gai_strerror(status),
+ OSError::kGetAddressInfo);
+ return false;
+ }
+ return true;
+}
+
+
+static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
+ int family = ifa->ifa_addr->sa_family;
+ if (lookup_family == family) return true;
+ if (lookup_family == AF_UNSPEC &&
+ (family == AF_INET || family == AF_INET6)) {
+ return true;
+ }
+ return false;
+}
+
+
+AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
+ int type,
+ OSError** os_error) {
+ struct ifaddrs* ifaddr;
+
+ int status = getifaddrs(&ifaddr);
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error = new OSError(status,
+ gai_strerror(status),
+ OSError::kGetAddressInfo);
+ return NULL;
+ }
+
+ int lookup_family = SocketAddress::FromType(type);
+
+ intptr_t count = 0;
+ for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) count++;
+ }
+
+ AddressList<InterfaceSocketAddress>* addresses =
+ new AddressList<InterfaceSocketAddress>(count);
+ int i = 0;
+ for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+ addresses->SetAt(i, new InterfaceSocketAddress(
+ ifa->ifa_addr, strdup(ifa->ifa_name)));
+ i++;
+ }
+ }
+ freeifaddrs(ifaddr);
+ return addresses;
+}
+
+
intptr_t ServerSocket::CreateBindListen(RawAddr addr,
intptr_t port,
intptr_t backlog,
@@ -245,7 +317,7 @@
if (TEMP_FAILURE_RETRY(
bind(fd,
&addr.addr,
- SocketAddress::GetAddrLength(addr))) < 0) {
+ SocketAddress::GetAddrLength(&addr))) < 0) {
TEMP_FAILURE_RETRY(close(fd));
return -1;
}
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 40b92cf..528f5ab 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -12,6 +12,7 @@
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
#include <netinet/tcp.h> // NOLINT
+#include <ifaddrs.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -22,17 +23,17 @@
namespace dart {
namespace bin {
-SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
+SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
- RawAddr* raw = reinterpret_cast<RawAddr*>(addrinfo->ai_addr);
- const char* result = inet_ntop(addrinfo->ai_family,
+ RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
+ const char* result = inet_ntop(sockaddr->sa_family,
&raw->in.sin_addr,
as_string_,
INET6_ADDRSTRLEN);
if (result == NULL) as_string_[0] = 0;
memmove(reinterpret_cast<void *>(&addr_),
- addrinfo->ai_addr,
- addrinfo->ai_addrlen);
+ sockaddr,
+ GetAddrLength(raw));
}
@@ -61,7 +62,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd,
&addr.addr,
- SocketAddress::GetAddrLength(addr)));
+ SocketAddress::GetAddrLength(&addr)));
if (result == 0 || errno == EINPROGRESS) {
return fd;
}
@@ -184,9 +185,9 @@
}
-SocketAddresses* Socket::LookupAddress(const char* host,
- int type,
- OSError** os_error) {
+AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
+ int type,
+ OSError** os_error) {
// Perform a name lookup for a host name.
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@@ -207,11 +208,11 @@
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
}
- SocketAddresses* addresses = new SocketAddresses(count);
intptr_t i = 0;
+ AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
- addresses->SetAt(i, new SocketAddress(c));
+ addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
}
@@ -220,6 +221,77 @@
}
+bool Socket::ReverseLookup(RawAddr addr,
+ char* host,
+ intptr_t host_len,
+ OSError** os_error) {
+ ASSERT(host_len >= NI_MAXHOST);
+ int status = TEMP_FAILURE_RETRY(getnameinfo(
+ &addr.addr,
+ SocketAddress::GetAddrLength(&addr),
+ host,
+ host_len,
+ NULL,
+ 0,
+ NI_NAMEREQD));
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error = new OSError(status,
+ gai_strerror(status),
+ OSError::kGetAddressInfo);
+ return false;
+ }
+ return true;
+}
+
+
+static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
+ int family = ifa->ifa_addr->sa_family;
+ if (lookup_family == family) return true;
+ if (lookup_family == AF_UNSPEC &&
+ (family == AF_INET || family == AF_INET6)) {
+ return true;
+ }
+ return false;
+}
+
+
+AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
+ int type,
+ OSError** os_error) {
+ struct ifaddrs* ifaddr;
+
+ int status = getifaddrs(&ifaddr);
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error = new OSError(status,
+ gai_strerror(status),
+ OSError::kGetAddressInfo);
+ return NULL;
+ }
+
+ int lookup_family = SocketAddress::FromType(type);
+
+ intptr_t count = 0;
+ for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) count++;
+ }
+
+ AddressList<InterfaceSocketAddress>* addresses =
+ new AddressList<InterfaceSocketAddress>(count);
+ int i = 0;
+ for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+ addresses->SetAt(i, new InterfaceSocketAddress(
+ ifa->ifa_addr, strdup(ifa->ifa_name)));
+ i++;
+ }
+ }
+ freeifaddrs(ifaddr);
+ return addresses;
+}
+
+
intptr_t ServerSocket::CreateBindListen(RawAddr addr,
intptr_t port,
intptr_t backlog,
@@ -245,7 +317,7 @@
if (TEMP_FAILURE_RETRY(
bind(fd,
&addr.addr,
- SocketAddress::GetAddrLength(addr))) < 0) {
+ SocketAddress::GetAddrLength(&addr))) < 0) {
VOID_TEMP_FAILURE_RETRY(close(fd));
return -1;
}
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index e69dfed..cc0a6e3 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -42,11 +42,25 @@
}
}
+patch class NetworkInterface {
+ /* patch */ static Future<List<NetworkInterface>> list({
+ bool includeLoopback: false,
+ bool includeLinkLocal: false,
+ InternetAddressType type: InternetAddressType.ANY}) {
+ return _NativeSocket.listInterfaces(includeLoopback: includeLoopback,
+ includeLinkLocal: includeLinkLocal,
+ type: type);
+ }
+}
+
class _InternetAddress implements InternetAddress {
static const int _ADDRESS_LOOPBACK_IP_V4 = 0;
static const int _ADDRESS_LOOPBACK_IP_V6 = 1;
static const int _ADDRESS_ANY_IP_V4 = 2;
static const int _ADDRESS_ANY_IP_V6 = 3;
+ static const int _IPV4_ADDR_OFFSET = 4;
+ static const int _IPV6_ADDR_OFFSET = 8;
+ static const int _IPV6_ADDR_LENGTH = 16;
static _InternetAddress LOOPBACK_IP_V4 =
new _InternetAddress.fixed(_ADDRESS_LOOPBACK_IP_V4);
@@ -62,6 +76,36 @@
final String host;
final Uint8List _sockaddr_storage;
+ bool get isLoopback {
+ switch (type) {
+ case InternetAddressType.IP_V4:
+ return _sockaddr_storage[_IPV4_ADDR_OFFSET] == 127;
+
+ case InternetAddressType.IP_V6:
+ for (int i = 0; i < _IPV6_ADDR_LENGTH - 1; i++) {
+ if (_sockaddr_storage[_IPV6_ADDR_OFFSET + i] != 0) return false;
+ }
+ int lastByteIndex = _IPV6_ADDR_OFFSET + _IPV6_ADDR_LENGTH - 1;
+ return _sockaddr_storage[lastByteIndex] == 1;
+ }
+ }
+
+ bool get isLinkLocal {
+ switch (type) {
+ case InternetAddressType.IP_V4:
+ // Checking for 169.254.0.0/16.
+ return _sockaddr_storage[_IPV4_ADDR_OFFSET] == 169 &&
+ _sockaddr_storage[_IPV4_ADDR_OFFSET + 1] == 254;
+
+ case InternetAddressType.IP_V6:
+ // Checking for fe80::/10.
+ return _sockaddr_storage[_IPV6_ADDR_OFFSET] == 0xFE &&
+ (_sockaddr_storage[_IPV6_ADDR_OFFSET + 1] & 0xB0) == 0x80;
+ }
+ }
+
+ Future<InternetAddress> reverse() => _NativeSocket.reverseLookup(this);
+
_InternetAddress(InternetAddressType this.type,
String this.address,
String this.host,
@@ -88,6 +132,12 @@
}
}
+ // Create a clone of this _InternetAddress replacing the host.
+ _InternetAddress _cloneWithNewHost(String host) {
+ return new _InternetAddress(
+ type, address, host, new Uint8List.fromList(_sockaddr_storage));
+ }
+
String toString() {
return "InternetAddress('$address', ${type.name})";
}
@@ -95,6 +145,17 @@
static Uint8List _fixed(int id) native "InternetAddress_Fixed";
}
+class _NetworkInterface implements NetworkInterface{
+ final String name;
+ final List<InternetAddress> addresses;
+
+ _NetworkInterface(String this.name, List<InternetAddress> this.addresses);
+
+ String toString() {
+ return "NetworkInterface('$name', $addresses)";
+ }
+}
+
// The _NativeSocket class encapsulates an OS socket.
class _NativeSocket extends NativeFieldWrapperClass1 {
@@ -131,6 +192,8 @@
// Native port messages.
static const HOST_NAME_LOOKUP = 0;
+ static const LIST_INTERFACES = 1;
+ static const REVERSE_LOOKUP = 2;
// Socket close state
bool isClosed = false;
@@ -174,6 +237,49 @@
});
}
+ static Future<InternetAddress> reverseLookup(InternetAddress addr) {
+ ensureSocketService();
+ return socketService.call([REVERSE_LOOKUP, addr._sockaddr_storage])
+ .then((response) {
+ if (isErrorResponse(response)) {
+ throw createError(response, "Failed host name lookup");
+ } else {
+ return addr._cloneWithNewHost(response);
+ }
+ });
+ }
+
+ static Future<List<NetworkInterface>> listInterfaces({
+ bool includeLoopback: false,
+ bool includeLinkLocal: false,
+ InternetAddressType type: InternetAddressType.ANY}) {
+ ensureSocketService();
+ return socketService.call([LIST_INTERFACES, type._value])
+ .then((response) {
+ if (isErrorResponse(response)) {
+ throw createError(response, "Failed listing interfaces");
+ } else {
+ var list = new List<NetworkInterface>();
+ var map = response.skip(1)
+ .fold(new Map<String, List<InternetAddress>>(), (map, result) {
+ var type = new InternetAddressType._from(result[0]);
+ var name = result[3];
+ var address = new _InternetAddress(
+ type, result[1], "", result[2]);
+ if (!includeLinkLocal && address.isLinkLocal) return map;
+ if (!includeLoopback && address.isLoopback) return map;
+ map.putIfAbsent(name, () => new List<InternetAddress>());
+ map[name].add(address);
+ return map;
+ })
+ .forEach((name, addresses) {
+ list.add(new _NetworkInterface(name, addresses));
+ });
+ return list;
+ }
+ });
+ }
+
static Future<_NativeSocket> connect(host, int port) {
return new Future.value(host)
.then((host) {
@@ -624,6 +730,9 @@
bool _readEventsEnabled = true;
bool _writeEventsEnabled = true;
+ // Flag to handle Ctrl-D closing of stdio on Mac OS.
+ bool _isMacOSTerminalInput = false;
+
static Future<RawSocket> connect(host, int port) {
return _NativeSocket.connect(host, port)
.then((socket) => new _RawSocket(socket));
@@ -663,7 +772,11 @@
var native = new _NativeSocket.pipe();
native.isClosedWrite = true;
if (fd != null) _getStdioHandle(native, fd);
- return new _RawSocket(native);
+ var result = new _RawSocket(native);
+ result._isMacOSTerminalInput =
+ Platform.isMacOS &&
+ _StdIOUtils._socketType(result._socket) == _STDIO_HANDLE_TYPE_TERMINAL;
+ return result;
}
StreamSubscription<RawSocketEvent> listen(void onData(RawSocketEvent event),
@@ -679,7 +792,21 @@
int available() => _socket.available();
- List<int> read([int len]) => _socket.read(len);
+ List<int> read([int len]) {
+ if (_isMacOSTerminalInput) {
+ var available = available();
+ if (available == 0) return null;
+ var data = _socket.read(len);
+ if (data == null || data.length < available) {
+ // Reading less than available from a Mac OS terminal indicate Ctrl-D.
+ // This is interpreted as read closed.
+ runAsync(() => _controller.add(RawSocketEvent.READ_CLOSED));
+ }
+ return data;
+ } else {
+ return _socket.read(len);
+ }
+ }
int write(List<int> buffer, [int offset, int count]) =>
_socket.write(buffer, offset, count);
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 3a3fd9d..f24cfc5 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -16,9 +16,9 @@
namespace dart {
namespace bin {
-SocketAddress::SocketAddress(struct addrinfo* addrinfo) {
+SocketAddress::SocketAddress(struct sockaddr* sockaddr) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
- RawAddr* raw = reinterpret_cast<RawAddr*>(addrinfo->ai_addr);
+ RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr);
// Clear the port before calling WSAAddressToString as WSAAddressToString
// includes the port in the formatted string.
@@ -33,8 +33,8 @@
as_string_[0] = 0;
}
memmove(reinterpret_cast<void *>(&addr_),
- addrinfo->ai_addr,
- addrinfo->ai_addrlen);
+ sockaddr,
+ SocketAddress::GetAddrLength(raw));
}
bool Socket::Initialize() {
@@ -142,7 +142,7 @@
SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd);
SOCKET s = handle->socket();
SocketAddress::SetAddrPort(&addr, port);
- int status = connect(s, &addr.addr, SocketAddress::GetAddrLength(addr));
+ int status = connect(s, &addr.addr, SocketAddress::GetAddrLength(&addr));
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd);
@@ -216,9 +216,9 @@
}
-SocketAddresses* Socket::LookupAddress(const char* host,
- int type,
- OSError** os_error) {
+AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
+ int type,
+ OSError** os_error) {
Initialize();
// Perform a name lookup for a host name.
@@ -241,11 +241,11 @@
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
}
- SocketAddresses* addresses = new SocketAddresses(count);
+ AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
intptr_t i = 0;
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
- addresses->SetAt(i, new SocketAddress(c));
+ addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
}
@@ -254,6 +254,85 @@
}
+bool Socket::ReverseLookup(RawAddr addr,
+ char* host,
+ intptr_t host_len,
+ OSError** os_error) {
+ ASSERT(host_len >= NI_MAXHOST);
+ int status = getnameinfo(&addr.addr,
+ SocketAddress::GetAddrLength(&addr),
+ host,
+ host_len,
+ NULL,
+ 0,
+ NI_NAMEREQD);
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ DWORD error_code = WSAGetLastError();
+ SetLastError(error_code);
+ *os_error = new OSError();
+ return false;
+ }
+ return true;
+}
+
+
+AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
+ int type,
+ OSError** os_error) {
+ Initialize();
+
+ ULONG size = 0;
+ DWORD flags = GAA_FLAG_SKIP_ANYCAST |
+ GAA_FLAG_SKIP_MULTICAST |
+ GAA_FLAG_SKIP_DNS_SERVER;
+ // Query the size needed.
+ int status = GetAdaptersAddresses(SocketAddress::FromType(type),
+ flags,
+ NULL,
+ NULL,
+ &size);
+ IP_ADAPTER_ADDRESSES* addrs = NULL;
+ if (status == ERROR_BUFFER_OVERFLOW) {
+ addrs = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(size));
+ // Get the addresses now we have the right buffer.
+ status = GetAdaptersAddresses(SocketAddress::FromType(type),
+ flags,
+ NULL,
+ addrs,
+ &size);
+ }
+ if (status != NO_ERROR) {
+ ASSERT(*os_error == NULL);
+ DWORD error_code = WSAGetLastError();
+ SetLastError(error_code);
+ *os_error = new OSError();
+ return NULL;
+ }
+ intptr_t count = 0;
+ for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) {
+ for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress;
+ u != NULL; u = u->Next) {
+ count++;
+ }
+ }
+ AddressList<InterfaceSocketAddress>* addresses =
+ new AddressList<InterfaceSocketAddress>(count);
+ intptr_t i = 0;
+ for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) {
+ for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress;
+ u != NULL; u = u->Next) {
+ addresses->SetAt(i, new InterfaceSocketAddress(
+ u->Address.lpSockaddr,
+ StringUtils::WideToUtf8(a->FriendlyName)));
+ i++;
+ }
+ }
+ free(addrs);
+ return addresses;
+}
+
+
intptr_t ServerSocket::CreateBindListen(RawAddr addr,
intptr_t port,
intptr_t backlog,
@@ -288,7 +367,7 @@
SocketAddress::SetAddrPort(&addr, port);
status = bind(s,
&addr.addr,
- SocketAddress::GetAddrLength(addr));
+ SocketAddress::GetAddrLength(&addr));
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
diff --git a/runtime/bin/socket_win.h b/runtime/bin/socket_win.h
index 67c9e7c..76f33fd 100644
--- a/runtime/bin/socket_win.h
+++ b/runtime/bin/socket_win.h
@@ -6,6 +6,7 @@
#define BIN_SOCKET_WIN_H_
#include <winsock2.h>
+#include <iphlpapi.h>
#include <ws2tcpip.h>
#include <mswsock.h>
diff --git a/runtime/bin/vmstats_impl.cc b/runtime/bin/vmstats_impl.cc
index b73fe64..b3eebff 100644
--- a/runtime/bin/vmstats_impl.cc
+++ b/runtime/bin/vmstats_impl.cc
@@ -59,7 +59,8 @@
// TODO(tball): allow host to be specified.
char* host = const_cast<char*>(DEFAULT_HOST);
OSError* os_error;
- SocketAddresses* addresses = Socket::LookupAddress(host, -1, &os_error);
+ AddressList<SocketAddress>* addresses =
+ Socket::LookupAddress(host, -1, &os_error);
if (addresses == NULL) {
Log::PrintErr("Failed IP lookup of VmStats host %s: %s\n",
host, os_error->message());
@@ -68,6 +69,7 @@
const intptr_t BACKLOG = 128; // Default value from HttpServer.dart
int64_t address = ServerSocket::CreateBindListen(
addresses->GetAt(0)->addr(), port, BACKLOG);
+ delete addresses;
if (address < 0) {
Log::PrintErr("Failed binding VmStats socket: %s:%d\n", host, port);
return;
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp
index b00105d..17f9bb3 100644
--- a/runtime/dart-runtime.gyp
+++ b/runtime/dart-runtime.gyp
@@ -11,11 +11,7 @@
'third_party/jscre/jscre.gypi',
],
'variables': {
- # TODO(zra): LIB_DIR is not defined by the ninja generator on Windows.
- # Also, LIB_DIR is not toolset specific on Mac. If we want to do a ninja
- # build on Windows, or cross-compile on Mac, we'll have to find some other
- # way of getting generated source files into toolset specific locations.
- 'gen_source_dir': '<(LIB_DIR)',
+ 'gen_source_dir': '<(SHARED_INTERMEDIATE_DIR)',
'version_in_cc_file': 'vm/version_in.cc',
'version_cc_file': '<(gen_source_dir)/version.cc',
@@ -42,7 +38,7 @@
'libdart_vm',
'libjscre',
'libdouble_conversion',
- 'generate_version_cc_file',
+ 'generate_version_cc_file#host',
],
'include_dirs': [
'.',
@@ -72,7 +68,7 @@
{
'target_name': 'generate_version_cc_file',
'type': 'none',
- 'toolsets':['target','host'],
+ 'toolsets':['host'],
'dependencies': [
'libdart_dependency_helper.target#target',
'libdart_dependency_helper.host#host',
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index cd09095b..a75932f 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1142,8 +1142,8 @@
DART_EXPORT bool Dart_IsExternalString(Dart_Handle object);
DART_EXPORT bool Dart_IsList(Dart_Handle object);
DART_EXPORT bool Dart_IsLibrary(Dart_Handle object);
+DART_EXPORT bool Dart_IsType(Dart_Handle handle);
DART_EXPORT bool Dart_IsClass(Dart_Handle handle);
-DART_EXPORT bool Dart_IsAbstractClass(Dart_Handle handle);
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle);
DART_EXPORT bool Dart_IsVariable(Dart_Handle handle);
DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle);
@@ -1165,6 +1165,18 @@
* any functions that more properly belong here. */
/**
+ * Gets the type of a Dart language object.
+ *
+ * \param instance Some Dart object.
+ *
+ * \return If no error occurs, the type is returned. Otherwise an
+ * error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance);
+
+/**
+ * TODO(asiva): Deprecate this method once all use cases have switched
+ * to using Dart_InstanceGetType
* Gets the class for some Dart language object.
*
* \param instance Some Dart object.
@@ -1736,7 +1748,7 @@
* This function allows hidden constructors (constructors with leading
* underscores) to be called.
*
- * \param clazz A class or an interface.
+ * \param type Type of object to be constructed.
* \param constructor_name The name of the constructor to invoke. Use
* Dart_Null() to invoke the unnamed constructor. This name should
* not include the name of the class.
@@ -1747,25 +1759,36 @@
* then the new object. If an error occurs during execution, then an
* error handle is returned.
*/
-DART_EXPORT Dart_Handle Dart_New(Dart_Handle clazz,
+DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
Dart_Handle constructor_name,
int number_of_arguments,
Dart_Handle* arguments);
/**
+ * Allocate a new object without invoking a constructor.
+ *
+ * \param type The type of an object to be allocated.
+ *
+ * \return The new object. If an error occurs during execution, then an
+ * error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type);
+
+/**
* Invokes a method or function.
*
- * The 'target' parameter may be an object, class, or library. If
+ * The 'target' parameter may be an object, type, or library. If
* 'target' is an object, then this function will invoke an instance
- * method. If 'target' is a class, then this function will invoke a
+ * method. If 'target' is a type, then this function will invoke a
* static method. If 'target' is a library, then this function will
* invoke a top-level function from that library.
+ * NOTE: This API call cannot be used to invoke methods of a type object.
*
* This function ignores visibility (leading underscores in names).
*
* May generate an unhandled exception error.
*
- * \param target An object, class, or library.
+ * \param target An object, type, or library.
* \param name The name of the function or method to invoke.
* \param number_of_arguments Size of the arguments array.
* \param arguments An array of arguments to the function.
@@ -1796,17 +1819,18 @@
/**
* Gets the value of a field.
*
- * The 'container' parameter may be an object, class, or library. If
+ * The 'container' parameter may be an object, type, or library. If
* 'container' is an object, then this function will access an
- * instance field. If 'container' is a class, then this function will
+ * instance field. If 'container' is a type, then this function will
* access a static field. If 'container' is a library, then this
* function will access a top-level variable.
+ * NOTE: This API call cannot be used to access fields of a type object.
*
* This function ignores field visibility (leading underscores in names).
*
* May generate an unhandled exception error.
*
- * \param container An object, class, or library.
+ * \param container An object, type, or library.
* \param name A field name.
*
* \return If no error occurs, then the value of the field is
@@ -1818,17 +1842,18 @@
/**
* Sets the value of a field.
*
- * The 'container' parameter may actually be an object, class, or
+ * The 'container' parameter may actually be an object, type, or
* library. If 'container' is an object, then this function will
- * access an instance field. If 'container' is a class, then this
+ * access an instance field. If 'container' is a type, then this
* function will access a static field. If 'container' is a library,
* then this function will access a top-level variable.
+ * NOTE: This API call cannot be used to access fields of a type object.
*
* This function ignores field visibility (leading underscores in names).
*
* May generate an unhandled exception error.
*
- * \param container An object, class, or library.
+ * \param container An object, type, or library.
* \param name A field name.
* \param value The new field value.
*
@@ -2058,6 +2083,24 @@
DART_EXPORT Dart_Handle Dart_RootLibrary();
/**
+ * Lookup or instantiate a type by name and type arguments from a Library.
+ *
+ * \param library The library containing the class or interface.
+ * \param class_name The class name for the type.
+ * \param number_of_type_arguments Number of type arguments.
+ * For non parametric types the number of type arguments would be 0.
+ * \param type_arguments Pointer to an array of type arguments.
+ * For non parameteric types a NULL would be passed in for this argument.
+ *
+ * \return If no error occurs, the type is returned.
+ * Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
+ Dart_Handle class_name,
+ intptr_t number_of_type_arguments,
+ Dart_Handle* type_arguments);
+
+/**
* Lookup a class or interface by name from a Library.
*
* \param library The library containing the class or interface.
@@ -2068,8 +2111,8 @@
*/
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
Dart_Handle class_name);
-/* TODO(turnidge): Consider returning Dart_Null() when the class is
- * not found to distinguish that from a true error case. */
+/* TODO(asiva): The above method needs to be removed once all uses
+ * of it are removed from the embedder code. */
/**
* Returns the url from which a library was loaded.
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart
index cfb640b..e7f88a3 100644
--- a/runtime/lib/array.dart
+++ b/runtime/lib/array.dart
@@ -118,7 +118,7 @@
// Iterable interface.
- bool contains(E element) {
+ bool contains(Object element) {
return IterableMixinWorkaround.contains(this, element);
}
@@ -202,11 +202,11 @@
IterableMixinWorkaround.sortList(this, compare);
}
- int indexOf(E element, [int start = 0]) {
+ int indexOf(Object element, [int start = 0]) {
return Arrays.indexOf(this, element, start, this.length);
}
- int lastIndexOf(E element, [int start = null]) {
+ int lastIndexOf(Object element, [int start = null]) {
if (start == null) start = length - 1;
return Arrays.lastIndexOf(this, element, start);
}
@@ -371,7 +371,7 @@
// Collection interface.
- bool contains(E element) {
+ bool contains(Object element) {
return IterableMixinWorkaround.contains(this, element);
}
@@ -460,11 +460,11 @@
return ToString.iterableToString(this);
}
- int indexOf(E element, [int start = 0]) {
+ int indexOf(Object element, [int start = 0]) {
return Arrays.indexOf(this, element, start, this.length);
}
- int lastIndexOf(E element, [int start = null]) {
+ int lastIndexOf(Object element, [int start = null]) {
if (start == null) start = length - 1;
return Arrays.lastIndexOf(this, element, start);
}
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index 6479ba2..415982c 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -9,11 +9,11 @@
_hashTable._container = this;
}
- /* patch */ bool containsKey(K key) {
+ /* patch */ bool containsKey(Object key) {
return _hashTable._get(key) >= 0;
}
- /* patch */ bool containsValue(V value) {
+ /* patch */ bool containsValue(Object value) {
List table = _hashTable._table;
int entrySize = _hashTable._entrySize;
for (int offset = 0; offset < table.length; offset += entrySize) {
@@ -33,7 +33,7 @@
});
}
- /* patch */ V operator [](K key) {
+ /* patch */ V operator [](Object key) {
int offset = _hashTable._get(key);
if (offset >= 0) return _hashTable._value(offset);
return null;
@@ -74,7 +74,7 @@
return value;
}
- /* patch */ V remove(K key) {
+ /* patch */ V remove(Object key) {
int offset = _hashTable._remove(key);
if (offset < 0) return null;
V oldValue = _hashTable._value(offset);
@@ -203,11 +203,11 @@
_hashTable._container = this;
}
- /* patch */ bool containsKey(K key) {
+ /* patch */ bool containsKey(Object key) {
return _hashTable._get(key) >= 0;
}
- /* patch */ bool containsValue(V value) {
+ /* patch */ bool containsValue(Object value) {
int modificationCount = _hashTable._modificationCount;
for (int offset = _hashTable._next(_LinkedHashTable._HEAD_OFFSET);
offset != _LinkedHashTable._HEAD_OFFSET;
@@ -229,7 +229,7 @@
});
}
- /* patch */ V operator [](K key) {
+ /* patch */ V operator [](Object key) {
int offset = _hashTable._get(key);
if (offset >= 0) return _hashTable._value(offset);
return null;
@@ -271,7 +271,7 @@
return value;
}
- /* patch */ V remove(K key) {
+ /* patch */ V remove(Object key) {
int offset = _hashTable._remove(key);
if (offset < 0) return null;
Object oldValue = _hashTable._value(offset);
@@ -644,7 +644,7 @@
/**
* Returns the offset of a key in [_table], or negative if it's not there.
*/
- int _get(K key) {
+ int _get(Object key) {
return _probeForLookup(_hashCodeOf(key), key);
}
@@ -678,7 +678,7 @@
* If [_entrySize] is greater than 1, the caller should clean up the
* remaining fields.
*/
- int _remove(K key) {
+ int _remove(Object key) {
int offset = _probeForLookup(_hashCodeOf(key), key);
if (offset >= 0) {
_deleteEntry(offset);
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index daf8f01..f52ff8f 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -169,3 +169,10 @@
return msg_buf.toString();
}
}
+
+class _FiftyThreeBitOverflowError implements Error {
+ final Object _value;
+
+ const _FiftyThreeBitOverflowError(this._value);
+ String toString() => "53-bit Overflow: $_value";
+}
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart
index 6dfb6f6..d58492e 100644
--- a/runtime/lib/growable_array.dart
+++ b/runtime/lib/growable_array.dart
@@ -212,11 +212,11 @@
throw new StateError("More than one element");
}
- int indexOf(T element, [int start = 0]) {
+ int indexOf(Object element, [int start = 0]) {
return IterableMixinWorkaround.indexOfList(this, element, start);
}
- int lastIndexOf(T element, [int start = null]) {
+ int lastIndexOf(Object element, [int start = null]) {
return IterableMixinWorkaround.lastIndexOfList(this, element, start);
}
@@ -230,7 +230,7 @@
// Collection interface.
- bool contains(T element) {
+ bool contains(Object element) {
return IterableMixinWorkaround.contains(this, element);
}
diff --git a/runtime/lib/immutable_map.dart b/runtime/lib/immutable_map.dart
index 3c5c72e..77127e5 100644
--- a/runtime/lib/immutable_map.dart
+++ b/runtime/lib/immutable_map.dart
@@ -10,7 +10,7 @@
: kvPairs_ = keyValuePairs;
- V operator [](K key) {
+ V operator [](Object key) {
// TODO(hausner): Since the keys are sorted, we could do a binary
// search. But is it worth it?
for (int i = 0; i < kvPairs_.length - 1; i += 2) {
@@ -45,7 +45,7 @@
return new _ImmutableMapValueIterable<V>(this);
}
- bool containsKey(K key) {
+ bool containsKey(Object key) {
for (int i = 0; i < kvPairs_.length; i += 2) {
if (key == kvPairs_[i]) {
return true;
@@ -54,7 +54,7 @@
return false;
}
- bool containsValue(V value) {
+ bool containsValue(Object value) {
for (int i = 1; i < kvPairs_.length; i += 2) {
if (value == kvPairs_[i]) {
return true;
@@ -75,7 +75,7 @@
throw new UnsupportedError("Cannot clear unmodifiable Map");
}
- V remove(K key) {
+ V remove(Object key) {
throw new UnsupportedError("Cannot remove from unmodifiable Map");
}
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 80b369c..2d40f2d 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -129,11 +129,14 @@
return _substringMatches(this.length - other.length, other);
}
- bool startsWith(Pattern pattern) {
- if (pattern is String) {
- return _substringMatches(0, pattern);
+ bool startsWith(Pattern pattern, [int index = 0]) {
+ if (index < 0 || index > this.length) {
+ throw new RangeError.range(index, 0, this.length);
}
- return pattern.matchAsPrefix(this, 0) != null;
+ if (pattern is String) {
+ return _substringMatches(index, pattern);
+ }
+ return pattern.matchAsPrefix(this, index) != null;
}
int indexOf(Pattern pattern, [int start = 0]) {
diff --git a/runtime/tests/vm/dart/byte_array_optimized_test.dart b/runtime/tests/vm/dart/byte_array_optimized_test.dart
index fafef82..8492798 100644
--- a/runtime/tests/vm/dart/byte_array_optimized_test.dart
+++ b/runtime/tests/vm/dart/byte_array_optimized_test.dart
@@ -1,6 +1,7 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// 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.
+// VMOptions=--optimization_counter_threshold=10
// Library tag to be able to run in html test framework.
library byte_array_test;
@@ -2129,7 +2130,7 @@
}
main() {
- for (var i=0; i<1000; i++) {
+ for (var i=0; i<20; i++) {
OptimizedByteArrayTest.testMain();
}
}
diff --git a/runtime/tests/vm/dart/byte_array_test.dart b/runtime/tests/vm/dart/byte_array_test.dart
index 0f3fe96..19fecb3 100644
--- a/runtime/tests/vm/dart/byte_array_test.dart
+++ b/runtime/tests/vm/dart/byte_array_test.dart
@@ -1,6 +1,7 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// 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.
+// VMOptions=--optimization_counter_threshold=10
// Library tag to be able to run in html test framework.
library byte_array_test;
@@ -2380,7 +2381,7 @@
}
main() {
- for (var i=0; i<1000; i++) {
+ for (var i=0; i<20; i++) {
ByteArrayTest.testMain();
}
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2319452..8f82b99 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -54,30 +54,19 @@
# Skip until we stabilize language tests.
*: Skip
-[ $arch == simarm || $arch == arm ]
-# Bug in optimized code generation results in timeout.
-dart/byte_array_test: Skip
-dart/byte_array_optimized_test: Skip
-
-[ $arch == arm ]
-cc/DoubleToFloatConversion: Fail # Issue: 11207
-cc/DoubleToIntConversion: Fail # Issue: 11207
-cc/FloatToDoubleConversion: Fail # Issue: 11207
-cc/FloatToIntConversion: Fail # Issue: 11207
-cc/IntToDoubleConversion: Fail # Issue: 11207
-cc/IntToFloatConversion: Fail # Issue: 11207
+[ $arch == arm && $mode == release ]
+dart/byte_array_optimized_test: Crash
+dart/byte_array_test: Crash
[ $arch == mips ]
*: Skip
-[ $arch == simmips ]
-# Tests missing code generation support.
-dart/byte_array_test: Skip
-dart/byte_array_optimized_test: Skip
+[ $arch == simarm ]
dart/isolate_mirror_local_test: Skip
-cc/ParsePatchLibrary: Skip
-cc/CorelibCompileAll: Skip
-cc/Dart2JSCompileAll: Skip
+
+[ $arch == simmips ]
+dart/isolate_mirror_local_test: Pass, Crash
+cc/FindCodeObject: Skip # Relative offsets are too far
# TODO(ajohnsen): Fix this as part of library changes.
[ $compiler == none ]
@@ -92,4 +81,3 @@
[ $compiler == dart2analyzer ]
# has compilation error, as designed
dart/isolate_mirror_local_test: fail
-
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 9e54e5a..4e31ae0 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -189,7 +189,6 @@
__ vsubs(S0, S0, S1); // 49.98f
__ vdivs(S0, S0, S1); // 14.7f
__ vsqrts(S0, S0); // 3.8340579f
- __ vmovrs(R0, S0);
__ bx(LR);
}
@@ -212,7 +211,6 @@
__ vsubd(D0, D0, D1); // 49.98
__ vdivd(D0, D0, D1); // 14.7
__ vsqrtd(D0, D0); // 3.8340579
- __ vmovrrd(R0, R1, D0);
__ bx(LR);
}
@@ -247,8 +245,7 @@
ASSEMBLER_TEST_GENERATE(IntToDoubleConversion, assembler) {
__ mov(R3, ShifterOperand(6));
__ vmovsr(S3, R3);
- __ vcvtdi(D1, S3);
- __ vmovrrd(R0, R1, D1);
+ __ vcvtdi(D0, S3);
__ bx(LR);
}
@@ -272,7 +269,6 @@
__ vcvtdi(D1, S2);
__ LoadDImmediate(D2, 1.0 * (1LL << 32), R0);
__ vmlad(D0, D1, D2);
- __ vmovrrd(R0, R1, D0);
__ bx(LR);
}
@@ -289,8 +285,7 @@
ASSEMBLER_TEST_GENERATE(IntToFloatConversion, assembler) {
__ mov(R3, ShifterOperand(6));
__ vmovsr(S3, R3);
- __ vcvtsi(S1, S3);
- __ vmovrs(R0, S1);
+ __ vcvtsi(S0, S3);
__ bx(LR);
}
@@ -304,9 +299,8 @@
ASSEMBLER_TEST_GENERATE(FloatToIntConversion, assembler) {
- __ vmovsr(S1, R0);
- __ vcvtis(S0, S1);
- __ vmovrs(R0, S0);
+ __ vcvtis(S1, S0);
+ __ vmovrs(R0, S1);
__ bx(LR);
}
@@ -327,8 +321,7 @@
ASSEMBLER_TEST_GENERATE(DoubleToIntConversion, assembler) {
- __ vmovdrr(D1, R0, R1);
- __ vcvtid(S0, D1);
+ __ vcvtid(S0, D0);
__ vmovrs(R0, S0);
__ bx(LR);
}
@@ -350,9 +343,8 @@
ASSEMBLER_TEST_GENERATE(FloatToDoubleConversion, assembler) {
- __ LoadSImmediate(S1, 12.8f);
- __ vcvtds(D2, S1);
- __ vmovrrd(R0, R1, D2);
+ __ LoadSImmediate(S2, 12.8f);
+ __ vcvtds(D0, S2);
__ bx(LR);
}
@@ -368,8 +360,7 @@
ASSEMBLER_TEST_GENERATE(DoubleToFloatConversion, assembler) {
__ LoadDImmediate(D1, 12.8, R0);
- __ vcvtsd(S3, D1);
- __ vmovrs(R0, S3);
+ __ vcvtsd(S0, D1);
__ bx(LR);
}
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index 0b74365..b94675a 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -138,7 +138,6 @@
public:
static void InitOnce() { }
static bool double_truncate_round_supported() {
- UNIMPLEMENTED();
return false;
}
};
@@ -461,6 +460,11 @@
EmitFpuRType(COP1, FMT_L, F0, fs, fd, COP1_CVT_D);
}
+ void cvtsd(FRegister fd, DRegister ds) {
+ FRegister fs = static_cast<FRegister>(ds * 2);
+ EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_S);
+ }
+
void cvtwd(FRegister fd, DRegister ds) {
FRegister fs = static_cast<FRegister>(ds * 2);
EmitFpuRType(COP1, FMT_D, F0, fs, fd, COP1_CVT_W);
diff --git a/runtime/vm/assembler_mips_test.cc b/runtime/vm/assembler_mips_test.cc
index 3152e4a..0e9185a 100644
--- a/runtime/vm/assembler_mips_test.cc
+++ b/runtime/vm/assembler_mips_test.cc
@@ -192,36 +192,6 @@
}
-ASSEMBLER_TEST_GENERATE(Divu_zero, assembler) {
- __ addiu(R1, ZR, Immediate(27));
- __ addiu(R2, ZR, Immediate(0));
- __ divu(R1, R2);
- __ mflo(V0);
- __ jr(RA);
-}
-
-
-ASSEMBLER_TEST_RUN(Divu_zero, test) {
- typedef int (*SimpleCode)();
- EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
-}
-
-
-ASSEMBLER_TEST_GENERATE(Div_zero, assembler) {
- __ addiu(R1, ZR, Immediate(27));
- __ addiu(R2, ZR, Immediate(0));
- __ div(R1, R2);
- __ mflo(V0);
- __ jr(RA);
-}
-
-
-ASSEMBLER_TEST_RUN(Div_zero, test) {
- typedef int (*SimpleCode)();
- EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
-}
-
-
ASSEMBLER_TEST_GENERATE(Divu_corner, assembler) {
__ LoadImmediate(R1, 0x80000000);
__ LoadImmediate(R2, 0xffffffff);
@@ -1217,25 +1187,24 @@
ASSEMBLER_TEST_GENERATE(Mtc1Mfc1, assembler) {
__ mtc1(ZR, F0);
+ __ mtc1(ZR, F1);
__ mfc1(V0, F0);
+ __ mfc1(V1, F1);
__ Ret();
}
ASSEMBLER_TEST_RUN(Mtc1Mfc1, test) {
- typedef double (*SimpleCode)();
+ typedef int (*SimpleCode)();
EXPECT(test != NULL);
- double res = EXECUTE_TEST_CODE_FLOAT(SimpleCode, test->entry());
- EXPECT_FLOAT_EQ(0.0, res, 0.001);
+ EXPECT_EQ(0, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
}
ASSEMBLER_TEST_GENERATE(Addd, assembler) {
__ LoadImmediate(D0, 1.0);
__ LoadImmediate(D1, 2.0);
- __ addd(D2, D0, D1);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ addd(D0, D0, D1);
__ Ret();
}
@@ -1249,10 +1218,8 @@
ASSEMBLER_TEST_GENERATE(Movd, assembler) {
- __ LoadImmediate(D0, 1.0);
- __ movd(D1, D0);
- __ mfc1(V0, F2);
- __ mfc1(V1, F3);
+ __ LoadImmediate(D1, 1.0);
+ __ movd(D0, D1);
__ Ret();
}
@@ -1269,11 +1236,9 @@
__ AddImmediate(SP, -8 * kWordSize);
__ LoadImmediate(T1, ~(8 - 1));
__ and_(T0, SP, T1); // Need 8 byte alignment.
- __ LoadImmediate(D0, 1.0);
- __ sdc1(D0, Address(T0));
- __ ldc1(D1, Address(T0));
- __ mfc1(V0, F2);
- __ mfc1(V1, F3);
+ __ LoadImmediate(D1, 1.0);
+ __ sdc1(D1, Address(T0));
+ __ ldc1(D0, Address(T0));
__ Ret();
}
@@ -1292,9 +1257,7 @@
__ LoadImmediate(T0, 0x7FF80000);
__ mtc1(ZR, F2); // Load upper bits of NaN.
__ mtc1(T0, F3); // Load lower bits of NaN.
- __ addd(D2, D0, D1);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ addd(D0, D0, D1);
__ Ret();
}
@@ -1312,9 +1275,7 @@
__ LoadImmediate(T0, 0x7FF00000); // +inf
__ mtc1(ZR, F2);
__ mtc1(T0, F3);
- __ addd(D2, D0, D1);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ addd(D0, D0, D1);
__ Ret();
}
@@ -1330,9 +1291,7 @@
ASSEMBLER_TEST_GENERATE(Subd, assembler) {
__ LoadImmediate(D0, 2.5);
__ LoadImmediate(D1, 1.5);
- __ subd(D2, D0, D1);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ subd(D0, D0, D1);
__ Ret();
}
@@ -1348,9 +1307,7 @@
ASSEMBLER_TEST_GENERATE(Muld, assembler) {
__ LoadImmediate(D0, 6.0);
__ LoadImmediate(D1, 7.0);
- __ muld(D2, D0, D1);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ muld(D0, D0, D1);
__ Ret();
}
@@ -1366,9 +1323,7 @@
ASSEMBLER_TEST_GENERATE(Divd, assembler) {
__ LoadImmediate(D0, 42.0);
__ LoadImmediate(D1, 7.0);
- __ divd(D2, D0, D1);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ divd(D0, D0, D1);
__ Ret();
}
@@ -1382,10 +1337,8 @@
ASSEMBLER_TEST_GENERATE(Sqrtd, assembler) {
- __ LoadImmediate(D0, 36.0);
- __ sqrtd(D2, D0);
- __ mfc1(V0, F4);
- __ mfc1(V1, F5);
+ __ LoadImmediate(D1, 36.0);
+ __ sqrtd(D0, D1);
__ Ret();
}
@@ -1602,10 +1555,8 @@
ASSEMBLER_TEST_GENERATE(Cop1CvtDW, assembler) {
__ LoadImmediate(T0, 42);
- __ mtc1(T0, F0);
- __ cvtdw(D1, F0);
- __ mfc1(V0, F2);
- __ mfc1(V1, F3);
+ __ mtc1(T0, F2);
+ __ cvtdw(D0, F2);
__ Ret();
}
@@ -1620,10 +1571,8 @@
ASSEMBLER_TEST_GENERATE(Cop1CvtDW_neg, assembler) {
__ LoadImmediate(T0, -42);
- __ mtc1(T0, F0);
- __ cvtdw(D1, F0);
- __ mfc1(V0, F2);
- __ mfc1(V1, F3);
+ __ mtc1(T0, F2);
+ __ cvtdw(D0, F2);
__ Ret();
}
@@ -1638,11 +1587,9 @@
ASSEMBLER_TEST_GENERATE(Cop1CvtDL, assembler) {
__ LoadImmediate(T0, 0x1);
- __ mtc1(ZR, F0);
- __ mtc1(T0, F1); // D0 <- 0x100000000 = 4294967296
- __ cvtdl(D1, D0);
- __ mfc1(V0, F2);
- __ mfc1(V1, F3);
+ __ mtc1(ZR, F2);
+ __ mtc1(T0, F3); // D0 <- 0x100000000 = 4294967296
+ __ cvtdl(D0, D1);
__ Ret();
}
@@ -1657,11 +1604,9 @@
ASSEMBLER_TEST_GENERATE(Cop1CvtDL_neg, assembler) {
__ LoadImmediate(T0, 0xffffffff);
- __ mtc1(T0, F0);
- __ mtc1(T0, F1); // D0 <- 0xffffffffffffffff = -1
- __ cvtdl(D1, D0);
- __ mfc1(V0, F2);
- __ mfc1(V1, F3);
+ __ mtc1(T0, F2);
+ __ mtc1(T0, F3); // D0 <- 0xffffffffffffffff = -1
+ __ cvtdl(D0, D1);;
__ Ret();
}
@@ -1675,35 +1620,51 @@
ASSEMBLER_TEST_GENERATE(Cop1CvtWD, assembler) {
- __ LoadImmediate(D0, 42.0);
- __ cvtwd(F2, D0);
- __ mfc1(V0, F2);
+ __ LoadImmediate(D1, 42.0);
+ __ cvtwd(F0, D1);
+ __ mfc1(V0, F0);
__ Ret();
}
ASSEMBLER_TEST_RUN(Cop1CvtWD, test) {
- typedef double (*SimpleCode)();
+ typedef int (*SimpleCode)();
EXPECT(test != NULL);
EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
}
ASSEMBLER_TEST_GENERATE(Cop1CvtWD_neg, assembler) {
- __ LoadImmediate(D0, -42.0);
- __ cvtwd(F2, D0);
- __ mfc1(V0, F2);
+ __ LoadImmediate(D1, -42.0);
+ __ cvtwd(F0, D1);
+ __ mfc1(V0, F0);
__ Ret();
}
ASSEMBLER_TEST_RUN(Cop1CvtWD_neg, test) {
- typedef double (*SimpleCode)();
+ typedef int (*SimpleCode)();
EXPECT(test != NULL);
EXPECT_EQ(-42, EXECUTE_TEST_CODE_INT32(SimpleCode, test->entry()));
}
+ASSEMBLER_TEST_GENERATE(Cop1CvtSD, assembler) {
+ __ LoadImmediate(D2, -42.42);
+ __ cvtsd(F2, D2);
+ __ cvtds(D0, F2);
+ __ Ret();
+}
+
+
+ASSEMBLER_TEST_RUN(Cop1CvtSD, test) {
+ typedef double (*SimpleCode)();
+ EXPECT(test != NULL);
+ double res = EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry());
+ EXPECT_FLOAT_EQ(-42.42, res, 0.001);
+}
+
+
// Called from assembler_test.cc.
// RA: return address.
// A0: context.
diff --git a/runtime/vm/base_isolate.h b/runtime/vm/base_isolate.h
index 687054f..e445209 100644
--- a/runtime/vm/base_isolate.h
+++ b/runtime/vm/base_isolate.h
@@ -95,6 +95,16 @@
}
#if defined(DEBUG)
+ void set_reusable_handle_scope_active(bool value) {
+ reusable_handle_scope_active_ = value;
+ }
+
+ bool reusable_handle_scope_active() {
+ return reusable_handle_scope_active_;
+ }
+#endif
+
+#if defined(DEBUG)
static void AssertCurrent(BaseIsolate* isolate);
#endif
@@ -106,6 +116,7 @@
top_handle_scope_(NULL),
no_handle_scope_depth_(0),
no_gc_scope_depth_(0),
+ reusable_handle_scope_active_(false),
#endif
no_callback_scope_depth_(0)
{}
@@ -120,9 +131,11 @@
HandleScope* top_handle_scope_;
int32_t no_handle_scope_depth_;
int32_t no_gc_scope_depth_;
+ bool reusable_handle_scope_active_;
#endif
int32_t no_callback_scope_depth_;
+ private:
DISALLOW_COPY_AND_ASSIGN(BaseIsolate);
};
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 9fff0d7..4b95263 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -957,7 +957,8 @@
function = super_class.LookupFunction(name);
if (!function.IsNull() &&
!function.is_static() &&
- !function.IsMethodExtractor()) {
+ !function.IsMethodExtractor() &&
+ !function.IsNoSuchMethodDispatcher()) {
return super_class.raw();
}
super_class = super_class.SuperClass();
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 88b5b76..2f08ac3 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -44,7 +44,7 @@
test->node_sequence()->Add(new ReturnNode(kPos, l));
parsed_function->SetNodeSequence(test->node_sequence());
parsed_function->set_instantiator(NULL);
- parsed_function->set_default_parameter_values(Array::ZoneHandle());
+ parsed_function->set_default_parameter_values(Object::null_array());
parsed_function->AllocateVariables();
bool retval;
Isolate* isolate = Isolate::Current();
@@ -259,7 +259,7 @@
PcDescriptors::Handle(code.pc_descriptors());
int call_count = 0;
for (int i = 0; i < descriptors.Length(); ++i) {
- if (descriptors.DescriptorKind(i) == PcDescriptors::kFuncCall) {
+ if (descriptors.DescriptorKind(i) == PcDescriptors::kUnoptStaticCall) {
stackmap_table_builder->AddEntry(descriptors.PC(i) - code.EntryPoint(),
stack_bitmap,
0);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 6eec38d..91ed8eb 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -38,7 +38,7 @@
"Trace IC miss in optimized code");
DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
-DEFINE_FLAG(int, optimization_counter_threshold, 3000,
+DEFINE_FLAG(int, optimization_counter_threshold, 15000,
"Function's usage-counter value before it is optimized, -1 means never");
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, trace_type_checks);
@@ -729,8 +729,8 @@
}
-// Patches static call with the target's entry point. Compiles target if
-// necessary.
+// Patches static call in optimized code with the target's entry point.
+// Compiles target if necessary.
DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) {
ASSERT(arguments.ArgCount() == kPatchStaticCallRuntimeEntry.argument_count());
DartFrameIterator iterator;
@@ -738,6 +738,7 @@
ASSERT(caller_frame != NULL);
const Code& caller_code = Code::Handle(caller_frame->LookupDartCode());
ASSERT(!caller_code.IsNull());
+ ASSERT(caller_code.is_optimized());
const Function& target_function = Function::Handle(
caller_code.GetStaticCallTargetFunctionAt(caller_frame->pc()));
if (!target_function.HasCode()) {
@@ -768,11 +769,10 @@
// Resolves and compiles the target function of an instance call, updates
// function cache of the receiver's class and returns the compiled code or null.
// Only the number of named arguments is checked, but not the actual names.
-RawCode* ResolveCompileInstanceCallTarget(
- const Instance& receiver,
- const ICData& ic_data,
- const Array& arguments_descriptor_array) {
- ArgumentsDescriptor arguments_descriptor(arguments_descriptor_array);
+RawCode* ResolveCompileInstanceCallTarget(const Instance& receiver,
+ const ICData& ic_data) {
+ ArgumentsDescriptor
+ arguments_descriptor(Array::Handle(ic_data.arguments_descriptor()));
intptr_t num_arguments = arguments_descriptor.Count();
int num_named_arguments = arguments_descriptor.NamedCount();
String& function_name = String::Handle(ic_data.target_name());
@@ -836,8 +836,10 @@
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame != NULL);
const Code& code = Code::Handle(caller_frame->LookupDartCode());
+ ASSERT(!code.is_optimized());
const Function& function =
- Function::Handle(code.GetStaticCallTargetFunctionAt(caller_frame->pc()));
+ Function::Handle(CodePatcher::GetUnoptimizedStaticCallAt(
+ caller_frame->pc(), code, NULL));
if (!function.HasCode()) {
const Error& error = Error::Handle(Compiler::CompileFunction(function));
@@ -871,18 +873,17 @@
static RawFunction* InlineCacheMissHandler(
const GrowableArray<const Instance*>& args,
const ICData& ic_data,
- const Array& arg_descriptor_array) {
+ const Array& args_descriptor_array) {
const Instance& receiver = *args[0];
const Code& target_code =
- Code::Handle(ResolveCompileInstanceCallTarget(receiver,
- ic_data,
- arg_descriptor_array));
+ Code::Handle(ResolveCompileInstanceCallTarget(receiver, ic_data));
if (target_code.IsNull()) {
// Let the megamorphic stub handle special cases: NoSuchMethod,
// closure calls.
if (FLAG_trace_ic) {
- OS::PrintErr("InlineCacheMissHandler NULL code for receiver: %s\n",
- receiver.ToCString());
+ OS::PrintErr("InlineCacheMissHandler NULL code for %s receiver: %s\n",
+ String::Handle(ic_data.target_name()).ToCString(),
+ receiver.ToCString());
}
return Function::null();
}
@@ -1157,7 +1158,9 @@
getter_name,
kNumArguments,
kNumNamedArguments));
- if (getter.IsNull() || getter.IsMethodExtractor()) {
+ if (getter.IsNull() ||
+ getter.IsMethodExtractor() ||
+ getter.IsNoSuchMethodDispatcher()) {
return false;
}
@@ -1182,6 +1185,41 @@
}
+// Create a method for noSuchMethod invocation and attach it to the receiver
+// class.
+static RawFunction* CreateNoSuchMethodDispatcher(
+ const String& target_name,
+ const Class& receiver_class,
+ const Array& arguments_descriptor) {
+ Function& invocation = Function::Handle(
+ Function::New(String::Handle(Symbols::New(target_name)),
+ RawFunction::kNoSuchMethodDispatcher,
+ false, // Not static.
+ false, // Not const.
+ false, // Not abstract.
+ false, // Not external.
+ receiver_class,
+ 0)); // No token position.
+
+ // Initialize signature: receiver is a single fixed parameter.
+ const intptr_t kNumParameters = 1;
+ invocation.set_num_fixed_parameters(kNumParameters);
+ invocation.SetNumOptionalParameters(0, 0);
+ invocation.set_parameter_types(Array::Handle(Array::New(kNumParameters,
+ Heap::kOld)));
+ invocation.set_parameter_names(Array::Handle(Array::New(kNumParameters,
+ Heap::kOld)));
+ invocation.SetParameterTypeAt(0, Type::Handle(Type::DynamicType()));
+ invocation.SetParameterNameAt(0, Symbols::This());
+ invocation.set_result_type(Type::Handle(Type::DynamicType()));
+ invocation.set_is_visible(false); // Not visible in stack trace.
+
+ receiver_class.AddFunction(invocation);
+
+ return invocation.raw();
+}
+
+
// The IC miss handler has failed to find a (cacheable) instance function to
// invoke. Handle three possibilities:
//
@@ -1216,16 +1254,78 @@
args_descriptor,
args,
&result)) {
- result = DartEntry::InvokeNoSuchMethod(receiver,
- target_name,
- args,
- args_descriptor);
+ ArgumentsDescriptor desc(args_descriptor);
+ Function& target_function = Function::Handle(
+ Resolver::ResolveDynamicAnyArgs(receiver_class, target_name));
+ // Check number of arguments and check that there is not already a method
+ // with the same name present.
+ // TODO(fschneider): Handle multiple arguments.
+ if (target_function.IsNull() &&
+ (desc.Count() == 1) && (desc.PositionalCount() == 1)) {
+ // Create Function for noSuchMethodInvocation and add it to the class.
+ target_function ^= CreateNoSuchMethodDispatcher(target_name,
+ receiver_class,
+ args_descriptor);
+
+ // Update IC data.
+ ASSERT(!target_function.IsNull());
+ ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
+ if (FLAG_trace_ic) {
+ OS::PrintErr("NoSuchMethod IC miss: adding <%s> id:%"Pd" -> <%s>\n",
+ Class::Handle(receiver.clazz()).ToCString(),
+ receiver.GetClassId(),
+ target_function.ToCString());
+ }
+ result =
+ DartEntry::InvokeFunction(target_function, args, args_descriptor);
+ } else {
+ result = DartEntry::InvokeNoSuchMethod(receiver,
+ target_name,
+ args,
+ args_descriptor);
+ }
}
CheckResultError(result);
arguments.SetReturn(result);
}
+static bool CanOptimizeFunction(const Function& function, Isolate* isolate) {
+ const intptr_t kLowInvocationCount = -100000000;
+ if (isolate->debugger()->HasBreakpoint(function)) {
+ // We cannot set breakpoints in optimized code, so do not optimize
+ // the function.
+ function.set_usage_counter(0);
+ return false;
+ }
+ if (function.deoptimization_counter() >=
+ FLAG_deoptimization_counter_threshold) {
+ if (FLAG_trace_failed_optimization_attempts) {
+ OS::PrintErr("Too Many Deoptimizations: %s\n",
+ function.ToFullyQualifiedCString());
+ }
+ // TODO(srdjan): Investigate excessive deoptimization.
+ function.set_usage_counter(kLowInvocationCount);
+ return false;
+ }
+ if ((FLAG_optimization_filter != NULL) &&
+ (strstr(function.ToFullyQualifiedCString(),
+ FLAG_optimization_filter) == NULL)) {
+ function.set_usage_counter(kLowInvocationCount);
+ return false;
+ }
+ if (!function.is_optimizable()) {
+ if (FLAG_trace_failed_optimization_attempts) {
+ OS::PrintErr("Not Optimizable: %s\n", function.ToFullyQualifiedCString());
+ }
+ // TODO(5442338): Abort as this should not happen.
+ function.set_usage_counter(kLowInvocationCount);
+ return false;
+ }
+ return true;
+}
+
+
DEFINE_RUNTIME_ENTRY(StackOverflow, 0) {
ASSERT(arguments.ArgCount() ==
kStackOverflowRuntimeEntry.argument_count());
@@ -1278,13 +1378,14 @@
StackFrame* frame = iterator.NextFrame();
const Function& function = Function::Handle(frame->LookupDartFunction());
ASSERT(!function.IsNull());
- if (!function.is_optimizable()) return;
+ if (!CanOptimizeFunction(function, isolate)) return;
intptr_t osr_id =
Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc());
if (FLAG_trace_osr) {
- OS::Print("Attempting OSR for %s at id=%"Pd"\n",
+ OS::Print("Attempting OSR for %s at id=%"Pd", count=%"Pd"\n",
function.ToFullyQualifiedCString(),
- osr_id);
+ osr_id,
+ function.usage_counter());
}
const Code& original_code = Code::Handle(function.CurrentCode());
@@ -1332,35 +1433,10 @@
DEFINE_RUNTIME_ENTRY(OptimizeInvokedFunction, 1) {
ASSERT(arguments.ArgCount() ==
kOptimizeInvokedFunctionRuntimeEntry.argument_count());
- const intptr_t kLowInvocationCount = -100000000;
const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
ASSERT(!function.IsNull());
- if (isolate->debugger()->HasBreakpoint(function)) {
- // We cannot set breakpoints in optimized code, so do not optimize
- // the function.
- function.set_usage_counter(0);
- arguments.SetReturn(Code::Handle(function.CurrentCode()));
- return;
- }
- if (function.deoptimization_counter() >=
- FLAG_deoptimization_counter_threshold) {
- if (FLAG_trace_failed_optimization_attempts) {
- OS::PrintErr("Too Many Deoptimizations: %s\n",
- function.ToFullyQualifiedCString());
- }
- // TODO(srdjan): Investigate excessive deoptimization.
- function.set_usage_counter(kLowInvocationCount);
- arguments.SetReturn(Code::Handle(function.CurrentCode()));
- return;
- }
- if ((FLAG_optimization_filter != NULL) &&
- (strstr(function.ToFullyQualifiedCString(),
- FLAG_optimization_filter) == NULL)) {
- function.set_usage_counter(kLowInvocationCount);
- arguments.SetReturn(Code::Handle(function.CurrentCode()));
- return;
- }
- if (function.is_optimizable()) {
+
+ if (CanOptimizeFunction(function, isolate)) {
const Error& error =
Error::Handle(Compiler::CompileOptimizedFunction(function));
if (!error.IsNull()) {
@@ -1370,12 +1446,6 @@
ASSERT(!optimized_code.IsNull());
// Reset usage counter for reoptimization.
function.set_usage_counter(0);
- } else {
- if (FLAG_trace_failed_optimization_attempts) {
- OS::PrintErr("Not Optimizable: %s\n", function.ToFullyQualifiedCString());
- }
- // TODO(5442338): Abort as this should not happen.
- function.set_usage_counter(kLowInvocationCount);
}
arguments.SetReturn(Code::Handle(function.CurrentCode()));
}
@@ -1400,6 +1470,7 @@
}
ASSERT(frame->IsDartFrame());
const Code& caller_code = Code::Handle(frame->LookupDartCode());
+ ASSERT(caller_code.is_optimized());
const Function& target_function = Function::Handle(
caller_code.GetStaticCallTargetFunctionAt(frame->pc()));
const Code& target_code = Code::Handle(target_function.CurrentCode());
diff --git a/runtime/vm/code_generator.h b/runtime/vm/code_generator.h
index 9cfbbf7..95b08cf 100644
--- a/runtime/vm/code_generator.h
+++ b/runtime/vm/code_generator.h
@@ -90,10 +90,8 @@
const char* DeoptReasonToText(intptr_t deopt_id);
-RawCode* ResolveCompileInstanceCallTarget(
- const Instance& receiver,
- const ICData& ic_data,
- const Array& arguments_descriptor);
+RawCode* ResolveCompileInstanceCallTarget(const Instance& receiver,
+ const ICData& ic_data);
void DeoptimizeAt(const Code& optimized_code, uword pc);
void DeoptimizeAll();
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index 70d26fd..fea3ba4 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -17,6 +17,7 @@
class Function;
class ICData;
class RawArray;
+class RawFunction;
class RawICData;
class String;
@@ -53,8 +54,13 @@
// non-NULL.
static uword GetInstanceCallAt(uword return_address,
const Code& code,
- ICData* ic_data,
- Array* arguments_descriptor);
+ ICData* ic_data);
+
+ // Return target of an unoptimized static call and its ICData object
+ // (calls target via a stub).
+ static RawFunction* GetUnoptimizedStaticCallAt(uword return_address,
+ const Code& code,
+ ICData* ic_data);
// Return the arguments descriptor array of the closure call
// before the given return address.
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc
index 0dbb42c..105d3a1 100644
--- a/runtime/vm/code_patcher_arm.cc
+++ b/runtime/vm/code_patcher_arm.cc
@@ -16,7 +16,7 @@
const Code& code) {
ASSERT(code.ContainsInstructionAt(return_address));
CallPattern call(return_address, code);
- return call.ArgumentsDescriptor();
+ return call.ClosureArgumentsDescriptor();
}
@@ -55,16 +55,12 @@
uword CodePatcher::GetInstanceCallAt(uword return_address,
const Code& code,
- ICData* ic_data,
- Array* arguments_descriptor) {
+ ICData* ic_data) {
ASSERT(code.ContainsInstructionAt(return_address));
CallPattern call(return_address, code);
if (ic_data != NULL) {
*ic_data = call.IcData();
}
- if (arguments_descriptor != NULL) {
- *arguments_descriptor = call.ArgumentsDescriptor();
- }
return call.TargetAddress();
}
@@ -75,6 +71,19 @@
return 0;
}
+
+RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
+ uword return_address, const Code& code, ICData* ic_data_result) {
+ ASSERT(code.ContainsInstructionAt(return_address));
+ CallPattern static_call(return_address, code);
+ ICData& ic_data = ICData::Handle();
+ ic_data ^= static_call.IcData();
+ if (ic_data_result != NULL) {
+ *ic_data_result = ic_data.raw();
+ }
+ return ic_data.GetTargetAt(0);
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index 6fbd1a3..a9bfc71 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -18,30 +18,6 @@
namespace dart {
-CODEGEN_TEST_GENERATE(NativePatchStaticCall, test) {
- SequenceNode* node_seq = test->node_sequence();
- const String& native_name =
- String::ZoneHandle(Symbols::New("TestStaticCallPatching"));
- NativeFunction native_function =
- reinterpret_cast<NativeFunction>(TestStaticCallPatching);
- test->function().set_is_native(true);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new NativeBodyNode(Scanner::kDummyTokenIndex,
- test->function(),
- native_name,
- native_function)));
-}
-
-CODEGEN_TEST2_GENERATE(PatchStaticCall, function, test) {
- SequenceNode* node_seq = test->node_sequence();
- ArgumentListNode* arguments = new ArgumentListNode(Scanner::kDummyTokenIndex);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new StaticCallNode(Scanner::kDummyTokenIndex,
- function, arguments)));
-}
-
-CODEGEN_TEST2_RUN(PatchStaticCall, NativePatchStaticCall, Instance::null());
-
#define __ assembler->
ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
@@ -49,19 +25,20 @@
const Script& script = Script::Handle();
const Class& owner_class =
Class::Handle(Class::New(class_name, script, Scanner::kDummyTokenIndex));
- const String& function_name =
- String::ZoneHandle(Symbols::New("callerFunction"));
- const Function& function = Function::ZoneHandle(
+ const String& function_name = String::Handle(Symbols::New("callerFunction"));
+ const Function& function = Function::Handle(
Function::New(function_name, RawFunction::kRegularFunction,
true, false, false, false, owner_class, 0));
const String& target_name = String::Handle(String::New("targetFunction"));
- const ICData& ic_data =
- ICData::ZoneHandle(ICData::New(function, target_name, 15, 1));
- const Array& arg_descriptor =
- Array::ZoneHandle(ArgumentsDescriptor::New(1, Array::Handle()));
+ const Array& args_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
+ const ICData& ic_data = ICData::ZoneHandle(ICData::New(function,
+ target_name,
+ args_descriptor,
+ 15,
+ 1));
- __ LoadObject(R4, arg_descriptor);
__ LoadObject(R5, ic_data);
ExternalLabel target_label(
"InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint());
@@ -74,7 +51,7 @@
uword return_address =
test->entry() + test->code().Size() - Instr::kInstrSize;
ICData& ic_data = ICData::Handle();
- CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data, NULL);
+ CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
EXPECT_STREQ("targetFunction",
String::Handle(ic_data.target_name()).ToCString());
EXPECT_EQ(1, ic_data.num_args_tested());
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc
index 45ddb0b..d68c938 100644
--- a/runtime/vm/code_patcher_ia32.cc
+++ b/runtime/vm/code_patcher_ia32.cc
@@ -15,14 +15,13 @@
namespace dart {
-// The pattern of a Dart instance call is:
-// 1: mov ECX, immediate 1
-// 2: mov EDX, immediate 2
-// 3: call target_address
-// <- return_address
-class DartCallPattern : public ValueObject {
+// The expected pattern of a Dart unoptimized call (static and instance):
+// mov ECX, ic-data
+// call target_address (stub)
+// <- return address
+class UnoptimizedCall : public ValueObject {
public:
- explicit DartCallPattern(uword return_address)
+ explicit UnoptimizedCall(uword return_address)
: start_(return_address - (kNumInstructions * kInstructionSize)) {
ASSERT(IsValid(return_address));
ASSERT(kInstructionSize == Assembler::kCallExternalLabelSize);
@@ -33,8 +32,7 @@
reinterpret_cast<uint8_t*>(
return_address - (kNumInstructions * kInstructionSize));
return (code_bytes[0] == 0xB9) &&
- (code_bytes[kInstructionSize] == 0xBA) &&
- (code_bytes[2 * kInstructionSize] == 0xE8);
+ (code_bytes[1 * kInstructionSize] == 0xE8);
}
uword target() const {
@@ -49,15 +47,11 @@
CPU::FlushICache(call_address(), kInstructionSize);
}
- RawObject* immediate_one() const {
+ RawObject* ic_data() const {
return *reinterpret_cast<RawObject**>(start_ + 1);
}
- RawObject* immediate_two() const {
- return *reinterpret_cast<RawObject**>(start_ + kInstructionSize + 1);
- }
-
- static const int kNumInstructions = 3;
+ static const int kNumInstructions = 2;
static const int kInstructionSize = 5; // All instructions have same length.
private:
@@ -66,32 +60,46 @@
}
uword call_address() const {
- return start_ + 2 * kInstructionSize;
+ return start_ + 1 * kInstructionSize;
}
uword start_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
};
-// The expected pattern of a dart instance call:
-// mov ECX, ic-data
-// mov EDX, arguments_descriptor_array
-// call target_address
-// <- return address
-class InstanceCall : public DartCallPattern {
+class InstanceCall : public UnoptimizedCall {
public:
explicit InstanceCall(uword return_address)
- : DartCallPattern(return_address) {}
-
- RawObject* ic_data() const { return immediate_one(); }
- RawObject* arguments_descriptor() const { return immediate_two(); }
+ : UnoptimizedCall(return_address) {
+#if defined(DEBUG)
+ ICData& test_ic_data = ICData::Handle();
+ test_ic_data ^= ic_data();
+ ASSERT(test_ic_data.num_args_tested() > 0);
+#endif // DEBUG
+ }
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
};
+class UnoptimizedStaticCall : public UnoptimizedCall {
+ public:
+ explicit UnoptimizedStaticCall(uword return_address)
+ : UnoptimizedCall(return_address) {
+#if defined(DEBUG)
+ ICData& test_ic_data = ICData::Handle();
+ test_ic_data ^= ic_data();
+ ASSERT(test_ic_data.num_args_tested() == 0);
+#endif // DEBUG
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
+};
+
+
// The expected pattern of a dart static call:
// mov EDX, arguments_descriptor_array (optional in polymorphic calls)
// call target_address
@@ -223,24 +231,32 @@
}
-uword CodePatcher::GetInstanceCallAt(uword return_address,
- const Code& code,
- ICData* ic_data,
- Array* arguments_descriptor) {
+uword CodePatcher::GetInstanceCallAt(
+ uword return_address, const Code& code, ICData* ic_data) {
ASSERT(code.ContainsInstructionAt(return_address));
InstanceCall call(return_address);
if (ic_data != NULL) {
*ic_data ^= call.ic_data();
}
- if (arguments_descriptor != NULL) {
- *arguments_descriptor ^= call.arguments_descriptor();
- }
return call.target();
}
+RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
+ uword return_address, const Code& code, ICData* ic_data_result) {
+ ASSERT(code.ContainsInstructionAt(return_address));
+ UnoptimizedStaticCall static_call(return_address);
+ ICData& ic_data = ICData::Handle();
+ ic_data ^= static_call.ic_data();
+ if (ic_data_result != NULL) {
+ *ic_data_result = ic_data.raw();
+ }
+ return ic_data.GetTargetAt(0);
+}
+
+
intptr_t CodePatcher::InstanceCallSizeInBytes() {
- return DartCallPattern::kNumInstructions * DartCallPattern::kInstructionSize;
+ return InstanceCall::kNumInstructions * InstanceCall::kInstructionSize;
}
} // namespace dart
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index 2bb6601..bb893d4 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -18,30 +18,6 @@
namespace dart {
-CODEGEN_TEST_GENERATE(NativePatchStaticCall, test) {
- SequenceNode* node_seq = test->node_sequence();
- const String& native_name =
- String::ZoneHandle(Symbols::New("TestStaticCallPatching"));
- NativeFunction native_function =
- reinterpret_cast<NativeFunction>(TestStaticCallPatching);
- test->function().set_is_native(true);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new NativeBodyNode(Scanner::kDummyTokenIndex,
- test->function(),
- native_name,
- native_function)));
-}
-
-CODEGEN_TEST2_GENERATE(PatchStaticCall, function, test) {
- SequenceNode* node_seq = test->node_sequence();
- ArgumentListNode* arguments = new ArgumentListNode(Scanner::kDummyTokenIndex);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new StaticCallNode(Scanner::kDummyTokenIndex,
- function, arguments)));
-}
-
-CODEGEN_TEST2_RUN(PatchStaticCall, NativePatchStaticCall, Instance::null());
-
#define __ assembler->
ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
@@ -49,20 +25,21 @@
const Script& script = Script::Handle();
const Class& owner_class =
Class::Handle(Class::New(class_name, script, Scanner::kDummyTokenIndex));
- const String& function_name =
- String::ZoneHandle(Symbols::New("callerFunction"));
- const Function& function = Function::ZoneHandle(
+ const String& function_name = String::Handle(Symbols::New("callerFunction"));
+ const Function& function = Function::Handle(
Function::New(function_name, RawFunction::kRegularFunction,
true, false, false, false, owner_class, 0));
const String& target_name = String::Handle(String::New("targetFunction"));
- const ICData& ic_data =
- ICData::ZoneHandle(ICData::New(function, target_name, 15, 1));
- const Array& arg_descriptor =
- Array::ZoneHandle(ArgumentsDescriptor::New(1, Array::Handle()));
+ const Array& args_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
+ const ICData& ic_data = ICData::ZoneHandle(ICData::New(function,
+ target_name,
+ args_descriptor,
+ 15,
+ 1));
__ LoadObject(ECX, ic_data);
- __ LoadObject(EDX, arg_descriptor);
ExternalLabel target_label(
"InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint());
__ call(&target_label);
@@ -73,7 +50,7 @@
ASSEMBLER_TEST_RUN(IcDataAccess, test) {
uword return_address = test->entry() + CodePatcher::InstanceCallSizeInBytes();
ICData& ic_data = ICData::Handle();
- CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data, NULL);
+ CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
EXPECT_STREQ("targetFunction",
String::Handle(ic_data.target_name()).ToCString());
EXPECT_EQ(1, ic_data.num_args_tested());
diff --git a/runtime/vm/code_patcher_mips.cc b/runtime/vm/code_patcher_mips.cc
index 5cd9108..f25b460 100644
--- a/runtime/vm/code_patcher_mips.cc
+++ b/runtime/vm/code_patcher_mips.cc
@@ -16,7 +16,7 @@
const Code& code) {
ASSERT(code.ContainsInstructionAt(return_address));
CallPattern call(return_address, code);
- return call.ArgumentsDescriptor();
+ return call.ClosureArgumentsDescriptor();
}
@@ -55,16 +55,12 @@
uword CodePatcher::GetInstanceCallAt(uword return_address,
const Code& code,
- ICData* ic_data,
- Array* arguments_descriptor) {
+ ICData* ic_data) {
ASSERT(code.ContainsInstructionAt(return_address));
CallPattern call(return_address, code);
if (ic_data != NULL) {
*ic_data = call.IcData();
}
- if (arguments_descriptor != NULL) {
- *arguments_descriptor = call.ArgumentsDescriptor();
- }
return call.TargetAddress();
}
@@ -75,6 +71,19 @@
return 0;
}
+
+RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
+ uword return_address, const Code& code, ICData* ic_data_result) {
+ ASSERT(code.ContainsInstructionAt(return_address));
+ CallPattern static_call(return_address, code);
+ ICData& ic_data = ICData::Handle();
+ ic_data ^= static_call.IcData();
+ if (ic_data_result != NULL) {
+ *ic_data_result = ic_data.raw();
+ }
+ return ic_data.GetTargetAt(0);
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/code_patcher_mips_test.cc b/runtime/vm/code_patcher_mips_test.cc
index 9d0a681..c5b51b5 100644
--- a/runtime/vm/code_patcher_mips_test.cc
+++ b/runtime/vm/code_patcher_mips_test.cc
@@ -18,30 +18,6 @@
namespace dart {
-CODEGEN_TEST_GENERATE(NativePatchStaticCall, test) {
- SequenceNode* node_seq = test->node_sequence();
- const String& native_name =
- String::ZoneHandle(Symbols::New("TestStaticCallPatching"));
- NativeFunction native_function =
- reinterpret_cast<NativeFunction>(TestStaticCallPatching);
- test->function().set_is_native(true);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new NativeBodyNode(Scanner::kDummyTokenIndex,
- test->function(),
- native_name,
- native_function)));
-}
-
-CODEGEN_TEST2_GENERATE(PatchStaticCall, function, test) {
- SequenceNode* node_seq = test->node_sequence();
- ArgumentListNode* arguments = new ArgumentListNode(Scanner::kDummyTokenIndex);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new StaticCallNode(Scanner::kDummyTokenIndex,
- function, arguments)));
-}
-
-CODEGEN_TEST2_RUN(PatchStaticCall, NativePatchStaticCall, Instance::null());
-
#define __ assembler->
ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
@@ -49,19 +25,20 @@
const Script& script = Script::Handle();
const Class& owner_class =
Class::Handle(Class::New(class_name, script, Scanner::kDummyTokenIndex));
- const String& function_name =
- String::ZoneHandle(Symbols::New("callerFunction"));
- const Function& function = Function::ZoneHandle(
+ const String& function_name = String::Handle(Symbols::New("callerFunction"));
+ const Function& function = Function::Handle(
Function::New(function_name, RawFunction::kRegularFunction,
true, false, false, false, owner_class, 0));
const String& target_name = String::Handle(String::New("targetFunction"));
- const ICData& ic_data =
- ICData::ZoneHandle(ICData::New(function, target_name, 15, 1));
- const Array& arg_descriptor =
- Array::ZoneHandle(ArgumentsDescriptor::New(1, Array::Handle()));
+ const Array& args_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
+ const ICData& ic_data = ICData::ZoneHandle(ICData::New(function,
+ target_name,
+ args_descriptor,
+ 15,
+ 1));
- __ LoadObject(S4, arg_descriptor);
__ LoadObject(S5, ic_data);
ExternalLabel target_label(
"InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint());
@@ -74,7 +51,7 @@
uword return_address =
test->entry() + test->code().Size() - 2 * Instr::kInstrSize;
ICData& ic_data = ICData::Handle();
- CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data, NULL);
+ CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
EXPECT_STREQ("targetFunction",
String::Handle(ic_data.target_name()).ToCString());
EXPECT_EQ(1, ic_data.num_args_tested());
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc
index 82652d0..ec9e56f 100644
--- a/runtime/vm/code_patcher_x64.cc
+++ b/runtime/vm/code_patcher_x64.cc
@@ -15,76 +15,82 @@
namespace dart {
-// The pattern of a Dart instance call is:
-// 00: 48 bb imm64 mov RBX, immediate 1
-// 10: 49 ba imm64 mov R10, immediate 2
-// 20: 49 bb imm64 mov R11, target_address
-// 30: 41 ff d3 call R11
-// 33: <- return_address
-class DartCallPattern : public ValueObject {
+// The expected pattern of a Dart unoptimized call (static and instance):
+// 00: 48 bb imm64 mov RBX, ic-data
+// 10: 49 bb imm64 mov R11, target_address
+// 20: 41 ff d3 call R11
+// 23 <- return address
+class UnoptimizedCall : public ValueObject {
public:
- explicit DartCallPattern(uword return_address)
+ explicit UnoptimizedCall(uword return_address)
: start_(return_address - kCallPatternSize) {
ASSERT(IsValid(return_address));
- ASSERT((kCallPatternSize - 20) == Assembler::kCallExternalLabelSize);
+ ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize);
}
- static const int kCallPatternSize = 33;
+ static const int kCallPatternSize = 23;
static bool IsValid(uword return_address) {
uint8_t* code_bytes =
reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
return (code_bytes[00] == 0x48) && (code_bytes[01] == 0xBB) &&
- (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBA) &&
- (code_bytes[20] == 0x49) && (code_bytes[21] == 0xBB) &&
- (code_bytes[30] == 0x41) && (code_bytes[31] == 0xFF) &&
- (code_bytes[32] == 0xD3);
+ (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) &&
+ (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) &&
+ (code_bytes[22] == 0xD3);
}
- uword target() const {
- return *reinterpret_cast<uword*>(start_ + 20 + 2);
- }
-
- void set_target(uword target) const {
- uword* target_addr = reinterpret_cast<uword*>(start_ + 20 + 2);
- *target_addr = target;
- CPU::FlushICache(start_ + 20, 2 + 8);
- }
-
- RawObject* immediate_one() const {
+ RawObject* ic_data() const {
return *reinterpret_cast<RawObject**>(start_ + 0 + 2);
}
- RawObject* immediate_two() const {
- return *reinterpret_cast<RawObject**>(start_ + 10 + 2);
+ uword target() const {
+ return *reinterpret_cast<uword*>(start_ + 10 + 2);
+ }
+
+ void set_target(uword target) const {
+ uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2);
+ *target_addr = target;
+ CPU::FlushICache(start_ + 10, 2 + 8);
}
private:
uword start_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
};
-// A Dart instance call passes the ic-data in RBX.
-// The expected pattern of a dart instance call:
-// mov RBX, ic-data
-// mov R10, arguments_descriptor_array
-// mov R11, target_address
-// call R11
-// <- return address
-class InstanceCall : public DartCallPattern {
+class InstanceCall : public UnoptimizedCall {
public:
explicit InstanceCall(uword return_address)
- : DartCallPattern(return_address) {}
-
- RawObject* ic_data() const { return immediate_one(); }
- RawObject* arguments_descriptor() const { return immediate_two(); }
+ : UnoptimizedCall(return_address) {
+#if defined(DEBUG)
+ ICData& test_ic_data = ICData::Handle();
+ test_ic_data ^= ic_data();
+ ASSERT(test_ic_data.num_args_tested() > 0);
+#endif // DEBUG
+ }
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
};
+class UnoptimizedStaticCall : public UnoptimizedCall {
+ public:
+ explicit UnoptimizedStaticCall(uword return_address)
+ : UnoptimizedCall(return_address) {
+#if defined(DEBUG)
+ ICData& test_ic_data = ICData::Handle();
+ test_ic_data ^= ic_data();
+ ASSERT(test_ic_data.num_args_tested() == 0);
+#endif // DEBUG
+ }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
+};
+
+
// The expected pattern of a dart static call:
// mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
// mov R11, target_address (10 bytes)
@@ -193,22 +199,18 @@
uword CodePatcher::GetInstanceCallAt(uword return_address,
const Code& code,
- ICData* ic_data,
- Array* arguments_descriptor) {
+ ICData* ic_data) {
ASSERT(code.ContainsInstructionAt(return_address));
InstanceCall call(return_address);
if (ic_data != NULL) {
*ic_data ^= call.ic_data();
}
- if (arguments_descriptor != NULL) {
- *arguments_descriptor ^= call.arguments_descriptor();
- }
return call.target();
}
intptr_t CodePatcher::InstanceCallSizeInBytes() {
- return DartCallPattern::kCallPatternSize;
+ return InstanceCall::kCallPatternSize;
}
@@ -222,6 +224,18 @@
}
+RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
+ uword return_address, const Code& code, ICData* ic_data_result) {
+ ASSERT(code.ContainsInstructionAt(return_address));
+ UnoptimizedStaticCall static_call(return_address);
+ ICData& ic_data = ICData::Handle();
+ ic_data ^= static_call.ic_data();
+ if (ic_data_result != NULL) {
+ *ic_data_result = ic_data.raw();
+ }
+ return ic_data.GetTargetAt(0);
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_X64
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index 61807b3..202c27a 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -18,30 +18,6 @@
namespace dart {
-CODEGEN_TEST_GENERATE(NativePatchStaticCall, test) {
- SequenceNode* node_seq = test->node_sequence();
- const String& native_name =
- String::ZoneHandle(Symbols::New("TestStaticCallPatching"));
- NativeFunction native_function =
- reinterpret_cast<NativeFunction>(TestStaticCallPatching);
- test->function().set_is_native(true);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new NativeBodyNode(Scanner::kDummyTokenIndex,
- test->function(),
- native_name,
- native_function)));
-}
-
-CODEGEN_TEST2_GENERATE(PatchStaticCall, function, test) {
- SequenceNode* node_seq = test->node_sequence();
- ArgumentListNode* arguments = new ArgumentListNode(Scanner::kDummyTokenIndex);
- node_seq->Add(new ReturnNode(Scanner::kDummyTokenIndex,
- new StaticCallNode(Scanner::kDummyTokenIndex,
- function, arguments)));
-}
-
-CODEGEN_TEST2_RUN(PatchStaticCall, NativePatchStaticCall, Instance::null());
-
#define __ assembler->
ASSEMBLER_TEST_GENERATE(IcDataAccess, assembler) {
@@ -49,20 +25,21 @@
const Script& script = Script::Handle();
const Class& owner_class =
Class::Handle(Class::New(class_name, script, Scanner::kDummyTokenIndex));
- const String& function_name =
- String::ZoneHandle(Symbols::New("callerFunction"));
- const Function& function = Function::ZoneHandle(
+ const String& function_name = String::Handle(Symbols::New("callerFunction"));
+ const Function& function = Function::Handle(
Function::New(function_name, RawFunction::kRegularFunction,
true, false, false, false, owner_class, 0));
const String& target_name = String::Handle(String::New("targetFunction"));
- const ICData& ic_data =
- ICData::ZoneHandle(ICData::New(function, target_name, 15, 1));
- const Array& arg_descriptor =
- Array::ZoneHandle(ArgumentsDescriptor::New(1, Array::Handle()));
+ const Array& args_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
+ const ICData& ic_data = ICData::ZoneHandle(ICData::New(function,
+ target_name,
+ args_descriptor,
+ 15,
+ 1));
__ LoadObject(RBX, ic_data);
- __ LoadObject(R10, arg_descriptor);
ExternalLabel target_label(
"InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint());
__ call(&target_label);
@@ -73,7 +50,7 @@
ASSEMBLER_TEST_RUN(IcDataAccess, test) {
uword return_address = test->entry() + CodePatcher::InstanceCallSizeInBytes();
ICData& ic_data = ICData::Handle();
- CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data, NULL);
+ CodePatcher::GetInstanceCallAt(return_address, test->code(), &ic_data);
EXPECT_STREQ("targetFunction",
String::Handle(ic_data.target_name()).ToCString());
EXPECT_EQ(1, ic_data.num_args_tested());
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 0fba07c..2faa434 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -268,14 +268,11 @@
ASSERT(function.HasCode());
// Extract type feedback before the graph is built, as the graph
// builder uses it to attach it to nodes.
- // Do not use type feedback to optimize a function that was
- // deoptimized too often.
- if (function.deoptimization_counter() <
- FLAG_deoptimization_counter_threshold) {
- const Code& unoptimized_code =
- Code::Handle(function.unoptimized_code());
- ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
- }
+ ASSERT(function.deoptimization_counter() <
+ FLAG_deoptimization_counter_threshold);
+ const Code& unoptimized_code =
+ Code::Handle(function.unoptimized_code());
+ ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
}
// Build the flow graph.
@@ -863,7 +860,7 @@
// here.
ParsedFunction* parsed_function = new ParsedFunction(func);
parsed_function->SetNodeSequence(fragment);
- parsed_function->set_default_parameter_values(Array::ZoneHandle());
+ parsed_function->set_default_parameter_values(Object::null_array());
parsed_function->EnsureExpressionTemp();
fragment->scope()->AddVariable(parsed_function->expression_temp_var());
parsed_function->AllocateVariables();
diff --git a/runtime/vm/constants_mips.h b/runtime/vm/constants_mips.h
index b1f910a..bb16ccd 100644
--- a/runtime/vm/constants_mips.h
+++ b/runtime/vm/constants_mips.h
@@ -135,23 +135,22 @@
// convert to the single precision registers when needed in the mips-specific
// code.
enum DRegister {
- D0 = 0,
- D1 = 1,
- D2 = 2,
- D3 = 3,
- D4 = 4,
- D5 = 5,
- D6 = 6,
- D7 = 7,
- D8 = 8,
- D9 = 9,
- D10 = 10,
- D11 = 11,
- D12 = 12,
- D13 = 13,
- D14 = 14,
- D15 = 15,
- D16 = 16,
+ D0 = 0, // Function return value 1.
+ D1 = 1, // Function return value 2.
+ D2 = 2, // Not preserved.
+ D3 = 3, // Not preserved.
+ D4 = 4, // Not preserved.
+ D5 = 5, // Not preserved.
+ D6 = 6, // Argument 1.
+ D7 = 7, // Argument 2.
+ D8 = 8, // Not preserved.
+ D9 = 9, // Not preserved.
+ D10 = 10, // Preserved.
+ D11 = 11, // Preserved.
+ D12 = 12, // Preserved.
+ D13 = 13, // Preserved.
+ D14 = 14, // Preserved.
+ D15 = 15, // Preserved.
kNumberOfDRegisters = 16,
kNoDRegister = -1,
};
@@ -409,6 +408,7 @@
COP1_DIV = 0x03,
COP1_SQRT = 0x04,
COP1_MOV = 0x06,
+ COP1_CVT_S = 0x20,
COP1_CVT_D = 0x21,
COP1_CVT_W = 0x24,
COP1_C_F = 0x30,
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index b68c88a..300e5b3 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -193,6 +193,11 @@
Object::VerifyBuiltinVtables();
StubCode::Init(isolate);
+ if (snapshot_buffer == NULL) {
+ if (!isolate->object_store()->PreallocateObjects()) {
+ return isolate->object_store()->sticky_error();
+ }
+ }
isolate->megamorphic_cache_table()->InitMissHandler();
isolate->heap()->EnableGrowthControl();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 176407c..99e6cca 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -133,8 +133,11 @@
Dart_Handle Api::CheckIsolateState(Isolate* isolate) {
- if (ClassFinalizer::FinalizePendingClasses() &&
- isolate->object_store()->PreallocateObjects()) {
+ if (!isolate->AllowClassFinalization()) {
+ // Class finalization is blocked for the isolate. Do nothing.
+ return Api::Success();
+ }
+ if (ClassFinalizer::FinalizePendingClasses()) {
return Api::Success();
}
ASSERT(isolate->object_store()->sticky_error() != Object::null());
@@ -1136,16 +1139,25 @@
// Do we also need a real Dart_IsInstanceOf, which should take an instance
// rather than an object and a type rather than a class?
DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
- Dart_Handle clazz,
+ Dart_Handle type,
bool* value) {
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
- const Class& cls = Api::UnwrapClassHandle(isolate, clazz);
- if (cls.IsNull()) {
- RETURN_TYPE_ERROR(isolate, clazz, Class);
+ Type& type_obj = Type::Handle();
+ Object& obj = Object::Handle(isolate, Api::UnwrapHandle(type));
+ if (obj.IsNull()) {
+ RETURN_NULL_ERROR(type);
}
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+ if (obj.IsType()) {
+ type_obj ^= obj.raw();
+ } else {
+ if (!obj.IsClass()) {
+ RETURN_TYPE_ERROR(isolate, type, Type);
+ }
+ type_obj ^= Type::NewNonParameterizedType(Class::Cast(obj));
+ }
+ obj = Api::UnwrapHandle(object);
if (obj.IsError()) {
return object;
} else if (!obj.IsNull() && !obj.IsInstance()) {
@@ -1160,10 +1172,8 @@
}
if (obj.IsInstance()) {
CHECK_CALLBACK_STATE(isolate);
- const Type& type = Type::Handle(isolate,
- Type::NewNonParameterizedType(cls));
Error& malformed_type_error = Error::Handle(isolate);
- *value = Instance::Cast(obj).IsInstanceOf(type,
+ *value = Instance::Cast(obj).IsInstanceOf(type_obj,
TypeArguments::Handle(isolate),
&malformed_type_error);
ASSERT(malformed_type_error.IsNull()); // Type was created from a class.
@@ -1234,6 +1244,11 @@
}
+DART_EXPORT bool Dart_IsType(Dart_Handle handle) {
+ return Api::ClassId(handle) == kTypeCid;
+}
+
+
DART_EXPORT bool Dart_IsClass(Dart_Handle handle) {
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
@@ -1242,17 +1257,6 @@
}
-DART_EXPORT bool Dart_IsAbstractClass(Dart_Handle handle) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
- if (obj.IsClass()) {
- return Class::Cast(obj).is_abstract();
- }
- return false;
-}
-
-
DART_EXPORT bool Dart_IsFunction(Dart_Handle handle) {
return Api::ClassId(handle) == kFunctionCid;
}
@@ -1280,7 +1284,21 @@
// --- Instances ----
-// TODO(turnidge): Technically, null has a class. Should we allow it?
+DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(instance));
+ if (obj.IsNull()) {
+ return Api::NewHandle(isolate, isolate->object_store()->null_type());
+ }
+ if (!obj.IsInstance()) {
+ RETURN_TYPE_ERROR(isolate, instance, Instance);
+ }
+ const Type& type = Type::Handle(Instance::Cast(obj).GetType());
+ return Api::NewHandle(isolate, type.Canonicalize());
+}
+
+// TODO(asiva): Deprecate this method.
DART_EXPORT Dart_Handle Dart_InstanceGetClass(Dart_Handle instance) {
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
@@ -2707,7 +2725,7 @@
}
-DART_EXPORT Dart_Handle Dart_New(Dart_Handle clazz,
+DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
Dart_Handle constructor_name,
int number_of_arguments,
Dart_Handle* arguments) {
@@ -2723,10 +2741,20 @@
}
// Get the class to instantiate.
- Class& cls =
- Class::Handle(isolate, Api::UnwrapClassHandle(isolate, clazz).raw());
- if (cls.IsNull()) {
- RETURN_TYPE_ERROR(isolate, clazz, Class);
+ result = Api::UnwrapHandle(type);
+ if (result.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, type, Type);
+ }
+ Class& cls = Class::Handle(isolate);
+ if (result.IsType()) {
+ cls = Type::Cast(result).type_class();
+ } else if (result.IsClass()) {
+ // For backwards compatibility we allow class objects to be passed in
+ // for now. This needs to be removed once all code that uses class
+ // objects to invoke Dart_New is removed.
+ cls ^= result.raw();
+ } else {
+ RETURN_TYPE_ERROR(isolate, type, Type);
}
String& base_constructor_name = String::Handle();
@@ -2734,12 +2762,11 @@
// And get the name of the constructor to invoke.
String& dot_name = String::Handle(isolate);
- const Object& name_obj =
- Object::Handle(isolate, Api::UnwrapHandle(constructor_name));
- if (name_obj.IsNull()) {
+ result = Api::UnwrapHandle(constructor_name);
+ if (result.IsNull()) {
dot_name = Symbols::Dot().raw();
- } else if (name_obj.IsString()) {
- dot_name = String::Concat(Symbols::Dot(), String::Cast(name_obj));
+ } else if (result.IsString()) {
+ dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
} else {
RETURN_TYPE_ERROR(isolate, constructor_name, String);
}
@@ -2818,6 +2845,33 @@
}
+DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+ CHECK_CALLBACK_STATE(isolate);
+ const Object& result = Object::Handle(isolate, Api::UnwrapHandle(type));
+
+ // Get the class to instantiate.
+ if (result.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, type, Type);
+ }
+ Class& cls = Class::Handle(isolate);
+ if (result.IsType()) {
+ cls = Type::Cast(result).type_class();
+ } else if (result.IsClass()) {
+ // For backwards compatibility we allow class objects to be passed in
+ // for now. This needs to be removed once all code that uses class
+ // objects to invoke Dart_New is removed.
+ cls ^= result.raw();
+ } else {
+ RETURN_TYPE_ERROR(isolate, type, Type);
+ }
+
+ // Allocate an object for the given class.
+ return Api::NewHandle(isolate, Instance::New(cls));
+}
+
+
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target,
Dart_Handle name,
int number_of_arguments,
@@ -2841,7 +2895,8 @@
}
// Check for malformed arguments in the arguments list.
- intptr_t num_receiver = (obj.IsNull() || obj.IsInstance()) ? 1 : 0;
+ intptr_t num_receiver =
+ (obj.IsNull() || (obj.IsInstance() && !obj.IsType())) ? 1 : 0;
const Array& args =
Array::Handle(isolate, Array::New(number_of_arguments + num_receiver));
Object& arg = Object::Handle(isolate);
@@ -2859,7 +2914,39 @@
args.SetAt((i + num_receiver), arg);
}
- if (obj.IsNull() || obj.IsInstance()) {
+ if (obj.IsType() || obj.IsClass()) {
+ // Finalize all classes.
+ Dart_Handle state = Api::CheckIsolateState(isolate);
+ if (::Dart_IsError(state)) {
+ return state;
+ }
+
+ // For backwards compatibility we allow class objects to be passed in
+ // for now. This needs to be removed once all code that uses class
+ // objects to invoke Dart_Invoke is removed.
+ Class& cls = Class::Handle();
+ if (obj.IsType()) {
+ cls = Type::Cast(obj).type_class();
+ } else {
+ cls = Class::Cast(obj).raw();
+ }
+ const Function& function = Function::Handle(
+ isolate,
+ Resolver::ResolveStatic(cls,
+ function_name,
+ number_of_arguments,
+ Object::empty_array(),
+ Resolver::kIsQualified));
+ if (function.IsNull()) {
+ const String& cls_name = String::Handle(isolate, cls.Name());
+ return Api::NewError("%s: did not find static method '%s.%s'.",
+ CURRENT_FUNC,
+ cls_name.ToCString(),
+ function_name.ToCString());
+ }
+ return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
+
+ } else if (obj.IsNull() || obj.IsInstance()) {
Instance& instance = Instance::Handle(isolate);
instance ^= obj.raw();
const Function& function = Function::Handle(
@@ -2880,51 +2967,16 @@
}
return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
- } else if (obj.IsClass()) {
- // Finalize all classes.
+ } else if (obj.IsLibrary()) {
+ // Check whether class finalization is needed.
+ const Library& lib = Library::Cast(obj);
+
+ // Finalize all classes if needed.
Dart_Handle state = Api::CheckIsolateState(isolate);
if (::Dart_IsError(state)) {
return state;
}
- const Class& cls = Class::Cast(obj);
- const Function& function = Function::Handle(
- isolate,
- Resolver::ResolveStatic(cls,
- function_name,
- number_of_arguments,
- Object::empty_array(),
- Resolver::kIsQualified));
- if (function.IsNull()) {
- const String& cls_name = String::Handle(isolate, cls.Name());
- return Api::NewError("%s: did not find static method '%s.%s'.",
- CURRENT_FUNC,
- cls_name.ToCString(),
- function_name.ToCString());
- }
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(function, args));
-
- } else if (obj.IsLibrary()) {
- // Check whether class finalization is needed.
- bool finalize_classes = true;
- const Library& lib = Library::Cast(obj);
-
- // When calling functions in the dart:builtin library do not finalize as it
- // should have been prefinalized.
- Library& builtin =
- Library::Handle(isolate, isolate->object_store()->builtin_library());
- if (builtin.raw() == lib.raw()) {
- finalize_classes = false;
- }
-
- // Finalize all classes if needed.
- if (finalize_classes) {
- Dart_Handle state = Api::CheckIsolateState(isolate);
- if (::Dart_IsError(state)) {
- return state;
- }
- }
-
Function& function = Function::Handle(isolate);
function = lib.LookupFunctionAllowPrivate(function_name);
if (function.IsNull()) {
@@ -2947,7 +2999,7 @@
} else {
return Api::NewError(
- "%s expects argument 'target' to be an object, class, or library.",
+ "%s expects argument 'target' to be an object, type, or library.",
CURRENT_FUNC);
}
}
@@ -3014,12 +3066,43 @@
if (::Dart_IsError(state)) {
return state;
}
+
Field& field = Field::Handle(isolate);
Function& getter = Function::Handle(isolate);
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
if (obj.IsNull()) {
return Api::NewError("%s expects argument 'container' to be non-null.",
CURRENT_FUNC);
+ } else if (obj.IsType() || obj.IsClass()) {
+ // To access a static field we may need to use the Field or the
+ // getter Function.
+ // For backwards compatibility we allow class objects to be passed in
+ // for now. This needs to be removed once all code that uses class
+ // objects to invoke Dart_GetField is removed.
+ Class& cls = Class::Handle();
+ if (obj.IsType()) {
+ cls = Type::Cast(obj).type_class();
+ } else {
+ cls = Class::Cast(obj).raw();
+ }
+ field = cls.LookupStaticField(field_name);
+ if (field.IsNull() || FieldIsUninitialized(isolate, field)) {
+ const String& getter_name =
+ String::Handle(isolate, Field::GetterName(field_name));
+ getter = cls.LookupStaticFunctionAllowPrivate(getter_name);
+ }
+
+ if (!getter.IsNull()) {
+ // Invoke the getter and return the result.
+ return Api::NewHandle(
+ isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
+ } else if (!field.IsNull()) {
+ return Api::NewHandle(isolate, field.value());
+ } else {
+ return Api::NewError("%s: did not find static field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
} else if (obj.IsInstance()) {
// Every instance field has a getter Function. Try to find the
// getter in any superclass and use that function to access the
@@ -3051,28 +3134,6 @@
}
return Api::NewHandle(isolate, DartEntry::InvokeFunction(getter, args));
- } else if (obj.IsClass()) {
- // To access a static field we may need to use the Field or the
- // getter Function.
- const Class& cls = Class::Cast(obj);
- field = cls.LookupStaticField(field_name);
- if (field.IsNull() || FieldIsUninitialized(isolate, field)) {
- const String& getter_name =
- String::Handle(isolate, Field::GetterName(field_name));
- getter = cls.LookupStaticFunctionAllowPrivate(getter_name);
- }
-
- if (!getter.IsNull()) {
- // Invoke the getter and return the result.
- return Api::NewHandle(
- isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
- } else if (!field.IsNull()) {
- return Api::NewHandle(isolate, field.value());
- } else {
- return Api::NewError("%s: did not find static field '%s'.",
- CURRENT_FUNC, field_name.ToCString());
- }
-
} else if (obj.IsLibrary()) {
// To access a top-level we may need to use the Field or the
// getter Function. The getter function may either be in the
@@ -3107,7 +3168,7 @@
return container;
} else {
return Api::NewError(
- "%s expects argument 'container' to be an object, class, or library.",
+ "%s expects argument 'container' to be an object, type, or library.",
CURRENT_FUNC);
}
}
@@ -3144,6 +3205,50 @@
if (obj.IsNull()) {
return Api::NewError("%s expects argument 'container' to be non-null.",
CURRENT_FUNC);
+ } else if (obj.IsType() || obj.IsClass()) {
+ // To access a static field we may need to use the Field or the
+ // setter Function.
+ // For backwards compatibility we allow class objects to be passed in
+ // for now. This needs to be removed once all code that uses class
+ // objects to invoke Dart_SetField is removed.
+ Class& cls = Class::Handle();
+ if (obj.IsType()) {
+ cls = Type::Cast(obj).type_class();
+ } else {
+ cls = Class::Cast(obj).raw();
+ }
+ field = cls.LookupStaticField(field_name);
+ if (field.IsNull()) {
+ String& setter_name =
+ String::Handle(isolate, Field::SetterName(field_name));
+ setter = cls.LookupStaticFunctionAllowPrivate(setter_name);
+ }
+
+ if (!setter.IsNull()) {
+ // Invoke the setter and return the result.
+ const int kNumArgs = 1;
+ const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ args.SetAt(0, value_instance);
+ const Object& result =
+ Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
+ if (result.IsError()) {
+ return Api::NewHandle(isolate, result.raw());
+ } else {
+ return Api::Success();
+ }
+ } else if (!field.IsNull()) {
+ if (field.is_final()) {
+ return Api::NewError("%s: cannot set final field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ } else {
+ field.set_value(value_instance);
+ return Api::Success();
+ }
+ } else {
+ return Api::NewError("%s: did not find static field '%s'.",
+ CURRENT_FUNC, field_name.ToCString());
+ }
+
} else if (obj.IsInstance()) {
// Every instance field has a setter Function. Try to find the
// setter in any superclass and use that function to access the
@@ -3181,42 +3286,6 @@
}
return Api::NewHandle(isolate, DartEntry::InvokeFunction(setter, args));
- } else if (obj.IsClass()) {
- // To access a static field we may need to use the Field or the
- // setter Function.
- const Class& cls = Class::Cast(obj);
- field = cls.LookupStaticField(field_name);
- if (field.IsNull()) {
- String& setter_name =
- String::Handle(isolate, Field::SetterName(field_name));
- setter = cls.LookupStaticFunctionAllowPrivate(setter_name);
- }
-
- if (!setter.IsNull()) {
- // Invoke the setter and return the result.
- const int kNumArgs = 1;
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
- args.SetAt(0, value_instance);
- const Object& result =
- Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
- if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
- } else {
- return Api::Success();
- }
- } else if (!field.IsNull()) {
- if (field.is_final()) {
- return Api::NewError("%s: cannot set final field '%s'.",
- CURRENT_FUNC, field_name.ToCString());
- } else {
- field.set_value(value_instance);
- return Api::Success();
- }
- } else {
- return Api::NewError("%s: did not find static field '%s'.",
- CURRENT_FUNC, field_name.ToCString());
- }
-
} else if (obj.IsLibrary()) {
// To access a top-level we may need to use the Field or the
// setter Function. The setter function may either be in the
@@ -3258,7 +3327,7 @@
return container;
} else {
return Api::NewError(
- "%s expects argument 'container' to be an object, class, or library.",
+ "%s expects argument 'container' to be an object, type, or library.",
CURRENT_FUNC);
}
}
@@ -3619,6 +3688,82 @@
}
+DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
+ Dart_Handle class_name,
+ intptr_t number_of_type_arguments,
+ Dart_Handle* type_arguments) {
+ Isolate* isolate = Isolate::Current();
+ DARTSCOPE(isolate);
+
+ // Validate the input arguments.
+ const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ if (lib.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, library, Library);
+ }
+ const String& name_str = Api::UnwrapStringHandle(isolate, class_name);
+ if (name_str.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, class_name, String);
+ }
+ // Ensure all classes are finalized.
+ Dart_Handle state = Api::CheckIsolateState(isolate);
+ if (::Dart_IsError(state)) {
+ return state;
+ }
+ const Class& cls =
+ Class::Handle(isolate, lib.LookupClassAllowPrivate(name_str));
+ if (cls.IsNull()) {
+ const String& lib_name = String::Handle(isolate, lib.name());
+ return Api::NewError("Type '%s' not found in library '%s'.",
+ name_str.ToCString(), lib_name.ToCString());
+ }
+ if (cls.NumTypeArguments() == 0) {
+ if (number_of_type_arguments != 0) {
+ return Api::NewError("Invalid number of type arguments specified, "
+ "got %"Pd" expected 0", number_of_type_arguments);
+ }
+ return Api::NewHandle(isolate, Type::NewNonParameterizedType(cls));
+ }
+ intptr_t num_expected_type_arguments = cls.NumTypeParameters();
+ TypeArguments& type_args_obj = TypeArguments::Handle();
+ if (number_of_type_arguments > 0) {
+ if (type_arguments == NULL) {
+ RETURN_NULL_ERROR(type_arguments);
+ }
+ if (num_expected_type_arguments != number_of_type_arguments) {
+ return Api::NewError("Invalid number of type arguments specified, "
+ "got %"Pd" expected %"Pd,
+ number_of_type_arguments,
+ num_expected_type_arguments);
+ }
+ const Array& array = Api::UnwrapArrayHandle(isolate, *type_arguments);
+ if (array.IsNull()) {
+ RETURN_TYPE_ERROR(isolate, *type_arguments, Array);
+ }
+ if (array.Length() != num_expected_type_arguments) {
+ return Api::NewError("Invalid type arguments specified, expected an "
+ "array of len %"Pd" but got an array of len %"Pd,
+ number_of_type_arguments,
+ array.Length());
+ }
+ // Set up the type arguments array.
+ type_args_obj ^= TypeArguments::New(num_expected_type_arguments);
+ AbstractType& type_arg = AbstractType::Handle();
+ for (intptr_t i = 0; i < number_of_type_arguments; i++) {
+ type_arg ^= array.At(i);
+ type_args_obj.SetTypeAt(i, type_arg);
+ }
+ }
+
+ // Construct the type object, canonicalize it and return.
+ const Type& instantiated_type = Type::Handle(
+ Type::New(cls, type_args_obj, Scanner::kDummyTokenIndex));
+ ClassFinalizer::FinalizeType(cls,
+ instantiated_type,
+ ClassFinalizer::kCanonicalize);
+ return Api::NewHandle(isolate, instantiated_type.raw());
+}
+
+
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
@@ -3722,7 +3867,7 @@
const String& prefix_symbol =
String::Handle(isolate, Symbols::New(prefix_vm));
const Namespace& import_ns = Namespace::Handle(
- Namespace::New(import_vm, Array::Handle(), Array::Handle()));
+ Namespace::New(import_vm, Object::null_array(), Object::null_array()));
if (prefix_vm.Length() == 0) {
library_vm.AddImport(import_ns);
} else {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 36ca32d..2c78b52 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -242,6 +242,37 @@
}
+TEST_CASE(InstanceGetType) {
+ Isolate* isolate = Isolate::Current();
+ // Get the handle from a valid instance handle.
+ Dart_Handle type = Dart_InstanceGetType(Dart_Null());
+ EXPECT_VALID(type);
+ EXPECT(Dart_IsType(type));
+ const Type& null_type_obj = Api::UnwrapTypeHandle(isolate, type);
+ EXPECT(null_type_obj.raw() == Type::NullType());
+
+ Dart_Handle instance = Dart_True();
+ type = Dart_InstanceGetType(instance);
+ EXPECT_VALID(type);
+ EXPECT(Dart_IsType(type));
+ const Type& bool_type_obj = Api::UnwrapTypeHandle(isolate, type);
+ EXPECT(bool_type_obj.raw() == Type::BoolType());
+
+ // Errors propagate.
+ Dart_Handle error = Dart_NewApiError("MyError");
+ Dart_Handle error_type = Dart_InstanceGetType(error);
+ EXPECT_ERROR(error_type, "MyError");
+
+ // Get the handle from a non-instance handle
+ Dart_Handle obj = Api::NewHandle(isolate,
+ isolate->object_store()->type_class());
+ Dart_Handle type_type = Dart_InstanceGetType(obj);
+ EXPECT_ERROR(type_type,
+ "Dart_InstanceGetType expects argument 'instance' to be of "
+ "type Instance.");
+}
+
+
TEST_CASE(InstanceGetClass) {
// Get the handle from a valid instance handle.
Dart_Handle instance = Dart_True();
@@ -2711,11 +2742,11 @@
"class 'SomeClass' is not a function-type class.");
}
-#define CHECK_ABSTRACT_CLASS(handle, name) \
+#define CHECK_CLASS(handle, name) \
{ \
Dart_Handle tmp = (handle); \
EXPECT_VALID(tmp); \
- EXPECT(Dart_IsAbstractClass(tmp)); \
+ EXPECT(Dart_IsClass(tmp)); \
Dart_Handle intf_name = Dart_ClassName(tmp); \
EXPECT_VALID(intf_name); \
const char* intf_name_cstr = ""; \
@@ -2758,7 +2789,7 @@
len = -1;
EXPECT_VALID(Dart_ClassGetInterfaceCount(cls1, &len));
EXPECT_EQ(1, len);
- CHECK_ABSTRACT_CLASS(Dart_ClassGetInterfaceAt(cls1, 0), "MyInterface1");
+ CHECK_CLASS(Dart_ClassGetInterfaceAt(cls1, 0), "MyInterface1");
EXPECT_ERROR(Dart_ClassGetInterfaceAt(cls1, -1),
"Dart_ClassGetInterfaceAt: argument 'index' out of bounds");
@@ -2770,8 +2801,8 @@
EXPECT_EQ(2, len);
// TODO(turnidge): The test relies on the ordering here. Sort this.
- CHECK_ABSTRACT_CLASS(Dart_ClassGetInterfaceAt(cls2, 0), "MyInterface0");
- CHECK_ABSTRACT_CLASS(Dart_ClassGetInterfaceAt(cls2, 1), "MyInterface1");
+ CHECK_CLASS(Dart_ClassGetInterfaceAt(cls2, 0), "MyInterface0");
+ CHECK_CLASS(Dart_ClassGetInterfaceAt(cls2, 1), "MyInterface1");
len = -1;
EXPECT_VALID(Dart_ClassGetInterfaceCount(intf0, &len));
@@ -2780,7 +2811,7 @@
len = -1;
EXPECT_VALID(Dart_ClassGetInterfaceCount(intf1, &len));
EXPECT_EQ(1, len);
- CHECK_ABSTRACT_CLASS(Dart_ClassGetInterfaceAt(intf1, 0), "MyInterface0");
+ CHECK_CLASS(Dart_ClassGetInterfaceAt(intf1, 0), "MyInterface0");
// Error cases.
EXPECT_ERROR(Dart_ClassGetInterfaceCount(Dart_True(), &len),
@@ -2791,6 +2822,208 @@
}
+TEST_CASE(TypeGetNonParamtericTypes) {
+ const char* kScriptChars =
+ "class MyClass0 {\n"
+ "}\n"
+ "\n"
+ "class MyClass1 implements MyInterface1 {\n"
+ "}\n"
+ "\n"
+ "class MyClass2 implements MyInterface0, MyInterface1 {\n"
+ "}\n"
+ "\n"
+ "abstract class MyInterface0 {\n"
+ "}\n"
+ "\n"
+ "abstract class MyInterface1 implements MyInterface0 {\n"
+ "}\n"
+ "MyClass0 getMyClass0() { return new MyClass0(); }\n"
+ "MyClass1 getMyClass1() { return new MyClass1(); }\n"
+ "MyClass2 getMyClass2() { return new MyClass2(); }\n"
+ "Type getMyClass0Type() { return new MyClass0().runtimeType; }\n"
+ "Type getMyClass1Type() { return new MyClass1().runtimeType; }\n"
+ "Type getMyClass2Type() { return new MyClass2().runtimeType; }\n";
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ bool instanceof = false;
+
+ // First get the type objects of these non parameterized types.
+ Dart_Handle type0 = Dart_GetType(lib, NewString("MyClass0"), 0, NULL);
+ EXPECT_VALID(type0);
+ Dart_Handle type1 = Dart_GetType(lib, NewString("MyClass1"), 0, NULL);
+ EXPECT_VALID(type1);
+ Dart_Handle type2 = Dart_GetType(lib, NewString("MyClass2"), 0, NULL);
+ EXPECT_VALID(type2);
+ Dart_Handle type3 = Dart_GetType(lib, NewString("MyInterface0"), 0, NULL);
+ EXPECT_VALID(type3);
+ Dart_Handle type4 = Dart_GetType(lib, NewString("MyInterface1"), 0, NULL);
+ EXPECT_VALID(type4);
+
+ // Now create objects of these non parameterized types and check
+ // that the validity of the type of the created object.
+ // MyClass0 type.
+ Dart_Handle type0_obj = Dart_Invoke(lib, NewString("getMyClass0"), 0, NULL);
+ EXPECT_VALID(type0_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, type0, &instanceof));
+ EXPECT(instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, type1, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, type2, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, type3, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, type4, &instanceof));
+ EXPECT(!instanceof);
+ type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, NULL);
+ EXPECT_VALID(type0_obj);
+ EXPECT(Dart_IdentityEquals(type0, type0_obj));
+
+ // MyClass1 type.
+ Dart_Handle type1_obj = Dart_Invoke(lib, NewString("getMyClass1"), 0, NULL);
+ EXPECT_VALID(type1_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, type1, &instanceof));
+ EXPECT(instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, type0, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, type2, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, type3, &instanceof));
+ EXPECT(instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, type4, &instanceof));
+ EXPECT(instanceof);
+ type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, NULL);
+ EXPECT_VALID(type1_obj);
+ EXPECT(Dart_IdentityEquals(type1, type1_obj));
+
+ // MyClass2 type.
+ Dart_Handle type2_obj = Dart_Invoke(lib, NewString("getMyClass2"), 0, NULL);
+ EXPECT_VALID(type2_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type2_obj, type2, &instanceof));
+ EXPECT(instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type2_obj, type0, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type2_obj, type1, &instanceof));
+ EXPECT(!instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type2_obj, type3, &instanceof));
+ EXPECT(instanceof);
+ EXPECT_VALID(Dart_ObjectIsType(type2_obj, type4, &instanceof));
+ EXPECT(instanceof);
+ type2_obj = Dart_Invoke(lib, NewString("getMyClass2Type"), 0, NULL);
+ EXPECT_VALID(type2_obj);
+ EXPECT(Dart_IdentityEquals(type2, type2_obj));
+}
+
+
+TEST_CASE(TypeGetParamterizedTypes) {
+ const char* kScriptChars =
+ "class MyClass0<A, B> {\n"
+ "}\n"
+ "\n"
+ "class MyClass1<A, C> {\n"
+ "}\n"
+ "MyClass0 getMyClass0() {\n"
+ " return new MyClass0<int, double>();\n"
+ "}\n"
+ "Type getMyClass0Type() {\n"
+ " return new MyClass0<int, double>().runtimeType;\n"
+ "}\n"
+ "MyClass1 getMyClass1() {\n"
+ " return new MyClass1<List<int>, List>();\n"
+ "}\n"
+ "Type getMyClass1Type() {\n"
+ " return new MyClass1<List<int>, List>().runtimeType;\n"
+ "}\n"
+ "MyClass0 getMyClass0_1() {\n"
+ " return new MyClass0<double, int>();\n"
+ "}\n"
+ "Type getMyClass0_1Type() {\n"
+ " return new MyClass0<double, int>().runtimeType;\n"
+ "}\n"
+ "MyClass1 getMyClass1_1() {\n"
+ " return new MyClass1<List<int>, List<double>>();\n"
+ "}\n"
+ "Type getMyClass1_1Type() {\n"
+ " return new MyClass1<List<int>, List<double>>().runtimeType;\n"
+ "}\n";
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ bool instanceof = false;
+
+ // First get type objects of some of the basic types used in the test.
+ Dart_Handle int_type = Dart_GetType(lib, NewString("int"), 0, NULL);
+ EXPECT_VALID(int_type);
+ Dart_Handle double_type = Dart_GetType(lib, NewString("double"), 0, NULL);
+ EXPECT_VALID(double_type);
+ Dart_Handle list_type = Dart_GetType(lib, NewString("List"), 0, NULL);
+ EXPECT_VALID(list_type);
+ Dart_Handle type_args = Dart_NewList(1);
+ EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
+ Dart_Handle list_int_type = Dart_GetType(lib,
+ NewString("List"),
+ 1,
+ &type_args);
+ EXPECT_VALID(list_int_type);
+
+ // Now instantiate MyClass0 and MyClass1 types with the same type arguments
+ // used in the code above.
+ type_args = Dart_NewList(2);
+ EXPECT_VALID(Dart_ListSetAt(type_args, 0, int_type));
+ EXPECT_VALID(Dart_ListSetAt(type_args, 1, double_type));
+ Dart_Handle myclass0_type = Dart_GetType(lib,
+ NewString("MyClass0"),
+ 2,
+ &type_args);
+ EXPECT_VALID(myclass0_type);
+
+ type_args = Dart_NewList(2);
+ EXPECT_VALID(Dart_ListSetAt(type_args, 0, list_int_type));
+ EXPECT_VALID(Dart_ListSetAt(type_args, 1, list_type));
+ Dart_Handle myclass1_type = Dart_GetType(lib,
+ NewString("MyClass1"),
+ 2,
+ &type_args);
+ EXPECT_VALID(myclass1_type);
+
+ // Now create objects of the type and validate the object type matches
+ // the one returned above. Also get the runtime type of the object and
+ // verify that it matches the type returned above.
+ // MyClass0<int, double> type.
+ Dart_Handle type0_obj = Dart_Invoke(lib, NewString("getMyClass0"), 0, NULL);
+ EXPECT_VALID(type0_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceof));
+ EXPECT(instanceof);
+ type0_obj = Dart_Invoke(lib, NewString("getMyClass0Type"), 0, NULL);
+ EXPECT_VALID(type0_obj);
+ EXPECT(Dart_IdentityEquals(type0_obj, myclass0_type));
+
+ // MyClass1<List<int>, List> type.
+ Dart_Handle type1_obj = Dart_Invoke(lib, NewString("getMyClass1"), 0, NULL);
+ EXPECT_VALID(type1_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceof));
+ EXPECT(instanceof);
+ type1_obj = Dart_Invoke(lib, NewString("getMyClass1Type"), 0, NULL);
+ EXPECT_VALID(type1_obj);
+ EXPECT(Dart_IdentityEquals(type1_obj, myclass1_type));
+
+ // MyClass0<double, int> type.
+ type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1"), 0, NULL);
+ EXPECT_VALID(type0_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type0_obj, myclass0_type, &instanceof));
+ EXPECT(!instanceof);
+ type0_obj = Dart_Invoke(lib, NewString("getMyClass0_1Type"), 0, NULL);
+ EXPECT_VALID(type0_obj);
+ EXPECT(!Dart_IdentityEquals(type0_obj, myclass0_type));
+
+ // MyClass1<List<int>, List<double>> type.
+ type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1"), 0, NULL);
+ EXPECT_VALID(type1_obj);
+ EXPECT_VALID(Dart_ObjectIsType(type1_obj, myclass1_type, &instanceof));
+ EXPECT(instanceof);
+ type1_obj = Dart_Invoke(lib, NewString("getMyClass1_1Type"), 0, NULL);
+ EXPECT_VALID(type1_obj);
+ EXPECT(!Dart_IdentityEquals(type1_obj, myclass1_type));
+}
+
+
static void TestFieldOk(Dart_Handle container,
Dart_Handle name,
bool final,
@@ -2923,8 +3156,8 @@
// Shared setup.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("Fields"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("Fields"), 0, NULL);
+ EXPECT_VALID(type);
Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, NULL);
EXPECT_VALID(instance);
Dart_Handle name;
@@ -2943,144 +3176,144 @@
// Instance field.
name = NewString("instance_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, false, "instance");
// Hidden instance field.
name = NewString("_instance_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, false, "hidden instance");
// Final instance field.
name = NewString("final_instance_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, true, "final instance");
// Hidden final instance field.
name = NewString("_final_instance_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, true, "hidden final instance");
// Inherited field.
name = NewString("inherited_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, false, "inherited");
// Instance get/set field.
name = NewString("instance_getset_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, false, "instance getset");
// Hidden instance get/set field.
name = NewString("_instance_getset_fld");
TestFieldNotFound(lib, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldOk(instance, name, false, "hidden instance getset");
// Static field.
name = NewString("static_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldOk(cls, name, false, "static");
+ TestFieldOk(type, name, false, "static");
// Hidden static field.
name = NewString("_static_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldOk(cls, name, false, "hidden static");
+ TestFieldOk(type, name, false, "hidden static");
// Static final field.
name = NewString("const_static_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldOk(cls, name, true, "const static");
+ TestFieldOk(type, name, true, "const static");
// Hidden static const field.
name = NewString("_const_static_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldOk(cls, name, true, "hidden const static");
+ TestFieldOk(type, name, true, "hidden const static");
// Static non-inherited field. Not found at any level.
name = NewString("non_inherited_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
// Static get/set field.
name = NewString("static_getset_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldOk(cls, name, false, "static getset");
+ TestFieldOk(type, name, false, "static getset");
// Hidden static get/set field.
name = NewString("_static_getset_fld");
TestFieldNotFound(lib, name);
TestFieldNotFound(instance, name);
- TestFieldOk(cls, name, false, "hidden static getset");
+ TestFieldOk(type, name, false, "hidden static getset");
// Top-Level field.
name = NewString("top_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, false, "top");
// Hidden top-level field.
name = NewString("_top_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, false, "hidden top");
// Top-Level final field.
name = NewString("const_top_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, true, "const top");
// Hidden top-level final field.
name = NewString("_const_top_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, true, "hidden const top");
// Top-Level get/set field.
name = NewString("top_getset_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, false, "top getset");
// Hidden top-level get/set field.
name = NewString("_top_getset_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, false, "hidden top getset");
// Imported top-Level field.
name = NewString("imported_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, false, "imported");
// Hidden imported top-level field. Not found at any level.
name = NewString("_imported_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldNotFound(lib, name);
// Imported top-Level get/set field.
name = NewString("imported_getset_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldOk(lib, name, false, "imported getset");
// Hidden imported top-level get/set field. Not found at any level.
name = NewString("_imported_getset_fld");
- TestFieldNotFound(cls, name);
+ TestFieldNotFound(type, name);
TestFieldNotFound(instance, name);
TestFieldNotFound(lib, name);
}
@@ -3588,33 +3821,33 @@
Dart_Handle result;
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("TestClass"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("TestClass"), 0, NULL);
+ EXPECT_VALID(type);
// Invoke a function which returns an object.
- result = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
+ result = Dart_Invoke(type, NewString("testMain"), 0, NULL);
EXPECT_VALID(result);
// For uninitialized fields, the getter is returned
- result = Dart_GetField(cls, NewString("fld1"));
+ result = Dart_GetField(type, NewString("fld1"));
EXPECT_VALID(result);
int64_t value = 0;
result = Dart_IntegerToInt64(result, &value);
EXPECT_EQ(7, value);
- result = Dart_GetField(cls, NewString("fld2"));
+ result = Dart_GetField(type, NewString("fld2"));
EXPECT_VALID(result);
result = Dart_IntegerToInt64(result, &value);
EXPECT_EQ(11, value);
// Overwrite fld2
- result = Dart_SetField(cls,
+ result = Dart_SetField(type,
NewString("fld2"),
Dart_NewInteger(13));
EXPECT_VALID(result);
// We now get the new value for fld2, not the initializer
- result = Dart_GetField(cls, NewString("fld2"));
+ result = Dart_GetField(type, NewString("fld2"));
EXPECT_VALID(result);
result = Dart_IntegerToInt64(result, &value);
EXPECT_EQ(13, value);
@@ -3633,10 +3866,10 @@
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("TestClass"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("TestClass"), 0, NULL);
+ EXPECT_VALID(type);
- result = Dart_GetField(cls, NewString("fld2"));
+ result = Dart_GetField(type, NewString("fld2"));
EXPECT_VALID(result);
result = Dart_IntegerToInt64(result, &value);
EXPECT_EQ(11, value);
@@ -3655,13 +3888,13 @@
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("TestClass"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("TestClass"), 0, NULL);
+ EXPECT_VALID(type);
- result = Dart_SetField(cls, NewString("fld2"), Dart_NewInteger(13));
+ result = Dart_SetField(type, NewString("fld2"), Dart_NewInteger(13));
EXPECT_VALID(result);
- result = Dart_GetField(cls, NewString("fld2"));
+ result = Dart_GetField(type, NewString("fld2"));
EXPECT_VALID(result);
result = Dart_IntegerToInt64(result, &value);
EXPECT_EQ(13, value);
@@ -3697,9 +3930,9 @@
"}\n";
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("MyClass"));
- EXPECT_VALID(cls);
- Dart_Handle intf = Dart_GetClass(lib, NewString("MyInterface"));
+ Dart_Handle type = Dart_GetType(lib, NewString("MyClass"), 0, NULL);
+ EXPECT_VALID(type);
+ Dart_Handle intf = Dart_GetType(lib, NewString("MyInterface"), 0, NULL);
EXPECT_VALID(intf);
Dart_Handle args[1];
args[0] = Dart_NewInteger(11);
@@ -3707,21 +3940,30 @@
bad_args[0] = Dart_Error("myerror");
// Invoke the unnamed constructor.
- Dart_Handle result = Dart_New(cls, Dart_Null(), 0, NULL);
+ Dart_Handle result = Dart_New(type, Dart_Null(), 0, NULL);
EXPECT_VALID(result);
bool instanceof = false;
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int64_t int_value = 0;
Dart_Handle foo = Dart_GetField(result, NewString("foo"));
EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
EXPECT_EQ(7, int_value);
- // Invoke the unnamed constructor with an empty string.
- result = Dart_New(cls, NewString(""), 0, NULL);
+ // Allocate without a constructor.
+ result = Dart_Allocate(type);
EXPECT_VALID(result);
instanceof = false;
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
+ EXPECT(instanceof);
+ foo = Dart_GetField(result, NewString("foo"));
+ EXPECT(Dart_IsNull(foo));
+
+ // Invoke the unnamed constructor with an empty string.
+ result = Dart_New(type, NewString(""), 0, NULL);
+ EXPECT_VALID(result);
+ instanceof = false;
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int_value = 0;
foo = Dart_GetField(result, NewString("foo"));
@@ -3729,9 +3971,9 @@
EXPECT_EQ(7, int_value);
// Invoke a named constructor.
- result = Dart_New(cls, NewString("named"), 1, args);
+ result = Dart_New(type, NewString("named"), 1, args);
EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int_value = 0;
foo = Dart_GetField(result, NewString("foo"));
@@ -3739,9 +3981,9 @@
EXPECT_EQ(11, int_value);
// Invoke a hidden named constructor.
- result = Dart_New(cls, NewString("_hidden"), 1, args);
+ result = Dart_New(type, NewString("_hidden"), 1, args);
EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int_value = 0;
foo = Dart_GetField(result, NewString("foo"));
@@ -3749,9 +3991,9 @@
EXPECT_EQ(-11, int_value);
// Invoke a factory constructor.
- result = Dart_New(cls, NewString("multiply"), 1, args);
+ result = Dart_New(type, NewString("multiply"), 1, args);
EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int_value = 0;
foo = Dart_GetField(result, NewString("foo"));
@@ -3759,7 +4001,7 @@
EXPECT_EQ(1100, int_value);
// Invoke a factory constructor which returns null.
- result = Dart_New(cls, NewString("nullo"), 0, NULL);
+ result = Dart_New(type, NewString("nullo"), 0, NULL);
EXPECT_VALID(result);
EXPECT(Dart_IsNull(result));
@@ -3769,44 +4011,44 @@
// Pass a bad class object.
result = Dart_New(Dart_Null(), NewString("named"), 1, args);
- EXPECT_ERROR(result, "Dart_New expects argument 'clazz' to be non-null.");
+ EXPECT_ERROR(result, "Dart_New expects argument 'type' to be non-null.");
// Pass a negative arg count.
- result = Dart_New(cls, NewString("named"), -1, args);
+ result = Dart_New(type, NewString("named"), -1, args);
EXPECT_ERROR(
result,
"Dart_New expects argument 'number_of_arguments' to be non-negative.");
// Pass the wrong arg count.
- result = Dart_New(cls, NewString("named"), 0, NULL);
+ result = Dart_New(type, NewString("named"), 0, NULL);
EXPECT_ERROR(
result,
"Dart_New: wrong argument count for constructor 'MyClass.named': "
"0 passed, 1 expected.");
// Pass a bad argument. Error is passed through.
- result = Dart_New(cls, NewString("named"), 1, bad_args);
+ result = Dart_New(type, NewString("named"), 1, bad_args);
EXPECT_ERROR(result, "myerror");
// Pass a bad constructor name.
- result = Dart_New(cls, Dart_NewInteger(55), 1, args);
+ result = Dart_New(type, Dart_NewInteger(55), 1, args);
EXPECT_ERROR(
result,
"Dart_New expects argument 'constructor_name' to be of type String.");
// Invoke a missing constructor.
- result = Dart_New(cls, NewString("missing"), 1, args);
+ result = Dart_New(type, NewString("missing"), 1, args);
EXPECT_ERROR(result,
"Dart_New: could not find constructor 'MyClass.missing'.");
// Invoke a constructor which throws an exception.
- result = Dart_New(cls, NewString("exception"), 1, args);
+ result = Dart_New(type, NewString("exception"), 1, args);
EXPECT_ERROR(result, "ConstructorDeath");
// Invoke two-hop redirecting factory constructor.
result = Dart_New(intf, NewString("named"), 1, args);
EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int_value = 0;
foo = Dart_GetField(result, NewString("foo"));
@@ -3816,7 +4058,7 @@
// Invoke one-hop redirecting factory constructor.
result = Dart_New(intf, NewString("multiply"), 1, args);
EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(instanceof);
int_value = 0;
foo = Dart_GetField(result, NewString("foo"));
@@ -3831,7 +4073,7 @@
// Invoke abstract constructor that is present in the interface.
result = Dart_New(intf, NewString("notfound"), 1, args);
EXPECT_VALID(result);
- EXPECT_VALID(Dart_ObjectIsType(result, cls, &instanceof));
+ EXPECT_VALID(Dart_ObjectIsType(result, type, &instanceof));
EXPECT(!instanceof);
}
@@ -3842,13 +4084,13 @@
// factories.
Dart_Handle core_lib = Dart_LookupLibrary(NewString("dart:core"));
EXPECT_VALID(core_lib);
- Dart_Handle list_class = Dart_GetClass(core_lib, NewString("List"));
- EXPECT_VALID(list_class);
+ Dart_Handle list_type = Dart_GetType(core_lib, NewString("List"), 0, NULL);
+ EXPECT_VALID(list_type);
const int kNumArgs = 1;
Dart_Handle args[kNumArgs];
args[0] = Dart_NewInteger(1);
- Dart_Handle list_obj = Dart_New(list_class, Dart_Null(), kNumArgs, args);
+ Dart_Handle list_obj = Dart_New(list_type, Dart_Null(), kNumArgs, args);
EXPECT_VALID(list_obj);
EXPECT(Dart_IsList(list_obj));
}
@@ -3886,8 +4128,8 @@
// Shared setup.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("Methods"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("Methods"), 0, NULL);
+ EXPECT_VALID(type);
Dart_Handle instance = Dart_Invoke(lib, NewString("test"), 0, NULL);
EXPECT_VALID(instance);
Dart_Handle args[1];
@@ -3902,7 +4144,7 @@
// Instance method.
name = NewString("instanceMethod");
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
- EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
+ EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
result = Dart_Invoke(instance, name, 1, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
@@ -3915,7 +4157,7 @@
name = PrivateLibName(lib, "_instanceMethod");
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
- EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
+ EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
result = Dart_Invoke(instance, name, 1, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
@@ -3924,7 +4166,7 @@
// Inherited method.
name = NewString("inheritedMethod");
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
- EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
+ EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
result = Dart_Invoke(instance, name, 1, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
@@ -3934,20 +4176,20 @@
name = NewString("staticMethod");
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
- result = Dart_Invoke(cls, name, 1, args);
+ result = Dart_Invoke(type, name, 1, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
EXPECT_STREQ("static !!!", str);
// Static method, wrong arg count.
- EXPECT_ERROR(Dart_Invoke(cls, name, 2, bad_args),
+ EXPECT_ERROR(Dart_Invoke(type, name, 2, bad_args),
"did not find static method 'Methods.staticMethod'");
// Hidden static method.
name = PrivateLibName(lib, "_staticMethod");
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
- result = Dart_Invoke(cls, name, 1, args);
+ result = Dart_Invoke(type, name, 1, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
EXPECT_STREQ("hidden static !!!", str);
@@ -3956,11 +4198,11 @@
name = NewString("non_inheritedMethod");
EXPECT(Dart_IsError(Dart_Invoke(lib, name, 1, args)));
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
- EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
+ EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
// Top-Level method.
name = NewString("topMethod");
- EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
+ EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
result = Dart_Invoke(lib, name, 1, args);
EXPECT_VALID(result);
@@ -3974,7 +4216,7 @@
// Hidden top-level method.
name = PrivateLibName(lib, "_topMethod");
- EXPECT(Dart_IsError(Dart_Invoke(cls, name, 1, args)));
+ EXPECT(Dart_IsError(Dart_Invoke(type, name, 1, args)));
EXPECT(Dart_IsError(Dart_Invoke(instance, name, 1, args)));
result = Dart_Invoke(lib, name, 1, args);
EXPECT_VALID(result);
@@ -4091,11 +4333,11 @@
Dart_Handle instance;
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Dart_Handle cls = Dart_GetClass(lib, NewString("TestClass"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("TestClass"), 0, NULL);
+ EXPECT_VALID(type);
// Invoke a function which returns an object.
- instance = Dart_Invoke(cls, NewString("testMain"), 0, NULL);
+ instance = Dart_Invoke(type, NewString("testMain"), 0, NULL);
EXPECT_VALID(instance);
// Try to get a field that does not exist, should call noSuchMethod.
@@ -4110,7 +4352,7 @@
result = Dart_Invoke(instance, NewString("method"), 0, NULL);
EXPECT_VALID(result);
- result = Dart_GetField(cls, NewString("fld1"));
+ result = Dart_GetField(type, NewString("fld1"));
EXPECT_VALID(result);
int64_t value = 0;
result = Dart_IntegerToInt64(result, &value);
@@ -4193,8 +4435,8 @@
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
- Dart_Handle cls = Dart_GetClass(lib, NewString("Foo"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("Foo"), 0, NULL);
+ EXPECT_VALID(type);
// Invoke a function which returns a closure.
Dart_Handle retobj = Dart_Invoke(lib, NewString("getClosure"), 0, NULL);
@@ -4235,6 +4477,9 @@
EXPECT(Dart_IsFunction(result));
owner = Dart_FunctionOwner(result);
EXPECT_VALID(owner);
+ Isolate* isolate = Isolate::Current();
+ Dart_Handle cls = Api::NewHandle(
+ isolate, Api::UnwrapTypeHandle(isolate, type).type_class());
defining_function = Dart_LookupFunction(cls,
NewString("getInstanceClosure"));
EXPECT(Dart_IdentityEquals(owner, defining_function));
@@ -4479,7 +4724,7 @@
}
-TEST_CASE(GetClass) {
+TEST_CASE(GetType) {
const char* kScriptChars =
"class Class {\n"
" static var name = 'Class';\n"
@@ -4492,38 +4737,38 @@
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
// Lookup a class.
- Dart_Handle cls = Dart_GetClass(lib, NewString("Class"));
- EXPECT_VALID(cls);
- Dart_Handle name = Dart_GetField(cls, NewString("name"));
+ Dart_Handle type = Dart_GetType(lib, NewString("Class"), 0, NULL);
+ EXPECT_VALID(type);
+ Dart_Handle name = Dart_GetField(type, NewString("name"));
EXPECT_VALID(name);
const char* name_cstr = "";
EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
EXPECT_STREQ("Class", name_cstr);
// Lookup a private class.
- cls = Dart_GetClass(lib, NewString("_Class"));
- EXPECT_VALID(cls);
- name = Dart_GetField(cls, NewString("name"));
+ type = Dart_GetType(lib, NewString("_Class"), 0, NULL);
+ EXPECT_VALID(type);
+ name = Dart_GetField(type, NewString("name"));
EXPECT_VALID(name);
name_cstr = "";
EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
EXPECT_STREQ("_Class", name_cstr);
// Lookup a class that does not exist.
- cls = Dart_GetClass(lib, NewString("DoesNotExist"));
- EXPECT(Dart_IsError(cls));
- EXPECT_STREQ("Class 'DoesNotExist' not found in library 'dart:test-lib'.",
- Dart_GetError(cls));
+ type = Dart_GetType(lib, NewString("DoesNotExist"), 0, NULL);
+ EXPECT(Dart_IsError(type));
+ EXPECT_STREQ("Type 'DoesNotExist' not found in library 'dart:test-lib'.",
+ Dart_GetError(type));
// Lookup a class from an error library. The error propagates.
- cls = Dart_GetClass(Api::NewError("myerror"), NewString("Class"));
- EXPECT(Dart_IsError(cls));
- EXPECT_STREQ("myerror", Dart_GetError(cls));
+ type = Dart_GetType(Api::NewError("myerror"), NewString("Class"), 0, NULL);
+ EXPECT(Dart_IsError(type));
+ EXPECT_STREQ("myerror", Dart_GetError(type));
- // Lookup a class using an error class name. The error propagates.
- cls = Dart_GetClass(lib, Api::NewError("myerror"));
- EXPECT(Dart_IsError(cls));
- EXPECT_STREQ("myerror", Dart_GetError(cls));
+ // Lookup a type using an error class name. The error propagates.
+ type = Dart_GetType(lib, Api::NewError("myerror"), 0, NULL);
+ EXPECT(Dart_IsError(type));
+ EXPECT_STREQ("myerror", Dart_GetError(type));
}
@@ -5221,51 +5466,51 @@
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
// Fetch InstanceOfTest class.
- Dart_Handle cls = Dart_GetClass(lib, NewString("InstanceOfTest"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("InstanceOfTest"), 0, NULL);
+ EXPECT_VALID(type);
// Invoke a function which returns an object of type InstanceOf..
Dart_Handle instanceOfTestObj =
- Dart_Invoke(cls, NewString("testMain"), 0, NULL);
+ Dart_Invoke(type, NewString("testMain"), 0, NULL);
EXPECT_VALID(instanceOfTestObj);
// Now check instanceOfTestObj reported as an instance of
// InstanceOfTest class.
bool is_instance = false;
- result = Dart_ObjectIsType(instanceOfTestObj, cls, &is_instance);
+ result = Dart_ObjectIsType(instanceOfTestObj, type, &is_instance);
EXPECT_VALID(result);
EXPECT(is_instance);
// Fetch OtherClass and check if instanceOfTestObj is instance of it.
- Dart_Handle otherClass = Dart_GetClass(lib, NewString("OtherClass"));
- EXPECT_VALID(otherClass);
+ Dart_Handle otherType = Dart_GetType(lib, NewString("OtherClass"), 0, NULL);
+ EXPECT_VALID(otherType);
- result = Dart_ObjectIsType(instanceOfTestObj, otherClass, &is_instance);
+ result = Dart_ObjectIsType(instanceOfTestObj, otherType, &is_instance);
EXPECT_VALID(result);
EXPECT(!is_instance);
// Check that primitives are not instances of InstanceOfTest class.
- result = Dart_ObjectIsType(NewString("a string"), otherClass,
+ result = Dart_ObjectIsType(NewString("a string"), otherType,
&is_instance);
EXPECT_VALID(result);
EXPECT(!is_instance);
- result = Dart_ObjectIsType(Dart_NewInteger(42), otherClass, &is_instance);
+ result = Dart_ObjectIsType(Dart_NewInteger(42), otherType, &is_instance);
EXPECT_VALID(result);
EXPECT(!is_instance);
- result = Dart_ObjectIsType(Dart_NewBoolean(true), otherClass, &is_instance);
+ result = Dart_ObjectIsType(Dart_NewBoolean(true), otherType, &is_instance);
EXPECT_VALID(result);
EXPECT(!is_instance);
// Check that null is not an instance of InstanceOfTest class.
- Dart_Handle null = Dart_Invoke(otherClass,
+ Dart_Handle null = Dart_Invoke(otherType,
NewString("returnNull"),
0,
NULL);
EXPECT_VALID(null);
- result = Dart_ObjectIsType(null, otherClass, &is_instance);
+ result = Dart_ObjectIsType(null, otherType, &is_instance);
EXPECT_VALID(result);
EXPECT(!is_instance);
@@ -5968,9 +6213,9 @@
EXPECT(Dart_IsLibrary(lib));
// Call a dynamic function on OldClass.
- Dart_Handle cls = Dart_GetClass(lib, NewString("OldClass"));
- EXPECT_VALID(cls);
- Dart_Handle recv = Dart_New(cls, Dart_Null(), 0, NULL);
+ Dart_Handle type = Dart_GetType(lib, NewString("OldClass"), 0, NULL);
+ EXPECT_VALID(type);
+ Dart_Handle recv = Dart_New(type, Dart_Null(), 0, NULL);
Dart_Handle result = Dart_Invoke(recv, NewString("foo"), 0, NULL);
EXPECT_VALID(result);
EXPECT(Dart_IsString(result));
@@ -5984,9 +6229,9 @@
EXPECT_VALID(Dart_LoadSource(lib, url, source));
// Call a dynamic function on NewClass in the updated library.
- cls = Dart_GetClass(lib, NewString("NewClass"));
- EXPECT_VALID(cls);
- recv = Dart_New(cls, Dart_Null(), 0, NULL);
+ type = Dart_GetType(lib, NewString("NewClass"), 0, NULL);
+ EXPECT_VALID(type);
+ recv = Dart_New(type, Dart_Null(), 0, NULL);
result = Dart_Invoke(recv, NewString("bar"), 0, NULL);
EXPECT_VALID(result);
EXPECT(Dart_IsString(result));
@@ -6233,8 +6478,8 @@
Dart_Handle lib = Dart_LoadScript(url, source, 0, 0);
EXPECT_VALID(lib);
EXPECT(Dart_IsLibrary(lib));
- Dart_Handle cls = Dart_GetClass(lib, NewString("Test"));
- EXPECT_VALID(cls);
+ Dart_Handle type = Dart_GetType(lib, NewString("Test"), 0, NULL);
+ EXPECT_VALID(type);
result = Dart_SetNativeResolver(Dart_Null(), &MyNativeResolver1);
EXPECT(Dart_IsError(result));
@@ -6256,7 +6501,7 @@
EXPECT_VALID(result);
// Call a function and make sure native resolution works.
- result = Dart_Invoke(cls, NewString("foo"), 0, NULL);
+ result = Dart_Invoke(type, NewString("foo"), 0, NULL);
EXPECT_VALID(result);
EXPECT(Dart_IsInteger(result));
int64_t value = 0;
@@ -6268,7 +6513,7 @@
EXPECT_VALID(result);
// 'foo' has already been resolved so gets the old value.
- result = Dart_Invoke(cls, NewString("foo"), 0, NULL);
+ result = Dart_Invoke(type, NewString("foo"), 0, NULL);
EXPECT_VALID(result);
EXPECT(Dart_IsInteger(result));
value = 0;
@@ -6276,7 +6521,7 @@
EXPECT_EQ(654321, value);
// 'bar' has not yet been resolved so gets the new value.
- result = Dart_Invoke(cls, NewString("bar"), 0, NULL);
+ result = Dart_Invoke(type, NewString("bar"), 0, NULL);
EXPECT_VALID(result);
EXPECT(Dart_IsInteger(result));
value = 0;
@@ -6287,7 +6532,7 @@
result = Dart_SetNativeResolver(lib, NULL);
EXPECT_VALID(result);
- EXPECT_ERROR(Dart_Invoke(cls, NewString("baz"), 0, NULL),
+ EXPECT_ERROR(Dart_Invoke(type, NewString("baz"), 0, NULL),
"native function 'SomeNativeFunction3' cannot be found");
}
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 3d77b54..561aea6 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -236,7 +236,7 @@
descriptor.SetAt(insert_index + kPositionOffset, pos);
}
// Set terminating null.
- descriptor.SetAt(descriptor_len - 1, Object::Handle());
+ descriptor.SetAt(descriptor_len - 1, Object::null_object());
// Share the immutable descriptor when possible by canonicalizing it.
descriptor.MakeImmutable();
@@ -271,7 +271,7 @@
descriptor.SetAt(kPositionalCountIndex, arg_count);
// Set terminating null.
- descriptor.SetAt((descriptor_len - 1), Object::Handle());
+ descriptor.SetAt((descriptor_len - 1), Object::null_object());
// Share the immutable descriptor when possible by canonicalizing it.
descriptor.MakeImmutable();
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 8b82f4c..c5cb5da 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -585,7 +585,8 @@
static bool IsSafePoint(PcDescriptors::Kind kind) {
return ((kind == PcDescriptors::kIcCall) ||
- (kind == PcDescriptors::kFuncCall) ||
+ (kind == PcDescriptors::kOptStaticCall) ||
+ (kind == PcDescriptors::kUnoptStaticCall) ||
(kind == PcDescriptors::kClosureCall) ||
(kind == PcDescriptors::kReturn) ||
(kind == PcDescriptors::kRuntimeCall));
@@ -658,12 +659,12 @@
const Code& code =
Code::Handle(Function::Handle(function_).unoptimized_code());
saved_bytes_.target_address_ =
- CodePatcher::GetInstanceCallAt(pc_, code, NULL, NULL);
+ CodePatcher::GetInstanceCallAt(pc_, code, NULL);
CodePatcher::PatchInstanceCallAt(pc_, code,
StubCode::BreakpointDynamicEntryPoint());
break;
}
- case PcDescriptors::kFuncCall: {
+ case PcDescriptors::kUnoptStaticCall: {
const Code& code =
Code::Handle(Function::Handle(function_).unoptimized_code());
saved_bytes_.target_address_ =
@@ -702,7 +703,7 @@
saved_bytes_.target_address_);
break;
}
- case PcDescriptors::kFuncCall:
+ case PcDescriptors::kUnoptStaticCall:
case PcDescriptors::kClosureCall:
case PcDescriptors::kRuntimeCall: {
const Code& code =
@@ -1178,6 +1179,7 @@
MakeCodeBreakpointsAt(closure, breakpoint_pos, source_bpt);
}
source_bpt->Enable();
+ SignalBpResolved(source_bpt);
return source_bpt;
}
@@ -1494,7 +1496,8 @@
if ((fkind == RawFunction::kImplicitGetter) ||
(fkind == RawFunction::kImplicitSetter) ||
(fkind == RawFunction::kConstImplicitGetter) ||
- (fkind == RawFunction::kMethodExtractor)) {
+ (fkind == RawFunction::kMethodExtractor) ||
+ (fkind == RawFunction::kNoSuchMethodDispatcher)) {
return false;
}
const Class& cls = Class::Handle(func.Owner());
@@ -1564,30 +1567,29 @@
if (bpt->breakpoint_kind_ == PcDescriptors::kIcCall) {
func_to_instrument = bpt->function();
ICData& ic_data = ICData::Handle();
- Array& descriptor = Array::Handle();
const Code& code =
Code::Handle(Function::Handle(bpt->function_).unoptimized_code());
- CodePatcher::GetInstanceCallAt(bpt->pc_, code, &ic_data, &descriptor);
- ArgumentsDescriptor arg_descriptor(descriptor);
+ CodePatcher::GetInstanceCallAt(bpt->pc_, code, &ic_data);
+ ArgumentsDescriptor
+ args_descriptor(Array::Handle(ic_data.arguments_descriptor()));
ActivationFrame* top_frame = stack_trace->ActivationFrameAt(0);
- intptr_t num_args = arg_descriptor.Count();
+ intptr_t num_args = args_descriptor.Count();
Instance& receiver =
Instance::Handle(top_frame->GetInstanceCallReceiver(num_args));
Code& target_code =
- Code::Handle(ResolveCompileInstanceCallTarget(receiver,
- ic_data,
- descriptor));
+ Code::Handle(ResolveCompileInstanceCallTarget(receiver, ic_data));
if (!target_code.IsNull()) {
Function& callee = Function::Handle(target_code.function());
if (IsDebuggable(callee)) {
func_to_instrument = callee.raw();
}
}
- } else if (bpt->breakpoint_kind_ == PcDescriptors::kFuncCall) {
+ } else if (bpt->breakpoint_kind_ == PcDescriptors::kUnoptStaticCall) {
func_to_instrument = bpt->function();
const Code& code = Code::Handle(func_to_instrument.CurrentCode());
- const Function& callee =
- Function::Handle(code.GetStaticCallTargetFunctionAt(bpt->pc_));
+ ASSERT(!code.is_optimized());
+ const Function& callee = Function::Handle(
+ CodePatcher::GetUnoptimizedStaticCallAt(bpt->pc_, code, NULL));
ASSERT(!callee.IsNull());
if (IsDebuggable(callee)) {
func_to_instrument = callee.raw();
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index d194c3c..9d22b64 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -280,7 +280,7 @@
// If the deoptimization happened at an IC call, update the IC data
// to avoid repeated deoptimization at the same site next time around.
ICData& ic_data = ICData::Handle();
- CodePatcher::GetInstanceCallAt(pc, code, &ic_data, NULL);
+ CodePatcher::GetInstanceCallAt(pc, code, &ic_data);
if (!ic_data.IsNull()) {
ic_data.set_deopt_reason(deopt_context->deopt_reason());
}
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index 3200439..ddef528 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -16,13 +16,8 @@
TEST_CASE(FindCodeObject) {
#if defined(TARGET_ARCH_IA32)
const int kLoopCount = 50000;
-#elif defined(TARGET_ARCH_X64)
- const int kLoopCount = 25000;
-#elif defined(TARGET_ARCH_MIPS)
- // TODO(zra): Increase after we implement far branches on MIPS.
- const int kLoopCount = 1818;
#else
- const int kLoopCount = 20000;
+ const int kLoopCount = 25000;
#endif
const int kScriptSize = 512 * KB;
const int kNumFunctions = 1024;
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index 5963f70..1003af0 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -955,11 +955,9 @@
// Find the natural loop for the back edge m->n and attach loop information
// to block n (loop header). The algorithm is described in "Advanced Compiler
// Design & Implementation" (Muchnick) p192.
-static void FindLoop(BlockEntryInstr* m,
- BlockEntryInstr* n,
- intptr_t num_blocks) {
+void FlowGraph::FindLoop(BlockEntryInstr* m, BlockEntryInstr* n) {
GrowableArray<BlockEntryInstr*> stack;
- BitVector* loop = new BitVector(num_blocks);
+ BitVector* loop = new BitVector(preorder_.length());
loop->Add(n->preorder_number());
if (n != m) {
@@ -980,7 +978,7 @@
n->set_loop_info(loop);
if (FLAG_trace_optimization) {
for (BitVector::Iterator it(loop); !it.Done(); it.Advance()) {
- OS::Print(" B%"Pd"\n", it.Current());
+ OS::Print(" B%"Pd"\n", preorder_[it.Current()]->block_id());
}
}
}
@@ -1001,7 +999,7 @@
OS::Print("Back edge B%"Pd" -> B%"Pd"\n", pred->block_id(),
block->block_id());
}
- FindLoop(pred, block, preorder_.length());
+ FindLoop(pred, block);
loop_headers->Add(block);
}
}
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h
index 8ed08c8..615cef1 100644
--- a/runtime/vm/flow_graph.h
+++ b/runtime/vm/flow_graph.h
@@ -218,6 +218,11 @@
void ReplacePredecessor(BlockEntryInstr* old_block,
BlockEntryInstr* new_block);
+ // Find the natural loop for the back edge m->n and attach loop
+ // information to block n (loop header). The algorithm is described in
+ // "Advanced Compiler Design & Implementation" (Muchnick) p192.
+ void FindLoop(BlockEntryInstr* m, BlockEntryInstr* n);
+
// Finds natural loops in the flow graph and attaches a list of loop
// body blocks for each loop header.
ZoneGrowableArray<BlockEntryInstr*>* ComputeLoops();
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index d878f8d..c63b362 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -60,6 +60,12 @@
}
+static intptr_t NextInstructionPos(intptr_t pos) {
+ ASSERT(IsInstructionStartPosition(pos));
+ return pos + 2;
+}
+
+
FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph)
: flow_graph_(flow_graph),
reaching_defs_(flow_graph),
@@ -512,6 +518,16 @@
range->DefineAt(catch_entry->start_pos()); // Defined at block entry.
ProcessInitialDefinition(defn, range, catch_entry);
}
+ // Block the two registers used by CatchEntryInstr from the block start to
+ // until the end of the instruction so that they are preserved.
+ ASSERT(catch_entry->next()->IsCatchEntry());
+ intptr_t start = catch_entry->start_pos();
+ BlockLocation(Location::RegisterLocation(kExceptionObjectReg),
+ start,
+ ToInstructionEnd(NextInstructionPos(start)));
+ BlockLocation(Location::RegisterLocation(kStackTraceObjectReg),
+ start,
+ ToInstructionEnd(NextInstructionPos(start)));
}
}
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index ed23d28..36088d9 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -59,6 +59,7 @@
context_level_(0),
last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
try_index_(CatchClauseNode::kInvalidTryIndex),
+ loop_depth_(0),
graph_entry_(NULL),
args_pushed_(0),
osr_id_(osr_id) { }
@@ -499,7 +500,7 @@
JoinEntryInstr* join =
new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
CheckStackOverflowInstr* check =
- new CheckStackOverflowInstr(token_pos, true);
+ new CheckStackOverflowInstr(token_pos, owner()->loop_depth());
join->LinkTo(check);
check->LinkTo(test_fragment.entry());
Goto(join);
@@ -978,7 +979,7 @@
name,
node->kind(),
arguments,
- Array::ZoneHandle(),
+ Object::null_array(),
2,
owner()->ic_data_array());
ReturnDefinition(call);
@@ -1222,7 +1223,7 @@
PrivateCoreLibName(Symbols::_instanceOf()),
node->kind(),
arguments,
- Array::ZoneHandle(), // No argument names.
+ Object::null_array(), // No argument names.
kNumArgsChecked,
owner()->ic_data_array());
ReturnDefinition(call);
@@ -1292,7 +1293,7 @@
PrivateCoreLibName(Symbols::_as()),
node->kind(),
arguments,
- Array::ZoneHandle(), // No argument names.
+ Object::null_array(), // No argument names.
kNumArgsChecked,
owner()->ic_data_array());
ReturnDefinition(call);
@@ -1406,7 +1407,7 @@
Symbols::New(Token::Str(node->kind()))),
node->kind(),
arguments,
- Array::ZoneHandle(),
+ Object::null_array(),
1,
owner()->ic_data_array());
ReturnDefinition(call);
@@ -1601,6 +1602,7 @@
// f) loop-exit-target
// g) break-join (optional)
void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
+ owner()->IncrementLoopDepth();
TestGraphVisitor for_test(owner(),
temp_index(),
node->condition()->token_pos());
@@ -1624,6 +1626,7 @@
Goto(join);
exit_ = join;
}
+ owner()->DecrementLoopDepth();
}
@@ -1636,6 +1639,7 @@
// f) loop-exit-target
// g) break-join
void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
+ owner()->IncrementLoopDepth();
// Traverse body first in order to generate continue and break labels.
EffectGraphVisitor for_body(owner(), temp_index());
node->body()->Visit(&for_body);
@@ -1660,7 +1664,7 @@
owner()->try_index());
}
CheckStackOverflowInstr* check =
- new CheckStackOverflowInstr(node->token_pos(), true);
+ new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth());
join->LinkTo(check);
check->LinkTo(for_test.entry());
if (body_exit != NULL) {
@@ -1676,6 +1680,7 @@
for_test.IfFalseGoto(join);
exit_ = join;
}
+ owner()->DecrementLoopDepth();
}
@@ -1697,6 +1702,7 @@
Append(for_initializer);
ASSERT(is_open());
+ owner()->IncrementLoopDepth();
// Compose body to set any jump labels.
EffectGraphVisitor for_body(owner(), temp_index());
node->body()->Visit(&for_body);
@@ -1719,7 +1725,8 @@
}
Goto(loop_entry);
exit_ = loop_entry;
- AddInstruction(new CheckStackOverflowInstr(node->token_pos(), true));
+ AddInstruction(
+ new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth()));
}
if (node->condition() == NULL) {
@@ -1743,6 +1750,7 @@
exit_ = node->label()->join_for_break();
}
}
+ owner()->DecrementLoopDepth();
}
@@ -2106,7 +2114,8 @@
new StaticCallInstr(node->token_pos(),
node->function(),
node->arguments()->names(),
- arguments);
+ arguments,
+ owner()->ic_data_array());
if (node->function().is_native()) {
const intptr_t result_cid = GetResultCidOfNative(node->function());
call->set_result_cid(result_cid);
@@ -2216,7 +2225,8 @@
Do(new StaticCallInstr(node->token_pos(),
node->constructor(),
node->arguments()->names(),
- arguments));
+ arguments,
+ owner()->ic_data_array()));
}
@@ -2284,7 +2294,8 @@
new StaticCallInstr(node->token_pos(),
node->constructor(),
node->arguments()->names(),
- arguments);
+ arguments,
+ owner()->ic_data_array());
const intptr_t result_cid = GetResultCidOfListFactory(node);
if (result_cid != kDynamicCid) {
call->set_result_cid(result_cid);
@@ -2512,7 +2523,7 @@
node->token_pos(),
name,
Token::kGET,
- arguments, Array::ZoneHandle(),
+ arguments, Object::null_array(),
1,
owner()->ic_data_array());
ReturnDefinition(call);
@@ -2552,7 +2563,7 @@
name,
Token::kSET,
arguments,
- Array::ZoneHandle(),
+ Object::null_array(),
2, // Checked arg count.
owner()->ic_data_array());
ReturnDefinition(call);
@@ -2569,7 +2580,7 @@
name,
Token::kSET,
arguments,
- Array::ZoneHandle(),
+ Object::null_array(),
2, // Checked argument count.
owner()->ic_data_array()));
ReturnDefinition(BuildLoadExprTemp());
@@ -2638,8 +2649,9 @@
ASSERT(!getter_function.IsNull());
StaticCallInstr* call = new StaticCallInstr(node->token_pos(),
getter_function,
- Array::ZoneHandle(), // No names.
- arguments);
+ Object::null_array(), // No names
+ arguments,
+ owner()->ic_data_array());
ReturnDefinition(call);
}
@@ -2705,8 +2717,9 @@
call = new StaticCallInstr(node->token_pos(),
setter_function,
- Array::ZoneHandle(), // No names.
- arguments);
+ Object::null_array(), // No names.
+ arguments,
+ owner()->ic_data_array());
}
if (result_is_needed) {
Do(call);
@@ -2926,8 +2939,9 @@
// Generate static call to super operator.
StaticCallInstr* load = new StaticCallInstr(node->token_pos(),
*super_function,
- Array::ZoneHandle(),
- arguments);
+ Object::null_array(),
+ arguments,
+ owner()->ic_data_array());
ReturnDefinition(load);
} else {
// Generate dynamic call to index operator.
@@ -2936,7 +2950,7 @@
Symbols::IndexToken(),
Token::kINDEX,
arguments,
- Array::ZoneHandle(),
+ Object::null_array(),
checked_argument_count,
owner()->ic_data_array());
ReturnDefinition(load);
@@ -3005,8 +3019,9 @@
StaticCallInstr* store =
new StaticCallInstr(node->token_pos(),
*super_function,
- Array::ZoneHandle(),
- arguments);
+ Object::null_array(),
+ arguments,
+ owner()->ic_data_array());
if (result_is_needed) {
Do(store);
return BuildLoadExprTemp();
@@ -3023,7 +3038,7 @@
name,
Token::kASSIGN_INDEX,
arguments,
- Array::ZoneHandle(),
+ Object::null_array(),
checked_argument_count,
owner()->ic_data_array());
if (result_is_needed) {
@@ -3317,8 +3332,9 @@
BuildPushArguments(*args, push_arguments);
return new StaticCallInstr(args_pos,
no_such_method_func,
- Array::ZoneHandle(),
- push_arguments);
+ Object::null_array(),
+ push_arguments,
+ owner()->ic_data_array());
}
StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError(
intptr_t token_pos,
@@ -3368,13 +3384,14 @@
Resolver::ResolveStatic(cls,
PrivateCoreLibName(Symbols::ThrowNew()),
arguments->length(),
- Array::ZoneHandle(),
+ Object::null_array(),
Resolver::kIsQualified));
ASSERT(!func.IsNull());
return new StaticCallInstr(token_pos,
func,
- Array::ZoneHandle(), // No names.
- arguments);
+ Object::null_array(), // No names.
+ arguments,
+ owner()->ic_data_array());
}
@@ -3458,7 +3475,7 @@
EffectGraphVisitor for_effect(this, 0);
// This check may be deleted if the generated code is leaf.
CheckStackOverflowInstr* check =
- new CheckStackOverflowInstr(function.token_pos(), false);
+ new CheckStackOverflowInstr(function.token_pos(), 0);
// If we are inlining don't actually attach the stack check. We must still
// create the stack check in order to allocate a deopt id.
if (!IsInlining()) for_effect.AddInstruction(check);
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h
index 2ae1401..3afcb09 100644
--- a/runtime/vm/flow_graph_builder.h
+++ b/runtime/vm/flow_graph_builder.h
@@ -120,6 +120,10 @@
void set_context_level(intptr_t value) { context_level_ = value; }
intptr_t context_level() const { return context_level_; }
+ void IncrementLoopDepth() { ++loop_depth_; }
+ void DecrementLoopDepth() { --loop_depth_; }
+ intptr_t loop_depth() const { return loop_depth_; }
+
// Each try in this function gets its own try index.
intptr_t AllocateTryIndex() { return ++last_used_try_index_; }
@@ -169,6 +173,7 @@
intptr_t context_level_;
intptr_t last_used_try_index_;
intptr_t try_index_;
+ intptr_t loop_depth_;
GraphEntryInstr* graph_entry_;
// Outgoing argument stack height.
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 07cc65a..e7f063c 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -30,6 +30,7 @@
DECLARE_FLAG(bool, report_usage_count);
DECLARE_FLAG(int, optimization_counter_threshold);
DECLARE_FLAG(bool, use_cha);
+DECLARE_FLAG(bool, use_osr);
// Assign locations to incoming arguments, i.e., values pushed above spill slots
@@ -164,6 +165,11 @@
}
+bool FlowGraphCompiler::CanOSRFunction() const {
+ return FLAG_use_osr & CanOptimizeFunction() && !is_optimizing();
+}
+
+
static bool IsEmptyBlock(BlockEntryInstr* block) {
return !block->HasParallelMove() &&
block->next()->IsGoto() &&
@@ -461,7 +467,7 @@
void FlowGraphCompiler::FinalizeStackmaps(const Code& code) {
if (stackmap_table_builder_ == NULL) {
// The unoptimizing compiler has no stack maps.
- code.set_stackmaps(Array::Handle());
+ code.set_stackmaps(Object::null_array());
} else {
// Finalize the stack map array and add it to the code object.
ASSERT(is_optimizing());
@@ -540,9 +546,6 @@
const ICData& ic_data) {
ASSERT(!ic_data.IsNull());
ASSERT(FLAG_propagate_ic_data || (ic_data.NumberOfChecks() == 0));
- const Array& arguments_descriptor =
- Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
- argument_names));
uword label_address = 0;
if (is_optimizing() && (ic_data.NumberOfChecks() == 0)) {
if (ic_data.is_closure_call()) {
@@ -551,8 +554,7 @@
ExternalLabel target_label("InlineCache", label_address);
EmitInstanceCall(&target_label,
ICData::ZoneHandle(ic_data.AsUnaryClassChecks()),
- arguments_descriptor, argument_count,
- deopt_id, token_pos, locs);
+ argument_count, deopt_id, token_pos, locs);
return;
}
// Emit IC call that will count and thus may need reoptimization at
@@ -575,13 +577,13 @@
UNIMPLEMENTED();
}
ExternalLabel target_label("InlineCache", label_address);
- EmitOptimizedInstanceCall(&target_label, ic_data, arguments_descriptor,
+ EmitOptimizedInstanceCall(&target_label, ic_data,
argument_count, deopt_id, token_pos, locs);
return;
}
if (is_optimizing()) {
- EmitMegamorphicInstanceCall(ic_data, arguments_descriptor, argument_count,
+ EmitMegamorphicInstanceCall(ic_data, argument_count,
deopt_id, token_pos, locs);
return;
}
@@ -600,7 +602,7 @@
UNIMPLEMENTED();
}
ExternalLabel target_label("InlineCache", label_address);
- EmitInstanceCall(&target_label, ic_data, arguments_descriptor, argument_count,
+ EmitInstanceCall(&target_label, ic_data, argument_count,
deopt_id, token_pos, locs);
}
@@ -614,8 +616,13 @@
const Array& arguments_descriptor =
Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
argument_names));
- EmitStaticCall(function, arguments_descriptor, argument_count,
- deopt_id, token_pos, locs);
+ if (is_optimizing()) {
+ EmitOptimizedStaticCall(function, arguments_descriptor, argument_count,
+ deopt_id, token_pos, locs);
+ } else {
+ EmitUnoptimizedStaticCall(function, arguments_descriptor, argument_count,
+ deopt_id, token_pos, locs);
+ }
}
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 6dbcaa4..4759b25 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -258,6 +258,7 @@
}
static bool CanOptimize();
bool CanOptimizeFunction() const;
+ bool CanOSRFunction() const;
bool is_optimizing() const { return is_optimizing_; }
const GrowableArray<BlockInfo*>& block_info() const { return block_info_; }
@@ -336,7 +337,6 @@
void EmitOptimizedInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
@@ -344,14 +344,12 @@
void EmitInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs);
void EmitMegamorphicInstanceCall(const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
@@ -481,12 +479,19 @@
// Emit code to load a Value into register 'dst'.
void LoadValue(Register dst, Value* value);
- void EmitStaticCall(const Function& function,
- const Array& arguments_descriptor,
- intptr_t argument_count,
- intptr_t deopt_id,
- intptr_t token_pos,
- LocationSummary* locs);
+ void EmitOptimizedStaticCall(const Function& function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs);
+
+ void EmitUnoptimizedStaticCall(const Function& function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs);
// Type checking helper methods.
void CheckClassIds(Register class_id_reg,
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index eab7bc6..ce260cf 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -910,7 +910,8 @@
function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked));
+ ICData::New(function, name, Object::null_array(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(R5, ic_data);
// FP - 4 : saved PP, object pool pointer of caller.
// FP + 0 : previous frame pointer.
@@ -1067,7 +1068,8 @@
ASSERT(!parsed_function().function().HasOptionalParameters());
const bool check_arguments = true;
#else
- const bool check_arguments = function.IsClosureFunction();
+ const bool check_arguments =
+ function.IsClosureFunction() || function.IsNoSuchMethodDispatcher();
#endif
if (check_arguments) {
__ Comment("Check argument count");
@@ -1081,7 +1083,7 @@
__ cmp(R0, ShifterOperand(R1));
__ b(&correct_num_arguments, EQ);
__ Bind(&wrong_num_arguments);
- if (function.IsClosureFunction()) {
+ if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
if (StackSize() != 0) {
// We need to unwind the space we reserved for locals and copied
// parameters. The NoSuchMethodFunction stub does not expect to see
@@ -1092,10 +1094,15 @@
// dropped the spill slots.
BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
- // Invoke noSuchMethod function passing "call" as the function name.
+ // Invoke noSuchMethod function passing the original function name.
+ // For closure functions, use "call" as the original name.
+ const String& name =
+ String::Handle(function.IsClosureFunction()
+ ? Symbols::Call().raw()
+ : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, Symbols::Call(),
+ ICData::New(function, name, Object::null_array(),
Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(R5, ic_data);
// FP - 4 : saved PP, object pool pointer of caller.
@@ -1238,7 +1245,6 @@
void FlowGraphCompiler::EmitOptimizedInstanceCall(
ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
@@ -1249,8 +1255,8 @@
// top-level function (parsed_function().function()) which could be
// reoptimized and which counter needs to be incremented.
// Pass the function explicitly, it is used in IC stub.
+
__ LoadObject(R6, parsed_function().function());
- __ LoadObject(R4, arguments_descriptor);
__ LoadObject(R5, ic_data);
GenerateDartCall(deopt_id,
token_pos,
@@ -1263,12 +1269,10 @@
void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
- __ LoadObject(R4, arguments_descriptor);
__ LoadObject(R5, ic_data);
GenerateDartCall(deopt_id,
token_pos,
@@ -1281,13 +1285,15 @@
void FlowGraphCompiler::EmitMegamorphicInstanceCall(
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(ic_data.target_name());
+ const Array& arguments_descriptor =
+ Array::ZoneHandle(ic_data.arguments_descriptor());
+ ASSERT(!arguments_descriptor.IsNull());
const MegamorphicCache& cache =
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
Label not_smi, load_cache;
@@ -1348,25 +1354,50 @@
}
-void FlowGraphCompiler::EmitStaticCall(const Function& function,
- const Array& arguments_descriptor,
- intptr_t argument_count,
- intptr_t deopt_id,
- intptr_t token_pos,
- LocationSummary* locs) {
+void FlowGraphCompiler::EmitOptimizedStaticCall(
+ const Function& function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
__ LoadObject(R4, arguments_descriptor);
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
GenerateDartCall(deopt_id,
token_pos,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
AddStaticCallTarget(function);
__ Drop(argument_count);
}
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+ const Function& target_function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(parsed_function().function(), // Caller function.
+ String::Handle(target_function.name()),
+ arguments_descriptor,
+ deopt_id,
+ 0)); // No arguments checked.
+ ic_data.AddTarget(target_function);
+ __ LoadObject(R5, ic_data);
+ GenerateDartCall(deopt_id,
+ token_pos,
+ &StubCode::UnoptimizedStaticCallLabel(),
+ PcDescriptors::kUnoptStaticCall,
+ locs);
+ __ Drop(argument_count);
+}
+
+
void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
const Object& obj,
bool needs_number_check,
@@ -1495,6 +1526,7 @@
intptr_t deopt_id,
intptr_t token_index,
LocationSummary* locs) {
+ ASSERT(is_optimizing());
ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
Label match_found;
const intptr_t len = ic_data.NumberOfChecks();
@@ -1520,7 +1552,7 @@
GenerateDartCall(deopt_id,
token_index,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
const Function& function = *sorted[i].target;
AddStaticCallTarget(function);
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index fe154c7..6504aa6 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1008,7 +1008,8 @@
function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked));
+ ICData::New(function, name, Object::null_array(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(ECX, ic_data);
// EBP - 4 : PC marker, allows easy identification of RawInstruction obj.
// EBP : points to previous frame pointer.
@@ -1149,7 +1150,8 @@
const bool check_arguments = !flow_graph().IsCompiledForOsr();
#else
const bool check_arguments =
- function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
+ (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) &&
+ !flow_graph().IsCompiledForOsr();
#endif
if (check_arguments) {
__ Comment("Check argument count");
@@ -1164,7 +1166,7 @@
__ j(EQUAL, &correct_num_arguments, Assembler::kNearJump);
__ Bind(&wrong_num_arguments);
- if (function.IsClosureFunction()) {
+ if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
if (StackSize() != 0) {
// We need to unwind the space we reserved for locals and copied
// parameters. The NoSuchMethodFunction stub does not expect to see
@@ -1175,10 +1177,15 @@
// dropped the spill slots.
BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
- // Invoke noSuchMethod function passing "call" as the function name.
+ // Invoke noSuchMethod function passing the original function name.
+ // For closure functions, use "call" as the original name.
+ const String& name =
+ String::Handle(function.IsClosureFunction()
+ ? Symbols::Call().raw()
+ : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, Symbols::Call(),
+ ICData::New(function, name, Object::null_array(),
Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(ECX, ic_data);
// EBP - 4 : PC marker, for easy identification of RawInstruction obj.
@@ -1320,7 +1327,6 @@
void FlowGraphCompiler::EmitOptimizedInstanceCall(
ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
@@ -1333,7 +1339,6 @@
// Pass the function explicitly, it is used in IC stub.
__ LoadObject(EDI, parsed_function().function());
__ LoadObject(ECX, ic_data);
- __ LoadObject(EDX, arguments_descriptor);
GenerateDartCall(deopt_id,
token_pos,
target_label,
@@ -1345,13 +1350,11 @@
void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
__ LoadObject(ECX, ic_data);
- __ LoadObject(EDX, arguments_descriptor);
GenerateDartCall(deopt_id,
token_pos,
target_label,
@@ -1363,13 +1366,15 @@
void FlowGraphCompiler::EmitMegamorphicInstanceCall(
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(ic_data.target_name());
+ const Array& arguments_descriptor =
+ Array::ZoneHandle(ic_data.arguments_descriptor());
+ ASSERT(!arguments_descriptor.IsNull());
const MegamorphicCache& cache =
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
Label not_smi, load_cache;
@@ -1428,25 +1433,50 @@
}
-void FlowGraphCompiler::EmitStaticCall(const Function& function,
- const Array& arguments_descriptor,
- intptr_t argument_count,
- intptr_t deopt_id,
- intptr_t token_pos,
- LocationSummary* locs) {
+void FlowGraphCompiler::EmitOptimizedStaticCall(
+ const Function& function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
__ LoadObject(EDX, arguments_descriptor);
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
GenerateDartCall(deopt_id,
token_pos,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
AddStaticCallTarget(function);
__ Drop(argument_count);
}
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+ const Function& target_function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(parsed_function().function(), // Caller function.
+ String::Handle(target_function.name()),
+ arguments_descriptor,
+ deopt_id,
+ 0)); // No arguments checked.
+ ic_data.AddTarget(target_function);
+ __ LoadObject(ECX, ic_data);
+ GenerateDartCall(deopt_id,
+ token_pos,
+ &StubCode::UnoptimizedStaticCallLabel(),
+ PcDescriptors::kUnoptStaticCall,
+ locs);
+ __ Drop(argument_count);
+}
+
+
void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
const Object& obj,
bool needs_number_check,
@@ -1592,6 +1622,7 @@
intptr_t deopt_id,
intptr_t token_index,
LocationSummary* locs) {
+ ASSERT(is_optimizing());
ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
Label match_found;
const intptr_t len = ic_data.NumberOfChecks();
@@ -1617,7 +1648,7 @@
GenerateDartCall(deopt_id,
token_index,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
const Function& function = *sorted[i].target;
AddStaticCallTarget(function);
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index a088cc6..2177423 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -936,7 +936,8 @@
function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked));
+ ICData::New(function, name, Object::null_array(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(S5, ic_data);
// FP - 4 : saved PP, object pool pointer of caller.
// FP + 0 : previous frame pointer.
@@ -1116,7 +1117,8 @@
ASSERT(!parsed_function().function().HasOptionalParameters());
const bool check_arguments = true;
#else
- const bool check_arguments = function.IsClosureFunction();
+ const bool check_arguments =
+ function.IsClosureFunction() || function.IsNoSuchMethodDispatcher();
#endif
if (check_arguments) {
__ TraceSimMsg("Check argument count");
@@ -1131,7 +1133,7 @@
ArgumentsDescriptor::positional_count_offset()));
__ beq(T0, T1, &correct_num_arguments);
__ Bind(&wrong_num_arguments);
- if (function.IsClosureFunction()) {
+ if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
if (StackSize() != 0) {
// We need to unwind the space we reserved for locals and copied
// parameters. The NoSuchMethodFunction stub does not expect to see
@@ -1142,10 +1144,15 @@
// dropped the spill slots.
BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
- // Invoke noSuchMethod function passing "call" as the function name.
+ // Invoke noSuchMethod function passing the original function name.
+ // For closure functions, use "call" as the original name.
+ const String& name =
+ String::Handle(function.IsClosureFunction()
+ ? Symbols::Call().raw()
+ : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, Symbols::Call(),
+ ICData::New(function, name, Object::null_array(),
Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(S5, ic_data);
// FP - 4 : saved PP, object pool pointer of caller.
@@ -1290,7 +1297,6 @@
void FlowGraphCompiler::EmitOptimizedInstanceCall(
ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
@@ -1303,7 +1309,6 @@
// Pass the function explicitly, it is used in IC stub.
__ TraceSimMsg("OptimizedInstanceCall");
__ LoadObject(T0, parsed_function().function());
- __ LoadObject(S4, arguments_descriptor);
__ LoadObject(S5, ic_data);
GenerateDartCall(deopt_id,
token_pos,
@@ -1316,13 +1321,11 @@
void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
__ TraceSimMsg("InstanceCall");
- __ LoadObject(S4, arguments_descriptor);
__ LoadObject(S5, ic_data);
GenerateDartCall(deopt_id,
token_pos,
@@ -1336,13 +1339,15 @@
void FlowGraphCompiler::EmitMegamorphicInstanceCall(
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(ic_data.target_name());
+ const Array& arguments_descriptor =
+ Array::ZoneHandle(ic_data.arguments_descriptor());
+ ASSERT(!arguments_descriptor.IsNull());
const MegamorphicCache& cache =
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
Label not_smi, load_cache;
@@ -1404,12 +1409,13 @@
}
-void FlowGraphCompiler::EmitStaticCall(const Function& function,
- const Array& arguments_descriptor,
- intptr_t argument_count,
- intptr_t deopt_id,
- intptr_t token_pos,
- LocationSummary* locs) {
+void FlowGraphCompiler::EmitOptimizedStaticCall(
+ const Function& function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
__ TraceSimMsg("StaticCall");
__ LoadObject(S4, arguments_descriptor);
// Do not use the code from the function, but let the code be patched so that
@@ -1417,13 +1423,37 @@
GenerateDartCall(deopt_id,
token_pos,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
AddStaticCallTarget(function);
__ Drop(argument_count);
}
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+ const Function& target_function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(parsed_function().function(), // Caller function.
+ String::Handle(target_function.name()),
+ arguments_descriptor,
+ deopt_id,
+ 0)); // No arguments checked.
+ ic_data.AddTarget(target_function);
+ __ LoadObject(S5, ic_data);
+ GenerateDartCall(deopt_id,
+ token_pos,
+ &StubCode::UnoptimizedStaticCallLabel(),
+ PcDescriptors::kUnoptStaticCall,
+ locs);
+ __ Drop(argument_count);
+}
+
+
void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
const Object& obj,
bool needs_number_check,
@@ -1579,6 +1609,7 @@
intptr_t deopt_id,
intptr_t token_index,
LocationSummary* locs) {
+ ASSERT(is_optimizing());
ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
Label match_found;
const intptr_t len = ic_data.NumberOfChecks();
@@ -1605,7 +1636,7 @@
GenerateDartCall(deopt_id,
token_index,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
const Function& function = *sorted[i].target;
AddStaticCallTarget(function);
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index df39bc48..6190bb1 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -1002,7 +1002,8 @@
function.IsClosureFunction() ? Symbols::Call().raw() : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, name, Isolate::kNoDeoptId, kNumArgsChecked));
+ ICData::New(function, name, Object::null_array(),
+ Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(RBX, ic_data);
// RBP - 8 : PC marker, allows easy identification of RawInstruction obj.
// RBP : points to previous frame pointer.
@@ -1144,7 +1145,8 @@
const bool check_arguments = !flow_graph().IsCompiledForOsr();
#else
const bool check_arguments =
- function.IsClosureFunction() && !flow_graph().IsCompiledForOsr();
+ (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) &&
+ !flow_graph().IsCompiledForOsr();
#endif
if (check_arguments) {
__ Comment("Check argument count");
@@ -1159,7 +1161,7 @@
__ j(EQUAL, &correct_num_arguments, Assembler::kNearJump);
__ Bind(&wrong_num_arguments);
- if (function.IsClosureFunction()) {
+ if (function.IsClosureFunction() || function.IsNoSuchMethodDispatcher()) {
if (StackSize() != 0) {
// We need to unwind the space we reserved for locals and copied
// parameters. The NoSuchMethodFunction stub does not expect to see
@@ -1170,10 +1172,15 @@
// dropped the spill slots.
BitmapBuilder* empty_stack_bitmap = new BitmapBuilder();
- // Invoke noSuchMethod function passing "call" as the function name.
+ // Invoke noSuchMethod function passing the original function name.
+ // For closure functions, use "call" as the original name.
+ const String& name =
+ String::Handle(function.IsClosureFunction()
+ ? Symbols::Call().raw()
+ : function.name());
const int kNumArgsChecked = 1;
const ICData& ic_data = ICData::ZoneHandle(
- ICData::New(function, Symbols::Call(),
+ ICData::New(function, name, Object::null_array(),
Isolate::kNoDeoptId, kNumArgsChecked));
__ LoadObject(RBX, ic_data);
// RBP - 8 : PC marker, for easy identification of RawInstruction obj.
@@ -1315,7 +1322,6 @@
void FlowGraphCompiler::EmitOptimizedInstanceCall(
ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
@@ -1328,7 +1334,6 @@
// Pass the function explicitly, it is used in IC stub.
__ LoadObject(RDI, parsed_function().function());
__ LoadObject(RBX, ic_data);
- __ LoadObject(R10, arguments_descriptor);
GenerateDartCall(deopt_id,
token_pos,
target_label,
@@ -1340,13 +1345,11 @@
void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
__ LoadObject(RBX, ic_data);
- __ LoadObject(R10, arguments_descriptor);
GenerateDartCall(deopt_id,
token_pos,
target_label,
@@ -1358,13 +1361,15 @@
void FlowGraphCompiler::EmitMegamorphicInstanceCall(
const ICData& ic_data,
- const Array& arguments_descriptor,
intptr_t argument_count,
intptr_t deopt_id,
intptr_t token_pos,
LocationSummary* locs) {
MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
const String& name = String::Handle(ic_data.target_name());
+ const Array& arguments_descriptor =
+ Array::ZoneHandle(ic_data.arguments_descriptor());
+ ASSERT(!arguments_descriptor.IsNull());
const MegamorphicCache& cache =
MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
Label not_smi, load_cache;
@@ -1423,25 +1428,50 @@
}
-void FlowGraphCompiler::EmitStaticCall(const Function& function,
- const Array& arguments_descriptor,
- intptr_t argument_count,
- intptr_t deopt_id,
- intptr_t token_pos,
- LocationSummary* locs) {
+void FlowGraphCompiler::EmitOptimizedStaticCall(
+ const Function& function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
__ LoadObject(R10, arguments_descriptor);
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
GenerateDartCall(deopt_id,
token_pos,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
AddStaticCallTarget(function);
__ Drop(argument_count);
}
+void FlowGraphCompiler::EmitUnoptimizedStaticCall(
+ const Function& target_function,
+ const Array& arguments_descriptor,
+ intptr_t argument_count,
+ intptr_t deopt_id,
+ intptr_t token_pos,
+ LocationSummary* locs) {
+ const ICData& ic_data = ICData::ZoneHandle(
+ ICData::New(parsed_function().function(), // Caller function.
+ String::Handle(target_function.name()),
+ arguments_descriptor,
+ deopt_id,
+ 0)); // No arguments checked.
+ ic_data.AddTarget(target_function);
+ __ LoadObject(RBX, ic_data);
+ GenerateDartCall(deopt_id,
+ token_pos,
+ &StubCode::UnoptimizedStaticCallLabel(),
+ PcDescriptors::kUnoptStaticCall,
+ locs);
+ __ Drop(argument_count);
+}
+
+
void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
const Object& obj,
bool needs_number_check,
@@ -1587,6 +1617,7 @@
intptr_t deopt_id,
intptr_t token_index,
LocationSummary* locs) {
+ ASSERT(is_optimizing());
ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
Label match_found;
const intptr_t len = ic_data.NumberOfChecks();
@@ -1612,7 +1643,7 @@
GenerateDartCall(deopt_id,
token_index,
&StubCode::CallStaticFunctionLabel(),
- PcDescriptors::kFuncCall,
+ PcDescriptors::kOptStaticCall,
locs);
const Function& function = *sorted[i].target;
AddStaticCallTarget(function);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 6d86710..fe8573a 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -186,12 +186,7 @@
: FlowGraphVisitor(flow_graph->postorder()), // We don't use this order.
static_calls_(),
closure_calls_(),
- instance_calls_(),
- skip_static_call_deopt_ids_() { }
-
- const GrowableArray<StaticCallInstr*>& static_calls() const {
- return static_calls_;
- }
+ instance_calls_() { }
const GrowableArray<ClosureCallInstr*>& closure_calls() const {
return closure_calls_;
@@ -204,10 +199,21 @@
: call(call_arg), ratio(0.0) {}
};
+ struct StaticCallInfo {
+ StaticCallInstr* call;
+ double ratio;
+ explicit StaticCallInfo(StaticCallInstr* value)
+ : call(value), ratio(0.0) {}
+ };
+
const GrowableArray<InstanceCallInfo>& instance_calls() const {
return instance_calls_;
}
+ const GrowableArray<StaticCallInfo>& static_calls() const {
+ return static_calls_;
+ }
+
bool HasCalls() const {
return !(static_calls_.is_empty() &&
closure_calls_.is_empty() &&
@@ -218,19 +224,52 @@
static_calls_.Clear();
closure_calls_.Clear();
instance_calls_.Clear();
- skip_static_call_deopt_ids_.Clear();
+ }
+
+ void ComputeCallSiteRatio(intptr_t static_call_start_ix,
+ intptr_t instance_call_start_ix) {
+ const intptr_t num_static_calls =
+ static_calls_.length() - static_call_start_ix;
+ const intptr_t num_instance_calls =
+ instance_calls_.length() - instance_call_start_ix;
+
+ intptr_t max_count = 0;
+ GrowableArray<intptr_t> instance_call_counts(num_instance_calls);
+ for (intptr_t i = 0; i < num_instance_calls; ++i) {
+ const intptr_t aggregate_count =
+ instance_calls_[i + instance_call_start_ix].
+ call->ic_data().AggregateCount();
+ instance_call_counts.Add(aggregate_count);
+ if (aggregate_count > max_count) max_count = aggregate_count;
+ }
+
+ GrowableArray<intptr_t> static_call_counts(num_static_calls);
+ for (intptr_t i = 0; i < num_static_calls; ++i) {
+ const intptr_t aggregate_count =
+ static_calls_[i + static_call_start_ix].
+ call->ic_data()->AggregateCount();
+ static_call_counts.Add(aggregate_count);
+ if (aggregate_count > max_count) max_count = aggregate_count;
+ }
+
+ // max_count can be 0 if none of the calls was executed.
+ for (intptr_t i = 0; i < num_instance_calls; ++i) {
+ const double ratio = (max_count == 0) ?
+ 0.0 : static_cast<double>(instance_call_counts[i]) / max_count;
+ instance_calls_[i + instance_call_start_ix].ratio = ratio;
+ }
+ for (intptr_t i = 0; i < num_static_calls; ++i) {
+ const double ratio = (max_count == 0) ?
+ 0.0 : static_cast<double>(static_call_counts[i]) / max_count;
+ static_calls_[i + static_call_start_ix].ratio = ratio;
+ }
}
void FindCallSites(FlowGraph* graph) {
ASSERT(graph != NULL);
- const Function& function = graph->parsed_function().function();
- ASSERT(function.HasCode());
- const Code& code = Code::Handle(function.unoptimized_code());
-
- skip_static_call_deopt_ids_.Clear();
- code.ExtractUncalledStaticCallDeoptIds(&skip_static_call_deopt_ids_);
const intptr_t instance_call_start_ix = instance_calls_.length();
+ const intptr_t static_call_start_ix = static_calls_.length();
for (BlockIterator block_it = graph->postorder_iterator();
!block_it.Done();
block_it.Advance()) {
@@ -240,24 +279,7 @@
it.Current()->Accept(this);
}
}
- // Compute instance call site ratio.
- const intptr_t num_instance_calls =
- instance_calls_.length() - instance_call_start_ix;
- intptr_t max_count = 0;
- GrowableArray<intptr_t> call_counts(num_instance_calls);
- for (intptr_t i = 0; i < num_instance_calls; ++i) {
- const intptr_t aggregate_count =
- instance_calls_[i + instance_call_start_ix].
- call->ic_data().AggregateCount();
- call_counts.Add(aggregate_count);
- if (aggregate_count > max_count) max_count = aggregate_count;
- }
-
-
- for (intptr_t i = 0; i < num_instance_calls; ++i) {
- const double ratio = static_cast<double>(call_counts[i]) / max_count;
- instance_calls_[i + instance_call_start_ix].ratio = ratio;
- }
+ ComputeCallSiteRatio(static_call_start_ix, instance_call_start_ix);
}
void VisitClosureCall(ClosureCallInstr* call) {
@@ -270,21 +292,13 @@
void VisitStaticCall(StaticCallInstr* call) {
if (!call->function().IsInlineable()) return;
- const intptr_t call_deopt_id = call->deopt_id();
- for (intptr_t i = 0; i < skip_static_call_deopt_ids_.length(); i++) {
- if (call_deopt_id == skip_static_call_deopt_ids_[i]) {
- // Do not inline this call.
- return;
- }
- }
- static_calls_.Add(call);
+ static_calls_.Add(StaticCallInfo(call));
}
private:
- GrowableArray<StaticCallInstr*> static_calls_;
+ GrowableArray<StaticCallInfo> static_calls_;
GrowableArray<ClosureCallInstr*> closure_calls_;
GrowableArray<InstanceCallInfo> instance_calls_;
- GrowableArray<intptr_t> skip_static_call_deopt_ids_;
DISALLOW_COPY_AND_ASSIGN(CallSites);
};
@@ -713,11 +727,11 @@
// if the incoming argument is a non-constant value.
// TODO(srdjan): Fix inlining of List. factory.
void InlineStaticCalls() {
- const GrowableArray<StaticCallInstr*>& calls =
+ const GrowableArray<CallSites::StaticCallInfo>& call_info =
inlining_call_sites_->static_calls();
- TRACE_INLINING(OS::Print(" Static Calls (%d)\n", calls.length()));
- for (intptr_t i = 0; i < calls.length(); ++i) {
- StaticCallInstr* call = calls[i];
+ TRACE_INLINING(OS::Print(" Static Calls (%d)\n", call_info.length()));
+ for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
+ StaticCallInstr* call = call_info[call_idx].call;
if (call->function().name() == Symbols::ListFactory().raw()) {
// Inline only if no arguments or a constant was passed.
ASSERT(call->function().NumImplicitParameters() == 1);
@@ -730,6 +744,15 @@
continue;
}
}
+ if ((call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
+ const Function& target = call->function();
+ TRACE_INLINING(OS::Print(
+ " => %s (deopt count %d)\n Bailout: cold %f\n",
+ target.ToCString(),
+ target.deoptimization_counter(),
+ call_info[call_idx].ratio));
+ continue;
+ }
GrowableArray<Value*> arguments(call->ArgumentCount());
for (int i = 0; i < call->ArgumentCount(); ++i) {
arguments.Add(call->PushArgumentAt(i)->value());
@@ -1099,6 +1122,7 @@
const ICData& new_checks = ICData::ZoneHandle(
ICData::New(Function::Handle(old_checks.function()),
String::Handle(old_checks.target_name()),
+ Array::Handle(old_checks.arguments_descriptor()),
old_checks.deopt_id(),
1)); // Number of args tested.
new_checks.AddReceiverCheck(inlined_variants_[i].cid,
@@ -1223,6 +1247,7 @@
const ICData& new_checks = ICData::ZoneHandle(
ICData::New(Function::Handle(old_checks.function()),
String::Handle(old_checks.target_name()),
+ Array::Handle(old_checks.arguments_descriptor()),
old_checks.deopt_id(),
1)); // Number of args tested.
for (intptr_t i = 0; i < non_inlined_variants_.length(); ++i) {
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 36646d3..231b65d 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -33,6 +33,8 @@
DEFINE_FLAG(bool, truncating_left_shift, true,
"Optimize left shift to truncate if possible");
DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
+DEFINE_FLAG(bool, trace_load_optimization, false,
+ "Print live sets for load optimization pass.");
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, trace_type_check_elimination);
@@ -120,6 +122,7 @@
ICData& ic_data = ICData::ZoneHandle(ICData::New(
flow_graph_->parsed_function().function(),
call->function_name(),
+ Object::null_array(), // Dummy argument descriptor.
call->deopt_id(),
class_ids.length()));
ic_data.AddReceiverCheck(class_ids[0], function);
@@ -141,6 +144,7 @@
const ICData& new_ic_data = ICData::ZoneHandle(ICData::New(
Function::Handle(ic_data.function()),
String::Handle(ic_data.target_name()),
+ Object::null_array(), // Dummy argument descriptor.
ic_data.deopt_id(),
ic_data.num_args_tested()));
@@ -413,6 +417,7 @@
InsertConversion(from_rep, to_rep, use, insert_before, deopt_target);
}
+
void FlowGraphOptimizer::InsertConversionsFor(Definition* def) {
const Representation from_rep = def->representation();
@@ -1503,6 +1508,8 @@
return true;
} else if (target.kind() == RawFunction::kMethodExtractor) {
return false;
+ } else if (target.kind() == RawFunction::kNoSuchMethodDispatcher) {
+ return false;
}
// Not an implicit getter.
@@ -2109,7 +2116,8 @@
case kTypedDataUint16ArrayCid: {
// Check that value is always smi.
value_check = ICData::New(Function::Handle(),
- String::Handle(),
+ Object::null_string(),
+ Object::null_array(),
Isolate::kNoDeoptId,
1);
value_check.AddReceiverCheck(kSmiCid, Function::Handle());
@@ -2122,7 +2130,8 @@
// before storing to handle the mint case, too.
if (call->ic_data()->deopt_reason() == kDeoptUnknown) {
value_check = ICData::New(Function::Handle(),
- String::Handle(),
+ Object::null_string(),
+ Object::null_array(), // Dummy args. descr.
Isolate::kNoDeoptId,
1);
value_check.AddReceiverCheck(kSmiCid, Function::Handle());
@@ -2132,7 +2141,8 @@
case kTypedDataFloat64ArrayCid: {
// Check that value is always double.
value_check = ICData::New(Function::Handle(),
- String::Handle(),
+ Object::null_string(),
+ Object::null_array(), // Dummy args. descr.
Isolate::kNoDeoptId,
1);
value_check.AddReceiverCheck(kDoubleCid, Function::Handle());
@@ -2141,7 +2151,8 @@
case kTypedDataFloat32x4ArrayCid: {
// Check that value is always Float32x4.
value_check = ICData::New(Function::Handle(),
- String::Handle(),
+ Object::null_string(),
+ Object::null_array(), // Dummy args. descr.
Isolate::kNoDeoptId,
1);
value_check.AddReceiverCheck(kFloat32x4Cid, Function::Handle());
@@ -2466,6 +2477,18 @@
new Value(call->ArgumentAt(4)),
call->deopt_id());
ReplaceCall(call, con);
+ } else if (recognized_kind == MethodRecognizer::kObjectConstructor) {
+ // Remove the original push arguments.
+ for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
+ PushArgumentInstr* push = call->PushArgumentAt(i);
+ push->ReplaceUsesWith(push->value()->definition());
+ push->RemoveFromGraph();
+ }
+ // Manually replace call with global null constant. ReplaceCall can't
+ // be used for definitions that are already in the graph.
+ call->ReplaceUsesWith(flow_graph_->constant_null());
+ ASSERT(current_iterator()->Current() == call);
+ current_iterator()->RemoveCurrentFromGraph();;
}
}
@@ -3502,9 +3525,9 @@
intptr_t loop_header_index,
Instruction* instr) {
return (sets != NULL) &&
- instr->HasExprId() &&
+ instr->HasPlaceId() &&
((*sets)[loop_header_index] != NULL) &&
- (*sets)[loop_header_index]->Contains(instr->expr_id());
+ (*sets)[loop_header_index]->Contains(instr->place_id());
}
@@ -3533,7 +3556,7 @@
Instruction* current = it.Current();
if ((current->AllowsCSE() &&
block_effects->CanBeMovedTo(current, pre_header)) ||
- IsLoopInvariantLoad(loop_invariant_loads, i, current)) {
+ IsLoopInvariantLoad(loop_invariant_loads, i, current)) {
bool inputs_loop_invariant = true;
for (int i = 0; i < current->InputCount(); ++i) {
Definition* input_def = current->InputAt(i)->definition();
@@ -3634,44 +3657,308 @@
};
-// Set mapping alias to a list of loads sharing this alias. Additionally
-// carries a set of loads that can be aliased by side-effects, essentially
+// Place describes an abstract location (e.g. field) that IR can load
+// from or store to.
+class Place : public ValueObject {
+ public:
+ enum Kind {
+ kNone,
+
+ // Field location. For instance fields is represented as a pair of a Field
+ // object and an instance (SSA definition) that is being accessed.
+ // For static fields instance is NULL.
+ kField,
+
+ // VMField location. Represented as a pair of an instance (SSA definition)
+ // being accessed and offset to the field.
+ kVMField,
+
+ // Indexed location.
+ kIndexed,
+
+ // Current context.
+ kContext
+ };
+
+ Place(const Place& other)
+ : ValueObject(),
+ kind_(other.kind_),
+ instance_(other.instance_),
+ raw_selector_(other.raw_selector_),
+ id_(other.id_) {
+ }
+
+ // Construct a place from instruction if instruction accesses any place.
+ // Otherwise constructs kNone place.
+ Place(Instruction* instr, bool* is_load)
+ : kind_(kNone), instance_(NULL), raw_selector_(0), id_(0) {
+ switch (instr->tag()) {
+ case Instruction::kLoadField: {
+ LoadFieldInstr* load_field = instr->AsLoadField();
+ instance_ = load_field->instance()->definition();
+ if (load_field->field() != NULL) {
+ kind_ = kField;
+ field_ = load_field->field();
+ } else {
+ kind_ = kVMField;
+ offset_in_bytes_ = load_field->offset_in_bytes();
+ }
+ *is_load = true;
+ break;
+ }
+
+ case Instruction::kStoreInstanceField: {
+ StoreInstanceFieldInstr* store_instance_field =
+ instr->AsStoreInstanceField();
+ kind_ = kField;
+ instance_ = store_instance_field->instance()->definition();
+ field_ = &store_instance_field->field();
+ break;
+ }
+
+ case Instruction::kStoreVMField: {
+ StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField();
+ kind_ = kVMField;
+ instance_ = store_vm_field->dest()->definition();
+ offset_in_bytes_ = store_vm_field->offset_in_bytes();
+ break;
+ }
+
+ case Instruction::kLoadStaticField:
+ kind_ = kField;
+ field_ = &instr->AsLoadStaticField()->StaticField();
+ *is_load = true;
+ break;
+
+ case Instruction::kStoreStaticField:
+ kind_ = kField;
+ field_ = &instr->AsStoreStaticField()->field();
+ break;
+
+ case Instruction::kLoadIndexed: {
+ LoadIndexedInstr* load_indexed = instr->AsLoadIndexed();
+ kind_ = kIndexed;
+ instance_ = load_indexed->array()->definition();
+ index_ = load_indexed->index()->definition();
+ *is_load = true;
+ break;
+ }
+
+ case Instruction::kStoreIndexed: {
+ StoreIndexedInstr* store_indexed = instr->AsStoreIndexed();
+ kind_ = kIndexed;
+ instance_ = store_indexed->array()->definition();
+ index_ = store_indexed->index()->definition();
+ break;
+ }
+
+ case Instruction::kCurrentContext:
+ kind_ = kContext;
+ *is_load = true;
+ break;
+
+ case Instruction::kChainContext:
+ case Instruction::kStoreContext:
+ kind_ = kContext;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ intptr_t id() const { return id_; }
+ void set_id(intptr_t id) { id_ = id; }
+
+ Kind kind() const { return kind_; }
+
+ Definition* instance() const {
+ ASSERT((kind_ == kField) || (kind_ == kVMField) || (kind_ == kIndexed));
+ return instance_;
+ }
+
+ void set_instance(Definition* def) {
+ ASSERT((kind_ == kField) || (kind_ == kVMField) || (kind_ == kIndexed));
+ instance_ = def;
+ }
+
+ const Field& field() const {
+ ASSERT(kind_ == kField);
+ return *field_;
+ }
+
+ intptr_t offset_in_bytes() const {
+ ASSERT(kind_ == kVMField);
+ return offset_in_bytes_;
+ }
+
+ Definition* index() const {
+ ASSERT(kind_ == kIndexed);
+ return index_;
+ }
+
+ const char* ToCString() const {
+ switch (kind_) {
+ case kNone:
+ return "<none>";
+
+ case kField: {
+ const char* field_name = String::Handle(field().name()).ToCString();
+ if (instance() == NULL) {
+ return field_name;
+ }
+ return Isolate::Current()->current_zone()->PrintToString(
+ "<v%"Pd".%s>", instance()->ssa_temp_index(), field_name);
+ }
+
+ case kVMField: {
+ return Isolate::Current()->current_zone()->PrintToString(
+ "<v%"Pd"@%"Pd">", instance()->ssa_temp_index(), offset_in_bytes());
+ }
+
+ case kIndexed: {
+ return Isolate::Current()->current_zone()->PrintToString(
+ "<v%"Pd"[v%"Pd"]>",
+ instance()->ssa_temp_index(),
+ index()->ssa_temp_index());
+ }
+
+ case kContext:
+ return "<context>";
+ }
+ UNREACHABLE();
+ return "<?>";
+ }
+
+ bool IsFinalField() const {
+ return (kind() == kField) && field().is_final();
+ }
+
+ intptr_t Hashcode() const {
+ return (kind_ * 63 + reinterpret_cast<intptr_t>(instance_)) * 31 +
+ FieldHashcode();
+ }
+
+ bool Equals(Place* other) const {
+ return (kind_ == other->kind_) &&
+ (instance_ == other->instance_) &&
+ SameField(other);
+ }
+
+ // Create a zone allocated copy of this place.
+ static Place* Wrap(const Place& place);
+
+ private:
+ bool SameField(Place* other) const {
+ return (kind_ == kField) ? (field().raw() == other->field().raw())
+ : (offset_in_bytes_ == other->offset_in_bytes_);
+ }
+
+ intptr_t FieldHashcode() const {
+ return (kind_ == kField) ? reinterpret_cast<intptr_t>(field().raw())
+ : offset_in_bytes_;
+ }
+
+ Kind kind_;
+ Definition* instance_;
+ union {
+ intptr_t raw_selector_;
+ const Field* field_;
+ intptr_t offset_in_bytes_;
+ Definition* index_;
+ };
+
+ intptr_t id_;
+};
+
+
+class ZonePlace : public ZoneAllocated {
+ public:
+ explicit ZonePlace(const Place& place) : place_(place) { }
+
+ Place* place() { return &place_; }
+
+ private:
+ Place place_;
+};
+
+
+Place* Place::Wrap(const Place& place) {
+ return (new ZonePlace(place))->place();
+}
+
+
+// Correspondence between places connected through outgoing phi moves on the
+// edge that targets join.
+class PhiPlaceMoves : public ZoneAllocated {
+ public:
+ // Record a move from the place with id |from| to the place with id |to| at
+ // the given block.
+ void CreateOutgoingMove(BlockEntryInstr* block, intptr_t from, intptr_t to) {
+ const intptr_t block_num = block->preorder_number();
+ while (moves_.length() <= block_num) {
+ moves_.Add(NULL);
+ }
+
+ if (moves_[block_num] == NULL) {
+ moves_[block_num] = new ZoneGrowableArray<Move>(5);
+ }
+
+ moves_[block_num]->Add(Move(from, to));
+ }
+
+ class Move {
+ public:
+ Move(intptr_t from, intptr_t to) : from_(from), to_(to) { }
+
+ intptr_t from() const { return from_; }
+ intptr_t to() const { return to_; }
+
+ private:
+ intptr_t from_;
+ intptr_t to_;
+ };
+
+ typedef const ZoneGrowableArray<Move>* MovesList;
+
+ MovesList GetOutgoingMoves(BlockEntryInstr* block) const {
+ const intptr_t block_num = block->preorder_number();
+ return (block_num < moves_.length()) ?
+ moves_[block_num] : NULL;
+ }
+
+ private:
+ GrowableArray<ZoneGrowableArray<Move>* > moves_;
+};
+
+
+// A map from aliases to a set of places sharing the alias. Additionally
+// carries a set of places that can be aliased by side-effects, essentially
// those that are affected by calls.
class AliasedSet : public ZoneAllocated {
public:
- explicit AliasedSet(intptr_t max_expr_id)
- : max_expr_id_(max_expr_id),
+ explicit AliasedSet(ZoneGrowableArray<Place*>* places,
+ PhiPlaceMoves* phi_moves)
+ : places_(*places),
+ phi_moves_(phi_moves),
sets_(),
- // BitVector constructor throws if requested length is 0.
- aliased_by_effects_(max_expr_id > 0 ? new BitVector(max_expr_id)
- : NULL),
+ aliased_by_effects_(new BitVector(places->length())),
max_field_id_(0),
field_ids_() { }
- Alias ComputeAliasForLoad(Definition* defn) {
- if (defn->IsLoadIndexed()) {
- // We are assuming that LoadField is never used to load the first word.
- return Alias::Indexes();
- }
-
- LoadFieldInstr* load_field = defn->AsLoadField();
- if (load_field != NULL) {
- if (load_field->field() != NULL) {
- Definition* instance = load_field->instance()->definition();
- return Alias::Field(GetInstanceFieldId(instance, *load_field->field()));
- } else {
- return Alias::VMField(load_field->offset_in_bytes());
- }
- }
-
- if (defn->IsCurrentContext()) {
- return Alias::CurrentContext();
- }
-
- LoadStaticFieldInstr* load_static_field = defn->AsLoadStaticField();
- if (load_static_field != NULL) {
- return Alias::Field(GetFieldId(kAnyInstance,
- load_static_field->StaticField()));
+ Alias ComputeAlias(Place* place) {
+ switch (place->kind()) {
+ case Place::kIndexed:
+ return Alias::Indexes();
+ case Place::kField:
+ return Alias::Field(
+ GetInstanceFieldId(place->instance(), place->field()));
+ case Place::kVMField:
+ return Alias::VMField(place->offset_in_bytes());
+ case Place::kContext:
+ return Alias::CurrentContext();
+ case Place::kNone:
+ UNREACHABLE();
}
UNREACHABLE();
@@ -3708,24 +3995,21 @@
return Alias::None();
}
- bool Contains(const Alias alias) {
- const intptr_t idx = alias.ToIndex();
- return (idx < sets_.length()) && (sets_[idx] != NULL);
- }
-
BitVector* Get(const Alias alias) {
- ASSERT(Contains(alias));
- return sets_[alias.ToIndex()];
+ const intptr_t idx = alias.ToIndex();
+ return (idx < sets_.length()) ? sets_[idx] : NULL;
}
- void AddRepresentative(Definition* defn) {
- AddIdForAlias(ComputeAliasForLoad(defn), defn->expr_id());
- if (!IsIndependentFromEffects(defn)) {
- aliased_by_effects_->Add(defn->expr_id());
+ void AddRepresentative(Place* place) {
+ if (!place->IsFinalField()) {
+ AddIdForAlias(ComputeAlias(place), place->id());
+ if (!IsIndependentFromEffects(place)) {
+ aliased_by_effects_->Add(place->id());
+ }
}
}
- void AddIdForAlias(const Alias alias, intptr_t expr_id) {
+ void AddIdForAlias(const Alias alias, intptr_t place_id) {
const intptr_t idx = alias.ToIndex();
while (sets_.length() <= idx) {
@@ -3733,17 +4017,36 @@
}
if (sets_[idx] == NULL) {
- sets_[idx] = new BitVector(max_expr_id_);
+ sets_[idx] = new BitVector(max_place_id());
}
- sets_[idx]->Add(expr_id);
+ sets_[idx]->Add(place_id);
}
- intptr_t max_expr_id() const { return max_expr_id_; }
- bool IsEmpty() const { return max_expr_id_ == 0; }
+ intptr_t max_place_id() const { return places().length(); }
+ bool IsEmpty() const { return max_place_id() == 0; }
BitVector* aliased_by_effects() const { return aliased_by_effects_; }
+ const ZoneGrowableArray<Place*>& places() const {
+ return places_;
+ }
+
+ void PrintSet(BitVector* set) {
+ bool comma = false;
+ for (BitVector::Iterator it(set);
+ !it.Done();
+ it.Advance()) {
+ if (comma) {
+ OS::Print(", ");
+ }
+ OS::Print("%s", places_[it.Current()]->ToCString());
+ comma = true;
+ }
+ }
+
+ const PhiPlaceMoves* phi_moves() const { return phi_moves_; }
+
private:
// Get id assigned to the given field. Assign a new id if the field is seen
// for the first time.
@@ -3770,14 +4073,16 @@
// If multiple SSA names can point to the same object then we use
// kAnyInstance instead of a concrete SSA name.
intptr_t GetInstanceFieldId(Definition* defn, const Field& field) {
- ASSERT(!field.is_static());
+ ASSERT(field.is_static() == (defn == NULL));
intptr_t instance_id = kAnyInstance;
- AllocateObjectInstr* alloc = defn->AsAllocateObject();
- if ((alloc != NULL) && !CanBeAliased(alloc)) {
- instance_id = alloc->ssa_temp_index();
- ASSERT(instance_id != kAnyInstance);
+ if (defn != NULL) {
+ AllocateObjectInstr* alloc = defn->AsAllocateObject();
+ if ((alloc != NULL) && !CanBeAliased(alloc)) {
+ instance_id = alloc->ssa_temp_index();
+ ASSERT(instance_id != kAnyInstance);
+ }
}
return GetFieldId(instance_id, field);
@@ -3820,9 +4125,8 @@
// Returns true if the given load is unaffected by external side-effects.
// This essentially means that no stores to the same location can
// occur in other functions.
- bool IsIndependentFromEffects(Definition* defn) {
- LoadFieldInstr* load_field = defn->AsLoadField();
- if (load_field != NULL) {
+ bool IsIndependentFromEffects(Place* place) {
+ if (place->IsFinalField()) {
// Note that we can't use LoadField's is_immutable attribute here because
// some VM-fields (those that have no corresponding Field object and
// accessed through offset alone) can share offset but have different
@@ -3835,19 +4139,14 @@
// conservative assumption for the VM-properties.
// TODO(vegorov): disambiguate immutable and non-immutable VM-fields with
// the same offset e.g. through recognized kind.
- if ((load_field->field() != NULL) &&
- (load_field->field()->is_final())) {
- return true;
- }
-
- AllocateObjectInstr* alloc =
- load_field->instance()->definition()->AsAllocateObject();
- return (alloc != NULL) && !CanBeAliased(alloc);
+ return true;
}
- LoadStaticFieldInstr* load_static_field = defn->AsLoadStaticField();
- if (load_static_field != NULL) {
- return load_static_field->StaticField().is_final();
+ if (((place->kind() == Place::kField) ||
+ (place->kind() == Place::kVMField)) &&
+ (place->instance() != NULL)) {
+ AllocateObjectInstr* alloc = place->instance()->AsAllocateObject();
+ return (alloc != NULL) && !CanBeAliased(alloc);
}
return false;
@@ -3890,7 +4189,9 @@
Value value_;
};
- const intptr_t max_expr_id_;
+ const ZoneGrowableArray<Place*>& places_;
+
+ const PhiPlaceMoves* phi_moves_;
// Maps alias index to a set of ssa indexes corresponding to loads with the
// given alias.
@@ -3933,114 +4234,69 @@
}
-// KeyValueTrait used for numbering of loads. Allows to lookup loads
-// corresponding to stores.
-class LoadKeyValueTrait {
- public:
- typedef Definition* Value;
- typedef Instruction* Key;
- typedef Definition* Pair;
+static bool IsPhiDependentPlace(Place* place) {
+ return ((place->kind() == Place::kField) ||
+ (place->kind() == Place::kVMField)) &&
+ (place->instance() != NULL) &&
+ place->instance()->IsPhi();
+}
- static Key KeyOf(Pair kv) {
- return kv;
- }
- static Value ValueOf(Pair kv) {
- return kv;
- }
+// For each place that depends on a phi ensure that equivalent places
+// corresponding to phi input are numbered and record outgoing phi moves
+// for each block which establish correspondence between phi dependent place
+// and phi input's place that is flowing in.
+static PhiPlaceMoves* ComputePhiMoves(
+ DirectChainedHashMap<PointerKeyValueTrait<Place> >* map,
+ ZoneGrowableArray<Place*>* places) {
+ PhiPlaceMoves* phi_moves = new PhiPlaceMoves();
- static inline intptr_t Hashcode(Key key) {
- intptr_t object = 0;
- intptr_t location = 0;
+ for (intptr_t i = 0; i < places->length(); i++) {
+ Place* place = (*places)[i];
- if (key->IsLoadIndexed()) {
- LoadIndexedInstr* load_indexed = key->AsLoadIndexed();
- object = load_indexed->array()->definition()->ssa_temp_index();
- location = load_indexed->index()->definition()->ssa_temp_index();
- } else if (key->IsStoreIndexed()) {
- StoreIndexedInstr* store_indexed = key->AsStoreIndexed();
- object = store_indexed->array()->definition()->ssa_temp_index();
- location = store_indexed->index()->definition()->ssa_temp_index();
- } else if (key->IsLoadField()) {
- LoadFieldInstr* load_field = key->AsLoadField();
- object = load_field->instance()->definition()->ssa_temp_index();
- location = load_field->offset_in_bytes();
- } else if (key->IsStoreInstanceField()) {
- StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField();
- object = store_field->instance()->definition()->ssa_temp_index();
- location = store_field->field().Offset();
- } else if (key->IsStoreVMField()) {
- StoreVMFieldInstr* store_field = key->AsStoreVMField();
- object = store_field->dest()->definition()->ssa_temp_index();
- location = store_field->offset_in_bytes();
- } else if (key->IsLoadStaticField()) {
- LoadStaticFieldInstr* load_static_field = key->AsLoadStaticField();
- object = String::Handle(load_static_field->StaticField().name()).Hash();
- } else if (key->IsStoreStaticField()) {
- StoreStaticFieldInstr* store_static_field = key->AsStoreStaticField();
- object = String::Handle(store_static_field->field().name()).Hash();
- } else {
- ASSERT(key->IsStoreContext() ||
- key->IsCurrentContext() ||
- key->IsChainContext());
- }
+ if (IsPhiDependentPlace(place)) {
+ PhiInstr* phi = place->instance()->AsPhi();
+ BlockEntryInstr* block = phi->GetBlock();
- return object * 31 + location;
- }
-
- static inline bool IsKeyEqual(Pair kv, Key key) {
- if (kv->Equals(key)) return true;
-
- if (kv->IsLoadIndexed()) {
- if (key->IsStoreIndexed()) {
- LoadIndexedInstr* load_indexed = kv->AsLoadIndexed();
- StoreIndexedInstr* store_indexed = key->AsStoreIndexed();
- return load_indexed->array()->Equals(store_indexed->array()) &&
- load_indexed->index()->Equals(store_indexed->index());
+ if (FLAG_trace_optimization) {
+ OS::Print("phi dependent place %s\n", place->ToCString());
}
- return false;
- }
- if (kv->IsLoadStaticField()) {
- if (key->IsStoreStaticField()) {
- LoadStaticFieldInstr* load_static_field = kv->AsLoadStaticField();
- StoreStaticFieldInstr* store_static_field = key->AsStoreStaticField();
- return load_static_field->StaticField().raw() ==
- store_static_field->field().raw();
+ Place input_place(*place);
+ for (intptr_t j = 0; j < phi->InputCount(); j++) {
+ input_place.set_instance(phi->InputAt(j)->definition());
+
+ Place* result = map->Lookup(&input_place);
+ if (result == NULL) {
+ input_place.set_id(places->length());
+ result = Place::Wrap(input_place);
+ map->Insert(result);
+ places->Add(result);
+ if (FLAG_trace_optimization) {
+ OS::Print(" adding place %s as %"Pd"\n",
+ result->ToCString(),
+ result->id());
+ }
+ }
+
+ phi_moves->CreateOutgoingMove(block->PredecessorAt(j),
+ result->id(),
+ place->id());
}
- return false;
}
-
- if (kv->IsCurrentContext()) {
- return key->IsStoreContext() || key->IsChainContext();
- }
-
- ASSERT(kv->IsLoadField());
- LoadFieldInstr* load_field = kv->AsLoadField();
- if (key->IsStoreVMField()) {
- StoreVMFieldInstr* store_field = key->AsStoreVMField();
- return load_field->instance()->Equals(store_field->dest()) &&
- (load_field->offset_in_bytes() == store_field->offset_in_bytes());
- } else if (key->IsStoreInstanceField()) {
- StoreInstanceFieldInstr* store_field = key->AsStoreInstanceField();
- return load_field->instance()->Equals(store_field->instance()) &&
- (load_field->offset_in_bytes() == store_field->field().Offset());
- }
-
- return false;
}
-};
+ return phi_moves;
+}
-static AliasedSet* NumberLoadExpressions(
+static AliasedSet* NumberPlaces(
FlowGraph* graph,
- DirectChainedHashMap<LoadKeyValueTrait>* map) {
- intptr_t expr_id = 0;
-
+ DirectChainedHashMap<PointerKeyValueTrait<Place> >* map) {
// Loads representing different expression ids will be collected and
// used to build per offset kill sets.
- GrowableArray<Definition*> loads(10);
+ ZoneGrowableArray<Place*>* places = new ZoneGrowableArray<Place*>(10);
+ bool has_loads = false;
for (BlockIterator it = graph->reverse_postorder_iterator();
!it.Done();
it.Advance()) {
@@ -4048,33 +4304,44 @@
for (ForwardInstructionIterator instr_it(block);
!instr_it.Done();
instr_it.Advance()) {
- Definition* defn = instr_it.Current()->AsDefinition();
- if ((defn == NULL) || !IsLoadEliminationCandidate(defn)) {
+ Instruction* instr = instr_it.Current();
+
+ Place place(instr, &has_loads);
+ if (place.kind() == Place::kNone) {
continue;
}
- Definition* result = map->Lookup(defn);
+
+ Place* result = map->Lookup(&place);
if (result == NULL) {
- map->Insert(defn);
- defn->set_expr_id(expr_id++);
- loads.Add(defn);
- } else {
- defn->set_expr_id(result->expr_id());
+ place.set_id(places->length());
+ result = Place::Wrap(place);
+ map->Insert(result);
+ places->Add(result);
+
+ if (FLAG_trace_optimization) {
+ OS::Print("numbering %s as %"Pd"\n",
+ result->ToCString(),
+ result->id());
+ }
}
- if (FLAG_trace_optimization) {
- OS::Print("load v%"Pd" is numbered as %"Pd"\n",
- defn->ssa_temp_index(),
- defn->expr_id());
- }
+ instr->set_place_id(result->id());
}
}
- // Build aliasing sets mapping aliases to loads.
- AliasedSet* aliased_set = new AliasedSet(expr_id);
- for (intptr_t i = 0; i < loads.length(); i++) {
- Definition* defn = loads[i];
- aliased_set->AddRepresentative(defn);
+ if (!has_loads) {
+ return NULL;
}
+
+ PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places);
+
+ // Build aliasing sets mapping aliases to loads.
+ AliasedSet* aliased_set = new AliasedSet(places, phi_moves);
+ for (intptr_t i = 0; i < places->length(); i++) {
+ Place* place = (*places)[i];
+ aliased_set->AddRepresentative(place);
+ }
+
return aliased_set;
}
@@ -4083,7 +4350,7 @@
public:
LoadOptimizer(FlowGraph* graph,
AliasedSet* aliased_set,
- DirectChainedHashMap<LoadKeyValueTrait>* map)
+ DirectChainedHashMap<PointerKeyValueTrait<Place> >* map)
: graph_(graph),
map_(map),
aliased_set_(aliased_set),
@@ -4099,10 +4366,10 @@
forwarded_(false) {
const intptr_t num_blocks = graph_->preorder().length();
for (intptr_t i = 0; i < num_blocks; i++) {
- out_.Add(new BitVector(aliased_set_->max_expr_id()));
- gen_.Add(new BitVector(aliased_set_->max_expr_id()));
- kill_.Add(new BitVector(aliased_set_->max_expr_id()));
- in_.Add(new BitVector(aliased_set_->max_expr_id()));
+ out_.Add(NULL);
+ gen_.Add(new BitVector(aliased_set_->max_place_id()));
+ kill_.Add(new BitVector(aliased_set_->max_place_id()));
+ in_.Add(new BitVector(aliased_set_->max_place_id()));
exposed_values_.Add(NULL);
out_values_.Add(NULL);
@@ -4111,10 +4378,13 @@
static bool OptimizeGraph(FlowGraph* graph) {
ASSERT(FLAG_load_cse);
+ if (FLAG_trace_load_optimization) {
+ FlowGraphPrinter::PrintGraph("Before LoadOptimizer", graph);
+ }
- DirectChainedHashMap<LoadKeyValueTrait> map;
- AliasedSet* aliased_set = NumberLoadExpressions(graph, &map);
- if (!aliased_set->IsEmpty()) {
+ DirectChainedHashMap<PointerKeyValueTrait<Place> > map;
+ AliasedSet* aliased_set = NumberPlaces(graph, &map);
+ if ((aliased_set != NULL) && !aliased_set->IsEmpty()) {
// If any loads were forwarded return true from Optimize to run load
// forwarding again. This will allow to forward chains of loads.
// This is especially important for context variables as they are built
@@ -4130,12 +4400,18 @@
private:
bool Optimize() {
ComputeInitialSets();
+ ComputeOutSets();
ComputeOutValues();
if (graph_->is_licm_allowed()) {
MarkLoopInvariantLoads();
}
ForwardLoads();
EmitPhis();
+
+ if (FLAG_trace_load_optimization) {
+ FlowGraphPrinter::PrintGraph("After LoadOptimizer", graph_);
+ }
+
return forwarded_;
}
@@ -4146,6 +4422,8 @@
// Loads that are locally redundant will be replaced as we go through
// instructions.
void ComputeInitialSets() {
+ BitVector* forwarded_loads = new BitVector(aliased_set_->max_place_id());
+
for (BlockIterator block_it = graph_->reverse_postorder_iterator();
!block_it.Done();
block_it.Advance()) {
@@ -4166,31 +4444,36 @@
const Alias alias = aliased_set_->ComputeAliasForStore(instr);
if (!alias.IsNone()) {
// Interfering stores kill only loads from the same offset.
- if (aliased_set_->Contains(alias)) {
- BitVector* killed = aliased_set_->Get(alias);
+ BitVector* killed = aliased_set_->Get(alias);
+
+ if (killed != NULL) {
kill->AddAll(killed);
// There is no need to clear out_values when clearing GEN set
// because only those values that are in the GEN set
// will ever be used.
gen->RemoveAll(killed);
+ }
- // Only forward stores to normal arrays and float64 arrays
- // to loads because other array stores (intXX/uintXX/float32)
- // may implicitly convert the value stored.
- StoreIndexedInstr* array_store = instr->AsStoreIndexed();
- if (array_store == NULL ||
- array_store->class_id() == kArrayCid ||
- array_store->class_id() == kTypedDataFloat64ArrayCid) {
- Definition* load = map_->Lookup(instr);
- if (load != NULL) {
- // Store has a corresponding numbered load. Try forwarding
- // stored value to it.
- gen->Add(load->expr_id());
- if (out_values == NULL) out_values = CreateBlockOutValues();
- (*out_values)[load->expr_id()] = GetStoredValue(instr);
- }
+ // Only forward stores to normal arrays and float64 arrays
+ // to loads because other array stores (intXX/uintXX/float32)
+ // may implicitly convert the value stored.
+ StoreIndexedInstr* array_store = instr->AsStoreIndexed();
+ if (array_store == NULL ||
+ array_store->class_id() == kArrayCid ||
+ array_store->class_id() == kTypedDataFloat64ArrayCid) {
+ bool is_load = false;
+ Place store_place(instr, &is_load);
+ ASSERT(!is_load);
+ Place* place = map_->Lookup(&store_place);
+ if (place != NULL) {
+ // Store has a corresponding numbered place that might have a
+ // load. Try forwarding stored value to it.
+ gen->Add(place->id());
+ if (out_values == NULL) out_values = CreateBlockOutValues();
+ (*out_values)[place->id()] = GetStoredValue(instr);
}
}
+
ASSERT(!instr->IsDefinition() ||
!IsLoadEliminationCandidate(instr->AsDefinition()));
continue;
@@ -4240,9 +4523,9 @@
LoadFieldInstr* load = use->instruction()->AsLoadField();
if (load != NULL) {
// Found a load. Initialize current value of the field to null.
- gen->Add(load->expr_id());
+ gen->Add(load->place_id());
if (out_values == NULL) out_values = CreateBlockOutValues();
- (*out_values)[load->expr_id()] = graph_->constant_null();
+ (*out_values)[load->place_id()] = graph_->constant_null();
}
}
continue;
@@ -4252,12 +4535,12 @@
continue;
}
- const intptr_t expr_id = defn->expr_id();
- if (gen->Contains(expr_id)) {
+ const intptr_t place_id = defn->place_id();
+ if (gen->Contains(place_id)) {
// This is a locally redundant load.
- ASSERT((out_values != NULL) && ((*out_values)[expr_id] != NULL));
+ ASSERT((out_values != NULL) && ((*out_values)[place_id] != NULL));
- Definition* replacement = (*out_values)[expr_id];
+ Definition* replacement = (*out_values)[place_id];
EnsureSSATempIndex(graph_, defn, replacement);
if (FLAG_trace_optimization) {
OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
@@ -4269,7 +4552,7 @@
instr_it.RemoveCurrentFromGraph();
forwarded_ = true;
continue;
- } else if (!kill->Contains(expr_id)) {
+ } else if (!kill->Contains(place_id)) {
// This is an exposed load: it is the first representative of a
// given expression id and it is not killed on the path from
// the block entry.
@@ -4277,33 +4560,60 @@
static const intptr_t kMaxExposedValuesInitialSize = 5;
exposed_values = new ZoneGrowableArray<Definition*>(
Utils::Minimum(kMaxExposedValuesInitialSize,
- aliased_set_->max_expr_id()));
+ aliased_set_->max_place_id()));
}
exposed_values->Add(defn);
}
- gen->Add(expr_id);
+ gen->Add(place_id);
if (out_values == NULL) out_values = CreateBlockOutValues();
- (*out_values)[expr_id] = defn;
+ (*out_values)[place_id] = defn;
}
- out_[preorder_number]->CopyFrom(gen);
+ PhiPlaceMoves::MovesList phi_moves =
+ aliased_set_->phi_moves()->GetOutgoingMoves(block);
+ if (phi_moves != NULL) {
+ PerformPhiMoves(phi_moves, gen, forwarded_loads);
+ }
+
exposed_values_[preorder_number] = exposed_values;
out_values_[preorder_number] = out_values;
}
}
- // Compute OUT sets and corresponding out_values mappings by propagating them
- // iteratively until fix point is reached.
- // No replacement is done at this point and thus any out_value[expr_id] is
- // changed at most once: from NULL to an actual value.
- // When merging incoming loads we might need to create a phi.
- // These phis are not inserted at the graph immediately because some of them
- // might become redundant after load forwarding is done.
- void ComputeOutValues() {
- BitVector* temp = new BitVector(aliased_set_->max_expr_id());
+ static void PerformPhiMoves(PhiPlaceMoves::MovesList phi_moves,
+ BitVector* out,
+ BitVector* forwarded_loads) {
+ forwarded_loads->Clear();
+
+ for (intptr_t i = 0; i < phi_moves->length(); i++) {
+ const intptr_t from = (*phi_moves)[i].from();
+ const intptr_t to = (*phi_moves)[i].to();
+ if (from == to) continue;
+
+ if (out->Contains(from)) {
+ forwarded_loads->Add(to);
+ }
+ }
+
+ for (intptr_t i = 0; i < phi_moves->length(); i++) {
+ const intptr_t from = (*phi_moves)[i].from();
+ const intptr_t to = (*phi_moves)[i].to();
+ if (from == to) continue;
+
+ out->Remove(to);
+ }
+
+ out->AddAll(forwarded_loads);
+ }
+
+ // Compute OUT sets by propagating them iteratively until fix point
+ // is reached.
+ void ComputeOutSets() {
+ BitVector* temp = new BitVector(aliased_set_->max_place_id());
+ BitVector* forwarded_loads = new BitVector(aliased_set_->max_place_id());
bool changed = true;
while (changed) {
@@ -4321,74 +4631,160 @@
BitVector* block_kill = kill_[preorder_number];
BitVector* block_gen = gen_[preorder_number];
- if (FLAG_trace_optimization) {
- OS::Print("B%"Pd"", block->block_id());
- block_in->Print();
- block_out->Print();
- block_kill->Print();
- block_gen->Print();
- OS::Print("\n");
- }
-
- ZoneGrowableArray<Definition*>* block_out_values =
- out_values_[preorder_number];
-
// Compute block_in as the intersection of all out(p) where p
// is a predecessor of the current block.
if (block->IsGraphEntry()) {
temp->Clear();
} else {
- // TODO(vegorov): this can be optimized for the case of a single
- // predecessor.
- // TODO(vegorov): this can be reordered to reduce amount of operations
- // temp->CopyFrom(first_predecessor)
temp->SetAll();
ASSERT(block->PredecessorCount() > 0);
for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
BlockEntryInstr* pred = block->PredecessorAt(i);
BitVector* pred_out = out_[pred->preorder_number()];
- temp->Intersect(pred_out);
+ if (pred_out != NULL) {
+ temp->Intersect(pred_out);
+ }
}
}
- if (!temp->Equals(*block_in)) {
+ if (!temp->Equals(*block_in) || (block_out == NULL)) {
// If IN set has changed propagate the change to OUT set.
block_in->CopyFrom(temp);
- if (block_out->KillAndAdd(block_kill, block_in)) {
- // If OUT set has changed then we have new values available out of
- // the block. Compute these values creating phi where necessary.
- for (BitVector::Iterator it(block_out);
- !it.Done();
- it.Advance()) {
- const intptr_t expr_id = it.Current();
- if (block_out_values == NULL) {
- out_values_[preorder_number] = block_out_values =
- CreateBlockOutValues();
- }
+ temp->RemoveAll(block_kill);
+ temp->AddAll(block_gen);
- if ((*block_out_values)[expr_id] == NULL) {
- ASSERT(block->PredecessorCount() > 0);
- (*block_out_values)[expr_id] =
- MergeIncomingValues(block, expr_id);
- }
+ PhiPlaceMoves::MovesList phi_moves =
+ aliased_set_->phi_moves()->GetOutgoingMoves(block);
+ if (phi_moves != NULL) {
+ PerformPhiMoves(phi_moves, temp, forwarded_loads);
+ }
+
+ if ((block_out == NULL) || !block_out->Equals(*temp)) {
+ if (block_out == NULL) {
+ block_out = out_[preorder_number] =
+ new BitVector(aliased_set_->max_place_id());
}
+ block_out->CopyFrom(temp);
changed = true;
}
}
-
- if (FLAG_trace_optimization) {
- OS::Print("after B%"Pd"", block->block_id());
- block_in->Print();
- block_out->Print();
- block_kill->Print();
- block_gen->Print();
- OS::Print("\n");
- }
}
}
}
+ // Compute out_values mappings by propagating them in reverse postorder once
+ // through the graph. Generate phis on back edges where eager merge is
+ // impossible.
+ // No replacement is done at this point and thus any out_value[place_id] is
+ // changed at most once: from NULL to an actual value.
+ // When merging incoming loads we might need to create a phi.
+ // These phis are not inserted at the graph immediately because some of them
+ // might become redundant after load forwarding is done.
+ void ComputeOutValues() {
+ GrowableArray<PhiInstr*> pending_phis(5);
+ ZoneGrowableArray<Definition*>* temp_forwarded_values = NULL;
+
+ for (BlockIterator block_it = graph_->reverse_postorder_iterator();
+ !block_it.Done();
+ block_it.Advance()) {
+ BlockEntryInstr* block = block_it.Current();
+
+ const bool can_merge_eagerly = CanMergeEagerly(block);
+
+ const intptr_t preorder_number = block->preorder_number();
+
+ ZoneGrowableArray<Definition*>* block_out_values =
+ out_values_[preorder_number];
+
+
+ // If OUT set has changed then we have new values available out of
+ // the block. Compute these values creating phi where necessary.
+ for (BitVector::Iterator it(out_[preorder_number]);
+ !it.Done();
+ it.Advance()) {
+ const intptr_t place_id = it.Current();
+
+ if (block_out_values == NULL) {
+ out_values_[preorder_number] = block_out_values =
+ CreateBlockOutValues();
+ }
+
+ if ((*block_out_values)[place_id] == NULL) {
+ ASSERT(block->PredecessorCount() > 0);
+ Definition* in_value = can_merge_eagerly ?
+ MergeIncomingValues(block, place_id) : NULL;
+ if ((in_value == NULL) &&
+ (in_[preorder_number]->Contains(place_id))) {
+ PhiInstr* phi = new PhiInstr(block->AsJoinEntry(),
+ block->PredecessorCount());
+ phi->set_place_id(place_id);
+ pending_phis.Add(phi);
+ in_value = phi;
+ }
+ (*block_out_values)[place_id] = in_value;
+ }
+ }
+
+ // If the block has outgoing phi moves perform them. Use temporary list
+ // of values to ensure that cyclic moves are performed correctly.
+ PhiPlaceMoves::MovesList phi_moves =
+ aliased_set_->phi_moves()->GetOutgoingMoves(block);
+ if ((phi_moves != NULL) && (block_out_values != NULL)) {
+ if (temp_forwarded_values == NULL) {
+ temp_forwarded_values = CreateBlockOutValues();
+ }
+
+ for (intptr_t i = 0; i < phi_moves->length(); i++) {
+ const intptr_t from = (*phi_moves)[i].from();
+ const intptr_t to = (*phi_moves)[i].to();
+ if (from == to) continue;
+
+ (*temp_forwarded_values)[to] = (*block_out_values)[from];
+ }
+
+ for (intptr_t i = 0; i < phi_moves->length(); i++) {
+ const intptr_t from = (*phi_moves)[i].from();
+ const intptr_t to = (*phi_moves)[i].to();
+ if (from == to) continue;
+
+ (*block_out_values)[to] = (*temp_forwarded_values)[to];
+ }
+ }
+
+ if (FLAG_trace_load_optimization) {
+ OS::Print("B%"Pd"\n", block->block_id());
+ OS::Print(" IN: ");
+ aliased_set_->PrintSet(in_[preorder_number]);
+ OS::Print("\n");
+
+ OS::Print(" KILL: ");
+ aliased_set_->PrintSet(kill_[preorder_number]);
+ OS::Print("\n");
+
+ OS::Print(" OUT: ");
+ aliased_set_->PrintSet(out_[preorder_number]);
+ OS::Print("\n");
+ }
+ }
+
+ // All blocks were visited. Fill pending phis with inputs
+ // that flow on back edges.
+ for (intptr_t i = 0; i < pending_phis.length(); i++) {
+ FillPhiInputs(pending_phis[i]);
+ }
+ }
+
+ bool CanMergeEagerly(BlockEntryInstr* block) {
+ for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
+ BlockEntryInstr* pred = block->PredecessorAt(i);
+ if (pred->postorder_number() < block->postorder_number()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
void MarkLoopInvariantLoads() {
const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
graph_->loop_headers();
@@ -4404,7 +4800,7 @@
continue;
}
- BitVector* loop_gen = new BitVector(aliased_set_->max_expr_id());
+ BitVector* loop_gen = new BitVector(aliased_set_->max_place_id());
for (BitVector::Iterator loop_it(header->loop_info());
!loop_it.Done();
loop_it.Advance()) {
@@ -4421,8 +4817,8 @@
if (FLAG_trace_optimization) {
for (BitVector::Iterator it(loop_gen); !it.Done(); it.Advance()) {
- OS::Print("load %"Pd" is loop invariant for B%"Pd"\n",
- it.Current(),
+ OS::Print("place %s is loop invariant for B%"Pd"\n",
+ aliased_set_->places()[it.Current()]->ToCString(),
header->block_id());
}
}
@@ -4436,41 +4832,53 @@
// Compute incoming value for the given expression id.
// Will create a phi if different values are incoming from multiple
// predecessors.
- Definition* MergeIncomingValues(BlockEntryInstr* block, intptr_t expr_id) {
+ Definition* MergeIncomingValues(BlockEntryInstr* block, intptr_t place_id) {
// First check if the same value is coming in from all predecessors.
+ static Definition* const kDifferentValuesMarker =
+ reinterpret_cast<Definition*>(-1);
Definition* incoming = NULL;
for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
BlockEntryInstr* pred = block->PredecessorAt(i);
ZoneGrowableArray<Definition*>* pred_out_values =
out_values_[pred->preorder_number()];
- if (incoming == NULL) {
- incoming = (*pred_out_values)[expr_id];
- } else if (incoming != (*pred_out_values)[expr_id]) {
- incoming = NULL;
- break;
+ if ((pred_out_values == NULL) || ((*pred_out_values)[place_id] == NULL)) {
+ return NULL;
+ } else if (incoming == NULL) {
+ incoming = (*pred_out_values)[place_id];
+ } else if (incoming != (*pred_out_values)[place_id]) {
+ incoming = kDifferentValuesMarker;
}
}
- if (incoming != NULL) {
+ if (incoming != kDifferentValuesMarker) {
+ ASSERT(incoming != NULL);
return incoming;
}
// Incoming values are different. Phi is required to merge.
PhiInstr* phi = new PhiInstr(
block->AsJoinEntry(), block->PredecessorCount());
+ phi->set_place_id(place_id);
+ FillPhiInputs(phi);
+ return phi;
+ }
+
+ void FillPhiInputs(PhiInstr* phi) {
+ BlockEntryInstr* block = phi->GetBlock();
+ const intptr_t place_id = phi->place_id();
for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
BlockEntryInstr* pred = block->PredecessorAt(i);
ZoneGrowableArray<Definition*>* pred_out_values =
out_values_[pred->preorder_number()];
- ASSERT((*pred_out_values)[expr_id] != NULL);
+ ASSERT((*pred_out_values)[place_id] != NULL);
// Sets of outgoing values are not linked into use lists so
// they might contain values that were replaced and removed
// from the graph by this iteration.
// To prevent using them we additionally mark definitions themselves
// as replaced and store a pointer to the replacement.
- Definition* replacement = (*pred_out_values)[expr_id]->Replacement();
+ Definition* replacement = (*pred_out_values)[place_id]->Replacement();
Value* input = new Value(replacement);
phi->SetInputAt(i, input);
replacement->AddInputUse(input);
@@ -4479,7 +4887,12 @@
phi->set_ssa_temp_index(graph_->alloc_ssa_temp_index());
phis_.Add(phi); // Postpone phi insertion until after load forwarding.
- return phi;
+ if (FLAG_trace_load_optimization) {
+ OS::Print("created pending phi %s for %s at B%"Pd"\n",
+ phi->ToCString(),
+ aliased_set_->places()[place_id]->ToCString(),
+ block->block_id());
+ }
}
// Iterate over basic blocks and replace exposed loads with incoming
@@ -4498,9 +4911,10 @@
for (intptr_t i = 0; i < loads->length(); i++) {
Definition* load = (*loads)[i];
- if (!in->Contains(load->expr_id())) continue; // No incoming value.
+ if (!in->Contains(load->place_id())) continue; // No incoming value.
- Definition* replacement = MergeIncomingValues(block, load->expr_id());
+ Definition* replacement = MergeIncomingValues(block, load->place_id());
+ ASSERT(replacement != NULL);
// Sets of outgoing values are not linked into use lists so
// they might contain values that were replace and removed
@@ -4580,16 +4994,117 @@
return true;
}
+ bool AddPhiPairToWorklist(PhiInstr* a, PhiInstr* b) {
+ // Can't compare two phis from different blocks.
+ if (a->block() != b->block()) {
+ return false;
+ }
+
+ // If a is already in the worklist check if it is being compared to b.
+ // Give up if it is not.
+ if (in_worklist_->Contains(a->ssa_temp_index())) {
+ for (intptr_t i = 0; i < worklist_.length(); i += 2) {
+ if (a == worklist_[i]) {
+ return (b == worklist_[i + 1]);
+ }
+ }
+ UNREACHABLE();
+ }
+
+ worklist_.Add(a);
+ worklist_.Add(b);
+ in_worklist_->Add(a->ssa_temp_index());
+ return true;
+ }
+
+ // Replace the given phi with another if they are equal.
+ // Returns true if succeeds.
+ bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) {
+ ASSERT(phi->InputCount() == replacement->InputCount());
+ ASSERT(phi->block() == replacement->block());
+
+ worklist_.Clear();
+ if (in_worklist_ == NULL) {
+ in_worklist_ = new BitVector(graph_->current_ssa_temp_index());
+ } else {
+ in_worklist_->Clear();
+ }
+
+ // During the comparison worklist contains pairs of phis to be compared.
+ AddPhiPairToWorklist(phi, replacement);
+
+ // Process the worklist. It might grow during each comparison step.
+ for (intptr_t i = 0; i < worklist_.length(); i += 2) {
+ PhiInstr* a = worklist_[i];
+ PhiInstr* b = worklist_[i + 1];
+
+ // Compare phi inputs.
+ for (intptr_t j = 0; j < a->InputCount(); j++) {
+ Definition* inputA = a->InputAt(j)->definition();
+ Definition* inputB = b->InputAt(j)->definition();
+
+ if (inputA != inputB) {
+ // If inputs are unequal by they are phis then add them to
+ // the worklist for recursive comparison.
+ if (inputA->IsPhi() && inputB->IsPhi() &&
+ AddPhiPairToWorklist(inputA->AsPhi(), inputB->AsPhi())) {
+ continue;
+ }
+ return false; // Not equal.
+ }
+ }
+ }
+
+ // At this point worklist contains pairs of equal phis. Replace the first
+ // phi in the pair with the second.
+ for (intptr_t i = 0; i < worklist_.length(); i += 2) {
+ PhiInstr* a = worklist_[i];
+ PhiInstr* b = worklist_[i + 1];
+ a->ReplaceUsesWith(b);
+ if (a->is_alive()) {
+ a->mark_dead();
+ a->block()->RemovePhi(a);
+ }
+ }
+
+ return true;
+ }
+
+ // Insert the given phi into the graph. Attempt to find an equal one in the
+ // target block first.
+ // Returns true if the phi was inserted and false if it was replaced.
+ bool EmitPhi(PhiInstr* phi) {
+ for (PhiIterator it(phi->block()); !it.Done(); it.Advance()) {
+ if (ReplacePhiWith(phi, it.Current())) {
+ return false;
+ }
+ }
+
+ phi->mark_alive();
+ phi->block()->InsertPhi(phi);
+ return true;
+ }
+
// Phis have not yet been inserted into the graph but they have uses of
// their inputs. Insert the non-redundant ones and clear the input uses
// of the redundant ones.
void EmitPhis() {
+ // First eliminate all redundant phis.
for (intptr_t i = 0; i < phis_.length(); i++) {
PhiInstr* phi = phis_[i];
- if (phi->HasUses() && !EliminateRedundantPhi(phi)) {
- phi->mark_alive();
- phi->block()->InsertPhi(phi);
- } else {
+ if (!phi->HasUses() || EliminateRedundantPhi(phi)) {
+ for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) {
+ phi->InputAt(j)->RemoveFromUseList();
+ }
+ phis_[i] = NULL;
+ }
+ }
+
+ // Now emit phis or replace them with equal phis already present in the
+ // graph.
+ for (intptr_t i = 0; i < phis_.length(); i++) {
+ PhiInstr* phi = phis_[i];
+ if ((phi != NULL) && (!phi->HasUses() || !EmitPhi(phi))) {
for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) {
phi->InputAt(j)->RemoveFromUseList();
}
@@ -4599,15 +5114,15 @@
ZoneGrowableArray<Definition*>* CreateBlockOutValues() {
ZoneGrowableArray<Definition*>* out =
- new ZoneGrowableArray<Definition*>(aliased_set_->max_expr_id());
- for (intptr_t i = 0; i < aliased_set_->max_expr_id(); i++) {
+ new ZoneGrowableArray<Definition*>(aliased_set_->max_place_id());
+ for (intptr_t i = 0; i < aliased_set_->max_place_id(); i++) {
out->Add(NULL);
}
return out;
}
FlowGraph* graph_;
- DirectChainedHashMap<LoadKeyValueTrait>* map_;
+ DirectChainedHashMap<PointerKeyValueTrait<Place> >* map_;
// Mapping between field offsets in words and expression ids of loads from
// that offset.
@@ -6059,7 +6574,7 @@
comparison->kind(),
left,
right,
- Array::Handle());
+ Object::null_array());
new_equality_compare->set_ic_data(equality_compare->ic_data());
new_comparison = new_equality_compare;
} else {
@@ -6070,7 +6585,7 @@
comparison->kind(),
left,
right,
- Array::Handle());
+ Object::null_array());
new_relational_op->set_ic_data(relational_op->ic_data());
new_comparison = new_relational_op;
}
@@ -6422,6 +6937,13 @@
OS::Print("discovered allocation sinking candidate: v%"Pd"\n",
alloc->ssa_temp_index());
}
+
+ if (alloc->identity() == AllocateObjectInstr::kAliased) {
+ // Allocation might have been classified as aliased earlier due to
+ // some operations that are now eliminated.
+ alloc->set_identity(AllocateObjectInstr::kNotAliased);
+ }
+
candidates.Add(alloc);
}
}
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index 9f08b7a..7672716 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -228,6 +228,7 @@
friend class HandleScope;
friend class Dart;
friend class ObjectStore;
+ friend class Isolate;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(Handles);
};
@@ -338,7 +339,7 @@
#endif // defined(DEBUG)
// Macro to start a no handles scope in the code.
-#define NOHANDLESCOPE(isolate) \
+#define NOHANDLESCOPE(isolate) \
dart::NoHandleScope no_vm_internal_handles_scope_(isolate);
} // namespace dart
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 47fa64b..cdddcd7 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -37,6 +37,7 @@
FlowGraphPrinter printer(*flow_graph);
printer.PrintBlocks();
OS::Print("*** END CFG\n");
+ fflush(stdout);
}
@@ -131,8 +132,6 @@
}
-
-
static void PrintICData(BufferFormatter* f, const ICData& ic_data) {
f->Print(" IC[%"Pd": ", ic_data.NumberOfChecks());
Function& target = Function::Handle();
@@ -171,6 +170,14 @@
}
+const char* Instruction::ToCString() const {
+ char buffer[1024];
+ BufferFormatter f(buffer, sizeof(buffer));
+ PrintTo(&f);
+ return Isolate::Current()->current_zone()->MakeCopyOfString(buffer);
+}
+
+
void Instruction::PrintTo(BufferFormatter* f) const {
if (GetDeoptId() != Isolate::kNoDeoptId) {
f->Print("%s:%"Pd"(", DebugName(), GetDeoptId());
@@ -861,7 +868,7 @@
void CheckStackOverflowInstr::PrintOperandsTo(BufferFormatter* f) const {
- if (in_loop()) f->Print("loop");
+ if (in_loop()) f->Print("depth %"Pd, loop_depth());
}
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index 03f94e9..c896e11 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -119,7 +119,7 @@
}
-RawArray* CallPattern::ArgumentsDescriptor() {
+RawArray* CallPattern::ClosureArgumentsDescriptor() {
if (args_desc_.IsNull()) {
IcData(); // Loading of the ic_data must be decoded first, if not already.
Register reg;
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h
index f54328a..98230ae 100644
--- a/runtime/vm/instructions_arm.h
+++ b/runtime/vm/instructions_arm.h
@@ -20,7 +20,7 @@
CallPattern(uword pc, const Code& code);
RawICData* IcData();
- RawArray* ArgumentsDescriptor();
+ RawArray* ClosureArgumentsDescriptor();
uword TargetAddress() const;
void SetTargetAddress(uword target_address) const;
diff --git a/runtime/vm/instructions_mips.cc b/runtime/vm/instructions_mips.cc
index 197efd1..1f79afd 100644
--- a/runtime/vm/instructions_mips.cc
+++ b/runtime/vm/instructions_mips.cc
@@ -129,7 +129,7 @@
}
-RawArray* CallPattern::ArgumentsDescriptor() {
+RawArray* CallPattern::ClosureArgumentsDescriptor() {
if (args_desc_.IsNull()) {
IcData(); // Loading of the ic_data must be decoded first, if not already.
Register reg;
diff --git a/runtime/vm/instructions_mips.h b/runtime/vm/instructions_mips.h
index f9d7908..fc2ef10 100644
--- a/runtime/vm/instructions_mips.h
+++ b/runtime/vm/instructions_mips.h
@@ -20,7 +20,7 @@
CallPattern(uword pc, const Code& code);
RawICData* IcData();
- RawArray* ArgumentsDescriptor();
+ RawArray* ClosureArgumentsDescriptor();
uword TargetAddress() const;
void SetTargetAddress(uword target_address) const;
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 87e5407..9ade377 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -937,6 +937,16 @@
phis_->Add(phi);
}
+void JoinEntryInstr::RemovePhi(PhiInstr* phi) {
+ ASSERT(phis_ != NULL);
+ for (intptr_t index = 0; index < phis_->length(); ++index) {
+ if (phi == (*phis_)[index]) {
+ (*phis_)[index] = phis_->Last();
+ phis_->RemoveLast();
+ return;
+ }
+ }
+}
void JoinEntryInstr::RemoveDeadPhis(Definition* replacement) {
if (phis_ == NULL) return;
@@ -1683,8 +1693,12 @@
void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ICData& call_ic_data = ICData::ZoneHandle(ic_data()->raw());
if (!FLAG_propagate_ic_data || !compiler->is_optimizing()) {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(ArgumentCount(),
+ argument_names()));
call_ic_data = ICData::New(compiler->parsed_function().function(),
function_name(),
+ arguments_descriptor,
deopt_id(),
checked_argument_count());
}
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 2285325..f4dc796 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -36,6 +36,7 @@
// (class-name, function-name, recognized enum, fingerprint).
// See intrinsifier for fingerprint computation.
#define RECOGNIZED_LIST(V) \
+ V(Object, Object., ObjectConstructor, 464682336) \
V(Object, get:_cid, ObjectCid, 732498573) \
V(_ObjectArray, get:length, ObjectArrayLength, 405297088) \
V(_ImmutableArray, get:length, ImmutableArrayLength, 433698233) \
@@ -640,7 +641,7 @@
previous_(NULL),
next_(NULL),
env_(NULL),
- expr_id_(kNoExprId) { }
+ place_id_(kNoPlaceId) { }
virtual Tag tag() const = 0;
@@ -731,6 +732,7 @@
virtual const char* DebugName() const = 0;
// Printing support.
+ const char* ToCString() const;
virtual void PrintTo(BufferFormatter* f) const;
virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -823,11 +825,10 @@
// Get the block entry for this instruction.
virtual BlockEntryInstr* GetBlock() const;
- // Id for load instructions used during load forwarding pass and later in
- // LICM.
- intptr_t expr_id() const { return expr_id_; }
- void set_expr_id(intptr_t expr_id) { expr_id_ = expr_id; }
- bool HasExprId() const { return expr_id_ != kNoExprId; }
+ // Place identifiers used by the load optimization pass.
+ intptr_t place_id() const { return place_id_; }
+ void set_place_id(intptr_t place_id) { place_id_ = place_id; }
+ bool HasPlaceId() const { return place_id_ != kNoPlaceId; }
// Returns a hash code for use with hash maps.
virtual intptr_t Hashcode() const;
@@ -927,7 +928,7 @@
virtual void RawSetInputAt(intptr_t i, Value* value) = 0;
enum {
- kNoExprId = -1
+ kNoPlaceId = -1
};
intptr_t deopt_id_;
@@ -935,7 +936,7 @@
Instruction* previous_;
Instruction* next_;
Environment* env_;
- intptr_t expr_id_;
+ intptr_t place_id_;
DISALLOW_COPY_AND_ASSIGN(Instruction);
};
@@ -1379,6 +1380,7 @@
void RemoveDeadPhis(Definition* replacement);
void InsertPhi(PhiInstr* phi);
+ void RemovePhi(PhiInstr* phi);
virtual void PrintTo(BufferFormatter* f) const;
@@ -1701,6 +1703,7 @@
// Phi is alive if it reaches a non-environment use.
bool is_alive() const { return is_alive_; }
void mark_alive() { is_alive_ = true; }
+ void mark_dead() { is_alive_ = false; }
virtual Representation RequiredInputRepresentation(intptr_t i) const {
return representation_;
@@ -2620,7 +2623,7 @@
checked_argument_count_(checked_argument_count) {
ASSERT(function_name.IsNotTemporaryScopedHandle());
ASSERT(!arguments->is_empty());
- ASSERT(argument_names.IsZoneHandle());
+ ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
ASSERT(Token::IsBinaryOperator(token_kind) ||
Token::IsPrefixOperator(token_kind) ||
Token::IsIndexOperator(token_kind) ||
@@ -3069,15 +3072,23 @@
StaticCallInstr(intptr_t token_pos,
const Function& function,
const Array& argument_names,
- ZoneGrowableArray<PushArgumentInstr*>* arguments)
- : token_pos_(token_pos),
+ ZoneGrowableArray<PushArgumentInstr*>* arguments,
+ const Array& ic_data_array)
+ : ic_data_(GetICData(ic_data_array)),
+ token_pos_(token_pos),
function_(function),
argument_names_(argument_names),
arguments_(arguments),
result_cid_(kDynamicCid),
is_known_list_constructor_(false) {
ASSERT(function.IsZoneHandle());
- ASSERT(argument_names.IsZoneHandle());
+ ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
+ }
+
+ // ICData for static calls carries call count.
+ const ICData* ic_data() const { return ic_data_; }
+ bool HasICData() const {
+ return (ic_data() != NULL) && !ic_data()->IsNull();
}
DECLARE_INSTRUCTION(StaticCall)
@@ -3109,6 +3120,7 @@
virtual bool MayThrow() const { return true; }
private:
+ const ICData* ic_data_;
const intptr_t token_pos_;
const Function& function_;
const Array& argument_names_;
@@ -5920,11 +5932,12 @@
class CheckStackOverflowInstr : public TemplateInstruction<0> {
public:
- CheckStackOverflowInstr(intptr_t token_pos, bool in_loop)
- : token_pos_(token_pos), in_loop_(in_loop) {}
+ CheckStackOverflowInstr(intptr_t token_pos, intptr_t loop_depth)
+ : token_pos_(token_pos), loop_depth_(loop_depth) {}
intptr_t token_pos() const { return token_pos_; }
- bool in_loop() const { return in_loop_; }
+ bool in_loop() const { return loop_depth_ > 0; }
+ intptr_t loop_depth() const { return loop_depth_; }
DECLARE_INSTRUCTION(CheckStackOverflow)
@@ -5940,7 +5953,7 @@
private:
const intptr_t token_pos_;
- const bool in_loop_;
+ const intptr_t loop_depth_;
DISALLOW_COPY_AND_ASSIGN(CheckStackOverflowInstr);
};
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index eacd243..d313806 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -152,6 +152,7 @@
Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
argument_names()));
__ LoadObject(temp_reg, arguments_descriptor);
+ ASSERT(temp_reg == R4);
compiler->GenerateDartCall(deopt_id(),
token_pos(),
&StubCode::CallClosureFunctionLabel(),
@@ -385,7 +386,7 @@
token_pos);
}
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
const int kNumArgumentsChecked = 2;
Label check_identity;
@@ -407,8 +408,12 @@
equality_ic_data = original_ic_data.AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments,
+ kNoArgumentNames));
equality_ic_data = ICData::New(compiler->parsed_function().function(),
Symbols::EqualOperator(),
+ arguments_descriptor,
deopt_id,
kNumArgumentsChecked);
}
@@ -545,7 +550,7 @@
}
} else {
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
compiler->GenerateStaticCall(deopt_id,
token_pos,
target,
@@ -926,7 +931,7 @@
compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
R2, // Class id register.
kNumArguments,
- Array::Handle(), // No named arguments.
+ Object::null_array(), // No named arguments.
deopt, // Deoptimize target.
deopt_id(),
token_pos(),
@@ -953,15 +958,19 @@
relational_ic_data = ic_data()->AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumArguments,
+ Object::null_array()));
relational_ic_data = ICData::New(compiler->parsed_function().function(),
function_name,
+ arguments_descriptor,
deopt_id(),
kNumArgsChecked);
}
compiler->GenerateInstanceCall(deopt_id(),
token_pos(),
kNumArguments,
- Array::ZoneHandle(), // No optional arguments.
+ Object::null_array(), // No optional args.
locs(),
relational_ic_data);
}
@@ -1358,8 +1367,6 @@
case kTypedDataUint8ArrayCid:
case kTypedDataUint8ClampedArrayCid:
case kOneByteStringCid:
- locs->set_in(2, Location::RegisterOrSmiConstant(value()));
- break;
case kTypedDataInt16ArrayCid:
case kTypedDataUint16ArrayCid:
case kTypedDataInt32ArrayCid:
@@ -1714,6 +1721,11 @@
}
+// When the parser is building an implicit static getter for optimization,
+// it can generate a function body where deoptimization ids do not line up
+// with the unoptimized code.
+//
+// This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register field = locs()->in(0).reg();
Register result = locs()->out().reg();
@@ -2151,8 +2163,8 @@
ShifterOperand(reinterpret_cast<int32_t>(Smi::New(max_right))));
__ b(deopt, CS);
}
- __ SmiUntag(right);
- __ Lsl(result, left, right);
+ __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
+ __ Lsl(result, left, IP);
}
return;
}
@@ -2173,11 +2185,11 @@
__ cmp(right,
ShifterOperand(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
__ mov(result, ShifterOperand(0), CS);
- __ SmiUntag(right, CC);
- __ Lsl(result, left, right, CC);
+ __ Asr(IP, right, kSmiTagSize, CC); // SmiUntag right into IP if CC.
+ __ Lsl(result, left, IP, CC);
} else {
- __ SmiUntag(right);
- __ Lsl(result, left, right);
+ __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
+ __ Lsl(result, left, IP);
}
} else {
if (right_needs_check) {
@@ -2188,13 +2200,14 @@
}
// Left is not a constant.
// Check if count too large for handling it inlined.
- __ SmiUntag(right);
- // Overflow test (preserve left and right);
- __ Lsl(IP, left, right);
- __ cmp(left, ShifterOperand(IP, ASR, right));
+ __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
+ // Overflow test (preserve left, right, and IP);
+ Register temp = locs.temp(0).reg();
+ __ Lsl(temp, left, IP);
+ __ cmp(left, ShifterOperand(temp, ASR, IP));
__ b(deopt, NE); // Overflow.
// Shift for result now we know there is no overflow.
- __ Lsl(result, left, right);
+ __ Lsl(result, left, IP);
}
}
@@ -2205,21 +2218,23 @@
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
if (op_kind() == Token::kTRUNCDIV) {
+ summary->set_in(0, Location::RequiresRegister());
if (RightIsPowerOfTwoConstant()) {
- summary->set_in(0, Location::RequiresRegister());
ConstantInstr* right_constant = right()->definition()->AsConstant();
summary->set_in(1, Location::Constant(right_constant->value()));
- summary->set_out(Location::RequiresRegister());
} else {
- // Both inputs must be writable because they will be untagged.
- summary->set_in(0, Location::WritableRegister());
- summary->set_in(1, Location::WritableRegister());
- summary->set_out(Location::RequiresRegister());
+ summary->set_in(1, Location::RequiresRegister());
}
+ summary->AddTemp(Location::RequiresRegister());
+ summary->set_out(Location::RequiresRegister());
return summary;
}
summary->set_in(0, Location::RequiresRegister());
summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+ if (((op_kind() == Token::kSHL) && !is_truncating()) ||
+ (op_kind() == Token::kSHR)) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
// We make use of 3-operand instructions by not requiring result register
// to be identical to first input register as on Intel.
summary->set_out(Location::RequiresRegister());
@@ -2238,7 +2253,7 @@
Register result = locs()->out().reg();
Label* deopt = NULL;
if (CanDeoptimize()) {
- deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
+ deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
}
if (locs()->in(1).IsConstant()) {
@@ -2302,9 +2317,10 @@
ASSERT(kSmiTagSize == 1);
__ mov(IP, ShifterOperand(left, ASR, 31));
ASSERT(shift_count > 1); // 1, -1 case handled above.
- __ add(left, left, ShifterOperand(IP, LSR, 32 - shift_count));
+ Register temp = locs()->temp(0).reg();
+ __ add(temp, left, ShifterOperand(IP, LSR, 32 - shift_count));
ASSERT(shift_count > 0);
- __ mov(result, ShifterOperand(left, ASR, shift_count));
+ __ mov(result, ShifterOperand(temp, ASR, shift_count));
if (value < 0) {
__ rsb(result, result, ShifterOperand(0));
}
@@ -2397,11 +2413,11 @@
break;
}
case Token::kMUL: {
- __ SmiUntag(left);
+ __ Asr(IP, left, kSmiTagSize); // SmiUntag left into IP.
if (deopt == NULL) {
- __ mul(result, left, right);
+ __ mul(result, IP, right);
} else {
- __ smull(result, IP, left, right);
+ __ smull(result, IP, IP, right);
// IP: result bits 32..63.
__ cmp(IP, ShifterOperand(result, ASR, 31));
__ b(deopt, NE);
@@ -2427,12 +2443,13 @@
// Handle divide by zero in runtime.
__ cmp(right, ShifterOperand(0));
__ b(deopt, EQ);
- __ SmiUntag(left);
- __ SmiUntag(right);
+ Register temp = locs()->temp(0).reg();
+ __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
+ __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
if (!CPUFeatures::integer_division_supported()) {
UNIMPLEMENTED();
}
- __ sdiv(result, left, right);
+ __ sdiv(result, temp, IP);
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
__ CompareImmediate(result, 0x40000000);
@@ -2445,17 +2462,18 @@
__ CompareImmediate(right, 0);
__ b(deopt, LT);
}
- __ SmiUntag(right);
+ __ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
// sarl operation masks the count to 5 bits.
const intptr_t kCountLimit = 0x1F;
Range* right_range = this->right()->definition()->range();
if ((right_range == NULL) ||
!right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
- __ CompareImmediate(right, kCountLimit);
- __ LoadImmediate(right, kCountLimit, GT);
+ __ CompareImmediate(IP, kCountLimit);
+ __ LoadImmediate(IP, kCountLimit, GT);
}
- __ SmiUntag(left);
- __ Asr(result, left, right);
+ Register temp = locs()->temp(0).reg();
+ __ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
+ __ Asr(result, temp, IP);
__ SmiTag(result);
break;
}
@@ -3011,7 +3029,7 @@
instance_call()->token_pos(),
target,
kNumberOfArguments,
- Array::Handle(), // No argument names.,
+ Object::null_array(), // No argument names.,
locs());
__ Bind(&done);
}
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index 444cd5c..2780369 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -108,17 +108,6 @@
}
-LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 0;
- const intptr_t kNumTemps = 1;
- LocationSummary* result =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
- result->set_out(Location::RegisterLocation(EAX));
- result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor.
- return result;
-}
-
-
LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 0;
return LocationSummary::Make(kNumInputs,
@@ -346,7 +335,7 @@
token_pos);
}
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
const int kNumArgumentsChecked = 2;
const Immediate& raw_null =
@@ -368,8 +357,12 @@
equality_ic_data = original_ic_data.AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments,
+ kNoArgumentNames));
equality_ic_data = ICData::New(compiler->parsed_function().function(),
Symbols::EqualOperator(),
+ arguments_descriptor,
deopt_id,
kNumArgumentsChecked);
}
@@ -496,7 +489,7 @@
}
} else {
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
compiler->GenerateStaticCall(deopt_id,
token_pos,
target,
@@ -985,7 +978,7 @@
compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
EDI, // Class id register.
kNumArguments,
- Array::Handle(), // No named arguments.
+ Object::null_array(), // No named arguments.
deopt, // Deoptimize target.
deopt_id(),
token_pos(),
@@ -1012,15 +1005,19 @@
relational_ic_data = ic_data()->AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumArguments,
+ Object::null_array()));
relational_ic_data = ICData::New(compiler->parsed_function().function(),
function_name,
+ arguments_descriptor,
deopt_id(),
kNumArgsChecked);
}
compiler->GenerateInstanceCall(deopt_id(),
token_pos(),
kNumArguments,
- Array::ZoneHandle(), // No optional arguments.
+ Object::null_array(), // No optional args.
locs(),
relational_ic_data);
}
@@ -1772,6 +1769,11 @@
}
+// When the parser is building an implicit static getter for optimization,
+// it can generate a function body where deoptimization ids do not line up
+// with the unoptimized code.
+//
+// This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register field = locs()->in(0).reg();
Register result = locs()->out().reg();
@@ -2147,12 +2149,15 @@
__ cmpl(ESP,
Address::Absolute(Isolate::Current()->stack_limit_address()));
__ j(BELOW_EQUAL, slow_path->entry_label());
- if (FLAG_use_osr && !compiler->is_optimizing() && in_loop()) {
+ if (compiler->CanOSRFunction() && in_loop()) {
// In unoptimized code check the usage counter to trigger OSR at loop
- // stack checks.
+ // stack checks. Use progressively higher thresholds for more deeply
+ // nested loops to attempt to hit outer loops with OSR when possible.
__ LoadObject(EDI, compiler->parsed_function().function());
+ intptr_t threshold =
+ FLAG_optimization_counter_threshold * (loop_depth() + 1);
__ cmpl(FieldAddress(EDI, Function::usage_counter_offset()),
- Immediate(2 * FLAG_optimization_counter_threshold));
+ Immediate(threshold));
__ j(GREATER_EQUAL, slow_path->entry_label());
}
__ Bind(slow_path->exit_label());
@@ -3723,7 +3728,7 @@
instance_call()->token_pos(),
target,
kNumberOfArguments,
- Array::Handle(), // No argument names.,
+ Object::null_array(), // No argument names.,
locs());
__ Bind(&done);
}
@@ -4643,6 +4648,17 @@
}
+LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 0;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* result =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ result->set_out(Location::RegisterLocation(EAX));
+ result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor.
+ return result;
+}
+
+
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// The arguments to the stub include the closure, as does the arguments
// descriptor.
@@ -4652,6 +4668,7 @@
Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
argument_names()));
__ LoadObject(temp_reg, arguments_descriptor);
+ ASSERT(temp_reg == EDX);
compiler->GenerateDartCall(deopt_id(),
token_pos(),
&StubCode::CallClosureFunctionLabel(),
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 813378d..bbb4f5e 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -153,6 +153,7 @@
const Array& arguments_descriptor =
Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
argument_names()));
+ ASSERT(temp_reg == S4);
__ LoadObject(temp_reg, arguments_descriptor);
compiler->GenerateDartCall(deopt_id(),
token_pos(),
@@ -383,7 +384,7 @@
token_pos);
}
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
const int kNumArgumentsChecked = 2;
__ TraceSimMsg("EmitEqualityAsInstanceCall");
@@ -406,8 +407,12 @@
equality_ic_data = original_ic_data.AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments,
+ kNoArgumentNames));
equality_ic_data = ICData::New(compiler->parsed_function().function(),
Symbols::EqualOperator(),
+ arguments_descriptor,
deopt_id,
kNumArgumentsChecked);
}
@@ -575,7 +580,7 @@
}
} else {
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
compiler->GenerateStaticCall(deopt_id,
token_pos,
target,
@@ -985,7 +990,7 @@
compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
A2, // Class id register.
kNumArguments,
- Array::Handle(), // No named arguments.
+ Object::null_array(), // No named arguments.
deopt, // Deoptimize target.
deopt_id(),
token_pos(),
@@ -1012,15 +1017,19 @@
relational_ic_data = ic_data()->AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumArguments,
+ Object::null_array()));
relational_ic_data = ICData::New(compiler->parsed_function().function(),
function_name,
+ arguments_descriptor,
deopt_id(),
kNumArgsChecked);
}
compiler->GenerateInstanceCall(deopt_id(),
token_pos(),
kNumArguments,
- Array::ZoneHandle(), // No optional arguments.
+ Object::null_array(), // No optional args.
locs(),
relational_ic_data);
}
@@ -1416,8 +1425,6 @@
case kTypedDataUint8ArrayCid:
case kTypedDataUint8ClampedArrayCid:
case kOneByteStringCid:
- locs->set_in(2, Location::RegisterOrSmiConstant(value()));
- break;
case kTypedDataInt16ArrayCid:
case kTypedDataUint16ArrayCid:
case kTypedDataInt32ArrayCid:
@@ -1559,7 +1566,15 @@
break;
}
case kTypedDataFloat32ArrayCid:
+ // Convert to single precision.
+ __ cvtsd(STMP1, locs()->in(2).fpu_reg());
+ // Store.
+ __ swc1(STMP1, element_address);
+ break;
case kTypedDataFloat64ArrayCid:
+ __ StoreDToOffset(locs()->in(2).fpu_reg(), index.reg(),
+ FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
+ break;
case kTypedDataFloat32x4ArrayCid:
UNIMPLEMENTED();
break;
@@ -1773,6 +1788,11 @@
}
+// When the parser is building an implicit static getter for optimization,
+// it can generate a function body where deoptimization ids do not line up
+// with the unoptimized code.
+//
+// This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ TraceSimMsg("LoadStaticFieldInstr");
Register field = locs()->in(0).reg();
@@ -2243,8 +2263,8 @@
__ BranchUnsignedGreaterEqual(
right, reinterpret_cast<int32_t>(Smi::New(max_right)), deopt);
}
- __ SmiUntag(right);
- __ sllv(result, left, right);
+ __ sra(TMP, right, kSmiTagMask); // SmiUntag right into TMP.
+ __ sllv(result, left, TMP);
}
return;
}
@@ -2271,8 +2291,8 @@
// result = right < kBits ? left << right : result.
__ movn(result, TMP1, CMPRES);
} else {
- __ SmiUntag(right);
- __ sllv(result, left, right);
+ __ sra(TMP, right, kSmiTagSize);
+ __ sllv(result, left, TMP);
}
} else {
if (right_needs_check) {
@@ -2282,13 +2302,14 @@
}
// Left is not a constant.
// Check if count too large for handling it inlined.
- __ SmiUntag(right);
- // Overflow test (preserve left and right);
- __ sllv(TMP1, left, right);
- __ srav(TMP1, TMP1, right);
- __ bne(TMP1, left, deopt); // Overflow.
+ __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
+ // Overflow test (preserve left, right, and TMP);
+ Register temp = locs.temp(0).reg();
+ __ sllv(temp, left, TMP);
+ __ srav(temp, temp, TMP);
+ __ bne(temp, left, deopt); // Overflow.
// Shift for result now we know there is no overflow.
- __ sllv(result, left, right);
+ __ sll(result, left, TMP);
}
}
@@ -2299,22 +2320,23 @@
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
if (op_kind() == Token::kTRUNCDIV) {
+ summary->set_in(0, Location::RequiresRegister());
if (RightIsPowerOfTwoConstant()) {
- summary->set_in(0, Location::RequiresRegister());
ConstantInstr* right_constant = right()->definition()->AsConstant();
summary->set_in(1, Location::Constant(right_constant->value()));
- summary->set_out(Location::RequiresRegister());
} else {
- // Both inputs must be writable because they will be untagged.
- summary->set_in(0, Location::WritableRegister());
- summary->set_in(1, Location::WritableRegister());
- summary->set_out(Location::RequiresRegister());
+ summary->set_in(1, Location::RequiresRegister());
}
+ summary->AddTemp(Location::RequiresRegister());
+ summary->set_out(Location::RequiresRegister());
return summary;
}
summary->set_in(0, Location::RequiresRegister());
summary->set_in(1, Location::RegisterOrSmiConstant(right()));
- if (op_kind() == Token::kADD) {
+ if (((op_kind() == Token::kSHL) && !is_truncating()) ||
+ (op_kind() == Token::kSHR)) {
+ summary->AddTemp(Location::RequiresRegister());
+ } else if (op_kind() == Token::kADD) {
// Need an extra temp for the overflow detection code.
summary->set_temp(0, Location::RequiresRegister());
}
@@ -2337,7 +2359,7 @@
Register result = locs()->out().reg();
Label* deopt = NULL;
if (CanDeoptimize()) {
- deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
+ deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp);
}
if (locs()->in(1).IsConstant()) {
@@ -2411,10 +2433,11 @@
ASSERT(kSmiTagSize == 1);
__ sra(TMP, left, 31);
ASSERT(shift_count > 1); // 1, -1 case handled above.
- __ sll(TMP, TMP, 32 - shift_count);
- __ addu(left, left, TMP);
+ Register temp = locs()->temp(0).reg();
+ __ srl(TMP, TMP, 32 - shift_count);
+ __ addu(temp, left, TMP);
ASSERT(shift_count > 0);
- __ sra(result, left, shift_count);
+ __ sra(result, temp, shift_count);
if (value < 0) {
__ subu(result, ZR, result);
}
@@ -2509,8 +2532,8 @@
}
case Token::kMUL: {
__ TraceSimMsg("kMUL");
- __ SmiUntag(left);
- __ mult(left, right);
+ __ sra(TMP, left, kSmiTagSize);
+ __ mult(TMP, right);
__ mflo(result);
if (deopt != NULL) {
__ mfhi(TMP1);
@@ -2537,18 +2560,36 @@
case Token::kTRUNCDIV: {
// Handle divide by zero in runtime.
__ beq(right, ZR, deopt);
- __ SmiUntag(left);
- __ SmiUntag(right);
- __ div(left, right);
+ Register temp = locs()->temp(0).reg();
+ __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
+ __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
+ __ div(temp, TMP);
__ mflo(result);
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
- __ BranchEqual(V0, 0x40000000, deopt);
+ __ BranchEqual(result, 0x40000000, deopt);
__ SmiTag(result);
break;
}
case Token::kSHR: {
- UNIMPLEMENTED();
+ if (CanDeoptimize()) {
+ __ bltz(right, deopt);
+ }
+ __ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
+ // sra operation masks the count to 5 bits.
+ const intptr_t kCountLimit = 0x1F;
+ Range* right_range = this->right()->definition()->range();
+ if ((right_range == NULL) ||
+ !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
+ Label ok;
+ __ BranchSignedLessEqual(TMP, kCountLimit, &ok);
+ __ LoadImmediate(TMP, kCountLimit);
+ __ Bind(&ok);
+ }
+ Register temp = locs()->temp(0).reg();
+ __ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
+ __ srav(result, temp, TMP);
+ __ SmiTag(result);
break;
}
case Token::kDIV: {
@@ -2996,13 +3037,18 @@
LocationSummary* MathSqrtInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void MathSqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ __ sqrtd(locs()->out().fpu_reg(), locs()->in(0).fpu_reg());
}
@@ -3072,13 +3118,28 @@
LocationSummary* DoubleToSmiInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* result = new LocationSummary(
+ kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ result->set_in(0, Location::RequiresFpuRegister());
+ result->set_out(Location::RequiresRegister());
+ return result;
}
void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptDoubleToSmi);
+ Register result = locs()->out().reg();
+ DRegister value = locs()->in(0).fpu_reg();
+ __ cvtwd(STMP1, value);
+ __ mfc1(result, STMP1);
+
+ // Check for overflow and that it fits into Smi.
+ __ LoadImmediate(TMP, 0xC0000000);
+ __ subu(CMPRES, result, TMP);
+ __ bltz(CMPRES, deopt);
+ __ SmiTag(result);
}
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index a55f175..16cb424 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -274,17 +274,6 @@
}
-LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 0;
- const intptr_t kNumTemps = 1;
- LocationSummary* result =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
- result->set_out(Location::RegisterLocation(RAX));
- result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor.
- return result;
-}
-
-
LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 0;
return LocationSummary::Make(kNumInputs,
@@ -502,7 +491,7 @@
token_pos);
}
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
const int kNumArgumentsChecked = 2;
const Immediate& raw_null =
@@ -524,8 +513,12 @@
equality_ic_data = original_ic_data.AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments,
+ kNoArgumentNames));
equality_ic_data = ICData::New(compiler->parsed_function().function(),
Symbols::EqualOperator(),
+ arguments_descriptor,
deopt_id,
kNumArgumentsChecked);
}
@@ -653,7 +646,7 @@
}
} else {
const int kNumberOfArguments = 2;
- const Array& kNoArgumentNames = Array::Handle();
+ const Array& kNoArgumentNames = Object::null_array();
compiler->GenerateStaticCall(deopt_id,
token_pos,
target,
@@ -1013,7 +1006,7 @@
compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
RDI, // Class id register.
kNumArguments,
- Array::Handle(), // No named arguments.
+ Object::null_array(), // No named arguments.
deopt, // Deoptimize target.
deopt_id(),
token_pos(),
@@ -1040,15 +1033,19 @@
relational_ic_data = ic_data()->AsUnaryClassChecks();
}
} else {
+ const Array& arguments_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(kNumArguments,
+ Object::null_array()));
relational_ic_data = ICData::New(compiler->parsed_function().function(),
function_name,
+ arguments_descriptor,
deopt_id(),
kNumArgsChecked);
}
compiler->GenerateInstanceCall(deopt_id(),
token_pos(),
kNumArguments,
- Array::ZoneHandle(), // No optional arguments.
+ Object::null_array(), // No optional args.
locs(),
relational_ic_data);
}
@@ -1754,6 +1751,11 @@
}
+// When the parser is building an implicit static getter for optimization,
+// it can generate a function body where deoptimization ids do not line up
+// with the unoptimized code.
+//
+// This is safe only so long as LoadStaticFieldInstr cannot deoptimize.
void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register field = locs()->in(0).reg();
Register result = locs()->out().reg();
@@ -2132,12 +2134,15 @@
__ movq(temp, Immediate(Isolate::Current()->stack_limit_address()));
__ cmpq(RSP, Address(temp, 0));
__ j(BELOW_EQUAL, slow_path->entry_label());
- if (FLAG_use_osr && !compiler->is_optimizing() && in_loop()) {
+ if (compiler->CanOSRFunction() && in_loop()) {
// In unoptimized code check the usage counter to trigger OSR at loop
- // stack checks.
+ // stack checks. Use progressively higher thresholds for more deeply
+ // nested loops to attempt to hit outer loops with OSR when possible.
__ LoadObject(temp, compiler->parsed_function().function());
+ intptr_t threshold =
+ FLAG_optimization_counter_threshold * (loop_depth() + 1);
__ cmpq(FieldAddress(temp, Function::usage_counter_offset()),
- Immediate(2 * FLAG_optimization_counter_threshold));
+ Immediate(threshold));
__ j(GREATER_EQUAL, slow_path->entry_label());
}
__ Bind(slow_path->exit_label());
@@ -3786,7 +3791,7 @@
instance_call()->token_pos(),
target,
kNumberOfArguments,
- Array::Handle(), // No argument names.
+ Object::null_array(), // No argument names.
locs());
__ Bind(&done);
}
@@ -4313,6 +4318,17 @@
}
+LocationSummary* ClosureCallInstr::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 0;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* result =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
+ result->set_out(Location::RegisterLocation(RAX));
+ result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor.
+ return result;
+}
+
+
void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// The arguments to the stub include the closure, as does the arguments
// descriptor.
@@ -4322,6 +4338,7 @@
Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
argument_names()));
__ LoadObject(temp_reg, arguments_descriptor);
+ ASSERT(temp_reg == R10);
compiler->GenerateDartCall(deopt_id(),
token_pos(),
&StubCode::CallClosureFunctionLabel(),
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 1e2dd8b..18b4744 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -243,7 +243,7 @@
__ StoreIntoObject(R0,
FieldAddress(R1, Array::data_offset()),
R2);
- // Caller is responsible of preserving the value if necessary.
+ // Caller is responsible for preserving the value if necessary.
__ Ret();
__ Bind(&fall_through);
return false;
@@ -869,23 +869,23 @@
__ bx(LR, EQ);
// Arguments are Smi but the shift produced an overflow to Mint.
- __ CompareImmediate(R6, 0);
+ __ CompareImmediate(R1, 0);
__ b(&fall_through, LT);
- __ SmiUntag(R6);
+ __ SmiUntag(R1);
- // Pull off high bits that will be shifted off of R6 by making a mask
- // ((1 << R0) - 1), shifting it to the left, masking R6, then shifting back.
- // high bits = (((1 << R0) - 1) << (32 - R0)) & R6) >> (32 - R0)
- // lo bits = R6 << R0
+ // Pull off high bits that will be shifted off of R1 by making a mask
+ // ((1 << R0) - 1), shifting it to the left, masking R1, then shifting back.
+ // high bits = (((1 << R0) - 1) << (32 - R0)) & R1) >> (32 - R0)
+ // lo bits = R1 << R0
__ LoadImmediate(R7, 1);
__ mov(R7, ShifterOperand(R7, LSL, R0)); // R7 <- 1 << R0
__ sub(R7, R7, ShifterOperand(1)); // R7 <- R7 - 1
__ rsb(R8, R0, ShifterOperand(32)); // R8 <- 32 - R0
__ mov(R7, ShifterOperand(R7, LSL, R8)); // R7 <- R7 << R8
- __ and_(R7, R6, ShifterOperand(R7)); // R7 <- R7 & R6
+ __ and_(R7, R1, ShifterOperand(R7)); // R7 <- R7 & R1
__ mov(R7, ShifterOperand(R7, LSR, R8)); // R7 <- R7 >> R8
- // Now R7 has the bits that fall off of R6 on a left shift.
- __ mov(R1, ShifterOperand(R6, LSL, R0)); // R1 gets the low bits.
+ // Now R7 has the bits that fall off of R1 on a left shift.
+ __ mov(R1, ShifterOperand(R1, LSL, R0)); // R1 gets the low bits.
const Class& mint_class = Class::Handle(
Isolate::Current()->object_store()->mint_class());
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 4f8588b..2627738 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -204,8 +204,8 @@
// Null value is valid for any type.
__ LoadImmediate(T7, reinterpret_cast<int32_t>(Object::null()));
__ beq(T2, T7, &checked_ok);
- __ delay_slot()->lw(T1, Address(SP, 2 * kWordSize)); // Array.
+ __ lw(T1, Address(SP, 2 * kWordSize)); // Array.
__ lw(T1, FieldAddress(T1, type_args_field_offset));
// T1: Type arguments of array.
@@ -232,8 +232,8 @@
__ andi(CMPRES, T1, Immediate(kSmiTagMask));
// Index not Smi.
__ bne(CMPRES, ZR, &fall_through);
- __ delay_slot()->lw(T0, Address(SP, 2 * kWordSize)); // Array.
+ __ lw(T0, Address(SP, 2 * kWordSize)); // Array.
// Range check.
__ lw(T3, FieldAddress(T0, Array::length_offset())); // Array length.
// Runtime throws exception.
@@ -248,7 +248,7 @@
__ StoreIntoObject(T0,
FieldAddress(T1, Array::data_offset()),
T2);
- // Caller is responsible of preserving the value if necessary.
+ // Caller is responsible for preserving the value if necessary.
__ Ret();
__ Bind(&fall_through);
return false;
@@ -864,10 +864,9 @@
// Check for overflow by shifting left and shifting back arithmetically.
// If the result is different from the original, there was overflow.
- __ mov(T2, T1);
- __ sllv(T1, T1, T0);
- __ srlv(T1, T1, T0);
- __ bne(T1, T2, &overflow);
+ __ sllv(TMP, T1, T0);
+ __ srav(TMP, TMP, T0);
+ __ bne(TMP, T1, &overflow);
// No overflow, result in V0.
__ Ret();
@@ -875,23 +874,23 @@
__ Bind(&overflow);
// Arguments are Smi but the shift produced an overflow to Mint.
- __ bltz(T2, &fall_through);
- __ SmiUntag(T2);
+ __ bltz(T1, &fall_through);
+ __ SmiUntag(T1);
- // Pull off high bits that will be shifted off of T2 by making a mask
- // ((1 << T0) - 1), shifting it to the right, masking T2, then shifting back.
- // high bits = (((1 << T0) - 1) << (32 - T0)) & T2) >> (32 - T0)
- // lo bits = T2 << T0
+ // Pull off high bits that will be shifted off of T1 by making a mask
+ // ((1 << T0) - 1), shifting it to the right, masking T1, then shifting back.
+ // high bits = (((1 << T0) - 1) << (32 - T0)) & T1) >> (32 - T0)
+ // lo bits = T1 << T0
__ LoadImmediate(T3, 1);
__ sllv(T3, T3, T0); // T3 <- T3 << T0
__ addiu(T3, T3, Immediate(-1)); // T3 <- T3 - 1
- __ addu(T4, ZR, T0); // T4 <- -T0
+ __ subu(T4, ZR, T0); // T4 <- -T0
__ addiu(T4, T4, Immediate(32)); // T4 <- 32 - T0
__ sllv(T3, T3, T4); // T3 <- T3 << T4
- __ and_(T3, T3, T2); // T3 <- T3 & T2
+ __ and_(T3, T3, T1); // T3 <- T3 & T1
__ srlv(T3, T3, T4); // T3 <- T3 >> T4
- // Now T3 has the bits that fall off of T2 on a left shift.
- __ sllv(T0, T2, T0); // T0 gets low bits.
+ // Now T3 has the bits that fall off of T1 on a left shift.
+ __ sllv(T0, T1, T0); // T0 gets low bits.
const Class& mint_class = Class::Handle(
Isolate::Current()->object_store()->mint_class());
@@ -1338,16 +1337,15 @@
bool Intrinsifier::Double_getIsNegative(Assembler* assembler) {
Label is_false, is_true, is_zero;
__ lw(T0, Address(SP, 0 * kWordSize));
- __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
- __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
+ __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
__ cund(D0, D0);
__ bc1t(&is_false); // NaN -> false.
+ __ LoadImmediate(D1, 0.0);
__ ceqd(D0, D1);
__ bc1t(&is_zero); // Check for negative zero.
- __ LoadImmediate(D1, 0.0);
__ coled(D1, D0);
__ bc1t(&is_false); // >= 0 -> false.
@@ -1372,14 +1370,17 @@
bool Intrinsifier::Double_toInt(Assembler* assembler) {
__ lw(T0, Address(SP, 0 * kWordSize));
- __ lwc1(F0, FieldAddress(T0, Double::value_offset()));
- __ lwc1(F1, FieldAddress(T0, Double::value_offset() + kWordSize));
+ __ LoadDFromOffset(D0, T0, Double::value_offset() - kHeapObjectTag);
+
__ cvtwd(F2, D0);
__ mfc1(V0, F2);
+
// Overflow is signaled with minint.
Label fall_through;
// Check for overflow and that it fits into Smi.
- __ BranchSignedLess(V0, 0xC0000000, &fall_through);
+ __ LoadImmediate(TMP, 0xC0000000);
+ __ subu(CMPRES, V0, TMP);
+ __ bltz(CMPRES, &fall_through);
__ Ret();
__ delay_slot()->SmiTag(V0);
__ Bind(&fall_through);
@@ -1448,24 +1449,25 @@
__ lw(T1, FieldAddress(T0, state_field.Offset())); // Field '_state'.
// Addresses of _state[0] and _state[1].
- const int64_t disp_0 =
- FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
+ const Address& addr_0 = FieldAddress(T1,
+ FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid));
- const int64_t disp_1 =
+ const Address& addr_1 = FieldAddress(T1,
FlowGraphCompiler::ElementSizeFor(kTypedDataUint32ArrayCid) +
- FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid);
+ FlowGraphCompiler::DataOffsetFor(kTypedDataUint32ArrayCid));
+
__ LoadImmediate(T0, a_int32_value);
- __ lw(T2, FieldAddress(T1, disp_0));
- __ lw(T3, FieldAddress(T1, disp_1));
+ __ lw(T2, addr_0);
+ __ lw(T3, addr_1);
__ sra(T6, T3, 31); // Sign extend T3 into T6.
__ mtlo(T3);
__ mthi(T6); // HI:LO <- T6:T3
// 64-bit multiply and accumulate into T6:T3.
- __ madd(T0, T2); // HI:LO <- HI:LO + T0 * T3.
+ __ madd(T0, T2); // HI:LO <- HI:LO + T0 * T2.
__ mflo(T3);
__ mfhi(T6);
- __ sw(T3, FieldAddress(T1, disp_0));
- __ sw(T6, FieldAddress(T1, disp_1));
+ __ sw(T3, addr_0);
+ __ sw(T6, addr_1);
__ Ret();
return true;
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 87a6d81..0e95ac0 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -371,6 +371,9 @@
}
+#define REUSABLE_HANDLE_INITIALIZERS(object) \
+ object##_handle_(NULL),
+
Isolate::Isolate()
: store_buffer_(),
message_notify_callback_(NULL),
@@ -399,6 +402,7 @@
running_state_(kIsolateWaiting),
gc_prologue_callbacks_(),
gc_epilogue_callbacks_(),
+ defer_finalization_count_(0),
deopt_cpu_registers_copy_(NULL),
deopt_fpu_registers_copy_(NULL),
deopt_frame_copy_(NULL),
@@ -409,11 +413,14 @@
deferred_objects_(NULL),
stacktrace_(NULL),
stack_frame_index_(-1),
- object_histogram_(NULL) {
+ object_histogram_(NULL),
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
+ reusable_handles_() {
if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) {
object_histogram_ = new ObjectHistogram(this);
}
}
+#undef REUSABLE_HANDLE_INITIALIZERS
Isolate::~Isolate() {
@@ -461,6 +468,13 @@
// the current isolate.
SetCurrent(result);
+ // Setup the isolate specific resuable handles.
+#define REUSABLE_HANDLE_ALLOCATION(object) \
+ result->object##_handle_ = result->AllocateReusableHandle<object>(); \
+
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION)
+#undef REUSABLE_HANDLE_ALLOCATION
+
// Setup the isolate message handler.
MessageHandler* handler = new IsolateMessageHandler(result);
ASSERT(handler != NULL);
@@ -825,6 +839,9 @@
// Visit objects in zones.
current_zone()->VisitObjectPointers(visitor);
+ // Visit objects in isolate specific handles area.
+ reusable_handles_.VisitObjectPointers(visitor);
+
// Iterate over all the stack frames and visit objects on the stack.
StackFrameIterator frames_iterator(validate_frames);
StackFrame* frame = frames_iterator.NextFrame();
@@ -1050,6 +1067,14 @@
}
+template<class T>
+T* Isolate::AllocateReusableHandle() {
+ T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle());
+ T::initializeHandle(handle, T::null());
+ return handle;
+}
+
+
static void FillDeferredSlots(DeferredSlot** slot_list) {
DeferredSlot* slot = *slot_list;
*slot_list = NULL;
@@ -1075,6 +1100,16 @@
}
+void ReusableHandleScope::ResetHandles() {
+#define CLEAR_REUSABLE_HANDLE(object) \
+ if (!object##Handle().IsNull()) { \
+ object##Handle().raw_ = Object::null(); \
+ }
+
+ REUSABLE_HANDLE_LIST(CLEAR_REUSABLE_HANDLE);
+}
+
+
static char* GetRootScriptUri(Isolate* isolate) {
const Library& library =
Library::Handle(isolate->object_store()->root_library());
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index a2e37c5..67ee82b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -11,6 +11,7 @@
#include "vm/base_isolate.h"
#include "vm/class_table.h"
#include "vm/gc_callbacks.h"
+#include "vm/handles.h"
#include "vm/megamorphic_cache_table.h"
#include "vm/store_buffer.h"
#include "vm/timer.h"
@@ -18,9 +19,13 @@
namespace dart {
// Forward declarations.
+class AbstractType;
class ApiState;
+class Array;
+class Class;
class CodeIndexTable;
class Debugger;
+class Field;
class Function;
class HandleScope;
class HandleVisitor;
@@ -30,6 +35,7 @@
class LongJump;
class MessageHandler;
class Mutex;
+class Object;
class ObjectPointerVisitor;
class ObjectStore;
class RawInstance;
@@ -40,12 +46,14 @@
class RawObject;
class RawInteger;
class RawError;
+class RawFloat32x4;
+class RawUint32x4;
class Simulator;
class StackResource;
class StackZone;
class StubCode;
-class RawFloat32x4;
-class RawUint32x4;
+class TypeArguments;
+class TypeParameter;
class ObjectHistogram;
@@ -217,6 +225,17 @@
DISALLOW_COPY_AND_ASSIGN(DeferredObject);
};
+#define REUSABLE_HANDLE_LIST(V) \
+ V(Object) \
+ V(Array) \
+ V(String) \
+ V(Instance) \
+ V(Function) \
+ V(Field) \
+ V(Class) \
+ V(AbstractType) \
+ V(TypeParameter) \
+ V(TypeArguments) \
class Isolate : public BaseIsolate {
public:
@@ -583,6 +602,21 @@
static char* GetStatus(const char* request);
+ intptr_t BlockClassFinalization() {
+ ASSERT(defer_finalization_count_ >= 0);
+ return defer_finalization_count_++;
+ }
+
+ intptr_t UnblockClassFinalization() {
+ ASSERT(defer_finalization_count_ > 0);
+ return defer_finalization_count_--;
+ }
+
+ bool AllowClassFinalization() {
+ ASSERT(defer_finalization_count_ >= 0);
+ return defer_finalization_count_ == 0;
+ }
+
private:
Isolate();
@@ -595,6 +629,7 @@
char* GetStatusStacktrace();
char* GetStatusStackFrame(intptr_t index);
char* DoStacktraceInterrupt(Dart_IsolateInterruptCallback cb);
+ template<class T> T* AllocateReusableHandle();
static ThreadLocalKey isolate_key;
StoreBuffer store_buffer_;
@@ -626,6 +661,7 @@
IsolateRunState running_state_;
GcPrologueCallbacks gc_prologue_callbacks_;
GcEpilogueCallbacks gc_epilogue_callbacks_;
+ intptr_t defer_finalization_count_;
// Deoptimization support.
intptr_t* deopt_cpu_registers_copy_;
@@ -643,6 +679,14 @@
intptr_t stack_frame_index_;
ObjectHistogram* object_histogram_;
+ // Reusable handles support.
+#define REUSABLE_HANDLE_FIELDS(object) \
+ object* object##_handle_; \
+
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_FIELDS)
+#undef REUSABLE_HANDLE_FIELDS
+ VMHandles reusable_handles_;
+
static Dart_IsolateCreateCallback create_callback_;
static Dart_IsolateInterruptCallback interrupt_callback_;
static Dart_IsolateUnhandledExceptionCallback unhandled_exception_callback_;
@@ -653,9 +697,85 @@
static Dart_FileCloseCallback file_close_callback_;
static Dart_IsolateInterruptCallback vmstats_callback_;
+ friend class ReusableHandleScope;
DISALLOW_COPY_AND_ASSIGN(Isolate);
};
+// The class ReusableHandleScope is used in regions of the
+// virtual machine where isolate specific reusable handles are used.
+// This class asserts that we do not add code that will result in recursive
+// uses of reusable handles.
+// It is used as follows:
+// {
+// ReusableHandleScope reused_handles(isolate);
+// ....
+// .....
+// code that uses isolate specific reusable handles.
+// Array& funcs = reused_handles.ArrayHandle();
+// ....
+// }
+#if defined(DEBUG)
+class ReusableHandleScope : public StackResource {
+ public:
+ explicit ReusableHandleScope(Isolate* isolate)
+ : StackResource(isolate), isolate_(isolate) {
+ ASSERT(!isolate->reusable_handle_scope_active());
+ isolate->set_reusable_handle_scope_active(true);
+ }
+ ReusableHandleScope()
+ : StackResource(Isolate::Current()), isolate_(Isolate::Current()) {
+ ASSERT(!isolate()->reusable_handle_scope_active());
+ isolate()->set_reusable_handle_scope_active(true);
+ }
+ ~ReusableHandleScope() {
+ ASSERT(isolate()->reusable_handle_scope_active());
+ isolate()->set_reusable_handle_scope_active(false);
+ ResetHandles();
+ }
+
+#define REUSABLE_HANDLE_ACCESSORS(object) \
+ object& object##Handle() { \
+ ASSERT(isolate_->object##_handle_ != NULL); \
+ return *isolate_->object##_handle_; \
+ } \
+
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ACCESSORS)
+#undef REUSABLE_HANDLE_ACCESSORS
+
+ private:
+ void ResetHandles();
+ Isolate* isolate_;
+ DISALLOW_COPY_AND_ASSIGN(ReusableHandleScope);
+};
+#else
+class ReusableHandleScope : public ValueObject {
+ public:
+ explicit ReusableHandleScope(Isolate* isolate) : isolate_(isolate) {
+ }
+ ReusableHandleScope() : isolate_(Isolate::Current()) {
+ }
+ ~ReusableHandleScope() {
+ ResetHandles();
+ }
+
+#define REUSABLE_HANDLE_ACCESSORS(object) \
+ object& object##Handle() { \
+ ASSERT(isolate_->object##_handle_ != NULL); \
+ return *isolate_->object##_handle_; \
+ } \
+
+ REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ACCESSORS)
+#undef REUSABLE_HANDLE_ACCESSORS
+
+ private:
+ void ResetHandles();
+ Isolate* isolate_;
+ DISALLOW_COPY_AND_ASSIGN(ReusableHandleScope);
+};
+#endif // defined(DEBUG)
+
+
+
// When we need to execute code in an isolate, we use the
// StartIsolateScope.
class StartIsolateScope {
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index c79d3ce..537c9ed 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -238,7 +238,8 @@
if (func.kind() == RawFunction::kImplicitGetter ||
func.kind() == RawFunction::kImplicitSetter ||
func.kind() == RawFunction::kConstImplicitGetter ||
- func.kind() == RawFunction::kMethodExtractor) {
+ func.kind() == RawFunction::kMethodExtractor ||
+ func.kind() == RawFunction::kNoSuchMethodDispatcher) {
continue;
}
diff --git a/runtime/vm/native_entry_test.cc b/runtime/vm/native_entry_test.cc
index 217c080..c8276f1 100644
--- a/runtime/vm/native_entry_test.cc
+++ b/runtime/vm/native_entry_test.cc
@@ -87,25 +87,4 @@
Dart_ExitScope();
}
-
-// Test code patching.
-void TestStaticCallPatching(Dart_NativeArguments args) {
- Dart_EnterScope();
- DartFrameIterator iterator;
- iterator.NextFrame(); // Skip native call.
- StackFrame* static_caller_frame = iterator.NextFrame();
- const Code& code = Code::Handle(static_caller_frame->LookupDartCode());
- uword target_address =
- CodePatcher::GetStaticCallTargetAt(static_caller_frame->pc(), code);
- const Function& target_function =
- Function::Handle(code.GetStaticCallTargetFunctionAt(
- static_caller_frame->pc()));
- EXPECT(String::Handle(target_function.name()).
- Equals(String::Handle(String::New("NativePatchStaticCall"))));
- const uword function_entry_address =
- Code::Handle(target_function.CurrentCode()).EntryPoint();
- EXPECT_EQ(function_entry_address, target_address);
- Dart_ExitScope();
-}
-
} // namespace dart
diff --git a/runtime/vm/native_entry_test.h b/runtime/vm/native_entry_test.h
index 0d4923a..2c34548 100644
--- a/runtime/vm/native_entry_test.h
+++ b/runtime/vm/native_entry_test.h
@@ -12,7 +12,6 @@
void TestSmiSub(Dart_NativeArguments args);
void TestSmiSum(Dart_NativeArguments args);
void TestNonNullSmiSum(Dart_NativeArguments args);
-void TestStaticCallPatching(Dart_NativeArguments args);
} // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c0e5a65..966aa45 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1614,25 +1614,34 @@
// To work properly, this call requires the super class of this class to be
// resolved, which is checked by the SuperClass() call.
Isolate* isolate = Isolate::Current();
- Class& cls = Class::Handle(isolate, raw());
+ ReusableHandleScope reused_handles(isolate);
+ Class& cls = reused_handles.ClassHandle();
+ TypeArguments& type_params = reused_handles.TypeArgumentsHandle();
+ AbstractType& sup_type = reused_handles.AbstractTypeHandle();
+ cls ^= raw();
intptr_t num_type_args = 0;
do {
if (cls.IsSignatureClass()) {
- const Function& signature_fun =
- Function::Handle(isolate, cls.signature_function());
+ Function& signature_fun = reused_handles.FunctionHandle();
+ signature_fun ^= cls.signature_function();
if (!signature_fun.is_static() &&
!signature_fun.HasInstantiatedSignature()) {
cls = signature_fun.Owner();
}
}
- num_type_args += cls.NumTypeParameters();
+ if (cls.type_parameters() != TypeArguments::null()) {
+ type_params ^= cls.type_parameters();
+ num_type_args += type_params.Length();
+ }
+
// Super type of Object class is null.
if (cls.super_type() == AbstractType::null() ||
cls.super_type() == isolate->object_store()->object_type()) {
break;
}
- cls = cls.SuperClass();
+ sup_type ^= cls.super_type();
+ cls = sup_type.type_class();
} while (true);
return num_type_args;
}
@@ -1653,7 +1662,10 @@
if (super_type() == AbstractType::null()) {
return Class::null();
}
- const AbstractType& sup_type = AbstractType::Handle(super_type());
+ Isolate* isolate = Isolate::Current();
+ ReusableHandleScope reused_handles(isolate);
+ AbstractType& sup_type = reused_handles.AbstractTypeHandle();
+ sup_type ^= super_type();
return sup_type.type_class();
}
@@ -1672,11 +1684,14 @@
RawTypeParameter* Class::LookupTypeParameter(const String& type_name,
intptr_t token_pos) const {
ASSERT(!type_name.IsNull());
- const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
+ Isolate* isolate = Isolate::Current();
+ ReusableHandleScope reused_handles(isolate);
+ TypeArguments& type_params = reused_handles.TypeArgumentsHandle();
+ type_params ^= type_parameters();
+ TypeParameter& type_param = reused_handles.TypeParameterHandle();
+ String& type_param_name = reused_handles.StringHandle();
if (!type_params.IsNull()) {
intptr_t num_type_params = type_params.Length();
- TypeParameter& type_param = TypeParameter::Handle();
- String& type_param_name = String::Handle();
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
type_param_name = type_param.name();
@@ -2449,12 +2464,14 @@
if (EnsureIsFinalized(isolate) != Error::null()) {
return Function::null();
}
- Array& funcs = Array::Handle(isolate, functions());
+ ReusableHandleScope reused_handles(isolate);
+ Array& funcs = reused_handles.ArrayHandle();
+ funcs ^= functions();
if (funcs.IsNull()) {
// This can occur, e.g., for Null classes.
return Function::null();
}
- Function& function = Function::Handle(isolate);
+ Function& function = reused_handles.FunctionHandle();
const intptr_t len = funcs.Length();
if (name.IsSymbol()) {
// Quick Symbol compare.
@@ -2466,7 +2483,7 @@
}
}
} else {
- String& function_name = String::Handle(isolate);
+ String& function_name = reused_handles.StringHandle();
for (intptr_t i = 0; i < len; i++) {
function ^= funcs.At(i);
function_name ^= function.name();
@@ -2486,13 +2503,15 @@
if (EnsureIsFinalized(isolate) != Error::null()) {
return Function::null();
}
- Array& funcs = Array::Handle(isolate, functions());
+ ReusableHandleScope reused_handles(isolate);
+ Array& funcs = reused_handles.ArrayHandle();
+ funcs ^= functions();
if (funcs.IsNull()) {
// This can occur, e.g., for Null classes.
return Function::null();
}
- Function& function = Function::Handle(isolate);
- String& function_name = String::Handle(isolate);
+ Function& function = reused_handles.FunctionHandle();
+ String& function_name = reused_handles.StringHandle();
intptr_t len = funcs.Length();
for (intptr_t i = 0; i < len; i++) {
function ^= funcs.At(i);
@@ -2523,9 +2542,11 @@
if (EnsureIsFinalized(isolate) != Error::null()) {
return Function::null();
}
- Array& funcs = Array::Handle(isolate, functions());
- Function& function = Function::Handle(isolate, Function::null());
- String& function_name = String::Handle(isolate, String::null());
+ ReusableHandleScope reused_handles(isolate);
+ Array& funcs = reused_handles.ArrayHandle();
+ funcs ^= functions();
+ Function& function = reused_handles.FunctionHandle();
+ String& function_name = reused_handles.StringHandle();
intptr_t len = funcs.Length();
for (intptr_t i = 0; i < len; i++) {
function ^= funcs.At(i);
@@ -2586,9 +2607,11 @@
if (EnsureIsFinalized(isolate) != Error::null()) {
return Field::null();
}
- const Array& flds = Array::Handle(isolate, fields());
- Field& field = Field::Handle(isolate, Field::null());
- String& field_name = String::Handle(isolate, String::null());
+ ReusableHandleScope reused_handles(isolate);
+ Array& flds = reused_handles.ArrayHandle();
+ flds ^= fields();
+ Field& field = reused_handles.FieldHandle();
+ String& field_name = reused_handles.StringHandle();
intptr_t len = flds.Length();
for (intptr_t i = 0; i < len; i++) {
field ^= flds.At(i);
@@ -4701,6 +4724,9 @@
case RawFunction::kMethodExtractor:
kind_str = " method-extractor";
break;
+ case RawFunction::kNoSuchMethodDispatcher:
+ kind_str = " no-such-method-dispatcher";
+ break;
default:
UNREACHABLE();
}
@@ -5363,8 +5389,7 @@
token_obj_(Object::Handle()),
literal_token_(LiteralToken::Handle()),
literal_str_(String::Handle()) {
- const String& empty_literal = String::Handle();
- token_objects_.Add(empty_literal);
+ token_objects_.Add(Object::null_string());
}
~CompressedTokenStreamData() {
}
@@ -6195,12 +6220,14 @@
RawObject* Library::LookupEntry(const String& name, intptr_t *index) const {
Isolate* isolate = Isolate::Current();
- const Array& dict = Array::Handle(isolate, dictionary());
+ ReusableHandleScope reused_handles(isolate);
+ Array& dict = reused_handles.ArrayHandle();
+ dict ^= dictionary();
intptr_t dict_size = dict.Length() - 1;
*index = name.Hash() % dict_size;
- Object& entry = Object::Handle(isolate);
- String& entry_name = String::Handle(isolate);
+ Object& entry = reused_handles.ObjectHandle();
+ String& entry_name = reused_handles.StringHandle();
entry = dict.At(*index);
// Search the entry in the hash set.
while (!entry.IsNull()) {
@@ -7284,17 +7311,18 @@
const char* PcDescriptors::KindAsStr(intptr_t index) const {
switch (DescriptorKind(index)) {
- case PcDescriptors::kDeopt: return "deopt ";
- case PcDescriptors::kEntryPatch: return "entry-patch ";
- case PcDescriptors::kPatchCode: return "patch ";
- case PcDescriptors::kLazyDeoptJump: return "lazy-deopt ";
- case PcDescriptors::kIcCall: return "ic-call ";
- case PcDescriptors::kFuncCall: return "fn-call ";
- case PcDescriptors::kClosureCall: return "closure-call ";
- case PcDescriptors::kReturn: return "return ";
- case PcDescriptors::kRuntimeCall: return "runtime-call ";
- case PcDescriptors::kOsrEntry: return "osr-entry ";
- case PcDescriptors::kOther: return "other ";
+ case PcDescriptors::kDeopt: return "deopt ";
+ case PcDescriptors::kEntryPatch: return "entry-patch ";
+ case PcDescriptors::kPatchCode: return "patch ";
+ case PcDescriptors::kLazyDeoptJump: return "lazy-deopt ";
+ case PcDescriptors::kIcCall: return "ic-call ";
+ case PcDescriptors::kOptStaticCall: return "opt-call ";
+ case PcDescriptors::kUnoptStaticCall: return "unopt-call ";
+ case PcDescriptors::kClosureCall: return "closure-call ";
+ case PcDescriptors::kReturn: return "return ";
+ case PcDescriptors::kRuntimeCall: return "runtime-call ";
+ case PcDescriptors::kOsrEntry: return "osr-entry ";
+ case PcDescriptors::kOther: return "other ";
}
UNREACHABLE();
return "";
@@ -8215,14 +8243,20 @@
ICData& ic_data_obj = ICData::Handle();
intptr_t max_id = -1;
for (intptr_t i = 0; i < descriptors.Length(); i++) {
- if (descriptors.DescriptorKind(i) == PcDescriptors::kIcCall) {
+ PcDescriptors::Kind kind = descriptors.DescriptorKind(i);
+ if ((kind == PcDescriptors::kIcCall) ||
+ (kind == PcDescriptors::kUnoptStaticCall)) {
intptr_t deopt_id = descriptors.DeoptId(i);
if (deopt_id > max_id) {
max_id = deopt_id;
}
node_ids->Add(deopt_id);
- CodePatcher::GetInstanceCallAt(descriptors.PC(i), *this,
- &ic_data_obj, NULL);
+ uword ret_addr = descriptors.PC(i);
+ if (kind == PcDescriptors::kIcCall) {
+ CodePatcher::GetInstanceCallAt(ret_addr, *this, &ic_data_obj);
+ } else {
+ CodePatcher::GetUnoptimizedStaticCallAt(ret_addr, *this, &ic_data_obj);
+ }
ic_data_objs.Add(ic_data_obj);
}
}
@@ -8247,26 +8281,6 @@
}
-void Code::ExtractUncalledStaticCallDeoptIds(
- GrowableArray<intptr_t>* deopt_ids) const {
- ASSERT(!IsNull() && !is_optimized());
- ASSERT(deopt_ids != NULL);
- deopt_ids->Clear();
- const PcDescriptors& descriptors =
- PcDescriptors::Handle(this->pc_descriptors());
- for (intptr_t i = 0; i < descriptors.Length(); i++) {
- if (descriptors.DescriptorKind(i) == PcDescriptors::kFuncCall) {
- // Static call.
- const uword target_addr =
- CodePatcher::GetStaticCallTargetAt(descriptors.PC(i), *this);
- if (target_addr == StubCode::CallStaticFunctionEntryPoint()) {
- deopt_ids->Add(descriptors.DeoptId(i));
- }
- }
- }
-}
-
-
RawStackmap* Code::GetStackmap(uword pc, Array* maps, Stackmap* map) const {
// This code is used during iterating frames during a GC and hence it
// should not in turn start a GC.
@@ -8456,6 +8470,10 @@
}
+void ICData::set_arguments_descriptor(const Array& value) const {
+ StorePointer(&raw_ptr()->args_descriptor_, value.raw());
+}
+
void ICData::set_deopt_id(intptr_t value) const {
raw_ptr()->deopt_id_ = value;
}
@@ -8527,6 +8545,25 @@
#endif // DEBUG
+// Used for unoptimized static calls when no class-ids are checked.
+void ICData::AddTarget(const Function& target) const {
+ ASSERT(num_args_tested() == 0);
+ // Can add only once.
+ const intptr_t old_num = NumberOfChecks();
+ ASSERT(old_num == 0);
+ Array& data = Array::Handle(ic_data());
+ const intptr_t new_len = data.Length() + TestEntryLength();
+ data = Array::Grow(data, new_len, Heap::kOld);
+ set_ic_data(data);
+ WriteSentinel(data);
+ intptr_t data_pos = old_num * TestEntryLength();
+ ASSERT(!target.IsNull());
+ data.SetAt(data_pos++, target);
+ const Smi& value = Smi::Handle(Smi::New(0));
+ data.SetAt(data_pos, value);
+}
+
+
void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
const Function& target) const {
DEBUG_ASSERT(!HasCheck(class_ids));
@@ -8666,6 +8703,7 @@
intptr_t ICData::AggregateCount() const {
+ if (IsNull()) return 0;
const intptr_t len = NumberOfChecks();
intptr_t count = 0;
for (intptr_t i = 0; i < len; i++) {
@@ -8697,6 +8735,7 @@
ICData& result = ICData::Handle(ICData::New(
Function::Handle(function()),
String::Handle(target_name()),
+ Array::Handle(arguments_descriptor()),
deopt_id(),
kNumArgsTested));
const intptr_t len = NumberOfChecks();
@@ -8792,10 +8831,11 @@
RawICData* ICData::New(const Function& function,
const String& target_name,
+ const Array& arguments_descriptor,
intptr_t deopt_id,
intptr_t num_args_tested) {
ASSERT(Object::icdata_class() != Class::null());
- ASSERT(num_args_tested > 0);
+ ASSERT(num_args_tested >= 0);
ICData& result = ICData::Handle();
{
// IC data objects are long living objects, allocate them in old generation.
@@ -8807,6 +8847,7 @@
}
result.set_function(function);
result.set_target_name(target_name);
+ result.set_arguments_descriptor(arguments_descriptor);
result.set_deopt_id(deopt_id);
result.set_num_args_tested(num_args_tested);
result.set_deopt_reason(kDeoptUnknown);
@@ -10630,7 +10671,8 @@
// Throw FiftyThreeBitOverflow exception.
static void ThrowFiftyThreeBitOverflow(const Integer& i) {
const Array& exc_args = Array::Handle(Array::New(1));
- exc_args.SetAt(0, i);
+ const String& i_str = String::Handle(String::New(i.ToCString()));
+ exc_args.SetAt(0, i_str);
Exceptions::ThrowByType(Exceptions::kFiftyThreeBitOverflowError, exc_args);
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 1f847b3..b307f6a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -32,6 +32,7 @@
class DeoptInstr;
class FinalizablePersistentHandle;
class LocalScope;
+class ReusableHandleScope;
class Symbols;
#if defined(DEBUG)
@@ -169,6 +170,7 @@
return raw()->ptr(); \
} \
SNAPSHOT_READER_SUPPORT(object) \
+ friend class Isolate; \
friend class StackFrame; \
// This macro is used to denote types that do not have a sub-type.
@@ -190,6 +192,7 @@
return raw()->ptr(); \
} \
SNAPSHOT_READER_SUPPORT(object) \
+ friend class Isolate; \
friend class StackFrame; \
class Object {
@@ -591,6 +594,8 @@
friend class TwoByteString;
friend class ExternalOneByteString;
friend class ExternalTwoByteString;
+ friend class Isolate;
+ friend class ReusableHandleScope;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(Object);
@@ -1395,6 +1400,10 @@
return kind() == RawFunction::kMethodExtractor;
}
+ bool IsNoSuchMethodDispatcher() const {
+ return kind() == RawFunction::kNoSuchMethodDispatcher;
+ }
+
// Returns true iff an implicit closure function has been created
// for this function.
bool HasImplicitClosureFunction() const {
@@ -1439,6 +1448,7 @@
case RawFunction::kImplicitGetter:
case RawFunction::kImplicitSetter:
case RawFunction::kMethodExtractor:
+ case RawFunction::kNoSuchMethodDispatcher:
return true;
case RawFunction::kClosureFunction:
case RawFunction::kConstructor:
@@ -2354,7 +2364,6 @@
friend class Class;
friend class Debugger;
friend class DictionaryIterator;
- friend class Isolate;
friend class Namespace;
friend class Object;
};
@@ -2390,7 +2399,6 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(LibraryPrefix, Object);
friend class Class;
- friend class Isolate;
};
@@ -2538,7 +2546,8 @@
kPatchCode, // Buffer for patching code entry.
kLazyDeoptJump, // Lazy deoptimization trampoline.
kIcCall, // IC call.
- kFuncCall, // Call to known target, e.g. static call.
+ kOptStaticCall, // Call directly to known target, e.g. static call.
+ kUnoptStaticCall, // Call to a known target via a stub.
kClosureCall, // Closure call.
kRuntimeCall, // Runtime call.
kReturn, // Return from function.
@@ -2982,11 +2991,6 @@
// Returns an array indexed by deopt id, containing the extracted ICData.
RawArray* ExtractTypeFeedbackArray() const;
- // Returns deopt-ids of all static calls that were never resolved, i.e.,
- // never executed.
- void ExtractUncalledStaticCallDeoptIds(
- GrowableArray<intptr_t>* deopt_ids) const;
-
private:
// An object finder visitor interface.
class FindRawCodeVisitor : public FindObjectVisitor {
@@ -3183,6 +3187,10 @@
return raw_ptr()->target_name_;
}
+ RawArray* arguments_descriptor() const {
+ return raw_ptr()->args_descriptor_;
+ }
+
intptr_t num_args_tested() const {
return raw_ptr()->num_args_tested_;
}
@@ -3217,6 +3225,10 @@
return OFFSET_OF(RawICData, num_args_tested_);
}
+ static intptr_t arguments_descriptor_offset() {
+ return OFFSET_OF(RawICData, args_descriptor_);
+ }
+
static intptr_t ic_data_offset() {
return OFFSET_OF(RawICData, ic_data_);
}
@@ -3229,6 +3241,9 @@
return OFFSET_OF(RawICData, is_closure_call_);
}
+ // Used for unoptimized static calls when no class-ids are checked.
+ void AddTarget(const Function& target) const;
+
// Adding checks.
// Adds one more class test to ICData. Length of 'classes' must be equal to
@@ -3274,6 +3289,7 @@
static RawICData* New(const Function& caller_function,
const String& target_name,
+ const Array& arguments_descriptor,
intptr_t deopt_id,
intptr_t num_args_tested);
@@ -3294,6 +3310,7 @@
void set_function(const Function& value) const;
void set_target_name(const String& value) const;
+ void set_arguments_descriptor(const Array& value) const;
void set_deopt_id(intptr_t value) const;
void set_num_args_tested(intptr_t value) const;
void set_ic_data(const Array& value) const;
@@ -5812,18 +5829,18 @@
}
-void Object::SetRaw(RawObject* value) {
+DART_FORCE_INLINE void Object::SetRaw(RawObject* value) {
// NOTE: The assignment "raw_ = value" should be the first statement in
// this function. Also do not use 'value' in this function after the
// assignment (use 'raw_' instead).
raw_ = value;
- if ((reinterpret_cast<uword>(raw_) & kSmiTagMask) == kSmiTag) {
+ if ((reinterpret_cast<uword>(value) & kSmiTagMask) == kSmiTag) {
set_vtable(Smi::handle_vtable_);
return;
}
- intptr_t cid = raw_->GetClassId();
+ intptr_t cid = value->GetClassId();
if (cid >= kNumPredefinedCids) {
- cid = kInstanceCid;
+ cid = kInstanceCid;
}
set_vtable(builtin_vtables_[cid]);
#if defined(DEBUG)
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index f235827..d545860 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -7,6 +7,7 @@
#include "vm/bigint_operations.h"
#include "vm/class_finalizer.h"
#include "vm/dart_api_impl.h"
+#include "vm/dart_entry.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"
@@ -2495,13 +2496,16 @@
const intptr_t id = 12;
const intptr_t num_args_tested = 1;
const String& target_name = String::Handle(String::New("Thun"));
+ const Array& args_descriptor =
+ Array::Handle(ArgumentsDescriptor::New(1, Object::null_array()));
ICData& o1 = ICData::Handle();
- o1 = ICData::New(function, target_name, id, num_args_tested);
+ o1 = ICData::New(function, target_name, args_descriptor, id, num_args_tested);
EXPECT_EQ(1, o1.num_args_tested());
EXPECT_EQ(id, o1.deopt_id());
EXPECT_EQ(function.raw(), o1.function());
EXPECT_EQ(0, o1.NumberOfChecks());
EXPECT_EQ(target_name.raw(), o1.target_name());
+ EXPECT_EQ(args_descriptor.raw(), o1.arguments_descriptor());
const Function& target1 = Function::Handle(GetDummyTarget("Thun"));
o1.AddReceiverCheck(kSmiCid, target1);
@@ -2525,7 +2529,7 @@
EXPECT_EQ(target2.raw(), test_target.raw());
ICData& o2 = ICData::Handle();
- o2 = ICData::New(function, target_name, 57, 2);
+ o2 = ICData::New(function, target_name, args_descriptor, 57, 2);
EXPECT_EQ(2, o2.num_args_tested());
EXPECT_EQ(57, o2.deopt_id());
EXPECT_EQ(function.raw(), o2.function());
@@ -2540,6 +2544,13 @@
EXPECT_EQ(kSmiCid, test_class_ids[0]);
EXPECT_EQ(kSmiCid, test_class_ids[1]);
EXPECT_EQ(target1.raw(), test_target.raw());
+
+ // Check ICData for unoptimized static calls.
+ const intptr_t kNumArgsChecked = 0;
+ const ICData& scall_icdata = ICData::Handle(
+ ICData::New(function, target_name, args_descriptor, 57, kNumArgsChecked));
+ scall_icdata.AddTarget(target1);
+ EXPECT_EQ(target1.raw(), scall_icdata.GetTargetAt(0));
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 0aec272..8773376 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -802,6 +802,9 @@
case RawFunction::kMethodExtractor:
node_sequence = parser.ParseMethodExtractor(func);
break;
+ case RawFunction::kNoSuchMethodDispatcher:
+ node_sequence = parser.ParseNoSuchMethodDispatcher(func);
+ break;
default:
UNREACHABLE();
}
@@ -920,6 +923,21 @@
const Field& field =
Field::ZoneHandle(field_class.LookupStaticField(field_name));
+ if (!field.is_const() &&
+ (field.value() != Object::transition_sentinel().raw()) &&
+ (field.value() != Object::sentinel().raw())) {
+ // The field has already been initialized at compile time (this can
+ // happen, e.g., if we are recompiling for optimization). There is no
+ // need to check for initialization and compile the potentially very
+ // large initialization code. By skipping this code, the deoptimization
+ // ids will not line up with the original code, but this is safe because
+ // LoadStaticField does not deoptimize.
+ LoadStaticFieldNode* load_node = new LoadStaticFieldNode(ident_pos, field);
+ ReturnNode* return_node = new ReturnNode(ident_pos, load_node);
+ current_block_->statements->Add(return_node);
+ return CloseBlock();
+ }
+
// Static const fields must have an initializer.
ExpectToken(Token::kASSIGN);
@@ -1119,6 +1137,46 @@
}
+SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func) {
+ TRACE_PARSER("ParseNoSuchMethodDispatcher");
+ ParamList params;
+
+ ASSERT(func.IsNoSuchMethodDispatcher());
+ intptr_t token_pos = func.token_pos();
+ ASSERT(func.token_pos() == 0);
+ ASSERT(current_class().raw() == func.Owner());
+ params.AddReceiver(ReceiverType(token_pos));
+ ASSERT(func.num_fixed_parameters() == 1); // Receiver.
+ ASSERT(!func.HasOptionalParameters());
+
+ // Build local scope for function and populate with the formal parameters.
+ OpenFunctionBlock(func);
+ LocalScope* scope = current_block_->scope;
+ AddFormalParamsToScope(¶ms, scope);
+
+ // Receiver is local 0.
+ LocalVariable* receiver = scope->VariableAt(0);
+ LoadLocalNode* load_receiver = new LoadLocalNode(token_pos, receiver);
+
+ ArgumentListNode* func_args = new ArgumentListNode(token_pos);
+ func_args->Add(load_receiver);
+ const String& func_name = String::ZoneHandle(func.name());
+ ArgumentListNode* arguments = BuildNoSuchMethodArguments(token_pos,
+ func_name,
+ *func_args);
+ const Function& no_such_method = Function::ZoneHandle(
+ Resolver::ResolveDynamicAnyArgs(Class::Handle(func.Owner()),
+ Symbols::NoSuchMethod()));
+ StaticCallNode* call =
+ new StaticCallNode(token_pos, no_such_method, arguments);
+
+
+ ReturnNode* return_node = new ReturnNode(token_pos, call);
+ current_block_->statements->Add(return_node);
+ return CloseBlock();
+}
+
+
void Parser::SkipBlock() {
ASSERT(CurrentToken() == Token::kLBRACE);
GrowableArray<Token::Kind> token_stack(8);
@@ -4363,9 +4421,13 @@
}
ErrorMsg(token_pos, "no library handler registered");
}
+ // Block class finalization attempts when calling into the library
+ // tag handler.
+ isolate()->BlockClassFinalization();
Dart_Handle result = handler(tag,
Api::NewHandle(isolate(), library_.raw()),
Api::NewHandle(isolate(), url.raw()));
+ isolate()->UnblockClassFinalization();
if (Dart_IsError(result)) {
// In case of an error we append an explanatory error message to the
// error obtained from the library tag handler.
@@ -8272,13 +8334,13 @@
ASSERT(arg->IsLiteralNode());
arg_values.SetAt((i + kNumExtraArgs), arg->AsLiteralNode()->literal());
}
- const Array& arg_descriptor =
+ const Array& args_descriptor =
Array::Handle(ArgumentsDescriptor::New(num_arguments,
arguments->names()));
const Object& result =
Object::Handle(DartEntry::InvokeFunction(constructor,
arg_values,
- arg_descriptor));
+ args_descriptor));
if (result.IsError()) {
// An exception may not occur in every parse attempt, i.e., the
// generated AST is not deterministic. Therefore mark the function as
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 00681dc..f80c674 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -63,7 +63,8 @@
return default_parameter_values_;
}
void set_default_parameter_values(const Array& default_parameter_values) {
- ASSERT(default_parameter_values.IsZoneHandle());
+ ASSERT(default_parameter_values.IsZoneHandle() ||
+ default_parameter_values.InVMHeap());
default_parameter_values_ = default_parameter_values.raw();
}
@@ -438,6 +439,7 @@
SequenceNode* ParseInstanceSetter(const Function& func);
SequenceNode* ParseStaticConstGetter(const Function& func);
SequenceNode* ParseMethodExtractor(const Function& func);
+ SequenceNode* ParseNoSuchMethodDispatcher(const Function& func);
void ChainNewBlock(LocalScope* outer_scope);
void OpenBlock();
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 9794c11..7fedccb 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -597,6 +597,7 @@
kImplicitSetter, // represents an implicit setter for fields.
kConstImplicitGetter, // represents an implicit const getter for fields.
kMethodExtractor, // converts method into implicit closure on the receiver.
+ kNoSuchMethodDispatcher, // invokes noSuchMethod.
};
private:
@@ -1022,16 +1023,17 @@
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->function_);
}
- RawFunction* function_; // Parent/calling function of this IC.
- RawString* target_name_; // Name of target function.
- RawArray* ic_data_; // Contains test class-ids and target functions.
+ RawFunction* function_; // Parent/calling function of this IC.
+ RawString* target_name_; // Name of target function.
+ RawArray* args_descriptor_; // Arguments descriptor.
+ RawArray* ic_data_; // Contains class-ids, target and count.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->ic_data_);
}
- intptr_t deopt_id_; // Deoptimization id corresponding to this IC.
- intptr_t num_args_tested_; // Number of arguments tested in IC.
- uint8_t deopt_reason_; // Last deoptimization reason.
- uint8_t is_closure_call_; // 0 or 1.
+ intptr_t deopt_id_; // Deoptimization id corresponding to this IC.
+ intptr_t num_args_tested_; // Number of arguments tested in IC.
+ uint8_t deopt_reason_; // Last deoptimization reason.
+ uint8_t is_closure_call_; // 0 or 1.
};
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 5a55b48..78bf848 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -138,7 +138,7 @@
// Getter invocation might actually be a method extraction.
if (is_getter && function.IsNull()) {
function ^= cls.LookupDynamicFunction(field_name);
- if (!function.IsNull()) {
+ if (!function.IsNull() && !function.IsNoSuchMethodDispatcher()) {
// We were looking for the getter but found a method with the same name.
// Create a method extractor and return it.
function ^= CreateMethodExtractor(function_name, function);
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 896142c..fff829a 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -15,7 +15,6 @@
namespace dart {
-DEFINE_FLAG(bool, disable_privacy, false, "Disable library privacy.");
DEFINE_FLAG(bool, print_tokens, false, "Print scanned tokens.");
void Scanner::InitKeywordTable() {
@@ -328,7 +327,7 @@
current_token_.kind = Token::kIDENT;
String& literal =
String::ZoneHandle(Symbols::New(source_, ident_pos, ident_length));
- if ((ident_char0 == kPrivateIdentifierStart) && !FLAG_disable_privacy) {
+ if (ident_char0 == kPrivateIdentifierStart) {
// Private identifiers are mangled on a per script basis.
literal = String::Concat(literal, private_key_);
literal = Symbols::New(literal);
@@ -392,19 +391,6 @@
}
-RawString* Scanner::ConsumeIdentChars(bool allow_dollar) {
- ASSERT(IsIdentStartChar(c0_));
- ASSERT(allow_dollar || (c0_ != '$'));
- int ident_length = 0;
- int32_t ident_pos = lookahead_pos_;
- while (IsIdentChar(c0_) && (allow_dollar || (c0_ != '$'))) {
- ReadChar();
- ident_length++;
- }
- return Symbols::New(source_, ident_pos, ident_length);
-}
-
-
void Scanner::SkipLine() {
while (c0_ != '\n' && c0_ != '\0') {
ReadChar();
diff --git a/runtime/vm/scanner.h b/runtime/vm/scanner.h
index 42dc417..316ac98 100644
--- a/runtime/vm/scanner.h
+++ b/runtime/vm/scanner.h
@@ -187,7 +187,6 @@
void ScanEscapedCodePoint(int32_t* escaped_char);
// Reads identifier.
- RawString* ConsumeIdentChars(bool allow_dollar);
void ScanIdentChars(bool allow_dollar);
void ScanIdent() {
ScanIdentChars(true);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index acfed60..cc08b23 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -2968,15 +2968,24 @@
int32_t parameter0,
int32_t parameter1,
int32_t parameter2,
- int32_t parameter3) {
+ int32_t parameter3,
+ bool fp_return,
+ bool fp_args) {
// Save the SP register before the call so we can restore it.
int32_t sp_before_call = get_register(SP);
// Setup parameters.
- set_register(R0, parameter0);
- set_register(R1, parameter1);
- set_register(R2, parameter2);
- set_register(R3, parameter3);
+ if (fp_args) {
+ set_sregister(S0, bit_cast<float, int32_t>(parameter0));
+ set_sregister(S1, bit_cast<float, int32_t>(parameter1));
+ set_sregister(S2, bit_cast<float, int32_t>(parameter2));
+ set_sregister(S3, bit_cast<float, int32_t>(parameter3));
+ } else {
+ set_register(R0, parameter0);
+ set_register(R1, parameter1);
+ set_register(R2, parameter2);
+ set_register(R3, parameter3);
+ }
// Make sure the activation frames are properly aligned.
int32_t stack_pointer = sp_before_call;
@@ -3042,7 +3051,13 @@
// Restore the SP register and return R1:R0.
set_register(SP, sp_before_call);
- return Utils::LowHighTo64Bits(get_register(R0), get_register(R1));
+ int64_t return_value;
+ if (fp_return) {
+ return_value = bit_cast<int64_t, double>(get_dregister(D0));
+ } else {
+ return_value = Utils::LowHighTo64Bits(get_register(R0), get_register(R1));
+ }
+ return return_value;
}
@@ -3073,11 +3088,10 @@
set_register(PC, static_cast<int32_t>(pc));
set_register(SP, static_cast<int32_t>(sp));
set_register(FP, static_cast<int32_t>(fp));
- ASSERT(raw_exception != NULL);
+
+ ASSERT(raw_exception != Object::null());
set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
- if (raw_stacktrace != NULL) {
- set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
- }
+ set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
buf->Longjmp();
}
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index d6e8409..5ccfc09 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -65,12 +65,17 @@
// Dart generally calls into generated code with 5 parameters. This is a
// convenience function, which sets up the simulator state and grabs the
- // result on return.
+ // result on return. When fp_return is true the return value is the D0
+ // floating point register. Otherwise, the return value is R1:R0.
+ // If fp_args is true, the parameters0-3 are placed in S0-3. Otherwise, they
+ // are placed in R0-3.
int64_t Call(int32_t entry,
int32_t parameter0,
int32_t parameter1,
int32_t parameter2,
- int32_t parameter3);
+ int32_t parameter3,
+ bool fp_return = false,
+ bool fp_args = false);
// Implementation of atomic compare and exchange in the same synchronization
// domain as other synchronization primitive instructions (e.g. ldrex, strex).
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index 0a12de3..a04d8f1 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -727,6 +727,23 @@
}
+void Simulator::set_dregister_bits(DRegister reg, int64_t value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfDRegisters);
+ FRegister lo = static_cast<FRegister>(reg * 2);
+ FRegister hi = static_cast<FRegister>((reg * 2) + 1);
+ set_fregister(lo, Utils::Low32Bits(value));
+ set_fregister(hi, Utils::High32Bits(value));
+}
+
+
+void Simulator::set_dregister(DRegister reg, double value) {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfDRegisters);
+ set_dregister_bits(reg, bit_cast<int64_t, double>(value));
+}
+
+
// Get the register from the architecture state.
int32_t Simulator::get_register(Register reg) const {
if (reg == R0) {
@@ -769,6 +786,23 @@
}
+int64_t Simulator::get_dregister_bits(DRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfDRegisters);
+ FRegister lo = static_cast<FRegister>(reg * 2);
+ FRegister hi = static_cast<FRegister>((reg * 2) + 1);
+ return Utils::LowHighTo64Bits(get_fregister(lo), get_fregister(hi));
+}
+
+
+double Simulator::get_dregister(DRegister reg) const {
+ ASSERT(reg >= 0);
+ ASSERT(reg < kNumberOfDRegisters);
+ const int64_t value = get_dregister_bits(reg);
+ return bit_cast<double, int64_t>(value);
+}
+
+
void Simulator::UnimplementedInstruction(Instr* instr) {
char buffer[64];
snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr);
@@ -1097,10 +1131,9 @@
int32_t rs_val = get_register(instr->RsField());
int32_t rt_val = get_register(instr->RtField());
if (rt_val == 0) {
- // Results are unpredictable.
- set_hi_register(0);
- set_lo_register(0);
- // TODO(zra): Drop into the debugger here.
+ // Results are unpredictable, but there is no arithmetic exception.
+ set_hi_register(icount_);
+ set_lo_register(icount_);
break;
}
@@ -1121,10 +1154,9 @@
uint32_t rs_val = get_register(instr->RsField());
uint32_t rt_val = get_register(instr->RtField());
if (rt_val == 0) {
- // Results are unpredictable.
- set_hi_register(0);
- set_lo_register(0);
- // TODO(zra): Drop into the debugger here.
+ // Results are unpredictable, but there is no arithmetic exception.
+ set_hi_register(icount_);
+ set_lo_register(icount_);
break;
}
set_lo_register(rs_val / rt_val);
@@ -1376,8 +1408,8 @@
uint32_t lo = get_lo_register();
uint32_t hi = get_hi_register();
uint64_t accum = Utils::LowHighTo64Bits(lo, hi);
- uint64_t rs = static_cast<int64_t>(get_register(instr->RsField()));
- uint64_t rt = static_cast<int64_t>(get_register(instr->RtField()));
+ uint64_t rs = static_cast<uint64_t>(get_register(instr->RsField()));
+ uint64_t rt = static_cast<uint64_t>(get_register(instr->RtField()));
uint64_t res = accum + rs * rt;
set_hi_register(Utils::High32Bits(res));
set_lo_register(Utils::Low32Bits(res));
@@ -1618,7 +1650,13 @@
switch (instr->FormatField()) {
case FMT_D: {
double fs_dbl = get_fregister_double(instr->FsField());
- int32_t fs_int = static_cast<int32_t>(fs_dbl);
+ int32_t fs_int;
+ if (isnan(fs_dbl) || isinf(fs_dbl) || (fs_dbl > INT_MAX) ||
+ (fs_dbl < INT_MIN)) {
+ fs_int = INT_MIN;
+ } else {
+ fs_int = static_cast<int32_t>(fs_dbl);
+ }
set_fregister(instr->FdField(), fs_int);
break;
}
@@ -1630,6 +1668,22 @@
}
break;
}
+ case COP1_CVT_S: {
+ switch (instr->FormatField()) {
+ case FMT_D: {
+ double fs_dbl = get_fregister_double(instr->FsField());
+ float fs_flt = static_cast<float>(fs_dbl);
+ set_fregister_float(instr->FdField(), fs_flt);
+ break;
+ }
+ default: {
+ OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
+ UnimplementedInstruction(instr);
+ break;
+ }
+ }
+ break;
+ }
default: {
OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits());
UnimplementedInstruction(instr);
@@ -2021,15 +2075,24 @@
int32_t parameter0,
int32_t parameter1,
int32_t parameter2,
- int32_t parameter3) {
+ int32_t parameter3,
+ bool fp_return,
+ bool fp_args) {
// Save the SP register before the call so we can restore it.
int32_t sp_before_call = get_register(SP);
// Setup parameters.
- set_register(A0, parameter0);
- set_register(A1, parameter1);
- set_register(A2, parameter2);
- set_register(A3, parameter3);
+ if (fp_args) {
+ set_fregister(F0, parameter0);
+ set_fregister(F1, parameter1);
+ set_fregister(F2, parameter2);
+ set_fregister(F3, parameter3);
+ } else {
+ set_register(A0, parameter0);
+ set_register(A1, parameter1);
+ set_register(A2, parameter2);
+ set_register(A3, parameter3);
+ }
// Make sure the activation frames are properly aligned.
int32_t stack_pointer = sp_before_call;
@@ -2058,6 +2121,13 @@
int32_t r22_val = get_register(R22);
int32_t r23_val = get_register(R23);
+ double d10_val = get_dregister(D10);
+ double d11_val = get_dregister(D11);
+ double d12_val = get_dregister(D12);
+ double d13_val = get_dregister(D13);
+ double d14_val = get_dregister(D14);
+ double d15_val = get_dregister(D15);
+
// Setup the callee-saved registers with a known value. To be able to check
// that they are preserved properly across dart execution.
int32_t callee_saved_value = icount_;
@@ -2070,6 +2140,13 @@
set_register(R22, callee_saved_value);
set_register(R23, callee_saved_value);
+ set_dregister_bits(D10, callee_saved_value);
+ set_dregister_bits(D11, callee_saved_value);
+ set_dregister_bits(D12, callee_saved_value);
+ set_dregister_bits(D13, callee_saved_value);
+ set_dregister_bits(D14, callee_saved_value);
+ set_dregister_bits(D15, callee_saved_value);
+
// Start the simulation
Execute();
@@ -2083,6 +2160,13 @@
ASSERT(callee_saved_value == get_register(R22));
ASSERT(callee_saved_value == get_register(R23));
+ ASSERT(callee_saved_value == get_dregister_bits(D10));
+ ASSERT(callee_saved_value == get_dregister_bits(D11));
+ ASSERT(callee_saved_value == get_dregister_bits(D12));
+ ASSERT(callee_saved_value == get_dregister_bits(D13));
+ ASSERT(callee_saved_value == get_dregister_bits(D14));
+ ASSERT(callee_saved_value == get_dregister_bits(D15));
+
// Restore callee-saved registers with the original value.
set_register(R16, r16_val);
set_register(R17, r17_val);
@@ -2093,9 +2177,22 @@
set_register(R22, r22_val);
set_register(R23, r23_val);
+ set_dregister(D10, d10_val);
+ set_dregister(D11, d11_val);
+ set_dregister(D12, d12_val);
+ set_dregister(D13, d13_val);
+ set_dregister(D14, d14_val);
+ set_dregister(D15, d15_val);
+
// Restore the SP register and return V1:V0.
set_register(SP, sp_before_call);
- return Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
+ int64_t return_value;
+ if (fp_return) {
+ return_value = Utils::LowHighTo64Bits(get_fregister(F0), get_fregister(F1));
+ } else {
+ return_value = Utils::LowHighTo64Bits(get_register(V0), get_register(V1));
+ }
+ return return_value;
}
@@ -2126,11 +2223,10 @@
set_pc(static_cast<int32_t>(pc));
set_register(SP, static_cast<int32_t>(sp));
set_register(FP, static_cast<int32_t>(fp));
- ASSERT(raw_exception != NULL);
+
+ ASSERT(raw_exception != Object::null());
set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
- if (raw_stacktrace != NULL) {
- set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
- }
+ set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
buf->Longjmp();
}
diff --git a/runtime/vm/simulator_mips.h b/runtime/vm/simulator_mips.h
index 9b685b2..db95370 100644
--- a/runtime/vm/simulator_mips.h
+++ b/runtime/vm/simulator_mips.h
@@ -50,6 +50,11 @@
double get_fregister_double(FRegister freg) const;
int64_t get_fregister_long(FRegister freg) const;
+ void set_dregister_bits(DRegister freg, int64_t value);
+ void set_dregister(DRegister freg, double value);
+
+ int64_t get_dregister_bits(DRegister freg) const;
+ double get_dregister(DRegister freg) const;
// Accessor for the pc.
void set_pc(int32_t value) { pc_ = value; }
@@ -95,12 +100,15 @@
// Dart generally calls into generated code with 5 parameters. This is a
// convenience function, which sets up the simulator state and grabs the
- // result on return.
+ // result on return. When fp_return is true the return value is the D0
+ // floating point register. Otherwise, the return value is V1:V0.
int64_t Call(int32_t entry,
int32_t parameter0,
int32_t parameter1,
int32_t parameter2,
- int32_t parameter3);
+ int32_t parameter3,
+ bool fp_return = false,
+ bool fp_args = false);
// Runtime and native call support.
enum CallKind {
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 1a3b791..d634fe1 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -61,6 +61,7 @@
V(ThreeArgsOptimizedCheckInlineCache) \
V(ClosureCallInlineCache) \
V(MegamorphicCall) \
+ V(UnoptimizedStaticCall) \
V(OptimizeFunction) \
V(BreakpointDynamic) \
V(EqualityWithNullArg) \
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 62314eb..6e26bd9 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1314,18 +1314,19 @@
// R6: function object.
// R5: inline cache data object.
-// R4: arguments descriptor array.
+// Cannot use function object from ICData as it may be the inlined
+// function and not the top-scope function.
void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
Register ic_reg = R5;
Register func_reg = R6;
if (FLAG_trace_optimized_ic_calls) {
__ EnterStubFrame();
- __ PushList((1 << R4) | (1 << R5) | (1 << R6)); // Preserve.
+ __ PushList((1 << R5) | (1 << R6)); // Preserve.
__ Push(ic_reg); // Argument.
__ Push(func_reg); // Argument.
__ CallRuntime(kTraceICCallRuntimeEntry);
__ Drop(2); // Discard argument;
- __ PushList((1 << R4) | (1 << R5) | (1 << R6)); // Restore.
+ __ PopList((1 << R5) | (1 << R6)); // Restore.
__ LeaveStubFrame();
}
__ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset()));
@@ -1372,7 +1373,6 @@
// Generate inline cache check for 'num_args'.
// LR: return address.
// R5: inline cache data object.
-// R4: arguments descriptor array.
// Control flow:
// - If receiver is null -> jump to IC miss.
// - If receiver is Smi -> load Smi class.
@@ -1395,6 +1395,8 @@
}
#endif // DEBUG
+ // Load arguments descriptor into R4.
+ __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
// Preserve return address, since LR is needed for subroutine call.
__ mov(R8, ShifterOperand(LR));
// Loop that checks if there is an IC data match.
@@ -1536,7 +1538,6 @@
// cache miss handler. Stub for 1-argument check (receiver class).
// LR: return address.
// R5: inline cache data object.
-// R4: arguments descriptor array.
// Inline cache data object structure:
// 0: function-name
// 1: N, number of arguments checked.
@@ -1592,29 +1593,95 @@
}
+// Intermediary stub between a static call and its target. ICData contains
+// the target function and the call count.
+// R5: ICData
+void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, R6);
+#if defined(DEBUG)
+ { Label ok;
+ // Check that the IC data array has NumberOfArgumentsChecked() == 0.
+ // 'num_args_tested' is stored as an untagged int.
+ __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset()));
+ __ CompareImmediate(R6, 0);
+ __ b(&ok, EQ);
+ __ Stop("Incorrect IC data for unoptimized static call");
+ __ Bind(&ok);
+ }
+#endif // DEBUG
+
+ // R5: IC data object (preserved).
+ __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset()));
+ // R6: ic_data_array with entries: target functions and count.
+ __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag);
+ // R6: points directly to the first ic data array element.
+ const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
+ const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+
+ // Increment count for this call.
+ Label increment_done;
+ __ LoadFromOffset(kLoadWord, R1, R6, count_offset);
+ __ adds(R1, R1, ShifterOperand(Smi::RawValue(1)));
+ __ StoreToOffset(kStoreWord, R1, R6, count_offset);
+ __ b(&increment_done, VC); // No overflow.
+ __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue));
+ __ StoreToOffset(kStoreWord, R1, R6, count_offset);
+ __ Bind(&increment_done);
+
+ Label target_is_compiled;
+ // Get function and call it, if possible.
+ __ LoadFromOffset(kLoadWord, R1, R6, target_offset);
+ __ ldr(R0, FieldAddress(R1, Function::code_offset()));
+ __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
+ __ b(&target_is_compiled, NE);
+ // R1: function.
+
+ __ EnterStubFrame();
+ // Preserve target function and IC data object.
+ __ PushList((1 << R1) | (1 << R5));
+ __ Push(R1); // Pass function.
+ __ CallRuntime(kCompileFunctionRuntimeEntry);
+ __ Drop(1); // Discard argument.
+ __ PopList((1 << R1) | (1 << R5)); // Restore function and IC data.
+ __ LeaveStubFrame();
+ // R0: target function.
+ __ ldr(R0, FieldAddress(R1, Function::code_offset()));
+
+ __ Bind(&target_is_compiled);
+ // R0: target code.
+ __ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
+ __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
+ // Load arguments descriptor into R4.
+ __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
+ __ bx(R0);
+}
+
+
void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
__ Unimplemented("BreakpointRuntime stub");
}
// LR: return address (Dart code).
-// R4: arguments descriptor array.
+// R5: IC data (unoptimized static call).
void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
__ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null()));
// Preserve arguments descriptor and make room for result.
- __ PushList((1 << R0) | (1 << R4));
+ __ PushList((1 << R0) | (1 << R5));
__ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
// Pop code object result and restore arguments descriptor.
- __ PopList((1 << R0) | (1 << R4));
+ __ PopList((1 << R0) | (1 << R5));
__ LeaveStubFrame();
// Now call the static function. The breakpoint handler function
// ensures that the call target is compiled.
__ ldr(R0, FieldAddress(R0, Code::instructions_offset()));
__ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag);
+ // Load arguments descriptor into R4.
+ __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
__ bx(R0);
}
@@ -1638,14 +1705,13 @@
// LR: return address (Dart code).
// R5: inline cache data array.
-// R4: arguments descriptor array.
void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
- __ PushList((1 << R4) | (1 << R5));
+ __ Push(R5);
__ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry);
- __ PopList((1 << R4) | (1 << R5));
+ __ Pop(R5);
__ LeaveStubFrame();
// Find out which dispatch stub to call.
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 7f884622f..3797ffd 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1416,14 +1416,14 @@
}
+// Cannot use function object from ICData as it may be the inlined
+// function and not the top-scope function.
void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
- Register argdesc_reg = EDX;
Register ic_reg = ECX;
Register func_reg = EDI;
if (FLAG_trace_optimized_ic_calls) {
__ EnterStubFrame();
__ pushl(func_reg); // Preserve
- __ pushl(argdesc_reg); // Preserve.
__ pushl(ic_reg); // Preserve.
__ pushl(ic_reg); // Argument.
__ pushl(func_reg); // Argument.
@@ -1431,7 +1431,6 @@
__ popl(EAX); // Discard argument;
__ popl(EAX); // Discard argument;
__ popl(ic_reg); // Restore.
- __ popl(argdesc_reg); // Restore.
__ popl(func_reg); // Restore.
__ LeaveFrame();
}
@@ -1452,7 +1451,6 @@
// Generate inline cache check for 'num_args'.
// ECX: Inline cache data object.
-// EDX: Arguments descriptor array.
// TOS(0): return address
// Control flow:
// - If receiver is null -> jump to IC miss.
@@ -1476,6 +1474,8 @@
}
#endif // DEBUG
+ // Load arguments descriptor into EDX.
+ __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset()));
// Loop that checks if there is an IC data match.
Label loop, update, test, found, get_class_id_as_smi;
// ECX: IC data object (preserved).
@@ -1581,7 +1581,7 @@
const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
__ movl(EAX, Address(EBX, target_offset));
__ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1)));
- __ j(NO_OVERFLOW, &call_target_function);
+ __ j(NO_OVERFLOW, &call_target_function, Assembler::kNearJump);
__ movl(Address(EBX, count_offset),
Immediate(Smi::RawValue(Smi::kMaxValue)));
@@ -1611,7 +1611,6 @@
// Use inline cache data array to invoke the target or continue in inline
// cache miss handler. Stub for 1-argument check (receiver class).
// ECX: Inline cache data object.
-// EDX: Arguments descriptor array.
// TOS(0): Return address.
// Inline cache data object structure:
// 0: function-name
@@ -1641,7 +1640,6 @@
// cache miss handler. Stub for 1-argument check (receiver class).
// EDI: function which counter needs to be incremented.
// ECX: Inline cache data object.
-// EDX: Arguments descriptor array.
// TOS(0): Return address.
// Inline cache data object structure:
// 0: function-name
@@ -1682,6 +1680,66 @@
GenerateNArgsCheckInlineCacheStub(assembler, 1);
}
+// Intermediary stub between a static call and its target. ICData contains
+// the target function and the call count.
+// ECX: ICData
+void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, EBX);
+#if defined(DEBUG)
+ { Label ok;
+ // Check that the IC data array has NumberOfArgumentsChecked() == 0.
+ // 'num_args_tested' is stored as an untagged int.
+ __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
+ __ cmpl(EBX, Immediate(0));
+ __ j(EQUAL, &ok, Assembler::kNearJump);
+ __ Stop("Incorrect IC data for unoptimized static call");
+ __ Bind(&ok);
+ }
+#endif // DEBUG
+
+ // ECX: IC data object (preserved).
+ __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
+ // EBX: ic_data_array with entries: target functions and count.
+ __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
+ // EBX: points directly to the first ic data array element.
+ const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
+ const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+
+ // Increment count for this call.
+ Label increment_done;
+ __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1)));
+ __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump);
+ __ movl(Address(EBX, count_offset), Immediate(Smi::RawValue(Smi::kMaxValue)));
+ __ Bind(&increment_done);
+
+ const Immediate& raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ Label target_is_compiled;
+ // Get function and call it, if possible.
+ __ movl(EDI, Address(EBX, target_offset));
+ __ movl(EAX, FieldAddress(EDI, Function::code_offset()));
+ __ cmpl(EAX, raw_null);
+ __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump);
+ __ EnterStubFrame();
+ __ pushl(EDI); // Preserve target function.
+ __ pushl(ECX); // Preserve IC data object.
+ __ pushl(EDI); // Pass function.
+ __ CallRuntime(kCompileFunctionRuntimeEntry);
+ __ popl(EAX); // Discard argument.
+ __ popl(ECX); // Restore IC data object.
+ __ popl(EDI); // Restore target function.
+ __ LeaveFrame();
+ __ movl(EAX, FieldAddress(EDI, Function::code_offset()));
+
+ __ Bind(&target_is_compiled);
+ // EAX: Target code.
+ __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
+ __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
+ // Load arguments descriptor into EDX.
+ __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset()));
+ __ jmp(EAX);
+}
+
// EDX, EXC: May contain arguments to runtime stub.
void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
@@ -1703,21 +1761,23 @@
}
-// EDX: Arguments descriptor array.
+// ECX: ICData (unoptimized static call).
// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
- __ pushl(EDX); // Preserve arguments descriptor.
+ __ pushl(ECX); // Preserve ICData for unoptimized call.
const Immediate& raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
__ pushl(raw_null); // Room for result.
__ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
__ popl(EAX); // Code object.
- __ popl(EDX); // Restore arguments descriptor.
+ __ popl(ECX); // Restore ICData.
__ LeaveFrame();
+ // Load arguments descriptor into EDX.
+ __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset()));
// Now call the static function. The breakpoint handler function
// ensures that the call target is compiled.
// Note that we can't just jump to the CallStatic function stub
@@ -1749,16 +1809,13 @@
// ECX: Inline cache data array.
-// EDX: Arguments descriptor array.
// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
__ pushl(ECX);
- __ pushl(EDX);
__ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry);
- __ popl(EDX);
__ popl(ECX);
__ LeaveFrame();
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 4bfd8a1..659a20b 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1062,8 +1062,8 @@
// Spilled: T1, T2, T3.
// T0: Address being stored.
__ lw(T2, FieldAddress(T0, Object::tags_offset()));
- __ andi(T1, T2, Immediate(1 << RawObject::kRememberedBit));
- __ beq(T1, ZR, &add_to_buffer);
+ __ andi(CMPRES, T2, Immediate(1 << RawObject::kRememberedBit));
+ __ beq(CMPRES, ZR, &add_to_buffer);
__ lw(T1, Address(SP, 0 * kWordSize));
__ lw(T2, Address(SP, 1 * kWordSize));
__ lw(T3, Address(SP, 2 * kWordSize));
@@ -1092,7 +1092,7 @@
// T2: top_
// T1: StoreBufferBlock
Label L;
- __ AddImmediate(T2, 1);
+ __ addiu(T2, T2, Immediate(1));
__ sw(T2, Address(T1, StoreBufferBlock::top_offset()));
__ addiu(CMPRES, T2, Immediate(-StoreBufferBlock::kSize));
// Restore values.
@@ -1107,7 +1107,7 @@
__ Bind(&L);
// Setup frame, push callee-saved registers.
- __ EnterCallRuntimeFrame(0 * kWordSize);
+ __ EnterCallRuntimeFrame(1 * kWordSize);
__ lw(A0, FieldAddress(CTX, Context::isolate_offset()));
__ CallRuntime(kStoreBufferBlockProcessRuntimeEntry);
__ TraceSimMsg("UpdateStoreBufferStub return");
@@ -1489,24 +1489,23 @@
// T0: function object.
// S5: inline cache data object.
-// S4: arguments descriptor array.
+// Cannot use function object from ICData as it may be the inlined
+// function and not the top-scope function.
void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
__ TraceSimMsg("OptimizedUsageCounterIncrement");
Register ic_reg = S5;
Register func_reg = T0;
if (FLAG_trace_optimized_ic_calls) {
__ EnterStubFrame();
- __ addiu(SP, SP, Immediate(-5 * kWordSize));
- __ sw(T0, Address(SP, 4 * kWordSize));
- __ sw(S5, Address(SP, 3 * kWordSize));
- __ sw(S4, Address(SP, 2 * kWordSize)); // Preserve.
+ __ addiu(SP, SP, Immediate(-4 * kWordSize));
+ __ sw(T0, Address(SP, 3 * kWordSize));
+ __ sw(S5, Address(SP, 2 * kWordSize));
__ sw(ic_reg, Address(SP, 1 * kWordSize)); // Argument.
__ sw(func_reg, Address(SP, 0 * kWordSize)); // Argument.
__ CallRuntime(kTraceICCallRuntimeEntry);
- __ lw(S4, Address(SP, 2 * kWordSize)); // Restore.
- __ lw(S5, Address(SP, 3 * kWordSize));
- __ lw(T0, Address(SP, 4 * kWordSize));
- __ addiu(SP, SP, Immediate(5 * kWordSize)); // Discard argument;
+ __ lw(S5, Address(SP, 2 * kWordSize));
+ __ lw(T0, Address(SP, 3 * kWordSize));
+ __ addiu(SP, SP, Immediate(4 * kWordSize)); // Discard argument;
__ LeaveStubFrame();
}
__ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset()));
@@ -1553,7 +1552,6 @@
// Generate inline cache check for 'num_args'.
// RA: return address
// S5: Inline cache data object.
-// S4: Arguments descriptor array.
// Control flow:
// - If receiver is null -> jump to IC miss.
// - If receiver is Smi -> load Smi class.
@@ -1576,6 +1574,8 @@
}
#endif // DEBUG
+ // Load argument descriptor into S4.
+ __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
// Preserve return address, since RA is needed for subroutine call.
__ mov(T2, RA);
// Loop that checks if there is an IC data match.
@@ -1743,7 +1743,6 @@
// cache miss handler. Stub for 1-argument check (receiver class).
// RA: Return address.
// S5: Inline cache data object.
-// S4: Arguments descriptor array.
// Inline cache data object structure:
// 0: function-name
// 1: N, number of arguments checked.
@@ -1799,13 +1798,83 @@
}
+// Intermediary stub between a static call and its target. ICData contains
+// the target function and the call count.
+// S5: ICData
+void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, T0);
+ __ TraceSimMsg("UnoptimizedStaticCallStub");
+#if defined(DEBUG)
+ { Label ok;
+ // Check that the IC data array has NumberOfArgumentsChecked() == 0.
+ // 'num_args_tested' is stored as an untagged int.
+ __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset()));
+ __ beq(T0, ZR, &ok);
+ __ Stop("Incorrect IC data for unoptimized static call");
+ __ Bind(&ok);
+ }
+#endif // DEBUG
+
+ // S5: IC data object (preserved).
+ __ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
+ // T0: ic_data_array with entries: target functions and count.
+ __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag);
+ // T0: points directly to the first ic data array element.
+ const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
+ const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+
+ // Increment count for this call.
+ Label increment_done;
+ __ lw(T4, Address(T0, count_offset));
+ __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6);
+ __ bgez(T5, &increment_done); // No overflow.
+ __ delay_slot()->sw(T4, Address(T0, count_offset));
+
+ __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue));
+ __ sw(T1, Address(T0, count_offset));
+
+ __ Bind(&increment_done);
+
+ Label target_is_compiled;
+ // Get function and call it, if possible.
+ __ lw(T3, Address(T0, target_offset));
+ __ lw(T4, FieldAddress(T3, Function::code_offset()));
+ __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
+ __ bne(T4, TMP, &target_is_compiled);
+
+ __ EnterStubFrame();
+ // Preserve target function and IC data object.
+ // Two preserved registers, one argument (function) => 3 slots.
+ __ addiu(SP, SP, Immediate(-3 * kWordSize));
+ __ sw(S5, Address(SP, 2 * kWordSize)); // Preserve IC data.
+ __ sw(T3, Address(SP, 1 * kWordSize)); // Preserve function.
+ __ sw(T3, Address(SP, 0 * kWordSize)); // Function argument.
+ __ CallRuntime(kCompileFunctionRuntimeEntry);
+ __ lw(T3, Address(SP, 1 * kWordSize)); // Restore function.
+ __ lw(S5, Address(SP, 2 * kWordSize)); // Restore IC data.
+ __ addiu(SP, SP, Immediate(3 * kWordSize));
+ // T3: target function.
+ __ lw(T4, FieldAddress(T3, Function::code_offset()));
+ __ LeaveStubFrame();
+
+ __ Bind(&target_is_compiled);
+ // T4: target code.
+ __ lw(T3, FieldAddress(T4, Code::instructions_offset()));
+ __ AddImmediate(T3, Instructions::HeaderSize() - kHeapObjectTag);
+ __ jr(T3);
+ // Load arguments descriptor into S4.
+ __ delay_slot()->
+ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
+}
+
+
void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
__ Unimplemented("BreakpointRuntime stub");
}
// RA: return address (Dart code).
-// S4: Arguments descriptor array.
+// S5: IC data (unoptimized static call).
void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
__ TraceSimMsg("BreakpointStaticStub");
// Create a stub frame as we are pushing some objects on the stack before
@@ -1813,13 +1882,13 @@
__ EnterStubFrame();
// Preserve arguments descriptor and make room for result.
__ addiu(SP, SP, Immediate(-2 * kWordSize));
- __ sw(S4, Address(SP, 1 * kWordSize));
+ __ sw(S5, Address(SP, 1 * kWordSize));
__ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
__ sw(TMP, Address(SP, 0 * kWordSize));
__ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
// Pop code object result and restore arguments descriptor.
__ lw(T0, Address(SP, 0 * kWordSize));
- __ lw(S4, Address(SP, 1 * kWordSize));
+ __ lw(S5, Address(SP, 1 * kWordSize));
__ addiu(SP, SP, Immediate(2 * kWordSize));
__ LeaveStubFrame();
@@ -1827,6 +1896,8 @@
// ensures that the call target is compiled.
__ lw(T0, FieldAddress(T0, Code::instructions_offset()));
__ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
+ // Load arguments descriptor into S4.
+ __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
__ jr(T0);
}
@@ -1850,19 +1921,14 @@
// RA: return address (Dart code).
// S5: Inline cache data array.
-// S4: Arguments descriptor array.
void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ TraceSimMsg("BreakpointDynamicStub");
__ EnterStubFrame();
- __ addiu(SP, SP, Immediate(-2 * kWordSize));
- __ sw(S5, Address(SP, 1 * kWordSize));
- __ sw(S4, Address(SP, 0 * kWordSize));
+ __ Push(S5);
__ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry);
- __ lw(S4, Address(SP, 0 * kWordSize));
- __ lw(S5, Address(SP, 1 * kWordSize));
- __ addiu(SP, SP, Immediate(2 * kWordSize));
+ __ Pop(S5);
__ LeaveStubFrame();
// Find out which dispatch stub to call.
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 8d78a52..97e2bbc 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1399,14 +1399,14 @@
}
+// Cannot use function object from ICData as it may be the inlined
+// function and not the top-scope function.
void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
- Register argdesc_reg = R10;
Register ic_reg = RBX;
Register func_reg = RDI;
if (FLAG_trace_optimized_ic_calls) {
__ EnterStubFrame();
__ pushq(func_reg); // Preserve
- __ pushq(argdesc_reg); // Preserve.
__ pushq(ic_reg); // Preserve.
__ pushq(ic_reg); // Argument.
__ pushq(func_reg); // Argument.
@@ -1414,7 +1414,6 @@
__ popq(RAX); // Discard argument;
__ popq(RAX); // Discard argument;
__ popq(ic_reg); // Restore.
- __ popq(argdesc_reg); // Restore.
__ popq(func_reg); // Restore.
__ LeaveFrame();
}
@@ -1435,7 +1434,6 @@
// Generate inline cache check for 'num_args'.
// RBX: Inline cache data object.
-// R10: Arguments descriptor array.
// TOS(0): return address
// Control flow:
// - If receiver is null -> jump to IC miss.
@@ -1459,6 +1457,8 @@
}
#endif // DEBUG
+ // Load arguments descriptor into R10.
+ __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
// Loop that checks if there is an IC data match.
Label loop, update, test, found, get_class_id_as_smi;
// RBX: IC data object (preserved).
@@ -1562,7 +1562,7 @@
const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
__ movq(RAX, Address(R12, target_offset));
__ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1)));
- __ j(NO_OVERFLOW, &call_target_function);
+ __ j(NO_OVERFLOW, &call_target_function, Assembler::kNearJump);
__ movq(Address(R12, count_offset),
Immediate(Smi::RawValue(Smi::kMaxValue)));
@@ -1591,7 +1591,6 @@
// Use inline cache data array to invoke the target or continue in inline
// cache miss handler. Stub for 1-argument check (receiver class).
// RBX: Inline cache data object.
-// R10: Arguments descriptor array.
// TOS(0): Return address.
// Inline cache data object structure:
// 0: function-name
@@ -1620,7 +1619,6 @@
// cache miss handler. Stub for 1-argument check (receiver class).
// RDI: function which counter needs to be incremented.
// RBX: Inline cache data object.
-// R10: Arguments descriptor array.
// TOS(0): Return address.
// Inline cache data object structure:
// 0: function-name
@@ -1662,6 +1660,69 @@
}
+// Intermediary stub between a static call and its target. ICData contains
+// the target function and the call count.
+// RBX: ICData
+void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) {
+ GenerateUsageCounterIncrement(assembler, RCX);
+#if defined(DEBUG)
+ { Label ok;
+ // Check that the IC data array has NumberOfArgumentsChecked() == 0.
+ // 'num_args_tested' is stored as an untagged int.
+ __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset()));
+ __ cmpq(RCX, Immediate(0));
+ __ j(EQUAL, &ok, Assembler::kNearJump);
+ __ Stop("Incorrect IC data for unoptimized static call");
+ __ Bind(&ok);
+ }
+#endif // DEBUG
+
+ // RBX: IC data object (preserved).
+ __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
+ // R12: ic_data_array with entries: target functions and count.
+ __ leaq(R12, FieldAddress(R12, Array::data_offset()));
+ // R12: points directly to the first ic data array element.
+ const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
+ const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+
+ // Increment count for this call.
+ Label increment_done;
+ __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1)));
+ __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump);
+ __ movq(Address(R12, count_offset),
+ Immediate(Smi::RawValue(Smi::kMaxValue)));
+ __ Bind(&increment_done);
+
+ const Immediate& raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ Label target_is_compiled;
+ // Get function and call it, if possible.
+ __ movq(R13, Address(R12, target_offset));
+ __ movq(RAX, FieldAddress(R13, Function::code_offset()));
+ __ cmpq(RAX, raw_null);
+ __ j(NOT_EQUAL, &target_is_compiled, Assembler::kNearJump);
+
+ __ EnterStubFrame();
+ __ pushq(R13); // Preserve target function.
+ __ pushq(RBX); // Preserve IC data object.
+ __ pushq(R13); // Pass function.
+ __ CallRuntime(kCompileFunctionRuntimeEntry);
+ __ popq(RAX); // Discard argument.
+ __ popq(RBX); // Restore IC data object.
+ __ popq(R13); // Restore target function.
+ __ LeaveFrame();
+ __ movq(RAX, FieldAddress(R13, Function::code_offset()));
+
+ __ Bind(&target_is_compiled);
+ // RAX: Target code.
+ __ movq(RAX, FieldAddress(RAX, Code::instructions_offset()));
+ __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
+ // Load arguments descriptor into R10.
+ __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
+ __ jmp(RAX);
+}
+
+
// RBX, R10: May contain arguments to runtime stub.
// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
@@ -1683,19 +1744,21 @@
}
-// R10: Arguments descriptor array.
+// RBX: ICData (unoptimized static call)
// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
const Immediate& raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
__ EnterStubFrame();
- __ pushq(R10); // Preserve arguments descriptor.
+ __ pushq(RBX); // Preserve IC data for unoptimized call.
__ pushq(raw_null); // Room for result.
__ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
__ popq(RAX); // Code object.
- __ popq(R10); // Restore arguments descriptor.
+ __ popq(RBX); // Restore IC data.
__ LeaveFrame();
+ // Load arguments descriptor into R10.
+ __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
// Now call the static function. The breakpoint handler function
// ensures that the call target is compiled.
__ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
@@ -1719,14 +1782,11 @@
// RBX: Inline cache data array.
-// R10: Arguments descriptor array.
// TOS(0): return address (Dart code).
void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
__ EnterStubFrame();
__ pushq(RBX);
- __ pushq(R10);
__ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry);
- __ popq(R10);
__ popq(RBX);
__ LeaveFrame();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 2688745..0fb42e2 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -226,7 +226,7 @@
V(NullThrownError, "NullThrownError") \
V(IsolateSpawnException, "IsolateSpawnException") \
V(IsolateUnhandledException, "IsolateUnhandledException") \
- V(FiftyThreeBitOverflowError, "FiftyThreeBitOverflowError") \
+ V(FiftyThreeBitOverflowError, "_FiftyThreeBitOverflowError") \
V(_setupFullStackTrace, "_setupFullStackTrace") \
V(BooleanExpression, "boolean expression") \
V(Malformed, "malformed") \
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 8f674c7..2ca6293 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -156,21 +156,21 @@
Utils::High32Bits(long_arg1)))
#define EXECUTE_TEST_CODE_FLOAT(name, entry) \
bit_cast<float, int32_t>(Simulator::Current()->Call( \
- bit_cast<int32_t, uword>(entry), 0, 0, 0, 0))
+ bit_cast<int32_t, uword>(entry), 0, 0, 0, 0, true))
#define EXECUTE_TEST_CODE_DOUBLE(name, entry) \
bit_cast<double, int64_t>(Simulator::Current()->Call( \
- bit_cast<int32_t, uword>(entry), 0, 0, 0, 0))
+ bit_cast<int32_t, uword>(entry), 0, 0, 0, 0, true))
#define EXECUTE_TEST_CODE_INT32_F(name, entry, float_arg) \
static_cast<int32_t>(Simulator::Current()->Call( \
bit_cast<int32_t, uword>(entry), \
bit_cast<int32_t, float>(float_arg), \
- 0, 0, 0))
+ 0, 0, 0, false, true))
#define EXECUTE_TEST_CODE_INT32_D(name, entry, double_arg) \
static_cast<int32_t>(Simulator::Current()->Call( \
bit_cast<int32_t, uword>(entry), \
Utils::Low32Bits(bit_cast<int64_t, double>(double_arg)), \
Utils::High32Bits(bit_cast<int64_t, double>(double_arg)), \
- 0, 0))
+ 0, 0, false, true))
#endif // defined(HOST_ARCH_ARM) || defined(HOST_ARCH_MIPS)
#endif // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index 1e1da59..3e0311a 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -4,7 +4,7 @@
{
'variables': {
- 'gen_source_dir': '<(LIB_DIR)',
+ 'gen_source_dir': '<(SHARED_INTERMEDIATE_DIR)',
'libgen_in_cc_file': '../lib/libgen_in.cc',
'builtin_in_cc_file': '../bin/builtin_in.cc',
'async_cc_file': '<(gen_source_dir)/async_gen.cc',
@@ -93,25 +93,25 @@
'type': 'static_library',
'toolsets':['host', 'target'],
'dependencies': [
- 'generate_async_cc_file',
- 'generate_async_patch_cc_file',
- 'generate_corelib_cc_file',
- 'generate_corelib_patch_cc_file',
- 'generate_collection_cc_file',
- 'generate_collection_patch_cc_file',
- 'generate_collection_dev_cc_file',
- 'generate_collection_dev_patch_cc_file',
- 'generate_math_cc_file',
- 'generate_math_patch_cc_file',
- 'generate_isolate_cc_file',
- 'generate_isolate_patch_cc_file',
- 'generate_json_cc_file',
- 'generate_json_patch_cc_file',
- 'generate_mirrors_cc_file',
- 'generate_mirrors_patch_cc_file',
- 'generate_typed_data_cc_file',
- 'generate_typed_data_patch_cc_file',
- 'generate_utf_cc_file',
+ 'generate_async_cc_file#host',
+ 'generate_async_patch_cc_file#host',
+ 'generate_corelib_cc_file#host',
+ 'generate_corelib_patch_cc_file#host',
+ 'generate_collection_cc_file#host',
+ 'generate_collection_patch_cc_file#host',
+ 'generate_collection_dev_cc_file#host',
+ 'generate_collection_dev_patch_cc_file#host',
+ 'generate_math_cc_file#host',
+ 'generate_math_patch_cc_file#host',
+ 'generate_isolate_cc_file#host',
+ 'generate_isolate_patch_cc_file#host',
+ 'generate_json_cc_file#host',
+ 'generate_json_patch_cc_file#host',
+ 'generate_mirrors_cc_file#host',
+ 'generate_mirrors_patch_cc_file#host',
+ 'generate_typed_data_cc_file#host',
+ 'generate_typed_data_patch_cc_file#host',
+ 'generate_utf_cc_file#host',
],
'includes': [
'../lib/async_sources.gypi',
@@ -172,7 +172,7 @@
{
'target_name': 'generate_async_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
'../../sdk/lib/async/async_sources.gypi',
],
@@ -211,7 +211,7 @@
{
'target_name': 'generate_corelib_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared core library sources.
'../../sdk/lib/core/corelib_sources.gypi',
@@ -251,7 +251,7 @@
{
'target_name': 'generate_corelib_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../lib/corelib_sources.gypi',
@@ -291,7 +291,7 @@
{
'target_name': 'generate_collection_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared collection library sources.
'../../sdk/lib/collection/collection_sources.gypi',
@@ -331,7 +331,7 @@
{
'target_name': 'generate_collection_dev_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../lib/collection_dev_sources.gypi',
@@ -371,7 +371,7 @@
{
'target_name': 'generate_collection_dev_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared collection_dev library sources.
'../../sdk/lib/_collection_dev/collection_dev_sources.gypi',
@@ -411,7 +411,7 @@
{
'target_name': 'generate_math_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared math library sources.
'../../sdk/lib/math/math_sources.gypi',
@@ -451,7 +451,7 @@
{
'target_name': 'generate_math_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared math library sources.
'../lib/math_sources.gypi',
@@ -491,7 +491,7 @@
{
'target_name': 'generate_mirrors_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared core library sources.
'../../sdk/lib/mirrors/mirrors_sources.gypi',
@@ -531,7 +531,7 @@
{
'target_name': 'generate_mirrors_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the patch sources.
'../lib/mirrors_sources.gypi',
@@ -571,7 +571,7 @@
{
'target_name': 'generate_isolate_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../../sdk/lib/isolate/isolate_sources.gypi',
@@ -611,7 +611,7 @@
{
'target_name': 'generate_async_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../lib/async_sources.gypi',
@@ -651,7 +651,7 @@
{
'target_name': 'generate_collection_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../lib/collection_sources.gypi',
@@ -691,7 +691,7 @@
{
'target_name': 'generate_isolate_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../lib/isolate_sources.gypi',
@@ -731,7 +731,7 @@
{
'target_name': 'generate_json_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared json sources.
'../../sdk/lib/json/json_sources.gypi',
@@ -764,7 +764,7 @@
{
'target_name': 'generate_json_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared json library sources.
'../lib/json_sources.gypi',
@@ -804,7 +804,7 @@
{
'target_name': 'generate_typed_data_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared library sources.
'../../sdk/lib/typed_data/typed_data_sources.gypi',
@@ -844,7 +844,7 @@
{
'target_name': 'generate_typed_data_patch_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the runtime implementation sources.
'../lib/typed_data_sources.gypi',
@@ -884,7 +884,7 @@
{
'target_name': 'generate_utf_cc_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'includes': [
# Load the shared utf sources.
'../../sdk/lib/utf/utf_sources.gypi',
@@ -917,7 +917,7 @@
{
'target_name': 'generate_snapshot_test_dat_file',
'type': 'none',
- 'toolsets':['host', 'target'],
+ 'toolsets':['host'],
'actions': [
{
'action_name': 'generate_snapshot_test_dat',
diff --git a/sdk/bin/pub b/sdk/bin/pub
index 3643085..231da3e 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -17,7 +17,7 @@
if test -f "$SNAPSHOT"; then
# We are running the snapshot in the built SDK.
DART="$BIN_DIR/dart"
- exec "$DART" "--checked" "$SNAPSHOT" "$@"
+ exec "$DART" "$SNAPSHOT" "$@"
else
# We are running pub from source in the development repo.
if [ -z "$DART_CONFIGURATION" ];
@@ -39,5 +39,5 @@
PUB="$SDK_DIR/lib/_internal/pub/bin/pub.dart"
- exec "$DART" "--checked" "--package-root=$PACKAGES_DIR" "$PUB" "$@"
+ exec "$DART" "--package-root=$PACKAGES_DIR" "$PUB" "$@"
fi
\ No newline at end of file
diff --git a/sdk/bin/pub.bat b/sdk/bin/pub.bat
index 6f0d4e0..03213fd 100644
--- a/sdk/bin/pub.bat
+++ b/sdk/bin/pub.bat
@@ -25,9 +25,9 @@
set SNAPSHOT=%BIN_DIR%\snapshots\pub.dart.snapshot
if exist "%SNAPSHOT%" (
- "%DART%" --checked "%SNAPSHOT%" %*
+ "%DART%" "%SNAPSHOT%" %*
) else (
- "%DART_IN_BUILT_SDK%" --checked --package-root=%PACKAGES_DIR% "%PUB%" %*
+ "%DART_IN_BUILT_SDK%" --package-root=%PACKAGES_DIR% "%PUB%" %*
)
endlocal
diff --git a/sdk/bin/pub_developer b/sdk/bin/pub_developer
new file mode 100755
index 0000000..be0510d9
--- /dev/null
+++ b/sdk/bin/pub_developer
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Run pub.dart on the Dart VM. This script assumes the Dart SDK's directory
+# structure.
+
+# Setting BIN_DIR this way is ugly, but is needed to handle the case where
+# dart-sdk/bin has been symlinked to. On MacOS, readlink doesn't work
+# with this case.
+BIN_DIR="$(cd "${0%/*}" ; pwd -P)"
+SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
+
+SNAPSHOT="$BIN_DIR/snapshots/pub.dart.snapshot"
+
+if test -f "$SNAPSHOT"; then
+ # We are running the snapshot in the built SDK.
+ DART="$BIN_DIR/dart"
+ exec "$DART" --checked "$SNAPSHOT" "$@"
+else
+ # We are running pub from source in the development repo.
+ if [ -z "$DART_CONFIGURATION" ];
+ then
+ DART_CONFIGURATION="ReleaseIA32"
+ fi
+
+ if [[ `uname` == 'Darwin' ]];
+ then
+ BUILD_DIR="$SDK_DIR/../xcodebuild/$DART_CONFIGURATION"
+ else
+ BUILD_DIR="$SDK_DIR/../out/$DART_CONFIGURATION"
+ fi
+
+ # Use the Dart binary in the built SDK so pub can find the version file next
+ # to it.
+ DART="$BUILD_DIR/dart-sdk/bin/dart"
+ PACKAGES_DIR="$BUILD_DIR/packages/"
+
+ PUB="$SDK_DIR/lib/_internal/pub/bin/pub.dart"
+
+ exec "$DART" "--checked" "--package-root=$PACKAGES_DIR" "$PUB" "$@"
+fi
\ No newline at end of file
diff --git a/sdk/bin/pub_developer.bat b/sdk/bin/pub_developer.bat
new file mode 100644
index 0000000..6f0d4e0
--- /dev/null
+++ b/sdk/bin/pub_developer.bat
@@ -0,0 +1,49 @@
+@echo off
+REM Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+REM for details. All rights reserved. Use of this source code is governed by a
+REM BSD-style license that can be found in the LICENSE file.
+
+setlocal
+rem Handle the case where dart-sdk/bin has been symlinked to.
+set DIR_NAME_WITH_SLASH=%~dp0
+set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
+call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
+rem Get rid of surrounding quotes.
+for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
+
+rem Get absolute full name for SDK_DIR.
+for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
+
+rem Remove trailing backslash if there is one
+IF %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
+
+set PUB=%SDK_DIR%\lib\_internal\pub\bin\pub.dart
+set BUILD_DIR=%SDK_DIR%\..\build\ReleaseIA32
+set PACKAGES_DIR=%BUILD_DIR%\packages\
+set DART=%BIN_DIR%\dart
+set DART_IN_BUILT_SDK=%BUILD_DIR%\dart-sdk\bin\dart
+set SNAPSHOT=%BIN_DIR%\snapshots\pub.dart.snapshot
+
+if exist "%SNAPSHOT%" (
+ "%DART%" --checked "%SNAPSHOT%" %*
+) else (
+ "%DART_IN_BUILT_SDK%" --checked --package-root=%PACKAGES_DIR% "%PUB%" %*
+)
+
+endlocal
+
+exit /b %errorlevel%
+
+:follow_links
+setlocal
+for %%i in (%1) do set result=%%~fi
+set current=
+for /f "tokens=2 delims=[]" %%i in ('dir /a:l ^"%~dp1^" 2^>nul ^
+ ^| find "> %~n1 ["') do (
+ set current=%%i
+)
+if not "%current%"=="" call :follow_links "%current%", result
+endlocal & set %~2=%result%
+goto :eof
+
+:end
diff --git a/sdk/lib/_collection_dev/iterable.dart b/sdk/lib/_collection_dev/iterable.dart
index a6a65b2..53b297f 100644
--- a/sdk/lib/_collection_dev/iterable.dart
+++ b/sdk/lib/_collection_dev/iterable.dart
@@ -46,7 +46,7 @@
return elementAt(0);
}
- bool contains(E element) {
+ bool contains(Object element) {
int length = this.length;
for (int i = 0; i < length; i++) {
if (elementAt(i) == element) return true;
@@ -79,7 +79,7 @@
return false;
}
- E firstWhere(bool test(E element), { E orElse() }) {
+ dynamic firstWhere(bool test(E element), { Object orElse() }) {
int length = this.length;
for (int i = 0; i < length; i++) {
E element = elementAt(i);
@@ -92,7 +92,7 @@
throw new StateError("No matching element");
}
- E lastWhere(bool test(E element), { E orElse() }) {
+ dynamic lastWhere(bool test(E element), { Object orElse() }) {
int length = this.length;
for (int i = length - 1; i >= 0; i--) {
E element = elementAt(i);
@@ -216,7 +216,19 @@
/** If null, represents the length of the iterable. */
final int _endOrLength;
- SubListIterable(this._iterable, this._start, this._endOrLength);
+ SubListIterable(this._iterable, this._start, this._endOrLength) {
+ if (_start < 0) {
+ throw new RangeError.value(_start);
+ }
+ if (_endOrLength != null) {
+ if (_endOrLength < 0) {
+ throw new RangeError.value(_endOrLength);
+ }
+ if (_start > _endOrLength) {
+ throw new RangeError.range(_start, 0, _endOrLength);
+ }
+ }
+ }
int get _endIndex {
int length = _iterable.length;
@@ -248,12 +260,12 @@
}
Iterable<E> skip(int count) {
- if (count < 0) throw new ArgumentError(count);
+ if (count < 0) throw new RangeError.value(count);
return new SubListIterable(_iterable, _start + count, _endOrLength);
}
Iterable<E> take(int count) {
- if (count < 0) throw new ArgumentError(count);
+ if (count < 0) throw new RangeError.value(count);
if (_endOrLength == null) {
return new SubListIterable(_iterable, _start, _start + count);
} else {
@@ -518,13 +530,13 @@
SkipIterable(this._iterable, this._skipCount) {
if (_skipCount is! int || _skipCount < 0) {
- throw new ArgumentError(_skipCount);
+ throw new RangeError(_skipCount);
}
}
Iterable<E> skip(int n) {
if (n is! int || n < 0) {
- throw new ArgumentError(n);
+ throw new RangeError.value(n);
}
return new SkipIterable<E>(_iterable, _skipCount + n);
}
@@ -608,7 +620,7 @@
E elementAt(int index) { throw new RangeError.value(index); }
- bool contains(E element) => false;
+ bool contains(Object element) => false;
bool every(bool test(E element)) => true;
@@ -643,11 +655,17 @@
return initialValue;
}
- Iterable<E> skip(int count) => this;
+ Iterable<E> skip(int count) {
+ if (count < 0) throw new RangeError.value(count);
+ return this;
+ }
Iterable<E> skipWhile(bool test(E element)) => this;
- Iterable<E> take(int count) => this;
+ Iterable<E> take(int count) {
+ if (count < 0) throw new RangeError.value(count);
+ this;
+ }
Iterable<E> takeWhile(bool test(E element)) => this;
@@ -780,8 +798,8 @@
}
static dynamic firstWhere(Iterable iterable,
- bool test(dynamic value),
- dynamic orElse()) {
+ bool test(dynamic value),
+ dynamic orElse()) {
for (dynamic element in iterable) {
if (test(element)) return element;
}
diff --git a/sdk/lib/_collection_dev/list.dart b/sdk/lib/_collection_dev/list.dart
index 90a1d16..7f894bb 100644
--- a/sdk/lib/_collection_dev/list.dart
+++ b/sdk/lib/_collection_dev/list.dart
@@ -35,7 +35,7 @@
"Cannot add to a fixed-length list");
}
- bool remove(E element) {
+ bool remove(Object element) {
throw new UnsupportedError(
"Cannot remove from a fixed-length list");
}
@@ -130,7 +130,7 @@
"Cannot add to an unmodifiable list");
}
- bool remove(E element) {
+ bool remove(Object element) {
throw new UnsupportedError(
"Cannot remove from an unmodifiable list");
}
@@ -239,7 +239,7 @@
bool get isEmpty => _values.isEmpty;
bool get isNotEmpty => _values.isNotEmpty;
- bool containsValue(E value) => _values.contains(value);
+ bool containsValue(Object value) => _values.contains(value);
bool containsKey(int key) => key is int && key >= 0 && key < length;
void forEach(void f(int key, E value)) {
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 35b227e..3815390 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -477,12 +477,12 @@
// capture them in the closure.
type.forEachTypeVariable((variable) => useLocal(variable.element));
}
- // TODO(karlklose): try to get rid of the isField check; there is a bug
- // with type variable use in field initializer (in both modes).
if (member.isInstanceMember() && !member.isField()) {
// In checked mode, using a type variable in a type annotation may lead
// to a runtime type check that needs to access the type argument and
- // therefore the closure needs a this-element.
+ // therefore the closure needs a this-element, if it is not in a field
+ // initializer; field initatializers are evaluated in a context where
+ // the type arguments are available in locals.
registerNeedsThis();
}
}
@@ -509,6 +509,12 @@
registerNeedsThis();
} else if (node.isSuperCall) {
registerNeedsThis();
+ } else if (node.isIsCheck || node.isIsNotCheck || node.isTypeCast) {
+ TypeAnnotation annotation = node.typeAnnotationFromIsCheckOrCast;
+ DartType type = elements.getType(annotation);
+ if (type != null && type.containsTypeVariables) {
+ registerNeedsThis();
+ }
} else if (node.isParameterCheck) {
Element parameter = elements[node.receiver];
FunctionElement enclosing = parameter.enclosingElement;
@@ -523,6 +529,12 @@
useLocal(newElement);
cached.parametersWithSentinel[parameter] = newElement;
}
+ } else if (node.isTypeTest) {
+ DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
+ analyzeType(type);
+ } else if (node.isTypeCast) {
+ DartType type = elements.getType(node.arguments.head);
+ analyzeType(type);
}
node.visitChildren(this);
}
@@ -541,44 +553,35 @@
visitNewExpression(NewExpression node) {
DartType type = elements.getType(node);
+ analyzeType(type);
+ node.visitChildren(this);
+ }
- bool hasTypeVariable(DartType type) {
- if (type is TypeVariableType) {
- return true;
- } else if (type is InterfaceType) {
- InterfaceType ifcType = type;
- for (DartType argument in ifcType.typeArguments) {
- if (hasTypeVariable(argument)) {
- return true;
- }
- }
+ void analyzeTypeVariables(DartType type) {
+ type.forEachTypeVariable((TypeVariableType typeVariable) {
+ useLocal(typeVariable.element);
+ // Field initializers are inlined and access the type variable as
+ // normal parameters.
+ if (!outermostElement.isField()) {
+ registerNeedsThis();
}
- return false;
- }
+ });
+ }
- void analyzeTypeVariables(DartType type) {
- if (type is TypeVariableType) {
- useLocal(type.element);
- } else if (type is InterfaceType) {
- InterfaceType ifcType = type;
- for (DartType argument in ifcType.typeArguments) {
- analyzeTypeVariables(argument);
- }
- }
- }
-
+ void analyzeType(DartType type) {
+ // TODO(johnniwinther): Find out why this can be null.
+ if (type == null) return;
if (outermostElement.isMember() &&
- compiler.backend.needsRti(outermostElement.getEnclosingClass())) {
- if (outermostElement.isConstructor() || outermostElement.isField()) {
+ compiler.backend.classNeedsRti(outermostElement.getEnclosingClass())) {
+ if (outermostElement.isConstructor() ||
+ outermostElement.isField()) {
analyzeTypeVariables(type);
} else if (outermostElement.isInstanceMember()) {
- if (hasTypeVariable(type)) {
+ if (type.containsTypeVariables) {
registerNeedsThis();
}
}
}
-
- node.visitChildren(this);
}
// If variables that are declared in the [node] scope are captured and need
@@ -737,7 +740,7 @@
}
if (currentElement.isFactoryConstructor() &&
- compiler.backend.needsRti(currentElement.enclosingElement)) {
+ compiler.backend.classNeedsRti(currentElement.enclosingElement)) {
// Declare the type parameters in the scope. Generative
// constructors just use 'this'.
ClassElement cls = currentElement.enclosingElement;
@@ -746,9 +749,18 @@
});
}
+ DartType type = element.computeType(compiler);
// Compute the function type and check for type variables in return or
// parameter types.
- if (element.computeType(compiler).containsTypeVariables) {
+ if (type.containsTypeVariables) {
+ registerNeedsThis();
+ }
+ // Ensure that closure that need runtime type information has access to
+ // this of the enclosing class.
+ if (element is FunctionElement &&
+ closureData.thisElement != null &&
+ type.containsTypeVariables &&
+ compiler.backend.methodNeedsRti(element)) {
registerNeedsThis();
}
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index ecc86458..d51b1b2 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -32,6 +32,9 @@
/** Caches the createRuntimeType function if registered. */
Element createRuntimeTypeFunction = null;
+ /** Caches the setRuntimeTypeInfo function if registered. */
+ Element setRuntimeTypeInfoFunction = null;
+
ConstantHandler(Compiler compiler, this.constantSystem,
{ bool this.isMetadata: false })
: initialVariableValues = new Map<VariableElement, dynamic>(),
@@ -43,37 +46,58 @@
String get name => 'ConstantHandler';
void registerCompileTimeConstant(Constant constant, TreeElements elements) {
- registerInstantiatedClass(constant.computeType(compiler).element, elements);
+ registerInstantiatedType(constant.computeType(compiler), elements);
if (constant.isFunction()) {
FunctionConstant function = constant;
registerGetOfStaticFunction(function.element);
} else if (constant.isInterceptor()) {
// An interceptor constant references the class's prototype chain.
InterceptorConstant interceptor = constant;
- registerInstantiatedClass(interceptor.dispatchedType.element, elements);
+ registerInstantiatedType(interceptor.dispatchedType, elements);
}
compiledConstants.add(constant);
}
- void registerInstantiatedClass(ClassElement element, TreeElements elements) {
- if (isMetadata) return;
- compiler.enqueuer.codegen.registerInstantiatedClass(element, elements);
+ void registerInstantiatedType(DartType type, TreeElements elements) {
+ if (isMetadata) {
+ compiler.backend.registerMetadataInstantiatedType(type, elements);
+ return;
+ }
+ compiler.enqueuer.codegen.registerInstantiatedType(type, elements);
+ if (type is InterfaceType &&
+ !type.isRaw &&
+ compiler.backend.classNeedsRti(type.element)) {
+ registerSetRuntimeTypeInfoFunction();
+ }
}
void registerStaticUse(Element element) {
- if (isMetadata) return;
+ if (isMetadata) {
+ compiler.backend.registerMetadataStaticUse(element);
+ return;
+ }
compiler.analyzeElement(element.declaration);
compiler.enqueuer.codegen.registerStaticUse(element);
}
void registerGetOfStaticFunction(FunctionElement element) {
- if (isMetadata) return;
+ if (isMetadata) {
+ compiler.backend.registerMetadataGetOfStaticFunction(element);
+ return;
+ }
compiler.analyzeElement(element.declaration);
compiler.enqueuer.codegen.registerGetOfStaticFunction(element);
}
void registerStringInstance(TreeElements elements) {
- registerInstantiatedClass(compiler.stringClass, elements);
+ registerInstantiatedType(compiler.stringClass.rawType, elements);
+ }
+
+ void registerSetRuntimeTypeInfoFunction() {
+ if (setRuntimeTypeInfoFunction != null) return;
+ SourceString helperName = const SourceString('setRuntimeTypeInfo');
+ setRuntimeTypeInfoFunction = compiler.findHelper(helperName);
+ registerStaticUse(setRuntimeTypeInfoFunction);
}
void registerCreateRuntimeTypeFunction() {
@@ -318,17 +342,17 @@
}
Constant visitLiteralBool(LiteralBool node) {
- handler.registerInstantiatedClass(compiler.boolClass, elements);
+ handler.registerInstantiatedType(compiler.boolClass.rawType, elements);
return constantSystem.createBool(node.value);
}
Constant visitLiteralDouble(LiteralDouble node) {
- handler.registerInstantiatedClass(compiler.doubleClass, elements);
+ handler.registerInstantiatedType(compiler.doubleClass.rawType, elements);
return constantSystem.createDouble(node.value);
}
Constant visitLiteralInt(LiteralInt node) {
- handler.registerInstantiatedClass(compiler.intClass, elements);
+ handler.registerInstantiatedType(compiler.intClass.rawType, elements);
return constantSystem.createInt(node.value);
}
@@ -342,9 +366,8 @@
link = link.tail) {
arguments.add(evaluateConstant(link.head));
}
- // TODO(9476): get type parameters.
- compiler.listClass.computeType(compiler);
- DartType type = compiler.listClass.rawType;
+ DartType type = elements.getType(node);
+ handler.registerInstantiatedType(type, elements);
Constant constant = new ListConstant(type, arguments);
handler.registerCompileTimeConstant(constant, elements);
return constant;
@@ -379,9 +402,10 @@
}
}
bool hasProtoKey = (protoValue != null);
- // TODO(9476): this should be a List<String> type.
- compiler.listClass.computeType(compiler);
- DartType keysType = compiler.listClass.rawType;
+ InterfaceType sourceType = elements.getType(node);
+ Link<DartType> arguments =
+ new Link<DartType>.fromList([compiler.stringClass.rawType]);
+ DartType keysType = new InterfaceType(compiler.listClass, arguments);
ListConstant keysList = new ListConstant(keysType, keys);
handler.registerCompileTimeConstant(keysList, elements);
SourceString className = hasProtoKey
@@ -389,9 +413,9 @@
: MapConstant.DART_CLASS;
ClassElement classElement = compiler.jsHelperLibrary.find(className);
classElement.ensureResolved(compiler);
- // TODO(9476): copy over the generic type.
- DartType type = classElement.rawType;
- handler.registerInstantiatedClass(classElement, elements);
+ Link<DartType> typeArgument = sourceType.typeArguments.tail;
+ InterfaceType type = new InterfaceType(classElement, typeArgument);
+ handler.registerInstantiatedType(type, elements);
Constant constant = new MapConstant(type, keysList, values, protoValue);
handler.registerCompileTimeConstant(constant, elements);
return constant;
@@ -444,9 +468,7 @@
Constant makeTypeConstant(Element element) {
DartType elementType = element.computeType(compiler).asRaw();
- if (compiler.mirrorsEnabled) {
- handler.registerInstantiatedClass(element, elements);
- }
+ compiler.backend.registerTypeLiteral(element, elements);
DartType constantType =
compiler.backend.typeImplementation.computeType(compiler);
Constant constant = new TypeConstant(elementType, constantType);
@@ -654,6 +676,12 @@
// constructor to ensure the redirectionTarget has been computed
// correctly. Find a way to avoid this.
compiler.analyzeElement(constructor.declaration);
+
+ InterfaceType type = elements.getType(node);
+ if ( constructor.isRedirectingFactory) {
+ type = constructor.computeTargetType(compiler, type);
+ }
+
constructor = constructor.redirectionTarget;
ClassElement classElement = constructor.getEnclosingClass();
// The constructor must be an implementation to ensure that field
@@ -669,10 +697,7 @@
evaluator.evaluateConstructorFieldValues(arguments);
List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
- handler.registerInstantiatedClass(classElement, elements);
- // TODO(9476): take generic types into account.
- classElement.computeType(compiler);
- DartType type = classElement.rawType;
+ handler.registerInstantiatedType(type, elements);
Constant constant = new ConstructedConstant(type, jsNewArguments);
handler.registerCompileTimeConstant(constant, elements);
return constant;
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 75844c2..a5ac2e0 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -126,7 +126,8 @@
return new ItemCompilationContext();
}
- bool needsRti(ClassElement cls);
+ bool classNeedsRti(ClassElement cls);
+ bool methodNeedsRti(FunctionElement function);
// The following methods are hooks for the backend to register its
// helper methods.
@@ -140,7 +141,7 @@
void registerThrowExpression(TreeElements elements) {}
void registerLazyField(TreeElements elements) {}
void registerTypeVariableExpression(TreeElements elements) {}
- void registerTypeLiteral(TreeElements elements) {}
+ void registerTypeLiteral(Element element, TreeElements elements) {}
void registerStackTraceInCatch(TreeElements elements) {}
void registerIsCheck(DartType type,
Enqueuer enqueuer,
@@ -152,11 +153,31 @@
void registerFallThroughError(TreeElements elements) {}
void registerSuperNoSuchMethod(TreeElements elements) {}
void registerConstantMap(TreeElements elements) {}
- void registerRuntimeType(TreeElements elements) {}
+ /**
+ * Call this to register that an instantiated generic class has a call
+ * method.
+ */
+ void registerGenericCallMethod(Element callMethod,
+ Enqueuer enqueuer,
+ TreeElements elements) {}
+ /**
+ * Call this to register that a getter exists for a function on an
+ * instantiated generic class.
+ */
+ void registerGenericClosure(Element closure,
+ Enqueuer enqueuer,
+ TreeElements elements) {}
+ /**
+ * Call this to register that the [:runtimeType:] property has been accessed.
+ */
+ void registerRuntimeType(Enqueuer enqueuer, TreeElements elements) {}
void registerRequiredType(DartType type, Element enclosingElement) {}
void registerClassUsingVariableExpression(ClassElement cls) {}
+ void registerConstSymbol(String name, TreeElements elements) {}
+ void registerNewSymbol(TreeElements elements) {}
+
bool isNullImplementation(ClassElement cls) {
return cls == compiler.nullClass;
}
@@ -183,9 +204,13 @@
return classElement == compiler.objectClass;
}
- void enableMirrors() {}
-
void registerStaticUse(Element element, Enqueuer enqueuer) {}
+
+ void onLibraryScanned(LibraryElement library, Uri uri) {}
+
+ void registerMetadataInstantiatedType(DartType type, TreeElements elements) {}
+ void registerMetadataStaticUse(Element element) {}
+ void registerMetadataGetOfStaticFunction(FunctionElement element) {}
}
/**
@@ -529,8 +554,6 @@
bool get hasBuildId => buildId != UNDETERMINED_BUILD_ID;
- bool get mirrorsEnabled => mirrorSystemClass != null;
-
bool get analyzeAll => analyzeAllFlag || compileAll;
bool get compileAll => false;
@@ -674,11 +697,10 @@
}
if (uri == Uri.parse('dart:mirrors')) {
mirrorSystemClass = library.find(const SourceString('MirrorSystem'));
- backend.enableMirrors();
- metadataHandler = constantHandler;
} else if (uri == Uri.parse('dart:_collection-dev')) {
symbolImplementationClass = library.find(const SourceString('Symbol'));
}
+ backend.onLibraryScanned(library, uri);
}
void onClassResolved(ClassElement cls) {
@@ -760,6 +782,15 @@
listClass.lookupConstructor(callConstructor);
}
+ Element _filledListConstructor;
+ Element get filledListConstructor {
+ if (_filledListConstructor != null) return _filledListConstructor;
+ Selector callConstructor = new Selector.callConstructor(
+ const SourceString("filled"), listClass.getLibrary());
+ return _filledListConstructor =
+ listClass.lookupConstructor(callConstructor);
+ }
+
void scanBuiltinLibraries() {
jsHelperLibrary = scanBuiltinLibrary('_js_helper');
interceptorsLibrary = scanBuiltinLibrary('_interceptors');
@@ -857,7 +888,6 @@
// Elements required by enqueueHelpers are global dependencies
// that are not pulled in by a particular element.
backend.enqueueHelpers(enqueuer.resolution, globalDependencies);
- resolveReflectiveDataIfNeeded();
processQueue(enqueuer.resolution, main);
enqueuer.resolution.logSummary(log);
@@ -887,7 +917,7 @@
enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN));
}
if (enabledNoSuchMethod) {
- enqueuer.codegen.registerInvocation(NO_SUCH_METHOD, noSuchMethodSelector);
+ enqueuer.codegen.registerInvocation(noSuchMethodSelector);
enqueuer.codegen.addToWorkList(createInvocationMirrorElement);
}
if (compileAll) {
@@ -903,17 +933,6 @@
checkQueues();
}
- void resolveReflectiveDataIfNeeded() {
- // Only need reflective data when dart:mirrors is loaded.
- if (!mirrorsEnabled) return;
-
- for (LibraryElement library in libraries.values) {
- for (Link link = library.metadata; !link.isEmpty; link = link.tail) {
- link.head.ensureResolved(this);
- }
- }
- }
-
void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) {
void enqueueAll(Element element) {
fullyEnqueueTopLevelElement(element, world);
@@ -1128,6 +1147,12 @@
api.Diagnostic.INFO);
}
+ void reportInternalError(Spannable node, String message) {
+ reportMessage(spanFromSpannable(node),
+ MessageKind.GENERIC.error({'text': message}),
+ api.Diagnostic.ERROR);
+ }
+
void reportMessage(SourceSpan span, Diagnostic message, api.Diagnostic kind) {
// TODO(ahe): The names Diagnostic and api.Diagnostic are in
// conflict. Fix it.
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index eae62ead..06e04fc 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -346,14 +346,17 @@
ListConstant(DartType type, List<Constant> entries)
: this.entries = entries,
- hashCode = _computeHash(entries),
+ hashCode = _computeHash(type, entries),
super(type);
bool isList() => true;
- static int _computeHash(List<Constant> entries) {
+ static int _computeHash(DartType type, List<Constant> entries) {
// TODO(floitsch): create a better hash.
- int hash = 0;
- for (Constant input in entries) hash ^= input.hashCode;
+ int hash = 7;
+ for (Constant input in entries) {
+ hash ^= input.hashCode;
+ }
+ hash ^= type.hashCode;
return hash;
}
@@ -361,7 +364,7 @@
if (other is !ListConstant) return false;
ListConstant otherList = other;
if (hashCode != otherList.hashCode) return false;
- // TODO(floitsch): verify that the generic types are the same.
+ if (type != otherList.type) return false;
if (entries.length != otherList.entries.length) return false;
for (int i = 0; i < entries.length; i++) {
if (entries[i] != otherList.entries[i]) return false;
@@ -400,14 +403,17 @@
MapConstant(DartType type, this.keys, List<Constant> values, this.protoValue)
: this.values = values,
- this.hashCode = computeHash(values),
+ this.hashCode = computeHash(type, values),
super(type);
bool isMap() => true;
- static int computeHash(List<Constant> values) {
+ static int computeHash(DartType type, List<Constant> values) {
// TODO(floitsch): create a better hash.
int hash = 0;
- for (Constant value in values) hash ^= value.hashCode;
+ for (Constant value in values) {
+ hash ^= value.hashCode;
+ }
+ hash ^= type.hashCode;
return hash;
}
@@ -415,7 +421,7 @@
if (other is !MapConstant) return false;
MapConstant otherMap = other;
if (hashCode != otherMap.hashCode) return false;
- // TODO(floitsch): verify that the generic types are the same.
+ if (type != other.type) return false;
if (keys != otherMap.keys) return false;
for (int i = 0; i < values.length; i++) {
if (values[i] != otherMap.values[i]) return false;
@@ -475,7 +481,7 @@
for (Constant field in fields) {
hash ^= field.hashCode;
}
- hash ^= type.element.hashCode;
+ hash ^= type.hashCode;
return hash;
}
@@ -483,8 +489,7 @@
if (otherVar is !ConstructedConstant) return false;
ConstructedConstant other = otherVar;
if (hashCode != other.hashCode) return false;
- // TODO(floitsch): verify that the (generic) types are the same.
- if (type.element != other.type.element) return false;
+ if (type != other.type) return false;
if (fields.length != other.fields.length) return false;
for (int i = 0; i < fields.length; i++) {
if (fields[i] != other.fields[i]) return false;
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index 609b2be..358ecab 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -221,7 +221,8 @@
stripAsserts = strips.indexOf('asserts') != -1,
super(compiler);
- bool needsRti(ClassElement cls) => false;
+ bool classNeedsRti(ClassElement cls) => false;
+ bool methodNeedsRti(FunctionElement function) => false;
void enqueueHelpers(ResolutionEnqueuer world, TreeElements elements) {
// Right now resolver doesn't always resolve interfaces needed
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index bcec921..d4fc525 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -908,6 +908,8 @@
}
abstract class DartTypeVisitor<R, A> {
+ const DartTypeVisitor();
+
R visitType(DartType type, A argument);
R visitVoidType(VoidType type, A argument) =>
@@ -938,6 +940,9 @@
visitInterfaceType(type, argument);
}
+/**
+ * Type visitor that determines the subtype relation two types.
+ */
class SubtypeVisitor extends DartTypeVisitor<bool, DartType> {
final Compiler compiler;
final DynamicType dynamicType;
@@ -1140,6 +1145,7 @@
final VoidType voidType;
final DynamicType dynamicType;
final SubtypeVisitor subtypeVisitor;
+ final PotentialSubtypeVisitor potentialSubtypeVisitor;
factory Types(Compiler compiler, BaseClassElementX dynamicElement) {
LibraryElement library = new LibraryElementX(new Script(null, null));
@@ -1148,11 +1154,15 @@
dynamicElement.rawTypeCache = dynamicElement.thisType = dynamicType;
SubtypeVisitor subtypeVisitor =
new SubtypeVisitor(compiler, dynamicType, voidType);
- return new Types.internal(compiler, voidType, dynamicType, subtypeVisitor);
+ PotentialSubtypeVisitor potentialSubtypeVisitor =
+ new PotentialSubtypeVisitor(compiler, dynamicType, voidType);
+
+ return new Types.internal(compiler, voidType, dynamicType,
+ subtypeVisitor, potentialSubtypeVisitor);
}
Types.internal(this.compiler, this.voidType, this.dynamicType,
- this.subtypeVisitor);
+ this.subtypeVisitor, this.potentialSubtypeVisitor);
/** Returns true if t is a subtype of s */
bool isSubtype(DartType t, DartType s) {
@@ -1163,6 +1173,11 @@
return subtypeVisitor.isAssignable(r, s);
}
+ bool isPotentialSubtype(DartType t, DartType s) {
+ // TODO(johnniwinther): Return a set of variable points in the positive
+ // cases.
+ return potentialSubtypeVisitor.isSubtype(t, s);
+ }
/**
* Helper method for performing substitution of a linked list of types.
@@ -1217,3 +1232,23 @@
return typeVariable.element.enclosingElement;
}
}
+
+/**
+ * Type visitor that determines one type could a subtype of another given the
+ * right type variable substitution. The computation is approximate and returns
+ * [:false:] only if we are sure no such substitution exists.
+ */
+class PotentialSubtypeVisitor extends SubtypeVisitor {
+ PotentialSubtypeVisitor(Compiler compiler,
+ DynamicType dynamicType,
+ VoidType voidType)
+ : super(compiler, dynamicType, voidType);
+
+
+ bool isSubtype(DartType t, DartType s) {
+ if (t is TypeVariableType || s is TypeVariableType) {
+ return true;
+ }
+ return super.isSubtype(t, s);
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index ea72505..2bd5812 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -526,6 +526,16 @@
&& node.arguments.isEmpty;
}
+ static bool isFilledListConstructorCall(Element element,
+ Send node,
+ Compiler compiler) {
+ return element == compiler.filledListConstructor
+ && node.isCall
+ && !node.arguments.isEmpty
+ && !node.arguments.tail.isEmpty
+ && node.arguments.tail.tail.isEmpty;
+ }
+
static bool switchStatementHasContinue(SwitchStatement node,
TreeElements elements) {
for (SwitchCase switchCase in node.cases) {
@@ -739,6 +749,16 @@
bool get isRedirectingFactory;
+ /**
+ * Compute the type of the target of a redirecting constructor or factory
+ * for an instantiation site with type [:newType:].
+ *
+ * TODO(karlklose): get rid of this method and resolve the target type
+ * during resolution when we correctly resolve chains of redirections.
+ */
+ InterfaceType computeTargetType(Compiler compiler,
+ InterfaceType newType);
+
// TODO(kasperl): These are bit fishy. Do we really need them?
void set patch(FunctionElement value);
void set origin(FunctionElement value);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 66f97f4..3d90f47 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1253,6 +1253,19 @@
return target;
}
+ InterfaceType computeTargetType(Compiler compiler,
+ InterfaceType newType) {
+ if (!isRedirectingFactory) return newType;
+ ClassElement targetClass = getEnclosingClass();
+ TreeElements treeElements =
+ compiler.enqueuer.resolution.getCachedElements(
+ declaration);
+ FunctionExpression functionNode = parseNode(compiler);
+ Return redirectionNode = functionNode.body;
+ return treeElements.getType(redirectionNode.expression)
+ .subst(newType.typeArguments, targetClass.typeVariables);
+ }
+
/**
* Applies a patch function to this function. The patch function's body
* is used as replacement when parsing this function's body.
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 1352cea..80ed094 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -152,11 +152,7 @@
void registerTypeLiteral(Element element, TreeElements elements) {
registerInstantiatedClass(compiler.typeClass, elements);
- compiler.backend.registerTypeLiteral(elements);
- if (compiler.mirrorsEnabled) {
- // In order to use reflectClass, we need to find the constructor.
- registerInstantiatedClass(element, elements);
- }
+ compiler.backend.registerTypeLiteral(element, elements);
}
bool checkNoEnqueuedInvokedInstanceMethods() {
@@ -177,9 +173,6 @@
cls.implementation.forEachMember(processInstantiatedClassMember);
}
- /**
- * Documentation wanted -- johnniwinther
- */
void processInstantiatedClassMember(ClassElement cls, Element member) {
assert(invariant(member, member.isDeclaration));
if (isProcessed(member)) return;
@@ -232,14 +225,14 @@
if (member.name == Compiler.NO_SUCH_METHOD) {
enableNoSuchMethod(member);
}
+ if (member.name == Compiler.CALL_OPERATOR_NAME &&
+ !cls.typeVariables.isEmpty) {
+ registerGenericCallMethod(member, compiler.globalDependencies);
+ }
// If there is a property access with the same name as a method we
// need to emit the method.
if (universe.hasInvokedGetter(member, compiler)) {
- // We will emit a closure, so make sure the bound closure class is
- // generated.
- registerInstantiatedClass(compiler.boundClosureClass,
- // Precise dependency is not important here.
- compiler.globalDependencies);
+ registerClosurizedMember(member, compiler.globalDependencies);
return addToWorkList(member);
}
// Store the member in [instanceFunctionsByName] to catch
@@ -298,13 +291,9 @@
});
}
- void registerNewSelector(SourceString name,
- Selector selector,
+ void registerNewSelector(Selector selector,
Map<SourceString, Set<Selector>> selectorsMap) {
- if (name != selector.name) {
- String message = "$name != ${selector.name} (${selector.kind})";
- compiler.internalError("Wrong selector name: $message.");
- }
+ SourceString name = selector.name;
Set<Selector> selectors =
selectorsMap.putIfAbsent(name, () => new Set<Selector>());
if (!selectors.contains(selector)) {
@@ -313,38 +302,27 @@
}
}
- void registerInvocation(SourceString methodName, Selector selector) {
+ void registerInvocation(Selector selector) {
task.measure(() {
- registerNewSelector(methodName, selector, universe.invokedNames);
+ registerNewSelector(selector, universe.invokedNames);
});
}
- void registerInvokedGetter(SourceString getterName, Selector selector) {
+ void registerInvokedGetter(Selector selector) {
task.measure(() {
- registerNewSelector(getterName, selector, universe.invokedGetters);
+ registerNewSelector(selector, universe.invokedGetters);
});
}
- void registerInvokedSetter(SourceString setterName, Selector selector) {
+ void registerInvokedSetter(Selector selector) {
task.measure(() {
- registerNewSelector(setterName, selector, universe.invokedSetters);
+ registerNewSelector(selector, universe.invokedSetters);
});
}
/// Called when [:const Symbol(name):] is seen.
void registerConstSymbol(String name, TreeElements elements) {
- // If dart:mirrors is loaded, a const symbol may be used to call a
- // static/top-level method or accessor, instantiate a class, call
- // an instance method or accessor with the given name.
- if (!compiler.mirrorsEnabled) return;
-
- task.ensureAllElementsByName();
-
- for (var link = task.allElementsByName[name];
- link != null && !link.isEmpty;
- link = link.tail) {
- pretendElementWasUsed(link.head, elements);
- }
+ compiler.backend.registerConstSymbol(name, elements);
}
void pretendElementWasUsed(Element element, TreeElements elements) {
@@ -367,27 +345,28 @@
element.asFunctionElement().requiredParameterCount(compiler);
Selector selector =
new Selector.call(element.name, element.getLibrary(), arity);
- registerInvocation(element.name, selector);
+ registerInvocation(selector);
} else if (element.isSetter()) {
Selector selector =
new Selector.setter(element.name, element.getLibrary());
- registerInvokedSetter(element.name, selector);
+ registerInvokedSetter(selector);
} else if (element.isGetter()) {
Selector selector =
new Selector.getter(element.name, element.getLibrary());
- registerInvokedGetter(element.name, selector);
+ registerInvokedGetter(selector);
} else if (element.isField()) {
Selector selector =
new Selector.setter(element.name, element.getLibrary());
- registerInvokedSetter(element.name, selector);
+ registerInvokedSetter(selector);
selector = new Selector.getter(element.name, element.getLibrary());
- registerInvokedGetter(element.name, selector);
+ registerInvokedGetter(selector);
}
}
}
/// Called when [:new Symbol(...):] is seen.
void registerNewSymbol(TreeElements elements) {
+ compiler.backend.registerNewSymbol(elements);
}
void enqueueEverything() {
@@ -408,11 +387,15 @@
String memberName = n.slowToString();
Link<Element> members = map[memberName];
if (members != null) {
+ // [f] might add elements to [: map[memberName] :] during the loop below
+ // so we create a new list for [: map[memberName] :] and prepend the
+ // [remaining] members after the loop.
+ map[memberName] = const Link<Element>();
LinkBuilder<Element> remaining = new LinkBuilder<Element>();
for (; !members.isEmpty; members = members.tail) {
if (!f(members.head)) remaining.addLast(members.head);
}
- map[memberName] = remaining.toLink();
+ map[memberName] = remaining.toLink(map[memberName]);
}
}
@@ -427,6 +410,9 @@
void handleUnseenSelector(SourceString methodName, Selector selector) {
processInstanceMembers(methodName, (Element member) {
if (selector.appliesUnnamed(member, compiler)) {
+ if (member.isFunction() && selector.isGetter()) {
+ registerClosurizedMember(member, compiler.globalDependencies);
+ }
if (member.isField() && member.getEnclosingClass().isNative()) {
if (selector.isGetter() || selector.isCall()) {
nativeEnqueuer.registerFieldLoad(member);
@@ -453,11 +439,7 @@
if (selector.isGetter()) {
processInstanceFunctions(methodName, (Element member) {
if (selector.appliesUnnamed(member, compiler)) {
- // We will emit a closure, so make sure the bound closure class is
- // generated.
- registerInstantiatedClass(compiler.boundClosureClass,
- // Precise dependency is not important here.
- compiler.globalDependencies);
+ registerBoundClosure();
return true;
}
return false;
@@ -484,49 +466,27 @@
universe.staticFunctionsNeedingGetter.add(element);
}
- void registerDynamicInvocation(SourceString methodName, Selector selector) {
+ void registerDynamicInvocation(Selector selector) {
assert(selector != null);
- registerInvocation(methodName, selector);
- }
-
- void registerDynamicInvocationOf(Element element, Selector selector) {
- assert(selector.isCall()
- || selector.isOperator()
- || selector.isIndex()
- || selector.isIndexSet());
- if (element.isFunction() || element.isGetter()) {
- addToWorkList(element);
- } else if (element.isAbstractField()) {
- AbstractFieldElement field = element;
- // Since the invocation is a dynamic call on a getter, we only
- // need to schedule the getter on the work list.
- addToWorkList(field.getter);
- } else {
- assert(element.isField());
- }
- // We also need to add the selector to the invoked names map,
- // because the emitter uses that map to generate parameter stubs.
- Set<Selector> selectors = universe.invokedNames.putIfAbsent(
- element.name, () => new Set<Selector>());
- selectors.add(selector);
+ registerInvocation(selector);
}
void registerSelectorUse(Selector selector) {
if (selector.isGetter()) {
- registerInvokedGetter(selector.name, selector);
+ registerInvokedGetter(selector);
} else if (selector.isSetter()) {
- registerInvokedSetter(selector.name, selector);
+ registerInvokedSetter(selector);
} else {
- registerInvocation(selector.name, selector);
+ registerInvocation(selector);
}
}
- void registerDynamicGetter(SourceString methodName, Selector selector) {
- registerInvokedGetter(methodName, selector);
+ void registerDynamicGetter(Selector selector) {
+ registerInvokedGetter(selector);
}
- void registerDynamicSetter(SourceString methodName, Selector selector) {
- registerInvokedSetter(methodName, selector);
+ void registerDynamicSetter(Selector selector) {
+ registerInvokedSetter(selector);
}
void registerFieldGetter(Element element) {
@@ -538,12 +498,12 @@
}
void registerIsCheck(DartType type, TreeElements elements) {
+ type = universe.registerIsCheck(type, compiler);
// Even in checked mode, type annotations for return type and argument
// types do not imply type checks, so there should never be a check
// against the type variable of a typedef.
assert(type.kind != TypeKind.TYPE_VARIABLE ||
!type.element.enclosingElement.isTypedef());
- universe.isChecks.add(type);
compiler.backend.registerIsCheck(type, this, elements);
}
@@ -561,6 +521,32 @@
compiler.backend.registerAsCheck(type, elements);
}
+ void registerGenericCallMethod(Element element, TreeElements elements) {
+ compiler.backend.registerGenericCallMethod(element, this, elements);
+ universe.genericCallMethods.add(element);
+ }
+
+ void registerBoundClosure() {
+ registerInstantiatedClass(compiler.boundClosureClass,
+ // Precise dependency is not important here.
+ compiler.globalDependencies);
+ }
+
+ void registerClosurizedMember(Element element, TreeElements elements) {
+ if (element.computeType(compiler).containsTypeVariables) {
+ registerClosurizedGenericMember(element, elements);
+ } else {
+ registerBoundClosure();
+ }
+ universe.closurizedMembers.add(element);
+ }
+
+ void registerClosurizedGenericMember(Element element, TreeElements elements) {
+ registerBoundClosure();
+ compiler.backend.registerGenericClosure(element, this, elements);
+ universe.closurizedGenericMembers.add(element);
+ }
+
void forEach(f(WorkItem work));
void forEachPostProcessTask(f(PostProcessTask work)) {}
@@ -655,7 +641,7 @@
// runtime type.
compiler.enabledRuntimeType = true;
// TODO(ahe): Record precise dependency here.
- compiler.backend.registerRuntimeType(compiler.globalDependencies);
+ compiler.backend.registerRuntimeType(this, compiler.globalDependencies);
} else if (element == compiler.functionApplyMethod) {
compiler.enabledFunctionApply = true;
} else if (element == compiler.invokeOnMethod) {
@@ -683,7 +669,7 @@
Selector selector = compiler.noSuchMethodSelector;
compiler.enabledNoSuchMethod = true;
- registerInvocation(Compiler.NO_SUCH_METHOD, selector);
+ registerInvocation(selector);
compiler.createInvocationMirrorElement =
compiler.findHelper(Compiler.CREATE_INVOCATION_MIRROR);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 5afa2a0..46abf0a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -11,6 +11,118 @@
: boundsChecked = new Set<HInstruction>();
}
+class CheckedModeHelper {
+ final SourceString name;
+
+ const CheckedModeHelper(SourceString this.name);
+
+ Element getElement(Compiler compiler) => compiler.findHelper(name);
+
+ jsAst.Expression generateCall(SsaCodeGenerator codegen,
+ HTypeConversion node) {
+ Element helperElement = getElement(codegen.compiler);
+ codegen.world.registerStaticUse(helperElement);
+ List<jsAst.Expression> arguments = <jsAst.Expression>[];
+ codegen.use(node.checkedInput);
+ arguments.add(codegen.pop());
+ generateAdditionalArguments(codegen, node, arguments);
+ String helperName = codegen.backend.namer.isolateAccess(helperElement);
+ return new jsAst.Call(new jsAst.VariableUse(helperName), arguments);
+ }
+
+ void generateAdditionalArguments(SsaCodeGenerator codegen,
+ HTypeConversion node,
+ List<jsAst.Expression> arguments) {
+ assert(!node.typeExpression.isMalformed);
+ // No additional arguments needed.
+ }
+}
+
+class PropertyCheckedModeHelper extends CheckedModeHelper {
+ const PropertyCheckedModeHelper(SourceString name) : super(name);
+
+ void generateAdditionalArguments(SsaCodeGenerator codegen,
+ HTypeConversion node,
+ List<jsAst.Expression> arguments) {
+ DartType type = node.typeExpression;
+ assert(!type.isMalformed);
+ String additionalArgument = codegen.backend.namer.operatorIsType(type);
+ arguments.add(js.string(additionalArgument));
+ }
+}
+
+class TypeVariableCheckedModeHelper extends CheckedModeHelper {
+ const TypeVariableCheckedModeHelper(SourceString name) : super(name);
+
+ void generateAdditionalArguments(SsaCodeGenerator codegen,
+ HTypeConversion node,
+ List<jsAst.Expression> arguments) {
+ assert(node.typeExpression.kind == TypeKind.TYPE_VARIABLE);
+ codegen.use(node.typeRepresentation);
+ arguments.add(codegen.pop());
+ }
+}
+
+class SubtypeCheckedModeHelper extends CheckedModeHelper {
+ const SubtypeCheckedModeHelper(SourceString name) : super(name);
+
+ void generateAdditionalArguments(SsaCodeGenerator codegen,
+ HTypeConversion node,
+ List<jsAst.Expression> arguments) {
+ DartType type = node.typeExpression;
+ Element element = type.element;
+ String isField = codegen.backend.namer.operatorIs(element);
+ arguments.add(js.string(isField));
+ codegen.use(node.typeRepresentation);
+ arguments.add(codegen.pop());
+ String asField = codegen.backend.namer.substitutionName(element);
+ arguments.add(js.string(asField));
+ }
+}
+
+class FunctionTypeCheckedModeHelper extends CheckedModeHelper {
+ const FunctionTypeCheckedModeHelper(SourceString name) : super(name);
+
+ void generateAdditionalArguments(SsaCodeGenerator codegen,
+ HTypeConversion node,
+ List<jsAst.Expression> arguments) {
+ DartType type = node.typeExpression;
+ String signatureName = codegen.backend.namer.getFunctionTypeName(type);
+ arguments.add(js.string(signatureName));
+
+ if (type.containsTypeVariables) {
+ ClassElement contextClass = Types.getClassContext(type);
+ String contextName = codegen.backend.namer.getName(contextClass);
+ arguments.add(js.string(contextName));
+
+ if (node.contextIsTypeArguments) {
+ arguments.add(new jsAst.LiteralNull());
+ codegen.use(node.context);
+ arguments.add(codegen.pop());
+ } else {
+ codegen.use(node.context);
+ arguments.add(codegen.pop());
+ }
+ }
+ }
+}
+
+class MalformedCheckedModeHelper extends CheckedModeHelper {
+ const MalformedCheckedModeHelper(SourceString name) : super(name);
+
+ void generateAdditionalArguments(SsaCodeGenerator codegen,
+ HTypeConversion node,
+ List<jsAst.Expression> arguments) {
+ DartType type = node.typeExpression;
+ assert(type.isMalformed);
+ String reasons = Types.fetchReasonsFromMalformedType(type);
+ arguments.add(js.string('$type'));
+ // TODO(johnniwinther): Handle escaping correctly.
+ arguments.add(js.string(reasons));
+ }
+}
+
+
class JavaScriptBackend extends Backend {
SsaBuilderTask builder;
SsaOptimizerTask optimizer;
@@ -98,13 +210,6 @@
ClassElement jsIndexingBehaviorInterface;
/**
- * A collection of selectors of intercepted method calls. The
- * emitter uses this set to generate the [:ObjectInterceptor:] class
- * whose members just forward the call to the intercepted receiver.
- */
- final Set<Selector> usedInterceptors;
-
- /**
* A collection of selectors that must have a one shot interceptor
* generated.
*/
@@ -163,9 +268,40 @@
/// dart:mirrors has been loaded.
FunctionElement preserveNamesMarker;
+ /// Holds the method "preserveMetadata" in js_mirrors when
+ /// dart:mirrors has been loaded.
+ FunctionElement preserveMetadataMarker;
+
+ /// True if a call to preserveMetadataMarker has been seen. This means that
+ /// metadata must be retained for dart:mirrors to work correctly.
+ bool mustRetainMetadata = false;
+
+ /// True if any metadata has been retained. This is slightly different from
+ /// [mustRetainMetadata] and tells us if any metadata was retained. For
+ /// example, if [mustRetainMetadata] is true but there is no metadata in the
+ /// program, this variable will stil be false.
+ bool hasRetainedMetadata = false;
+
+ /// True if a call to preserveNames has been seen.
+ bool mustPreserveNames = false;
+
+ /// True if a call to disableTreeShaking has been seen.
+ bool isTreeShakingDisabled = false;
+
+ /// List of instantiated types from metadata. If metadata must be preserved,
+ /// these types must registered.
+ final List<Dependency> metadataInstantiatedTypes = <Dependency>[];
+
+ /// List of elements used from metadata. If metadata must be preserved,
+ /// these elements must be compiled.
+ final List<Element> metadataStaticUse = <Element>[];
+
+ /// List of tear-off functions referenced from metadata. If metadata must be
+ /// preserved, these elements must be compiled.
+ final List<FunctionElement> metadataGetOfStaticFunction = <FunctionElement>[];
+
JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
: namer = determineNamer(compiler),
- usedInterceptors = new Set<Selector>(),
oneShotInterceptors = new Map<String, Selector>(),
interceptedElements = new Map<SourceString, Set<Element>>(),
rti = new RuntimeTypes(compiler),
@@ -193,10 +329,6 @@
return false;
}
- void addInterceptedSelector(Selector selector) {
- usedInterceptors.add(selector);
- }
-
String registerOneShotInterceptor(Selector selector) {
Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
String name = namer.getOneShotInterceptorName(selector, classes);
@@ -609,8 +741,11 @@
enqueueInResolution(getCyclicThrowHelper(), elements);
}
- void registerTypeLiteral(TreeElements elements) {
+ void registerTypeLiteral(Element element, TreeElements elements) {
enqueueInResolution(getCreateRuntimeType(), elements);
+ // TODO(ahe): Might want to register [element] as an instantiated class
+ // when reflection is used. However, as long as we disable tree-shaking
+ // eagerly it doesn't matter.
}
void registerStackTraceInCatch(TreeElements elements) {
@@ -625,25 +760,72 @@
enqueueInResolution(getGetRuntimeTypeArgument(), elements);
}
- void registerRuntimeType(TreeElements elements) {
+ void registerGenericCallMethod(Element callMethod,
+ Enqueuer enqueuer, TreeElements elements) {
+ if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) {
+ registerComputeSignature(enqueuer, elements);
+ }
+ }
+
+ void registerGenericClosure(Element closure,
+ Enqueuer enqueuer, TreeElements elements) {
+ if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) {
+ registerComputeSignature(enqueuer, elements);
+ }
+ }
+
+ void registerComputeSignature(Enqueuer enqueuer, TreeElements elements) {
+ // Calls to [:computeSignature:] are generated by the emitter and we
+ // therefore need to enqueue the used elements in the codegen enqueuer as
+ // well as in the resolution enqueuer.
+ enqueue(enqueuer, getSetRuntimeTypeInfo(), elements);
+ enqueue(enqueuer, getGetRuntimeTypeInfo(), elements);
+ enqueue(enqueuer, getComputeSignature(), elements);
+ enqueue(enqueuer, getGetRuntimeTypeArguments(), elements);
+ enqueuer.registerInstantiatedClass(compiler.listClass, elements);
+ }
+
+ void registerRuntimeType(Enqueuer enqueuer, TreeElements elements) {
+ registerComputeSignature(enqueuer, elements);
enqueueInResolution(getSetRuntimeTypeInfo(), elements);
enqueueInResolution(getGetRuntimeTypeInfo(), elements);
- enqueueInResolution(getGetRuntimeTypeArgument(), elements);
+ registerGetRuntimeTypeArgument(elements);
compiler.enqueuer.resolution.registerInstantiatedClass(
compiler.listClass, elements);
}
void registerTypeVariableExpression(TreeElements elements) {
- registerRuntimeType(elements);
+ enqueueInResolution(getSetRuntimeTypeInfo(), elements);
+ enqueueInResolution(getGetRuntimeTypeInfo(), elements);
+ registerGetRuntimeTypeArgument(elements);
+ compiler.enqueuer.resolution.registerInstantiatedClass(
+ compiler.listClass, elements);
enqueueInResolution(getRuntimeTypeToString(), elements);
enqueueInResolution(getCreateRuntimeType(), elements);
}
void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) {
+ type = type.unalias(compiler);
world.registerInstantiatedClass(compiler.boolClass, elements);
- bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
bool inCheckedMode = compiler.enableTypeAssertions;
- if (!type.isRaw || isTypeVariable) {
+ // [registerIsCheck] is also called for checked mode checks, so we
+ // need to register checked mode helpers.
+ if (inCheckedMode) {
+ CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false);
+ if (helper != null) world.addToWorkList(helper.getElement(compiler));
+ // We also need the native variant of the check (for DOM types).
+ helper = getNativeCheckedModeHelper(type, typeCast: false);
+ if (helper != null) world.addToWorkList(helper.getElement(compiler));
+ if (type.isMalformed) {
+ enqueueInResolution(getThrowMalformedSubtypeError(), elements);
+ return;
+ }
+ } else if (type.isMalformed) {
+ registerThrowRuntimeError(elements);
+ return;
+ }
+ bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
+ if (!type.isRaw || type.containsTypeVariables) {
enqueueInResolution(getSetRuntimeTypeInfo(), elements);
enqueueInResolution(getGetRuntimeTypeInfo(), elements);
enqueueInResolution(getGetRuntimeTypeArgument(), elements);
@@ -659,14 +841,8 @@
}
world.registerInstantiatedClass(compiler.listClass, elements);
}
- // [registerIsCheck] is also called for checked mode checks, so we
- // need to register checked mode helpers.
- if (inCheckedMode) {
- Element e = getCheckedModeHelper(type, typeCast: false);
- if (e != null) world.addToWorkList(e);
- // We also need the native variant of the check (for DOM types).
- e = getNativeCheckedModeHelper(type, typeCast: false);
- if (e != null) world.addToWorkList(e);
+ if (type is FunctionType) {
+ enqueueInResolution(getCheckFunctionSubtype(), elements);
}
if (type.element.isNative()) {
// We will neeed to add the "$is" and "$as" properties on the
@@ -675,14 +851,17 @@
world.addToWorkList(
compiler.findHelper(const SourceString('defineProperty')));
}
- }
+ }
void registerAsCheck(DartType type, TreeElements elements) {
- Element e = getCheckedModeHelper(type, typeCast: true);
- enqueueInResolution(e, elements);
+ type = type.unalias(compiler);
+ CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: true);
+ enqueueInResolution(helper.getElement(compiler), elements);
// We also need the native variant of the check (for DOM types).
- e = getNativeCheckedModeHelper(type, typeCast: true);
- enqueueInResolution(e, elements);
+ helper = getNativeCheckedModeHelper(type, typeCast: true);
+ if (helper != null) {
+ enqueueInResolution(helper.getElement(compiler), elements);
+ }
}
void registerThrowNoSuchMethod(TreeElements elements) {
@@ -746,7 +925,7 @@
rti.classesUsingTypeVariableExpression.add(cls);
}
- bool needsRti(ClassElement cls) {
+ bool classNeedsRti(ClassElement cls) {
return rti.classesNeedingRti.contains(cls.declaration) ||
compiler.enabledRuntimeType;
}
@@ -766,11 +945,20 @@
|| classElement == jsNullClass;
}
+ bool methodNeedsRti(FunctionElement function) {
+ return rti.methodsNeedingRti.contains(function) ||
+ compiler.enabledRuntimeType;
+ }
+
+ void enqueue(Enqueuer enqueuer, Element e, TreeElements elements) {
+ enqueuer.addToWorkList(e);
+ elements.registerDependency(e);
+ }
+
void enqueueInResolution(Element e, TreeElements elements) {
if (e == null) return;
ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution;
- enqueuer.addToWorkList(e);
- elements.registerDependency(e);
+ enqueue(enqueuer, e, elements);
}
void registerConstantMap(TreeElements elements) {
@@ -869,10 +1057,9 @@
* the resolver with interface types (int, String, ...), and by the SSA
* backend with implementation types (JSInt, JSString, ...).
*/
- Element getCheckedModeHelper(DartType type, {bool typeCast}) {
- SourceString name = getCheckedModeHelperName(
+ CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) {
+ return getCheckedModeHelperInternal(
type, typeCast: typeCast, nativeCheckOnly: false);
- return compiler.findHelper(name);
}
/**
@@ -880,20 +1067,19 @@
* check/type cast on [type] at runtime. If no native helper exists for
* [type], [:null:] is returned.
*/
- Element getNativeCheckedModeHelper(DartType type, {bool typeCast}) {
- SourceString sourceName = getCheckedModeHelperName(
+ CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) {
+ return getCheckedModeHelperInternal(
type, typeCast: typeCast, nativeCheckOnly: true);
- if (sourceName == null) return null;
- return compiler.findHelper(sourceName);
}
/**
- * Returns the name of the type check/type cast helper method for [type]. If
+ * Returns the checked mode helper for the type check/type cast for [type]. If
* [nativeCheckOnly] is [:true:], only names for native helpers are returned.
*/
- SourceString getCheckedModeHelperName(DartType type,
- {bool typeCast,
- bool nativeCheckOnly}) {
+ CheckedModeHelper getCheckedModeHelperInternal(DartType type,
+ {bool typeCast,
+ bool nativeCheckOnly}) {
+ assert(type.kind != TypeKind.TYPEDEF);
Element element = type.element;
bool nativeCheck = nativeCheckOnly ||
emitter.nativeEmitter.requiresNativeIsCheck(element);
@@ -902,94 +1088,122 @@
// with a malformed argument type.
if (nativeCheckOnly) return null;
return typeCast
- ? const SourceString('malformedTypeCast')
- : const SourceString('malformedTypeCheck');
+ ? const MalformedCheckedModeHelper(
+ const SourceString('malformedTypeCast'))
+ : const MalformedCheckedModeHelper(
+ const SourceString('malformedTypeCheck'));
} else if (type == compiler.types.voidType) {
assert(!typeCast); // Cannot cast to void.
if (nativeCheckOnly) return null;
- return const SourceString('voidTypeCheck');
+ return const CheckedModeHelper(const SourceString('voidTypeCheck'));
} else if (element == jsStringClass || element == compiler.stringClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const SourceString("stringTypeCast")
- : const SourceString('stringTypeCheck');
+ ? const CheckedModeHelper(const SourceString("stringTypeCast"))
+ : const CheckedModeHelper(const SourceString('stringTypeCheck'));
} else if (element == jsDoubleClass || element == compiler.doubleClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const SourceString("doubleTypeCast")
- : const SourceString('doubleTypeCheck');
+ ? const CheckedModeHelper(const SourceString("doubleTypeCast"))
+ : const CheckedModeHelper(const SourceString('doubleTypeCheck'));
} else if (element == jsNumberClass || element == compiler.numClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const SourceString("numTypeCast")
- : const SourceString('numTypeCheck');
+ ? const CheckedModeHelper(const SourceString("numTypeCast"))
+ : const CheckedModeHelper(const SourceString('numTypeCheck'));
} else if (element == jsBoolClass || element == compiler.boolClass) {
if (nativeCheckOnly) return null;
return typeCast
- ? const SourceString("boolTypeCast")
- : const SourceString('boolTypeCheck');
+ ? const CheckedModeHelper(const SourceString("boolTypeCast"))
+ : const CheckedModeHelper(const SourceString('boolTypeCheck'));
} else if (element == jsIntClass || element == compiler.intClass) {
if (nativeCheckOnly) return null;
- return typeCast ?
- const SourceString("intTypeCast") :
- const SourceString('intTypeCheck');
+ return typeCast
+ ? const CheckedModeHelper(const SourceString("intTypeCast"))
+ : const CheckedModeHelper(const SourceString('intTypeCheck'));
} else if (Elements.isNumberOrStringSupertype(element, compiler)) {
if (nativeCheck) {
return typeCast
- ? const SourceString("numberOrStringSuperNativeTypeCast")
- : const SourceString('numberOrStringSuperNativeTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("numberOrStringSuperNativeTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('numberOrStringSuperNativeTypeCheck'));
} else {
return typeCast
- ? const SourceString("numberOrStringSuperTypeCast")
- : const SourceString('numberOrStringSuperTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("numberOrStringSuperTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('numberOrStringSuperTypeCheck'));
}
} else if (Elements.isStringOnlySupertype(element, compiler)) {
if (nativeCheck) {
return typeCast
- ? const SourceString("stringSuperNativeTypeCast")
- : const SourceString('stringSuperNativeTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("stringSuperNativeTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('stringSuperNativeTypeCheck'));
} else {
return typeCast
- ? const SourceString("stringSuperTypeCast")
- : const SourceString('stringSuperTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("stringSuperTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('stringSuperTypeCheck'));
}
} else if ((element == compiler.listClass || element == jsArrayClass) &&
type.isRaw) {
if (nativeCheckOnly) return null;
return typeCast
- ? const SourceString("listTypeCast")
- : const SourceString('listTypeCheck');
+ ? const CheckedModeHelper(const SourceString("listTypeCast"))
+ : const CheckedModeHelper(const SourceString('listTypeCheck'));
} else {
if (Elements.isListSupertype(element, compiler)) {
if (nativeCheck) {
return typeCast
- ? const SourceString("listSuperNativeTypeCast")
- : const SourceString('listSuperNativeTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("listSuperNativeTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('listSuperNativeTypeCheck'));
} else {
return typeCast
- ? const SourceString("listSuperTypeCast")
- : const SourceString('listSuperTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("listSuperTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('listSuperTypeCheck'));
}
} else {
if (nativeCheck) {
// TODO(karlklose): can we get rid of this branch when we use
// interceptors?
return typeCast
- ? const SourceString("interceptedTypeCast")
- : const SourceString('interceptedTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString("interceptedTypeCast"))
+ : const PropertyCheckedModeHelper(
+ const SourceString('interceptedTypeCheck'));
} else {
if (type.kind == TypeKind.INTERFACE && !type.isRaw) {
return typeCast
- ? const SourceString('subtypeCast')
- : const SourceString('assertSubtype');
+ ? const SubtypeCheckedModeHelper(
+ const SourceString('subtypeCast'))
+ : const SubtypeCheckedModeHelper(
+ const SourceString('assertSubtype'));
} else if (type.kind == TypeKind.TYPE_VARIABLE) {
return typeCast
- ? const SourceString('subtypeOfRuntimeTypeCast')
- : const SourceString('assertSubtypeOfRuntimeType');
+ ? const TypeVariableCheckedModeHelper(
+ const SourceString('subtypeOfRuntimeTypeCast'))
+ : const TypeVariableCheckedModeHelper(
+ const SourceString('assertSubtypeOfRuntimeType'));
+ } else if (type.kind == TypeKind.FUNCTION) {
+ return typeCast
+ ? const FunctionTypeCheckedModeHelper(
+ const SourceString('functionSubtypeCast'))
+ : const FunctionTypeCheckedModeHelper(
+ const SourceString('assertFunctionSubtype'));
} else {
return typeCast
- ? const SourceString('propertyTypeCast')
- : const SourceString('propertyTypeCheck');
+ ? const PropertyCheckedModeHelper(
+ const SourceString('propertyTypeCast'))
+ : const PropertyCheckedModeHelper(
+ const SourceString('propertyTypeCheck'));
}
}
}
@@ -1004,6 +1218,10 @@
return compiler.findHelper(const SourceString('throwRuntimeError'));
}
+ Element getMalformedTypeCheck() {
+ return compiler.findHelper(const SourceString('malformedTypeCheck'));
+ }
+
Element getThrowMalformedSubtypeError() {
return compiler.findHelper(
const SourceString('throwMalformedSubtypeError'));
@@ -1046,6 +1264,14 @@
return compiler.findHelper(const SourceString('getRuntimeTypeInfo'));
}
+ Element getComputeSignature() {
+ return compiler.findHelper(const SourceString('computeSignature'));
+ }
+
+ Element getGetRuntimeTypeArguments() {
+ return compiler.findHelper(const SourceString('getRuntimeTypeArguments'));
+ }
+
Element getGetRuntimeTypeArgument() {
return compiler.findHelper(const SourceString('getRuntimeTypeArgument'));
}
@@ -1071,6 +1297,10 @@
const SourceString('assertSubtypeOfRuntimeType'));
}
+ Element getCheckFunctionSubtype() {
+ return compiler.findHelper(const SourceString('checkFunctionSubtype'));
+ }
+
Element getThrowNoSuchMethod() {
return compiler.findHelper(const SourceString('throwNoSuchMethod'));
}
@@ -1122,19 +1352,102 @@
ClassElement get boolImplementation => jsBoolClass;
ClassElement get nullImplementation => jsNullClass;
- void enableMirrors() {
- LibraryElement library = compiler.libraries['dart:_js_mirrors'];
- disableTreeShakingMarker =
- library.find(const SourceString('disableTreeShaking'));
- preserveNamesMarker =
- library.find(const SourceString('preserveNames'));
- }
-
void registerStaticUse(Element element, Enqueuer enqueuer) {
if (element == disableTreeShakingMarker) {
enqueuer.enqueueEverything();
+ if (isTreeShakingDisabled) return;
compiler.disableTypeInferenceForMirrors = true;
+ isTreeShakingDisabled = true;
} else if (element == preserveNamesMarker) {
+ if (mustPreserveNames) return;
+ mustPreserveNames = true;
+ compiler.log('Preserving names.');
+ } else if (element == preserveMetadataMarker) {
+ if (mustRetainMetadata) return;
+ compiler.log('Retaining metadata.');
+ mustRetainMetadata = true;
+ for (LibraryElement library in compiler.libraries.values) {
+ if (retainMetadataOf(library)) {
+ for (Link link = library.metadata; !link.isEmpty; link = link.tail) {
+ link.head.ensureResolved(compiler);
+ }
+ }
+ }
+ for (Dependency dependency in metadataInstantiatedTypes) {
+ registerMetadataInstantiatedType(dependency.type, dependency.user);
+ }
+ metadataInstantiatedTypes.clear();
+ for (Element e in metadataStaticUse) {
+ registerMetadataStaticUse(e);
+ }
+ metadataStaticUse.clear();
+ for (Element e in metadataGetOfStaticFunction) {
+ registerMetadataGetOfStaticFunction(e);
+ }
+ metadataGetOfStaticFunction.clear();
}
}
+
+ /// Called when [:const Symbol(name):] is seen.
+ void registerConstSymbol(String name, TreeElements elements) {
+ }
+
+ /// Called when [:new Symbol(...):] is seen.
+ void registerNewSymbol(TreeElements elements) {
+ }
+
+ bool retainGetter(Element element) => isTreeShakingDisabled;
+
+ bool retainSetter(Element element) => isTreeShakingDisabled;
+
+ bool retainName(SourceString name) => mustPreserveNames;
+
+ bool retainMetadataOf(Element element) {
+ if (mustRetainMetadata) hasRetainedMetadata = true;
+ return mustRetainMetadata;
+ }
+
+ void onLibraryScanned(LibraryElement library, Uri uri) {
+ if (uri == Uri.parse('dart:_js_mirrors')) {
+ disableTreeShakingMarker =
+ library.find(const SourceString('disableTreeShaking'));
+ preserveMetadataMarker =
+ library.find(const SourceString('preserveMetadata'));
+ } else if (uri == Uri.parse('dart:_js_names')) {
+ preserveNamesMarker =
+ library.find(const SourceString('preserveNames'));
+ }
+ }
+
+ void registerMetadataInstantiatedType(DartType type, TreeElements elements) {
+ if (mustRetainMetadata) {
+ compiler.constantHandler.registerInstantiatedType(type, elements);
+ } else {
+ metadataInstantiatedTypes.add(new Dependency(type, elements));
+ }
+ }
+
+ void registerMetadataStaticUse(Element element) {
+ if (mustRetainMetadata) {
+ compiler.constantHandler.registerStaticUse(element);
+ } else {
+ metadataStaticUse.add(element);
+ }
+ }
+
+ void registerMetadataGetOfStaticFunction(FunctionElement element) {
+ if (mustRetainMetadata) {
+ compiler.constantHandler.registerGetOfStaticFunction(element);
+ } else {
+ metadataGetOfStaticFunction.add(element);
+ }
+ }
+}
+
+/// Records that [type] is used by [user.element].
+class Dependency {
+ final DartType type;
+ final TreeElements user;
+
+ const Dependency(this.type, this.user);
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
index 2b4d152..c3cff04 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -209,11 +209,12 @@
}
jsAst.Expression visitList(ListConstant constant) {
- return new jsAst.Call(
+ jsAst.Expression value = new jsAst.Call(
new jsAst.PropertyAccess.field(
new jsAst.VariableUse(namer.isolateName),
'makeConstantList'),
[new jsAst.ArrayInitializer.from(_array(constant.entries))]);
+ return maybeAddTypeArguments(constant.type, value);
}
String getJsConstructor(ClassElement element) {
@@ -276,23 +277,27 @@
badFieldCountError();
}
- return new jsAst.New(
+ jsAst.Expression value = new jsAst.New(
new jsAst.VariableUse(getJsConstructor(classElement)),
arguments);
+ return maybeAddTypeArguments(constant.type, value);
+ }
+
+ JavaScriptBackend get backend => compiler.backend;
+
+ jsAst.PropertyAccess getHelperProperty(Element helper) {
+ String helperName = backend.namer.getName(helper);
+ return new jsAst.PropertyAccess.field(
+ new jsAst.VariableUse(namer.CURRENT_ISOLATE),
+ helperName);
}
jsAst.Expression visitType(TypeConstant constant) {
- JavaScriptBackend backend = compiler.backend;
- Element helper = backend.getCreateRuntimeType();
- String helperName = backend.namer.getName(helper);
DartType type = constant.representedType;
String name = namer.getRuntimeTypeName(type.element);
jsAst.Expression typeName = new jsAst.LiteralString("'$name'");
- return new jsAst.Call(
- new jsAst.PropertyAccess.field(
- new jsAst.VariableUse(namer.CURRENT_ISOLATE),
- helperName),
- [typeName]);
+ return new jsAst.Call(getHelperProperty(backend.getCreateRuntimeType()),
+ [typeName]);
}
jsAst.Expression visitInterceptor(InterceptorConstant constant) {
@@ -303,9 +308,10 @@
}
jsAst.Expression visitConstructed(ConstructedConstant constant) {
- return new jsAst.New(
+ jsAst.New instantiation = new jsAst.New(
new jsAst.VariableUse(getJsConstructor(constant.type.element)),
_array(constant.fields));
+ return maybeAddTypeArguments(constant.type, instantiation);
}
List<jsAst.Expression> _array(List<Constant> values) {
@@ -315,4 +321,22 @@
}
return valueList;
}
+
+ jsAst.Expression maybeAddTypeArguments(InterfaceType type,
+ jsAst.Expression value) {
+ if (type is InterfaceType &&
+ !type.isRaw &&
+ backend.classNeedsRti(type.element)) {
+ InterfaceType interface = type;
+ RuntimeTypes rti = backend.rti;
+ Iterable<String> arguments = interface.typeArguments
+ .toList(growable: false)
+ .map((DartType type) => rti.getTypeRepresentation(type, (_){}));
+ jsAst.Expression argumentList =
+ new jsAst.LiteralString('[${arguments.join(', ')}]');
+ return new jsAst.Call(getHelperProperty(backend.getSetRuntimeTypeInfo()),
+ [value, argumentList]);
+ }
+ return value;
+ }
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 7721152..0a2f53a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -48,6 +48,13 @@
}
}
+// Function signatures used in the generation of runtime type information.
+typedef void FunctionTypeSignatureEmitter(Element method,
+ FunctionType methodType);
+// TODO(johnniwinther): Clean up terminology for rti in the emitter.
+typedef void FunctionTypeTestEmitter(FunctionType functionType);
+typedef void SubstitutionEmitter(Element element, {bool emitNull});
+
/**
* Generates the code for all used classes in the program. Static fields (even
* in classes) are ignored, since they can be treated as non-class elements.
@@ -75,6 +82,8 @@
final List<ClassElement> nativeClasses = <ClassElement>[];
final List<Selector> trivialNsmHandlers = <Selector>[];
final Map<String, String> mangledFieldNames = <String, String>{};
+ final Set<String> recordedMangledNames = new Set<String>();
+ final Set<String> interceptorInvocationNames = new Set<String>();
// TODO(ngeoffray): remove this field.
Set<ClassElement> instantiatedClasses;
@@ -110,11 +119,26 @@
Set<ClassElement> checkedClasses;
/**
- * Raw Typedef symbols occuring in is-checks and type assertions. If the
- * program contains `x is F<int>` and `x is F<bool>` then the TypedefElement
- * `F` will occur once in [checkedTypedefs].
+ * The set of function types that checked, both explicity through tests of
+ * typedefs and implicitly through type annotations in checked mode.
*/
- Set<TypedefElement> checkedTypedefs;
+ Set<FunctionType> checkedFunctionTypes;
+
+ Map<ClassElement, Set<FunctionType>> checkedGenericFunctionTypes =
+ new Map<ClassElement, Set<FunctionType>>();
+
+ Set<FunctionType> checkedNonGenericFunctionTypes =
+ new Set<FunctionType>();
+
+ void registerDynamicFunctionTypeCheck(FunctionType functionType) {
+ ClassElement classElement = Types.getClassContext(functionType);
+ if (classElement != null) {
+ checkedGenericFunctionTypes.putIfAbsent(classElement,
+ () => new Set<FunctionType>()).add(functionType);
+ } else {
+ checkedNonGenericFunctionTypes.add(functionType);
+ }
+ }
final bool generateSourceMap;
@@ -145,18 +169,20 @@
}
void computeRequiredTypeChecks() {
- assert(checkedClasses == null && checkedTypedefs == null);
+ assert(checkedClasses == null && checkedFunctionTypes == null);
backend.rti.addImplicitChecks(compiler.codegenWorld,
classesUsingTypeVariableTests);
checkedClasses = new Set<ClassElement>();
- checkedTypedefs = new Set<TypedefElement>();
+ checkedFunctionTypes = new Set<FunctionType>();
compiler.codegenWorld.isChecks.forEach((DartType t) {
- if (t is InterfaceType) {
- checkedClasses.add(t.element);
- } else if (t is TypedefType) {
- checkedTypedefs.add(t.element);
+ if (!t.isMalformed) {
+ if (t is InterfaceType) {
+ checkedClasses.add(t.element);
+ } else if (t is FunctionType) {
+ checkedFunctionTypes.add(t);
+ }
}
});
}
@@ -615,7 +641,7 @@
*/
js('var classData = desc[""], supr, name = cls, fields = classData'),
optional(
- compiler.mirrorsEnabled,
+ backend.hasRetainedMetadata,
js.if_('typeof classData == "object" && '
'classData instanceof Array',
[js('classData = fields = classData[0]')])),
@@ -649,7 +675,7 @@
])),
js('var constructor = defineClass(name, cls, fields, desc)'),
- optional(compiler.mirrorsEnabled,
+ optional(backend.hasRetainedMetadata,
js('constructor["${namer.metadataField}"] = desc')),
js('isolateProperties[cls] = constructor'),
js.if_('supr', js('pendingClasses[cls] = supr'))
@@ -958,6 +984,7 @@
count++;
parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
argumentsBuffer[0] = js(receiverArgumentName);
+ interceptorInvocationNames.add(invocationName);
}
int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
@@ -1015,6 +1042,11 @@
jsAst.Fun function = js.fun(parametersBuffer, body);
defineStub(invocationName, function);
+
+ String reflectionName = getReflectionName(selector, invocationName);
+ if (reflectionName != null) {
+ defineStub('+$reflectionName', js('0'));
+ }
}
void addParameterStubs(FunctionElement member,
@@ -1132,7 +1164,7 @@
bool instanceFieldNeedsGetter(Element member) {
assert(member.isField());
if (fieldAccessNeverThrows(member)) return false;
- return compiler.mirrorsEnabled
+ return backend.retainGetter(member)
|| compiler.codegenWorld.hasInvokedGetter(member, compiler);
}
@@ -1140,7 +1172,7 @@
assert(member.isField());
if (fieldAccessNeverThrows(member)) return false;
return (!member.modifiers.isFinalOrConst())
- && (compiler.mirrorsEnabled
+ && (backend.retainSetter(member)
|| compiler.codegenWorld.hasInvokedSetter(member, compiler));
}
@@ -1175,12 +1207,15 @@
jsAst.Expression code = backend.generatedCode[member];
if (code == null) return;
String name = namer.getName(member);
+ if (backend.isInterceptedMethod(member)) {
+ interceptorInvocationNames.add(name);
+ }
builder.addProperty(name, code);
var metadata = buildMetadataFunction(member);
if (metadata != null) {
builder.addProperty('@$name', metadata);
}
- String reflectionName = getReflectionName(member);
+ String reflectionName = getReflectionName(member, name);
if (reflectionName != null) {
builder.addProperty('+$reflectionName', js('0'));
}
@@ -1200,23 +1235,76 @@
emitExtraAccessors(member, builder);
}
- String getReflectionName(Element element) {
- if (!compiler.mirrorsEnabled) return null;
- String name = element.name.slowToString();
- if (element.isGetter()) return name;
- if (element.isSetter()) return '$name=';
- if (element.isFunction()) {
- FunctionElement function = element;
- int requiredParameterCount = function.requiredParameterCount(compiler);
- int optionalParameterCount = function.optionalParameterCount(compiler);
- String suffix = '$name:$requiredParameterCount:$optionalParameterCount';
- return (function.isConstructor()) ? 'new $suffix' : suffix;
+ String getReflectionName(elementOrSelector, String mangledName) {
+ if (!backend.retainName(elementOrSelector.name)) return null;
+ // TODO(ahe): Enable the next line when I can tell the difference between
+ // an instance method and a global. They may have the same mangled name.
+ // if (recordedMangledNames.contains(mangledName)) return null;
+ recordedMangledNames.add(mangledName);
+ return getReflectionNameInternal(elementOrSelector, mangledName);
+ }
+
+ String getReflectionNameInternal(elementOrSelector, String mangledName) {
+ String name = elementOrSelector.name.slowToString();
+ if (elementOrSelector.isGetter()) return name;
+ if (elementOrSelector.isSetter()) {
+ if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
+ String base = mangledName.substring(namer.setterPrefix.length);
+ String getter = '${namer.getterPrefix}$base';
+ mangledFieldNames[getter] = name;
+ recordedMangledNames.add(getter);
+ return null;
}
+ if (elementOrSelector is Selector
+ || elementOrSelector.isFunction()
+ || elementOrSelector.isConstructor()) {
+ int requiredParameterCount;
+ int optionalParameterCount;
+ String namedArguments = '';
+ bool isConstructor;
+ if (elementOrSelector is Selector) {
+ Selector selector = elementOrSelector;
+ requiredParameterCount = selector.argumentCount;
+ optionalParameterCount = 0;
+ isConstructor = false;
+ namedArguments = namedParametersAsReflectionNames(selector);
+ } else {
+ FunctionElement function = elementOrSelector;
+ requiredParameterCount = function.requiredParameterCount(compiler);
+ optionalParameterCount = function.optionalParameterCount(compiler);
+ isConstructor = function.isConstructor();
+ FunctionSignature signature = function.computeSignature(compiler);
+ if (signature.optionalParametersAreNamed) {
+ var names = [];
+ for (Element e in signature.optionalParameters) {
+ names.add(e.name);
+ }
+ Selector selector = new Selector.call(
+ function.name,
+ function.getLibrary(),
+ requiredParameterCount,
+ names);
+ namedArguments = namedParametersAsReflectionNames(selector);
+ }
+ }
+ String suffix =
+ '$name:$requiredParameterCount:$optionalParameterCount'
+ '$namedArguments';
+ return (isConstructor) ? 'new $suffix' : suffix;
+ }
+ Element element = elementOrSelector;
if (element.isGenerativeConstructorBody()) {
return null;
}
throw compiler.internalErrorOnElement(
- element, 'Do not know how to reflect on this');
+ element, 'Do not know how to reflect on this $element');
+ }
+
+ String namedParametersAsReflectionNames(Selector selector) {
+ if (selector.orderedNamedArguments.isEmpty) return '';
+ String names =
+ selector.orderedNamedArguments.map((x) => x.slowToString()).join(':');
+ return ':$names';
}
/**
@@ -1263,9 +1351,34 @@
builder.addProperty(namer.operatorIs(other), js('true'));
}
+ void generateIsFunctionTypeTest(FunctionType type) {
+ String operator = namer.operatorIsType(type);
+ builder.addProperty(operator, new jsAst.LiteralBool(true));
+ }
+
+ void generateFunctionTypeSignature(Element method, FunctionType type) {
+ assert(method.isImplementation);
+ String thisAccess = 'this';
+ Node node = method.parseNode(compiler);
+ ClosureClassMap closureData =
+ compiler.closureToClassMapper.closureMappingCache[node];
+ if (closureData != null) {
+ Element thisElement =
+ closureData.freeVariableMapping[closureData.thisElement];
+ if (thisElement != null) {
+ String thisName = backend.namer.getName(thisElement);
+ thisAccess = 'this.$thisName';
+ }
+ }
+ RuntimeTypes rti = backend.rti;
+ String encoding = rti.getSignatureEncoding(type, () => '$thisAccess');
+ String operatorSignature = namer.operatorSignature();
+ builder.addProperty(operatorSignature,
+ new jsAst.LiteralExpression(encoding));
+ }
+
void generateSubstitution(Element other, {bool emitNull: false}) {
RuntimeTypes rti = backend.rti;
- // TODO(karlklose): support typedefs with variables.
jsAst.Expression expression;
bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other);
if (other.kind == ElementKind.CLASS) {
@@ -1282,7 +1395,9 @@
}
}
- generateIsTestsOn(classElement, generateIsTest, generateSubstitution);
+ generateIsTestsOn(classElement, generateIsTest,
+ generateIsFunctionTypeTest, generateFunctionTypeSignature,
+ generateSubstitution);
}
void emitRuntimeTypeSupport(CodeBuffer buffer) {
@@ -1302,6 +1417,17 @@
}
};
}
+
+ void addSignature(FunctionType type) {
+ String encoding = rti.getTypeEncoding(type);
+ buffer.add('${namer.signatureName(type)}$_=${_}$encoding$N');
+ }
+
+ checkedNonGenericFunctionTypes.forEach(addSignature);
+
+ checkedGenericFunctionTypes.forEach((_, Set<FunctionType> functionTypes) {
+ functionTypes.forEach(addSignature);
+ });
}
/**
@@ -1433,12 +1559,14 @@
DartType type = member.computeType(compiler);
// TODO(ahe): Generate a dynamic type error here.
if (type.element.isErroneous()) return;
- FunctionElement helperElement
- = backend.getCheckedModeHelper(type, typeCast: false);
+ type = type.unalias(compiler);
+ CheckedModeHelper helper =
+ backend.getCheckedModeHelper(type, typeCast: false);
+ FunctionElement helperElement = helper.getElement(compiler);
String helperName = namer.isolateAccess(helperElement);
List<jsAst.Expression> arguments = <jsAst.Expression>[js('v')];
if (helperElement.computeSignature(compiler).parameterCount != 1) {
- arguments.add(js.string(namer.operatorIs(type.element)));
+ arguments.add(js.string(namer.operatorIsType(type)));
}
String setterName = namer.setterNameFromAccessorName(accessorName);
@@ -1467,16 +1595,12 @@
void recordMangledField(Element member,
String accessorName,
String memberName) {
+ if (!backend.retainGetter(member)) return;
String previousName = mangledFieldNames.putIfAbsent(
'${namer.getterPrefix}$accessorName',
() => memberName);
assert(invariant(member, previousName == memberName,
message: '$previousName != ${memberName}'));
- previousName = mangledFieldNames.putIfAbsent(
- '${namer.setterPrefix}$accessorName',
- () => '${memberName}=');
- assert(invariant(member, previousName == '${memberName}=',
- message: '$previousName != ${memberName}='));
}
/// Returns `true` if fields added.
@@ -1512,18 +1636,14 @@
if (!classIsNative || needsAccessor) {
buffer.write(separator);
separator = ',';
- if (compiler.mirrorsEnabled) {
- var metadata = buildMetadataFunction(member);
- if (metadata != null) {
- hasMetadata = true;
- } else {
- metadata = new jsAst.LiteralNull();
- }
- fieldMetadata.add(metadata);
+ var metadata = buildMetadataFunction(member);
+ if (metadata != null) {
+ hasMetadata = true;
+ } else {
+ metadata = new jsAst.LiteralNull();
}
- if (compiler.mirrorsEnabled) {
- recordMangledField(member, accessorName, member.name.slowToString());
- }
+ fieldMetadata.add(metadata);
+ recordMangledField(member, accessorName, member.name.slowToString());
if (!needsAccessor) {
// Emit field for constructor generation.
assert(!classIsNative);
@@ -1560,7 +1680,12 @@
assert(setterCode != 0);
}
int code = getterCode + (setterCode << 2);
- buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]);
+ if (code == 0) {
+ compiler.reportInternalError(
+ member, 'Internal error: code is 0 ($classElement/$member)');
+ } else {
+ buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]);
+ }
}
}
});
@@ -1649,6 +1774,9 @@
}
buffer.write('$className:$_');
buffer.write(jsAst.prettyPrint(builder.toObjectInitializer(), compiler));
+ if (backend.retainName(classElement.name)) {
+ buffer.write(',$n$n"+${classElement.name.slowToString()}": 0');
+ }
}
bool get getterAndSetterCanBeImplementedByFieldSpec => true;
@@ -1671,14 +1799,27 @@
return _selectorRank(selector1) - _selectorRank(selector2);
}
- Iterable<Element> getTypedefChecksOn(DartType type) {
- bool isSubtype(TypedefElement typedef) {
- FunctionType typedefType =
- typedef.computeType(compiler).unalias(compiler);
- return compiler.types.isSubtype(type, typedefType);
+ /**
+ * Returns a mapping containing all checked function types for which [type]
+ * can be a subtype. A function type is mapped to [:true:] if [type] is
+ * statically known to be a subtype of it and to [:false:] if [type] might
+ * be a subtype, provided with the right type arguments.
+ */
+ // TODO(johnniwinther): Change to return a mapping from function types to
+ // a set of variable points and use this to detect statically/dynamically
+ // known subtype relations.
+ Map<FunctionType, bool> getFunctionTypeChecksOn(DartType type) {
+ Map<FunctionType, bool> functionTypeMap =
+ new LinkedHashMap<FunctionType, bool>();
+ for (FunctionType functionType in checkedFunctionTypes) {
+ if (compiler.types.isSubtype(type, functionType)) {
+ functionTypeMap[functionType] = true;
+ } else if (compiler.types.isPotentialSubtype(type, functionType)) {
+ functionTypeMap[functionType] = false;
+ }
}
- return checkedTypedefs.where(isSubtype).toList()
- ..sort(Elements.compareByPosition);
+ // TODO(johnniwinther): Ensure stable ordering of the keys.
+ return functionTypeMap;
}
/**
@@ -1690,7 +1831,9 @@
*/
void generateIsTestsOn(ClassElement cls,
void emitIsTest(Element element),
- void emitSubstitution(Element element, {emitNull})) {
+ FunctionTypeTestEmitter emitIsFunctionTypeTest,
+ FunctionTypeSignatureEmitter emitFunctionTypeSignature,
+ SubstitutionEmitter emitSubstitution) {
if (checkedClasses.contains(cls)) {
emitIsTest(cls);
emitSubstitution(cls);
@@ -1713,7 +1856,7 @@
Set<ClassElement> emitted = new Set<ClassElement>();
// TODO(karlklose): move the computation of these checks to
// RuntimeTypeInformation.
- if (backend.needsRti(cls)) {
+ if (backend.classNeedsRti(cls)) {
emitSubstitution(superclass, emitNull: true);
emitted.add(superclass);
}
@@ -1741,7 +1884,7 @@
// A class that defines a [:call:] method implicitly implements
// [Function] and needs checks for all typedefs that are used in is-checks.
if (checkedClasses.contains(compiler.functionClass) ||
- !checkedTypedefs.isEmpty) {
+ !checkedFunctionTypes.isEmpty) {
Element call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME);
if (call == null) {
// If [cls] is a closure, it has a synthetic call operator method.
@@ -1752,8 +1895,12 @@
emitIsTest,
emitSubstitution,
generated);
- getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest);
- }
+ FunctionType callType = call.computeType(compiler);
+ Map<FunctionType, bool> functionTypeChecks =
+ getFunctionTypeChecksOn(callType);
+ generateFunctionTypeTests(call, callType, functionTypeChecks,
+ emitFunctionTypeSignature, emitIsFunctionTypeTest);
+ }
}
for (DartType interfaceType in cls.interfaces) {
@@ -1767,7 +1914,7 @@
*/
void generateInterfacesIsTests(ClassElement cls,
void emitIsTest(ClassElement element),
- void emitSubstitution(ClassElement element),
+ SubstitutionEmitter emitSubstitution,
Set<Element> alreadyGenerated) {
void tryEmitTest(ClassElement check) {
if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) {
@@ -1795,6 +1942,45 @@
}
}
+ static const int MAX_FUNCTION_TYPE_PREDICATES = 10;
+
+ /**
+ * Generates function type checks on [method] with type [methodType] against
+ * the function type checks in [functionTypeChecks].
+ */
+ void generateFunctionTypeTests(
+ Element method,
+ FunctionType methodType,
+ Map<FunctionType, bool> functionTypeChecks,
+ FunctionTypeSignatureEmitter emitFunctionTypeSignature,
+ FunctionTypeTestEmitter emitIsFunctionTypeTest) {
+ bool hasDynamicFunctionTypeCheck = false;
+ int neededPredicates = 0;
+ functionTypeChecks.forEach((FunctionType functionType, bool knownSubtype) {
+ if (!knownSubtype) {
+ registerDynamicFunctionTypeCheck(functionType);
+ hasDynamicFunctionTypeCheck = true;
+ } else {
+ neededPredicates++;
+ }
+ });
+ bool alwaysUseSignature = false;
+ if (hasDynamicFunctionTypeCheck ||
+ neededPredicates > MAX_FUNCTION_TYPE_PREDICATES) {
+ emitFunctionTypeSignature(method, methodType);
+ alwaysUseSignature = true;
+ }
+ functionTypeChecks.forEach((FunctionType functionType, bool knownSubtype) {
+ if (knownSubtype) {
+ if (alwaysUseSignature) {
+ registerDynamicFunctionTypeCheck(functionType);
+ } else {
+ emitIsFunctionTypeTest(functionType);
+ }
+ }
+ });
+ }
+
/**
* Return a function that returns true if its argument is a class
* that needs to be emitted.
@@ -1879,6 +2065,10 @@
buffer.write(',$n$n"@$name":$_');
buffer.write(jsAst.prettyPrint(metadata, compiler));
}
+ String reflectionName = getReflectionName(element, name);
+ if (reflectionName != null) {
+ buffer.write(',$n$n"+$reflectionName":${_}0');
+ }
jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
if (bailoutCode != null) {
pendingElementsWithBailouts.remove(element);
@@ -1953,12 +2143,6 @@
addParameterStubs(callElement, closureBuilder.addProperty);
- DartType type = element.computeType(compiler);
- getTypedefChecksOn(type).forEach((Element typedef) {
- String operator = namer.operatorIs(typedef);
- closureBuilder.addProperty(operator, js('true'));
- });
-
// TODO(ngeoffray): Cache common base classes for closures, bound
// closures, and static closures that have common type checks.
boundClosures.add(
@@ -1966,6 +2150,28 @@
closureBuilder.toObjectInitializer()));
staticGetters[element] = closureClassElement;
+
+ void emitFunctionTypeSignature(Element method, FunctionType methodType) {
+ RuntimeTypes rti = backend.rti;
+ // [:() => null:] is dummy encoding of [this] which is never needed for
+ // the encoding of the type of the static [method].
+ String encoding = rti.getSignatureEncoding(methodType, () => 'null');
+ String operatorSignature = namer.operatorSignature();
+ // TODO(johnniwinther): Make MiniJsParser support function expressions.
+ closureBuilder.addProperty(operatorSignature,
+ new jsAst.LiteralExpression(encoding));
+ }
+
+ void emitIsFunctionTypeTest(FunctionType functionType) {
+ String operator = namer.operatorIsType(functionType);
+ closureBuilder.addProperty(operator, js('true'));
+ }
+
+ FunctionType methodType = element.computeType(compiler);
+ Map<FunctionType, bool> functionTypeChecks =
+ getFunctionTypeChecksOn(methodType);
+ generateFunctionTypeTests(element, methodType, functionTypeChecks,
+ emitFunctionTypeSignature, emitIsFunctionTypeTest);
}
}
@@ -2023,12 +2229,14 @@
fieldNames.add(namer.getName(field));
});
- Iterable<Element> typedefChecks =
- getTypedefChecksOn(member.computeType(compiler));
- bool hasTypedefChecks = !typedefChecks.isEmpty;
+ DartType memberType = member.computeType(compiler);
+ Map<FunctionType, bool> functionTypeChecks =
+ getFunctionTypeChecksOn(memberType);
+ bool hasFunctionTypeChecks = !functionTypeChecks.isEmpty;
- bool canBeShared = !hasOptionalParameters && !hasTypedefChecks;
+ bool canBeShared = !hasOptionalParameters && !hasFunctionTypeChecks;
+ ClassElement classElement = member.getEnclosingClass();
String closureClass = canBeShared ? cache[parameterCount] : null;
if (closureClass == null) {
// Either the class was not cached yet, or there are optional parameters.
@@ -2084,10 +2292,23 @@
boundClosureBuilder.addProperty(invocationName, fun);
addParameterStubs(callElement, boundClosureBuilder.addProperty);
- typedefChecks.forEach((Element typedef) {
- String operator = namer.operatorIs(typedef);
- boundClosureBuilder.addProperty(operator, js('true'));
- });
+
+ void emitFunctionTypeSignature(Element method, FunctionType methodType) {
+ String encoding = backend.rti.getSignatureEncoding(
+ methodType, () => 'this.${fieldNames[0]}');
+ String operatorSignature = namer.operatorSignature();
+ boundClosureBuilder.addProperty(operatorSignature,
+ new jsAst.LiteralExpression(encoding));
+ }
+
+ void emitIsFunctionTypeTest(FunctionType functionType) {
+ String operator = namer.operatorIsType(functionType);
+ boundClosureBuilder.addProperty(operator,
+ new jsAst.LiteralBool(true));
+ }
+
+ generateFunctionTypeTests(member, memberType, functionTypeChecks,
+ emitFunctionTypeSignature, emitIsFunctionTypeTest);
boundClosures.add(
js('$classesCollector.$mangledName = #',
@@ -2119,8 +2340,7 @@
}
jsAst.Expression getterFunction = js.fun(
- parameters,
- js.return_(js(closureClass).newWith(arguments)));
+ parameters, js.return_(js(closureClass).newWith(arguments)));
defineStub(getterName, getterFunction);
}
@@ -2160,7 +2380,6 @@
// identical stubs for each we track untyped selectors which already have
// stubs.
Set<Selector> generatedSelectors = new Set<Selector>();
-
for (Selector selector in selectors) {
if (selector.applies(member, compiler)) {
selector = selector.asUntyped;
@@ -2404,6 +2623,10 @@
if (mask.willHit(selector, compiler)) continue;
String jsName = namer.invocationMirrorInternalName(selector);
addedJsNames[jsName] = selector;
+ String reflectionName = getReflectionName(selector, jsName);
+ if (reflectionName != null) {
+ mangledFieldNames[jsName] = reflectionName;
+ }
}
}
@@ -2761,6 +2984,15 @@
rti.getClassesUsedInSubstitutions(backend, requiredChecks);
addClassesWithSuperclasses(classesUsedInSubstitutions);
+ // 3c. Add classes that contain checked generic function types. These are
+ // needed to store the signature encoding.
+ for (FunctionType type in checkedFunctionTypes) {
+ ClassElement contextClass = Types.getClassContext(type);
+ if (contextClass != null) {
+ neededClasses.add(contextClass);
+ }
+ }
+
// 4. Finally, sort the classes.
List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses);
@@ -2977,18 +3209,21 @@
* method with an extra parameter.
*/
void emitInterceptedNames(CodeBuffer buffer) {
+ // TODO(ahe): We should not generate the list of intercepted names at
+ // compile time, it can be generated automatically at runtime given
+ // subclasses of Interceptor (which can easily be identified).
if (!compiler.enabledInvokeOn) return;
String name = backend.namer.getName(backend.interceptedNames);
int index = 0;
- List<jsAst.ArrayElement> elements = backend.usedInterceptors.map(
- (Selector selector) {
- jsAst.Literal str = js.string(namer.invocationName(selector));
+ var invocationNames = interceptorInvocationNames.toList()..sort();
+ List<jsAst.ArrayElement> elements = invocationNames.map(
+ (String invocationName) {
+ jsAst.Literal str = js.string(invocationName);
return new jsAst.ArrayElement(index++, str);
}).toList();
- jsAst.ArrayInitializer array = new jsAst.ArrayInitializer(
- backend.usedInterceptors.length,
- elements);
+ jsAst.ArrayInitializer array =
+ new jsAst.ArrayInitializer(invocationNames.length, elements);
jsAst.Expression assignment = js('$isolateProperties.$name = #', array);
@@ -3017,17 +3252,27 @@
/// annotated with itself. The metadata function is used by
/// mirrors_patch to implement DeclarationMirror.metadata.
jsAst.Fun buildMetadataFunction(Element element) {
- if (!compiler.mirrorsEnabled) return null;
- var metadata = [];
- Link link = element.metadata;
- // TODO(ahe): Why is metadata sometimes null?
- if (link != null) {
- for (; !link.isEmpty; link = link.tail) {
- metadata.add(constantReference(link.head.value));
+ if (!backend.retainMetadataOf(element)) return null;
+ return compiler.withCurrentElement(element, () {
+ var metadata = [];
+ Link link = element.metadata;
+ // TODO(ahe): Why is metadata sometimes null?
+ if (link != null) {
+ for (; !link.isEmpty; link = link.tail) {
+ MetadataAnnotation annotation = link.head;
+ Constant value = annotation.value;
+ if (value == null) {
+ compiler.reportInternalError(
+ annotation, 'Internal error: value is null');
+ } else {
+ metadata.add(constantReference(value));
+ }
+ }
}
- }
- if (metadata.isEmpty) return null;
- return js.fun([], [js.return_(new jsAst.ArrayInitializer.from(metadata))]);
+ if (metadata.isEmpty) return null;
+ return js.fun(
+ [], [js.return_(new jsAst.ArrayInitializer.from(metadata))]);
+ });
}
String assembleProgram() {
@@ -3174,13 +3419,16 @@
emitStaticFunctionGetters(mainBuffer);
emitRuntimeTypeSupport(mainBuffer);
+ emitGetInterceptorMethods(mainBuffer);
+ // Constants in checked mode call into RTI code to set type information
+ // which may need getInterceptor methods, so we have to make sure that
+ // [emitGetInterceptorMethods] has been called.
emitCompileTimeConstants(mainBuffer);
// Static field initializations require the classes and compile-time
// constants to be set up.
emitStaticNonFinalFieldInitializations(mainBuffer);
emitOneShotInterceptors(mainBuffer);
emitInterceptedNames(mainBuffer);
- emitGetInterceptorMethods(mainBuffer);
emitLazilyInitializedStaticFields(mainBuffer);
mainBuffer.add(nativeBuffer);
@@ -3333,8 +3581,12 @@
(function (reflectionData) {
if (!init.libraries) init.libraries = [];
if (!init.mangledNames) init.mangledNames = {};
+ if (!init.mangledGlobalNames) init.mangledGlobalNames = {};
+ init.getterPrefix = "${namer.getterPrefix}";
+ init.setterPrefix = "${namer.setterPrefix}";
var libraries = init.libraries;
var mangledNames = init.mangledNames;
+ var mangledGlobalNames = init.mangledGlobalNames;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var length = reflectionData.length;
for (var i = 0; i < length; i++) {
@@ -3348,18 +3600,23 @@
for (var property in descriptor) {
if (!hasOwnProperty.call(descriptor, property)) continue;
var element = descriptor[property];
- if (property.substring(0, 1) == "@") {
+ var firstChar = property.substring(0, 1);
+ var previousProperty;
+ if (firstChar == "+") {
+ mangledGlobalNames[previousProperty] = property.substring(1);
+ } else if (firstChar == "@") {
property = property.substring(1);
${namer.CURRENT_ISOLATE}[property]["${namer.metadataField}"] = element;
} else if (typeof element === "function") {
- ${namer.CURRENT_ISOLATE}[property] = element;
+ ${namer.CURRENT_ISOLATE}[previousProperty = property] = element;
functions.push(property);
} else {
+ previousProperty = property;
var newDesc = {};
var previousProp;
for (var prop in element) {
if (!hasOwnProperty.call(element, prop)) continue;
- var firstChar = prop.substring(0, 1);
+ firstChar = prop.substring(0, 1);
if (firstChar == "+") {
mangledNames[previousProp] = prop.substring(1);
} else if (firstChar == "@" && prop != "@") {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 77766eb..a15f5e0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -173,6 +173,7 @@
}
final String CURRENT_ISOLATE;
+ String get GLOBAL_OBJECT => CURRENT_ISOLATE;
final String getterPrefix = r'get$';
final String setterPrefix = r'set$';
@@ -766,6 +767,41 @@
String operatorAsPrefix() => r'$as';
+ String operatorSignature() => r'$signature';
+
+ String functionTypeTag() => r'func';
+
+ String functionTypeVoidReturnTag() => r'void';
+
+ String functionTypeReturnTypeTag() => r'ret';
+
+ String functionTypeRequiredParametersTag() => r'args';
+
+ String functionTypeOptionalParametersTag() => r'opt';
+
+ String functionTypeNamedParametersTag() => r'named';
+
+ Map<FunctionType,String> functionTypeNameMap =
+ new Map<FunctionType,String>();
+ FunctionTypeNamer functionTypeNamer = new FunctionTypeNamer();
+
+ String getFunctionTypeName(FunctionType functionType) {
+ return functionTypeNameMap.putIfAbsent(functionType, () {
+ String proposedName = functionTypeNamer.computeName(functionType);
+ String freshName = getFreshName(proposedName, usedInstanceNames,
+ suggestedInstanceNames, ensureSafe: true);
+ return freshName;
+ });
+ }
+
+ String operatorIsType(DartType type) {
+ if (type.kind == TypeKind.FUNCTION) {
+ // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
+ return '${operatorIsPrefix()}_${getFunctionTypeName(type)}';
+ }
+ return operatorIs(type.element);
+ }
+
String operatorIs(Element element) {
// TODO(erikcorry): Reduce from $isx to ix when we are minifying.
return '${operatorIsPrefix()}${getRuntimeTypeName(element)}';
@@ -787,6 +823,20 @@
return '${operatorAsPrefix()}${getName(element)}';
}
+ String signatureLocation(FunctionType type) {
+ ClassElement classElement = Types.getClassContext(type);
+ if (classElement != null) {
+ return '${isolateAccess(classElement)}';
+ } else {
+ return '${GLOBAL_OBJECT}';
+ }
+ }
+
+ String signatureName(FunctionType type) {
+ String signature = '${operatorSignature()}_${getFunctionTypeName(type)}';
+ return '${signatureLocation(type)}.$signature';
+ }
+
String safeName(String name) => _safeName(name, jsReserved);
String safeVariableName(String name) => _safeName(name, jsVariableReserved);
@@ -841,7 +891,6 @@
}
}
-
/**
* Generator of names for [Constant] values.
*
@@ -1015,7 +1064,6 @@
}
}
-
/**
* Generates canonical hash values for [Constant]s.
*
@@ -1161,3 +1209,56 @@
return _MASK & (hash + (((_MASK >> 15) & hash) << 15));
}
}
+
+class FunctionTypeNamer extends DartTypeVisitor {
+ StringBuffer sb;
+
+ String computeName(DartType type) {
+ sb = new StringBuffer();
+ visit(type);
+ return sb.toString();
+ }
+
+ visit(DartType type) {
+ type.accept(this, null);
+ }
+
+ visitType(DartType type, _) {
+ sb.write(type.name.slowToString());
+ }
+
+ visitFunctionType(FunctionType type, _) {
+ visit(type.returnType);
+ sb.write('_');
+ for (Link<DartType> link = type.parameterTypes;
+ !link.isEmpty;
+ link = link.tail) {
+ sb.write('_');
+ visit(link.head);
+ }
+ bool first = false;
+ for (Link<DartType> link = type.optionalParameterTypes;
+ !link.isEmpty;
+ link = link.tail) {
+ if (!first) {
+ sb.write('_');
+ }
+ sb.write('_');
+ visit(link.head);
+ first = true;
+ }
+ if (!type.namedParameterTypes.isEmpty) {
+ first = false;
+ for (Link<DartType> link = type.namedParameterTypes;
+ !link.isEmpty;
+ link = link.tail) {
+ if (!first) {
+ sb.write('_');
+ }
+ sb.write('_');
+ visit(link.head);
+ first = true;
+ }
+ }
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index c162f55..76b9efc 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -20,6 +20,7 @@
final Map<ClassElement, Set<ClassElement>> rtiDependencies;
final Set<ClassElement> classesNeedingRti;
+ final Set<Element> methodsNeedingRti;
// The set of classes that use one of their type variables as expressions
// to get the runtime type.
final Set<ClassElement> classesUsingTypeVariableExpression;
@@ -30,6 +31,7 @@
: this.compiler = compiler,
representationGenerator = new TypeRepresentationGenerator(compiler),
classesNeedingRti = new Set<ClassElement>(),
+ methodsNeedingRti = new Set<Element>(),
rtiDependencies = new Map<ClassElement, Set<ClassElement>>(),
classesUsingTypeVariableExpression = new Set<ClassElement>();
@@ -77,7 +79,7 @@
InterfaceType interface = type;
do {
for (DartType argument in interface.typeArguments) {
- universe.isChecks.add(argument);
+ universe.registerIsCheck(argument, compiler);
}
interface = interface.element.supertype;
} while (interface != null && !instantiatedTypes.contains(interface));
@@ -100,7 +102,7 @@
InterfaceType instance = current.asInstanceOf(cls);
if (instance == null) break;
for (DartType argument in instance.typeArguments) {
- universe.isChecks.add(argument);
+ universe.registerIsCheck(argument, compiler);
}
current = current.element.supertype;
} while (current != null && !instantiatedTypes.contains(current));
@@ -155,18 +157,50 @@
if (backend.jsArrayClass != null) {
registerRtiDependency(backend.jsArrayClass, compiler.listClass);
}
- // Compute the set of all classes that need runtime type information.
+ // Compute the set of all classes and methods that need runtime type
+ // information.
compiler.resolverWorld.isChecks.forEach((DartType type) {
if (type.kind == TypeKind.INTERFACE) {
InterfaceType itf = type;
if (!itf.isRaw) {
potentiallyAddForRti(itf.element);
}
- } else if (type.kind == TypeKind.TYPE_VARIABLE) {
- TypeVariableElement variable = type.element;
- potentiallyAddForRti(variable.enclosingElement);
+ } else {
+ ClassElement contextClass = Types.getClassContext(type);
+ if (contextClass != null) {
+ // [type] contains type variables (declared in [contextClass]) if
+ // [contextClass] is non-null. This handles checks against type
+ // variables and function types containing type variables.
+ potentiallyAddForRti(contextClass);
+ }
+ if (type.kind == TypeKind.FUNCTION) {
+ void analyzeMethod(Element method) {
+ DartType memberType = method.computeType(compiler);
+ ClassElement contextClass = Types.getClassContext(memberType);
+ if (contextClass != null &&
+ compiler.types.isPotentialSubtype(memberType, type)) {
+ potentiallyAddForRti(contextClass);
+ methodsNeedingRti.add(method);
+ }
+ }
+ compiler.resolverWorld.closurizedGenericMembers.forEach(
+ analyzeMethod);
+ compiler.resolverWorld.genericCallMethods.forEach(analyzeMethod);
+ }
}
});
+ if (compiler.enableTypeAssertions) {
+ void analyzeMethod(Element method) {
+ DartType memberType = method.computeType(compiler);
+ ClassElement contextClass = Types.getClassContext(memberType);
+ if (contextClass != null) {
+ potentiallyAddForRti(contextClass);
+ methodsNeedingRti.add(method);
+ }
+ }
+ compiler.resolverWorld.closurizedGenericMembers.forEach(analyzeMethod);
+ compiler.resolverWorld.genericCallMethods.forEach(analyzeMethod);
+ }
// Add the classes that need RTI because they use a type variable as
// expression.
classesUsingTypeVariableExpression.forEach(potentiallyAddForRti);
@@ -210,12 +244,43 @@
}
void computeRequiredChecks() {
- computeInstantiatedArguments(compiler.codegenWorld);
- computeCheckedArguments(compiler.codegenWorld);
+ Set<DartType> isChecks = compiler.codegenWorld.isChecks;
+ bool hasFunctionTypeCheck =
+ isChecks.any((type) => identical(type.kind, TypeKind.FUNCTION));
+ Set<DartType> instantiatedTypesAndClosures = hasFunctionTypeCheck
+ ? computeInstantiatedTypesAndClosures(compiler.codegenWorld)
+ : compiler.codegenWorld.instantiatedTypes;
+ computeInstantiatedArguments(instantiatedTypesAndClosures, isChecks);
+ computeCheckedArguments(instantiatedTypesAndClosures, isChecks);
cachedRequiredChecks =
computeChecks(allInstantiatedArguments, checkedArguments);
}
+ Set<DartType> computeInstantiatedTypesAndClosures(Universe universe) {
+ Set<DartType> instantiatedTypes =
+ new Set<DartType>.from(universe.instantiatedTypes);
+ for (DartType instantiatedType in universe.instantiatedTypes) {
+ if (instantiatedType.kind == TypeKind.INTERFACE) {
+ Member member =
+ instantiatedType.lookupMember(Compiler.CALL_OPERATOR_NAME);
+ if (member != null) {
+ instantiatedTypes.add(member.computeType(compiler));
+ }
+ }
+ }
+ for (FunctionElement element in universe.staticFunctionsNeedingGetter) {
+ instantiatedTypes.add(element.computeType(compiler));
+ }
+ // TODO(johnniwinther): We should get this information through the
+ // [neededClasses] computed in the emitter instead of storing it and pulling
+ // it from resolution, but currently it would introduce a cyclic dependency
+ // between [computeRequiredChecks] and [computeNeededClasses].
+ for (Element element in compiler.resolverWorld.closurizedMembers) {
+ instantiatedTypes.add(element.computeType(compiler));
+ }
+ return instantiatedTypes;
+ }
+
/**
* Collects all types used in type arguments of instantiated types.
*
@@ -223,14 +288,26 @@
* have a type check against this supertype that includes a check against
* the type arguments.
*/
- void computeInstantiatedArguments(Universe universe) {
+ void computeInstantiatedArguments(Set<DartType> instantiatedTypes,
+ Set<DartType> isChecks) {
ArgumentCollector superCollector = new ArgumentCollector(backend);
ArgumentCollector directCollector = new ArgumentCollector(backend);
- for (DartType type in universe.instantiatedTypes) {
+ FunctionArgumentCollector functionArgumentCollector =
+ new FunctionArgumentCollector(backend);
+
+ // We need to add classes occuring in function type arguments, like for
+ // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :].
+ for (DartType type in isChecks) {
+ functionArgumentCollector.collect(type);
+ }
+
+ for (DartType type in instantiatedTypes) {
directCollector.collect(type);
- ClassElement cls = type.element;
- for (DartType supertype in cls.allSupertypes) {
- superCollector.collect(supertype);
+ if (type.kind == TypeKind.INTERFACE) {
+ ClassElement cls = type.element;
+ for (DartType supertype in cls.allSupertypes) {
+ superCollector.collect(supertype);
+ }
}
}
for (ClassElement cls in superCollector.classes.toList()) {
@@ -238,18 +315,33 @@
superCollector.collect(supertype);
}
}
- directlyInstantiatedArguments = directCollector.classes;
+
+ directlyInstantiatedArguments =
+ directCollector.classes..addAll(functionArgumentCollector.classes);
allInstantiatedArguments =
superCollector.classes..addAll(directlyInstantiatedArguments);
}
/// Collects all type arguments used in is-checks.
- void computeCheckedArguments(Universe universe) {
+ void computeCheckedArguments(Set<DartType> instantiatedTypes,
+ Set<DartType> isChecks) {
ArgumentCollector collector = new ArgumentCollector(backend);
- for (DartType type in universe.isChecks) {
+ FunctionArgumentCollector functionArgumentCollector =
+ new FunctionArgumentCollector(backend);
+
+ // We need to add types occuring in function type arguments, like for
+ // instance 'J' for [: (J j) {} is f :] where f is
+ // [: typedef void f(I i); :] and 'J' is a subtype of 'I'.
+ for (DartType type in instantiatedTypes) {
+ functionArgumentCollector.collect(type);
+ }
+
+ for (DartType type in isChecks) {
collector.collect(type);
}
- checkedArguments = collector.classes;
+
+ checkedArguments =
+ collector.classes..addAll(functionArgumentCollector.classes);
}
Set<ClassElement> getClassesUsedInSubstitutions(JavaScriptBackend backend,
@@ -392,7 +484,42 @@
return '[$code]';
}
- String getTypeRepresentation(DartType type, void onVariable(variable)) {
+ String getTypeEncoding(DartType type,
+ {bool alwaysGenerateFunction: false}) {
+ ClassElement contextClass = Types.getClassContext(type);
+ String onVariable(TypeVariableType v) {
+ return v.toString();
+ };
+ String encoding = _getTypeRepresentation(type, onVariable);
+ if (contextClass == null && !alwaysGenerateFunction) {
+ return encoding;
+ } else {
+ String parameters = contextClass != null
+ ? contextClass.typeVariables.toList().join(', ')
+ : '';
+ return 'function ($parameters) { return $encoding; }';
+ }
+ }
+
+ String getSignatureEncoding(DartType type, String generateThis()) {
+ ClassElement contextClass = Types.getClassContext(type);
+ String encoding = getTypeEncoding(type, alwaysGenerateFunction: true);
+ if (contextClass != null) {
+ String this_ = generateThis();
+ JavaScriptBackend backend = compiler.backend;
+ String computeSignature =
+ backend.namer.getName(backend.getComputeSignature());
+ String contextName = backend.namer.getName(contextClass);
+ return 'function () {'
+ ' return ${backend.namer.GLOBAL_OBJECT}.'
+ '$computeSignature($encoding, $this_, "$contextName"); '
+ '}';
+ } else {
+ return encoding;
+ }
+ }
+
+ String getTypeRepresentation(DartType type, VariableSubstitution onVariable) {
// Create a type representation. For type variables call the original
// callback for side effects and return a template placeholder.
return _getTypeRepresentation(type, (variable) {
@@ -432,6 +559,9 @@
OnVariableCallback onVariable;
StringBuffer builder;
+ JavaScriptBackend get backend => compiler.backend;
+ Namer get namer => backend.namer;
+
TypeRepresentationGenerator(Compiler this.compiler);
/**
@@ -449,8 +579,6 @@
}
String getJsName(Element element) {
- JavaScriptBackend backend = compiler.backend;
- Namer namer = backend.namer;
return namer.isolateAccess(backend.getImplementationClass(element));
}
@@ -491,25 +619,26 @@
}
visitFunctionType(FunctionType type, _) {
- builder.write('{func: true');
+ builder.write('{${namer.functionTypeTag()}:'
+ ' "${namer.getFunctionTypeName(type)}"');
if (type.returnType.isVoid) {
- builder.write(', retvoid: true');
+ builder.write(', ${namer.functionTypeVoidReturnTag()}: true');
} else if (!type.returnType.isDynamic) {
- builder.write(', ret: ');
+ builder.write(', ${namer.functionTypeReturnTypeTag()}: ');
visit(type.returnType);
}
if (!type.parameterTypes.isEmpty) {
- builder.write(', args: [');
+ builder.write(', ${namer.functionTypeRequiredParametersTag()}: [');
visitList(type.parameterTypes);
builder.write(']');
}
if (!type.optionalParameterTypes.isEmpty) {
- builder.write(', opt: [');
+ builder.write(', ${namer.functionTypeOptionalParametersTag()}: [');
visitList(type.optionalParameterTypes);
builder.write(']');
}
if (!type.namedParameterTypes.isEmpty) {
- builder.write(', named: {');
+ builder.write(', ${namer.functionTypeNamedParametersTag()}: {');
bool first = true;
Link<SourceString> names = type.namedParameters;
Link<DartType> types = type.namedParameterTypes;
@@ -529,8 +658,13 @@
builder.write('}');
}
+ visitMalformedType(MalformedType type, _) {
+ // Treat malformed types as dynamic at runtime.
+ builder.write('null');
+ }
+
visitType(DartType type, _) {
- compiler.internalError('Unexpected type: $type');
+ compiler.internalError('Unexpected type: $type (${type.kind})');
}
}
@@ -589,6 +723,10 @@
// Do not collect [:dynamic:].
}
+ visitTypedefType(TypedefType type, bool isTypeArgument) {
+ type.unalias(backend.compiler).accept(this, isTypeArgument);
+ }
+
visitInterfaceType(InterfaceType type, bool isTypeArgument) {
if (isTypeArgument) {
classes.add(backend.getImplementationClass(type.element));
@@ -601,6 +739,48 @@
}
}
+class FunctionArgumentCollector extends DartTypeVisitor {
+ final JavaScriptBackend backend;
+ final Set<ClassElement> classes = new Set<ClassElement>();
+
+ FunctionArgumentCollector(this.backend);
+
+ collect(DartType type) {
+ type.accept(this, false);
+ }
+
+ /// Collect all types in the list as if they were arguments of an
+ /// InterfaceType.
+ collectAll(Link<DartType> types) {
+ for (Link<DartType> link = types; !link.isEmpty; link = link.tail) {
+ link.head.accept(this, true);
+ }
+ }
+
+ visitType(DartType type, _) {
+ // Do nothing.
+ }
+
+ visitDynamicType(DynamicType type, _) {
+ // Do not collect [:dynamic:].
+ }
+
+ visitTypedefType(TypedefType type, bool inFunctionType) {
+ type.unalias(backend.compiler).accept(this, inFunctionType);
+ }
+
+ visitInterfaceType(InterfaceType type, bool inFunctionType) {
+ if (inFunctionType) {
+ classes.add(backend.getImplementationClass(type.element));
+ }
+ type.visitChildren(this, inFunctionType);
+ }
+
+ visitFunctionType(FunctionType type, _) {
+ type.visitChildren(this, true);
+ }
+}
+
/**
* Representation of the substitution of type arguments
* when going from the type of a class to one of its supertypes.
@@ -632,7 +812,7 @@
String formals = parameters.toList().map(variableName).join(', ');
return 'function ($formals) { return $code; }';
} else if (ensureIsFunction) {
- return 'function() { return $code; }';
+ return 'function () { return $code; }';
} else {
return code;
}
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index df00f77..c6f20a0 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -25,9 +25,6 @@
/// The type Object, but no subtypes:
static const JsObject = const SpecialType._('=Object');
-
- /// The specific implementation of List that is JavaScript Array:
- static const JsArray = const SpecialType._('=List');
}
@@ -331,9 +328,7 @@
if (matchedTypeConstraints.contains(type)) continue;
matchedTypeConstraints.add(type);
if (type is SpecialType) {
- if (type == SpecialType.JsArray) {
- world.registerInstantiatedClass(compiler.listClass, elements);
- } else if (type == SpecialType.JsObject) {
+ if (type == SpecialType.JsObject) {
world.registerInstantiatedClass(compiler.objectClass, elements);
}
continue;
@@ -352,6 +347,9 @@
world.registerInstantiatedClass(compiler.nullClass, elements);
} else if (type.element == compiler.boolClass) {
world.registerInstantiatedClass(compiler.boolClass, elements);
+ } else if (compiler.types.isSubtype(
+ type, compiler.backend.listImplementation.rawType)) {
+ world.registerInstantiatedClass(type.element, elements);
}
}
assert(type is DartType);
@@ -634,7 +632,6 @@
//
// 'Type1|Type2'. A union type.
// '=Object'. A JavaScript Object, no subtype.
- // '=List'. A JavaScript Array, no subtype.
var argNodes = jsCall.arguments;
if (argNodes.isEmpty) {
@@ -816,7 +813,6 @@
static _parseType(String typeString, Compiler compiler,
lookup(name), locationNodeOrElement) {
if (typeString == '=Object') return SpecialType.JsObject;
- if (typeString == '=List') return SpecialType.JsArray;
if (typeString == 'dynamic') {
return compiler.dynamicClass.computeType(compiler);
}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 95f6edf..4f619ce 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1901,6 +1901,12 @@
}
parameterNodes = parameterNodes.tail;
});
+ if (inCheckContext) {
+ functionParameters.forEachParameter((Element element) {
+ compiler.enqueuer.resolution.registerIsCheck(
+ element.computeType(compiler), mapping);
+ });
+ }
}
visitCascade(Cascade node) {
@@ -1998,6 +2004,7 @@
scope = oldScope;
enclosingElement = previousEnclosingElement;
+ world.registerClosurizedMember(function, mapping);
world.registerInstantiatedClass(compiler.functionClass, mapping);
}
@@ -2076,7 +2083,7 @@
// We still need to register the invocation, because we might
// call [:super.noSuchMethod:] which calls
// [JSInvocationMirror._invokeOn].
- world.registerDynamicInvocation(selector.name, selector);
+ world.registerDynamicInvocation(selector);
compiler.backend.registerSuperNoSuchMethod(mapping);
}
} else if (Elements.isUnresolved(resolvedReceiver)) {
@@ -2104,7 +2111,7 @@
// [resolveSend] to select better warning messages for getters and
// setters.
MessageKind kind = (target == null)
- ? MessageKind.METHOD_NOT_FOUND
+ ? MessageKind.MEMBER_NOT_FOUND
: MessageKind.MEMBER_NOT_STATIC;
return warnAndCreateErroneousElement(node, name, kind,
{'className': receiverClass.name,
@@ -2250,6 +2257,10 @@
assert(enclosingElement.getEnclosingClass() == cls);
compiler.backend.registerClassUsingVariableExpression(cls);
compiler.backend.registerTypeVariableExpression(mapping);
+ // Set the type of the node to [Type] to mark this send as a
+ // type variable expression.
+ mapping.setType(node, compiler.typeClass.computeType(compiler));
+ world.registerInstantiatedClass(compiler.typeClass, mapping);
} else if (target.impliesType() && !sendIsMemberAccess) {
// Set the type of the node to [Type] to mark this send as a
// type literal.
@@ -2262,7 +2273,8 @@
if (node.isOperator) {
String operatorString = node.selector.asOperator().source.stringValue;
if (operatorString == 'is') {
- DartType type = resolveTypeRequired(node.typeAnnotationFromIsCheck);
+ DartType type =
+ resolveTypeRequired(node.typeAnnotationFromIsCheckOrCast);
if (type != null) {
compiler.enqueuer.resolution.registerIsCheck(type, mapping);
}
@@ -2302,7 +2314,7 @@
// we need to register that fact that we may be calling a closure
// with the same arguments.
Selector call = new Selector.callClosureFrom(selector);
- world.registerDynamicInvocation(call.name, call);
+ world.registerDynamicInvocation(call);
} else if (target.impliesType()) {
// We call 'call()' on a Type instance returned from the reference to a
// class or typedef literal. We do not need to register this call as a
@@ -2412,7 +2424,7 @@
// the ++ and -- ones. Also, if op= form is used, include op itself.
void registerBinaryOperator(SourceString name) {
Selector binop = new Selector.binaryOperator(name);
- world.registerDynamicInvocation(binop.name, binop);
+ world.registerDynamicInvocation(binop);
mapping.setOperatorSelectorInComplexSendSet(node, binop);
}
if (identical(source, '++')) {
@@ -2431,11 +2443,11 @@
void registerSend(Selector selector, Element target) {
if (target == null || target.isInstanceMember()) {
if (selector.isGetter()) {
- world.registerDynamicGetter(selector.name, selector);
+ world.registerDynamicGetter(selector);
} else if (selector.isSetter()) {
- world.registerDynamicSetter(selector.name, selector);
+ world.registerDynamicSetter(selector);
} else {
- world.registerDynamicInvocation(selector.name, selector);
+ world.registerDynamicInvocation(selector);
}
} else if (Elements.isStaticOrTopLevel(target)) {
// TODO(kasperl): It seems like we're not supposed to register
@@ -2615,6 +2627,10 @@
world.registerStaticUse(constructor.declaration);
ClassElement cls = constructor.getEnclosingClass();
InterfaceType type = mapping.getType(node);
+ if (node.isConst() && type.containsTypeVariables) {
+ compiler.reportErrorCode(node.send.selector,
+ MessageKind.TYPE_VARIABLE_IN_CONSTANT);
+ }
world.registerInstantiatedType(type, mapping);
if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) {
world.registerFactoryWithTypeArguments(mapping);
@@ -2723,6 +2739,10 @@
}
DartType listType;
if (typeArgument != null) {
+ if (node.isConst() && typeArgument.containsTypeVariables) {
+ compiler.reportErrorCode(arguments.nodes.head,
+ MessageKind.TYPE_VARIABLE_IN_CONSTANT);
+ }
listType = new InterfaceType(compiler.listClass,
new Link<DartType>.fromList([typeArgument]));
} else {
@@ -2810,20 +2830,17 @@
registerImplicitInvocation(SourceString name, int arity) {
Selector selector = new Selector.call(name, null, arity);
- world.registerDynamicInvocation(name, selector);
+ world.registerDynamicInvocation(selector);
}
visitForIn(ForIn node) {
LibraryElement library = enclosingElement.getLibrary();
mapping.setIteratorSelector(node, compiler.iteratorSelector);
- world.registerDynamicGetter(compiler.iteratorSelector.name,
- compiler.iteratorSelector);
+ world.registerDynamicGetter(compiler.iteratorSelector);
mapping.setCurrentSelector(node, compiler.currentSelector);
- world.registerDynamicGetter(compiler.currentSelector.name,
- compiler.currentSelector);
+ world.registerDynamicGetter(compiler.currentSelector);
mapping.setMoveNextSelector(node, compiler.moveNextSelector);
- world.registerDynamicInvocation(compiler.moveNextSelector.name,
- compiler.moveNextSelector);
+ world.registerDynamicInvocation(compiler.moveNextSelector);
visit(node.expression);
Scope blockScope = new BlockScope(scope);
@@ -2938,6 +2955,10 @@
compiler.mapClass.computeType(compiler);
mapType = compiler.mapClass.rawType;
}
+ if (node.isConst() && mapType.containsTypeVariables) {
+ compiler.reportErrorCode(arguments,
+ MessageKind.TYPE_VARIABLE_IN_CONSTANT);
+ }
mapping.setType(node, mapType);
world.registerInstantiatedClass(compiler.mapClass, mapping);
if (node.isConst()) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 75d6443..3b3c999 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -53,7 +53,6 @@
assert(graph.isValid());
if (!identical(kind, ElementKind.FIELD)) {
FunctionElement function = element;
- graph.calledInLoop = compiler.world.isCalledInLoop(function);
FunctionSignature signature = function.computeSignature(compiler);
signature.forEachOptionalParameter((Element parameter) {
// This ensures the default value will be computed.
@@ -932,10 +931,14 @@
static const MAX_INLINING_DEPTH = 3;
static const MAX_INLINING_NODES = 46;
+
List<InliningState> inliningStack;
+
Element returnElement;
DartType returnType;
+
bool inTryStatement = false;
+ int loopNesting = 0;
HBasicBlock get current => _current;
void set current(c) {
@@ -1002,6 +1005,7 @@
*/
HGraph buildMethod(FunctionElement functionElement) {
assert(invariant(functionElement, functionElement.isImplementation));
+ graph.calledInLoop = compiler.world.isCalledInLoop(functionElement);
FunctionExpression function = functionElement.parseNode(compiler);
assert(function != null);
assert(!function.modifiers.isExternal());
@@ -1171,7 +1175,7 @@
ClassElement enclosing = function.getEnclosingClass();
if ((function.isConstructor() || function.isGenerativeConstructorBody())
- && backend.needsRti(enclosing)) {
+ && backend.classNeedsRti(enclosing)) {
enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
HInstruction argument = compiledArguments[argumentIndex++];
newLocalsHandler.updateLocal(typeVariable.element, argument);
@@ -1222,7 +1226,10 @@
// connected-component of the deferred library.
if (compiler.deferredLoadTask.isDeferred(element)) return false;
if (compiler.disableInlining) return false;
- if (inliningStack.length > MAX_INLINING_DEPTH) return false;
+
+ if (loopNesting == 0 && !graph.calledInLoop) return false;
+ int maxDepth = (loopNesting > 0) ? MAX_INLINING_DEPTH : 1;
+ if (inliningStack.length >= maxDepth) return false;
// Ensure that [element] is an implementation element.
element = element.implementation;
@@ -1242,6 +1249,15 @@
}
}
+ // Don't inline if the return type was inferred to be non-null empty. This
+ // means that the function always throws an exception.
+ TypeMask returnType =
+ compiler.typesTask.getGuaranteedReturnTypeOfElement(element);
+ if (returnType != null && returnType.isEmpty && !returnType.isNullable) {
+ isReachable = false;
+ return false;
+ }
+
FunctionExpression functionExpression = function.parseNode(compiler);
TreeElements newElements =
compiler.enqueuer.resolution.getCachedElements(function);
@@ -1327,7 +1343,7 @@
}
ClassElement superclass = constructor.getEnclosingClass();
- if (backend.needsRti(superclass)) {
+ if (backend.classNeedsRti(superclass)) {
// If [superclass] needs RTI, we have to give a value to its
// type parameters. Those values are in the [supertype]
// declaration of [subclass].
@@ -1574,7 +1590,7 @@
add(newObject);
// Create the runtime type information, if needed.
- if (backend.needsRti(classElement)) {
+ if (backend.classNeedsRti(classElement)) {
List<HInstruction> rtiInputs = <HInstruction>[];
classElement.typeVariables.forEach((TypeVariableType typeVariable) {
rtiInputs.add(localsHandler.readLocal(typeVariable.element));
@@ -1620,7 +1636,7 @@
});
ClassElement currentClass = constructor.getEnclosingClass();
- if (backend.needsRti(currentClass)) {
+ if (backend.classNeedsRti(currentClass)) {
// If [currentClass] needs RTI, we add the type variables as
// parameters of the generative constructor body.
currentClass.typeVariables.forEach((DartType argument) {
@@ -1724,7 +1740,7 @@
// may contain references to type variables.
var enclosing = element.enclosingElement;
if ((element.isConstructor() || element.isGenerativeConstructorBody())
- && backend.needsRti(enclosing)) {
+ && backend.classNeedsRti(enclosing)) {
enclosing.typeVariables.forEach((TypeVariableType typeVariable) {
HParameterValue param = addParameter(typeVariable.element);
localsHandler.directLocals[typeVariable.element] = param;
@@ -1773,6 +1789,7 @@
DartType type,
int kind) {
if (type == null) return original;
+ type = type.unalias(compiler);
if (type.kind == TypeKind.INTERFACE && !type.isMalformed && !type.isRaw) {
HType subtype = new HType.subtype(type, compiler);
HInstruction representations = buildTypeArgumentRepresentations(type);
@@ -1784,6 +1801,24 @@
HInstruction typeVariable = addTypeVariableReference(type);
return new HTypeConversion.withTypeRepresentation(type, kind, subtype,
original, typeVariable);
+ } else if (type.kind == TypeKind.FUNCTION) {
+ HType subtype = original.instructionType;
+ if (type.containsTypeVariables) {
+ bool contextIsTypeArguments = false;
+ HInstruction context;
+ if (currentElement.isInstanceMember()) {
+ context = localsHandler.readThis();
+ } else {
+ ClassElement contextClass = Types.getClassContext(type);
+ context = buildTypeVariableList(contextClass);
+ add(context);
+ contextIsTypeArguments = true;
+ }
+ return new HTypeConversion.withContext(type, kind, subtype,
+ original, context, contextIsTypeArguments: contextIsTypeArguments);
+ } else {
+ return new HTypeConversion(type, kind, subtype, original);
+ }
} else {
return original.convertType(compiler, type, kind);
}
@@ -1794,6 +1829,7 @@
if (!compiler.enableTypeAssertions) return original;
HInstruction other = buildTypeConversion(original, type, kind);
if (other != original) add(other);
+ compiler.enqueuer.codegen.registerIsCheck(type, work.resolutionTree);
return other;
}
@@ -2070,6 +2106,7 @@
new SubExpression(initializerBlock, current);
}
+ loopNesting++;
JumpHandler jumpHandler = beginLoopHeader(loop);
HLoopInformation loopInfo = current.loopInformation;
HBasicBlock conditionBlock = current;
@@ -2229,6 +2266,7 @@
}
}
jumpHandler.close();
+ loopNesting--;
}
visitFor(For node) {
@@ -2283,6 +2321,7 @@
assert(isReachable);
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
localsHandler.startLoop(node);
+ loopNesting++;
JumpHandler jumpHandler = beginLoopHeader(node);
HLoopInformation loopInfo = current.loopInformation;
HBasicBlock loopEntryBlock = current;
@@ -2408,6 +2447,7 @@
}
}
jumpHandler.close();
+ loopNesting--;
}
visitFunctionExpression(FunctionExpression node) {
@@ -2439,6 +2479,12 @@
compiler.functionClass.computeType(compiler),
compiler);
push(new HForeignNew(closureClassElement, type, capturedVariables));
+
+ Element methodElement = nestedClosureData.closureElement;
+ if (compiler.backend.methodNeedsRti(methodElement)) {
+ compiler.backend.registerGenericClosure(
+ methodElement, compiler.enqueuer.codegen, work.resolutionTree);
+ }
}
visitFunctionDeclaration(FunctionDeclaration node) {
@@ -2548,7 +2594,7 @@
String getTargetName(ErroneousElement error, [String prefix]) {
String result = error.name.slowToString();
- if (?prefix) {
+ if (prefix != null) {
result = '$prefix $result';
}
return result;
@@ -2722,7 +2768,7 @@
}
}
- visitOperatorSend(node) {
+ visitOperatorSend(Send node) {
Operator op = node.selector;
if (const SourceString("[]") == op.source) {
visitDynamicSend(node);
@@ -2758,7 +2804,8 @@
visit(node.receiver);
HInstruction expression = pop();
bool isNot = node.isIsNotCheck;
- DartType type = elements.getType(node.typeAnnotationFromIsCheck);
+ DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
+ type = type.unalias(compiler);
if (type.isMalformed) {
String reasons = Types.fetchReasonsFromMalformedType(type);
if (compiler.enableTypeAssertions) {
@@ -2776,8 +2823,57 @@
}
}
+ HLiteralList buildTypeVariableList(ClassElement contextClass) {
+ List<HInstruction> inputs = <HInstruction>[];
+ for (Link<DartType> link = contextClass.typeVariables;
+ !link.isEmpty;
+ link = link.tail) {
+ inputs.add(addTypeVariableReference(link.head));
+ }
+ return buildLiteralList(inputs);
+ }
+
HInstruction buildIsNode(Node node, DartType type, HInstruction expression) {
- if (type.kind == TypeKind.TYPE_VARIABLE) {
+ type = type.unalias(compiler);
+ if (type.kind == TypeKind.FUNCTION) {
+ Element checkFunctionSubtype = backend.getCheckFunctionSubtype();
+
+ HInstruction signatureName = graph.addConstantString(
+ new DartString.literal(backend.namer.getFunctionTypeName(type)),
+ node, compiler);
+
+ HInstruction contextName;
+ HInstruction context;
+ HInstruction typeArguments;
+ if (type.containsTypeVariables) {
+ ClassElement contextClass = Types.getClassContext(type);
+ contextName = graph.addConstantString(
+ new DartString.literal(backend.namer.getName(contextClass)),
+ node, compiler);
+ if (currentElement.isInstanceMember()) {
+ context = localsHandler.readThis();
+ typeArguments = graph.addConstantNull(compiler);
+ } else {
+ context = graph.addConstantNull(compiler);
+ typeArguments = buildTypeVariableList(contextClass);
+ add(typeArguments);
+ }
+ } else {
+ contextName = graph.addConstantNull(compiler);
+ context = graph.addConstantNull(compiler);
+ typeArguments = graph.addConstantNull(compiler);
+ }
+
+ List<HInstruction> inputs = <HInstruction>[expression,
+ signatureName,
+ contextName,
+ context,
+ typeArguments];
+ pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN);
+ HInstruction call = pop();
+ return new HIs(type, <HInstruction>[expression, call],
+ HIs.COMPOUND_CHECK);
+ } else if (type.kind == TypeKind.TYPE_VARIABLE) {
HInstruction runtimeType = addTypeVariableReference(type);
Element helper = backend.getCheckSubtypeOfRuntimeType();
List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
@@ -2975,6 +3071,18 @@
}
}
+ void handleForeignJsSetupObject(Send node) {
+ if (!node.arguments.isEmpty) {
+ compiler.cancel(
+ 'Too many arguments to JS_GLOBAL_OBJECT', node: node);
+ }
+
+ String name = backend.namer.GLOBAL_OBJECT;
+ push(new HForeign(new js.LiteralString(name),
+ HType.UNKNOWN,
+ <HInstruction>[]));
+ }
+
void handleForeignJsCallInIsolate(Send node) {
Link<Node> link = node.arguments;
if (!compiler.hasIsolateSupport()) {
@@ -3086,6 +3194,8 @@
handleForeignJs(node);
} else if (name == const SourceString('JS_CURRENT_ISOLATE_CONTEXT')) {
handleForeignJsCurrentIsolateContext(node);
+ } else if (name == const SourceString('JS_GLOBAL_OBJECT')) {
+ handleForeignJsSetupObject(node);
} else if (name == const SourceString('JS_CALL_IN_ISOLATE')) {
handleForeignJsCallInIsolate(node);
} else if (name == const SourceString('DART_CLOSURE_TO_JS')) {
@@ -3101,8 +3211,33 @@
} else if (name == const SourceString('JS_OBJECT_CLASS_NAME')) {
String name = backend.namer.getRuntimeTypeName(compiler.objectClass);
stack.add(addConstantString(node, name));
+ } else if (name == const SourceString('JS_FUNCTION_CLASS_NAME')) {
+ String name = backend.namer.getRuntimeTypeName(compiler.functionClass);
+ stack.add(addConstantString(node, name));
} else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) {
stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
+ } else if (name == const SourceString('JS_SIGNATURE_NAME')) {
+ stack.add(addConstantString(node, backend.namer.operatorSignature()));
+ } else if (name == const SourceString('JS_FUNCTION_TYPE_TAG')) {
+ stack.add(addConstantString(node, backend.namer.functionTypeTag()));
+ } else if (name == const SourceString('JS_FUNCTION_TYPE_VOID_RETURN_TAG')) {
+ stack.add(addConstantString(node,
+ backend.namer.functionTypeVoidReturnTag()));
+ } else if (name == const SourceString('JS_FUNCTION_TYPE_RETURN_TYPE_TAG')) {
+ stack.add(addConstantString(node,
+ backend.namer.functionTypeReturnTypeTag()));
+ } else if (name ==
+ const SourceString('JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG')) {
+ stack.add(addConstantString(node,
+ backend.namer.functionTypeRequiredParametersTag()));
+ } else if (name ==
+ const SourceString('JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG')) {
+ stack.add(addConstantString(node,
+ backend.namer.functionTypeOptionalParametersTag()));
+ } else if (name ==
+ const SourceString('JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG')) {
+ stack.add(addConstantString(node,
+ backend.namer.functionTypeNamedParametersTag()));
} else if (name == const SourceString('JS_DART_OBJECT_CONSTRUCTOR')) {
handleForeignDartObjectJsConstructorFunction(node);
} else if (name == const SourceString('JS_IS_INDEXABLE_FIELD_NAME')) {
@@ -3219,17 +3354,14 @@
TypeVariableElement variable) {
assert(currentElement.isInstanceMember());
int index = RuntimeTypes.getTypeVariableIndex(variable);
- String substitutionNameString = backend.namer.substitutionName(cls);
+ String substitutionNameString = backend.namer.getName(cls);
HInstruction substitutionName = graph.addConstantString(
new LiteralDartString(substitutionNameString), null, compiler);
HInstruction target = localsHandler.readThis();
- HInstruction substitution = createForeign('#[#]', HType.UNKNOWN,
- <HInstruction>[target, substitutionName]);
- add(substitution);
pushInvokeStatic(null,
backend.getGetRuntimeTypeArgument(),
[target,
- substitution,
+ substitutionName,
graph.addConstantInt(index, compiler)],
HType.UNKNOWN);
return pop();
@@ -3246,13 +3378,29 @@
member = closureClass.methodElement;
member = member.getOutermostEnclosingMemberOrTopLevel();
}
- if (isClosure && member.isFactoryConstructor()) {
- // The type variable is used from a closure in a factory constructor. The
- // value of the type argument is stored as a local on the closure itself.
- return localsHandler.readLocal(type.element);
- } else if (member.isConstructor() ||
- member.isGenerativeConstructorBody() ||
- member.isField()) {
+ bool isInConstructorContext = member.isConstructor() ||
+ member.isGenerativeConstructorBody() ||
+ member.isField();
+ if (isClosure) {
+ if (member.isFactoryConstructor()) {
+ // The type variable is used from a closure in a factory constructor.
+ // The value of the type argument is stored as a local on the closure
+ // itself.
+ return localsHandler.readLocal(type.element);
+ } else if (member.isFunction() ||
+ member.isGetter() ||
+ member.isSetter() ||
+ member.isConstructor() ||
+ member.isGenerativeConstructorBody()) {
+ // The type variable is stored on the "enclosing object" and needs to be
+ // accessed using the this-reference in the closure.
+ return readTypeVariable(member.getEnclosingClass(), type.element);
+ } else {
+ assert(member.isField());
+ // The type variable is stored in a parameter of the method.
+ return localsHandler.readLocal(type.element);
+ }
+ } else if (isInConstructorContext) {
// The type variable is stored in a parameter of the method.
return localsHandler.readLocal(type.element);
} else if (member.isInstanceMember()) {
@@ -3295,7 +3443,7 @@
void handleListConstructor(InterfaceType type,
Node currentNode,
HInstruction newObject) {
- if (!backend.needsRti(type.element)) return;
+ if (!backend.classNeedsRti(type.element)) return;
if (!type.isRaw) {
List<HInstruction> inputs = <HInstruction>[];
type.typeArguments.forEach((DartType argument) {
@@ -3308,7 +3456,7 @@
void callSetRuntimeTypeInfo(ClassElement element,
List<HInstruction> rtiInputs,
HInstruction newObject) {
- if (!backend.needsRti(element) || element.typeVariables.isEmpty) {
+ if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) {
return;
}
@@ -3338,23 +3486,25 @@
bool isListConstructor = false;
computeType(element) {
Element originalElement = elements[send];
- if (Elements.isFixedListConstructorCall(
- originalElement, send, compiler)) {
+ if (Elements.isFixedListConstructorCall(originalElement, send, compiler)
+ || Elements.isFilledListConstructorCall(
+ originalElement, send, compiler)) {
isListConstructor = true;
HType inferred =
- new HType.inferredForNode(currentElement, node, compiler);
+ new HType.inferredForNode(currentElement, send, compiler);
return inferred.isUnknown() ? backend.fixedArrayType : inferred;
} else if (Elements.isGrowableListConstructorCall(
originalElement, send, compiler)) {
isListConstructor = true;
HType inferred =
- new HType.inferredForNode(currentElement, node, compiler);
+ new HType.inferredForNode(currentElement, send, compiler);
return inferred.isUnknown() ? backend.extendableArrayType : inferred;
} else if (element.isGenerativeConstructor()) {
ClassElement cls = element.getEnclosingClass();
return new HType.nonNullExact(cls.thisType, compiler);
} else {
- return new HType.inferredTypeForElement(originalElement, compiler);
+ return new HType.inferredReturnTypeForElement(
+ originalElement, compiler);
}
}
@@ -3385,18 +3535,7 @@
bool isRedirected = functionElement.isRedirectingFactory;
DartType expectedType = type;
if (isRedirected) {
- FunctionExpression functionNode = functionElement.parseNode(compiler);
- if (functionNode.isRedirectingFactory) {
- // Lookup the type used in the redirection.
- Return redirectionNode = functionNode.body;
- TreeElements treeElements =
- compiler.enqueuer.resolution.getCachedElements(
- functionElement.declaration);
- ClassElement targetClass = functionElement.getEnclosingClass();
- type = treeElements.getType(redirectionNode.expression)
- .subst(type.typeArguments, targetClass.typeVariables);
- }
- functionElement = functionElement.redirectionTarget;
+ type = functionElement.computeTargetType(compiler, type);
}
var inputs = <HInstruction>[];
@@ -3415,7 +3554,7 @@
generateAbstractClassInstantiationError(send, cls.name.slowToString());
return;
}
- if (backend.needsRti(cls)) {
+ if (backend.classNeedsRti(cls)) {
Link<DartType> typeVariable = cls.typeVariables;
type.typeArguments.forEach((DartType argument) {
inputs.add(analyzeTypeArgument(argument, send));
@@ -3440,7 +3579,7 @@
// not know about the type argument. Therefore we special case
// this constructor to have the setRuntimeTypeInfo called where
// the 'new' is done.
- if (isListConstructor && backend.needsRti(compiler.listClass)) {
+ if (isListConstructor && backend.classNeedsRti(compiler.listClass)) {
handleListConstructor(type, send, newInstance);
}
@@ -3651,7 +3790,6 @@
generateRuntimeError(node.send, message.toString());
}
} else if (node.isConst()) {
- // TODO(karlklose): add type representation
ConstantHandler handler = compiler.constantHandler;
Constant constant = handler.compileNodeWithDefinitions(node, elements);
stack.add(graph.addConstant(constant, compiler));
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index b4f0d92..ef11642 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1550,12 +1550,6 @@
return receiverType.refine(selector, compiler);
}
- void registerInvoke(HInvokeDynamic node, Selector selector) {
- if (node.isInterceptedCall) {
- backend.addInterceptedSelector(selector);
- }
- }
-
void registerMethodInvoke(HInvokeDynamic node) {
Selector selector = getOptimizedSelectorFor(node, node.selector);
@@ -1568,35 +1562,22 @@
// may know something about the types of closures that need
// the specific closure call method.
Selector call = new Selector.callClosureFrom(selector);
- world.registerDynamicInvocation(call.name, call);
+ world.registerDynamicInvocation(call);
}
-
- if (target != null) {
- // If we know we're calling a specific method, register that
- // method only.
- world.registerDynamicInvocationOf(target, selector);
- } else {
- SourceString name = node.selector.name;
- world.registerDynamicInvocation(name, selector);
- }
- registerInvoke(node, selector);
+ world.registerDynamicInvocation(selector);
}
void registerSetter(HInvokeDynamic node) {
Selector selector = getOptimizedSelectorFor(node, node.selector);
- world.registerDynamicSetter(selector.name, selector);
+ world.registerDynamicSetter(selector);
HType valueType = node.isInterceptedCall
? node.inputs[2].instructionType
: node.inputs[1].instructionType;
- registerInvoke(node, selector);
}
void registerGetter(HInvokeDynamic node) {
Selector selector = getOptimizedSelectorFor(node, node.selector);
- world.registerDynamicGetter(selector.name, selector);
- world.registerInstantiatedClass(
- compiler.functionClass, work.resolutionTree);
- registerInvoke(node, selector);
+ world.registerDynamicGetter(selector);
}
visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
@@ -1620,7 +1601,7 @@
backend.namer.invocationName(call),
visitArguments(node.inputs)),
node);
- world.registerDynamicInvocation(call.name, call);
+ world.registerDynamicInvocation(call);
}
visitInvokeStatic(HInvokeStatic node) {
@@ -1998,8 +1979,6 @@
void visitStatic(HStatic node) {
Element element = node.element;
if (element.isFunction()) {
- world.registerInstantiatedClass(
- compiler.functionClass, work.resolutionTree);
push(new js.VariableUse(
backend.namer.isolateStaticClosureAccess(node.element)));
} else {
@@ -2223,7 +2202,6 @@
assert(invariant(input, !type.isMalformed,
message: 'Attempt to check malformed type $type'));
Element element = type.element;
-
if (element == backend.jsArrayClass) {
checkArray(input, negative ? '!==': '===');
return;
@@ -2503,6 +2481,9 @@
return;
}
if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
+ // An int check if the input is not int or null, is not
+ // sufficient for doing a argument or receiver check.
+ assert(!node.isInteger() || node.checkedInput.isIntegerOrNull());
js.Expression test = generateTest(node);
js.Block oldContainer = currentContainer;
js.Statement body = new js.Block.empty();
@@ -2524,6 +2505,7 @@
assert(node.isCheckedModeCheck || node.isCastTypeCheck);
DartType type = node.typeExpression;
+ assert(type.kind != TypeKind.TYPEDEF);
if (type.kind == TypeKind.FUNCTION) {
// TODO(5022): We currently generate $isFunction checks for
// function types.
@@ -2532,53 +2514,17 @@
}
world.registerIsCheck(type, work.resolutionTree);
+ CheckedModeHelper helper;
FunctionElement helperElement;
if (node.isBooleanConversionCheck) {
- helperElement =
- compiler.findHelper(const SourceString('boolConversionCheck'));
+ helper =
+ const CheckedModeHelper(const SourceString('boolConversionCheck'));
} else {
- helperElement = backend.getCheckedModeHelper(type,
- typeCast: node.isCastTypeCheck);
+ helper =
+ backend.getCheckedModeHelper(type, typeCast: node.isCastTypeCheck);
}
- world.registerStaticUse(helperElement);
- List<js.Expression> arguments = <js.Expression>[];
- use(node.checkedInput);
- arguments.add(pop());
- int parameterCount =
- helperElement.computeSignature(compiler).parameterCount;
- // TODO(johnniwinther): Refactor this to avoid using the parameter count
- // to determine how the helper should be called.
- if (node.typeExpression.kind == TypeKind.TYPE_VARIABLE) {
- assert(parameterCount == 2);
- use(node.typeRepresentation);
- arguments.add(pop());
- } else if (parameterCount == 2) {
- // 2 arguments implies that the method is either [propertyTypeCheck],
- // [propertyTypeCast] or [assertObjectIsSubtype].
- assert(!type.isMalformed);
- String additionalArgument = backend.namer.operatorIs(type.element);
- arguments.add(js.string(additionalArgument));
- } else if (parameterCount == 3) {
- // 3 arguments implies that the method is [malformedTypeCheck].
- assert(type.isMalformed);
- String reasons = Types.fetchReasonsFromMalformedType(type);
- arguments.add(js.string('$type'));
- // TODO(johnniwinther): Handle escaping correctly.
- arguments.add(js.string(reasons));
- } else if (parameterCount == 4) {
- Element element = type.element;
- String isField = backend.namer.operatorIs(element);
- arguments.add(js.string(isField));
- use(node.typeRepresentation);
- arguments.add(pop());
- String asField = backend.namer.substitutionName(element);
- arguments.add(js.string(asField));
- } else {
- assert(!type.isMalformed);
- // No additional arguments needed.
- }
- String helperName = backend.namer.isolateAccess(helperElement);
- push(new js.Call(new js.VariableUse(helperName), arguments));
+
+ push(helper.generateCall(this, node));
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index d36e593e..2af8285 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -131,7 +131,11 @@
}
if (constantInterceptor == null) return null;
- if (constantInterceptor == work.element.getEnclosingClass()) {
+
+ // If we just happen to be in an instance method of the constant
+ // interceptor, `this` is a shorter alias.
+ if (constantInterceptor == work.element.getEnclosingClass()
+ && graph.thisInstruction != null) {
return graph.thisInstruction;
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 3f47849..23e9d32 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1110,14 +1110,13 @@
HInstruction convertType(Compiler compiler, DartType type, int kind) {
if (type == null) return this;
+ type = type.unalias(compiler);
// Only the builder knows how to create [HTypeConversion]
// instructions with generics. It has the generic type context
// available.
assert(type.kind != TypeKind.TYPE_VARIABLE);
- // TODO(5022): Generic typedefs should not be handled here.
assert(type.isRaw
|| type.isMalformed
- || type.kind == TypeKind.TYPEDEF
|| type.kind == TypeKind.FUNCTION);
if (identical(type.element, compiler.dynamicClass)) return this;
if (identical(type.element, compiler.objectClass)) return this;
@@ -2251,6 +2250,7 @@
final DartType typeExpression;
final int kind;
final Selector receiverTypeCheckSelector;
+ final bool contextIsTypeArguments;
static const int NO_CHECK = 0;
static const int CHECKED_MODE_CHECK = 1;
@@ -2262,8 +2262,11 @@
HTypeConversion(this.typeExpression, this.kind,
HType type, HInstruction input,
[this.receiverTypeCheckSelector])
- : super(<HInstruction>[input]) {
+ : contextIsTypeArguments = false,
+ super(<HInstruction>[input]) {
assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
+ assert(typeExpression == null ||
+ typeExpression.kind != TypeKind.TYPEDEF);
sourceElement = input.sourceElement;
instructionType = type;
}
@@ -2271,15 +2274,35 @@
HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
HType type, HInstruction input,
HInstruction typeRepresentation)
- : super(<HInstruction>[input, typeRepresentation]),
+ : contextIsTypeArguments = false,
+ super(<HInstruction>[input, typeRepresentation]),
receiverTypeCheckSelector = null {
+ assert(typeExpression.kind != TypeKind.TYPEDEF);
sourceElement = input.sourceElement;
instructionType = type;
}
- bool get hasTypeRepresentation => inputs.length > 1;
+ HTypeConversion.withContext(this.typeExpression, this.kind,
+ HType type, HInstruction input,
+ HInstruction context,
+ {bool this.contextIsTypeArguments})
+ : super(<HInstruction>[input, context]),
+ receiverTypeCheckSelector = null {
+ assert(typeExpression.kind != TypeKind.TYPEDEF);
+ sourceElement = input.sourceElement;
+ instructionType = type;
+ }
+
+ bool get hasTypeRepresentation {
+ return typeExpression.kind == TypeKind.INTERFACE && inputs.length > 1;
+ }
HInstruction get typeRepresentation => inputs[1];
+ bool get hasContext {
+ return typeExpression.kind == TypeKind.FUNCTION && inputs.length > 1;
+ }
+ HInstruction get context => inputs[1];
+
HInstruction convertType(Compiler compiler, DartType type, int kind) {
if (typeExpression == type) return this;
return super.convertType(compiler, type, kind);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index ce291f2..f8ef54e 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -596,8 +596,14 @@
HInstruction visitTypeConversion(HTypeConversion node) {
HInstruction value = node.inputs[0];
DartType type = node.typeExpression;
- if (type != null && (!type.isRaw || type.kind == TypeKind.TYPE_VARIABLE)) {
- return node;
+ if (type != null) {
+ if (!type.isRaw || type.kind == TypeKind.TYPE_VARIABLE) {
+ return node;
+ }
+ if (type.kind == TypeKind.FUNCTION) {
+ // TODO(johnniwinther): Optimize function type conversions.
+ return node;
+ }
}
HType convertedType = node.instructionType;
if (convertedType.isUnknown()) return node;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
index 188969a..38cc812 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -120,14 +120,11 @@
}
// [type] is either an instance of [DartType] or special objects
- // like [native.SpecialType.JsObject], or [native.SpecialType.JsArray].
+ // like [native.SpecialType.JsObject].
static HType fromNativeType(type, Compiler compiler) {
if (type == native.SpecialType.JsObject) {
return new HType.nonNullExact(
compiler.objectClass.computeType(compiler), compiler);
- } else if (type == native.SpecialType.JsArray) {
- JavaScriptBackend backend = compiler.backend;
- return backend.readableArrayType;
} else if (type.isVoid) {
return HType.NULL;
} else if (type.element == compiler.nullClass) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 9ff7a6c..2afc618 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -148,6 +148,24 @@
return inputsType;
}
+ HType visitTypeConversion(HTypeConversion instruction) {
+ HType oldType = instruction.instructionType;
+ // Do not change a checked mode check.
+ if (instruction.isCheckedModeCheck) return oldType;
+ // We must make sure a type conversion for receiver or argument check
+ // does not try to do an int check, because an int check is not enough.
+ // We only do an int check if the input is integer or null.
+ HInstruction checked = instruction.checkedInput;
+ if (oldType.isNumber()
+ && !oldType.isDouble()
+ && checked.isIntegerOrNull()) {
+ return HType.INTEGER;
+ } else if (oldType.isInteger() && !checked.isIntegerOrNull()) {
+ return HType.NUMBER;
+ }
+ return oldType;
+ }
+
void convertInput(HInvokeDynamic instruction,
HInstruction input,
HType type,
@@ -231,13 +249,14 @@
Selector selector = instruction.selector;
if (selector.isOperator() && receiverType.isNumber()) {
if (right.isNumber()) return false;
+ HType type = right.isIntegerOrNull() ? HType.INTEGER : HType.NUMBER;
// TODO(ngeoffray): Some number operations don't have a builtin
// variant and will do the check in their method anyway. We
// still add a check because it allows to GVN these operations,
// but we should find a better way.
convertInput(instruction,
right,
- HType.NUMBER,
+ type,
HTypeConversion.ARGUMENT_TYPE_CHECK);
return true;
}
@@ -331,10 +350,6 @@
instruction, input, compiler);
}
- HType visitNot(HNot instruction) {
- return HType.BOOLEAN;
- }
-
HType visitPhi(HPhi phi) {
// Best case scenario for a phi is, when all inputs have the same type. If
// there is no desired outgoing type we therefore try to unify the input
@@ -455,6 +470,9 @@
// TODO(ngeoffray): Allow speculative optimizations on
// non-primitive types?
if (!desiredType.isPrimitive(compiler)) return newType;
+ // It's not worth having a bailout method just because we want a
+ // boolean. Comparing to true is enough.
+ if (desiredType.isBooleanOrNull()) return newType;
desiredType = newType.intersection(desiredType, compiler);
if (desiredType != newType && !hasBeenSpeculativelyOptimized(instruction)) {
savedTypes[instruction] = oldType;
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index 9a3c43c..81a51d3 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -369,15 +369,32 @@
bool get isParameterCheck =>
isOperator && identical(selector.asOperator().source.stringValue, '?');
+ bool get isTypeCast {
+ return isOperator
+ && identical(selector.asOperator().source.stringValue, 'as');
+ }
+
+ bool get isTypeTest {
+ return isOperator
+ && identical(selector.asOperator().source.stringValue, 'is');
+ }
+
+ bool get isIsCheck {
+ return isOperator
+ && identical(selector.asOperator().source.stringValue, 'is')
+ && arguments.head.asSend() == null;
+ }
+
bool get isIsNotCheck {
return isOperator
&& identical(selector.asOperator().source.stringValue, 'is')
&& arguments.head.asSend() != null;
}
- TypeAnnotation get typeAnnotationFromIsCheck {
- assert(isOperator
- && identical(selector.asOperator().source.stringValue, 'is'));
+ TypeAnnotation get typeAnnotationFromIsCheckOrCast {
+ assert(isOperator);
+ assert(identical(selector.asOperator().source.stringValue, 'is') ||
+ identical(selector.asOperator().source.stringValue, 'as'));
return isIsNotCheck
? arguments.head.asSend().receiver
: arguments.head;
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index 49612a9..78f4c8a 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -506,6 +506,10 @@
*/
ElementAccess computeAccess(Send node, SourceString name, Element element,
MemberKind memberKind) {
+ if (element != null && element.isErroneous()) {
+ // An error has already been reported for this node.
+ return const DynamicAccess();
+ }
if (node.receiver != null) {
Element receiverElement = elements[node.receiver];
if (receiverElement != null) {
@@ -557,6 +561,16 @@
} else if (element.isErroneous()) {
// foo() where foo is erroneous.
return const DynamicAccess();
+ } else if (element.impliesType()) {
+ // The literal `Foo` where Foo is a class, a typedef, or a type variable.
+ if (elements.getType(node) != null) {
+ assert(invariant(node, identical(compiler.typeClass,
+ elements.getType(node).element),
+ message: 'Expected type literal type: '
+ '${elements.getType(node)}'));
+ return new TypeLiteralAccess(element);
+ }
+ return createResolvedAccess(node, name, element);
} else if (element.isMember()) {
// foo() where foo is an instance member.
return lookupMember(node, currentClass.computeType(compiler),
@@ -569,16 +583,6 @@
element.isField()) {
// foo() where foo is a field in the same class.
return createResolvedAccess(node, name, element);
- } else if (element.impliesType()) {
- // The literal `Foo` where Foo is a class, a typedef, or a type variable.
- if (elements.getType(node) != null) {
- assert(invariant(node, identical(compiler.typeClass,
- elements.getType(node).element),
- message: 'Expected type literal type: '
- '${elements.getType(node)}'));
- return new TypeLiteralAccess(element);
- }
- return createResolvedAccess(node, name, element);
} else if (element.isGetter() || element.isSetter()) {
return createResolvedAccess(node, name, element);
} else {
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index ee5ccd5..c7af6a1 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -470,6 +470,18 @@
throw new UnsupportedError("");
}
+ bool get isContainer {
+ throw new UnsupportedError("");
+ }
+
+ bool get isForwarding {
+ throw new UnsupportedError("");
+ }
+
+ bool get isElement {
+ throw new UnsupportedError("");
+ }
+
bool containsOnlyInt(Compiler compiler) {
throw new UnsupportedError("");
}
@@ -1142,9 +1154,6 @@
// TODO(polux): track native types
if (type == native.SpecialType.JsObject) {
return unknownConcreteType;
- } else if (type == native.SpecialType.JsArray) {
- concreteType = singletonConcreteType(baseTypes.listBaseType);
-
// at this point, we know that type is not a SpecialType and thus has to
// be a DartType
} else if (type.element == compiler.objectClass) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
index 04c9923..4913c8b 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
@@ -9,7 +9,8 @@
import '../tree/tree.dart';
import '../universe/universe.dart';
import '../util/util.dart' show Link;
-import 'simple_types_inferrer.dart' show SimpleTypesInferrer, InferrerVisitor;
+import 'simple_types_inferrer.dart'
+ show SimpleTypesInferrer, InferrerVisitor, LocalsHandler;
import 'types.dart';
/**
@@ -95,6 +96,8 @@
var internal = inferrer.internal;
// Walk over all created [ContainerTypeMask].
internal.concreteTypes.values.forEach((ContainerTypeMask mask) {
+ // The element type has already been set for const containers.
+ if (mask.elementType != null) return;
mask.elementType = new TracerForConcreteContainer(
mask, this, compiler, inferrer).run();
});
@@ -162,9 +165,8 @@
// [potentialType] can be null if we did not find any instruction
// that adds elements to the list.
- if (potentialType == null) return new TypeMask.empty();
+ if (potentialType == null) return new TypeMask.nonNullEmpty();
- potentialType = potentialType.nullable();
// Walk over the found constraints and update the type according
// to the selectors of these constraints.
for (Selector constraint in constraints) {
@@ -174,7 +176,7 @@
inferrer.getTypeOfSelector(constraint), compiler);
}
if (_VERBOSE) {
- print('$potentialType for $analyzedNode');
+ print('$potentialType for $analyzedNode $startElement');
}
return potentialType;
}
@@ -257,13 +259,15 @@
class ContainerTracerVisitor extends InferrerVisitor {
final Element analyzedElement;
final TracerForConcreteContainer tracer;
- ContainerTracerVisitor(element, tracer)
- : super(element, tracer.inferrer, tracer.compiler),
+ final bool visitingClosure;
+
+ ContainerTracerVisitor(element, tracer, [LocalsHandler locals])
+ : super(element, tracer.inferrer, tracer.compiler, locals),
this.analyzedElement = element,
- this.tracer = tracer;
+ this.tracer = tracer,
+ visitingClosure = locals != null;
bool escaping = false;
- bool visitingClosure = false;
bool visitingInitializers = false;
void run() {
@@ -334,20 +338,22 @@
}
TypeMask visitFunctionExpression(FunctionExpression node) {
- bool oldVisitingClosure = visitingClosure;
FunctionElement function = elements[node];
- FunctionSignature signature = function.computeSignature(compiler);
- signature.forEachParameter((element) {
- locals.update(element, inferrer.getTypeOfElement(element));
- });
- visitingClosure = function != analyzedElement;
- bool oldVisitingInitializers = visitingInitializers;
- visitingInitializers = true;
- visit(node.initializers);
- visitingInitializers = oldVisitingInitializers;
- visit(node.body);
- visitingClosure = oldVisitingClosure;
-
+ if (function != analyzedElement) {
+ // Visiting a closure.
+ LocalsHandler closureLocals = new LocalsHandler.from(locals);
+ new ContainerTracerVisitor(function, tracer, closureLocals).run();
+ } else {
+ // Visiting [analyzedElement].
+ FunctionSignature signature = function.computeSignature(compiler);
+ signature.forEachParameter((element) {
+ locals.update(element, inferrer.getTypeOfElement(element));
+ });
+ visitingInitializers = true;
+ visit(node.initializers);
+ visitingInitializers = false;
+ visit(node.body);
+ }
return inferrer.functionType;
}
@@ -518,6 +524,32 @@
TypeMask visitStaticSend(Send node) {
Element element = elements[node];
+
+ if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
+ visitArguments(node.arguments, element);
+ if (tracer.couldBeTheList(node)) {
+ escaping = true;
+ }
+ return inferrer.growableListType;
+ } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
+ tracer.unionPotentialTypeWith(inferrer.nullType);
+ visitArguments(node.arguments, element);
+ if (tracer.couldBeTheList(node)) {
+ escaping = true;
+ }
+ return inferrer.fixedListType;
+ } else if (Elements.isFilledListConstructorCall(element, node, compiler)) {
+ if (tracer.couldBeTheList(node)) {
+ escaping = true;
+ visit(node.arguments.head);
+ TypeMask fillWithType = visit(node.arguments.tail.head);
+ tracer.unionPotentialTypeWith(fillWithType);
+ } else {
+ visitArguments(node.arguments, element);
+ }
+ return inferrer.fixedListType;
+ }
+
bool isEscaping = visitArguments(node.arguments, element);
if (element.isForeign(compiler)) {
@@ -528,17 +560,7 @@
escaping = true;
}
- if (Elements.isGrowableListConstructorCall(element, node, compiler)) {
- if (tracer.couldBeTheList(node)) {
- escaping = true;
- }
- return inferrer.growableListType;
- } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
- if (tracer.couldBeTheList(node)) {
- escaping = true;
- }
- return inferrer.fixedListType;
- } else if (element.isFunction() || element.isConstructor()) {
+ if (element.isFunction() || element.isConstructor()) {
return inferrer.getReturnTypeOfElement(element);
} else {
// Closure call or unresolved.
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index 3684755..f74db6e 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -15,11 +15,10 @@
/// A [ContainerTypeMask] is a [TypeMask] for a specific allocation
/// site of a container (currently only List) that will get specialized
/// once the [ListTracer] phase finds an element type for it.
-class ContainerTypeMask implements TypeMask {
-
+class ContainerTypeMask extends ForwardingTypeMask {
// The flat version of a [ContainerTypeMask] is the container type
// (for example List).
- final FlatTypeMask asFlat;
+ final FlatTypeMask forwardTo;
// The [Node] where this type mask was created.
final Node allocationNode;
@@ -36,7 +35,7 @@
holder.elementType = mask;
}
- ContainerTypeMask(this.asFlat,
+ ContainerTypeMask(this.forwardTo,
this.allocationNode,
this.allocationElement,
[holder])
@@ -45,7 +44,7 @@
TypeMask nullable() {
return isNullable
? this
- : new ContainerTypeMask(asFlat.nullable(),
+ : new ContainerTypeMask(forwardTo.nullable(),
allocationNode,
allocationElement,
holder);
@@ -53,79 +52,29 @@
TypeMask nonNullable() {
return isNullable
- ? new ContainerTypeMask(asFlat.nonNullable(),
+ ? new ContainerTypeMask(forwardTo.nonNullable(),
allocationNode,
allocationElement,
holder)
: this;
}
- TypeMask simplify(Compiler compiler) => this;
-
- bool get isEmpty => false;
- bool get isNullable => asFlat.isNullable;
- bool get isExact => true;
- bool get isUnion => false;
bool get isContainer => true;
+ bool get isExact => true;
- bool containsOnlyInt(Compiler compiler) => false;
- bool containsOnlyDouble(Compiler compiler) => false;
- bool containsOnlyNum(Compiler compiler) => false;
- bool containsOnlyNull(Compiler compiler) => false;
- bool containsOnlyBool(Compiler compiler) => false;
- bool containsOnlyString(Compiler compiler) => false;
- bool containsOnly(ClassElement element) {
- return asFlat.containsOnly(element);
- }
-
- bool satisfies(ClassElement cls, Compiler compiler) {
- return asFlat.satisfies(cls, compiler);
- }
-
- bool contains(DartType type, Compiler compiler) {
- return asFlat.contains(type, compiler);
- }
-
- bool containsAll(Compiler compiler) => false;
-
- ClassElement singleClass(Compiler compiler) {
- return asFlat.singleClass(compiler);
- }
-
- Iterable<ClassElement> containedClasses(Compiler compiler) {
- return asFlat.containedClasses(compiler);
- }
-
- TypeMask union(other, Compiler compiler) {
- if (other.isContainer
- && other.allocationNode == this.allocationNode) {
- return other.isNullable ? other : this;
- } else if (other.isEmpty) {
- return other.isNullable ? this.nullable() : this;
- }
- return asFlat.union(other, compiler);
+ bool equalsDisregardNull(other) {
+ if (other is! ContainerTypeMask) return false;
+ return allocationNode == other.allocationNode;
}
TypeMask intersection(TypeMask other, Compiler compiler) {
- TypeMask flatIntersection = asFlat.intersection(other, compiler);
- if (flatIntersection.isEmpty) return flatIntersection;
- return flatIntersection.isNullable
+ TypeMask forwardIntersection = forwardTo.intersection(other, compiler);
+ if (forwardIntersection.isEmpty) return forwardIntersection;
+ return forwardIntersection.isNullable
? nullable()
: nonNullable();
}
- bool willHit(Selector selector, Compiler compiler) {
- return asFlat.willHit(selector, compiler);
- }
-
- bool canHit(Element element, Selector selector, Compiler compiler) {
- return asFlat.canHit(element, selector, compiler);
- }
-
- Element locateSingleElement(Selector selector, Compiler compiler) {
- return asFlat.locateSingleElement(selector, compiler);
- }
-
bool operator==(other) {
if (other is! ContainerTypeMask) return false;
return allocationNode == other.allocationNode
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index c96f28d..3013586 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -62,8 +62,11 @@
bool get isEmpty => (flags >> 1) == EMPTY;
bool get isExact => (flags >> 1) == EXACT;
bool get isNullable => (flags & 1) != 0;
+
bool get isUnion => false;
bool get isContainer => false;
+ bool get isForwarding => false;
+ bool get isElement => false;
// TODO(kasperl): Get rid of these. They should not be a visible
// part of the implementation because they make it hard to add
@@ -426,11 +429,18 @@
|| compiler.world.hasAnySubclassThatMixes(self, other);
} else {
assert(isSubtype);
- return hasElementIn(self, selector, element, compiler)
+ bool result = hasElementIn(self, selector, element, compiler)
|| other.implementsInterface(self)
- || other.isSubclassOf(self)
- || compiler.world.hasAnySubclassThatMixes(self, other)
|| compiler.world.hasAnySubclassThatImplements(other, base);
+ if (result) return true;
+ // If the class is used as a mixin, we have to check if the element
+ // can be hit from any of the mixin applications.
+ Iterable<ClassElement> mixinUses = compiler.world.mixinUses[self];
+ if (mixinUses == null) return false;
+ return mixinUses.any((mixinApplication) =>
+ hasElementIn(mixinApplication, selector, element, compiler)
+ || other.isSubclassOf(mixinApplication)
+ || compiler.world.hasAnySubclassThatMixes(mixinApplication, other));
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index 75e35e1..81d00bb 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -31,9 +31,9 @@
* Returns the least upper bound between [firstType] and
* [secondType].
*/
- TypeMask computeLUB(TypeMask firstType,
- TypeMask secondType,
- Compiler compiler) {
+TypeMask computeLUB(TypeMask firstType,
+ TypeMask secondType,
+ Compiler compiler) {
TypeMask dynamicType = compiler.typesTask.dynamicType;
if (firstType == null) {
return secondType;
@@ -41,6 +41,8 @@
return secondType;
} else if (firstType == dynamicType) {
return firstType;
+ } else if (firstType == secondType) {
+ return firstType;
} else {
TypeMask union = firstType.union(secondType, compiler);
// TODO(kasperl): If the union isn't nullable it seems wasteful
@@ -60,11 +62,11 @@
final Map<Element, TypeMask> fieldsInitializedInConstructor;
final bool inTryBlock;
bool isThisExposed;
- bool seenReturn = false;
+ bool seenReturnOrThrow = false;
bool seenBreakOrContinue = false;
bool get aborts {
- return seenReturn || seenBreakOrContinue;
+ return seenReturnOrThrow || seenBreakOrContinue;
}
LocalsHandler(this.inferrer, this.compiler)
@@ -183,7 +185,7 @@
fieldsInitializedInConstructor.remove(element);
});
isThisExposed = isThisExposed || other.isThisExposed;
- seenReturn = seenReturn && other.seenReturn;
+ seenReturnOrThrow = seenReturnOrThrow && other.seenReturnOrThrow;
seenBreakOrContinue = seenBreakOrContinue && other.seenBreakOrContinue;
return changed;
@@ -365,7 +367,7 @@
} else {
if (!usePositive) continue;
}
- DartType type = elements.getType(node.typeAnnotationFromIsCheck);
+ DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
Element element = elements[node.receiver];
TypeMask existing = locals.use(element);
TypeMask newType = narrowType(
@@ -591,7 +593,7 @@
TypeMask visitThrow(Throw node) {
node.visitChildren(this);
- locals.seenReturn = true;
+ locals.seenReturnOrThrow = true;
return inferrer.dynamicType;
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index bcc73b3..e28ffaa 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -14,7 +14,8 @@
import '../tree/tree.dart';
import '../util/util.dart' show Link;
import 'types.dart'
- show TypesInferrer, FlatTypeMask, TypeMask, ContainerTypeMask;
+ show TypesInferrer, FlatTypeMask, TypeMask, ContainerTypeMask,
+ ElementTypeMask;
// BUG(8802): There's a bug in the analyzer that makes the re-export
// of Selector from dart2jslib.dart fail. For now, we work around that
@@ -51,17 +52,82 @@
}
/**
- * Placeholder for type information of final fields of classes.
+ * A [TypeInformation] object contains information from the inferrer
+ * on a specific [Element].
*/
-class ClassInfoForFinalFields {
+abstract class TypeInformation {
/**
- * Maps a final field to a map from generative constructor to the
- * inferred type of the field in that generative constructor.
+ * Assignments on the element and the types inferred at
+ * these assignments.
*/
- final Map<Element, Map<Node, TypeMask>> typesOfFinalFields =
- new Map<Element, Map<Node, TypeMask>>();
+ Map<Node, TypeMask> get assignments => null;
/**
+ * Callers of an element.
+ */
+ Set<Element> get callers => null;
+
+ /**
+ * Number of times the element has been processed.
+ */
+ int get analyzeCount => 0;
+ void set analyzeCount(value) {}
+
+ TypeMask get type => null;
+ void set type(value) {}
+
+ TypeMask get returnType => null;
+ void set returnType(value) {}
+
+ void addCaller(Element element) {
+ callers.add(element);
+ }
+
+ void addAssignment(Node node, TypeMask mask) {
+ assignments[node] = mask;
+ }
+
+ void clear();
+}
+
+class FunctionTypeInformation extends TypeInformation {
+ Set<Element> callers = new Set<Element>();
+ TypeMask returnType;
+ int analyzeCount = 0;
+ bool canBeClosurized = false;
+
+ void clear() {
+ callers = null;
+ }
+}
+
+class ParameterTypeInformation extends TypeInformation {
+ Map<Node, TypeMask> assignments = new Map<Node, TypeMask>();
+ TypeMask type;
+ TypeMask defaultType;
+
+ void clear() {
+ assignments = null;
+ }
+}
+
+class FieldTypeInformation extends TypeInformation {
+ TypeMask type;
+ Set<Element> callers = new Set<Element>();
+ Map<Node, TypeMask> assignments = new Map<Node, TypeMask>();
+ int analyzeCount = 0;
+
+ void clear() {
+ assignments = null;
+ callers = null;
+ }
+}
+
+/**
+ * A class for knowing when can we compute a type for final fields.
+ */
+class ClassTypeInformation {
+ /**
* The number of generative constructors that need to be visited
* before we can take any decision on the type of the fields.
* Given that all generative constructors must be analyzed before
@@ -70,20 +136,7 @@
*/
int constructorsToVisitCount;
- ClassInfoForFinalFields(this.constructorsToVisitCount);
-
- /**
- * Records that the generative [constructor] has inferred [type]
- * for the final [field].
- */
- void recordFinalFieldType(Node node,
- Element constructor,
- Element field,
- TypeMask type) {
- Map<Node, TypeMask> typesFor = typesOfFinalFields.putIfAbsent(
- field, () => new Map<Node, TypeMask>());
- typesFor[node] = type;
- }
+ ClassTypeInformation(this.constructorsToVisitCount);
/**
* Records that [constructor] has been analyzed. If not at 0,
@@ -130,11 +183,11 @@
TypeMask getReturnTypeOfElement(Element element) {
if (compiler.disableTypeInference) return dynamicType;
- return internal.getReturnTypeOfElement(element);
+ return internal.getReturnTypeOfElement(element.implementation);
}
TypeMask getTypeOfElement(Element element) {
if (compiler.disableTypeInference) return dynamicType;
- return internal.getTypeOfElement(element);
+ return internal.getTypeOfElement(element.implementation);
}
TypeMask getTypeOfNode(Element owner, Node node) {
if (compiler.disableTypeInference) return dynamicType;
@@ -144,13 +197,9 @@
if (compiler.disableTypeInference) return dynamicType;
return internal.getTypeOfSelector(selector);
}
-
Iterable<Element> getCallersOf(Element element) {
if (compiler.disableTypeInference) throw "Don't use me";
- Iterable<Element> result = internal.callersOf[element];
- return result == null
- ? internal.callersOf[element] = const <Element>[]
- : result;
+ return internal.getCallersOf(element.implementation);
}
bool analyzeMain(Element element) {
@@ -171,67 +220,25 @@
class InternalSimpleTypesInferrer extends TypesInferrer {
/**
+ * Maps a class to a [ClassTypeInformation] to help collect type
+ * information of final fields.
+ */
+ Map<ClassElement, ClassTypeInformation> classInfoForFinalFields =
+ new Map<ClassElement, ClassTypeInformation>();
+
+ /**
+ * Maps an element to its corresponding [TypeInformation].
+ */
+ final Map<Element, TypeInformation> typeInfo =
+ new Map<Element, TypeInformation>();
+
+ /**
* Maps a node to its type. Currently used for computing element
* types of lists.
*/
final Map<Node, TypeMask> concreteTypes = new Map<Node, TypeMask>();
/**
- * Maps an element to its callers.
- */
- final Map<Element, Iterable<Element>> callersOf =
- new Map<Element, Iterable<Element>>();
-
- /**
- * Maps an element to its return type.
- */
- final Map<Element, TypeMask> returnTypeOf =
- new Map<Element, TypeMask>();
-
- /**
- * Maps an element to its type.
- */
- final Map<Element, TypeMask> typeOf = new Map<Element, TypeMask>();
-
- /**
- * Maps an element to its assignments and the types inferred at
- * these assignments.
- */
- final Map<Element, Map<Node, TypeMask>> typeOfFields =
- new Map<Element, Map<Node, TypeMask>>();
-
- /**
- * Maps an element to the type of its parameters at call sites.
- */
- final Map<Element, Map<Node, ArgumentsTypes>> typeOfArguments =
- new Map<Element, Map<Node, ArgumentsTypes>>();
-
- /**
- * Maps an optional parameter to its default type.
- */
- final Map<Element, TypeMask> defaultTypeOfParameter =
- new Map<Element, TypeMask>();
-
- /**
- * Set of methods that the inferrer found could be closurized. We
- * don't compute parameter types for such methods.
- */
- final Set<Element> methodsThatCanBeClosurized = new Set<Element>();
-
- /**
- * Maps an element to the number of times this type inferrer
- * analyzed it.
- */
- final Map<Element, int> analyzeCount = new Map<Element, int>();
-
- /**
- * Maps a class to a [ClassInfoForFinalFields] to help collect type
- * information of final fields.
- */
- final Map<ClassElement, ClassInfoForFinalFields> classInfoForFinalFields =
- new Map<ClassElement, ClassInfoForFinalFields>();
-
- /**
* A map of constraints on a setter. When computing the type
* of a field, these [Node] are initially discarded, and once the
* type is computed, we make sure these constraints are satisfied
@@ -246,12 +253,12 @@
* returns that type.
*
*/
- final Map<Node, Selector> setterConstraints = new Map<Node, Selector>();
+ Map<Node, CallSite> setterConstraints = new Map<Node, CallSite>();
/**
* The work list of the inferrer.
*/
- final WorkSet<Element> workSet = new WorkSet<Element>();
+ WorkSet<Element> workSet = new WorkSet<Element>();
/**
* Heuristic for avoiding too many re-analysis of an element.
@@ -319,6 +326,11 @@
*/
int numberOfElementsToAnalyze;
+ /**
+ * The number of analysis already done.
+ */
+ int analyzed = 0;
+
InternalSimpleTypesInferrer(this.compiler, this.optimismState);
/**
@@ -327,7 +339,6 @@
*/
bool analyzeMain(Element element) {
buildWorkQueue();
- int analyzed = 0;
compiler.progress.reset();
int maxReanalysis = (numberOfElementsToAnalyze * 1.5).toInt();
do {
@@ -338,7 +349,7 @@
element = workSet.remove();
if (element.isErroneous()) continue;
- bool wasAnalyzed = analyzeCount.containsKey(element);
+ bool wasAnalyzed = typeInformationOf(element).analyzeCount != 0;
if (wasAnalyzed) {
recompiles++;
if (recompiles >= maxReanalysis) {
@@ -365,15 +376,28 @@
return true;
}
+ TypeInformation typeInformationOf(Element element) {
+ return typeInfo.putIfAbsent(element, () {
+ if (element.isParameter() || element.isFieldParameter()) {
+ return new ParameterTypeInformation();
+ } else if (element.isField() || element.isVariable()) {
+ return new FieldTypeInformation();
+ } else {
+ assert(element is FunctionElement);
+ return new FunctionTypeInformation();
+ }
+ });
+ }
+
/**
* Query method after the analysis to know the type of [element].
*/
TypeMask getReturnTypeOfElement(Element element) {
- return getNonNullType(returnTypeOf[element]);
+ return getNonNullType(typeInformationOf(element).returnType);
}
TypeMask getTypeOfElement(Element element) {
- return getNonNullType(typeOf[element]);
+ return getNonNullType(typeInformationOf(element).type);
}
TypeMask getTypeOfSelector(Selector selector) {
@@ -388,6 +412,10 @@
return returnType != null ? returnType : dynamicType;
}
+ Iterable<Element> getCallersOf(Element element) {
+ return typeInformationOf(element).callers;
+ }
+
/**
* Query method after the analysis to know the type of [node],
* defined in the context of [owner].
@@ -398,29 +426,39 @@
void checkAnalyzedAll() {
if (hasAnalyzedAll) return;
- if (analyzeCount.length != numberOfElementsToAnalyze) return;
+ if (analyzed < numberOfElementsToAnalyze) return;
hasAnalyzedAll = true;
+
// If we have analyzed all the world, we know all assigments to
- // fields and can therefore infer a type for them.
- typeOfFields.keys.forEach(updateNonFinalFieldType);
- // We also know all calls to methods.
- typeOfArguments.keys.forEach(updateArgumentsType);
+ // fields and parameters, and can therefore infer a type for them.
+ typeInfo.forEach((element, TypeInformation info) {
+ if (element.isParameter() || element.isFieldParameter()) {
+ if (updateParameterType(element)) {
+ enqueueAgain(element.enclosingElement);
+ }
+ } else if (element.isField()
+ && !(element.modifiers.isFinal()
+ || element.modifiers.isConst())) {
+ updateNonFinalFieldType(element);
+ } else if (element.isVariable()) {
+ updateNonFinalFieldType(element);
+ }
+ });
}
/**
* Enqueues [e] in the work queue if it is valuable.
*/
void enqueueAgain(Element e) {
- int count = analyzeCount[e];
+ assert(isNotClosure(e));
+ int count = typeInformationOf(e).analyzeCount;
if (count != null && count > MAX_ANALYSIS_COUNT_PER_ELEMENT) return;
workSet.add(e);
}
void enqueueCallersOf(Element element) {
- Set<Element> methodCallers = callersOf[element];
- if (methodCallers != null) {
- methodCallers.forEach(enqueueAgain);
- }
+ assert(isNotClosure(element));
+ typeInformationOf(element).callers.forEach(enqueueAgain);
}
/**
@@ -453,7 +491,9 @@
// Optimistically assume that they return bool. We may need to back
// out of this.
if (optimismState == OPTIMISTIC) {
- returnTypeOf[element.implementation] = boolType;
+ FunctionTypeInformation info =
+ typeInformationOf(element.implementation);
+ info.returnType = boolType;
}
} else {
// Put the other operators in buckets by length, later to be added in
@@ -490,7 +530,7 @@
}
});
classInfoForFinalFields[cls.implementation] =
- new ClassInfoForFinalFields(constructorCount);
+ new ClassTypeInformation(constructorCount);
});
}
@@ -504,13 +544,15 @@
dump() {
int interestingTypes = 0;
- returnTypeOf.forEach((Element element, TypeMask type) {
- if (type != nullType && !isDynamicType(type)) {
+ typeInfo.forEach((element, TypeInformation info) {
+ TypeMask type = info.type;
+ TypeMask returnType = info.returnType;
+ if (type != null && type != nullType && !isDynamicType(type)) {
interestingTypes++;
}
- });
- typeOf.forEach((Element element, TypeMask type) {
- if (type != nullType && !isDynamicType(type)) {
+ if (returnType != null
+ && returnType != nullType
+ && !isDynamicType(returnType)) {
interestingTypes++;
}
});
@@ -525,11 +567,10 @@
* Clear data structures that are not used after the analysis.
*/
void clear() {
- callersOf.clear();
- analyzeCount.clear();
- classInfoForFinalFields.clear();
- typeOfFields.clear();
- setterConstraints.clear();
+ classInfoForFinalFields = null;
+ setterConstraints = null;
+ workSet = null;
+ typeInfo.forEach((_, info) { info.clear(); });
}
bool analyze(Element element) {
@@ -539,11 +580,7 @@
SimpleTypeInferrerVisitor visitor =
new SimpleTypeInferrerVisitor(element, compiler, this);
TypeMask returnType = visitor.run();
- if (analyzeCount.containsKey(element)) {
- analyzeCount[element]++;
- } else {
- analyzeCount[element] = 1;
- }
+ typeInformationOf(element).analyzeCount++;
if (element.isGenerativeConstructor()) {
// We always know the return type of a generative constructor.
return false; // Nothing changed.
@@ -575,11 +612,18 @@
}
bool recordType(Element analyzedElement, TypeMask type) {
+ if (isNativeElement(analyzedElement)) return false;
assert(type != null);
assert(analyzedElement.isField()
|| analyzedElement.isParameter()
|| analyzedElement.isFieldParameter());
- return internalRecordType(analyzedElement, type, typeOf);
+ TypeMask newType = checkTypeAnnotation(analyzedElement, type);
+ TypeMask existing = typeInformationOf(analyzedElement).type;
+ typeInformationOf(analyzedElement).type = newType;
+ // If the type is useful, say it has changed.
+ return existing != newType
+ && !isDynamicType(newType)
+ && newType != nullType;
}
/**
@@ -588,15 +632,23 @@
* [analyzedElement].
*/
bool recordReturnType(Element analyzedElement, TypeMask returnType) {
+ if (isNativeElement(analyzedElement)) return false;
assert(analyzedElement.implementation == analyzedElement);
+ TypeMask existing = typeInformationOf(analyzedElement).returnType;
if (optimismState == OPTIMISTIC
&& shouldOptimisticallyOptimizeToBool(analyzedElement)
- && returnType != returnTypeOf[analyzedElement]) {
+ && returnType != existing) {
// One of the functions turned out not to return what we expected.
// This means we need to restart the analysis.
optimismState = RETRY;
}
- return internalRecordType(analyzedElement, returnType, returnTypeOf);
+ TypeMask newType = checkTypeAnnotation(analyzedElement, returnType);
+ FunctionTypeInformation info = typeInformationOf(analyzedElement);
+ info.returnType = newType;
+ // If the return type is useful, say it has changed.
+ return existing != newType
+ && !isDynamicType(newType)
+ && newType != nullType;
}
bool isNativeElement(Element element) {
@@ -606,31 +658,32 @@
&& element.isField();
}
- bool internalRecordType(Element analyzedElement,
- TypeMask newType,
- Map<Element, TypeMask> types) {
+ TypeMask checkTypeAnnotation(Element analyzedElement, TypeMask newType) {
if (compiler.trustTypeAnnotations
// Parameters are being checked by the method, and we can
// therefore only trust their type after the checks.
|| (compiler.enableTypeAssertions && !analyzedElement.isParameter())) {
var annotation = analyzedElement.computeType(compiler);
- if (types == returnTypeOf) {
+ if (analyzedElement.isGetter()
+ || analyzedElement.isFunction()
+ || analyzedElement.isConstructor()
+ || analyzedElement.isSetter()) {
assert(annotation is FunctionType);
annotation = annotation.returnType;
}
newType = narrowType(newType, annotation, compiler);
}
+ return newType;
+ }
- // Fields and native methods of native classes are handled
- // specially when querying for their type or return type.
- if (isNativeElement(analyzedElement)) return false;
- assert(newType != null);
- TypeMask existing = types[analyzedElement];
- types[analyzedElement] = newType;
- // If the return type is useful, say it has changed.
- return existing != newType
- && !isDynamicType(newType)
- && newType != nullType;
+ TypeMask fetchReturnType(Element element) {
+ TypeMask returnType = typeInformationOf(element).returnType;
+ return returnType is ElementTypeMask ? dynamicType : returnType;
+ }
+
+ TypeMask fetchType(Element element) {
+ TypeMask type = typeInformationOf(element).type;
+ return type is ElementTypeMask ? dynamicType : type;
}
/**
@@ -639,22 +692,25 @@
*/
TypeMask returnTypeOfElement(Element element) {
element = element.implementation;
+ TypeInformation info = typeInformationOf(element);
if (element.isGenerativeConstructor()) {
- return returnTypeOf.putIfAbsent(element, () {
- return new TypeMask.nonNullExact(
- rawTypeOf(element.getEnclosingClass()));
- });
+ return info.returnType == null
+ ? info.returnType = new TypeMask.nonNullExact(
+ rawTypeOf(element.getEnclosingClass()))
+ : info.returnType;
} else if (element.isNative()) {
- return returnTypeOf.putIfAbsent(element, () {
+ if (info.returnType == null) {
var elementType = element.computeType(compiler);
if (elementType.kind != TypeKind.FUNCTION) {
- return dynamicType;
- }
- return typeOfNativeBehavior(
+ info.returnType = dynamicType;
+ } else {
+ info.returnType = typeOfNativeBehavior(
native.NativeBehavior.ofMethod(element, compiler));
- });
+ }
+ }
+ return info.returnType;
}
- TypeMask returnType = returnTypeOf[element];
+ TypeMask returnType = info.returnType;
if (returnType == null) {
if ((compiler.trustTypeAnnotations || compiler.enableTypeAssertions)
&& (element.isFunction()
@@ -663,7 +719,8 @@
FunctionType functionType = element.computeType(compiler);
returnType = narrowType(dynamicType, functionType.returnType, compiler);
} else {
- returnType = dynamicType;
+ returnType = info.returnType =
+ new ElementTypeMask(fetchReturnType, element);
}
}
return returnType;
@@ -678,8 +735,6 @@
TypeMask mappedType;
if (type == native.SpecialType.JsObject) {
mappedType = new TypeMask.nonNullExact(rawTypeOf(compiler.objectClass));
- } else if (type == native.SpecialType.JsArray) {
- mappedType = listType;
} else if (type.element == compiler.stringClass) {
mappedType = stringType;
} else if (type.element == compiler.intClass) {
@@ -696,12 +751,17 @@
mappedType = nullType;
} else if (type.isDynamic) {
return dynamicType;
- } else if (compiler.world.hasAnySubclass(type.element)) {
- mappedType = new TypeMask.nonNullSubclass(rawTypeOf(type.element));
- } else if (compiler.world.hasAnySubtype(type.element)) {
- mappedType = new TypeMask.nonNullSubtype(rawTypeOf(type.element));
- } else {
+ } else if (!compiler.world.hasAnySubtype(type.element)) {
mappedType = new TypeMask.nonNullExact(rawTypeOf(type.element));
+ } else {
+ Element element = type.element;
+ Set<ClassElement> subtypes = compiler.world.subtypesOf(element);
+ Set<ClassElement> subclasses = compiler.world.subclassesOf(element);
+ if (subclasses != null && subtypes.length == subclasses.length) {
+ mappedType = new TypeMask.nonNullSubclass(rawTypeOf(element));
+ } else {
+ mappedType = new TypeMask.nonNullSubtype(rawTypeOf(element));
+ }
}
returnType = computeLUB(returnType, mappedType, compiler);
if (!isTypeValuable(returnType)) {
@@ -719,15 +779,18 @@
*/
TypeMask typeOfElement(Element element) {
element = element.implementation;
+ TypeInformation info = typeInformationOf(element);
+ TypeMask type = info.type;
if (isNativeElement(element) && element.isField()) {
- var type = typeOf.putIfAbsent(element, () {
+ if (type == null) {
InterfaceType rawType = element.computeType(compiler).asRaw();
- return rawType.isDynamic ? dynamicType : new TypeMask.subtype(rawType);
- });
+ info.type = type = rawType.isDynamic
+ ? dynamicType
+ : new TypeMask.subtype(rawType);
+ }
assert(type != null);
return type;
}
- TypeMask type = typeOf[element];
if (type == null) {
if ((compiler.trustTypeAnnotations
&& (element.isField()
@@ -739,7 +802,7 @@
&& (element.isField() || element.isVariable()))) {
type = narrowType(dynamicType, element.computeType(compiler), compiler);
} else {
- type = dynamicType;
+ type = info.type = new ElementTypeMask(fetchType, element);
}
}
return type;
@@ -791,9 +854,8 @@
ContainerTypeMask mask = selector.mask;
TypeMask elementType = mask.elementType;
return elementType == null ? dynamicType : elementType;
- } else if (element.isGetter()) {
- // Closure call.
- assert(selector.isCall());
+ } else if (element.isGetter() || element.isField()) {
+ assert(selector.isCall() || selector.isSetter());
return dynamicType;
} else {
return returnTypeOfElement(element);
@@ -811,17 +873,74 @@
assert(caller.isImplementation);
assert(callee.isImplementation);
assert(isNotClosure(caller));
- Set<Element> callers = callersOf.putIfAbsent(
- callee, () => new Set<Element>());
+ Set<Element> callers = typeInformationOf(callee).callers;
callers.add(caller);
}
- bool addArguments(Node node, Element element, ArgumentsTypes arguments) {
- Map<Node, ArgumentsTypes> types = typeOfArguments.putIfAbsent(
- element, () => new Map<Node, ArgumentsTypes>());
- ArgumentsTypes existing = types[node];
- types[node] = arguments;
- return existing != arguments;
+ bool addArguments(Node node,
+ FunctionElement element,
+ ArgumentsTypes arguments) {
+ FunctionTypeInformation info = typeInformationOf(element);
+ if (info.canBeClosurized) return false;
+ // A [noSuchMethod] method can be the target of any call, with
+ // any number of arguments. For simplicity, we just do not
+ // infer any parameter types for [noSuchMethod].
+ if (element.name == Compiler.NO_SUCH_METHOD) return false;
+
+ FunctionSignature signature = element.computeSignature(compiler);
+ int parameterIndex = 0;
+ bool changed = false;
+ bool visitingOptionalParameter = false;
+ signature.forEachParameter((Element parameter) {
+ if (parameter == signature.firstOptionalParameter) {
+ visitingOptionalParameter = true;
+ }
+ TypeMask type;
+ ParameterTypeInformation info = typeInformationOf(parameter);
+ if (!visitingOptionalParameter) {
+ type = arguments.positional[parameterIndex];
+ } else {
+ type = signature.optionalParametersAreNamed
+ ? arguments.named[parameter.name]
+ : parameterIndex < arguments.positional.length
+ ? arguments.positional[parameterIndex]
+ : info.defaultType;
+ }
+ TypeMask oldType = info.assignments[node];
+ info.addAssignment(node, type);
+ changed = changed || (oldType != type);
+ parameterIndex++;
+ });
+ return changed;
+ }
+
+ bool updateParameterType(Element parameter) {
+ FunctionTypeInformation functionInfo =
+ typeInformationOf(parameter.enclosingElement);
+ if (functionInfo.canBeClosurized) return false;
+ if (!isNotClosure(parameter.enclosingElement)) return false;
+
+ ParameterTypeInformation info = typeInformationOf(parameter);
+ TypeMask elementType;
+ info.assignments.forEach((Node node, TypeMask mask) {
+ if (mask == null) {
+ // Now that we know we have analyzed the function holding
+ // [parameter], we have a default type for that [parameter].
+ mask = info.defaultType;
+ info.addAssignment(node, mask);
+ }
+ elementType = computeLubFor(elementType, mask, parameter);
+ });
+ if (elementType == null) {
+ elementType = dynamicType;
+ }
+ return recordType(parameter, elementType);
+ }
+
+ void updateAllParametersOf(FunctionElement function) {
+ function.computeSignature(compiler).forEachParameter((Element parameter) {
+ updateParameterType(parameter);
+ });
}
void updateSideEffects(SideEffects sideEffects,
@@ -865,7 +984,7 @@
Element caller,
Element callee,
ArgumentsTypes arguments,
- Selector constraint,
+ CallSite constraint,
SideEffects sideEffects,
bool inLoop) {
updateSideEffects(sideEffects, selector, callee);
@@ -890,18 +1009,21 @@
assert(isNotClosure(caller));
callee = callee.implementation;
- if (!analyzeCount.containsKey(caller)) {
- addCaller(caller, callee);
- }
+ TypeInformation info = typeInformationOf(callee);
+ info.addCaller(caller);
if (selector.isSetter() && callee.isField()) {
recordNonFinalFieldElementType(
- node, callee, arguments.positional[0], constraint);
+ node,
+ callee,
+ arguments.positional[0],
+ constraint);
return;
} else if (selector.isGetter()) {
assert(arguments == null);
if (callee.isFunction()) {
- methodsThatCanBeClosurized.add(callee);
+ FunctionTypeInformation functionInfo = info;
+ functionInfo.canBeClosurized = true;
}
return;
} else if (callee.isField()) {
@@ -927,74 +1049,37 @@
Element callee) {
if (callee.isField()) {
if (selector.isSetter()) {
- Map<Node, TypeMask> types = typeOfFields[callee];
- if (types == null || !types.containsKey(node)) return;
- types.remove(node);
+ Map<Node, TypeMask> assignments = typeInformationOf(callee).assignments;
+ if (assignments == null || !assignments.containsKey(node)) return;
+ assignments.remove(node);
if (hasAnalyzedAll) updateNonFinalFieldType(callee);
}
} else if (callee.isGetter()) {
return;
} else {
- Map<Node, ArgumentsTypes> types = typeOfArguments[callee];
- if (types == null || !types.containsKey(node)) return;
- types.remove(node);
- if (hasAnalyzedAll) enqueueAgain(callee);
+ FunctionElement element = callee;
+ element.computeSignature(compiler).forEachParameter((Element parameter) {
+ Map<Node, TypeMask> assignments =
+ typeInformationOf(parameter).assignments;
+ if (assignments == null || !assignments.containsKey(node)) return;
+ assignments.remove(node);
+ if (hasAnalyzedAll) enqueueAgain(callee);
+ });
}
}
- /**
- * Computes the parameter types of [element], based on all call sites we
- * have collected on that [element]. This method can only be called after
- * we have analyzed all elements in the world.
- */
- void updateArgumentsType(FunctionElement element) {
- assert(hasAnalyzedAll);
- if (methodsThatCanBeClosurized.contains(element)) return;
- // A [noSuchMethod] method can be the target of any call, with
- // any number of arguments. For simplicity, we just do not
- // infer any parameter types for [noSuchMethod].
- if (element.name == Compiler.NO_SUCH_METHOD) return;
- FunctionSignature signature = element.computeSignature(compiler);
-
- if (typeOfArguments[element] == null || typeOfArguments[element].isEmpty) {
- signature.forEachParameter((Element parameter) {
- typeOf.remove(parameter);
- });
- return;
+ TypeMask computeLubFor(TypeMask firstType,
+ TypeMask secondType,
+ Element element) {
+ if (secondType.isElement) {
+ ElementTypeMask mask = secondType;
+ if (element == mask.element) {
+ // Simple constraint of the abstract form [: foo = foo :], for
+ // example a recursive function passing the same parameter.
+ return firstType;
+ }
}
-
- int parameterIndex = 0;
- bool changed = false;
- bool visitingOptionalParameter = false;
- signature.forEachParameter((Element parameter) {
- if (parameter == signature.firstOptionalParameter) {
- visitingOptionalParameter = true;
- }
- TypeMask type;
- typeOfArguments[element].forEach((_, ArgumentsTypes arguments) {
- if (!visitingOptionalParameter) {
- type = computeLUB(
- type, arguments.positional[parameterIndex], compiler);
- } else {
- TypeMask argumentType = signature.optionalParametersAreNamed
- ? arguments.named[parameter.name]
- : parameterIndex < arguments.positional.length
- ? arguments.positional[parameterIndex]
- : null;
- if (argumentType == null) {
- argumentType = defaultTypeOfParameter[parameter];
- }
- assert(argumentType != null);
- type = computeLUB(type, argumentType, compiler);
- }
- });
- if (recordType(parameter, type)) {
- changed = true;
- }
- parameterIndex++;
- });
-
- if (changed) enqueueAgain(element);
+ return computeLUB(firstType, secondType, compiler);
}
TypeMask handleIntrisifiedSelector(Selector selector,
@@ -1031,7 +1116,7 @@
TypeMask receiverType,
Element caller,
ArgumentsTypes arguments,
- Selector constraint,
+ CallSite constraint,
SideEffects sideEffects,
bool inLoop) {
TypeMask result;
@@ -1080,11 +1165,10 @@
void recordNonFinalFieldElementType(Node node,
Element element,
TypeMask argumentType,
- Selector constraint) {
- Map<Node, TypeMask> map =
- typeOfFields.putIfAbsent(element, () => new Map<Node, TypeMask>());
- map[node] = argumentType;
- bool changed = typeOf[element] != argumentType;
+ CallSite constraint) {
+ TypeInformation info = typeInformationOf(element);
+ info.addAssignment(node, argumentType);
+ bool changed = info.type != argumentType;
if (constraint != null && constraint != setterConstraints[node]) {
changed = true;
setterConstraints[node] = constraint;
@@ -1096,48 +1180,54 @@
}
}
- TypeMask computeFieldTypeWithConstraints(Element element, Map types) {
- Set<Selector> constraints = new Set<Selector>();
- TypeMask fieldType;
+ TypeMask computeTypeWithConstraints(Element element,
+ Map<Node, TypeMask> types) {
+ List<CallSite> constraints = <CallSite>[];
+ TypeMask elementType;
types.forEach((Node node, TypeMask mask) {
- Selector constraint = setterConstraints[node];
+ CallSite constraint = setterConstraints[node];
if (constraint != null) {
// If this update has a constraint, we collect it and don't
// use its type.
constraints.add(constraint);
} else {
- fieldType = computeLUB(fieldType, mask, compiler);
+ elementType = computeLubFor(elementType, mask, element);
}
});
- if (!constraints.isEmpty && !isDynamicType(fieldType)) {
+ if (!constraints.isEmpty && !isDynamicType(elementType)) {
// Now that we have found a type, we go over the collected
// constraints, and make sure they apply to the found type. We
// update [typeOf] to make sure [typeOfSelector] knows the field
// type.
- TypeMask existing = typeOf[element];
- typeOf[element] = fieldType;
+ TypeInformation info = typeInformationOf(element);
+ TypeMask existing = info.type;
+ info.type = elementType;
- for (Selector constraint in constraints) {
- if (constraint.isOperator()) {
+ for (CallSite constraint in constraints) {
+ Selector selector = constraint.selector;
+ TypeMask type;
+ if (selector.isOperator()) {
// If the constraint is on an operator, we type the receiver
// to be the field.
- if (fieldType != null) {
- constraint = new TypedSelector(fieldType, constraint);
+ if (elementType != null) {
+ selector = new TypedSelector(elementType, selector);
}
+ type = handleIntrisifiedSelector(selector, constraint.arguments);
+ if (type == null) type = typeOfSelector(selector);
} else {
// Otherwise the constraint is on the form [: field = other.field :].
- assert(constraint.isGetter());
+ assert(selector.isGetter());
+ type = typeOfSelector(selector);
}
- fieldType = computeLUB(fieldType, typeOfSelector(constraint), compiler);
+ elementType = computeLUB(elementType, type, compiler);
}
- if (existing == null) {
- typeOf.remove(element);
- } else {
- typeOf[element] = existing;
- }
+ info.type = existing;
}
- return fieldType;
+ if (elementType == null) {
+ elementType = new TypeMask.nonNullEmpty();
+ }
+ return elementType;
}
/**
@@ -1149,13 +1239,11 @@
if (isNativeElement(element)) return;
assert(hasAnalyzedAll);
- if (typeOfFields[element] == null || typeOfFields[element].isEmpty) {
- typeOf.remove(element);
- return;
- }
+ TypeInformation info = typeInformationOf(element);
+ Map<Node, TypeMask> assignments = info.assignments;
+ if (assignments.isEmpty) return;
- TypeMask fieldType = computeFieldTypeWithConstraints(
- element, typeOfFields[element]);
+ TypeMask fieldType = computeTypeWithConstraints(element, assignments);
// If the type of [element] has changed, re-analyze its users.
if (recordType(element, fieldType)) {
@@ -1171,7 +1259,7 @@
Element constructor,
Element field,
TypeMask type,
- Selector constraint) {
+ CallSite constraint) {
if (constraint != null) {
setterConstraints[node] = constraint;
}
@@ -1179,9 +1267,8 @@
// being tracked in the [classInfoForFinalFields] map.
if (constructor == field) return;
assert(field.modifiers.isFinal() || field.modifiers.isConst());
- ClassElement cls = constructor.getEnclosingClass();
- ClassInfoForFinalFields info = classInfoForFinalFields[cls.implementation];
- info.recordFinalFieldType(node, constructor, field, type);
+ TypeInformation info = typeInformationOf(field);
+ info.addAssignment(node, type);
}
/**
@@ -1191,23 +1278,26 @@
*/
void doneAnalyzingGenerativeConstructor(Element constructor) {
ClassElement cls = constructor.getEnclosingClass();
- ClassInfoForFinalFields info = classInfoForFinalFields[cls.implementation];
+ ClassTypeInformation info = classInfoForFinalFields[cls.implementation];
info.doneAnalyzingGenerativeConstructor(constructor);
if (info.isDone) {
- updateFinalFieldsType(info);
+ updateFinalFieldsType(info, constructor.getEnclosingClass());
}
}
/**
* Updates types of final fields listed in [info].
*/
- void updateFinalFieldsType(ClassInfoForFinalFields info) {
+ void updateFinalFieldsType(ClassTypeInformation info, ClassElement cls) {
assert(info.isDone);
- info.typesOfFinalFields.forEach((Element field,
- Map<Node, TypeMask> types) {
+ cls.forEachInstanceField((_, Element field) {
if (isNativeElement(field)) return;
- assert(field.modifiers.isFinal());
- TypeMask fieldType = computeFieldTypeWithConstraints(field, types);
+ if (!field.modifiers.isFinal()) return;
+ // If the field is being set at its declaration site, it is not
+ // being tracked in the [classInfoForFinalFields] map.
+ if (field.parseNode(compiler).asSendSet() != null) return;
+ TypeInformation info = typeInformationOf(field);
+ TypeMask fieldType = computeTypeWithConstraints(field, info.assignments);
if (recordType(field, fieldType)) {
enqueueCallersOf(field);
}
@@ -1215,6 +1305,14 @@
}
}
+class CallSite {
+ final Selector selector;
+ final ArgumentsTypes arguments;
+ CallSite(this.selector, this.arguments) {
+ assert(selector != null);
+ }
+}
+
/**
* Placeholder for inferred arguments types on sends.
*/
@@ -1298,16 +1396,16 @@
FunctionElement function = analyzedElement;
if (inferrer.hasAnalyzedAll) {
- inferrer.updateArgumentsType(function);
+ inferrer.updateAllParametersOf(function);
}
FunctionSignature signature = function.computeSignature(compiler);
signature.forEachOptionalParameter((element) {
Node node = element.parseNode(compiler);
Send send = node.asSendSet();
- inferrer.defaultTypeOfParameter[element] = (send == null)
+ ParameterTypeInformation info = inferrer.typeInformationOf(element);
+ info.defaultType = (send == null)
? inferrer.nullType
: visit(send.arguments.head);
- assert(inferrer.defaultTypeOfParameter[element] != null);
});
if (analyzedElement.isNative()) {
@@ -1366,8 +1464,11 @@
visit(node.body);
if (returnType == null) {
// No return in the body.
- returnType = inferrer.nullType;
- } else if (!locals.seenReturn && !inferrer.isDynamicType(returnType)) {
+ returnType = locals.seenReturnOrThrow
+ ? new TypeMask.nonNullEmpty() // Body always throws.
+ : inferrer.nullType;
+ } else if (!locals.seenReturnOrThrow &&
+ !inferrer.isDynamicType(returnType)) {
// We haven't seen returns on all branches. So the method may
// also return null.
returnType = returnType.nullable();
@@ -1394,7 +1495,7 @@
});
// TODO(ngeoffray): Re-analyze method if [changed]?
}
- compiler.world.registerSideEffects(analyzedElement, sideEffects);
+ compiler.world.registerSideEffects(analyzedElement, sideEffects);
assert(breaksFor.isEmpty);
assert(continuesFor.isEmpty);
return returnType;
@@ -1431,11 +1532,25 @@
}
TypeMask visitLiteralList(LiteralList node) {
- node.visitChildren(this);
- if (node.isConst()) return inferrer.constListType;
- return inferrer.concreteTypes.putIfAbsent(
- node, () => new ContainerTypeMask(
- inferrer.growableListType, node, outermostElement));
+ if (node.isConst()) {
+ // We only set the type once. We don't need to re-visit the children
+ // when re-analyzing the node.
+ return inferrer.concreteTypes.putIfAbsent(node, () {
+ ContainerTypeMask container = new ContainerTypeMask(
+ inferrer.constListType, node, outermostElement);
+ TypeMask elementType = new TypeMask.nonNullEmpty();
+ for (Node element in node.elements.nodes) {
+ elementType = computeLUB(elementType, visit(element), compiler);
+ }
+ container.elementType = elementType;
+ return container;
+ });
+ } else {
+ node.visitChildren(this);
+ return inferrer.concreteTypes.putIfAbsent(
+ node, () => new ContainerTypeMask(
+ inferrer.growableListType, node, outermostElement));
+ }
}
bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
@@ -1559,14 +1674,14 @@
node.arguments.head);
} else {
// [: foo++ :] or [: foo += 1 :].
- Selector constraint;
+ ArgumentsTypes operatorArguments = new ArgumentsTypes([rhsType], null);
+ CallSite constraint;
if (!Elements.isLocal(element)) {
// Record a constraint of the form [: field++ :], or [: field += 42 :].
- constraint = operatorSelector;
+ constraint = new CallSite(operatorSelector, operatorArguments);
}
TypeMask getterType;
TypeMask newType;
- ArgumentsTypes operatorArguments = new ArgumentsTypes([rhsType], null);
if (Elements.isStaticOrTopLevelField(element)) {
Element getterElement = elements[node.selector];
getterType =
@@ -1613,7 +1728,7 @@
TypeMask receiverType,
TypeMask rhsType,
Node rhs) {
- Selector constraint;
+ CallSite constraint;
if (node.asSend() != null && !Elements.isLocal(element)) {
// Recognize a constraint of the form [: field = other.field :].
// Note that we check if the right hand side is a local to
@@ -1626,7 +1741,7 @@
&& !Elements.isLocal(elements[rhs])
&& send.selector.asIdentifier().source
== node.asSend().selector.asIdentifier().source) {
- constraint = elements.getSelector(rhs);
+ constraint = new CallSite(elements.getSelector(rhs), null);
}
}
ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
@@ -1697,7 +1812,8 @@
return inferrer.concreteTypes.putIfAbsent(
node, () => new ContainerTypeMask(
inferrer.growableListType, node, outermostElement));
- } else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
+ } else if (Elements.isFixedListConstructorCall(element, node, compiler)
+ || Elements.isFilledListConstructorCall(element, node, compiler)) {
return inferrer.concreteTypes.putIfAbsent(
node, () => new ContainerTypeMask(
inferrer.fixedListType, node, outermostElement));
@@ -1825,7 +1941,7 @@
Selector selector,
TypeMask receiver,
ArgumentsTypes arguments,
- [Selector constraint]) {
+ [CallSite constraint]) {
if (selector.mask != receiver) {
selector = inferrer.isDynamicType(receiver)
? selector.asUntyped
@@ -1862,7 +1978,7 @@
}
void recordReturnType(TypeMask type) {
- returnType = computeLUB(returnType, type, compiler);
+ returnType = inferrer.computeLubFor(returnType, type, analyzedElement);
}
TypeMask visitReturn(Return node) {
@@ -1901,7 +2017,7 @@
? inferrer.nullType
: expression.accept(this));
}
- locals.seenReturn = true;
+ locals.seenReturnOrThrow = true;
return inferrer.dynamicType;
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
index e53cc0a..334b520 100644
--- a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
@@ -47,8 +47,11 @@
bool get isEmpty;
bool get isNullable;
bool get isExact;
+
bool get isUnion;
bool get isContainer;
+ bool get isForwarding;
+ bool get isElement;
bool containsOnlyInt(Compiler compiler);
bool containsOnlyDouble(Compiler compiler);
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index d260746..6db7670 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -18,7 +18,9 @@
part 'concrete_types_inferrer.dart';
part 'container_type_mask.dart';
+part 'element_type_mask.dart';
part 'flat_type_mask.dart';
+part 'forwarding_type_mask.dart';
part 'type_mask.dart';
part 'union_type_mask.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
index 357486b..8f1a4ff 100644
--- a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
@@ -20,23 +20,23 @@
return new UnionTypeMask._(disjoint);
}
+ static TypeMask nonForwardingMask(mask) {
+ while (mask.isForwarding) mask = mask.forwardTo;
+ return mask;
+ }
+
static void unionOfHelper(Iterable<TypeMask> masks,
List<FlatTypeMask> disjoint,
Compiler compiler) {
for (TypeMask mask in masks) {
+ mask = nonForwardingMask(mask);
if (mask.isUnion) {
UnionTypeMask union = mask;
unionOfHelper(union.disjointMasks, disjoint, compiler);
} else if (mask.isEmpty && !mask.isNullable) {
continue;
} else {
- FlatTypeMask flatMask;
- if (mask.isContainer) {
- ContainerTypeMask container = mask;
- flatMask = container.asFlat;
- } else {
- flatMask = mask;
- }
+ FlatTypeMask flatMask = mask;
assert(flatMask.base == null
|| flatMask.base.element != compiler.dynamicClass);
int inListIndex = -1;
@@ -146,7 +146,7 @@
}
TypeMask union(var other, Compiler compiler) {
- if (other.isContainer) other = other.asFlat;
+ other = nonForwardingMask(other);
if (!other.isUnion && disjointMasks.contains(other)) return this;
List<FlatTypeMask> newList =
@@ -161,7 +161,7 @@
}
TypeMask intersection(var other, Compiler compiler) {
- if (other.isContainer) other = other.asFlat;
+ other = nonForwardingMask(other);
if (!other.isUnion && disjointMasks.contains(other)) return other;
List<TypeMask> intersections = <TypeMask>[];
@@ -198,6 +198,8 @@
bool get isExact => false;
bool get isUnion => true;
bool get isContainer => false;
+ bool get isForwarding => false;
+ bool get isElement => false;
bool containsOnlyInt(Compiler compiler) => false;
bool containsOnlyDouble(Compiler compiler) => false;
diff --git a/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart b/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart
deleted file mode 100644
index 29e705c..0000000
--- a/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-part of universe;
-
-class SelectorMap<T> {
- final Compiler compiler;
- final Map<SourceString, SelectorMapNode<T>> nodes =
- new Map<SourceString, SelectorMapNode<T>>();
- SelectorMap(this.compiler);
-
- T operator [](Selector selector) {
- SourceString name = selector.name;
- SelectorMapNode node = nodes[name];
- return (node != null)
- ? node.lookup(selector)
- : null;
- }
-
- void operator []=(Selector selector, T value) {
- SourceString name = selector.name;
- SelectorMapNode node = nodes.putIfAbsent(
- name, () => new SelectorMapNode(name));
- node.update(selector, value);
- }
-
- bool containsKey(Selector selector) {
- SourceString name = selector.name;
- SelectorMapNode node = nodes[name];
- return (node != null)
- ? node.containsKey(selector)
- : false;
- }
-
- T remove(Selector selector) {
- SourceString name = selector.name;
- SelectorMapNode node = nodes[name];
- return (node != null)
- ? node.remove(selector)
- : null;
- }
-
- /**
- * Visits all mappings for selectors that may be used to invoke the
- * given [member] element. If the [visit] function ever returns false,
- * we abort the traversal early.
- */
- void visitMatching(Element member, bool visit(Selector selector, T value)) {
- assert(member.isMember());
- SourceString name = member.name;
- SelectorMapNode node = nodes[name];
- if (node != null) {
- node.visitMatching(member, compiler, visit);
- }
- }
-}
-
-class SelectorMapNode<T> {
- final SourceString name;
- final Map<Selector, T> selectors = new Map<Selector, T>();
-
- // We start caching which selectors match which elements when the
- // number of different selectors exceed a threshold. This way we
- // avoid lots of repeated calls to the Selector.applies method.
- static const int MAX_SELECTORS_NO_CACHE = 8;
- Map<Element, List<Selector>> cache;
-
- SelectorMapNode(this.name);
-
- T lookup(Selector selector) {
- assert(selector.name == name);
- return selectors[selector];
- }
-
- void update(Selector selector, T value) {
- assert(selector.name == name);
- bool existing = selectors.containsKey(selector);
- selectors[selector] = value;
- if (existing) return;
- // The update has introduced a new selector in the map, so we need
- // to consider if we should start caching. At the very least, we
- // have to clear the cache because the new element may invalidate
- // existing cache entries.
- if (cache == null) {
- if (selectors.length > MAX_SELECTORS_NO_CACHE) {
- cache = new Map<Element, List<Selector>>();
- }
- } else if (!cache.isEmpty) {
- cache.clear();
- }
- }
-
- bool containsKey(Selector selector) {
- assert(selector.name == name);
- return selectors.containsKey(selector);
- }
-
- T remove(Selector selector) {
- assert(selector.name == name);
- if (!selectors.containsKey(selector)) return null;
- if (cache != null && !cache.isEmpty) cache.clear();
- return selectors.remove(selector);
- }
-
- void visitMatching(Element member, Compiler compiler,
- bool visit(Selector selector, T value)) {
- assert(member.name == name);
- Iterable<Selector> matching = computeMatching(member, compiler);
- for (Selector selector in matching) {
- if (!visit(selector, selectors[selector])) return;
- }
- }
-
- Iterable<Selector> computeMatching(Element member, Compiler compiler) {
- // Probe the cache if it exists. Do this before creating the
- // matching iterable to cut down on the overhead for cache hits.
- if (cache != null) {
- List<Selector> cached = cache[member];
- if (cached != null) return cached;
- }
- // Filter the selectors keys so we only have the ones that apply
- // to the given member element.
- Iterable<Selector> matching = selectors.keys.where(
- (Selector selector) => selector.appliesUnnamed(member, compiler));
- if (cache == null) return matching;
- return cache[member] = matching.toList();
- }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index ae3b54b..c366000 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -14,7 +14,6 @@
import '../js/js.dart' as js;
part 'function_set.dart';
-part 'selector_map.dart';
part 'side_effects.dart';
class Universe {
@@ -50,6 +49,20 @@
final Set<Element> fieldSetters;
final Set<DartType> isChecks;
+ /**
+ * Set of [:call:] methods in instantiated classes that use type variables
+ * in their signature.
+ */
+ final Set<Element> genericCallMethods;
+
+ /**
+ * Set of methods in instantiated classes that use type variables in their
+ * signature and have potentially been closurized.
+ */
+ final Set<Element> closurizedGenericMembers;
+
+ final Set<Element> closurizedMembers;
+
bool usingFactoryWithTypeArguments = false;
Universe() : instantiatedClasses = new Set<ClassElement>(),
@@ -60,7 +73,10 @@
invokedSetters = new Map<SourceString, Set<Selector>>(),
fieldGetters = new Set<Element>(),
fieldSetters = new Set<Element>(),
- isChecks = new Set<DartType>();
+ isChecks = new Set<DartType>(),
+ genericCallMethods = new Set<Element>(),
+ closurizedGenericMembers = new Set<Element>(),
+ closurizedMembers = new Set<Element>();
bool hasMatchingSelector(Set<Selector> selectors,
Element member,
@@ -91,6 +107,15 @@
bool hasFieldSetter(Element member, Compiler compiler) {
return fieldSetters.contains(member);
}
+
+ DartType registerIsCheck(DartType type, Compiler compiler) {
+ type = type.unalias(compiler);
+ // Even in checked mode, type annotations for return type and argument
+ // types do not imply type checks, so there should never be a check
+ // against the type variable of a typedef.
+ isChecks.add(type);
+ return type;
+ }
}
class SelectorKind {
diff --git a/sdk/lib/_internal/compiler/implementation/util/expensive_map.dart b/sdk/lib/_internal/compiler/implementation/util/expensive_map.dart
new file mode 100644
index 0000000..735284f
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/util/expensive_map.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of dart2js.util;
+
+/**
+ * The expensive map is a data structure useful for tracking down
+ * excessive memory usage due to large maps. It acts as an ordinary
+ * hash map, but it uses 10 times more memory (by default).
+ */
+class ExpensiveMap<K, V> implements LinkedHashMap<K, V> {
+
+ final List _maps;
+
+ ExpensiveMap([int copies = 10]) : _maps = new List(copies) {
+ assert(copies > 0);
+ for (int i = 0; i < _maps.length; i++) {
+ _maps[i] = new LinkedHashMap<K, V>();
+ }
+ }
+
+ int get length => _maps[0].length;
+ bool get isEmpty => _maps[0].isEmpty;
+ bool get isNotEmpty => _maps[0].isNotEmpty;
+
+ Iterable<K> get keys => _maps[0].keys;
+ Iterable<V> get values => _maps[0].values;
+
+ bool containsKey(K key) => _maps[0].containsKey(key);
+ bool containsValue(V value) => _maps[0].containsValue(value);
+
+ V operator[](K key) => _maps[0][key];
+
+ void forEach(void action(K key, V value)) {
+ _maps[0].forEach(action);
+ }
+
+ void operator[]=(K key, V value) {
+ for (int i = 0; i < _maps.length; i++) {
+ _maps[i][key] = value;
+ }
+ }
+
+ V putIfAbsent(K key, V ifAbsent()) {
+ if (containsKey(key)) return this[key];
+ V value = ifAbsent();
+ this[key] = value;
+ return value;
+ }
+
+ void addAll(Map<K, V> other) {
+ for (int i = 0; i < _maps.length; i++) {
+ _maps[i].addAll(other);
+ }
+ }
+
+ void remove(Object key) {
+ for (int i = 0; i < _maps.length; i++) {
+ _maps[i].remove(key);
+ }
+ }
+
+ void clear() {
+ for (int i = 0; i < _maps.length; i++) {
+ _maps[i].clear();
+ }
+ }
+
+ String toString() => "expensive(${_maps[0]}x${_maps.length})";
+}
diff --git a/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart b/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart
new file mode 100644
index 0000000..477eb4c
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/util/expensive_set.dart
@@ -0,0 +1,121 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+part of dart2js.util;
+
+/**
+ * The expensive set is a data structure useful for tracking down
+ * excessive memory usage due to large sets. It acts as an ordinary
+ * hash set, but it uses 10 times more memory (by default).
+ */
+class ExpensiveSet<E> extends IterableBase<E> implements LinkedHashSet<E> {
+
+ final List _sets;
+
+ ExpensiveSet([int copies = 10]) : _sets = new List(copies) {
+ assert(copies > 0);
+ for (int i = 0; i < _sets.length; i++) {
+ _sets[i] = new LinkedHashSet<E>();
+ }
+ }
+
+ int get length => _sets[0].length;
+ bool get isEmpty => _sets[0].isEmpty;
+ bool get isNotEmpty => _sets[0].isNotEmpty;
+
+ Iterator<E> get iterator => _sets[0].iterator;
+
+ bool contains(Object object) => _sets[0].contains(object);
+
+ void forEach(void action(E element)) {
+ _sets[0].forEach(action);
+ }
+
+ void add(E element) {
+ for (int i = 0; i < _sets.length; i++) {
+ _sets[i].add(element);
+ }
+ }
+
+ void addAll(Iterable<E> objects) {
+ for (E each in objects) {
+ add(each);
+ }
+ }
+
+ bool remove(Object object) {
+ bool result = _sets[0].remove(object);
+ for (int i = 1; i < _sets.length; i++) {
+ _sets[i].remove(object);
+ }
+ return result;
+ }
+
+ void clear() {
+ for (int i = 0; i < _sets.length; i++) {
+ _sets[i].clear();
+ }
+ }
+
+ void removeAll(Iterable<Object> objectsToRemove) {
+ for (var each in objectsToRemove) {
+ remove(each);
+ }
+ }
+
+ void removeWhere(bool test(E element)) {
+ removeAll(this.toList().where((e) => test(e)));
+ }
+
+ void retainWhere(bool test(E element)) {
+ removeAll(toList().where((e) => !test(e)));
+ }
+
+ bool containsAll(Iterable<Object> other) {
+ for (Object object in other) {
+ if (!this.contains(object)) return false;
+ }
+ return true;
+ }
+
+ Set _newSet() => new ExpensiveSet(_sets.length);
+
+ Set<E> intersection(Set<Object> other) {
+ Set<E> result = _newSet();
+ if (other.length < this.length) {
+ for (var element in other) {
+ if (this.contains(element)) result.add(element);
+ }
+ } else {
+ for (E element in this) {
+ if (other.contains(element)) result.add(element);
+ }
+ }
+ return result;
+ }
+
+ Set<E> union(Set<E> other) {
+ return _newSet()..addAll(this)..addAll(other);
+ }
+
+ Set<E> difference(Set<E> other) {
+ Set<E> result = _newSet();
+ for (E element in this) {
+ if (!other.contains(element)) result.add(element);
+ }
+ return result;
+ }
+
+ void retainAll(Iterable objectsToRetain) {
+ Set retainSet;
+ if (objectsToRetain is Set) {
+ retainSet = objectsToRetain;
+ } else {
+ retainSet = objectsToRetain.toSet();
+ }
+ retainWhere(retainSet.contains);
+ }
+
+ String toString() => "expensive(${_sets[0]}x${_sets.length})";
+}
diff --git a/sdk/lib/_internal/compiler/implementation/util/link.dart b/sdk/lib/_internal/compiler/implementation/util/link.dart
index 29bc4c6..f46af2d 100644
--- a/sdk/lib/_internal/compiler/implementation/util/link.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/link.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-part of org_dartlang_compiler_util;
+part of dart2js.util;
class Link<T> {
T get head => null;
@@ -107,7 +107,12 @@
abstract class LinkBuilder<T> {
factory LinkBuilder() = LinkBuilderImplementation;
- Link<T> toLink();
+ /**
+ * Prepends all elements added to the builder to [tail]. The resulting list is
+ * returned and the builder is cleared.
+ */
+ Link<T> toLink([Link<T> tail = const Link()]);
+
void addLast(T t);
final int length;
diff --git a/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart b/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
index 4b0a618..6743738 100644
--- a/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/link_implementation.dart
@@ -110,9 +110,9 @@
LinkBuilderImplementation();
- Link<T> toLink() {
- if (head == null) return const Link();
- lastLink.tail = const Link();
+ Link<T> toLink([Link<T> tail = const Link()]) {
+ if (head == null) return tail;
+ lastLink.tail = tail;
Link<T> link = head;
lastLink = null;
head = null;
diff --git a/sdk/lib/_internal/compiler/implementation/util/util.dart b/sdk/lib/_internal/compiler/implementation/util/util.dart
index c9c0e66..94a0ce0 100644
--- a/sdk/lib/_internal/compiler/implementation/util/util.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/util.dart
@@ -2,13 +2,15 @@
// 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.
-library org_dartlang_compiler_util;
+library dart2js.util;
import "dart:collection";
import 'util_implementation.dart';
import 'characters.dart';
part 'link.dart';
+part 'expensive_map.dart';
+part 'expensive_set.dart';
/**
* Tagging interface for classes from which source spans can be generated.
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 5425bd1..8f9b9cb 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -26,6 +26,8 @@
'additional argument');
static const NAMED_ARGUMENT_NOT_FOUND = const MessageKind(
"no named argument '#{argumentName}' found on method");
+ static const MEMBER_NOT_FOUND = const MessageKind(
+ 'no member named #{memberName} in class #{className}');
static const METHOD_NOT_FOUND = const MessageKind(
'no method named #{memberName} in class #{className}');
static const OPERATOR_NOT_FOUND = const MessageKind(
@@ -163,6 +165,8 @@
static const TYPE_VARIABLE_WITHIN_STATIC_MEMBER = const MessageKind(
'cannot refer to type variable #{typeVariableName} '
'within a static member');
+ static const TYPE_VARIABLE_IN_CONSTANT = const MessageKind(
+ 'Error: cannot refer to type variable in constant');
static const INVALID_USE_OF_SUPER = const MessageKind(
'super not allowed here');
diff --git a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
index c0fdf6e..2e42264 100644
--- a/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/bin/dartdoc.dart
@@ -207,14 +207,14 @@
final entrypoints = <Uri>[];
try {
- final option = argParser.parse(args);
+ final option = argParser.parse(args, allowTrailingOptions: true);
// This checks to see if the root of all entrypoints is the same.
// If it is not, then we display a warning, as package imports might fail.
var entrypointRoot;
for (final entrypoint in option.rest) {
var uri = Uri.parse(entrypoint);
- if (uri.scheme == '') uri = pathToFileUri(entrypoint);
+ if (uri.scheme == '') uri = path.toUri(entrypoint);
entrypoints.add(uri);
if (uri.scheme != 'file') continue;
@@ -274,7 +274,7 @@
orElse: () => null);
if (fileEntrypoint == null) return;
- var script = path.normalize(path.absolute(fileUriToPath(fileEntrypoint)));
+ var script = path.normalize(path.absolute(path.fromUri(fileEntrypoint)));
var dir = path.join(path.dirname(script), 'packages/');
if (new Directory(dir).existsSync()) return dir;
diff --git a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
index 7d5eba0..0274875 100644
--- a/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
+++ b/sdk/lib/_internal/dartdoc/lib/dartdoc.dart
@@ -71,7 +71,7 @@
// TODO(johnniwinther): Convert to final (lazily initialized) variables when
// the feature is supported.
Path get scriptDir =>
- new Path(new Options().script).directoryPath;
+ new Path(Platform.script).directoryPath;
/**
* Deletes and recreates the output directory at [path] if it exists.
@@ -434,7 +434,7 @@
_exports = new ExportMap.parse(libraryList, packageRoot);
var librariesToAnalyze = _exports.allExportedFiles.toList();
librariesToAnalyze.addAll(libraryList.map((uri) {
- if (uri.scheme == 'file') return fileUriToPath(uri);
+ if (uri.scheme == 'file') return pathos.fromUri(uri);
// dart2js takes "dart:*" URIs as Path objects for some reason.
return uri.toString();
}));
@@ -771,11 +771,11 @@
/// Whether dartdoc is running from within the Dart SDK or the
/// Dart source repository.
bool get runningFromSdk =>
- pathos.extension(new Options().script) == '.snapshot';
+ pathos.extension(Platform.script) == '.snapshot';
/// Gets the path to the root directory of the SDK.
String get sdkDir =>
- pathos.dirname(pathos.dirname(new Options().executable));
+ pathos.dirname(pathos.dirname(Platform.executable));
/// Gets the path to the dartdoc directory normalized for running in different
/// places.
@@ -799,9 +799,8 @@
'''library client;
import 'dart:html';
import 'dart:json';
- import r'${pathToFileUri(
- pathos.join(clientDir, 'client-shared.dart'))}';
- import r'${pathToFileUri(pathos.join(clientDir, 'dropdown.dart'))}';
+ import r'${pathos.toUri(pathos.join(clientDir, 'client-shared.dart'))}';
+ import r'${pathos.toUri(pathos.join(clientDir, 'dropdown.dart'))}';
main() {
setup();
diff --git a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
index 4b95669..425deaf 100644
--- a/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
+++ b/sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart
@@ -96,7 +96,7 @@
* If a URI cannot be converted, this will return `null`.
*/
String importUriToPath(Uri uri, {String basePath, String packageRoot}) {
- if (uri.scheme == 'file') return fileUriToPath(uri);
+ if (uri.scheme == 'file') return pathos.fromUri(uri);
if (basePath != null && uri.scheme == '') {
return pathos.normalize(pathos.absolute(pathos.join(basePath, uri.path)));
@@ -111,36 +111,6 @@
return null;
}
-/** Converts a `file:` [Uri] to a local path string. */
-String fileUriToPath(Uri uri) {
- if (uri.scheme != 'file') {
- throw new ArgumentError("Uri $uri must have scheme 'file:'.");
- }
- if (Platform.operatingSystem != 'windows') return uri.path;
- if (uri.path.startsWith("/")) {
- // Drive-letter paths look like "file:///C:/path/to/file". The replaceFirst
- // removes the extra initial slash.
- return uri.path.replaceFirst("/", "").replaceAll("/", "\\");
- } else {
- // Network paths look like "file://hostname/path/to/file".
- return "\\\\${uri.path.replaceAll("/", "\\")}";
- }
-}
-
-/** Converts a local path string to a `file:` [Uri]. */
-Uri pathToFileUri(String pathString) {
- pathString = pathos.absolute(pathString);
- if (Platform.operatingSystem != 'windows') {
- return Uri.parse('file://$pathString');
- } else if (pathos.rootPrefix(pathString).startsWith('\\\\')) {
- // Network paths become "file://hostname/path/to/file".
- return Uri.parse('file:${pathString.replaceAll("\\", "/")}');
- } else {
- // Drive-letter paths become "file:///C:/path/to/file".
- return Uri.parse('file:///${pathString.replaceAll("\\", "/")}');
- }
-}
-
/**
* If [map] contains an [Export] under [key], this merges that with [export].
* Otherwise, it sets [key] to [export].
diff --git a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
index 60eb3ac..d3936c5 100644
--- a/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/dartdoc_test.dart
@@ -194,7 +194,7 @@
/// The path to the root directory of the dartdoc entrypoint.
String get _dartdocDir {
- var dir = path.absolute(new Options().script);
+ var dir = path.absolute(Platform.script);
while (path.basename(dir) != 'dartdoc') {
if (!path.absolute(dir).contains('dartdoc') || dir == path.dirname(dir)) {
fail('Unable to find root dartdoc directory.');
@@ -217,7 +217,7 @@
// is in the build output directory. We can find that directory relative to
// the Dart executable, but that could be in one of two places: in
// "$BUILD/dart" or "$BUILD/dart-sdk/bin/dart".
- var executableDir = path.dirname(new Options().executable);
+ var executableDir = path.dirname(Platform.executable);
if (new Directory(path.join(executableDir, 'dart-sdk')).existsSync()) {
// The executable is in "$BUILD/dart".
return path.absolute(path.join(executableDir, 'packages'));
@@ -230,7 +230,7 @@
/// Runs dartdoc with the libraryPaths provided, and completes to dartdoc's
/// ProcessResult.
Future<ProcessResult> _runDartdoc(List<String> libraryPaths) {
- var dartBin = new Options().executable;
+ var dartBin = Platform.executable;
var dartdoc = path.join(_dartdocDir, 'bin/dartdoc.dart');
diff --git a/sdk/lib/_internal/dartdoc/test/export_map_test.dart b/sdk/lib/_internal/dartdoc/test/export_map_test.dart
index 7d271d8..badb755 100644
--- a/sdk/lib/_internal/dartdoc/test/export_map_test.dart
+++ b/sdk/lib/_internal/dartdoc/test/export_map_test.dart
@@ -373,8 +373,7 @@
ExportMap parse(List<String> libraries) {
return new ExportMap.parse(
- libraries.map(libPath)
- .map(pathToFileUri),
+ libraries.map(libPath).map(pathos.toUri),
pathos.join(tempDir, 'packages'));
}
diff --git a/sdk/lib/_internal/lib/collection_patch.dart b/sdk/lib/_internal/lib/collection_patch.dart
index 803c97e..3fb0f45 100644
--- a/sdk/lib/_internal/lib/collection_patch.dart
+++ b/sdk/lib/_internal/lib/collection_patch.dart
@@ -40,7 +40,7 @@
return keys.map((each) => this[each]);
}
- patch bool containsKey(K key) {
+ patch bool containsKey(Object key) {
if (_isStringKey(key)) {
var strings = _strings;
return (strings == null) ? false : _hasTableEntry(strings, key);
@@ -55,7 +55,7 @@
}
}
- patch bool containsValue(V value) {
+ patch bool containsValue(Object value) {
return _computeKeys().any((each) => this[each] == value);
}
@@ -65,7 +65,7 @@
});
}
- patch V operator[](K key) {
+ patch V operator[](Object key) {
if (_isStringKey(key)) {
var strings = _strings;
return (strings == null) ? null : _getTableEntry(strings, key);
@@ -119,7 +119,7 @@
return value;
}
- patch V remove(K key) {
+ patch V remove(Object key) {
if (_isStringKey(key)) {
return _removeHashTableEntry(_strings, key);
} else if (_isNumericKey(key)) {
@@ -319,7 +319,7 @@
return new HashMapKeyIterator<E>(_map, _map._computeKeys());
}
- bool contains(E element) {
+ bool contains(Object element) {
return _map.containsKey(element);
}
@@ -403,7 +403,7 @@
return keys.map((each) => this[each]);
}
- patch bool containsKey(K key) {
+ patch bool containsKey(Object key) {
if (_isStringKey(key)) {
var strings = _strings;
if (strings == null) return false;
@@ -422,7 +422,7 @@
}
}
- patch bool containsValue(V value) {
+ patch bool containsValue(Object value) {
return keys.any((each) => this[each] == value);
}
@@ -432,7 +432,7 @@
});
}
- patch V operator[](K key) {
+ patch V operator[](Object key) {
if (_isStringKey(key)) {
var strings = _strings;
if (strings == null) return null;
@@ -491,7 +491,7 @@
return value;
}
- patch V remove(K key) {
+ patch V remove(Object key) {
if (_isStringKey(key)) {
return _removeHashTableEntry(_strings, key);
} else if (_isNumericKey(key)) {
@@ -673,7 +673,7 @@
return new LinkedHashMapKeyIterator<E>(_map, _map._modifications);
}
- bool contains(E element) {
+ bool contains(Object element) {
return _map.containsKey(element);
}
@@ -819,7 +819,7 @@
}
}
- patch void removeAll(Iterable objectsToRemove) {
+ patch void removeAll(Iterable<Object> objectsToRemove) {
for (var each in objectsToRemove) {
remove(each);
}
diff --git a/sdk/lib/_internal/lib/foreign_helper.dart b/sdk/lib/_internal/lib/foreign_helper.dart
index 3cfe86a..55e99a1 100644
--- a/sdk/lib/_internal/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/lib/foreign_helper.dart
@@ -34,10 +34,6 @@
* [typeDescription] has several extensions to help describe the behavior more
* accurately. In addition to the union type already described:
*
- * + `=List` is the JavaScript array type. This is more precise than `List`,
- * which includes about fifty DOM types that also implement the List
- * interface.
- *
* + `=Object` is a plain JavaScript object. Some DOM methods return instances
* that have no corresponing Dart type (e.g. cross-frame documents),
* `=Object` can be used to describe these untyped' values.
@@ -47,9 +43,6 @@
*
* Examples:
*
- * // Create a JavaScript Array.
- * List a = JS('=List', 'new Array(#)', length);
- *
* // Parent window might be an opaque cross-frame window.
* var thing = JS('=Object|Window', '#.parent', myWindow);
*
@@ -161,6 +154,9 @@
/// Returns the name of the class `Object` in the generated code.
String JS_OBJECT_CLASS_NAME() {}
+/// Returns the name of the class `Function` in the generated code.
+String JS_FUNCTION_CLASS_NAME() {}
+
/**
* Returns the field name used for determining if an object or its
* interceptor has JavaScript indexing behavior.
@@ -171,3 +167,44 @@
* Returns the object corresponding to Namer.CURRENT_ISOLATE.
*/
JS_CURRENT_ISOLATE() {}
+
+/// Returns the name used for generated function types on classes and methods.
+String JS_SIGNATURE_NAME() {}
+
+/// Returns the name used to tag function type representations in JavaScript.
+String JS_FUNCTION_TYPE_TAG() {}
+
+/**
+ * Returns the name used to tag void return in function type representations
+ * in JavaScript.
+ */
+String JS_FUNCTION_TYPE_VOID_RETURN_TAG() {}
+
+/**
+ * Returns the name used to tag return types in function type representations
+ * in JavaScript.
+ */
+String JS_FUNCTION_TYPE_RETURN_TYPE_TAG() {}
+
+/**
+ * Returns the name used to tag required parameters in function type
+ * representations in JavaScript.
+ */
+String JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG() {}
+
+/**
+ * Returns the name used to tag optional parameters in function type
+ * representations in JavaScript.
+ */
+String JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG() {}
+
+/**
+ * Returns the name used to tag named parameters in function type
+ * representations in JavaScript.
+ */
+String JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG() {}
+
+/**
+ * Returns the global object, usually called encoded as [: $ :].
+ */
+JS_GLOBAL_OBJECT() {}
diff --git a/sdk/lib/_internal/lib/io_patch.dart b/sdk/lib/_internal/lib/io_patch.dart
index 25df301..4967d94 100644
--- a/sdk/lib/_internal/lib/io_patch.dart
+++ b/sdk/lib/_internal/lib/io_patch.dart
@@ -168,6 +168,9 @@
patch static _environment() {
throw new UnsupportedError("Platform._environment");
}
+ patch static String _version() {
+ throw new UnsupportedError("Platform._version");
+ }
}
patch class _ProcessUtils {
@@ -191,6 +194,7 @@
List<String> arguments,
{String workingDirectory,
Map<String, String> environment,
+ bool includeParentEnvironment: true,
bool runInShell: false}) {
throw new UnsupportedError("Process.start");
}
@@ -200,6 +204,7 @@
List<String> arguments,
{String workingDirectory,
Map<String, String> environment,
+ bool includeParentEnvironment: true,
bool runInShell: false,
Encoding stdoutEncoding: Encoding.SYSTEM,
Encoding stderrEncoding: Encoding.SYSTEM}) {
@@ -226,6 +231,15 @@
}
}
+patch class NetworkInterface {
+ patch static Future<List<NetworkInterface>> list({
+ bool includeLoopback: false,
+ bool includeLinkLocal: false,
+ InternetAddressType type: InternetAddressType.ANY}) {
+ throw new UnsupportedError("NetworkInterface.list");
+ }
+}
+
patch class RawServerSocket {
patch static Future<RawServerSocket> bind(address,
int port,
@@ -272,6 +286,9 @@
patch factory _SecureFilter() {
throw new UnsupportedError("_SecureFilter._SecureFilter");
}
+ patch static SendPort _newServicePort() {
+ throw new UnsupportedError("_SecureFilter._newServicePort");
+ }
}
patch class _StdIOUtils {
@@ -306,9 +323,3 @@
throw new UnsupportedError("newZLibInflateFilter");
}
}
-
-patch class _OptionsImpl {
- patch String get version {
- throw new UnsupportedError("_OptionsImpl.version");
- }
-}
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index 3743ad0..47df338 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -16,6 +16,7 @@
JS_CURRENT_ISOLATE,
JS_SET_CURRENT_ISOLATE,
IsolateContext;
+import 'dart:_interceptors' show JSExtendableArray;
ReceivePort lazyPort;
@@ -455,14 +456,14 @@
r'new RegExp("^ *at [^(]*\\((.*):[0-9]*:[0-9]*\\)$", "m")');
- matches = JS('=List|Null', '#.match(#)', stack, pattern);
+ matches = JS('JSExtendableArray|Null', '#.match(#)', stack, pattern);
if (matches != null) return JS('String', '#[1]', matches);
// This pattern matches Firefox stack traces that look like this:
// methodName@URI:LINE
pattern = JS('', r'new RegExp("^[^@]*@(.*):[0-9]*$", "m")');
- matches = JS('=List|Null', '#.match(#)', stack, pattern);
+ matches = JS('JSExtendableArray|Null', '#.match(#)', stack, pattern);
if (matches != null) return JS('String', '#[1]', matches);
throw new UnsupportedError('Cannot extract URI from "$stack"');
diff --git a/sdk/lib/_internal/lib/js_array.dart b/sdk/lib/_internal/lib/js_array.dart
index 40ce9fa..d3f3551 100644
--- a/sdk/lib/_internal/lib/js_array.dart
+++ b/sdk/lib/_internal/lib/js_array.dart
@@ -143,11 +143,11 @@
return IterableMixinWorkaround.fold(this, initialValue, combine);
}
- E firstWhere(bool test(E value), {E orElse()}) {
+ dynamic firstWhere(bool test(E value), {Object orElse()}) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- E lastWhere(bool test(E value), {E orElse()}) {
+ dynamic lastWhere(bool test(E value), {Object orElse()}) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -175,7 +175,7 @@
}
// TODO(ngeoffray): Parameterize the return value.
if (start == end) return [];
- return JS('=List', r'#.slice(#, #)', this, start, end);
+ return JS('JSExtendableArray', r'#.slice(#, #)', this, start, end);
}
@@ -242,17 +242,17 @@
IterableMixinWorkaround.sortList(this, compare);
}
- int indexOf(E element, [int start = 0]) {
+ int indexOf(Object element, [int start = 0]) {
return IterableMixinWorkaround.indexOfList(this, element, start);
}
- int lastIndexOf(E element, [int start]) {
+ int lastIndexOf(Object element, [int start]) {
return IterableMixinWorkaround.lastIndexOfList(this, element, start);
}
- bool contains(E other) {
+ bool contains(Object other) {
for (int i = 0; i < length; i++) {
- if (other == this[i]) return true;
+ if (this[i] == other) return true;
}
return false;
}
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index cd4e627..fadb984 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -11,13 +11,24 @@
JS_CURRENT_ISOLATE,
JS_CURRENT_ISOLATE_CONTEXT,
JS_DART_OBJECT_CONSTRUCTOR,
+ JS_FUNCTION_CLASS_NAME,
JS_IS_INDEXABLE_FIELD_NAME,
JS_OBJECT_CLASS_NAME,
JS_OPERATOR_AS_PREFIX,
JS_OPERATOR_IS_PREFIX,
+ JS_GLOBAL_OBJECT,
+ JS_SIGNATURE_NAME,
+ JS_HAS_EQUALS,
+ JS_FUNCTION_TYPE_TAG,
+ JS_FUNCTION_TYPE_VOID_RETURN_TAG,
+ JS_FUNCTION_TYPE_RETURN_TYPE_TAG,
+ JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG,
+ JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG,
+ JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG,
RAW_DART_FUNCTION_REF;
import 'dart:_interceptors';
-import "dart:_collection-dev" as _symbol_dev;
+import 'dart:_collection-dev' as _symbol_dev;
+import 'dart:_js_names' show mangledNames;
part 'constant_map.dart';
part 'native_helper.dart';
@@ -25,10 +36,6 @@
part 'string_helper.dart';
part 'js_rti.dart';
-bool isJsArray(var value) {
- return value != null && JS('bool', r'(#.constructor === Array)', value);
-}
-
bool isJsIndexable(var object, var record) {
if (record != null) {
var result = dispatchRecordIndexability(record);
@@ -56,8 +63,18 @@
return res;
}
-createInvocationMirror(name, internalName, type, arguments, argumentNames) {
- return new JSInvocationMirror(new _symbol_dev.Symbol.unvalidated(name),
+createInvocationMirror(String name, internalName, type, arguments,
+ argumentNames) {
+ return new JSInvocationMirror(name,
+ internalName,
+ type,
+ arguments,
+ argumentNames);
+}
+
+createUnmangledInvocationMirror(Symbol symbol, internalName, type, arguments,
+ argumentNames) {
+ return new JSInvocationMirror(symbol,
internalName,
type,
arguments,
@@ -69,7 +86,9 @@
static const GETTER = 1;
static const SETTER = 2;
- final Symbol memberName;
+ /// When [_memberName] is a String, it holds the mangled name of this
+ /// invocation. When it is a Symbol, it holds the unmangled name.
+ var /* String or Symbol */ _memberName;
final String _internalName;
final int _kind;
final List _arguments;
@@ -77,12 +96,23 @@
/** Map from argument name to index in _arguments. */
Map<String,dynamic> _namedIndices = null;
- JSInvocationMirror(this.memberName,
+ JSInvocationMirror(this._memberName,
this._internalName,
this._kind,
this._arguments,
this._namedArgumentNames);
+ Symbol get memberName {
+ if (_memberName is Symbol) return _memberName;
+ String name = _memberName;
+ String unmangledName = mangledNames[name];
+ if (unmangledName != null) {
+ name = unmangledName.split(':')[0];
+ }
+ _memberName = new _symbol_dev.Symbol.unvalidated(name);
+ return _memberName;
+ }
+
bool get isMethod => _kind == METHOD;
bool get isGetter => _kind == GETTER;
bool get isSetter => _kind == SETTER;
@@ -121,7 +151,7 @@
// to be a JavaScript object with intercepted names as property
// instead of a JavaScript array.
if (JS('int', '#.indexOf(#)', interceptedNames, name) == -1) {
- if (!isJsArray(arguments)) arguments = new List.from(arguments);
+ if (arguments is! JSArray) arguments = new List.from(arguments);
} else {
arguments = [object]..addAll(arguments);
receiver = interceptor;
@@ -186,7 +216,7 @@
JS('void', 'throw "Unable to print message: " + String(#)', string);
}
- static void _throwFormatException(String string) {
+ static _throwFormatException(String string) {
throw new FormatException(string);
}
@@ -196,7 +226,7 @@
if (handleError == null) handleError = _throwFormatException;
checkString(source);
- var match = JS('=List|Null',
+ var match = JS('JSExtendableArray|Null',
r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i.exec(#)',
source);
int digitsIndex = 1;
@@ -319,11 +349,11 @@
}
static List newGrowableList(length) {
- return JS('=List', r'new Array(#)', length);
+ return JS('JSExtendableArray', r'new Array(#)', length);
}
static List newFixedList(length) {
- var result = JS('=List', r'new Array(#)', length);
+ var result = JS('JSFixedArray', r'new Array(#)', length);
JS('void', r'#.fixed$length = #', result, true);
return result;
}
@@ -352,7 +382,7 @@
if (end <= kMaxApply) {
subarray = array;
} else {
- subarray = JS('=List', r'#.slice(#, #)', array,
+ subarray = JS('JSExtendableArray', r'#.slice(#, #)', array,
i, i + kMaxApply < end ? i + kMaxApply : end);
}
result = JS('String', '# + String.fromCharCode.apply(#, #)',
@@ -566,7 +596,7 @@
return JS('var', '#.apply(#, #)', jsFunction, function, arguments);
}
- static getConstructor(String className) {
+ static getConstructorOrInterceptor(String className) {
// TODO(ahe): Generalize this and improve test coverage of
// reflecting on intercepted classes.
if (JS('bool', '# == "String"', className)) return const JSString();
@@ -1022,9 +1052,6 @@
* one or more types, separated by vertical bars `|`. There are some special
* names:
*
- * * `=List`. This means 'exactly List', which is the JavaScript Array
- * implementation of [List] and no other implementation.
- *
* * `=Object`. This means 'exactly Object', which is a plain JavaScript object
* with properties and none of the subtypes of Object.
*
@@ -1059,11 +1086,11 @@
*
* Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys.
*
- * @Returns('String|num|=List')
+ * @Returns('String|num|JSExtendableArray')
* dynamic key;
*
* // Equivalent:
- * @Returns('String') @Returns('num') @Returns('=List')
+ * @Returns('String') @Returns('num') @Returns('JSExtendableArray')
* dynamic key;
*/
class Returns {
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 59b8355..d904246 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -16,27 +16,23 @@
Null,
Primitives,
RuntimeError,
- createInvocationMirror;
-import 'dart:_interceptors' show Interceptor;
+ createUnmangledInvocationMirror;
+import 'dart:_interceptors' show Interceptor, JSExtendableArray;
+import 'dart:_js_names';
-/// No-op method that is called to inform the compiler that
-/// tree-shaking needs to be disabled.
+/// No-op method that is called to inform the compiler that tree-shaking needs
+/// to be disabled.
disableTreeShaking() => preserveNames();
-/// No-op method that is called to inform the compiler that unmangled
-/// named must be preserved.
-preserveNames() {}
+/// No-op method that is called to inform the compiler that metadata must be
+/// preserved at runtime.
+preserveMetadata() {}
String getName(Symbol symbol) {
preserveNames();
return n(symbol);
}
-final Map<String, String> mangledNames = JsMirrorSystem.computeMangledNames();
-
-final Map<String, String> reflectiveNames =
- JsMirrorSystem.computeReflectiveNames();
-
class JsMirrorSystem implements MirrorSystem {
TypeMirror get dynamicType => _dynamicType;
TypeMirror get voidType => _voidType;
@@ -48,6 +44,16 @@
static final Map<String, List<LibraryMirror>> librariesByName =
computeLibrariesByName();
+ Map<Uri, LibraryMirror> get libraries {
+ Map<Uri, LibraryMirror> result = new Map<Uri, LibraryMirror>();
+ for (List<LibraryMirror> list in librariesByName.values) {
+ for (LibraryMirror library in list) {
+ result[library.uri] = library;
+ }
+ }
+ return result;
+ }
+
Iterable<LibraryMirror> findLibrary(Symbol libraryName) {
return new List<LibraryMirror>.from(librariesByName[n(libraryName)]);
}
@@ -55,7 +61,7 @@
static Map<String, List<LibraryMirror>> computeLibrariesByName() {
disableTreeShaking();
var result = new Map<String, List<LibraryMirror>>();
- var jsLibraries = JS('=List|Null', 'init.libraries');
+ var jsLibraries = JS('JSExtendableArray|Null', 'init.libraries');
if (jsLibraries == null) return result;
for (List data in jsLibraries) {
String name = data[0];
@@ -71,26 +77,6 @@
}
return result;
}
-
- static Map<String, String> computeMangledNames() {
- disableTreeShaking();
- var mangledNames = JS('', 'init.mangledNames');
- var keys = extractKeys(mangledNames);
- var result = <String, String>{};
- for (String key in keys) {
- result[key] = JS('String', '#[#]', mangledNames, key);
- }
- return result;
- }
-
- static Map<String, String> computeReflectiveNames() {
- disableTreeShaking();
- var result = <String, String>{};
- mangledNames.forEach((String mangledName, String reflectiveName) {
- result[reflectiveName] = mangledName;
- });
- return result;
- }
}
abstract class JsMirror {
@@ -127,6 +113,7 @@
final List<String> _classes;
final List<String> _functions;
final List _metadata;
+ List<JsMethodMirror> _cachedFunctionMirrors;
JsLibraryMirror(Symbol simpleName,
this.uri,
@@ -142,9 +129,8 @@
Map<Symbol, ClassMirror> get classes {
var result = new Map<Symbol, ClassMirror>();
for (String className in _classes) {
- Symbol symbol = s(className);
- JsClassMirror cls = reflectClassByName(symbol);
- result[symbol] = cls;
+ JsClassMirror cls = reflectClassByMangledName(className);
+ result[cls.simpleName] = cls;
cls._owner = this;
}
return result;
@@ -161,25 +147,42 @@
return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), n(fieldName)));
}
- Map<Symbol, MethodMirror> get functions {
- var result = new Map<Symbol, MethodMirror>();
+ List<JsMethodMirror> get _functionMirrors {
+ if (_cachedFunctionMirrors != null) return _cachedFunctionMirrors;
+ var result = new List<JsMethodMirror>(_functions.length);
for (int i = 0; i < _functions.length; i++) {
String name = _functions[i];
- Symbol symbol = s(name);
+ String unmangledName = mangledGlobalNames[name];
+ if (unmangledName == null) unmangledName = name;
int parameterCount = null; // TODO(ahe): Compute this.
- bool isStatic = true; // Top-level functions are static.
bool isSetter = false; // TODO(ahe): Compute this.
bool isGetter = false; // TODO(ahe): Compute this.
+ bool isConstructor = unmangledName.startsWith('new ');
+ bool isStatic = true && !isConstructor; // Top-level functions are
+ // static, but constructors are
+ // not.
+ if (isConstructor) {
+ unmangledName = unmangledName.substring(4).replaceAll(r'$', '.');
+ }
+ unmangledName = unmangledName.split(':')[0];
+ Symbol symbol = s(unmangledName);
JsMethodMirror mirror =
// TODO(ahe): Create accessor for accessing $. It is also
// used in js_helper.
new JsMethodMirror(
symbol, JS('', '#[#]', JS_CURRENT_ISOLATE(), name),
- parameterCount, isGetter, isSetter, isStatic);
- // TODO(ahe): Cache mirrors.
- result[symbol] = mirror;
+ parameterCount, isGetter, isSetter, isStatic, isConstructor);
+ result[i] = mirror;
mirror._owner = this;
}
+ return _cachedFunctionMirrors = result;
+ }
+
+ Map<Symbol, MethodMirror> get functions {
+ var result = new Map<Symbol, MethodMirror>();
+ for (JsMethodMirror mirror in _functionMirrors) {
+ if (!mirror.isConstructor) result[mirror.simpleName] = mirror;
+ }
return result;
}
@@ -213,7 +216,10 @@
return result;
}
- List<InstanceMirror> get metadata => _metadata.map(reflect).toList();
+ List<InstanceMirror> get metadata {
+ preserveMetadata();
+ return _metadata.map(reflect).toList();
+ }
}
String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);
@@ -236,18 +242,27 @@
final Expando<ClassMirror> classMirrors = new Expando<ClassMirror>();
ClassMirror reflectType(Type key) {
- return reflectClassByName(s('$key'.split('<')[0]));
+ return reflectClassByMangledName('$key'.split('<')[0]);
}
-ClassMirror reflectClassByName(Symbol symbol) {
+ClassMirror reflectClassByMangledName(String mangledName) {
+ String unmangledName = mangledGlobalNames[mangledName];
+ if (unmangledName == null) unmangledName = mangledName;
+ return reflectClassByName(s(unmangledName), mangledName);
+}
+
+ClassMirror reflectClassByName(Symbol symbol, String mangledName) {
disableTreeShaking();
- String className = n(symbol);
- var constructor = Primitives.getConstructor(className);
- if (constructor == null) {
+ var constructorOrInterceptor =
+ Primitives.getConstructorOrInterceptor(mangledName);
+ if (constructorOrInterceptor == null) {
// Probably an intercepted class.
// TODO(ahe): How to handle intercepted classes?
- throw new UnsupportedError('Cannot find class for: $className');
+ throw new UnsupportedError('Cannot find class for: ${n(symbol)}');
}
+ var constructor = (constructorOrInterceptor is Interceptor)
+ ? JS('', '#.constructor', constructorOrInterceptor)
+ : constructorOrInterceptor;
var descriptor = JS('', '#["@"]', constructor);
var fields;
var fieldsMetadata;
@@ -266,10 +281,11 @@
fields = '';
}
}
- var mirror = classMirrors[constructor];
+ var mirror = classMirrors[constructorOrInterceptor];
if (mirror == null) {
- mirror = new JsClassMirror(symbol, constructor, fields, fieldsMetadata);
- classMirrors[constructor] = mirror;
+ mirror = new JsClassMirror(
+ symbol, constructorOrInterceptor, fields, fieldsMetadata);
+ classMirrors[constructorOrInterceptor] = mirror;
}
return mirror;
}
@@ -322,10 +338,11 @@
int type,
String mangledName,
List arguments) {
+ disableTreeShaking();
// TODO(ahe): Get the argument names.
List<String> argumentNames = [];
- Invocation invocation = createInvocationMirror(
- n(name), mangledName, type, arguments, argumentNames);
+ Invocation invocation = createUnmangledInvocationMirror(
+ name, mangledName, type, arguments, argumentNames);
return reflect(delegate(invocation));
}
@@ -352,7 +369,7 @@
class JsClassMirror extends JsTypeMirror with JsObjectMirror
implements ClassMirror {
- final _jsConstructor;
+ final _jsConstructorOrInterceptor;
final String _fields;
final List _fieldsMetadata;
List _metadata;
@@ -363,7 +380,7 @@
JsLibraryMirror _owner;
JsClassMirror(Symbol simpleName,
- this._jsConstructor,
+ this._jsConstructorOrInterceptor,
this._fields,
this._fieldsMetadata)
: super(simpleName);
@@ -372,6 +389,30 @@
Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
+ get _jsConstructor {
+ if (_jsConstructorOrInterceptor is Interceptor) {
+ return JS('', '#.constructor', _jsConstructorOrInterceptor);
+ } else {
+ return _jsConstructorOrInterceptor;
+ }
+ }
+
+ Map<Symbol, MethodMirror> get constructors {
+ Map<Symbol, MethodMirror> result = new Map<Symbol, MethodMirror>();
+ JsLibraryMirror library = owner;
+ String unmangledName = mangledGlobalNames[n(simpleName)];
+ if (unmangledName == null) unmangledName = n(simpleName);
+ for (JsMethodMirror mirror in library._functionMirrors) {
+ Symbol name = mirror.simpleName;
+ if (mirror.isConstructor
+ && (name == simpleName || n(name).startsWith('$unmangledName.'))) {
+ result[name] = mirror;
+ mirror._owner = this;
+ }
+ }
+ return result;
+ }
+
List<JsMethodMirror> get _methods {
if (_cachedMethods != null) return _cachedMethods;
var prototype = JS('', '#.prototype', _jsConstructor);
@@ -480,15 +521,20 @@
if (namedArguments != null && !namedArguments.isEmpty) {
throw new UnsupportedError('Named arguments are not implemented');
}
- String mangledName = '${n(simpleName)}\$${n(constructorName)}';
+ String reflectiveName = 'new ${n(simpleName)}';
+ String name = n(constructorName);
+ if (!name.isEmpty) {
+ reflectiveName = '$reflectiveName\$$name';
+ }
+ reflectiveName = '$reflectiveName:${positionalArguments.length}:0';
+ String mangledName = reflectiveGlobalNames[reflectiveName];
var factory = JS('', '#[#]', JS_CURRENT_ISOLATE(), mangledName);
if (factory == null) {
// TODO(ahe): Pass namedArguments when NoSuchMethodError has
// been fixed to use Symbol.
// TODO(ahe): What receiver to use?
throw new NoSuchMethodError(
- this, "constructor ${n(constructorName)}", positionalArguments,
- null);
+ this, reflectiveName, positionalArguments, null);
}
return reflect(JS('', r'#.apply(#, #)',
factory,
@@ -510,7 +556,7 @@
DeclarationMirror get owner {
if (_owner == null) {
- if (_jsConstructor is Interceptor) {
+ if (_jsConstructorOrInterceptor is Interceptor) {
_owner = reflectType(Object).owner;
} else {
for (var list in JsMirrorSystem.librariesByName.values) {
@@ -540,8 +586,8 @@
if (_superclass == null) {
var superclassName = _fields.split(';')[0];
// Use _superclass == this to represent class with no superclass (Object).
- _superclass =
- (superclassName == '') ? this : reflectClassByName(s(superclassName));
+ _superclass = (superclassName == '')
+ ? this : reflectClassByMangledName(superclassName);
}
return _superclass == this ? null : _superclass;
}
@@ -585,6 +631,7 @@
String get _prettyName => 'VariableMirror';
+ // TODO(ahe): Improve this information and test it.
TypeMirror get type => JsMirrorSystem._dynamicType;
DeclarationMirror get owner => _owner;
@@ -592,6 +639,7 @@
Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
List<InstanceMirror> get metadata {
+ preserveMetadata();
if (_metadata == null) {
_metadata = (_metadataFunction == null)
? const [] : JS('', '#()', _metadataFunction);
@@ -633,11 +681,12 @@
var self = BoundClosure.selfOf(reflectee);
return new JsMethodMirror(
s(target), JS('', '#[#]', self, target), parameterCount,
- false, false, isStatic);
+ false, false, isStatic, false);
} else {
var jsFunction = JS('', '#[#]', reflectee, callName);
return new JsMethodMirror(
- s(callName), jsFunction, parameterCount, false, false, isStatic);
+ s(callName), jsFunction, parameterCount,
+ false, false, isStatic, false);
}
}
@@ -662,6 +711,7 @@
final bool isGetter;
final bool isSetter;
final bool isStatic;
+ final bool isConstructor;
DeclarationMirror _owner;
List _metadata;
@@ -670,7 +720,8 @@
this._parameterCount,
this.isGetter,
this.isSetter,
- this.isStatic)
+ this.isStatic,
+ this.isConstructor)
: super(simpleName);
factory JsMethodMirror.fromUnmangledName(String name, jsFunction) {
@@ -693,7 +744,7 @@
}
return new JsMethodMirror(
s(name), jsFunction, requiredParameterCount + optionalParameterCount,
- isGetter, isSetter, false);
+ isGetter, isSetter, false, false);
}
String get _prettyName => 'MethodMirror';
@@ -707,6 +758,9 @@
Symbol get qualifiedName => computeQualifiedName(owner, simpleName);
+ // TODO(ahe): Improve this information and test it.
+ TypeMirror get returnType => JsMirrorSystem._dynamicType;
+
List<InstanceMirror> get metadata {
if (_metadata == null) {
_metadata = extractMetadata(_jsFunction);
@@ -723,18 +777,8 @@
}
List extractMetadata(victim) {
+ preserveMetadata();
var metadataFunction = JS('', '#["@"]', victim);
return (metadataFunction == null)
? const [] : JS('', '#()', metadataFunction);
}
-
-List extractKeys(victim) {
- return JS('List', '''
-(function(victim, hasOwnProperty) {
- var result = [];
- for (var key in victim) {
- if (hasOwnProperty.call(victim, key)) result.push(key);
- }
- return result;
-})(#, Object.prototype.hasOwnProperty)''', victim);
-}
diff --git a/sdk/lib/_internal/lib/js_names.dart b/sdk/lib/_internal/lib/js_names.dart
index 5e0fc89..1d56354 100644
--- a/sdk/lib/_internal/lib/js_names.dart
+++ b/sdk/lib/_internal/lib/js_names.dart
@@ -14,7 +14,7 @@
/// with some additional information, such as, number of required arguments.
/// This map is for mangled names used as instance members.
final Map<String, String> mangledNames =
- computeMangledNames(JS('', 'init.mangledNames'));
+ computeMangledNames(JS('', 'init.mangledNames'), false);
/// A map from "reflective" names to mangled names (the reverse of
/// [mangledNames]).
@@ -24,7 +24,7 @@
/// A map from mangled names to "reflective" names (see [mangledNames]). This
/// map is for globals, that is, static and top-level members.
final Map<String, String> mangledGlobalNames =
- computeMangledNames(JS('', 'init.mangledGlobalNames'));
+ computeMangledNames(JS('', 'init.mangledGlobalNames'), true);
/// A map from "reflective" names to mangled names (the reverse of
/// [mangledGlobalNames]).
@@ -33,12 +33,21 @@
/// [jsMangledNames] is a JavaScript object literal. The keys are the mangled
/// names, and the values are the "reflective" names.
-Map<String, String> computeMangledNames(jsMangledNames) {
+Map<String, String> computeMangledNames(jsMangledNames, bool isGlobal) {
preserveNames();
var keys = extractKeys(jsMangledNames);
var result = <String, String>{};
+ String getterPrefix = JS('String', 'init.getterPrefix');
+ int getterPrefixLength = getterPrefix.length;
+ String setterPrefix = JS('String', 'init.setterPrefix');
for (String key in keys) {
- result[key] = JS('String', '#[#]', jsMangledNames, key);
+ String value = JS('String', '#[#]', jsMangledNames, key);
+ result[key] = value;
+ if (!isGlobal) {
+ if (key.startsWith(getterPrefix)) {
+ result['$setterPrefix${key.substring(getterPrefixLength)}'] = '$value=';
+ }
+ }
}
return result;
}
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index 0cd37e1..01d8ace 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -2,30 +2,54 @@
// 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.
+/**
+ * This part contains helpers for supporting runtime type information.
+ *
+ * The helper use a mixture of Dart and JavaScript objects. To indicate which is
+ * used where we adopt the scheme of using explicit type annotation for Dart
+ * objects and 'var' or omitted return type for JavaScript objects.
+ *
+ * Since bool, int, and String values are represented by the same JavaScript
+ * primitives, type annotations are used for these types in all cases.
+ *
+ * Several methods use a common JavaScript encoding of runtime type information.
+ * This encoding is referred to as the type representation which is one of
+ * these:
+ * 1) a JavaScript constructor for a class C: the represented type is the raw
+ * type C.
+ * 2) a Dart object: this is the interceptor instance for a native type.
+ * 3) a JavaScript object: this represents a class for which there is no
+ * JavaScript constructor, because it is only used in type arguments or it
+ * is native. The represented type is the raw type of this class.
+ * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
+ * subtyping flags and the substitution of the type and the rest of the
+ * array are the type arguments.
+ * 5) `null`: the dynamic type.
+ *
+ *
+ * To check subtype relations between generic classes we use a JavaScript
+ * expression that describes the necessary substitution for type arguments.
+ * Such a substitution expresssion can be:
+ * 1) `null`, if no substituted check is necessary, because the
+ * type variables are the same or there are no type variables in the class
+ * that is checked for.
+ * 2) A list expression describing the type arguments to be used in the
+ * subtype check, if the type arguments to be used in the check do not
+ * depend on the type arguments of the object.
+ * 3) A function mapping the type variables of the object to be checked to
+ * a list expression.
+ */
+
part of _js_helper;
-setRuntimeTypeInfo(target, typeInfo) {
- assert(typeInfo == null || typeInfo is JSArray);
- // We have to check for null because factories may return null.
- if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
-}
-
-getRuntimeTypeInfo(target) {
- if (target == null) return null;
- return JS('var', r'#.$builtinTypeInfo', target);
-}
-
-getRuntimeTypeArgument(target, substitution, index) {
- var arguments = substitute(substitution, getRuntimeTypeInfo(target));
- return (arguments == null) ? null : getField(arguments, index);
-}
+Type createRuntimeType(String name) => new TypeImpl(name);
class TypeImpl implements Type {
final String _typeName;
TypeImpl(this._typeName);
- toString() => _typeName;
+ String toString() => _typeName;
// TODO(ahe): This is a poor hashCode as it collides with its name.
int get hashCode => _typeName.hashCode;
@@ -35,21 +59,77 @@
}
}
+/**
+ * Sets the runtime type information on [target]. [typeInfo] is a type
+ * representation of type 4 or 5, that is, either a JavaScript array or
+ * [:null:].
+ */
+Object setRuntimeTypeInfo(Object target, var typeInfo) {
+ assert(isNull(typeInfo) || isJsArray(typeInfo));
+ // We have to check for null because factories may return null.
+ if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo);
+ return target;
+}
+
+/**
+ * Returns the runtime type information of [target]. The returned value is a
+ * list of type representations for the type arguments.
+ */
+getRuntimeTypeInfo(Object target) {
+ if (target == null) return null;
+ return JS('var', r'#.$builtinTypeInfo', target);
+}
+
+/**
+ * Returns the type arguments of [target] as an instance of [substitutionName].
+ */
+getRuntimeTypeArguments(target, substitutionName) {
+ var substitution =
+ getField(target, '${JS_OPERATOR_AS_PREFIX()}$substitutionName');
+ return substitute(substitution, getRuntimeTypeInfo(target));
+}
+
+/**
+ * Returns the [index]th type argument of [target] as an instance of
+ * [substitutionName].
+ */
+getRuntimeTypeArgument(Object target, String substitutionName, int index) {
+ var arguments = getRuntimeTypeArguments(target, substitutionName);
+ return isNull(arguments) ? null : getIndex(arguments, index);
+}
+
+/**
+ * Retrieves the class name from type information stored on the constructor
+ * of [object].
+ */
String getClassName(var object) {
return JS('String', r'#.constructor.builtin$cls', getInterceptor(object));
}
-String getRuntimeTypeAsString(List runtimeType) {
- String className = getConstructorName(runtimeType[0]);
+/**
+ * Creates the string representation for the type representation [runtimeType]
+ * of type 4, the JavaScript array, where the first element represents the class
+ * and the remaining elements represent the type arguments.
+ */
+String getRuntimeTypeAsString(var runtimeType) {
+ assert(isJsArray(runtimeType));
+ String className = getConstructorName(getIndex(runtimeType, 0));
return '$className${joinArguments(runtimeType, 1)}';
}
-String getConstructorName(type) => JS('String', r'#.builtin$cls', type);
+/**
+ * Retrieves the class name from type information stored on the constructor
+ * [type].
+ */
+String getConstructorName(var type) => JS('String', r'#.builtin$cls', type);
-String runtimeTypeToString(type) {
- if (type == null) {
+/**
+ * Returns a human-readable representation of the type representation [type].
+ */
+String runtimeTypeToString(var type) {
+ if (isNull(type)) {
return 'dynamic';
- } else if (type is JSArray) {
+ } else if (isJsArray(type)) {
// A list representing a type with arguments.
return getRuntimeTypeAsString(type);
} else {
@@ -58,18 +138,24 @@
}
}
+/**
+ * Creates a comma-separated string of human-readable representations of the
+ * type representations in the JavaScript array [types] starting at index
+ * [startIndex].
+ */
String joinArguments(var types, int startIndex) {
- if (types == null) return '';
+ if (isNull(types)) return '';
+ assert(isJsArray(types));
bool firstArgument = true;
bool allDynamic = true;
StringBuffer buffer = new StringBuffer();
- for (int index = startIndex; index < types.length; index++) {
+ for (int index = startIndex; index < getLength(types); index++) {
if (firstArgument) {
firstArgument = false;
} else {
buffer.write(', ');
}
- var argument = types[index];
+ var argument = getIndex(types, index);
if (argument != null) {
allDynamic = false;
}
@@ -78,8 +164,11 @@
return allDynamic ? '' : '<$buffer>';
}
+/**
+ * Returns a human-readable representation of the type of [object].
+ */
String getRuntimeTypeString(var object) {
- String className = object is JSArray ? 'List' : getClassName(object);
+ String className = isJsArray(object) ? 'List' : getClassName(object);
var typeInfo = JS('var', r'#.$builtinTypeInfo', object);
return "$className${joinArguments(typeInfo, 0)}";
}
@@ -89,19 +178,27 @@
return new TypeImpl(type);
}
-bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
-
-Object invoke(function, arguments) {
- return JS('var', r'#.apply(null, #)', function, arguments);
-}
-
-Object call(target, name) => JS('var', r'#[#]()', target, name);
-
+/**
+ * Applies the [substitution] on the [arguments].
+ *
+ * See the comment in the beginning of this file for a description of the
+ * possible values for [substitution].
+ */
substitute(var substitution, var arguments) {
- if (substitution is JSArray) {
+ assert(isNull(substitution) ||
+ isJsArray(substitution) ||
+ isJsFunction(substitution));
+ assert(isNull(arguments) || isJsArray(arguments));
+ if (isJsArray(substitution)) {
arguments = substitution;
} else if (isJsFunction(substitution)) {
- arguments = invoke(substitution, arguments);
+ substitution = invoke(substitution, arguments);
+ if (isJsArray(substitution)) {
+ arguments = substitution;
+ } else if (isJsFunction(substitution)) {
+ // TODO(johnniwinther): Check if this is still needed.
+ arguments = invoke(substitution, arguments);
+ }
}
return arguments;
}
@@ -126,9 +223,9 @@
// `null` or a primitive.
// TODO(9586): Move type info for static functions onto an interceptor.
var interceptor = getInterceptor(object);
- bool isSubclass = getField(interceptor, isField);
+ var isSubclass = getField(interceptor, isField);
// When we read the field and it is not there, [isSubclass] will be [:null:].
- if (isSubclass == null || !isSubclass) return false;
+ if (isNull(isSubclass)) return false;
// Should the asField function be passed the receiver?
var substitution = getField(interceptor, asField);
return checkArguments(substitution, arguments, checks);
@@ -146,7 +243,9 @@
if (object != null && !checkSubtype(object, isField, checks, asField)) {
String actualType = Primitives.objectTypeName(object);
String typeName = computeTypeName(isField, checks);
- throw new CastErrorImplementation(object, typeName);
+ // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to
+ // align with [TypeErrorImplementation].
+ throw new CastErrorImplementation(actualType, typeName);
}
return object;
}
@@ -165,49 +264,136 @@
* list [checks] (at the respective positions), possibly applying [substitution]
* to the arguments before the check.
*
- * See [:RuntimeTypes.getSubtypeSubstitution:] for a description of the possible
- * values for [substitution].
+ * See the comment in the beginning of this file for a description of the
+ * possible values for [substitution].
*/
bool checkArguments(var substitution, var arguments, var checks) {
return areSubtypes(substitute(substitution, arguments), checks);
}
-bool areSubtypes(List s, List t) {
+/**
+ * Checks whether the types of [s] are all subtypes of the types of [t].
+ *
+ * [s] and [t] are either [:null:] or JavaScript arrays of type representations,
+ * A [:null:] argument is interpreted as the arguments of a raw type, that is a
+ * list of [:dynamic:]. If [s] and [t] are JavaScript arrays they must be of the
+ * same length.
+ *
+ * See the comment in the beginning of this file for a description of type
+ * representations.
+ */
+bool areSubtypes(var s, var t) {
// [:null:] means a raw type.
- if (s == null || t == null) return true;
+ if (isNull(s) || isNull(t)) return true;
- assert(s is JSArray);
- assert(t is JSArray);
- assert(s.length == t.length);
+ assert(isJsArray(s));
+ assert(isJsArray(t));
+ assert(getLength(s) == getLength(t));
- int len = s.length;
+ int len = getLength(s);
for (int i = 0; i < len; i++) {
- if (!isSubtype(s[i], t[i])) {
+ if (!isSubtype(getIndex(s, i), getIndex(t, i))) {
return false;
}
}
return true;
}
-getArguments(var type) {
- return type is JSArray ? JS('var', r'#.slice(1)', type) : null;
+Object functionSubtypeCast(Object object, String signatureName,
+ String contextName, var context,
+ var typeArguments) {
+ if (!checkFunctionSubtype(object, signatureName,
+ contextName, context, typeArguments)) {
+ String actualType = Primitives.objectTypeName(object);
+ // TODO(johnniwinther): Provide better function type naming.
+ String typeName = signatureName;
+ throw new CastErrorImplementation(actualType, typeName);
+ }
+ return object;
}
-getField(var object, var name) => JS('var', r'#[#]', object, name);
+Object assertFunctionSubtype(Object object, String signatureName,
+ String contextName, var context,
+ var typeArguments) {
+ if (!checkFunctionSubtype(object, signatureName,
+ contextName, context, typeArguments)) {
+ // TODO(johnniwinther): Provide better function type naming.
+ String typeName = signatureName;
+ throw new TypeErrorImplementation(object, typeName);
+ }
+ return object;
+}
-bool isSubtypeOfNull(type) {
+/**
+ * Checks that the type of [target] is a subtype of the function type denoted by
+ * [signatureName]. If the type contains type variables, [contextName] holds the
+ * name of the class where these were declared and either [context] holds the
+ * object in which the runtime values of these can be found or [typeArguments]
+ * contains these values as a list of runtime type information.
+ */
+bool checkFunctionSubtype(var target, String signatureName,
+ String contextName, var context,
+ var typeArguments) {
+ if (isNull(target)) return true;
+ var interceptor = getInterceptor(target);
+ if (hasField(interceptor, '${JS_OPERATOR_IS_PREFIX()}_$signatureName')) {
+ return true;
+ }
+ var signatureLocation = JS_GLOBAL_OBJECT();
+ if (isNotNull(contextName)) {
+ signatureLocation = getField(signatureLocation, contextName);
+ }
+ var typeSignature =
+ getField(signatureLocation, '${JS_SIGNATURE_NAME()}_$signatureName');
+ if (isNull(typeSignature)) {
+ // All checks can be determined statically so the type signature has not
+ // been computed.
+ return false;
+ }
+ var targetSignatureFunction = getField(interceptor, '${JS_SIGNATURE_NAME()}');
+ if (isNull(targetSignatureFunction)) return false;
+ var targetSignature = invokeOn(targetSignatureFunction, interceptor, null);
+ if (isJsFunction(typeSignature)) {
+ if (isNotNull(typeArguments)) {
+ typeSignature = invoke(typeSignature, typeArguments);
+ } else if (isNotNull(context)) {
+ typeSignature =
+ invoke(typeSignature, getRuntimeTypeArguments(context, contextName));
+ } else {
+ typeSignature = invoke(typeSignature, null);
+ }
+ }
+ return isFunctionSubtype(targetSignature, typeSignature);
+}
+
+/**
+ * Computes the signature by applying the type arguments of [context] as an
+ * instance of [contextName] to the signature function [signature].
+ */
+computeSignature(var signature, var context, var contextName) {
+ var typeArguments = getRuntimeTypeArguments(context, contextName);
+ return invokeOn(signature, context, typeArguments);
+}
+
+/**
+ * Returns [:true:] if the runtime type representation [type] is a supertype of
+ * [:Null:].
+ */
+bool isSupertypeOfNull(var type) {
// `null` means `dynamic`.
- return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME();
+ return isNull(type) || getConstructorName(type) == JS_OBJECT_CLASS_NAME();
}
/**
* Tests whether the Dart object [o] is a subtype of the runtime type
- * representation [t], which is a type representation as described in the
- * comment on [isSubtype].
+ * representation [t].
+ *
+ * See the comment in the beginning of this file for a description of type
+ * representations.
*/
bool checkSubtypeOfRuntimeType(Object o, var t) {
- if (JS('bool', '# == null', o)) return isSubtypeOfNull(t);
- if (JS('bool', '# == null', t)) return true;
+ if (isNull(o)) return isSupertypeOfNull(t);
+ if (isNull(t)) return true;
// Get the runtime type information from the object here, because we may
// overwrite o with the interceptor below.
var rti = getRuntimeTypeInfo(o);
@@ -216,7 +402,7 @@
// the subtype flags and the substitution on the prototype, so they are
// properties of the object in JS.
var type;
- if (JS('bool', '# != null', rti)) {
+ if (isNotNull(rti)) {
// If the type has type variables (that is, [:rti != null:]), make a copy of
// the type arguments and insert [o] in the first position to create a
// compound type representation.
@@ -245,40 +431,52 @@
}
/**
- * Check whether the type represented by [s] is a subtype of the type
- * represented by [t].
+ * Extracts the type arguments from a type representation. The result is a
+ * JavaScript array or [:null:].
+ */
+getArguments(var type) {
+ return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
+}
+
+/**
+ * Checks whether the type represented by the type representation [s] is a
+ * subtype of the type represented by the type representation [t].
*
- * Type representations can be:
- * 1) a JavaScript constructor for a class C: the represented type is the raw
- * type C.
- * 2) a Dart object: this is the interceptor instance for a native type.
- * 3) a JavaScript object: this represents a class for which there is no
- * JavaScript constructor, because it is only used in type arguments or it
- * is native. The represented type is the raw type of this class.
- * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the
- * subtyping flags and the substitution of the type and the rest of the
- * array are the type arguments.
- * 5) [:null:]: the dynamic type.
+ * See the comment in the beginning of this file for a description of type
+ * representations.
*/
bool isSubtype(var s, var t) {
- // If either type is dynamic, [s] is a subtype of [t].
- if (JS('bool', '# == null', s) || JS('bool', '# == null', t)) return true;
// Subtyping is reflexive.
- if (JS('bool', '# === #', s, t)) return true;
- // Get the object describing the class and check for the subtyping flag
- // constructed from the type of [t].
- var typeOfS = s is JSArray ? s[0] : s;
- var typeOfT = t is JSArray ? t[0] : t;
- // TODO(johnniwinther): replace this with the real function subtype test.
- if (JS('bool', '#.func', s) == true || JS('bool', '#.func', t) == true ) {
+ if (isIdentical(s, t)) return true;
+ // If either type is dynamic, [s] is a subtype of [t].
+ if (isNull(s) || isNull(t)) return true;
+ if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) {
+ if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) {
+ var signatureName =
+ '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}';
+ if (hasField(s, signatureName)) return true;
+ var targetSignatureFunction = getField(s, '${JS_SIGNATURE_NAME()}');
+ if (isNull(targetSignatureFunction)) return false;
+ s = invokeOn(targetSignatureFunction, s, null);
+ }
+ return isFunctionSubtype(s, t);
+ }
+ // Check function types against the Function class.
+ if (getConstructorName(t) == JS_FUNCTION_CLASS_NAME() &&
+ hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) {
return true;
}
+ // Get the object describing the class and check for the subtyping flag
+ // constructed from the type of [t].
+ var typeOfS = isJsArray(s) ? getIndex(s, 0) : s;
+ var typeOfT = isJsArray(t) ? getIndex(t, 0) : t;
// Check for a subtyping flag.
- var test = '${JS_OPERATOR_IS_PREFIX()}${runtimeTypeToString(typeOfT)}';
- if (getField(typeOfS, test) == null) return false;
+ var name = runtimeTypeToString(typeOfT);
+ var test = '${JS_OPERATOR_IS_PREFIX()}${name}';
+ if (hasNoField(typeOfS, test)) return false;
// Get the necessary substitution of the type arguments, if there is one.
var substitution;
- if (JS('bool', '# !== #', typeOfT, typeOfS)) {
+ if (isNotIdentical(typeOfT, typeOfS)) {
var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}';
substitution = getField(typeOfS, field);
}
@@ -286,12 +484,231 @@
// arguments and no substitution, it is used as raw type. If [t] has no
// type arguments, it used as a raw type. In both cases, [s] is a subtype
// of [t].
- if ((s is! JSArray && JS('bool', '# == null', substitution)) ||
- t is! JSArray) {
+ if ((!isJsArray(s) && isNull(substitution)) || !isJsArray(t)) {
return true;
}
// Recursively check the type arguments.
return checkArguments(substitution, getArguments(s), getArguments(t));
}
-createRuntimeType(String name) => new TypeImpl(name);
+bool isAssignable(var s, var t) {
+ return isSubtype(s, t) || isSubtype(t, s);
+}
+
+/**
+ * If [allowShorter] is [:true:], [t] is allowed to be shorter than [s].
+ */
+bool areAssignable(List s, List t, bool allowShorter) {
+ // Both lists are empty and thus equal.
+ if (isNull(t) && isNull(s)) return true;
+ // [t] is empty (and [s] is not) => only OK if [allowShorter].
+ if (isNull(t)) return allowShorter;
+ // [s] is empty (and [t] is not) => [s] is not longer or equal to [t].
+ if (isNull(s)) return false;
+
+ assert(isJsArray(s));
+ assert(isJsArray(t));
+
+ int sLength = getLength(s);
+ int tLength = getLength(t);
+ if (allowShorter) {
+ if (sLength < tLength) return false;
+ } else {
+ if (sLength != tLength) return false;
+ }
+
+ for (int i = 0; i < tLength; i++) {
+ if (!isAssignable(getIndex(s, i), getIndex(t, i))) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool areAssignableMaps(var s, var t) {
+ if (isNull(t)) return true;
+ if (isNull(s)) return false;
+
+ assert(isJsObject(s));
+ assert(isJsObject(t));
+
+ return JS('bool', r'''
+ function (t, s, isAssignable) {
+ for (var $name in t) {
+ if (!s.hasOwnProperty($name)) {
+ return false;
+ }
+ var tType = t[$name];
+ var sType = s[$name];
+ if (!isAssignable.call$2(sType, tType)) {
+ return false;
+ }
+ }
+ return true;
+ }(#, #, #)
+ ''', t, s, RAW_DART_FUNCTION_REF(isAssignable));
+}
+
+bool isFunctionSubtype(var s, var t) {
+ assert(hasField(t, '${JS_FUNCTION_TYPE_TAG()}'));
+ if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) return false;
+ if (hasField(s, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) {
+ if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}') &&
+ hasField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}')) {
+ return false;
+ }
+ } else if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) {
+ var sReturnType = getField(s, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}');
+ var tReturnType = getField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}');
+ if (!isAssignable(sReturnType, tReturnType)) return false;
+ }
+ var sParameterTypes =
+ getField(s, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}');
+ var tParameterTypes =
+ getField(t, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}');
+
+ var sOptionalParameterTypes =
+ getField(s, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}');
+ var tOptionalParameterTypes =
+ getField(t, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}');
+
+ int sParametersLen =
+ isNotNull(sParameterTypes) ? getLength(sParameterTypes) : 0;
+ int tParametersLen =
+ isNotNull(tParameterTypes) ? getLength(tParameterTypes) : 0;
+
+ int sOptionalParametersLen = isNotNull(sOptionalParameterTypes)
+ ? getLength(sOptionalParameterTypes) : 0;
+ int tOptionalParametersLen = isNotNull(tOptionalParameterTypes)
+ ? getLength(tOptionalParameterTypes) : 0;
+
+ if (sParametersLen > tParametersLen) {
+ // Too many required parameters in [s].
+ return false;
+ }
+ if (sParametersLen + sOptionalParametersLen <
+ tParametersLen + tOptionalParametersLen) {
+ // Too few required and optional parameters in [s].
+ return false;
+ }
+ if (sParametersLen == tParametersLen) {
+ // Simple case: Same number of required parameters.
+ if (!areAssignable(sParameterTypes, tParameterTypes, false)) return false;
+ if (!areAssignable(sOptionalParameterTypes,
+ tOptionalParameterTypes, true)) {
+ return false;
+ }
+ } else {
+ // Complex case: Optional parameters of [s] for required parameters of [t].
+ int pos = 0;
+ // Check all required parameters of [s].
+ for (; pos < sParametersLen; pos++) {
+ if (!isAssignable(getIndex(sParameterTypes, pos),
+ getIndex(tParameterTypes, pos))) {
+ return false;
+ }
+ }
+ int sPos = 0;
+ int tPos = pos;
+ // Check the remaining parameters of [t] with the first optional parameters
+ // of [s].
+ for (; tPos < tParametersLen ; sPos++, tPos++) {
+ if (!isAssignable(getIndex(sOptionalParameterTypes, sPos),
+ getIndex(tParameterTypes, tPos))) {
+ return false;
+ }
+ }
+ sPos = 0;
+ // Check the optional parameters of [t] with the remaing optional parameters
+ // of [s]:
+ for (; tPos < tOptionalParametersLen ; sPos++, tPos++) {
+ if (!isAssignable(getIndex(tOptionalParameterTypes, sPos),
+ getIndex(tOptionalParameterTypes, tPos))) {
+ return false;
+ }
+ }
+ }
+
+ var sNamedParameters =
+ getField(s, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}');
+ var tNamedParameters =
+ getField(t, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}');
+ return areAssignableMaps(sNamedParameters, tNamedParameters);
+}
+
+/**
+ * Calls the JavaScript [function] with the [arguments] with the global scope
+ * as the [:this:] context.
+ */
+invoke(var function, var arguments) => invokeOn(function, null, arguments);
+
+/**
+ * Calls the JavaScript [function] with the [arguments] with [receiver] as the
+ * [:this:] context.
+ */
+Object invokeOn(function, receiver, arguments) {
+ assert(isJsFunction(function));
+ assert(isNull(arguments) || isJsArray(arguments));
+ return JS('var', r'#.apply(#, #)', function, receiver, arguments);
+}
+
+/// Calls the property [name] on the JavaScript [object].
+call(var object, String name) => JS('var', r'#[#]()', object, name);
+
+/// Returns the property [name] of the JavaScript object [object].
+getField(var object, String name) => JS('var', r'#[#]', object, name);
+
+/// Returns the property [index] of the JavaScript array [array].
+getIndex(var array, int index) {
+ assert(isJsArray(array));
+ return JS('var', r'#[#]', array, index);
+}
+
+/// Returns the length of the JavaScript array [array].
+int getLength(var array) {
+ assert(isJsArray(array));
+ return JS('int', r'#.length', array);
+}
+
+/// Returns whether [value] is a JavaScript array.
+bool isJsArray(var value) {
+ return value is JSArray;
+}
+
+hasField(var object, var name) => JS('bool', r'#[#] != null', object, name);
+
+hasNoField(var object, var name) => JS('bool', r'#[#] == null', object, name);
+
+/// Returns [:true:] if [o] is a JavaScript function.
+bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o);
+
+/// Returns [:true:] if [o] is a JavaScript object.
+bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o);
+
+/**
+ * Returns [:true:] if [o] is equal to [:null:], that is either [:null:] or
+ * [:undefined:]. We use this helper to avoid generating code under the invalid
+ * assumption that [o] is a Dart value.
+ */
+bool isNull(var o) => JS('bool', '# == null', o);
+
+/**
+ * Returns [:true:] if [o] is not equal to [:null:], that is neither [:null:]
+ * nor [:undefined:]. We use this helper to avoid generating code under the
+ * invalid assumption that [o] is a Dart value.
+ */
+bool isNotNull(var o) => JS('bool', '# != null', o);
+
+/**
+ * Returns [:true:] if the JavaScript values [s] and [t] are identical. We use
+ * this helper to avoid generating code under the invalid assumption that [s]
+ * and [t] are Dart values.
+ */
+bool isIdentical(var s, var t) => JS('bool', '# === #', s, t);
+
+/**
+ * Returns [:true:] if the JavaScript values [s] and [t] are not identical. We
+ * use this helper to avoid generating code under the invalid assumption that
+ * [s] and [t] are Dart values.
+ */
+bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t);
diff --git a/sdk/lib/_internal/lib/js_string.dart b/sdk/lib/_internal/lib/js_string.dart
index 2da5ed4..adc32e8 100644
--- a/sdk/lib/_internal/lib/js_string.dart
+++ b/sdk/lib/_internal/lib/js_string.dart
@@ -76,24 +76,28 @@
List<String> split(Pattern pattern) {
checkNull(pattern);
if (pattern is String) {
- return JS('=List', r'#.split(#)', this, pattern);
+ return JS('JSExtendableArray', r'#.split(#)', this, pattern);
} else if (pattern is JSSyntaxRegExp) {
var re = regExpGetNative(pattern);
- return JS('=List', r'#.split(#)', this, re);
+ return JS('JSExtendableArray', r'#.split(#)', this, re);
} else {
throw "String.split(Pattern) UNIMPLEMENTED";
}
}
- bool startsWith(Pattern pattern) {
+ bool startsWith(Pattern pattern, [int index = 0]) {
+ if (index < 0 || index > this.length) {
+ throw new RangeError.range(index, 0, this.length);
+ }
if (pattern is String) {
String other = pattern;
int otherLength = other.length;
- if (otherLength > length) return false;
+ int endIndex = index + otherLength;
+ if (endIndex > length) return false;
return JS('bool', r'# == #', other,
- JS('String', r'#.substring(0, #)', this, otherLength));
+ JS('String', r'#.substring(#, #)', this, index, endIndex));
}
- return pattern.matchAsPrefix(this, 0) != null;
+ return pattern.matchAsPrefix(this, index) != null;
}
String substring(int startIndex, [int endIndex]) {
diff --git a/sdk/lib/_internal/lib/json_patch.dart b/sdk/lib/_internal/lib/json_patch.dart
index 01cce1a..ad22ae7 100644
--- a/sdk/lib/_internal/lib/json_patch.dart
+++ b/sdk/lib/_internal/lib/json_patch.dart
@@ -5,6 +5,7 @@
// Patch file for dart:json library.
import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSExtendableArray;
/**
* Parses [json] and builds the corresponding parsed JSON value.
@@ -27,7 +28,9 @@
var parsed;
try {
- parsed = JS('=Object|=List|Null|bool|num|String', 'JSON.parse(#)', json);
+ parsed = JS('=Object|JSExtendableArray|Null|bool|num|String',
+ 'JSON.parse(#)',
+ json);
} catch (e) {
throw new FormatException(JS('String', 'String(#)', e));
}
@@ -54,7 +57,7 @@
// TODO(sra): Replace this test with cheaper '#.constructor === Array' when
// bug 621 below is fixed.
if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) {
- var list = JS('=List', '#', e); // Teach compiler the type is known.
+ var list = JS('JSExtendableArray', '#', e); // Teach compiler the type is known.
// In-place update of the elements since JS Array is a Dart List.
for (int i = 0; i < list.length; i++) {
// Use JS indexing to avoid range checks. We know this is the only
@@ -69,7 +72,7 @@
}
// Otherwise it is a plain Object, so copy to a Map.
- var keys = JS('=List', 'Object.keys(#)', e);
+ var keys = JS('JSExtendableArray', 'Object.keys(#)', e);
Map map = {};
for (int i = 0; i < keys.length; i++) {
String key = keys[i];
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index f4c1fe2..8ad597e 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -255,7 +255,7 @@
if (interceptorsByTag == null) interceptorsByTag = JS('=Object', '{}');
if (leafTags == null) leafTags = JS('=Object', '{}');
- var tagsList = JS('=List', '#.split("|")', tags);
+ var tagsList = JS('JSExtendableArray', '#.split("|")', tags);
for (int i = 0; i < tagsList.length; i++) {
var tag = tagsList[i];
JS('void', '#[#] = #', interceptorsByTag, tag, methods);
diff --git a/sdk/lib/_internal/lib/regexp_helper.dart b/sdk/lib/_internal/lib/regexp_helper.dart
index c9d9636..94b015f 100644
--- a/sdk/lib/_internal/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/lib/regexp_helper.dart
@@ -84,8 +84,10 @@
}
Match firstMatch(String str) {
- List<String> m =
- JS('=List|Null', r'#.exec(#)', _nativeRegExp, checkString(str));
+ List<String> m = JS('JSExtendableArray|Null',
+ r'#.exec(#)',
+ _nativeRegExp,
+ checkString(str));
if (m == null) return null;
return new _MatchImplementation(this, m);
}
@@ -108,7 +110,7 @@
Match _execGlobal(String string, int start) {
Object regexp = _nativeGlobalVersion;
JS("void", "#.lastIndex = #", regexp, start);
- List match = JS("=List|Null", "#.exec(#)", regexp, string);
+ List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
if (match == null) return null;
return new _MatchImplementation(this, match);
}
@@ -116,7 +118,7 @@
Match _execAnchored(String string, int start) {
Object regexp = _nativeAnchoredVersion;
JS("void", "#.lastIndex = #", regexp, start);
- List match = JS("=List|Null", "#.exec(#)", regexp, string);
+ List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
if (match == null) return null;
// If the last capture group participated, the original regexp did not
// match at the start position.
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index d56bdc3..51e5037 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -152,6 +152,12 @@
category: "Internal",
documented: false,
platforms: DART2JS_PLATFORM),
+
+ "_js_names": const LibraryInfo(
+ "_internal/lib/js_names.dart",
+ category: "Internal",
+ documented: false,
+ platforms: DART2JS_PLATFORM),
};
/**
diff --git a/sdk/lib/_internal/pub/lib/src/command_cache.dart b/sdk/lib/_internal/pub/lib/src/command_cache.dart
index b4131b4..9beb611 100644
--- a/sdk/lib/_internal/pub/lib/src/command_cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/command_cache.dart
@@ -33,11 +33,11 @@
// TODO(keertip): Add flag to list packages from non default sources
var packagesObj = <String, Map>{};
+
for (var package in cache.sources.defaultSource.getCachedPackages()) {
- packagesObj[package.name] = {
- 'version': package.version.toString(),
- 'location': package.dir
- };
+
+ var packageInfo = packagesObj.putIfAbsent(package.name, () => {});
+ packageInfo[package.version.toString()] = {'location': package.dir};
}
// TODO(keertip): Add support for non-JSON format
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index 819053c..0ad59c0 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -41,9 +41,9 @@
}
return compiler.compile(
- pathToFileUri(entrypoint),
- pathToFileUri(appendSlash(_libPath)),
- pathToFileUri(appendSlash(packageRoot)),
+ path.toUri(entrypoint),
+ path.toUri(appendSlash(_libPath)),
+ path.toUri(appendSlash(packageRoot)),
provider.readStringFromUri,
new FormattingDiagnosticHandler(provider).diagnosticHandler,
options);
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index 8b6c7fd..66477f5 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -368,7 +368,7 @@
/// Whether pub is running from within the Dart SDK, as opposed to from the Dart
/// source repository.
-bool get runningFromSdk => path.extension(new Options().script) == '.snapshot';
+bool get runningFromSdk => path.extension(Platform.script) == '.snapshot';
/// Resolves [target] relative to the path to pub's `resource` directory.
String resourcePath(String target) {
@@ -591,19 +591,12 @@
executable = "cmd";
}
- var env = null;
- if (environment != null) {
- env = new Map.from(Platform.environment);
- environment.forEach((key, value) => env[key] = value);
- }
-
-
log.process(executable, args);
return fn(executable,
args,
workingDirectory: workingDir,
- environment: env);
+ environment: environment);
}
/// Wraps [input] to provide a timeout. If [input] completes before
@@ -772,7 +765,7 @@
// Create the tar file.
var tarFile = path.join(tempDir, "intermediate.tar");
var args = ["a", "-w$baseDir", tarFile];
- args.addAll(contents.map((entry) => '-i!"$entry"'));
+ args.addAll(contents.map((entry) => '-i!$entry'));
// We're passing 'baseDir' both as '-w' and setting it as the working
// directory explicitly here intentionally. The former ensures that the
diff --git a/sdk/lib/_internal/pub/lib/src/sdk.dart b/sdk/lib/_internal/pub/lib/src/sdk.dart
index 0fbe5f9..7f4e26a 100644
--- a/sdk/lib/_internal/pub/lib/src/sdk.dart
+++ b/sdk/lib/_internal/pub/lib/src/sdk.dart
@@ -29,7 +29,7 @@
}
// Assume the Dart executable is always coming from the SDK.
- return path.dirname(path.dirname(new Options().executable));
+ return path.dirname(path.dirname(Platform.executable));
}
/// Gets the SDK's revision number formatted to be a semantic version.
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index c67ce57..d5210f3 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -376,37 +376,7 @@
/// be globally unique, or the wrong library path may be returned.
String libraryPath(String libraryName) {
var libraries = currentMirrorSystem().findLibrary(new Symbol(libraryName));
- return fileUriToPath(libraries.single.uri);
-}
-
-/// Converts a `file:` [Uri] to a local path string.
-String fileUriToPath(Uri uri) {
- if (uri.scheme != 'file') {
- throw new ArgumentError("Uri $uri must have scheme 'file:'.");
- }
- if (Platform.operatingSystem != 'windows') return uri.path;
- if (uri.path.startsWith("/")) {
- // Drive-letter paths look like "file:///C:/path/to/file". The replaceFirst
- // removes the extra initial slash.
- return uri.path.replaceFirst("/", "").replaceAll("/", "\\");
- } else {
- // Network paths look like "file://hostname/path/to/file".
- return "\\\\${uri.path.replaceAll("/", "\\")}";
- }
-}
-
-/// Converts a local path string to a `file:` [Uri].
-Uri pathToFileUri(String pathString) {
- pathString = path.absolute(pathString);
- if (Platform.operatingSystem != 'windows') {
- return Uri.parse('file://$pathString');
- } else if (path.rootPrefix(pathString).startsWith('\\\\')) {
- // Network paths become "file://hostname/path/to/file".
- return Uri.parse('file:${pathString.replaceAll("\\", "/")}');
- } else {
- // Drive-letter paths become "file:///C:/path/to/file".
- return Uri.parse('file:///${pathString.replaceAll("\\", "/")}');
- }
+ return path.fromUri(libraries.single.uri);
}
/// Gets a "special" string (ANSI escape or Unicode). On Windows, returns
diff --git a/sdk/lib/_internal/pub/test/pub_cache_test.dart b/sdk/lib/_internal/pub/test/pub_cache_test.dart
index 195bcd5..f902a92 100644
--- a/sdk/lib/_internal/pub/test/pub_cache_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_cache_test.dart
@@ -73,9 +73,9 @@
]).create();
schedulePub(args: ['cache', 'list'], output:
- new RegExp(r'\{"packages":\{"bar":\{"version":"2\.0\.0","location":'
- r'"[^"]+bar-2\.0\.0"\},"foo":\{"version":"1\.2\.3","location":'
- r'"[^"]+foo-1\.2\.3"\}\}\}$'));
+ new RegExp(r'\{"packages":\{"bar":\{"2\.0\.0":\{"location":'
+ r'"[^"]+bar-2\.0\.0"\}},"foo":\{"1\.2\.3":\{"location":'
+ r'"[^"]+foo-1\.2\.3"\}\}\}\}$'));
});
integration('includes packages containing deps with bad sources', () {
@@ -92,7 +92,7 @@
]).create();
schedulePub(args: ['cache', 'list'], output:
- new RegExp(r'\{"packages":\{"foo":\{"version":"1\.2\.3","location":'
- r'"[^"]+foo-1\.2\.3"\}\}\}$'));
+ new RegExp(r'\{"packages":\{"foo":\{"1\.2\.3":\{"location":'
+ r'"[^"]+foo-1\.2\.3"\}\}\}\}$'));
});
}
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 4813ee4..c35ab69 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -436,7 +436,7 @@
// Find a Dart executable we can use to spawn. Use the same one that was
// used to run this script itself.
- var dartBin = new Options().executable;
+ var dartBin = Platform.executable;
// If the executable looks like a path, get its full path. That way we
// can still find it when we spawn it with a different working directory.
@@ -453,8 +453,7 @@
if (tokenEndpoint == null) tokenEndpoint = new Future.value();
var environmentFuture = tokenEndpoint.then((tokenEndpoint) {
- // TODO(nweiz): remove this when issue 9294 is fixed.
- var environment = new Map.from(Platform.environment);
+ var environment = {};
environment['_PUB_TESTING'] = 'true';
environment['PUB_CACHE'] = pathInSandbox(cachePath);
environment['DART_SDK'] = pathInSandbox(sdkPath);
@@ -556,7 +555,7 @@
/// The path to the `packages` directory from which pub loads its dependencies.
String get _packageRoot {
return path.absolute(path.join(
- path.dirname(new Options().executable), '..', '..', 'packages'));
+ path.dirname(Platform.executable), '..', '..', 'packages'));
}
/// Skips the current test if Git is not installed. This validates that the
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index bff0435..0de2919 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -76,6 +76,11 @@
/**
* Creates a single-subscription stream that gets its data from [data].
+ *
+ * If iterating [data] throws an error, the stream ends immediately with
+ * that error. No done event will be sent (iteration is not complete), but no
+ * further data events will be generated either, since iteration cannot
+ * continue.
*/
factory Stream.fromIterable(Iterable<T> data) {
return new _GeneratedStreamImpl<T>(
@@ -307,12 +312,12 @@
}
/**
- * Checks whether [match] occurs in the elements provided by this stream.
+ * Checks whether [needle] occurs in the elements provided by this stream.
*
* Completes the [Future] when the answer is known.
* If this stream reports an error, the [Future] will report that error.
*/
- Future<bool> contains(T match) {
+ Future<bool> contains(Object needle) {
_FutureImpl<bool> future = new _FutureImpl<bool>();
StreamSubscription subscription;
subscription = this.listen(
@@ -320,7 +325,7 @@
// checked mode. http://dartbug.com/7733
(/*T*/ element) {
_runUserCode(
- () => (element == match),
+ () => (element == needle),
(bool isMatch) {
if (isMatch) {
subscription.cancel();
@@ -673,8 +678,8 @@
* with no [defaultValue] function provided, the future will receive an
* error.
*/
- Future<T> firstWhere(bool test(T element), {T defaultValue()}) {
- _FutureImpl<T> future = new _FutureImpl<T>();
+ Future<dynamic> firstWhere(bool test(T element), {Object defaultValue()}) {
+ _FutureImpl<dynamic> future = new _FutureImpl();
StreamSubscription subscription;
subscription = this.listen(
// TODO(ahe): Restore type when feature is implemented in dart2js
@@ -710,8 +715,8 @@
* That means that the result cannot be provided before this stream
* is done.
*/
- Future<T> lastWhere(bool test(T element), {T defaultValue()}) {
- _FutureImpl<T> future = new _FutureImpl<T>();
+ Future<dynamic> lastWhere(bool test(T element), {Object defaultValue()}) {
+ _FutureImpl<dynamic> future = new _FutureImpl();
T result = null;
bool foundResult = false;
StreamSubscription subscription;
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index e5aca17..9438452 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.dart
@@ -151,8 +151,6 @@
}
void _handleDone() {
- // On a done-event, we have already been unsubscribed.
- _subscription = null;
_stream._handleDone(this);
}
}
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index b92aa16..1379128 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -410,10 +410,10 @@
_ZoneTimer(this._zone, Duration duration, this._callback) {
_zone.expectCallback();
- _timer = _createTimer(duration, this.run);
+ _timer = _createTimer(duration, this._run);
}
- void run() {
+ void _run() {
_isDone = true;
_zone.executeCallbackGuarded(_callback);
}
@@ -438,10 +438,10 @@
_PeriodicZoneTimer(this._zone, Duration duration, this._callback) {
_zone.expectCallback();
- _timer = _createPeriodicTimer(duration, this.run);
+ _timer = _createPeriodicTimer(duration, this._run);
}
- void run(Timer timer) {
+ void _run(Timer timer) {
assert(identical(_timer, timer));
_zone.executePeriodicCallbackGuarded(() { _callback(this); });
}
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 2aea9c9..ab1f09c 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -29,17 +29,17 @@
external Iterable<K> get keys;
external Iterable<V> get values;
- external bool containsKey(K key);
- external bool containsValue(V value);
+ external bool containsKey(Object key);
+ external bool containsValue(Object value);
external void addAll(Map<K, V> other);
- external V operator [](K key);
+ external V operator [](Object key);
external void operator []=(K key, V value);
external V putIfAbsent(K key, V ifAbsent());
- external V remove(K key);
+ external V remove(Object key);
external void clear();
external void forEach(void action(K key, V value));
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index e2c797d..86c69c8 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -7,8 +7,8 @@
/** Common parts of [HashSet] and [LinkedHashSet] implementations. */
abstract class _HashSetBase<E> extends IterableBase<E> implements Set<E> {
// Set.
- bool containsAll(Iterable<E> other) {
- for (E object in other) {
+ bool containsAll(Iterable<Object> other) {
+ for (Object object in other) {
if (!this.contains(object)) return false;
}
return true;
@@ -17,10 +17,10 @@
/** Create a new Set of the same type as this. */
Set _newSet();
- Set<E> intersection(Set<E> other) {
+ Set<E> intersection(Set<Object> other) {
Set<E> result = _newSet();
if (other.length < this.length) {
- for (E element in other) {
+ for (var element in other) {
if (this.contains(element)) result.add(element);
}
} else {
@@ -95,7 +95,7 @@
external bool remove(Object object);
- external void removeAll(Iterable objectsToRemove);
+ external void removeAll(Iterable<Object> objectsToRemove);
external void removeWhere(bool test(E element));
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index a950543..6dbf92d 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -17,7 +17,7 @@
Iterable expand(Iterable f(E element)) =>
new ExpandIterable<E, dynamic>(this, f);
- bool contains(E element) {
+ bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
@@ -141,8 +141,7 @@
return result;
}
- E firstWhere(bool test(E value), { E orElse() }) {
- // TODO(floitsch): check that arguments are of correct type?
+ dynamic firstWhere(bool test(E value), { Object orElse() }) {
for (E element in this) {
if (test(element)) return element;
}
@@ -150,8 +149,7 @@
throw new StateError("No matching element");
}
- E lastWhere(bool test(E value), {E orElse()}) {
- // TODO(floitsch): check that arguments are of correct type?
+ dynamic lastWhere(bool test(E value), { Object orElse() }) {
E result = null;
bool foundMatching = false;
for (E element in this) {
@@ -166,7 +164,6 @@
}
E singleWhere(bool test(E value)) {
- // TODO(floitsch): check that argument is of correct type?
E result = null;
bool foundMatching = false;
for (E element in this) {
@@ -211,7 +208,7 @@
Iterable expand(Iterable f(E element)) =>
new ExpandIterable<E, dynamic>(this, f);
- bool contains(E element) {
+ bool contains(Object element) {
for (E e in this) {
if (e == element) return true;
}
@@ -335,8 +332,7 @@
return result;
}
- E firstWhere(bool test(E value), { E orElse() }) {
- // TODO(floitsch): check that arguments are of correct type?
+ dynamic firstWhere(bool test(E value), { Object orElse() }) {
for (E element in this) {
if (test(element)) return element;
}
@@ -344,8 +340,7 @@
throw new StateError("No matching element");
}
- E lastWhere(bool test(E value), {E orElse()}) {
- // TODO(floitsch): check that arguments are of correct type?
+ dynamic lastWhere(bool test(E value), { Object orElse() }) {
E result = null;
bool foundMatching = false;
for (E element in this) {
@@ -360,7 +355,6 @@
}
E singleWhere(bool test(E value)) {
- // TODO(floitsch): check that argument is of correct type?
E result = null;
bool foundMatching = false;
for (E element in this) {
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 8e6538c..3082ce0 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -25,19 +25,19 @@
return new LinkedHashMap<K, V>()..addAll(other);
}
- external bool containsKey(K key);
+ external bool containsKey(Object key);
- external bool containsValue(V value);
+ external bool containsValue(Object value);
external void addAll(Map<K, V> other);
- external V operator [](K key);
+ external V operator [](Object key);
external void operator []=(K key, V value);
external V putIfAbsent(K key, V ifAbsent());
- external V remove(K key);
+ external V remove(Object key);
external void clear();
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index fa1bd50..5c81ae7 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -63,7 +63,7 @@
return this[0];
}
- bool contains(E element) {
+ bool contains(Object element) {
int length = this.length;
for (int i = 0; i < length; i++) {
if (this[i] == element) return true;
@@ -96,7 +96,7 @@
return false;
}
- E firstWhere(bool test(E element), { E orElse() }) {
+ dynamic firstWhere(bool test(E element), { Object orElse() }) {
int length = this.length;
for (int i = 0; i < length; i++) {
E element = this[i];
@@ -109,7 +109,7 @@
throw new StateError("No matching element");
}
- E lastWhere(bool test(E element), { E orElse() }) {
+ dynamic lastWhere(bool test(E element), { Object orElse() }) {
int length = this.length;
for (int i = length - 1; i >= 0; i--) {
E element = this[i];
@@ -385,7 +385,7 @@
insertAll(start, newContents);
}
- int indexOf(E element, [int startIndex = 0]) {
+ int indexOf(Object element, [int startIndex = 0]) {
if (startIndex >= this.length) {
return -1;
}
@@ -405,7 +405,7 @@
* the search at index [startIndex] to 0.
* Returns -1 if [element] is not found.
*/
- int lastIndexOf(E element, [int startIndex]) {
+ int lastIndexOf(Object element, [int startIndex]) {
if (startIndex == null) {
startIndex = this.length - 1;
} else {
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 20cc84c..84e61e1 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -255,8 +255,9 @@
SplayTreeMap._internal();
- V operator [](K key) {
+ V operator [](Object key) {
if (key == null) throw new ArgumentError(key);
+ if (key is! K) return null;
if (_root != null) {
int comp = _splay(key);
if (comp == 0) {
@@ -337,11 +338,11 @@
_clear();
}
- bool containsKey(K key) {
- return _splay(key) == 0;
+ bool containsKey(Object key) {
+ return key is K && _splay(key) == 0;
}
- bool containsValue(V value) {
+ bool containsValue(Object value) {
bool found = false;
int initialSplayCount = _splayCount;
bool visit(_SplayTreeMapNode node) {
diff --git a/sdk/lib/core/double.dart b/sdk/lib/core/double.dart
index d07e9c2..0028f91 100644
--- a/sdk/lib/core/double.dart
+++ b/sdk/lib/core/double.dart
@@ -149,6 +149,9 @@
* used instead. If no handleError is provided, a [FormatException]
* is thrown.
*
+ * The [onError] function is only invoked if [source] is a [String]. It is
+ * not invoked if the [source] is, for example, `null`.
+ *
* Examples of accepted strings:
*
* "3.14"
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index a0cf1b6..a19c651 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -82,9 +82,12 @@
/**
* Multiplies this [Duration] by the given [factor] and returns the result
* as a new [Duration].
+ *
+ * Note that when [factor] is a double, and the duration is greater than
+ * 53 bits, precision is lost because of double-precision arithmetic.
*/
- Duration operator *(int factor) {
- return new Duration(microseconds: _duration * factor);
+ Duration operator *(num factor) {
+ return new Duration(microseconds: (_duration * factor).round());
}
/**
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 245fc49..060eba7 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -235,13 +235,6 @@
String toString() => "Stack Overflow";
}
-class FiftyThreeBitOverflowError implements Error {
- final Object value;
-
- const FiftyThreeBitOverflowError(this.value);
- String toString() => "53-bit Overflow: $value";
-}
-
/**
* Error thrown when a lazily initialized variable cannot be initialized.
*
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index 4518b7b..2dd2be2 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -111,6 +111,9 @@
* sign, the [onError] is called with the [source] as argument, and its return
* value is used instead. If no [onError] is provided, a [FormatException]
* is thrown.
+ *
+ * The [onError] function is only invoked if [source] is a [String]. It is
+ * not invoked if the [source] is, for example, `null`.
*/
external static int parse(String source,
{ int radix,
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 41972b9..9d919ae 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -76,7 +76,7 @@
/**
* Check whether the collection contains an element equal to [element].
*/
- bool contains(E element);
+ bool contains(Object element);
/**
* Applies the function [f] to each element of this collection.
@@ -171,6 +171,8 @@
*
* The returned [Iterable] may contain fewer than [n] elements, if `this`
* contains fewer than [n] elements.
+ *
+ * It is an error if [n] is negative.
*/
Iterable<E> take(int n);
@@ -191,6 +193,8 @@
*
* If `this` has fewer than [n] elements, then the resulting [Iterable] will
* be empty.
+ *
+ * It is an error if [n] is negative.
*/
Iterable<E> skip(int n);
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 419527e..7bb8b5d 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -295,7 +295,7 @@
List<E> sublist(int start, [int end]);
/**
- * Returns an [Iterable] that iterators over the elements in the range
+ * Returns an [Iterable] that iterates over the elements in the range
* [start] to [end] exclusive. The result of this function
* is backed by `this`.
*
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index 4f67ea1..88776c1 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -22,12 +22,12 @@
/**
* Returns whether this map contains the given [value].
*/
- bool containsValue(V value);
+ bool containsValue(Object value);
/**
* Returns whether this map contains the given [key].
*/
- bool containsKey(K key);
+ bool containsKey(Object key);
/**
* Returns the value for the given [key] or null if [key] is not
@@ -35,7 +35,7 @@
* use containsKey to distinguish between an absent key and a null
* value, or use the [putIfAbsent] method.
*/
- V operator [](K key);
+ V operator [](Object key);
/**
* Associates the [key] with the given [value].
@@ -69,7 +69,7 @@
* can be null and a returned null value does not always imply that the
* key is absent.
*/
- V remove(K key);
+ V remove(Object key);
/**
* Removes all pairs from the map.
@@ -86,7 +86,6 @@
/**
* The keys of [this].
*/
- // TODO(floitsch): this should return a [Set].
Iterable<K> get keys;
/**
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 19dbbe2..b9b3616 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -165,7 +165,7 @@
double toDouble();
/**
- * Converts [this] to a [double] and then gives string representation with
+ * Converts `this` to a [double] and returns its string representation with
* [fractionDigits] digits after the decimal point.
*
* The parameter [fractionDigits] must be an integer satisfying:
@@ -174,8 +174,9 @@
String toStringAsFixed(int fractionDigits);
/**
- * Converts [this] to a [double] and then gives a string in decimal
- * exponential notation with [fractionDigits] digits after the decimal point.
+ * Converts `this` to a [double] and returns its string representation in
+ * decimal exponential notation with [fractionDigits] digits after the decimal
+ * point.
*
* If [fractionDigits] is given then it must be an integer satisfying:
* [:0 <= fractionDigits <= 20:]. Without the parameter the returned string
@@ -184,11 +185,49 @@
String toStringAsExponential([int fractionDigits]);
/**
- * Converts [this] to a double and gives a string representation with
+ * Converts `this` to a double and returns its string representation with
* [precision] significant digits.
*
* The parameter [precision] must be an integer satisfying:
* [:1 <= precision <= 21:].
*/
String toStringAsPrecision(int precision);
+
+ /**
+ * Computes the shortest string of digits that correctly represent the input
+ * number.
+ *
+ * [double]s in the range `10^-6` (inclusive) to `10^21` (exclusive)
+ * are converted to their decimal representation with at least one digit
+ * after the decimal point. For all other doubles,
+ * except for special values like `NaN` or `Infinity`, this method returns an
+ * exponential representation (see [toStringAsExponential]).
+ *
+ * Returns `"NaN"` for [double.NAN], `"Infinity"` for [double.INFINITY], and
+ * `"-Infinity"` for [double.MINUS_INFINITY].
+ *
+ * [int]s are always converted to their decimal representation.
+ *
+ * Examples:
+ *
+ * (0.000001).toString(); // "0.000001"
+ * (0.0000001).toString(); // "1e-7"
+ * (111111111111111111111.0).toString(); // "111111111111111110000.0"
+ * (100000000000000000000.0).toString(); // "100000000000000000000.0"
+ * (1000000000000000000000.0).toString(); // "1e+21"
+ * (1111111111111111111111.0).toString(); // "1.1111111111111111e+21"
+ * 1.toString(); // "1"
+ * 111111111111111111111.toString(); // "111111111111111110000"
+ * 100000000000000000000.toString(); // "100000000000000000000"
+ * 1000000000000000000000.toString(); // "1000000000000000000000"
+ * 1111111111111111111111.toString(); // "1111111111111111111111"
+ *
+ * Note: the conversion may round the output if the returned string
+ * is accurate enough to uniquely identify the input-number.
+ * For example the most precise representation of the [double] `9e59` equals
+ * `"899999999999999918767229449717619953810131273674690656206848"`, but
+ * this method returns the shorter (but still correct) `"9e59"`.
+ *
+ */
+ String toString();
}
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index 7b5980e..aaab5ec 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -42,7 +42,7 @@
/**
* Returns true if [value] is in the set.
*/
- bool contains(E value);
+ bool contains(Object value);
/**
* Adds [value] into the set.
@@ -69,12 +69,12 @@
/**
* Removes each element of [elements] from this set.
*/
- void removeAll(Iterable elements);
+ void removeAll(Iterable<Object> elements);
/**
* Removes all elements of this set that are not elements in [elements].
*/
- void retainAll(Iterable elements);
+ void retainAll(Iterable<Object> elements);
/**
* Removes all elements of this set that satisfy [test].
@@ -89,7 +89,7 @@
/**
* Returns whether this Set contains all the elements of [other].
*/
- bool containsAll(Iterable<E> other);
+ bool containsAll(Iterable<Object> other);
/**
* Returns a new set which is the intersection between this set and [other].
@@ -97,7 +97,7 @@
* That is, the returned set contains all the elements of this `Set` that
* are also elements of [other].
*/
- Set<E> intersection(Set<E> other);
+ Set<E> intersection(Set<Object> other);
/**
* Returns a new set which contains all the elements of this set and [other].
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index 0d2503a..e2ffc23 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -106,8 +106,18 @@
/**
* Returns whether this string starts with a match of [pattern].
+ *
+ * If [index] is provided, instead check if the substring starting
+ * at that index starts with a match of [pattern].
+ *
+ * It is an error if [index] is negative or greater than [length].
+ *
+ * A [RegExp] containing "^" will not match if the [index] is greater than
+ * zero. The pattern works on the string as a whole, and does not extract
+ * a substring starting at [index] first. That is.
+ * "abc".startsWith(new RegExp("^.", 1)) == false
*/
- bool startsWith(Pattern pattern);
+ bool startsWith(Pattern pattern, [int index = 0]);
/**
* Returns the first position of a match of [pattern] in this string,
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index c0a7fdf..0eaee85 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -108,7 +108,7 @@
fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT]));
/**
- * Create a new URI from its components.
+ * Creates a new URI from its components.
*
* Each component is set through a named argument. Any number of
* components can be provided. The default value for the components
@@ -178,6 +178,91 @@
}
/**
+ * Creates a new `http` URI from authority, path and query.
+ *
+ * Examples:
+ *
+ * // Create the URI http://example.org/path?q=abc.
+ * new Uri.http("google.com", "/search", { "q" : "dart" });http://example.org/path?q=abc.
+ * new Uri.http("user:pass@localhost:8080, ""); // http://user:pass@localhost:8080/
+ * new Uri.http("example.org, "a b"); // http://example.org/a%20b
+ * new Uri.http("example.org, "/a%2F"); // http://example.org/a%25%2F
+ *
+ * The `scheme` is always set to `http`.
+ *
+ * The `userInfo`, `host` and `port` components are set from the
+ * [authority] argument.
+ *
+ * The `path` component is set from the [unencodedPath]
+ * argument. The path passed must not be encoded as this constructor
+ * encodes the path.
+ *
+ * The `query` component is set from the optional [queryParameters]
+ * argument.
+ */
+ factory Uri.http(String authority,
+ String unencodedPath,
+ [Map<String, String> queryParameters]) {
+ return _makeHttpUri("http", authority, unencodedPath, queryParameters);
+ }
+
+ /**
+ * Creates a new `https` URI from authority, path and query.
+ *
+ * This constructor is the same as [Uri.http] except for the scheme
+ * which is set to `https`.
+ */
+ factory Uri.https(String authority,
+ String unencodedPath,
+ [Map<String, String> queryParameters]) {
+ return _makeHttpUri("https", authority, unencodedPath, queryParameters);
+ }
+
+ static Uri _makeHttpUri(String scheme,
+ String authority,
+ String unencodedPath,
+ Map<String, String> queryParameters) {
+ var userInfo = "";
+ var host = "";
+ var port = 0;
+
+ var hostStart = 0;
+ // Split off the user info.
+ bool hasUserInfo = false;
+ for (int i = 0; i < authority.length; i++) {
+ if (authority.codeUnitAt(i) == _AT_SIGN) {
+ hasUserInfo = true;
+ userInfo = authority.substring(0, i);
+ hostStart = i + 1;
+ break;
+ }
+ }
+ // Split host and port.
+ bool hasPort = false;
+ for (int i = hostStart; i < authority.length; i++) {
+ if (authority.codeUnitAt(i) == _COLON) {
+ hasPort = true;
+ host = authority.substring(hostStart, i);
+ if (!host.isEmpty) {
+ var portString = authority.substring(i + 1);
+ if (portString.isNotEmpty) port = int.parse(portString);
+ }
+ break;
+ }
+ }
+ if (!hasPort) {
+ host = hasUserInfo ? authority.substring(hostStart) : authority;
+ }
+
+ return new Uri(scheme: scheme,
+ userInfo: userInfo,
+ host: host,
+ port: port,
+ pathSegments: unencodedPath.split("/"),
+ queryParameters: queryParameters);
+ }
+
+ /**
* Returns the URI path split into its segments. Each of the
* segments in the returned list have been decoded. If the path is
* empty the empty list will be returned. A leading slash `/` does
@@ -746,6 +831,7 @@
static const int _ZERO = 0x30;
static const int _NINE = 0x39;
static const int _COLON = 0x3A;
+ static const int _AT_SIGN = 0x40;
static const int _UPPER_CASE_A = 0x41;
static const int _UPPER_CASE_F = 0x46;
static const int _LOWER_CASE_A = 0x61;
@@ -1016,9 +1102,9 @@
final Map _map;
const _UnmodifiableMap(this._map);
- bool containsValue(V value) => _map.containsValue(value);
- bool containsKey(K key) => _map.containsKey(key);
- V operator [](K key) => _map[key];
+ bool containsValue(Object value) => _map.containsValue(value);
+ bool containsKey(Object key) => _map.containsKey(key);
+ V operator [](Object key) => _map[key];
void operator []=(K key, V value) {
throw new UnsupportedError("Cannot modify an unmodifiable map");
}
@@ -1028,7 +1114,7 @@
addAll(Map other) {
throw new UnsupportedError("Cannot modify an unmodifiable map");
}
- V remove(K key) {
+ V remove(Object key) {
throw new UnsupportedError("Cannot modify an unmodifiable map");
}
void clear() {
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index abafc22..8f155b4 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1,4 +1,8 @@
/// The Dart HTML library.
+///
+/// For examples, see
+/// [Dart HTML5 Samples](https://github.com/dart-lang/dart-html5-samples)
+/// on Github.
library dart.dom.html;
import 'dart:async';
@@ -16,7 +20,7 @@
import 'dart:web_gl' as gl;
import 'dart:web_sql';
import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
-import 'dart:_interceptors' show Interceptor;
+import 'dart:_interceptors' show Interceptor, JSExtendableArray;
import 'dart:_isolate_helper' show IsolateNatives;
import 'dart:_foreign_helper' show JS;
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -855,7 +859,7 @@
* var ctx = canvas.context2D
* ..fillStyle = "rgb(200,0,0)"
* ..fillRect(10, 10, 55, 50);
- * var dataUrl = canvas.toDataURL("image/jpeg", 0.95);
+ * var dataUrl = canvas.toDataUrl("image/jpeg", 0.95);
* // The Data Uri would look similar to
* // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
* // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
@@ -6770,6 +6774,10 @@
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#dom-document-visibilitystate
final String $dom_webkitVisibilityState;
+ @DomName('Document.adoptNode')
+ @DocsEditable
+ Node adoptNode(Node source) native;
+
@JSName('caretRangeFromPoint')
/// Use the [Range] constructor instead.
@DomName('Document.caretRangeFromPoint')
@@ -6888,6 +6896,10 @@
@Creates('NodeList')
List<Node> getElementsByTagName(String tagname) native;
+ @DomName('Document.importNode')
+ @DocsEditable
+ Node importNode(Node importedNode, [bool deep]) native;
+
@DomName('Document.queryCommandEnabled')
@DocsEditable
bool queryCommandEnabled(String command) native;
@@ -7624,7 +7636,7 @@
: _childElements = element.$dom_children,
_element = element;
- bool contains(Element element) => _childElements.contains(element);
+ bool contains(Object element) => _childElements.contains(element);
bool get isEmpty {
@@ -11990,7 +12002,7 @@
@SupportedBrowser(SupportedBrowser.FIREFOX)
@SupportedBrowser(SupportedBrowser.IE, '10')
@SupportedBrowser(SupportedBrowser.SAFARI)
- @Creates('ByteBuffer|Blob|Document|=Object|=List|String|num')
+ @Creates('ByteBuffer|Blob|Document|=Object|JSExtendableArray|String|num')
final Object response;
/**
@@ -13449,6 +13461,15 @@
// BSD-style license that can be found in the LICENSE file.
+/**
+ * An event that describes user interaction with the keyboard.
+ *
+ * The [type] of the event identifies what kind of interaction occurred.
+ *
+ * See also:
+ *
+ * * [KeyboardEvent](https://developer.mozilla.org/en/DOM/KeyboardEvent) at MDN.
+ */
@DomName('KeyboardEvent')
class KeyboardEvent extends UIEvent native "KeyboardEvent" {
@@ -15129,7 +15150,7 @@
@DomName('MessageEvent.ports')
@DocsEditable
@Unstable
- @Creates('=List')
+ @Creates('JSExtendableArray')
final List<MessagePort> ports;
WindowBase get source => _convertNativeToDart_Window(this._get_source);
@@ -22512,7 +22533,7 @@
*
* To receive data on the WebSocket, register a listener for message events.
*
- * webSocket.on.message.add((MessageEvent e) {
+ * webSocket.onMessage.listen((MessageEvent e) {
* receivedData(e.data);
* });
*
@@ -27468,293 +27489,6 @@
// BSD-style license that can be found in the LICENSE file.
-// This code is inspired by ChangeSummary:
-// https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
-// ...which underlies MDV. Since we don't need the functionality of
-// ChangeSummary, we just implement what we need for data bindings.
-// This allows our implementation to be much simpler.
-
-// TODO(jmesserly): should we make these types stronger, and require
-// Observable objects? Currently, it is fine to say something like:
-// var path = new PathObserver(123, '');
-// print(path.value); // "123"
-//
-// Furthermore this degenerate case is allowed:
-// var path = new PathObserver(123, 'foo.bar.baz.qux');
-// print(path.value); // "null"
-//
-// Here we see that any invalid (i.e. not Observable) value will break the
-// path chain without producing an error or exception.
-//
-// Now the real question: should we do this? For the former case, the behavior
-// is correct but we could chose to handle it in the dart:html bindings layer.
-// For the latter case, it might be better to throw an error so users can find
-// the problem.
-
-
-/**
- * A data-bound path starting from a view-model or model object, for example
- * `foo.bar.baz`.
- *
- * When the [values] stream is being listened to, this will observe changes to
- * the object and any intermediate object along the path, and send [values]
- * accordingly. When all listeners are unregistered it will stop observing
- * the objects.
- *
- * This class is used to implement [Node.bind] and similar functionality.
- */
-// TODO(jmesserly): find a better home for this type.
-@Experimental
-class PathObserver {
- /** The object being observed. */
- final object;
-
- /** The path string. */
- final String path;
-
- /** True if the path is valid, otherwise false. */
- final bool _isValid;
-
- // TODO(jmesserly): same issue here as ObservableMixin: is there an easier
- // way to get a broadcast stream?
- StreamController _values;
- Stream _valueStream;
-
- _PropertyObserver _observer, _lastObserver;
-
- Object _lastValue;
- bool _scheduled = false;
-
- /**
- * Observes [path] on [object] for changes. This returns an object that can be
- * used to get the changes and get/set the value at this path.
- * See [PathObserver.values] and [PathObserver.value].
- */
- PathObserver(this.object, String path)
- : path = path, _isValid = _isPathValid(path) {
-
- // TODO(jmesserly): if the path is empty, or the object is! Observable, we
- // can optimize the PathObserver to be more lightweight.
-
- _values = new StreamController.broadcast(sync: true,
- onListen: _observe,
- onCancel: _unobserve);
-
- if (_isValid) {
- var segments = [];
- for (var segment in path.trim().split('.')) {
- if (segment == '') continue;
- var index = int.parse(segment, onError: (_) {});
- segments.add(index != null ? index : new Symbol(segment));
- }
-
- // Create the property observer linked list.
- // Note that the structure of a path can't change after it is initially
- // constructed, even though the objects along the path can change.
- for (int i = segments.length - 1; i >= 0; i--) {
- _observer = new _PropertyObserver(this, segments[i], _observer);
- if (_lastObserver == null) _lastObserver = _observer;
- }
- }
- }
-
- // TODO(jmesserly): we could try adding the first value to the stream, but
- // that delivers the first record async.
- /**
- * Listens to the stream, and invokes the [callback] immediately with the
- * current [value]. This is useful for bindings, which want to be up-to-date
- * immediately.
- */
- StreamSubscription bindSync(void callback(value)) {
- var result = values.listen(callback);
- callback(value);
- return result;
- }
-
- // TODO(jmesserly): should this be a change record with the old value?
- // TODO(jmesserly): should this be a broadcast stream? We only need
- // single-subscription in the bindings system, so single sub saves overhead.
- /**
- * Gets the stream of values that were observed at this path.
- * This returns a single-subscription stream.
- */
- Stream get values => _values.stream;
-
- /** Force synchronous delivery of [values]. */
- void _deliverValues() {
- _scheduled = false;
-
- var newValue = value;
- if (!identical(_lastValue, newValue)) {
- _values.add(newValue);
- _lastValue = newValue;
- }
- }
-
- void _observe() {
- if (_observer != null) {
- _lastValue = value;
- _observer.observe();
- }
- }
-
- void _unobserve() {
- if (_observer != null) _observer.unobserve();
- }
-
- void _notifyChange() {
- if (_scheduled) return;
- _scheduled = true;
-
- // TODO(jmesserly): should we have a guarenteed order with respect to other
- // paths? If so, we could implement this fairly easily by sorting instances
- // of this class by birth order before delivery.
- queueChangeRecords(_deliverValues);
- }
-
- /** Gets the last reported value at this path. */
- get value {
- if (!_isValid) return null;
- if (_observer == null) return object;
- _observer.ensureValue(object);
- return _lastObserver.value;
- }
-
- /** Sets the value at this path. */
- void set value(Object value) {
- // TODO(jmesserly): throw if property cannot be set?
- // MDV seems tolerant of these error.
- if (_observer == null || !_isValid) return;
- _observer.ensureValue(object);
- var last = _lastObserver;
- if (_setObjectProperty(last._object, last._property, value)) {
- // Technically, this would get updated asynchronously via a change record.
- // However, it is nice if calling the getter will yield the same value
- // that was just set. So we use this opportunity to update our cache.
- last.value = value;
- }
- }
-}
-
-// TODO(jmesserly): these should go away in favor of mirrors!
-_getObjectProperty(object, property) {
- if (object is List && property is int) {
- if (property >= 0 && property < object.length) {
- return object[property];
- } else {
- return null;
- }
- }
-
- // TODO(jmesserly): what about length?
- if (object is Map) return object[property];
-
- if (object is Observable) return object.getValueWorkaround(property);
-
- return null;
-}
-
-bool _setObjectProperty(object, property, value) {
- if (object is List && property is int) {
- object[property] = value;
- } else if (object is Map) {
- object[property] = value;
- } else if (object is Observable) {
- (object as Observable).setValueWorkaround(property, value);
- } else {
- return false;
- }
- return true;
-}
-
-
-class _PropertyObserver {
- final PathObserver _path;
- final _property;
- final _PropertyObserver _next;
-
- // TODO(jmesserly): would be nice not to store both of these.
- Object _object;
- Object _value;
- StreamSubscription _sub;
-
- _PropertyObserver(this._path, this._property, this._next);
-
- get value => _value;
-
- void set value(Object newValue) {
- _value = newValue;
- if (_next != null) {
- if (_sub != null) _next.unobserve();
- _next.ensureValue(_value);
- if (_sub != null) _next.observe();
- }
- }
-
- void ensureValue(object) {
- // If we're observing, values should be up to date already.
- if (_sub != null) return;
-
- _object = object;
- value = _getObjectProperty(object, _property);
- }
-
- void observe() {
- if (_object is Observable) {
- assert(_sub == null);
- _sub = (_object as Observable).changes.listen(_onChange);
- }
- if (_next != null) _next.observe();
- }
-
- void unobserve() {
- if (_sub == null) return;
-
- _sub.cancel();
- _sub = null;
- if (_next != null) _next.unobserve();
- }
-
- void _onChange(List<ChangeRecord> changes) {
- for (var change in changes) {
- // TODO(jmesserly): what to do about "new Symbol" here?
- // Ideally this would only preserve names if the user has opted in to
- // them being preserved.
- // TODO(jmesserly): should we drop observable maps with String keys?
- // If so then we only need one check here.
- if (change.changes(_property)) {
- value = _getObjectProperty(_object, _property);
- _path._notifyChange();
- return;
- }
- }
- }
-}
-
-// From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
-
-const _pathIndentPart = r'[$a-z0-9_]+[$a-z0-9_\d]*';
-final _pathRegExp = new RegExp('^'
- '(?:#?' + _pathIndentPart + ')?'
- '(?:'
- '(?:\\.' + _pathIndentPart + ')'
- ')*'
- r'$', caseSensitive: false);
-
-final _spacesRegExp = new RegExp(r'\s');
-
-bool _isPathValid(String s) {
- s = s.replaceAll(_spacesRegExp, '');
-
- if (s == '') return true;
- if (s[0] == '.') return false;
- return _pathRegExp.hasMatch(s);
-}
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-
/**
* A utility class for representing two-dimensional positions.
*/
@@ -29433,9 +29167,9 @@
void sort([int compare(E a, E b)]) { _list.sort(compare); }
- int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+ int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
- int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+ int lastIndexOf(Object element, [int start]) => _list.lastIndexOf(element, start);
void insert(int index, E element) => _list.insert(index, element);
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index a97473f..0e28ef6 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -1,4 +1,8 @@
/// The Dart HTML library.
+///
+/// For examples, see
+/// [Dart HTML5 Samples](https://github.com/dart-lang/dart-html5-samples)
+/// on Github.
library dart.dom.html;
import 'dart:async';
@@ -1057,7 +1061,7 @@
* var ctx = canvas.context2D
* ..fillStyle = "rgb(200,0,0)"
* ..fillRect(10, 10, 55, 50);
- * var dataUrl = canvas.toDataURL("image/jpeg", 0.95);
+ * var dataUrl = canvas.toDataUrl("image/jpeg", 0.95);
* // The Data Uri would look similar to
* // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
* // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
@@ -7326,6 +7330,10 @@
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#dom-document-visibilitystate
String get $dom_webkitVisibilityState native "Document_webkitVisibilityState_Getter";
+ @DomName('Document.adoptNode')
+ @DocsEditable
+ Node adoptNode(Node source) native "Document_adoptNode_Callback";
+
/// Use the [Range] constructor instead.
@DomName('Document.caretRangeFromPoint')
@DocsEditable
@@ -7436,6 +7444,17 @@
@DocsEditable
List<Node> getElementsByTagName(String tagname) native "Document_getElementsByTagName_Callback";
+ Node importNode(Node importedNode, [bool deep]) {
+ if (deep != null) {
+ return _importNode_1(importedNode, deep);
+ }
+ return _importNode_2(importedNode);
+ }
+
+ Node _importNode_1(importedNode, deep) native "Document__importNode_1_Callback";
+
+ Node _importNode_2(importedNode) native "Document__importNode_2_Callback";
+
@DomName('Document.queryCommandEnabled')
@DocsEditable
bool queryCommandEnabled(String command) native "Document_queryCommandEnabled_Callback";
@@ -8182,7 +8201,7 @@
: _childElements = element.$dom_children,
_element = element;
- bool contains(Element element) => _childElements.contains(element);
+ bool contains(Object element) => _childElements.contains(element);
bool get isEmpty {
@@ -24422,7 +24441,7 @@
*
* To receive data on the WebSocket, register a listener for message events.
*
- * webSocket.on.message.add((MessageEvent e) {
+ * webSocket.onMessage.listen((MessageEvent e) {
* receivedData(e.data);
* });
*
@@ -29464,293 +29483,6 @@
// BSD-style license that can be found in the LICENSE file.
-// This code is inspired by ChangeSummary:
-// https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
-// ...which underlies MDV. Since we don't need the functionality of
-// ChangeSummary, we just implement what we need for data bindings.
-// This allows our implementation to be much simpler.
-
-// TODO(jmesserly): should we make these types stronger, and require
-// Observable objects? Currently, it is fine to say something like:
-// var path = new PathObserver(123, '');
-// print(path.value); // "123"
-//
-// Furthermore this degenerate case is allowed:
-// var path = new PathObserver(123, 'foo.bar.baz.qux');
-// print(path.value); // "null"
-//
-// Here we see that any invalid (i.e. not Observable) value will break the
-// path chain without producing an error or exception.
-//
-// Now the real question: should we do this? For the former case, the behavior
-// is correct but we could chose to handle it in the dart:html bindings layer.
-// For the latter case, it might be better to throw an error so users can find
-// the problem.
-
-
-/**
- * A data-bound path starting from a view-model or model object, for example
- * `foo.bar.baz`.
- *
- * When the [values] stream is being listened to, this will observe changes to
- * the object and any intermediate object along the path, and send [values]
- * accordingly. When all listeners are unregistered it will stop observing
- * the objects.
- *
- * This class is used to implement [Node.bind] and similar functionality.
- */
-// TODO(jmesserly): find a better home for this type.
-@Experimental
-class PathObserver {
- /** The object being observed. */
- final object;
-
- /** The path string. */
- final String path;
-
- /** True if the path is valid, otherwise false. */
- final bool _isValid;
-
- // TODO(jmesserly): same issue here as ObservableMixin: is there an easier
- // way to get a broadcast stream?
- StreamController _values;
- Stream _valueStream;
-
- _PropertyObserver _observer, _lastObserver;
-
- Object _lastValue;
- bool _scheduled = false;
-
- /**
- * Observes [path] on [object] for changes. This returns an object that can be
- * used to get the changes and get/set the value at this path.
- * See [PathObserver.values] and [PathObserver.value].
- */
- PathObserver(this.object, String path)
- : path = path, _isValid = _isPathValid(path) {
-
- // TODO(jmesserly): if the path is empty, or the object is! Observable, we
- // can optimize the PathObserver to be more lightweight.
-
- _values = new StreamController.broadcast(sync: true,
- onListen: _observe,
- onCancel: _unobserve);
-
- if (_isValid) {
- var segments = [];
- for (var segment in path.trim().split('.')) {
- if (segment == '') continue;
- var index = int.parse(segment, onError: (_) {});
- segments.add(index != null ? index : new Symbol(segment));
- }
-
- // Create the property observer linked list.
- // Note that the structure of a path can't change after it is initially
- // constructed, even though the objects along the path can change.
- for (int i = segments.length - 1; i >= 0; i--) {
- _observer = new _PropertyObserver(this, segments[i], _observer);
- if (_lastObserver == null) _lastObserver = _observer;
- }
- }
- }
-
- // TODO(jmesserly): we could try adding the first value to the stream, but
- // that delivers the first record async.
- /**
- * Listens to the stream, and invokes the [callback] immediately with the
- * current [value]. This is useful for bindings, which want to be up-to-date
- * immediately.
- */
- StreamSubscription bindSync(void callback(value)) {
- var result = values.listen(callback);
- callback(value);
- return result;
- }
-
- // TODO(jmesserly): should this be a change record with the old value?
- // TODO(jmesserly): should this be a broadcast stream? We only need
- // single-subscription in the bindings system, so single sub saves overhead.
- /**
- * Gets the stream of values that were observed at this path.
- * This returns a single-subscription stream.
- */
- Stream get values => _values.stream;
-
- /** Force synchronous delivery of [values]. */
- void _deliverValues() {
- _scheduled = false;
-
- var newValue = value;
- if (!identical(_lastValue, newValue)) {
- _values.add(newValue);
- _lastValue = newValue;
- }
- }
-
- void _observe() {
- if (_observer != null) {
- _lastValue = value;
- _observer.observe();
- }
- }
-
- void _unobserve() {
- if (_observer != null) _observer.unobserve();
- }
-
- void _notifyChange() {
- if (_scheduled) return;
- _scheduled = true;
-
- // TODO(jmesserly): should we have a guarenteed order with respect to other
- // paths? If so, we could implement this fairly easily by sorting instances
- // of this class by birth order before delivery.
- queueChangeRecords(_deliverValues);
- }
-
- /** Gets the last reported value at this path. */
- get value {
- if (!_isValid) return null;
- if (_observer == null) return object;
- _observer.ensureValue(object);
- return _lastObserver.value;
- }
-
- /** Sets the value at this path. */
- void set value(Object value) {
- // TODO(jmesserly): throw if property cannot be set?
- // MDV seems tolerant of these error.
- if (_observer == null || !_isValid) return;
- _observer.ensureValue(object);
- var last = _lastObserver;
- if (_setObjectProperty(last._object, last._property, value)) {
- // Technically, this would get updated asynchronously via a change record.
- // However, it is nice if calling the getter will yield the same value
- // that was just set. So we use this opportunity to update our cache.
- last.value = value;
- }
- }
-}
-
-// TODO(jmesserly): these should go away in favor of mirrors!
-_getObjectProperty(object, property) {
- if (object is List && property is int) {
- if (property >= 0 && property < object.length) {
- return object[property];
- } else {
- return null;
- }
- }
-
- // TODO(jmesserly): what about length?
- if (object is Map) return object[property];
-
- if (object is Observable) return object.getValueWorkaround(property);
-
- return null;
-}
-
-bool _setObjectProperty(object, property, value) {
- if (object is List && property is int) {
- object[property] = value;
- } else if (object is Map) {
- object[property] = value;
- } else if (object is Observable) {
- (object as Observable).setValueWorkaround(property, value);
- } else {
- return false;
- }
- return true;
-}
-
-
-class _PropertyObserver {
- final PathObserver _path;
- final _property;
- final _PropertyObserver _next;
-
- // TODO(jmesserly): would be nice not to store both of these.
- Object _object;
- Object _value;
- StreamSubscription _sub;
-
- _PropertyObserver(this._path, this._property, this._next);
-
- get value => _value;
-
- void set value(Object newValue) {
- _value = newValue;
- if (_next != null) {
- if (_sub != null) _next.unobserve();
- _next.ensureValue(_value);
- if (_sub != null) _next.observe();
- }
- }
-
- void ensureValue(object) {
- // If we're observing, values should be up to date already.
- if (_sub != null) return;
-
- _object = object;
- value = _getObjectProperty(object, _property);
- }
-
- void observe() {
- if (_object is Observable) {
- assert(_sub == null);
- _sub = (_object as Observable).changes.listen(_onChange);
- }
- if (_next != null) _next.observe();
- }
-
- void unobserve() {
- if (_sub == null) return;
-
- _sub.cancel();
- _sub = null;
- if (_next != null) _next.unobserve();
- }
-
- void _onChange(List<ChangeRecord> changes) {
- for (var change in changes) {
- // TODO(jmesserly): what to do about "new Symbol" here?
- // Ideally this would only preserve names if the user has opted in to
- // them being preserved.
- // TODO(jmesserly): should we drop observable maps with String keys?
- // If so then we only need one check here.
- if (change.changes(_property)) {
- value = _getObjectProperty(_object, _property);
- _path._notifyChange();
- return;
- }
- }
- }
-}
-
-// From: https://github.com/rafaelw/ChangeSummary/blob/master/change_summary.js
-
-const _pathIndentPart = r'[$a-z0-9_]+[$a-z0-9_\d]*';
-final _pathRegExp = new RegExp('^'
- '(?:#?' + _pathIndentPart + ')?'
- '(?:'
- '(?:\\.' + _pathIndentPart + ')'
- ')*'
- r'$', caseSensitive: false);
-
-final _spacesRegExp = new RegExp(r'\s');
-
-bool _isPathValid(String s) {
- s = s.replaceAll(_spacesRegExp, '');
-
- if (s == '') return true;
- if (s[0] == '.') return false;
- return _pathRegExp.hasMatch(s);
-}
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// 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.
-
-
/**
* A utility class for representing two-dimensional positions.
*/
@@ -30847,9 +30579,9 @@
void sort([int compare(E a, E b)]) { _list.sort(compare); }
- int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+ int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
- int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+ int lastIndexOf(Object element, [int start]) => _list.lastIndexOf(element, start);
void insert(int index, E element) => _list.insert(index, element);
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index 12591d5..b387f41 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.dart
@@ -34,7 +34,8 @@
Map convertNativeToDart_Dictionary(object) {
if (object == null) return null;
var dict = {};
- for (final key in JS('=List', 'Object.getOwnPropertyNames(#)', object)) {
+ var keys = JS('JSExtendableArray', 'Object.getOwnPropertyNames(#)', object);
+ for (final key in keys) {
dict[key] = JS('var', '#[#]', object, key);
}
return dict;
@@ -165,7 +166,7 @@
var copy = readSlot(slot);
if (copy != null) {
if (true == copy) { // Cycle, so commit to making a copy.
- copy = JS('=List', 'new Array(#)', length);
+ copy = JS('JSExtendableArray', 'new Array(#)', length);
writeSlot(slot, copy);
}
return copy;
@@ -175,7 +176,7 @@
// Always clone the list, as it may have non-native properties or methods
// from interceptors and such.
- copy = JS('=List', 'new Array(#)', length);
+ copy = JS('JSExtendableArray', 'new Array(#)', length);
writeSlot(slot, copy);
for ( ; i < length; i++) {
@@ -254,7 +255,7 @@
copy = {};
writeSlot(slot, copy);
- for (final key in JS('=List', 'Object.keys(#)', e)) {
+ for (final key in JS('JSExtendableArray', 'Object.keys(#)', e)) {
copy[key] = walk(JS('var', '#[#]', e, key));
}
return copy;
@@ -268,7 +269,7 @@
int length = e.length;
// Since a JavaScript Array is an instance of Dart List, we can modify it
// in-place unless we must copy.
- copy = mustCopy ? JS('=List', 'new Array(#)', length) : e;
+ copy = mustCopy ? JS('JSExtendableArray', 'new Array(#)', length) : e;
writeSlot(slot, copy);
for (int i = 0; i < length; i++) {
@@ -342,7 +343,7 @@
const String _serializedScriptValue =
'num|String|bool|'
- '=List|=Object|'
+ 'JSExtendableArray|=Object|'
'Blob|File|ByteBuffer|TypedData'
// TODO(sra): Add Date, RegExp.
;
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index ab17d10..18a80e71 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.dart
@@ -174,9 +174,9 @@
Iterable<String> skip(int n) => readClasses().skip(n);
Iterable<String> skipWhile(bool test(String value)) =>
readClasses().skipWhile(test);
- String firstWhere(bool test(String value), { String orElse() }) =>
+ dynamic firstWhere(bool test(String value), { Object orElse() }) =>
readClasses().firstWhere(test, orElse: orElse);
- String lastWhere(bool test(String value), {String orElse()}) =>
+ dynamic lastWhere(bool test(String value), { Object orElse()}) =>
readClasses().lastWhere(test, orElse: orElse);
String singleWhere(bool test(String value)) =>
readClasses().singleWhere(test);
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index 61954e6..64326a4 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.dart
@@ -59,8 +59,10 @@
}
}
- bool contains(Element element) {
- return (element != null) && (element.parentNode == _node);
+ bool contains(Object needle) {
+ if (needle is! Element) return false;
+ Element element = needle;
+ return element.parentNode == _node;
}
Iterable<Element> get reversed => _filtered.reversed;
diff --git a/sdk/lib/html/html_common/html_common_dart2js.dart b/sdk/lib/html/html_common/html_common_dart2js.dart
index ed42991..dbf9352 100644
--- a/sdk/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk/lib/html/html_common/html_common_dart2js.dart
@@ -9,6 +9,7 @@
import 'dart:typed_data';
import 'dart:_js_helper' show Creates, Returns;
import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSExtendableArray;
import 'metadata.dart';
export 'metadata.dart';
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 9dd0d9a..e8ab65e 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -6,6 +6,7 @@
import 'dart:typed_data';
import 'dart:_js_helper' show Creates, Returns, JSName, Null;
import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSExtendableArray;
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// 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.
@@ -128,8 +129,8 @@
return convertNativeToDart_AcceptStructuredClone(object, mustCopy: false);
}
-
-const String _idbKey = '=List|=Object|num|String'; // TODO(sra): Add DateTime.
+// TODO(sra): Add DateTime.
+const String _idbKey = 'JSExtendableArray|=Object|num|String';
const _annotation_Creates_IDBKey = const Creates(_idbKey);
const _annotation_Returns_IDBKey = const Returns(_idbKey);
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index f47ef4f..4472fcb 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -237,16 +237,35 @@
return new Directory(newPath);
}
+ static String _trimTrailingPathSeparators(String path) {
+ // Don't handle argument errors here.
+ if (path is! String) return path;
+ if (Platform.operatingSystem == 'windows') {
+ while (path.length > 1 &&
+ (path.endsWith(Platform.pathSeparator) ||
+ path.endsWith('/'))) {
+ path = path.substring(0, path.length - 1);
+ }
+ } else {
+ while (path.length > 1 && path.endsWith(Platform.pathSeparator)) {
+ path = path.substring(0, path.length - 1);
+ }
+ }
+ return path;
+ }
+
Stream<FileSystemEntity> list({bool recursive: false,
bool followLinks: true}) {
- return new _AsyncDirectoryLister(path, recursive, followLinks).stream;
+ return new _AsyncDirectoryLister(_trimTrailingPathSeparators(path),
+ recursive,
+ followLinks).stream;
}
List listSync({bool recursive: false, bool followLinks: true}) {
- if (_path is! String || recursive is! bool) {
+ if (_path is! String || recursive is! bool || followLinks is! bool) {
throw new ArgumentError();
}
- return _list(_path, recursive, followLinks);
+ return _list(_trimTrailingPathSeparators(path), recursive, followLinks);
}
String get path => _path;
@@ -308,7 +327,8 @@
bool this.followLinks) {
controller = new StreamController(onListen: onListen,
onResume: onResume,
- onCancel: onCancel);
+ onCancel: onCancel,
+ sync: true);
}
Stream get stream => controller.stream;
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index 7a59c19..1fc9a17 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -994,10 +994,12 @@
// Transformer that transforms data to HTTP Chunked Encoding.
class _ChunkedTransformer extends StreamEventTransformer<List<int>, List<int>> {
+ int _pendingFooter = 0;
+
void handleData(List<int> data, EventSink<List<int>> sink) {
sink.add(_chunkHeader(data.length));
if (data.length > 0) sink.add(data);
- sink.add(_chunkFooter);
+ _pendingFooter = 2;
}
void handleDone(EventSink<List<int>> sink) {
@@ -1005,25 +1007,41 @@
sink.close();
}
- static List<int> _chunkHeader(int length) {
+ List<int> _chunkHeader(int length) {
const hexDigits = const [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46];
- var header = [];
if (length == 0) {
- header.add(hexDigits[length]);
- } else {
- while (length > 0) {
- header.insert(0, hexDigits[length % 16]);
- length = length >> 4;
- }
+ if (_pendingFooter == 2) return _footerAndChunk0Length;
+ return _chunk0Length;
}
- header.add(_CharCode.CR);
- header.add(_CharCode.LF);
- return header;
+ int size = _pendingFooter;
+ int len = length;
+ // Compute a fast integer version of (log(length + 1) / log(16)).ceil().
+ while (len > 0) {
+ size++;
+ len >>= 4;
+ }
+ var footerAndHeader = new Uint8List(size + 2);
+ if (_pendingFooter == 2) {
+ footerAndHeader[0] = _CharCode.CR;
+ footerAndHeader[1] = _CharCode.LF;
+ }
+ int index = size;
+ while (index > _pendingFooter) {
+ footerAndHeader[--index] = hexDigits[length & 15];
+ length = length >> 4;
+ }
+ footerAndHeader[size + 0] = _CharCode.CR;
+ footerAndHeader[size + 1] = _CharCode.LF;
+ return footerAndHeader;
}
- // Footer is just a CRLF.
- static List<int> get _chunkFooter => const [_CharCode.CR, _CharCode.LF];
+ static List<int> get _footerAndChunk0Length => new Uint8List.fromList(
+ const [_CharCode.CR, _CharCode.LF, 0x30, _CharCode.CR, _CharCode.LF,
+ _CharCode.CR, _CharCode.LF]);
+
+ static List<int> get _chunk0Length => new Uint8List.fromList(
+ const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF]);
}
@@ -2364,7 +2382,7 @@
}
String _getHttpVersion() {
- var version = new Options().version;
+ var version = Platform.version;
// Only include major and minor version numbers.
int index = version.indexOf('.', version.indexOf('.') + 1);
version = version.substring(0, index);
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index f863e4fc..d885008 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -660,7 +660,7 @@
_index--;
int dataAvailable = _buffer.length - _index;
List<int> data;
- if (_remainingContent == null ||
+ if (_remainingContent == -1 ||
dataAvailable <= _remainingContent) {
if (_index == 0) {
data = _buffer;
@@ -673,7 +673,7 @@
data.setRange(0, _remainingContent, _buffer, _index);
}
_bodyController.add(data);
- if (_remainingContent != null) {
+ if (_remainingContent != -1) {
_remainingContent -= data.length;
}
_index += data.length;
@@ -814,6 +814,8 @@
_method_or_status_code = new List();
_uri_or_reason_phrase = new List();
+ _statusCode = 0;
+
_httpVersion = _HttpVersion.UNDETERMINED;
_transferLength = -1;
_persistentConnection = false;
@@ -822,7 +824,7 @@
_noMessageBody = false;
_responseToMethod = null;
- _remainingContent = null;
+ _remainingContent = -1;
_headers = null;
}
@@ -961,21 +963,21 @@
int _state;
int _httpVersionIndex;
int _messageType;
- int _statusCode;
+ int _statusCode = 0;
List _method_or_status_code;
List _uri_or_reason_phrase;
List _headerField;
List _headerValue;
int _httpVersion;
- int _transferLength;
+ int _transferLength = -1;
bool _persistentConnection;
bool _connectionUpgrade;
bool _chunked;
bool _noMessageBody;
String _responseToMethod; // Indicates the method used for the request.
- int _remainingContent;
+ int _remainingContent = -1;
_HttpHeaders _headers;
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 955622f..e8c4a49 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -146,7 +146,7 @@
target = _makeWindowsLinkTarget(target);
}
var result = _File._createLink(path, target);
- throwIfError(result, "Cannot create link '$path'");
+ throwIfError(result, "Cannot create link", path);
}
// Put target into the form "\??\C:\my\target\dir".
@@ -155,12 +155,16 @@
return target;
}
if (!(target.length > 3 && target[1] == ':' && target[2] == '\\')) {
- target = new File(target).fullPathSync();
+ try {
+ target = new File(target).fullPathSync();
+ } catch (e) {
+ throw new LinkException('Could not locate target', target, e.osError);
+ }
}
if (target.length > 3 && target[1] == ':' && target[2] == '\\') {
target = '\\??\\$target';
} else {
- throw new ArgumentError(
+ throw new LinkException(
'Target $target of Link.create on Windows cannot be converted' +
' to start with a drive letter. Unexpected error.');
}
@@ -188,7 +192,7 @@
void deleteSync() {
var result = _File._deleteLink(path);
- throwIfError(result, "Cannot delete link '$path'");
+ throwIfError(result, "Cannot delete link", path);
}
Future<String> target() {
@@ -207,13 +211,13 @@
String targetSync() {
var result = _File._linkTarget(path);
- throwIfError(result, "Cannot read link '$path'");
+ throwIfError(result, "Cannot read link", path);
return result;
}
- static throwIfError(Object result, String msg) {
+ static throwIfError(Object result, String msg, [String path = ""]) {
if (result is OSError) {
- throw new LinkException(msg, result);
+ throw new LinkException(msg, path, result);
}
}
@@ -245,8 +249,8 @@
class LinkException implements IOException {
const LinkException([String this.message = "",
- String this.path = "",
- OSError this.osError = null]);
+ String this.path = "",
+ OSError this.osError = null]);
String toString() {
StringBuffer sb = new StringBuffer();
sb.write("LinkException");
diff --git a/sdk/lib/io/options.dart b/sdk/lib/io/options.dart
index 7b483e5..08dd129 100644
--- a/sdk/lib/io/options.dart
+++ b/sdk/lib/io/options.dart
@@ -44,12 +44,17 @@
/**
- * Returns the version of the current dart runtime.
+ * Returns the version of the current Dart runtime.
*/
String get version;
}
class _OptionsImpl implements Options {
+ List<String> _arguments = null;
+
+ // This arguments singleton is written to by the embedder if applicable.
+ static List<String> _nativeArguments = const [];
+
List<String> get arguments {
if (_arguments == null) {
// On first access make a copy of the native arguments.
@@ -58,24 +63,7 @@
return _arguments;
}
- String get executable {
- return _nativeExecutable;
- }
-
- String get script {
- return _nativeScript;
- }
-
- external String get version;
-
- List<String> _arguments = null;
-
- // This arguments singleton is written to by the embedder if applicable.
- static List<String> _nativeArguments = const [];
-
- // This executable singleton is written to by the embedder if applicable.
- static String _nativeExecutable = '';
-
- // This script singleton is written to by the embedder if applicable.
- static String _nativeScript = '';
+ String get executable => Platform.executable;
+ String get script => Platform.script;
+ String get version => Platform.version;
}
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index 156238a..90fe65a 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.dart
@@ -9,27 +9,59 @@
* system.
*/
class Platform {
+ static final _numberOfProcessors = _Platform.numberOfProcessors;
+ static final _pathSeparator = _Platform.pathSeparator;
+ static final _operatingSystem = _Platform.operatingSystem;
+ static final _localHostname = _Platform.localHostname;
+ static final _version = _Platform.version;
+
+ // This executable singleton is written to by the embedder if applicable.
+ static String _nativeExecutable = '';
+
+ // This script singleton is written to by the embedder if applicable.
+ static String _nativeScript = '';
+
/**
* Get the number of processors of the machine.
*/
- static int get numberOfProcessors => _Platform.numberOfProcessors;
+ static int get numberOfProcessors => _numberOfProcessors;
/**
* Get the path separator used by the operating system to separate
* components in file paths.
*/
- static String get pathSeparator => _Platform.pathSeparator;
+ static String get pathSeparator => _pathSeparator;
/**
- * Get a string ('macos', 'windows', 'linux') representing the
- * operating system.
+ * Get a string (`linux`, `macos`, `windows` or `android`)
+ * representing the operating system.
*/
- static String get operatingSystem => _Platform.operatingSystem;
+ static String get operatingSystem => _operatingSystem;
/**
* Get the local hostname for the system.
*/
- static String get localHostname => _Platform.localHostname;
+ static String get localHostname => _localHostname;
+
+ /**
+ * Returns true if the operating system is Linux.
+ */
+ static bool get isLinux => _operatingSystem == "linux";
+
+ /**
+ * Returns true if the operating system is Mac OS.
+ */
+ static bool get isMacOS => _operatingSystem == "macos";
+
+ /**
+ * Returns true if the operating system is Windows.
+ */
+ static bool get isWindows => _operatingSystem == "windows";
+
+ /**
+ * Returns true if the operating system is Android.
+ */
+ static bool get isAndroid => _operatingSystem == "android";
/**
* Get the environment for this process.
@@ -40,4 +72,27 @@
* a standard case-sensitive map.
*/
static Map<String, String> get environment => _Platform.environment;
+
+ /**
+ * Returns the path of the executable used to run the script in this
+ * isolate.
+ *
+ * If the execution environment does not support [executable] an empty
+ * string is returned.
+ */
+ static String get executable => _nativeExecutable;
+
+ /**
+ * Returns the path of the script being run in this isolate.
+ *
+ * If the executable environment does not support [script] an empty
+ * string is returned.
+ */
+ static String get script => _nativeScript;
+
+
+ /**
+ * Returns the version of the current Dart runtime.
+ */
+ static String get version => _version;
}
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index 89fc2a0..b9bae78 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.dart
@@ -10,18 +10,11 @@
external static String _operatingSystem();
external static _localHostname();
external static _environment();
+ external static String _version();
- static int get numberOfProcessors {
- return _numberOfProcessors();
- }
-
- static String get pathSeparator {
- return _pathSeparator();
- }
-
- static String get operatingSystem {
- return _operatingSystem();
- }
+ static int get numberOfProcessors => _numberOfProcessors();
+ static String get pathSeparator => _pathSeparator();
+ static String get operatingSystem => _operatingSystem();
static String get localHostname {
var result = _localHostname();
@@ -57,6 +50,8 @@
return result;
}
}
+
+ static String get version => _version();
}
// Environment variables are case-insensitive on Windows. In order
@@ -72,7 +67,7 @@
}
bool containsKey(String key) => _map.containsKey(key.toUpperCase());
- bool containsValue(V value) => _map.containsValue(value);
+ bool containsValue(Object value) => _map.containsValue(value);
V operator [](String key) => _map[key.toUpperCase()];
void operator []=(String key, V value) {
_map[key.toUpperCase()] = value;
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 6c79c12..456d215 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -83,6 +83,10 @@
* if an environment variable with code-points outside the US-ASCII range is
* passed in.
*
+ * If [includeParentEnvironment] is `true`, the process's environment will
+ * include the parent process's environment, with [environment] taking
+ * precedence. Default is `true`.
+ *
* If [runInShell] is true, the process will be spawned through a system
* shell. On Linux and Mac OS, [:/bin/sh:] is used, while
* [:%WINDIR%\system32\cmd.exe:] is used on Windows.
@@ -97,6 +101,7 @@
List<String> arguments,
{String workingDirectory,
Map<String, String> environment,
+ bool includeParentEnvironment: true,
bool runInShell: false});
/**
@@ -114,6 +119,10 @@
* if an environment variable with code-points outside the US-ASCII range is
* passed in.
*
+ * If [includeParentEnvironment] is `true`, the process's environment will
+ * include the parent process's environment, with [environment] taking
+ * precedence. Default is `true`.
+ *
* If [runInShell] is true, the process will be spawned through a system
* shell. On Linux and Mac OS, `/bin/sh` is used, while
* `%WINDIR%\system32\cmd.exe` is used on Windows.
@@ -133,6 +142,7 @@
List<String> arguments,
{String workingDirectory,
Map<String, String> environment,
+ bool includeParentEnvironment: true,
bool runInShell: false,
Encoding stdoutEncoding: Encoding.SYSTEM,
Encoding stderrEncoding: Encoding.SYSTEM});
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index d6f5734..8733f32 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -57,7 +57,7 @@
*
* If the [socket] already has a subscription, this subscription
* will no longer receive and events. In most cases calling
- * [:pause:] on this subscription before starting TLS handshake is
+ * `pause` on this subscription before starting TLS handshake is
* the right thing to do.
*
* If the [host] argument is passed it will be used as the host name
@@ -65,6 +65,12 @@
* the [socket] will be used. The [host] can be either a [String] or
* an [InternetAddress].
*
+ * Calling this function will _not_ cause a DNS host lookup. If the
+ * [host] passed is a [String] the [InternetAddress] for the
+ * resulting [SecureSocket] will have the passed in [host] as its
+ * host value and the internet address of the already connected
+ * socket as its address value.
+ *
* See [connect] for more information on the arguments.
*
*/
@@ -144,16 +150,18 @@
X509Certificate get peerCertificate;
/**
- * Initializes the NSS library. If [initialize] is not called, the library
+ * Initializes the NSS library. If [initialize] is not called, the library
* is automatically initialized as if [initialize] were called with no
- * arguments.
+ * arguments. If [initialize] is called more than once, or called after
+ * automatic initialization has happened (when a secure connection is made),
+ * then a TlsException is thrown.
*
* The optional argument [database] is the path to a certificate database
* directory containing root certificates for verifying certificate paths on
* client connections, and server certificates to provide on server
- * connections. The argument [password] should be used when creating
+ * connections. The argument [password] should be used when creating
* secure server sockets, to allow the private key of the server
- * certificate to be fetched. If [useBuiltinRoots] is true (the default),
+ * certificate to be fetched. If [useBuiltinRoots] is true (the default),
* then a built-in set of root certificates for trusted certificate
* authorities is merged with the certificates in the database.
* The list of built-in root certificates, and documentation about this
@@ -161,7 +169,7 @@
* http://www.mozilla.org/projects/security/certs/included/ .
*
* If the [database] argument is omitted, then only the
- * builtin root certificates are used. If [useBuiltinRoots] is also false,
+ * builtin root certificates are used. If [useBuiltinRoots] is also false,
* then no certificates are available.
*
* Examples:
@@ -246,7 +254,19 @@
* If the [socket] already has a subscription, pass the existing
* subscription in the [subscription] parameter. The secure socket
* will take over the subscription and process any subsequent
- * events.
+ * events. In most cases calling `pause` on this subscription before
+ * starting TLS handshake is the right thing to do.
+ *
+ * If the [host] argument is passed it will be used as the host name
+ * for the TLS handshake. If [host] is not passed the host name from
+ * the [socket] will be used. The [host] can be either a [String] or
+ * an [InternetAddress].
+ *
+ * Calling this function will _not_ cause a DNS host lookup. If the
+ * [host] passed is a [String] the [InternetAddress] for the
+ * resulting [SecureSocket] will have this passed in [host] as its
+ * host value and the internet address of the already connected
+ * socket as its address value.
*
* See [connect] for more information on the arguments.
*
@@ -340,10 +360,23 @@
}
+class _FilterStatus {
+ bool progress = false; // The filter read or wrote data to the buffers.
+ bool readEmpty = true; // The read buffers and decryption filter are empty.
+ bool writeEmpty = true; // The write buffers and encryption filter are empty.
+ // These are set if a buffer changes state from empty or full.
+ bool readPlaintextNoLongerEmpty = false;
+ bool writePlaintextNoLongerFull = false;
+ bool readEncryptedNoLongerFull = false;
+ bool writeEncryptedNoLongerEmpty = false;
+
+ _FilterStatus();
+}
+
+
class _RawSecureSocket extends Stream<RawSocketEvent>
implements RawSecureSocket {
// Status states
- static final int NOT_CONNECTED = 200;
static final int HANDSHAKE = 201;
static final int CONNECTED = 202;
static final int CLOSED = 203;
@@ -356,6 +389,9 @@
static final int WRITE_ENCRYPTED = 3;
static final int NUM_BUFFERS = 4;
+ // Is a buffer identifier for an encrypted buffer?
+ static bool _isBufferEncrypted(int identifier) => identifier >= READ_ENCRYPTED;
+
RawSocket _socket;
final Completer<_RawSecureSocket> _handshakeComplete =
new Completer<_RawSecureSocket>();
@@ -372,17 +408,23 @@
final bool sendClientCertificate;
final Function onBadCertificate;
- var _status = NOT_CONNECTED;
+ var _status = HANDSHAKE;
bool _writeEventsEnabled = true;
bool _readEventsEnabled = true;
+ int _pauseCount = 0;
+ bool _pendingReadEvent = false;
bool _socketClosedRead = false; // The network socket is closed for reading.
bool _socketClosedWrite = false; // The network socket is closed for writing.
bool _closedRead = false; // The secure socket has fired an onClosed event.
bool _closedWrite = false; // The secure socket has been closed for writing.
- bool _filterReadEmpty = true; // There is no buffered data to read.
- bool _filterWriteEmpty = true; // There is no buffered data to be written.
+ _FilterStatus _filterStatus = new _FilterStatus();
bool _connectPending = false;
+ bool _filterPending = false;
+ bool _filterActive = false;
+
_SecureFilter _secureFilter = new _SecureFilter();
+ int _filterPointer;
+ SendPort _filterService;
static Future<_RawSecureSocket> connect(
host,
@@ -397,8 +439,16 @@
bool sendClientCertificate: false,
bool onBadCertificate(X509Certificate certificate)}) {
var future;
+ _verifyFields(host, requestedPort, certificateName, is_server,
+ requestClientCertificate, requireClientCertificate,
+ sendClientCertificate, onBadCertificate);
if (host is String) {
- future = InternetAddress.lookup(host).then((addrs) => addrs.first);
+ if (socket != null) {
+ future = new Future.value(
+ (socket.address as dynamic)._cloneWithNewHost(host));
+ } else {
+ future = InternetAddress.lookup(host).then((addrs) => addrs.first);
+ }
} else {
future = new Future.value(host);
}
@@ -439,9 +489,8 @@
_stream = _controller.stream;
// Throw an ArgumentError if any field is invalid. After this, all
// errors will be reported through the future or the stream.
- _verifyFields();
_secureFilter.init();
- if (_bufferedData != null) _readFromBuffered();
+ _filterPointer = _secureFilter._pointer();
_secureFilter.registerHandshakeCompleteCallback(
_secureHandshakeCompleteHandler);
if (onBadCertificate != null) {
@@ -454,6 +503,7 @@
futureSocket = new Future.value(socket);
}
futureSocket.then((rawSocket) {
+ _connectPending = true;
_socket = rawSocket;
_socket.readEventsEnabled = true;
_socket.writeEventsEnabled = false;
@@ -461,15 +511,15 @@
// If a current subscription is provided use this otherwise
// create a new one.
_socketSubscription = _socket.listen(_eventDispatcher,
- onError: _errorHandler,
+ onError: _reportError,
onDone: _doneHandler);
} else {
_socketSubscription.onData(_eventDispatcher);
- _socketSubscription.onError(_errorHandler);
+ _socketSubscription.onError(_reportError);
_socketSubscription.onDone(_doneHandler);
}
- _connectPending = true;
_secureFilter.connect(address.host,
+ (address as dynamic)._sockaddr_storage,
port,
is_server,
certificateName,
@@ -477,35 +527,38 @@
requireClientCertificate,
requireClientCertificate,
sendClientCertificate);
- _status = HANDSHAKE;
_secureHandshake();
})
- .catchError((error) {
- _handshakeComplete.completeError(error);
- _close();
- });
+ .catchError(_reportError);
}
StreamSubscription listen(void onData(RawSocketEvent data),
{void onError(error),
void onDone(),
bool cancelOnError}) {
- if (_writeEventsEnabled) {
- _writeEventsEnabled = false;
- _controller.add(RawSocketEvent.WRITE);
- }
+ _sendWriteEvent();
return _stream.listen(onData,
onError: onError,
onDone: onDone,
cancelOnError: cancelOnError);
}
- void _verifyFields() {
- assert(is_server is bool);
- assert(_socket == null || _socket is RawSocket);
- if (address is! InternetAddress) {
- throw new ArgumentError(
- "RawSecureSocket constructor: host is not an InternetAddress");
+ static void _verifyFields(host,
+ int requestedPort,
+ String certificateName,
+ bool is_server,
+ bool requestClientCertificate,
+ bool requireClientCertificate,
+ bool sendClientCertificate,
+ Function onBadCertificate) {
+ if (host is! String && host is! InternetAddress) {
+ throw new ArgumentError("host is not a String or an InternetAddress");
+ }
+ if (requestedPort is! int) {
+ throw new ArgumentError("requestedPort is not an int");
+ }
+ if (requestedPort < 0 || requestedPort > 65535) {
+ throw new ArgumentError("requestedPort is not in the range 0..65535");
}
if (certificateName != null && certificateName is! String) {
throw new ArgumentError("certificateName is not null or a String");
@@ -535,7 +588,6 @@
int available() {
if (_status != CONNECTED) return 0;
- _readEncryptedData();
return _secureFilter.buffers[READ_PLAINTEXT].length;
}
@@ -551,7 +603,7 @@
}
_socketClosedWrite = true;
_socketClosedRead = true;
- if (_secureFilter != null) {
+ if (!_filterActive && _secureFilter != null) {
_secureFilter.destroy();
_secureFilter = null;
}
@@ -566,8 +618,7 @@
if (direction == SocketDirection.SEND ||
direction == SocketDirection.BOTH) {
_closedWrite = true;
- _writeEncryptedData();
- if (_filterWriteEmpty) {
+ if (_filterStatus.writeEmpty) {
_socket.shutdown(SocketDirection.SEND);
_socketClosedWrite = true;
if (_closedRead) {
@@ -589,99 +640,60 @@
bool get writeEventsEnabled => _writeEventsEnabled;
void set writeEventsEnabled(bool value) {
- if (value &&
- _controller.hasListener &&
- _secureFilter != null &&
- _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
- Timer.run(() => _controller.add(RawSocketEvent.WRITE));
- } else {
- _writeEventsEnabled = value;
+ _writeEventsEnabled = value;
+ if (value) {
+ Timer.run(() => _sendWriteEvent());
}
}
bool get readEventsEnabled => _readEventsEnabled;
void set readEventsEnabled(bool value) {
- _readEventsEnabled = value;
- if (value &&
- ((_secureFilter != null &&
- _secureFilter.buffers[READ_PLAINTEXT].length > 0) ||
- _socketClosedRead)) {
- // We might not have no underlying socket to set off read events.
- Timer.run(_readHandler);
- }
+ _readEventsEnabled = value;
+ _scheduleReadEvent();
}
- List<int> read([int len]) {
+ List<int> read([int length]) {
+ if (length != null && (length is! int || length < 0)) {
+ throw new ArgumentError(
+ "Invalid length parameter in SecureSocket.read (length: $length)");
+ }
if (_closedRead) {
throw new SocketException("Reading from a closed socket");
}
if (_status != CONNECTED) {
return null;
}
- var buffer = _secureFilter.buffers[READ_PLAINTEXT];
- _readEncryptedData();
- int toRead = buffer.length;
- if (len != null) {
- if (len is! int || len < 0) {
- throw new ArgumentError(
- "Invalid len parameter in SecureSocket.read (len: $len)");
- }
- if (len < toRead) {
- toRead = len;
- }
- }
- List<int> result = (toRead == 0) ? null :
- buffer.data.sublist(buffer.start, buffer.start + toRead);
- buffer.advanceStart(toRead);
-
- // Set up a read event if the filter still has data.
- if (!_filterReadEmpty) {
- Timer.run(_readHandler);
- }
-
- if (_socketClosedRead) { // An onClose event is pending.
- // _closedRead is false, since we are in a read call.
- if (!_filterReadEmpty) {
- // _filterReadEmpty may be out of date since read empties
- // the plaintext buffer after calling _readEncryptedData.
- // TODO(whesse): Fix this as part of fixing read.
- _readEncryptedData();
- }
- if (_filterReadEmpty) {
- // This can't be an else clause: the value of _filterReadEmpty changes.
- // This must be asynchronous, because we are in a read call.
- Timer.run(_closeHandler);
- }
- }
-
+ var result = _secureFilter.buffers[READ_PLAINTEXT].read(length);
+ _scheduleFilter();
return result;
}
- // Write the data to the socket, and flush it as much as possible
- // until it would block. If the write would block, _writeEncryptedData sets
- // up handlers to flush the pipeline when possible.
+ // Write the data to the socket, and schedule the filter to encrypt it.
int write(List<int> data, [int offset, int bytes]) {
+ if (bytes != null && (bytes is! int || bytes < 0)) {
+ throw new ArgumentError(
+ "Invalid bytes parameter in SecureSocket.read (bytes: $bytes)");
+ }
+ if (offset != null && (offset is! int || offset < 0)) {
+ throw new ArgumentError(
+ "Invalid offset parameter in SecureSocket.read (offset: $offset)");
+ }
if (_closedWrite) {
_controller.addError(new SocketException("Writing to a closed socket"));
return 0;
}
if (_status != CONNECTED) return 0;
-
if (offset == null) offset = 0;
if (bytes == null) bytes = data.length - offset;
- var buffer = _secureFilter.buffers[WRITE_PLAINTEXT];
- if (bytes > buffer.free) {
- bytes = buffer.free;
+ int written =
+ _secureFilter.buffers[WRITE_PLAINTEXT].write(data, offset, bytes);
+ if (written > 0) {
+ _filterStatus.writeEmpty = false;
}
- if (bytes > 0) {
- int startIndex = buffer.start + buffer.length;
- buffer.data.setRange(startIndex, startIndex + bytes, data, offset);
- buffer.length += bytes;
- }
- _writeEncryptedData(); // Tries to flush all pipeline stages.
- return bytes;
+ _scheduleFilter();
+ return written;
}
X509Certificate get peerCertificate => _secureFilter.peerCertificate;
@@ -691,106 +703,43 @@
return _socket.setOption(option, enabled);
}
- void _writeHandler() {
- if (_status == CLOSED) return;
- _writeEncryptedData();
- if (_filterWriteEmpty && _closedWrite && !_socketClosedWrite) {
- // Close _socket for write, by calling shutdown(), to avoid cloning the
- // socket closing code in shutdown().
- shutdown(SocketDirection.SEND);
- }
- if (_status == HANDSHAKE) {
- try {
- _secureHandshake();
- } catch (e) { _reportError(e, "RawSecureSocket error"); }
- } else if (_status == CONNECTED &&
- _controller.hasListener &&
- _writeEventsEnabled &&
- _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
- // Reset the one-shot handler.
- _writeEventsEnabled = false;
- _controller.add(RawSocketEvent.WRITE);
- }
- }
-
void _eventDispatcher(RawSocketEvent event) {
- if (event == RawSocketEvent.READ) {
- _readHandler();
- } else if (event == RawSocketEvent.WRITE) {
- _writeHandler();
- } else if (event == RawSocketEvent.READ_CLOSED) {
- _closeHandler();
- }
- }
-
- void _readFromBuffered() {
- assert(_bufferedData != null);
- var encrypted = _secureFilter.buffers[READ_ENCRYPTED];
- var bytes = _bufferedData.length - _bufferedDataIndex;
- int startIndex = encrypted.start + encrypted.length;
- encrypted.data.setRange(startIndex,
- startIndex + bytes,
- _bufferedData,
- _bufferedDataIndex);
- encrypted.length += bytes;
- _bufferedDataIndex += bytes;
- if (_bufferedData.length == _bufferedDataIndex) {
- _bufferedData = null;
+ try {
+ if (event == RawSocketEvent.READ) {
+ _readHandler();
+ } else if (event == RawSocketEvent.WRITE) {
+ _writeHandler();
+ } else if (event == RawSocketEvent.READ_CLOSED) {
+ _closeHandler();
+ }
+ } catch (e) {
+ _reportError(e);
}
}
void _readHandler() {
- if (_status == CLOSED) {
- return;
- } else if (_status == HANDSHAKE) {
- try {
- _secureHandshake();
- if (_status != HANDSHAKE) _readHandler();
- } catch (e) { _reportError(e, "RawSecureSocket error"); }
- } else {
- if (_status != CONNECTED) {
- // Cannot happen.
- throw new SocketException("Internal SocketIO Error");
- }
- try {
- _readEncryptedData();
- } catch (e) { _reportError(e, "RawSecureSocket error"); }
- if (!_filterReadEmpty) {
- if (_readEventsEnabled) {
- if (_secureFilter.buffers[READ_PLAINTEXT].length > 0) {
- _controller.add(RawSocketEvent.READ);
- }
- if (_socketClosedRead) {
- // Keep firing read events until we are paused or buffer is empty.
- Timer.run(_readHandler);
- }
- }
- } else if (_socketClosedRead) {
- _closeHandler();
- }
- }
+ _readSocket();
+ _scheduleFilter();
+ }
+
+ void _writeHandler() {
+ _writeSocket();
+ _scheduleFilter();
}
void _doneHandler() {
- if (_filterReadEmpty) {
+ if (_filterStatus.readEmpty) {
_close();
}
}
- void _errorHandler(e) {
- _reportError(e, 'Error on underlying RawSocket');
- }
-
- void _reportError(e, String message) {
- // TODO(whesse): Call _reportError from all internal functions that throw.
- if (e is SocketException) {
- e = new SocketException('$message (${e.message})', e.osError);
- } else if (e is OSError) {
- e = new SocketException(message, e);
- } else {
- e = new SocketException('$message (${e.toString()})', null);
- }
+ void _reportError(e) {
if (_connectPending) {
+ // _connectPending is true after the underlying connection has been
+ // made, but before the handshake has completed.
+ if (e is! TlsException) {
+ e = new HandshakeException("$e", null);
+ }
_handshakeComplete.completeError(e);
} else {
_controller.addError(e);
@@ -802,38 +751,58 @@
if (_status == CONNECTED) {
if (_closedRead) return;
_socketClosedRead = true;
- if (_filterReadEmpty) {
+ if (_filterStatus.readEmpty) {
_closedRead = true;
_controller.add(RawSocketEvent.READ_CLOSED);
if (_socketClosedWrite) {
_close();
}
+ } else {
+ _scheduleFilter();
}
} else if (_status == HANDSHAKE) {
+ _socketClosedRead = true;
+ if (_filterStatus.readEmpty) {
_reportError(
- new SocketException('Connection terminated during handshake'),
- 'handshake error');
+ new HandshakeException('Connection terminated during handshake'));
+ } else {
+ _secureHandshake();
+ }
}
}
void _secureHandshake() {
- _readEncryptedData();
- _secureFilter.handshake();
- _writeEncryptedData();
+ try {
+ _secureFilter.handshake();
+ _filterStatus.writeEmpty = false;
+ _readSocket();
+ _writeSocket();
+ _scheduleFilter();
+ } catch (e) {
+ _reportError(e);
+ }
}
void _secureHandshakeCompleteHandler() {
_status = CONNECTED;
if (_connectPending) {
_connectPending = false;
- // If we complete the future synchronously, user code will run here,
- // and modify the state of the RawSecureSocket. For example, it
- // could close the socket, and set _filter to null.
+ // We don't want user code to run synchronously in this callback.
Timer.run(() => _handshakeComplete.complete(this));
}
}
void _onPauseStateChange() {
+ if (_controller.isPaused) {
+ _pauseCount++;
+ } else {
+ _pauseCount--;
+ if (_pauseCount == 0) {
+ _scheduleReadEvent();
+ _sendWriteEvent(); // Can send event synchronously.
+ }
+ }
+
if (!_socketClosedRead || !_socketClosedWrite) {
if (_controller.isPaused) {
_socketSubscription.pause();
@@ -849,121 +818,333 @@
}
}
- void _readEncryptedData() {
- // Read from the socket, and push it through the filter as far as
- // possible.
- var encrypted = _secureFilter.buffers[READ_ENCRYPTED];
- var plaintext = _secureFilter.buffers[READ_PLAINTEXT];
- bool progress = true;
- while (progress) {
- progress = false;
- // Do not try to read plaintext from the filter while handshaking.
- if ((_status == CONNECTED) && plaintext.free > 0) {
- int bytes = _secureFilter.processBuffer(READ_PLAINTEXT);
- if (bytes > 0) {
- plaintext.length += bytes;
- progress = true;
- }
- }
- if (encrypted.length > 0) {
- int bytes = _secureFilter.processBuffer(READ_ENCRYPTED);
- if (bytes > 0) {
- encrypted.advanceStart(bytes);
- progress = true;
- }
- }
- if (!_socketClosedRead && encrypted.free > 0) {
- if (_bufferedData != null) {
- _readFromBuffered();
- progress = true;
- } else {
- List<int> data = _socket.read(encrypted.free);
- if (data != null) {
- int bytes = data.length;
- int startIndex = encrypted.start + encrypted.length;
- encrypted.data.setRange(startIndex, startIndex + bytes, data);
- encrypted.length += bytes;
- progress = true;
- }
- }
- }
- }
- // If there is any data in any stages of the filter, there should
- // be data in the plaintext buffer after this process.
- // TODO(whesse): Verify that this is true, and there can be no
- // partial encrypted block stuck in the secureFilter.
- _filterReadEmpty = (plaintext.length == 0);
+ void _scheduleFilter() {
+ _filterPending = true;
+ _tryFilter();
}
- void _writeEncryptedData() {
- if (_socketClosedWrite) return;
- var encrypted = _secureFilter.buffers[WRITE_ENCRYPTED];
- var plaintext = _secureFilter.buffers[WRITE_PLAINTEXT];
- while (true) {
- if (encrypted.length > 0) {
- // Write from the filter to the socket.
- int bytes = _socket.write(encrypted.data,
- encrypted.start,
- encrypted.length);
- encrypted.advanceStart(bytes);
- if (encrypted.length > 0) {
- // The socket has blocked while we have data to write.
- // We must be notified when it becomes unblocked.
- _socket.writeEventsEnabled = true;
- _filterWriteEmpty = false;
- break;
+ void _tryFilter() {
+ if (_status == CLOSED) return;
+ if (_filterPending && !_filterActive) {
+ _filterActive = true;
+ _filterPending = false;
+ _pushAllFilterStages().then((status) {
+ _filterStatus = status;
+ _filterActive = false;
+ if (_status == CLOSED) {
+ _secureFilter.destroy();
+ _secureFilter = null;
+ return;
}
- } else {
- var plaintext = _secureFilter.buffers[WRITE_PLAINTEXT];
- if (plaintext.length > 0) {
- int plaintext_bytes = _secureFilter.processBuffer(WRITE_PLAINTEXT);
- plaintext.advanceStart(plaintext_bytes);
+ if (_filterStatus.writeEmpty && _closedWrite && !_socketClosedWrite) {
+ // Checks for and handles all cases of partially closed sockets.
+ shutdown(SocketDirection.SEND);
+ if (_status == CLOSED) return;
}
- int bytes = _secureFilter.processBuffer(WRITE_ENCRYPTED);
- if (bytes <= 0) {
- // We know the WRITE_ENCRYPTED buffer is empty, and the
- // filter wrote zero bytes to it, so the filter must be empty.
- // Also, the WRITE_PLAINTEXT buffer must have been empty, or
- // it would have written to the filter.
- // TODO(whesse): Verify that the filter works this way.
- _filterWriteEmpty = true;
- break;
+ if (_filterStatus.readEmpty && _socketClosedRead && !_closedRead) {
+ if (_status == HANDSHAKE) {
+ _secureFilter.handshake();
+ if (_status == HANDSHAKE) {
+ throw new HandshakeException(
+ 'Connection terminated during handshake');
+ }
+ }
+ _closeHandler();
}
- encrypted.length += bytes;
- }
+ if (_status == CLOSED) return;
+ if (_filterStatus.progress) {
+ _filterPending = true;
+ if (_filterStatus.writePlaintextNoLongerFull) _sendWriteEvent();
+ if (_filterStatus.readEncryptedNoLongerFull) _readSocket();
+ if (_filterStatus.writeEncryptedNoLongerEmpty) _writeSocket();
+ if (_filterStatus.readPlaintextNoLongerEmpty) _scheduleReadEvent();
+ if (_status == HANDSHAKE) _secureHandshake();
+ }
+ _tryFilter();
+ }).catchError(_reportError);
}
}
+
+ List<int> _readSocketOrBufferedData(int bytes) {
+ if (_bufferedData != null) {
+ if (bytes > _bufferedData.length - _bufferedDataIndex) {
+ bytes = _bufferedData.length - _bufferedDataIndex;
+ }
+ var result = _bufferedData.sublist(_bufferedDataIndex,
+ _bufferedDataIndex + bytes);
+ _bufferedDataIndex += bytes;
+ if (_bufferedData.length == _bufferedDataIndex) {
+ _bufferedData = null;
+ }
+ return result;
+ } else if (!_socketClosedRead) {
+ return _socket.read(bytes);
+ } else {
+ return null;
+ }
+ }
+
+ void _readSocket() {
+ if (_status == CLOSED) return;
+ var buffer = _secureFilter.buffers[READ_ENCRYPTED];
+ if (buffer.writeFromSource(_readSocketOrBufferedData) > 0) {
+ _filterStatus.readEmpty = false;
+ }
+ }
+
+ void _writeSocket() {
+ if (_socketClosedWrite) return;
+ var buffer = _secureFilter.buffers[WRITE_ENCRYPTED];
+ if (buffer.readToSocket(_socket)) { // Returns true if blocked
+ _socket.writeEventsEnabled = true;
+ }
+ }
+
+ // If a read event should be sent, add it to the controller.
+ _scheduleReadEvent() {
+ if (!_pendingReadEvent &&
+ _readEventsEnabled &&
+ _pauseCount == 0 &&
+ _secureFilter != null &&
+ !_secureFilter.buffers[READ_PLAINTEXT].isEmpty) {
+ _pendingReadEvent = true;
+ Timer.run(_sendReadEvent);
+ }
+ }
+
+ _sendReadEvent() {
+ _pendingReadEvent = false;
+ if (_readEventsEnabled &&
+ _pauseCount == 0 &&
+ _secureFilter != null &&
+ !_secureFilter.buffers[READ_PLAINTEXT].isEmpty) {
+ _controller.add(RawSocketEvent.READ);
+ _scheduleReadEvent();
+ }
+ }
+
+ // If a write event should be sent, add it to the controller.
+ _sendWriteEvent() {
+ if (!_closedWrite &&
+ _writeEventsEnabled &&
+ _pauseCount == 0 &&
+ _secureFilter != null &&
+ _secureFilter.buffers[WRITE_PLAINTEXT].free > 0) {
+ _writeEventsEnabled = false;
+ _controller.add(RawSocketEvent.WRITE);
+ }
+ }
+
+ Future<_FilterStatus> _pushAllFilterStages() {
+ if (_filterService == null) {
+ _filterService = _SecureFilter._newServicePort();
+ }
+ List args = [_filterPointer, _status != CONNECTED];
+ var bufs = _secureFilter.buffers;
+ for (var i = 0; i < NUM_BUFFERS; ++i) {
+ args.add(bufs[i].start);
+ args.add(bufs[i].end);
+ }
+
+ return _filterService.call(args).then((response) {
+ bool wasInHandshake = response[1];
+ int start(int index) => response[2 * index + 2];
+ int end(int index) => response[2 * index + 3];
+
+ _FilterStatus status = new _FilterStatus();
+ // Compute writeEmpty as "write plaintext buffer and write encrypted
+ // buffer were empty when we started and are empty now".
+ status.writeEmpty = bufs[WRITE_PLAINTEXT].isEmpty &&
+ start(WRITE_ENCRYPTED) == end(WRITE_ENCRYPTED);
+ // If we were in handshake when this started, _writeEmpty may be false
+ // because the handshake wrote data after we checked.
+ if (wasInHandshake) status.writeEmpty = false;
+
+ // Compute readEmpty as "both read buffers were empty when we started
+ // and are empty now".
+ status.readEmpty = bufs[READ_ENCRYPTED].isEmpty &&
+ start(READ_PLAINTEXT) == end(READ_PLAINTEXT);
+
+ _ExternalBuffer buffer = bufs[WRITE_PLAINTEXT];
+ int new_start = start(WRITE_PLAINTEXT);
+ if (new_start != buffer.start) {
+ status.progress = true;
+ if (buffer.free == 0) {
+ status.writePlaintextNoLongerFull = true;
+ }
+ buffer.start = new_start;
+ }
+ buffer = bufs[READ_ENCRYPTED];
+ new_start = start(READ_ENCRYPTED);
+ if (new_start != buffer.start) {
+ status.progress = true;
+ if (buffer.free == 0) {
+ status.readEncryptedNoLongerFull = true;
+ }
+ buffer.start = new_start;
+ }
+ buffer = bufs[WRITE_ENCRYPTED];
+ int new_end = end(WRITE_ENCRYPTED);
+ if (new_end != buffer.end) {
+ status.progress = true;
+ if (buffer.length == 0) {
+ status.writeEncryptedNoLongerEmpty = true;
+ }
+ buffer.end = new_end;
+ }
+ buffer = bufs[READ_PLAINTEXT];
+ new_end = end(READ_PLAINTEXT);
+ if (new_end != buffer.end) {
+ status.progress = true;
+ if (buffer.length == 0) {
+ status.readPlaintextNoLongerEmpty = true;
+ }
+ buffer.end = new_end;
+ }
+ return status;
+ });
+ }
}
+/**
+ * A circular buffer backed by an external byte array. Accessed from
+ * both C++ and Dart code in an unsynchronized way, with one reading
+ * and one writing. All updates to start and end are done by Dart code.
+ */
class _ExternalBuffer {
- // Performance is improved if a full buffer of plaintext fits
- // in the encrypted buffer, when encrypted.
- static final int SIZE = 8 * 1024;
- static final int ENCRYPTED_SIZE = 10 * 1024;
- _ExternalBuffer() : start = 0, length = 0;
+ _ExternalBuffer(this.size) {
+ start = size~/2;
+ end = size~/2;
+ }
- // TODO(whesse): Consider making this a circular buffer. Only if it helps.
- void advanceStart(int numBytes) {
- start += numBytes;
- length -= numBytes;
- if (length == 0) {
- start = 0;
+ void advanceStart(int bytes) {
+ assert(start > end || start + bytes <= end);
+ start += bytes;
+ if (start >= size) {
+ start -= size;
+ assert(start <= end);
+ assert(start < size);
}
}
- int get free => data.length - (start + length);
+ void advanceEnd(int bytes) {
+ assert(start <= end || start > end + bytes);
+ end += bytes;
+ if (end >= size) {
+ end -= size;
+ assert(end < start);
+ assert(end < size);
+ }
+ }
+
+ bool get isEmpty => end == start;
+
+ int get length {
+ if (start > end) return size + end - start;
+ return end - start;
+ }
+
+ int get linearLength {
+ if (start > end) return size - start;
+ return end - start;
+ }
+
+ int get free {
+ if (start > end) return start - end - 1;
+ return size + start - end - 1;
+ }
+
+ int get linearFree {
+ if (start > end) return start - end - 1;
+ if (start == 0) return size - end - 1;
+ return size - end;
+ }
+
+ List<int> read(int bytes) {
+ if (bytes == null) {
+ bytes = length;
+ } else {
+ bytes = min(bytes, length);
+ }
+ if (bytes == 0) return null;
+ List<int> result = new Uint8List(bytes);
+ int bytesRead = 0;
+ // Loop over zero, one, or two linear data ranges.
+ while (bytesRead < bytes) {
+ int toRead = linearLength;
+ result.setRange(bytesRead,
+ bytesRead + toRead,
+ data,
+ start);
+ advanceStart(toRead);
+ bytesRead += toRead;
+ }
+ return result;
+ }
+
+ int write(List<int> inputData, int offset, int bytes) {
+ if (bytes > free) {
+ bytes = free;
+ }
+ int written = 0;
+ int toWrite = min(bytes, linearFree);
+ // Loop over zero, one, or two linear data ranges.
+ while (toWrite > 0) {
+ data.setRange(end, end + toWrite, inputData, offset);
+ advanceEnd(toWrite);
+ offset += toWrite;
+ written += toWrite;
+ toWrite = min(bytes - written, linearFree);
+ }
+ return written;
+ }
+
+ int writeFromSource(List<int> getData(int requested)) {
+ int written = 0;
+ int toWrite = linearFree;
+ // Loop over zero, one, or two linear data ranges.
+ while (toWrite > 0) {
+ // Source returns at most toWrite bytes, and it returns null when empty.
+ var inputData = getData(toWrite);
+ if (inputData == null) break;
+ var len = inputData.length;
+ data.setRange(end, end + len, inputData);
+ advanceEnd(len);
+ written += len;
+ toWrite = linearFree;
+ }
+ return written;
+ }
+
+ bool readToSocket(RawSocket socket) {
+ // Loop over zero, one, or two linear data ranges.
+ while (true) {
+ var toWrite = linearLength;
+ if (toWrite == 0) return false;
+ int bytes = socket.write(data, start, toWrite);
+ advanceStart(bytes);
+ if (bytes < toWrite) {
+ // The socket has blocked while we have data to write.
+ return true;
+ }
+ }
+ }
List data; // This will be a ExternalByteArray, backed by C allocated data.
int start;
- int length;
+ int end;
+ final size;
}
abstract class _SecureFilter {
external factory _SecureFilter();
+ external static SendPort _newServicePort();
+
void connect(String hostName,
+ Uint8List addr,
int port,
bool is_server,
String certificateName,
@@ -977,6 +1158,61 @@
int processBuffer(int bufferIndex);
void registerBadCertificateCallback(Function callback);
void registerHandshakeCompleteCallback(Function handshakeCompleteHandler);
+ int _pointer();
List<_ExternalBuffer> get buffers;
}
+
+/** A secure networking exception caused by a failure in the
+ * TLS/SSL protocol.
+ */
+class TlsException implements IOException {
+ final String type;
+ final String message;
+ final OSError osError;
+
+ const TlsException([String message = "",
+ OSError osError = null])
+ : this._("TlsException", message, osError);
+
+ const TlsException._(String this.type,
+ String this.message,
+ OSError this.osError);
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write(type);
+ if (!message.isEmpty) {
+ sb.write(": $message");
+ if (osError != null) {
+ sb.write(" ($osError)");
+ }
+ } else if (osError != null) {
+ sb.write(": $osError");
+ }
+ return sb.toString();
+ }
+}
+
+
+/**
+ * An exception that happens in the handshake phase of establishing
+ * a secure network connection.
+ */
+class HandshakeException extends TlsException {
+ const HandshakeException([String message = "",
+ OSError osError = null])
+ : super._("HandshakeException", message, osError);
+}
+
+
+/**
+ * An exception that happens in the handshake phase of establishing
+ * a secure network connection, when looking up or verifying a
+ * certificate.
+ */
+class CertificateException extends TlsException {
+ const CertificateException([String message = "",
+ OSError osError = null])
+ : super._("CertificateException", message, osError);
+}
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 7164bf1..a74f2a1 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -87,6 +87,22 @@
String get host;
/**
+ * Returns true if the [InternetAddress] is a loopback address.
+ */
+ bool get isLoopback;
+
+ /**
+ * Returns true if the [InternetAddress]s scope is a link-local.
+ */
+ bool get isLinkLocal;
+
+ /**
+ * Perform a reverse dns lookup on the [address], creating a new
+ * [InternetAddress] where the host field set to the result.
+ */
+ Future<InternetAddress> reverse();
+
+ /**
* Lookup a host, returning a Future of a list of
* [InternetAddress]s. If [type] is [InternetAddressType.ANY], it
* will lookup both IP version 4 (IPv4) and IP version 6 (IPv6)
@@ -99,6 +115,44 @@
String host, {InternetAddressType type: InternetAddressType.ANY});
}
+
+/**
+ * A [NetworkInterface] represent an active network interface on the current
+ * system. It contains a list of [InternetAddress]s, that's bound to the
+ * interface.
+ */
+abstract class NetworkInterface {
+ /**
+ * Get the name of the [NetworkInterface].
+ */
+ String get name;
+
+ /**
+ * Get a list of [InternetAddress]s currently bound to this
+ * [NetworkInterface].
+ */
+ List<InternetAddress> get addresses;
+
+ /**
+ * Query the system for [NetworkInterface]s.
+ *
+ * If [includeLoopback] is `true`, the returned list will include the
+ * loopback device. Default is `false`.
+ *
+ * If [includeLinkLocal] is `true`, the list of addresses of the returned
+ * [NetworkInterface]s, may include link local addresses. Default is `false`.
+ *
+ * If [type] is either [InternetAddressType.IP_V4] or
+ * [InternetAddressType.IP_V6] it will only lookup addresses of the
+ * specified type. Default is [InternetAddressType.ANY].
+ */
+ external static Future<List<NetworkInterface>> list({
+ bool includeLoopback: false,
+ bool includeLinkLocal: false,
+ InternetAddressType type: InternetAddressType.ANY});
+}
+
+
/**
* A [RawServerSocket] represents a listening socket, and provides a
* stream of low-level [RawSocket] objects, one for each connection
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index f127b38..e08e807 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.dart
@@ -91,8 +91,34 @@
var _decoder;
/**
+ * Decodes a stream of bytes into a `String` with an optional
+ * [encoding] and [replacementChar].
+ *
+ * The default value for [encoding] is [Encoding.UTF_8].
+ *
+ * The default value for [replacementChar] is code point U+FFFD.
+ *
+ * Completes with the decoded `String` when the stream is done.
+ */
+ static Future<String> decode(
+ Stream<List<int>> stream,
+ [Encoding encoding = Encoding.UTF_8,
+ int replacementChar = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) {
+ return stream
+ .transform(new StringDecoder(encoding, replacementChar))
+ .fold(
+ new StringBuffer(),
+ (prev, data) => prev..write(data))
+ .then((sb) => sb.toString());
+ }
+
+ /**
* Create a new [StringDecoder] with an optional [encoding] and
* [replacementChar].
+ *
+ * The default value for [encoding] is [Encoding.UTF_8].
+ *
+ * The default value for [replacementChar] is code point U+FFFD.
*/
StringDecoder([Encoding encoding = Encoding.UTF_8, int replacementChar]) {
switch (encoding) {
diff --git a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart b/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
index e83a15d..9429da1 100644
--- a/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
+++ b/sdk/lib/mdv_observe_impl/mdv_observe_impl.dart
@@ -12,6 +12,8 @@
import 'dart:async';
import 'dart:collection';
+part 'path_observer.dart';
+
/**
* Interface representing an observable object. This is used by data in
* model-view architectures to notify interested parties of [changes].
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index f6ba0c9..e29c225 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -665,7 +665,7 @@
* An immutable map from names to mirrors for all constructor
* declarations for this type.
*/
- Map<Symbol, MethodMirror> get constructors;
+ Map<Symbol, MethodMirror> get constructors;
/**
* An immutable map from names to mirrors for all type variables for
@@ -673,7 +673,7 @@
*
* This map preserves the order of declaration of the type variables.
*/
- Map<Symbol, TypeVariableMirror> get typeVariables;
+ Map<Symbol, TypeVariableMirror> get typeVariables;
/**
* An immutable map from names to mirrors for all type arguments for
diff --git a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
index 1fcecdb..41e2450 100644
--- a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
+++ b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
@@ -318,11 +318,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- num firstWhere(bool test(num value), { num orElse() }) {
+ dynamic firstWhere(bool test(num value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- num lastWhere(bool test(num value), {num orElse()}) {
+ dynamic lastWhere(bool test(num value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -540,11 +540,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- num firstWhere(bool test(num value), { num orElse() }) {
+ dynamic firstWhere(bool test(num value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- num lastWhere(bool test(num value), {num orElse()}) {
+ dynamic lastWhere(bool test(num value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -762,11 +762,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -984,11 +984,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -1206,11 +1206,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -1428,11 +1428,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -1650,11 +1650,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -1871,11 +1871,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
@@ -2093,11 +2093,11 @@
return IterableMixinWorkaround.skipWhile(this, test);
}
- int firstWhere(bool test(int value), { int orElse() }) {
+ dynamic firstWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- int lastWhere(bool test(int value), {int orElse()}) {
+ dynamic lastWhere(bool test(int value), { Object orElse() }) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index 1cad109..eb14d3a 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -7,7 +7,7 @@
import 'dart:typed_data';
import 'dart:_js_helper' show Creates, JSName, Null, Returns, convertDartClosureToJS;
import 'dart:_foreign_helper' show JS;
-import 'dart:_interceptors' show Interceptor;
+import 'dart:_interceptors' show Interceptor, JSExtendableArray;
// DO NOT EDIT - unless you are editing documentation as per:
// https://code.google.com/p/dart/wiki/ContributingHTMLDocumentation
// Auto-generated dart:web_gl library.
@@ -669,6 +669,11 @@
@DomName('EXTDrawBuffers.MAX_DRAW_BUFFERS_EXT')
@DocsEditable
static const int MAX_DRAW_BUFFERS_EXT = 0x8824;
+
+ @JSName('drawBuffersEXT')
+ @DomName('EXTDrawBuffers.drawBuffersEXT')
+ @DocsEditable
+ void drawBuffersExt(List<int> buffers) native;
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -2320,8 +2325,8 @@
@DomName('WebGLRenderingContext.getParameter')
@DocsEditable
- @Creates('Null|num|String|bool|=List|Float32List|Int32List|Uint32List|Framebuffer|Renderbuffer|Texture')
- @Returns('Null|num|String|bool|=List|Float32List|Int32List|Uint32List|Framebuffer|Renderbuffer|Texture')
+ @Creates('Null|num|String|bool|JSExtendableArray|Float32List|Int32List|Uint32List|Framebuffer|Renderbuffer|Texture')
+ @Returns('Null|num|String|bool|JSExtendableArray|Float32List|Int32List|Uint32List|Framebuffer|Renderbuffer|Texture')
Object getParameter(int pname) native;
@DomName('WebGLRenderingContext.getProgramInfoLog')
@@ -2370,8 +2375,8 @@
@DomName('WebGLRenderingContext.getUniform')
@DocsEditable
- @Creates('Null|num|String|bool|=List|Float32List|Int32List|Uint32List')
- @Returns('Null|num|String|bool|=List|Float32List|Int32List|Uint32List')
+ @Creates('Null|num|String|bool|JSExtendableArray|Float32List|Int32List|Uint32List')
+ @Returns('Null|num|String|bool|JSExtendableArray|Float32List|Int32List|Uint32List')
Object getUniform(Program program, UniformLocation location) native;
@DomName('WebGLRenderingContext.getUniformLocation')
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index a1e5550..9506607 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -735,6 +735,10 @@
@DocsEditable
static const int MAX_DRAW_BUFFERS_EXT = 0x8824;
+ @DomName('EXTDrawBuffers.drawBuffersEXT')
+ @DocsEditable
+ void drawBuffersExt(List<int> buffers) native "EXTDrawBuffers_drawBuffersEXT_Callback";
+
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
diff --git a/tests/async_helper.dart b/tests/async_helper.dart
new file mode 100644
index 0000000..34d471e
--- /dev/null
+++ b/tests/async_helper.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/// This library is used for testing asynchronous tests.
+/// If a test is asynchronous, it needs to notify the testing driver
+/// about this (otherwise tests may get reported as passing [after main()
+/// finished] even if the asynchronous operations fail).
+/// Tests which can't use the unittest framework should use the helper functions
+/// in this library.
+/// This library provides two methods
+/// - asyncStart(): Needs to be called before an asynchronous operation is
+/// scheduled.
+/// - asyncEnd(): Needs to be called as soon as the asynchronous operation
+/// ended.
+/// After the last asyncStart() called was matched with a corresponding
+/// asyncEnd() call, the testing driver will be notified that the tests is done.
+
+library async_helper;
+
+
+bool _initialized = false;
+int _asyncLevel = 0;
+
+Exception _buildException(String msg) {
+ return new Exception('Fatal: $msg. This is most likely a bug in your test.');
+}
+
+void asyncStart() {
+ if (_initialized && _asyncLevel == 0) {
+ throw _buildException('asyncStart() was called even though we are done '
+ 'with testing.');
+ }
+ if (!_initialized) {
+ print('unittest-suite-wait-for-done');
+ _initialized = true;
+ }
+ _asyncLevel++;
+}
+
+void asyncEnd() {
+ if (_asyncLevel <= 0) {
+ if (!_initialized) {
+ throw _buildException('asyncEnd() was called before asyncStart().');
+ } else {
+ throw _buildException('asyncEnd() was called more often than '
+ 'asyncStart().');
+ }
+ }
+ _asyncLevel--;
+ if (_asyncLevel == 0) {
+ print('unittest-suite-done');
+ }
+}
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index c3a7852..98b0881 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -4,154 +4,71 @@
[ $compiler == dartanalyzer ]
Language/05_Variables/05_Variables_A05_t04: fail
-Language/06_Functions/06_Functions_A01_t31: fail
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: fail
Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: fail
Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t03: fail
-Language/06_Functions/2_Formal_Parameters_A01_t02: fail
-Language/06_Functions/2_Formal_Parameters_A01_t09: fail
Language/06_Functions/2_Formal_Parameters_A02_t02: fail
-Language/07_Classes/07_Classes_A01_t20: fail
-Language/07_Classes/07_Classes_A09_t01: fail
-Language/07_Classes/07_Classes_A09_t02: fail
-Language/07_Classes/07_Classes_A09_t03: fail
-Language/07_Classes/07_Classes_A09_t04: fail
-Language/07_Classes/2_Getters_A04_t03: fail
-Language/07_Classes/2_Getters_A04_t04: fail
-Language/07_Classes/2_Getters_A04_t05: fail
-Language/07_Classes/2_Getters_A04_t07: fail
-Language/07_Classes/3_Setters_A03_t02: fail
-Language/07_Classes/3_Setters_A03_t04: fail
-Language/07_Classes/3_Setters_A03_t06: fail
-Language/07_Classes/3_Setters_A03_t08: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: fail
Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A11_t09: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t01: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A14_t04: fail
-Language/07_Classes/6_Constructors/1_Generative_Constructors_A15_t07: fail
-Language/07_Classes/6_Constructors/2_Factories_A06_t01: fail
-Language/07_Classes/6_Constructors/2_Factories_A06_t02: fail
-Language/07_Classes/6_Constructors/2_Factories_A06_t04: fail
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: fail
Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: fail
-Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: fail
-Language/07_Classes/7_Static_Methods_A01_t01: fail
-Language/09_Generics/09_Generics_A04_t07: fail
-Language/11_Expressions/01_Constants_A01_t01: fail
-Language/11_Expressions/01_Constants_A11_t03: fail
-Language/11_Expressions/01_Constants_A15_t07: fail
-Language/11_Expressions/01_Constants_A15_t08: fail
Language/11_Expressions/01_Constants_A16_t01: fail
Language/11_Expressions/01_Constants_A16_t02: fail
Language/11_Expressions/01_Constants_A16_t03: fail
Language/11_Expressions/01_Constants_A17_t03: fail
-Language/11_Expressions/01_Constants_A19_t04: fail
-Language/11_Expressions/03_Numbers_A01_t01: fail
-Language/11_Expressions/03_Numbers_A01_t02: fail
-Language/11_Expressions/03_Numbers_A01_t03: fail
-Language/11_Expressions/03_Numbers_A01_t04: fail
-Language/11_Expressions/03_Numbers_A01_t08: fail
-Language/11_Expressions/03_Numbers_A01_t10: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A03_t01: fail
-Language/11_Expressions/05_Strings/1_String_Interpolation_A04_t01: fail
Language/11_Expressions/05_Strings_A02_t46: fail
Language/11_Expressions/05_Strings_A02_t48: fail
-Language/11_Expressions/06_Lists_A03_t01: fail
-Language/11_Expressions/06_Lists_A06_t01: fail
Language/11_Expressions/11_Instance_Creation/1_New_A13_t02: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A06_t01: fail
-Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: fail
Language/11_Expressions/11_Instance_Creation_A05_t02: fail
-Language/11_Expressions/14_Function_Invocation/1_Actual_Argument_List_Evaluation_A02_t01: fail
-Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t05: fail
-Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A02_t01: fail
-Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t01: fail
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A04_t01: fail
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A08_t01: fail
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t01: fail
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t07: fail
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t05: fail
-Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A06_t02: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t04: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t01: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t02: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t03: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A03_t04: fail
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A08_t02: fail
Language/11_Expressions/22_Equality_A01_t15: fail
Language/11_Expressions/22_Equality_A01_t16: fail
-Language/11_Expressions/28_Postfix_Expressions_A01_t06: fail
-Language/11_Expressions/30_Identifier_Reference_A01_t07: fail
-Language/11_Expressions/30_Identifier_Reference_A01_t08: fail
-Language/11_Expressions/33_Argument_Definition_Test_A01_t14: fail
-Language/11_Expressions/33_Argument_Definition_Test_A01_t18: fail
-Language/12_Statements/02_Expression_Statements_A01_t06: fail
-Language/12_Statements/09_Switch_A04_t01: fail
-Language/13_Libraries_and_Scripts/13_Libraries_and_Scripts_A03_t17: fail
-Language/13_Libraries_and_Scripts/1_Imports_A01_t46: fail
-Language/13_Libraries_and_Scripts/1_Imports_A04_t03: fail
Language/13_Libraries_and_Scripts/1_Imports_A05_t01: fail
-Language/13_Libraries_and_Scripts/2_Exports_A05_t01: fail
Language/13_Libraries_and_Scripts/5_URIs_A01_t24: fail
Language/13_Libraries_and_Scripts/5_URIs_A01_t25: fail
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t01: fail
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t02: fail
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t03: fail
Language/14_Types/3_Type_Declarations/1_Typedef_A07_t04: fail
-Language/14_Types/4_Interface_Types_A10_t03: fail
-Language/14_Types/4_Interface_Types_A10_t04: fail
-Language/14_Types/4_Interface_Types_A10_t09: fail
Language/15_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: fail
-Language/15_Reference/1_Lexical_Rules_A01_t10: fail
Language/15_Reference/1_Lexical_Rules_A02_t06: fail
-LibTest/core/AssertionError/column_A01_t02: fail
-LibTest/core/AssertionError/failedAssertion_A01_t01: fail
-LibTest/core/AssertionError/line_A01_t02: fail
-LibTest/core/AssertionError/url_A01_t01: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A03_t02: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A04_t01: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A07_t01: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A08_t01: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A08_t02: fail
-LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A09_t01: fail
-LibTest/core/Set/isSubsetOf_A01_t01: fail
-LibTest/core/Set/isSubsetOf_A01_t02: fail
-LibTest/core/String/String_class_A01_t01: fail
-LibTest/core/String/charCodeAt_A01_t01: fail
-LibTest/core/String/charCodeAt_A02_t01: fail
-LibTest/core/String/charCodeAt_A03_t01: fail
-LibTest/core/String/charCodes_A01_t01: fail
-LibTest/core/String/concat_A01_t01: fail
-LibTest/core/String/concat_A02_t01: fail
-LibTest/core/String/hashCode_A01_t01: fail
-LibTest/core/String/splitChars_A01_t01: fail
-LibTest/core/StringBuffer/addAll_A01_t01: fail
-LibTest/core/StringBuffer/addAll_A01_t02: fail
-LibTest/core/StringBuffer/addAll_A03_t01: fail
-LibTest/core/StringBuffer/add_A01_t01: fail
-LibTest/core/StringBuffer/add_A01_t02: fail
-LibTest/core/StringBuffer/isEmpty_A01_t01: fail
-LibTest/core/StringBuffer/toString_A01_t01: fail
-LibTest/core/double/ceil_A01_t05: fail
-LibTest/core/double/floor_A01_t05: fail
-LibTest/core/int/operator_division_A01_t01: fail
+
# fails locally, passes on bot
Language/13_Libraries_and_Scripts/3_Parts_A02_t03: skip
+# co19 issue #380, Strings class has been removed
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail, OK
+
+# co19 issue #382, Deprecated parts of String interface is being removed.
+LibTest/core/String/charCodes_A01_t01: fail, OK
+LibTest/core/String/charCodeAt_A02_t01: fail, OK
+LibTest/core/String/charCodeAt_A03_t01: fail, OK
+LibTest/core/String/charCodeAt_A01_t01: fail, OK
+LibTest/core/String/splitChars_A01_t01: fail, OK
+
+# co19 issue #389, ceil, floor, truncate and round return integers
+LibTest/core/int/operator_division_A01_t01: fail
+
+# co19 issue #395, uses dart:io API (outdated)
+Language/15_Reference/1_Lexical_Rules_A01_t10: Fail, OK
+
# co19 issue #397, List.addLast removed
+Language/11_Expressions/06_Lists_A06_t01: fail, OK
LibTest/core/Iterable/where_A01_t07: fail, OK
LibTest/core/List/addLast_A01_t01: fail, OK
LibTest/core/List/addLast_A01_t03: fail, OK
LibTest/core/List/addLast_A02_t01: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: fail, OK
# co19 issue #400, collection library reorg
LibTest/core/List/List.fixedLength_A01_t01: fail, OK
LibTest/core/List/operator_subscript_A01_t02: fail, OK
+LibTest/core/String/String_class_A01_t01: fail, OK
+LibTest/core/String/concat_A01_t01: fail, OK
+LibTest/core/String/concat_A02_t01: fail, OK
+LibTest/core/String/hashCode_A01_t01: fail, OK
+LibTest/core/Set/isSubsetOf_A01_t01: fail, OK
+LibTest/core/Set/isSubsetOf_A01_t02: fail, OK
# co19 issue #403
LibTest/core/List/List_A01_t02: fail, OK
@@ -210,3 +127,70 @@
Language/05_Variables/05_Variables_A12_t06: fail, OK
Language/05_Variables/05_Variables_A13_t01: fail, OK
Language/07_Classes/07_Classes_A02_t11: fail, OK
+
+# co19 issue #429, It is a compile-time error if a formal parameter is declared as a constant variable
+Language/07_Classes/6_Constructors/1_Generative_Constructors_A15_t07: fail, OK
+
+# co19 issue #430, return not subtype from factory
+Language/07_Classes/6_Constructors/2_Factories_A06_t01: fail, OK
+Language/07_Classes/6_Constructors/2_Factories_A06_t02: fail, OK
+Language/07_Classes/6_Constructors/2_Factories_A06_t04: fail, OK
+
+# co19 issue #431, it is OK to use 'double' argument for const constructor
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: fail, OK
+Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: fail, OK
+
+# co19 issue #428, number literals with a + prefix
+Language/11_Expressions/01_Constants_A01_t01: fail, OK
+Language/11_Expressions/03_Numbers_A01_t01: fail, OK
+Language/11_Expressions/03_Numbers_A01_t02: fail, OK
+Language/11_Expressions/03_Numbers_A01_t03: fail, OK
+Language/11_Expressions/03_Numbers_A01_t04: fail, OK
+Language/11_Expressions/03_Numbers_A01_t08: fail, OK
+Language/11_Expressions/03_Numbers_A01_t10: fail, OK
+Language/12_Statements/02_Expression_Statements_A01_t06: fail, OK
+LibTest/core/double/ceil_A01_t05: fail, OK
+LibTest/core/double/floor_A01_t05: fail, OK
+
+# co19 issue #385, library name is not required
+Language/13_Libraries_and_Scripts/1_Imports_A04_t03: fail, OK
+Language/13_Libraries_and_Scripts/2_Exports_A05_t01: fail, OK
+
+# co19 issue #388, StringBuffer renamed add to write
+Language/11_Expressions/05_Strings/1_String_Interpolation_A03_t01: fail, OK
+Language/11_Expressions/05_Strings/1_String_Interpolation_A04_t01: fail, OK
+Language/11_Expressions/14_Function_Invocation/1_Actual_Argument_List_Evaluation_A02_t01: fail, OK
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A04_t01: fail, OK
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t05: fail, OK
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t04: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A03_t02: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A04_t01: fail, OK
+LibTest/core/StringBuffer/addAll_A03_t01: fail, OK
+LibTest/core/StringBuffer/add_A01_t01: fail, OK
+LibTest/core/StringBuffer/add_A01_t02: fail, OK
+LibTest/core/StringBuffer/addAll_A01_t01: fail, OK
+LibTest/core/StringBuffer/addAll_A01_t02: fail, OK
+LibTest/core/StringBuffer/isEmpty_A01_t01: fail, OK
+LibTest/core/StringBuffer/toString_A01_t01: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A07_t01: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A08_t01: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A08_t02: fail, OK
+LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A09_t01: fail, OK
+
+#co19 issue #432, missing @static-warning annotation
+Language/14_Types/8_Parameterized_Types_A03_t03: fail,OK
+Language/14_Types/8_Parameterized_Types_A03_t05: fail,OK
+
+# co19 issue #433, missing @static-warning annotation
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t01: fail, OK
+Language/11_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t07: fail, OK
+
+# co19 issue #434, argument definition was dropped
+Language/11_Expressions/33_Argument_Definition_Test_A01_t14: fail, OK
+Language/11_Expressions/33_Argument_Definition_Test_A01_t18: fail, OK
+
+# co19 issue #435, AssertioError has not properties
+LibTest/core/AssertionError/column_A01_t02: fail, OK
+LibTest/core/AssertionError/failedAssertion_A01_t01: fail, OK
+LibTest/core/AssertionError/line_A01_t02: fail, OK
+LibTest/core/AssertionError/url_A01_t01: fail, OK
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 065b1c1..dcbf037 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -19,7 +19,6 @@
Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: Fail # TODO(dart2dart-team): Please triage this failure.
Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t03: Fail # TODO(dart2dart-team): Please triage this failure.
Language/11_Expressions/01_Constants_A18_t06: Fail # TODO(dart2dart-team): Please triage this failure.
-Language/11_Expressions/11_Instance_Creation/2_Const_A03_t01: Fail # TODO(dart2dart-team): Please triage this failure.
Language/11_Expressions/11_Instance_Creation_A05_t02: Fail # TODO(dart2dart-team): Please triage this failure.
Language/11_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: Fail # TODO(dart2dart-team): Please triage this failure.
Language/11_Expressions/33_Argument_Definition_Test_A02_t02: Fail # TODO(dart2dart-team): Please triage this failure.
@@ -253,7 +252,6 @@
Language/11_Expressions/05_Strings_A20_t01: Fail # inherited from VM
Language/11_Expressions/06_Lists_A03_t01: Fail # http://dartbug.com/5519
Language/11_Expressions/06_Lists_A03_t02: Fail # http://dartbug.com/5519
-Language/11_Expressions/06_Lists_A04_t01: Fail # http://dartbug.com/5519
Language/11_Expressions/07_Maps_A01_t01: Skip # co19 issue 91: map literals illegal at statement beginning.
Language/11_Expressions/07_Maps_A02_t01: Fail # http://dartbug.com/5519
Language/11_Expressions/07_Maps_A02_t02: Fail # http://dartbug.com/5519
@@ -421,6 +419,17 @@
LibTest/core/String/lastIndexOf_A01_t02: Fail # Issue 427
[ $compiler == dart2dart && $minified ]
+Language/14_Types/5_Function_Types_A01_t07: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A01_t08: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A01_t09: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A01_t11: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A02_t05: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A02_t09: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A02_t10: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A03_t06: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A03_t10: Fail # dartbug.com/11467
+Language/14_Types/5_Function_Types_A03_t11: Fail # dartbug.com/11467
+
Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 396
Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail, OK # co19 issue 396
Language/11_Expressions/18_Assignment_A05_t02: Fail, OK # co19 issue 396
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index fb5aa0d..28e9415 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -4,6 +4,7 @@
[ $compiler == dart2js && $runtime == jsshell ]
LibTest/isolate/isolate_api/spawnUri_A02_t01: Crash # TODO(ahe): Please triage this crash.
+LibTest/core/List/sort_A01_t04: Pass, Timeout # Must be a bug in jsshell, test sometimes times out.
[ $compiler == dart2js && $checked && $runtime == ie9 ]
LibTest/core/Map/Map_class_A01_t04: Slow, Pass
@@ -47,7 +48,6 @@
Language/11_Expressions/11_Instance_Creation/1_New_A02_t06: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation/1_New_A02_t07: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation/2_Const_A01_t02: Fail # TODO(ahe): Please triage this failure.
-Language/11_Expressions/11_Instance_Creation/2_Const_A03_t01: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation/2_Const_A11_t01: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation/2_Const_A11_t03: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation_A05_t02: Fail # TODO(ahe): Please triage this failure.
@@ -77,7 +77,6 @@
Language/12_Statements/04_Local_Function_Declaration_A02_t02: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/09_Switch_A02_t02: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/09_Switch_A06_t02: Fail # co19 issue 413
-Language/12_Statements/10_Try_A06_t01: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/10_Try_A07_t03: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/11_Return_A05_t01: Fail # TODO(ahe): Please triage this failure.
Language/12_Statements/11_Return_A05_t02: Fail # TODO(ahe): Please triage this failure.
@@ -170,8 +169,6 @@
[ $compiler == dart2js && $runtime == ie9 ]
Language/11_Expressions/03_Numbers_A01_t06: Fail # Issue: 8920
Language/11_Expressions/03_Numbers_A01_t09: Fail # Issue: 8920
-Language/11_Expressions/06_Lists_A07_t02: Fail # Issue: 8920
-Language/11_Expressions/07_Maps_A06_t02: Fail # Issue: 8920
Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t04: Fail # Issue: 8920
LibTest/core/Date/Date_A01_t03: Fail # Issue: 8920
LibTest/core/Date/Date.fromString_A03_t01: Fail # Issue: 8920
@@ -225,6 +222,8 @@
Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK
Language/11_Expressions/18_Assignment_A08_t04: Fail, OK
+[ $compiler == dart2js && ($minified || $runtime == ie9) ]
+Language/12_Statements/10_Try_A06_t01: Fail # BUG(11480): Triage.
[ $compiler == dart2js && $checked ]
Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t03: Fail # TODO(ahe): Please triage this failure.
@@ -234,7 +233,6 @@
Language/11_Expressions/03_Numbers_A05_t02: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/06_Lists_A09_t01: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/06_Lists_A09_t04: Fail # TODO(ahe): Please triage this failure.
-Language/11_Expressions/06_Lists_A09_t05: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/07_Maps_A10_t05: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/07_Maps_A11_t01: Fail # TODO(ahe): Please triage this failure.
Language/11_Expressions/11_Instance_Creation/1_New_A07_t01: Fail # TODO(ahe): Please triage this failure.
@@ -269,8 +267,6 @@
Language/11_Expressions/11_Instance_Creation/1_New_A12_t02: Fail # http://dartbug.com/3970
-Language/14_Types/3_Type_Declarations/1_Typedef_A01_t01: Fail # http://dartbug.com/5022
-
Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 405
Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK # co19 issue 405
@@ -618,7 +614,13 @@
Language/11_Expressions/30_Identifier_Reference_A02_t01: Fail # Pseudo keyword "abstract".
Language/12_Statements/06_For_A01_t11: Fail # http://dartbug.com/9824
-Language/14_Types/6_Type_dynamic_A03_t01: Fail # Renamed Date to DateTime (issue 373, 374)
+
+
+# BUG(11331): Renamed Date to DateTime (issue 373, 374) but this only has an
+# impact on V8, because of the way method calls are evaluated. Needs more
+# investigation.
+[ $compiler == dart2js && $runtime == d8 ]
+Language/14_Types/6_Type_dynamic_A03_t01: Fail
[ $compiler == dart2js && $jscl ]
@@ -628,10 +630,6 @@
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Expect.fail('Some exception expected')
LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Expect.fail('Some exception expected')
-Language/11_Expressions/06_Lists_A07_t02: Fail # generic type information is lost during canonicalization.
-Language/11_Expressions/07_Maps_A06_t02: Fail # generic type information is lost during canonicalization.
-
-
#
# The following tests may be broken, but require further review.
@@ -692,7 +690,6 @@
Language/11_Expressions/01_Constants_A16_t02: Fail # Checks that an OutOfMemoryException raised during evaluation of a compile-time constant causes a compile-time error.
Language/11_Expressions/05_Strings_A02_t46: Fail # Checks that multi-line strings that contain characters and sequences prohibited by this grammar, cause compile-time errors.
Language/11_Expressions/05_Strings_A02_t48: Fail # Checks that multi-line strings that contain characters and sequences prohibited by this grammar, cause compile-time errors.
-Language/11_Expressions/06_Lists_A04_t01: Fail # Checks that it is a compile-time error if the type argument of a constant list literal includes a type variable.
Language/11_Expressions/22_Equality_A01_t15: Fail # Checks that equality expressions cannot be operands of another equality expression.
Language/11_Expressions/22_Equality_A01_t16: Fail # Checks that equality expressions cannot be operands of another equality expression.
Language/11_Expressions/23_Relational_Expressions_A01_t10: Fail # Checks that a relational expression cannot be the operand of another relational expression.
@@ -716,7 +713,6 @@
Language/07_Classes/3_Setters_A04_t06: Fail # http://dartbug.com/5023
Language/07_Classes/3_Setters_A04_t07: Fail # http://dartbug.com/5023
-
Language/13_Libraries_and_Scripts/4_Scripts_A03_t01: Fail # http://dartbug.com/5683
Language/13_Libraries_and_Scripts/4_Scripts_A03_t03: Fail # http://dartbug.com/5683
@@ -727,6 +723,9 @@
# Unexpected runtime errors.
#
[ $compiler == dart2js ]
+#Language/11_Expressions/32_Type_Cast_A01_t01: Fail # http://dartbug.com/9074
+
+#Language/14_Types/4_Interface_Types_A08_t06: Fail # class Queue cannot be resolved.
Language/14_Types/4_Interface_Types_A11_t04: Fail # http://dartbug.com/5020
Language/14_Types/4_Interface_Types_A12_t10: Fail # http://dartbug.com/5020
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 6a518b5..82e9361 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -2,6 +2,9 @@
# 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.
+[ $runtime == vm && $system == windows ]
+LibTest/core/Stopwatch/elapsed_A01_t01: Pass, Fail # Issue 11382.
+
[ $runtime == vm ]
Language/11_Expressions/33_Argument_Definition_Test_A02_t02: Crash, Pass # http://dartbug.com/9597
Language/07_Classes/6_Constructors_A02_t01: Skip # co19 issue 415.
@@ -508,7 +511,6 @@
LibTest/math/sin_A01_t01: Pass, Fail
LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
LibTest/core/int/operator_unary_minus_A01_t01: Pass, Fail
-LibTest/math/Random/nextDouble_A01_t01: Pass, Fail
[ $compiler == none && $runtime == vm && $arch == arm && $mode == debug ]
@@ -519,28 +521,39 @@
LibTest/core/double/floor_A01_t02: Fail
LibTest/core/double/truncate_A01_t01: Fail
-
-[ $compiler == none && $runtime == vm && $arch == simarm ]
-LibTest/math/tan_A01_t01: Pass, Fail
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-LibTest/core/int/operator_unary_minus_A01_t01: Fail, Pass # Pass on Mac
+[ $compiler == none && $runtime == vm && $arch == simarm && $mode == release ]
+LibTest/math/tan_A01_t01: Fail
LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
-LibTest/math/Random/nextDouble_A01_t01: Pass, Crash
-
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+LibTest/core/int/operator_unary_minus_A01_t01: Fail
+LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
[ $compiler == none && $runtime == vm && $arch == simarm && $mode == debug ]
-LibTest/core/Expect/throws_A01_t04: Crash
+LibTest/math/tan_A01_t01: Fail
+LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
LibTest/core/List/sort_A01_t05: Crash
LibTest/core/List/sort_A01_t06: Crash
-LibTest/core/double/ceil_A01_t02: Fail, Pass # Pass on Mac
-LibTest/core/double/floor_A01_t02: Fail, Pass # Pass on Mac
-LibTest/core/double/truncate_A01_t01: Fail, Pass # Pass on Mac
-
+LibTest/core/double/ceil_A01_t02: Fail, Pass # Passes on Mac.
+LibTest/core/double/floor_A01_t02: Fail, Pass # Passes on Mac.
+LibTest/core/double/truncate_A01_t01: Fail, Pass # Passes on Mac.
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+LibTest/core/int/operator_unary_minus_A01_t01: Fail
[ $compiler == none && $runtime == vm && $arch == mips ]
*: Skip
-[ $compiler == none && $runtime == vm && $arch == simmips ]
-*: Skip
+[ $compiler == none && $runtime == vm && $arch == simmips && $mode == release ]
+LibTest/math/tan_A01_t01: Fail
+LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
+LibTest/core/int/operator_unary_minus_A01_t01: Fail
+[ $compiler == none && $runtime == vm && $arch == simmips && $mode == debug ]
+LibTest/math/tan_A01_t01: Fail
+LibTest/math/cos_A01_t01: Pass, Fail # Fail on Mac
+LibTest/core/List/sort_A01_t04: Crash # Too far relative jump.
+LibTest/core/List/sort_A01_t05: Crash
+LibTest/core/List/sort_A01_t06: Crash
+LibTest/core/int/operator_unary_minus_A01_t01: Fail
+LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 29ad0ef..5c6da03 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -20,7 +20,7 @@
// TODO(johnniwinther): Support canonical URIs as keys and message kinds as
// values.
const Map<String, List<String>> WHITE_LIST = const {
- 'html_dart2js.dart':
+ 'path_observer.dart':
const ['Warning: Using "new Symbol"', // Issue 10565.
],
};
diff --git a/tests/compiler/dart2js/bad_loop_test.dart b/tests/compiler/dart2js/bad_loop_test.dart
index dbf8795..5cecb22 100644
--- a/tests/compiler/dart2js/bad_loop_test.dart
+++ b/tests/compiler/dart2js/bad_loop_test.dart
@@ -9,7 +9,7 @@
show Diagnostic;
main() {
- Uri script = currentDirectory.resolve(nativeToUriPath(new Options().script));
+ Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libraryRoot = script.resolve('../../../sdk/');
Uri packageRoot = script.resolve('./packages/');
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index d3fd545..0e7b685 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -222,7 +222,7 @@
int index = 0;
signature.forEachParameter((Element element) {
Expect.equals(expectedTypes[index++],
- inferrer.internal.typeOf[element].simplify(inferrer.compiler));
+ inferrer.getTypeOfElement(element).simplify(inferrer.compiler));
});
Expect.equals(index, expectedTypes.length);
});
@@ -247,14 +247,12 @@
runTest(TEST_7a, (inferrer) => [subclassOfInterceptor(inferrer)]);
runTest(TEST_7b, (inferrer) => [inferrer.dynamicType.nonNullable()]);
- // In the following tests, we can't infer the right types because we
- // have recursive calls with the same parameters. We should build a
- // constraint system for those, to find the types.
- runTest(TEST_8, (inferrer) => [inferrer.dynamicType,
+ runTest(TEST_8, (inferrer) => [inferrer.intType,
subclassOfInterceptor(inferrer),
inferrer.dynamicType.nonNullable()]);
- runTest(TEST_9, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
- runTest(TEST_10, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+ runTest(TEST_9, (inferrer) => [inferrer.intType, inferrer.intType]);
+ runTest(TEST_10, (inferrer) => [subclassOfInterceptor(inferrer),
+ subclassOfInterceptor(inferrer)]);
runTest(TEST_11, (inferrer) => [subclassOfInterceptor(inferrer),
subclassOfInterceptor(inferrer)]);
@@ -274,7 +272,8 @@
inferrer.boolType,
inferrer.doubleType]);
- runTest(TEST_18, (inferrer) => [inferrer.dynamicType, inferrer.dynamicType]);
+ runTest(TEST_18, (inferrer) => [subclassOfInterceptor(inferrer),
+ subclassOfInterceptor(inferrer)]);
}
void main() {
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index 23884da..4e8d498 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -9,7 +9,7 @@
show SourceString;
Map<String, String> generate(String code, [List<String> options = const []]) {
- Uri script = currentDirectory.resolve(nativeToUriPath(new Options().script));
+ Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libraryRoot = script.resolve('../../../sdk/');
Uri packageRoot = script.resolve('./packages/');
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index 8284448..71d8488 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -34,7 +34,7 @@
printElement.computeSignature(compiler).requiredParameters.head;
var type = compiler.typesTask.getGuaranteedTypeOfElement(parameter);
var inferrer = compiler.typesTask.typesInferrer;
- Expect.identical(inferrer.dynamicType, type);
+ Expect.identical(inferrer.dynamicType, type.simplify(compiler));
});
compileAndFind(
@@ -63,7 +63,7 @@
});
checkPrintType('[]', (compiler, type) {
var inferrer = compiler.typesTask.typesInferrer;
- if (type.isContainer) type = type.asFlat;
+ if (type.isForwarding) type = type.forwardTo;
Expect.identical(inferrer.growableListType, type);
});
checkPrintType('null', (compiler, type) {
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 493a8b7..0040e8c 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -159,7 +159,9 @@
class Object {}
class Function {}
abstract class List<E> {
- factory List([int length]) => JS('=List', r'new Array(#)', length);
+ factory List([int length]) {
+ return JS('JSExtendableArray', r'new Array(#)', length);
+ }
}
abstract class Map<K, V> {}
class Closure {}
@@ -1123,6 +1125,7 @@
testJsCall() {
final String source = r"""
import 'dart:foreign';
+ import 'dart:interceptors';
class A {}
class B extends A {}
@@ -1138,7 +1141,7 @@
var a = JS('', '1');
var b = JS('Object', '1');
- var c = JS('=List', '1');
+ var c = JS('JSExtendableArray', '1');
var d = JS('String', '1');
var e = JS('int', '1');
var f = JS('double', '1');
@@ -1152,7 +1155,8 @@
AnalysisResult result = analyze(source);
result.checkNodeHasUnknownType('a');
result.checkNodeHasUnknownType('b');
- result.checkNodeHasType('c', [result.nullType, result.list]);
+ // TODO(polux): Fix this test.
+ // result.checkNodeHasType('c', [result.nullType, result.list]);
result.checkNodeHasType('d', [result.nullType, result.string]);
result.checkNodeHasType('e', [result.nullType, result.int]);
result.checkNodeHasType('f', [result.nullType, result.double]);
diff --git a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
index eec688a..b6b1065 100644
--- a/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
+++ b/tests/compiler/dart2js/deferred_load_graph_segmentation_test.dart
@@ -13,7 +13,7 @@
as dart2js;
void main() {
- Uri script = currentDirectory.resolve(nativeToUriPath(new Options().script));
+ Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libraryRoot = script.resolve('../../../sdk/');
Uri packageRoot = script.resolve('./packages/');
diff --git a/tests/compiler/dart2js/diagnose_ambiguous_test.dart b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
index cd10b1b..39f9d8f 100644
--- a/tests/compiler/dart2js/diagnose_ambiguous_test.dart
+++ b/tests/compiler/dart2js/diagnose_ambiguous_test.dart
@@ -11,7 +11,7 @@
import 'dart:json';
main() {
- Uri script = currentDirectory.resolve(nativeToUriPath(new Options().script));
+ Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libraryRoot = script.resolve('../../../sdk/');
Uri packageRoot = script.resolve('./packages/');
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 1e25741..db2d968 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -453,7 +453,7 @@
(inferrer, field) {
TypeMask type = f(inferrer);
TypeMask inferredType =
- inferrer.internal.typeOf[field].simplify(inferrer.compiler);
+ inferrer.getTypeOfElement(field).simplify(inferrer.compiler);
Expect.equals(type, inferredType, name);
});
});
@@ -522,8 +522,8 @@
'f3': (inferrer) => inferrer.intType.nullable(),
'f4': (inferrer) => inferrer.intType.nullable()});
- runTest(TEST_24, {'f1': (inferrer) => inferrer.numType,
- 'f2': (inferrer) => inferrer.numType,
+ runTest(TEST_24, {'f1': (inferrer) => inferrer.intType,
+ 'f2': (inferrer) => inferrer.intType,
'f3': (inferrer) => inferrer.intType,
'f4': (inferrer) => inferrer.intType,
'f5': (inferrer) => inferrer.numType.nullable(),
diff --git a/tests/compiler/dart2js/inferrer_factory_test.dart b/tests/compiler/dart2js/inferrer_factory_test.dart
new file mode 100644
index 0000000..7e2c9ec
--- /dev/null
+++ b/tests/compiler/dart2js/inferrer_factory_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+import 'compiler_helper.dart';
+
+const String TEST1 = r"""
+class A implements List {
+ factory A() {
+ // Avoid inlining by using try/catch.
+ try {
+ return new List();
+ } catch (e) {
+ }
+ }
+}
+
+main() {
+ new A()[0] = 42;
+}
+""";
+
+main() {
+ String generated = compileAll(TEST1);
+ // Check that we're using the index operator on the object returned
+ // by the A factory.
+ Expect.isTrue(generated.contains('[0] = 42'));
+}
+
diff --git a/tests/compiler/dart2js/list_tracer_node_type_test.dart b/tests/compiler/dart2js/list_tracer_node_type_test.dart
index e8022e6..ad06034 100644
--- a/tests/compiler/dart2js/list_tracer_node_type_test.dart
+++ b/tests/compiler/dart2js/list_tracer_node_type_test.dart
@@ -29,6 +29,14 @@
}
""";
+const String TEST4 = r"""
+main() {
+ var a = new List.filled(42, null);
+ a[0] = 42;
+ return a[0] + 42;
+}
+""";
+
main() {
String generated = compileAll(TEST1);
@@ -45,4 +53,8 @@
generated = compileAll(TEST3);
Expect.isFalse(generated.contains('if (typeof t1'));
Expect.isTrue(generated.contains('if (t1 == null)'));
+
+ generated = compileAll(TEST4);
+ Expect.isFalse(generated.contains('if (typeof t1'));
+ Expect.isTrue(generated.contains('if (t1 == null)'));
}
diff --git a/tests/compiler/dart2js/list_tracer_test.dart b/tests/compiler/dart2js/list_tracer_test.dart
index a82cac8..d782239 100644
--- a/tests/compiler/dart2js/list_tracer_test.dart
+++ b/tests/compiler/dart2js/list_tracer_test.dart
@@ -85,6 +85,7 @@
var listPassedAsOptionalParameter = $listAllocation;
var listPassedAsNamedParameter = $listAllocation;
var listSetInNonFinalField = $listAllocation;
+var listWithChangedLength = $listAllocation;
foo(list) {
list[0] = aDouble;
@@ -170,17 +171,22 @@
listSetInNonFinalField[0] = anInt;
new B(listSetInNonFinalField);
+
+ listWithChangedLength[0] = anInt;
+ listWithChangedLength.length = 54;
}
""";
}
void main() {
- doTest('[]'); // Test literal list.
- doTest('new List()'); // Test growable list.
- doTest('new List(1)'); // Test fixed list.
+ doTest('[]', nullify: false); // Test literal list.
+ doTest('new List()', nullify: false); // Test growable list.
+ doTest('new List(1)', nullify: true); // Test fixed list.
+ doTest('new List.filled(1, 0)', nullify: false); // Test List.filled.
+ doTest('new List.filled(1, null)', nullify: true); // Test List.filled.
}
-void doTest(String allocation) {
+void doTest(String allocation, {bool nullify}) {
Uri uri = new Uri(scheme: 'source');
var compiler = compilerFor(generateTest(allocation), uri);
compiler.runCompiler(uri);
@@ -188,26 +194,28 @@
checkType(String name, type) {
var element = findElement(compiler, name);
- ContainerTypeMask mask = typesInferrer.internal.typeOf[element];
+ ContainerTypeMask mask = typesInferrer.getTypeOfElement(element);
+ if (nullify) type = type.nullable();
Expect.equals(type, mask.elementType.simplify(compiler), name);
}
- checkType('listInField', typesInferrer.numType.nullable());
- checkType('listPassedToMethod', typesInferrer.numType.nullable());
- checkType('listReturnedFromMethod', typesInferrer.numType.nullable());
- checkType('listUsedWithCascade', typesInferrer.numType.nullable());
- checkType('listUsedInClosure', typesInferrer.numType.nullable());
- checkType('listPassedToSelector', typesInferrer.numType.nullable());
- checkType('listReturnedFromSelector', typesInferrer.numType.nullable());
- checkType('listUsedWithAddAndInsert', typesInferrer.numType.nullable());
- checkType('listUsedWithConstraint', typesInferrer.numType.nullable());
- checkType('listEscapingFromSetter', typesInferrer.numType.nullable());
- checkType('listUsedInLocal', typesInferrer.numType.nullable());
- checkType('listEscapingInSetterValue', typesInferrer.numType.nullable());
- checkType('listEscapingInIndex', typesInferrer.numType.nullable());
- checkType('listEscapingInIndexSet', typesInferrer.intType.nullable());
- checkType('listEscapingTwiceInIndexSet', typesInferrer.numType.nullable());
- checkType('listSetInNonFinalField', typesInferrer.numType.nullable());
+ checkType('listInField', typesInferrer.numType);
+ checkType('listPassedToMethod', typesInferrer.numType);
+ checkType('listReturnedFromMethod', typesInferrer.numType);
+ checkType('listUsedWithCascade', typesInferrer.numType);
+ checkType('listUsedInClosure', typesInferrer.numType);
+ checkType('listPassedToSelector', typesInferrer.numType);
+ checkType('listReturnedFromSelector', typesInferrer.numType);
+ checkType('listUsedWithAddAndInsert', typesInferrer.numType);
+ checkType('listUsedWithConstraint', typesInferrer.numType);
+ checkType('listEscapingFromSetter', typesInferrer.numType);
+ checkType('listUsedInLocal', typesInferrer.numType);
+ checkType('listEscapingInSetterValue', typesInferrer.numType);
+ checkType('listEscapingInIndex', typesInferrer.numType);
+ checkType('listEscapingInIndexSet', typesInferrer.intType);
+ checkType('listEscapingTwiceInIndexSet', typesInferrer.numType);
+ checkType('listSetInNonFinalField', typesInferrer.numType);
+ checkType('listWithChangedLength', typesInferrer.intType.nullable());
checkType('listPassedToClosure', typesInferrer.dynamicType);
checkType('listReturnedFromClosure', typesInferrer.dynamicType);
@@ -215,6 +223,8 @@
checkType('listPassedAsOptionalParameter', typesInferrer.dynamicType);
checkType('listPassedAsNamedParameter', typesInferrer.dynamicType);
- checkType('listUnset', new TypeMask.empty());
- checkType('listOnlySetWithConstraint', new TypeMask.empty());
+ if (!allocation.contains('filled')) {
+ checkType('listUnset', new TypeMask.nonNullEmpty());
+ checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
+ }
}
diff --git a/tests/compiler/dart2js/memory_source_file_helper.dart b/tests/compiler/dart2js/memory_source_file_helper.dart
index 10f3102..987fff7 100644
--- a/tests/compiler/dart2js/memory_source_file_helper.dart
+++ b/tests/compiler/dart2js/memory_source_file_helper.dart
@@ -6,7 +6,7 @@
import 'dart:async' show Future;
import 'dart:io';
-export 'dart:io' show Options;
+export 'dart:io' show Platform;
export '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart'
show Compiler;
diff --git a/tests/compiler/dart2js/mini_parser_test.dart b/tests/compiler/dart2js/mini_parser_test.dart
index 7227f28..dc2d642 100644
--- a/tests/compiler/dart2js/mini_parser_test.dart
+++ b/tests/compiler/dart2js/mini_parser_test.dart
@@ -10,7 +10,7 @@
void main() {
// Parse this script itself.
- tool.toolMain(<String>[ new Options().script ]);
+ tool.toolMain(<String>[ Platform.script ]);
}
/** This class is unused but used to test mini_parser.dart. */
diff --git a/tests/compiler/dart2js/mirror_tree_shaking_test.dart b/tests/compiler/dart2js/mirror_tree_shaking_test.dart
index 4869c70..6287c12 100644
--- a/tests/compiler/dart2js/mirror_tree_shaking_test.dart
+++ b/tests/compiler/dart2js/mirror_tree_shaking_test.dart
@@ -16,7 +16,7 @@
import 'dart:async';
main() {
- Uri script = currentDirectory.resolve(nativeToUriPath(new Options().script));
+ Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libraryRoot = script.resolve('../../../sdk/');
Uri packageRoot = script.resolve('./packages/');
@@ -45,6 +45,7 @@
Expect.isFalse(compiler.enqueuer.resolution.hasEnqueuedEverything);
Expect.isFalse(compiler.enqueuer.codegen.hasEnqueuedEverything);
Expect.isFalse(compiler.disableTypeInference);
+ Expect.isFalse(compiler.backend.hasRetainedMetadata);
}
const Map MEMORY_SOURCE_FILES = const {
diff --git a/tests/compiler/dart2js/mirrors_test.dart b/tests/compiler/dart2js/mirrors_test.dart
index 6fc2094..4090882 100644
--- a/tests/compiler/dart2js/mirrors_test.dart
+++ b/tests/compiler/dart2js/mirrors_test.dart
@@ -42,7 +42,7 @@
main() {
Uri scriptUri =
- currentDirectory.resolve(nativeToUriPath(new Options().script));
+ currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libUri = scriptUri.resolve('../../../sdk/');
Uri inputUri = scriptUri.resolve('mirrors_helper.dart');
var provider = new SourceFileProvider();
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 9fde6d6..1e9a796 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -73,7 +73,19 @@
createRuntimeType(a) {}
createInvocationMirror(a0, a1, a2, a3, a4, a5) {}
throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {}
- throwAbstractClassInstantiationError(className) {}''';
+ throwAbstractClassInstantiationError(className) {}
+ boolTypeCheck(value) {}
+ propertyTypeCheck(value, property) {}
+ interceptedTypeCheck(value, property) {}
+ functionSubtypeCast(Object object, String signatureName,
+ String contextName, var context) {}
+ checkFunctionSubtype(var target, String signatureName,
+ String contextName, var context,
+ var typeArguments) {}
+ computeSignature(var signature, var context, var contextName) {}
+ defineNativeMethodsFinish() {}
+ getRuntimeTypeArguments(target, substitutionName) {}
+ voidTypeCheck(value) {}''';
const String FOREIGN_LIBRARY = r'''
dynamic JS(String typeDescription, String codeTemplate,
@@ -92,7 +104,7 @@
abstract class JSMutableIndexable extends JSIndexable {}
class JSArray extends Interceptor implements List, JSIndexable {
var length;
- operator[](index) {}
+ operator[](index) => this[index];
operator[]=(index, value) {}
var add;
}
@@ -168,7 +180,10 @@
abstract class StackTrace {}
class Type {}
class Function {}
- class List<E> { List([length]); }
+ class List<E> {
+ List([length]);
+ List.filled(length, element);
+ }
abstract class Map<K,V> {}
class DateTime {
DateTime(year);
diff --git a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
index eccf849..267f5fe 100644
--- a/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_and_or_test.dart
@@ -63,7 +63,7 @@
checkReturn(String name, type) {
var element = findElement(compiler, name);
Expect.equals(type,
- typesInferrer.internal.returnTypeOf[element].simplify(compiler));
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
}
var subclassOfInterceptor =
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index 23d6db0..0f10a24 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -87,7 +87,7 @@
checkReturn(String name, type) {
var element = findElement(compiler, name);
- Expect.equals(type, typesInferrer.internal.returnTypeOf[element]);
+ Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
}
checkReturn('returnInt1', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index e03c4f3..5904dee 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -32,7 +32,7 @@
checkFieldTypeInClass(String className, String fieldName, type) {
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(buildSourceString(fieldName));
- Expect.equals(type, typesInferrer.internal.typeOf[element]);
+ Expect.equals(type, typesInferrer.getTypeOfElement(element));
}
checkFieldTypeInClass('A', 'intField', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
index 058187b..a4a4e1f 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field3_test.dart
@@ -32,7 +32,7 @@
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(buildSourceString(fieldName));
Expect.equals(type,
- typesInferrer.internal.typeOf[element].simplify(compiler));
+ typesInferrer.getTypeOfElement(element).simplify(compiler));
}
checkFieldTypeInClass('A', 'dynamicField',
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 3108608..8cea159 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -35,7 +35,7 @@
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(buildSourceString(fieldName));
Expect.equals(type,
- typesInferrer.internal.typeOf[element].simplify(compiler));
+ typesInferrer.getTypeOfElement(element).simplify(compiler));
}
checkFieldTypeInClass('A', 'intField', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
index 400c0f8..f4589cd 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -103,12 +103,12 @@
var element = findElement(compiler, name);
Expect.equals(
type,
- typesInferrer.internal.returnTypeOf[element].simplify(compiler),
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
name);
}
checkReturn('test1', typesInferrer.intType);
- checkReturn('test2', typesInferrer.dynamicType);
+ checkReturn('test2', typesInferrer.dynamicType.nonNullable());
checkReturn('test3', typesInferrer.intType);
checkReturn('test4', typesInferrer.mapType);
checkReturn('test5', typesInferrer.dynamicType.nonNullable());
@@ -118,17 +118,13 @@
compiler.runCompiler(uri);
typesInferrer = compiler.typesTask.typesInferrer;
- checkReturn('test1', typesInferrer.dynamicType);
+ checkReturn('test1', typesInferrer.dynamicType.nonNullable());
checkReturn('test2', typesInferrer.mapType);
checkReturn('test3', typesInferrer.mapType);
checkReturn('test4', typesInferrer.mapType);
checkReturn('test5', typesInferrer.mapType);
- // TODO(ngeoffray): The reason for nullablity is because the
- // inferrer thinks Object.noSuchMethod return null. Once we track
- // aborting control flow in the analysis, we won't get the nullable
- // anymore.
- checkReturn('test6', typesInferrer.numType.nullable());
+ checkReturn('test6', typesInferrer.numType);
checkReturn('test7', typesInferrer.intType);
checkReturn('test8', typesInferrer.intType);
checkReturn('test9', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
index cfae3a7..c5fbce1 100644
--- a/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_postfix_prefix_test.dart
@@ -70,7 +70,7 @@
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(buildSourceString(methodName));
Expect.equals(type,
- typesInferrer.internal.returnTypeOf[element].simplify(compiler));
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
}
var subclassOfInterceptor =
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index cfd0ba8..b5b9d9b 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -351,8 +351,23 @@
return b;
}
+testReturnElementOfConstList1() {
+ return const [42][0];
+}
+
+testReturnElementOfConstList2() {
+ return topLevelConstList[0];
+}
+
+testReturnItselfOrInt(a) {
+ if (a) return 42;
+ return testReturnItselfOrInt(a);
+}
+
testReturnInvokeDynamicGetter() => new A().myFactory();
+var topLevelConstList = const [42];
+
get topLevelGetter => 42;
returnDynamic() => topLevelGetter(42);
returnTopLevelGetter() => topLevelGetter;
@@ -459,6 +474,9 @@
..returnInt7()
..returnInt8()
..returnInt9();
+ testReturnElementOfConstList1();
+ testReturnElementOfConstList2();
+ testReturnItselfOrInt(topLevelGetter());
testReturnInvokeDynamicGetter();
}
""";
@@ -473,7 +491,7 @@
var element = findElement(compiler, name);
Expect.equals(
type,
- typesInferrer.internal.returnTypeOf[element].simplify(compiler),
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
name);
}
var interceptorType =
@@ -532,13 +550,16 @@
checkReturn('testBreak1', interceptorType.nullable());
checkReturn('testContinue2', interceptorType.nullable());
checkReturn('testBreak2', typesInferrer.intType.nullable());
+ checkReturn('testReturnElementOfConstList1', typesInferrer.intType);
+ checkReturn('testReturnElementOfConstList2', typesInferrer.intType);
+ checkReturn('testReturnItselfOrInt', typesInferrer.intType);
checkReturn('testReturnInvokeDynamicGetter', typesInferrer.dynamicType);
checkReturnInClass(String className, String methodName, type) {
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(buildSourceString(methodName));
Expect.equals(type,
- typesInferrer.internal.returnTypeOf[element].simplify(compiler));
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
}
checkReturnInClass('A', 'returnInt1', typesInferrer.intType);
@@ -563,7 +584,7 @@
var cls = findElement(compiler, className);
var element = cls.localLookup(buildSourceString(className));
Expect.equals(new TypeMask.nonNullExact(cls.rawType),
- typesInferrer.internal.returnTypeOf[element]);
+ typesInferrer.getReturnTypeOfElement(element));
}
checkFactoryConstructor('A');
}
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index 917ffe9..18eddc7 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -162,7 +162,7 @@
checkReturn(String name, type) {
var element = findElement(compiler, name);
Expect.equals(type,
- typesInferrer.internal.returnTypeOf[element].simplify(compiler));
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
}
checkReturn('returnInt1', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index 0341df4..020f4c6 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -38,7 +38,7 @@
checkReturnInClass(String className, String methodName, type) {
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(buildSourceString(methodName));
- Expect.equals(type, typesInferrer.internal.returnTypeOf[element]);
+ Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
}
checkReturnInClass('A', '+', typesInferrer.intType);
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart
index b4efe86..35a4651 100644
--- a/tests/compiler/dart2js/subtype_test.dart
+++ b/tests/compiler/dart2js/subtype_test.dart
@@ -264,6 +264,7 @@
testFunctionSubtyping() {
var env = new TypeEnvironment(r"""
+ _() => null;
void void_() {}
void void_2() {}
int int_() => 0;
@@ -285,6 +286,7 @@
testTypedefSubtyping() {
var env = new TypeEnvironment(r"""
+ typedef _();
typedef void void_();
typedef void void_2();
typedef int int_();
@@ -317,6 +319,13 @@
// Function <: () -> int
expect(false, 'Function', 'int_');
+ // () -> dynamic <: () -> dynamic
+ expect(true, '_', '_');
+ // () -> dynamic <: () -> void
+ expect(true, '_', 'void_');
+ // () -> void <: () -> dynamic
+ expect(true, 'void_', '_');
+
// () -> int <: () -> void
expect(true, 'int_', 'void_');
// () -> void <: () -> int
diff --git a/tests/compiler/dart2js/type_checker_test.dart b/tests/compiler/dart2js/type_checker_test.dart
index 08a8630..c10aa77 100644
--- a/tests/compiler/dart2js/type_checker_test.dart
+++ b/tests/compiler/dart2js/type_checker_test.dart
@@ -46,7 +46,8 @@
testThis,
testSuper,
testOperatorsAssignability,
- testFieldInitializers];
+ testFieldInitializers,
+ testTypeVariableExpressions];
for (Function test in tests) {
setup();
test();
@@ -1025,6 +1026,25 @@
}""", MessageKind.NOT_ASSIGNABLE);
}
+void testTypeVariableExpressions() {
+ String script = """class Foo<T> {
+ void method() {}
+ }""";
+ LibraryElement library = mockLibrary(compiler, script);
+ compiler.parseScript(script, library);
+ ClassElement foo = library.find(const SourceString("Foo"));
+ foo.ensureResolved(compiler);
+ Element method = foo.lookupLocalMember(const SourceString('method'));
+
+ analyzeIn(method, "{ Type type = T; }");
+ analyzeIn(method, "{ T type = T; }", MessageKind.NOT_ASSIGNABLE);
+ analyzeIn(method, "{ int type = T; }", MessageKind.NOT_ASSIGNABLE);
+
+ analyzeIn(method, "{ String typeName = T.toString(); }");
+ analyzeIn(method, "{ T.foo; }", MessageKind.PROPERTY_NOT_FOUND);
+ analyzeIn(method, "{ T.foo(); }", MessageKind.METHOD_NOT_FOUND);
+ analyzeIn(method, "{ T + 1; }", MessageKind.OPERATOR_NOT_FOUND);
+}
const CLASS_WITH_METHODS = '''
class ClassWithMethods {
diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart
index 132d3a7..1c946ee 100644
--- a/tests/compiler/dart2js/type_representation_test.dart
+++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -10,7 +10,7 @@
import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'
show Element, ClassElement;
import '../../../sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart'
- show TypeRepresentationGenerator;
+ show JavaScriptBackend, TypeRepresentationGenerator;
void main() {
testTypeRepresentations();
@@ -42,6 +42,14 @@
Expect.stringEquals(expectedRepresentation, foundRepresentation);
}
+ JavaScriptBackend backend = env.compiler.backend;
+ String func = backend.namer.functionTypeTag();
+ String retvoid = backend.namer.functionTypeVoidReturnTag();
+ String ret = backend.namer.functionTypeReturnTypeTag();
+ String args = backend.namer.functionTypeRequiredParametersTag();
+ String opt = backend.namer.functionTypeOptionalParametersTag();
+ String named = backend.namer.functionTypeNamedParametersTag();
+
ClassElement List_ = env.getElement('List');
TypeVariableType List_E = List_.typeVariables.head;
ClassElement Map_ = env.getElement('Map');
@@ -77,7 +85,7 @@
// List<int>
expect('[$List_rep, $int_rep]', instantiate(List_, [int_]));
// List<Typedef>
- expect('[$List_rep, {func: true, retvoid: true}]',
+ expect('[$List_rep, {$func: "void_", $retvoid: true}]',
instantiate(List_, [Typedef_]));
// Map<K,V>
@@ -91,46 +99,51 @@
instantiate(Map_, [int_, String_]));
// void m1() {}
- expect("{func: true, retvoid: true}",
+ expect('{$func: "void_", $retvoid: true}',
env.getElement('m1').computeType(env.compiler));
// int m2() => 0;
- expect("{func: true, ret: $int_rep}",
+ expect('{$func: "int_", $ret: $int_rep}',
env.getElement('m2').computeType(env.compiler));
// List<int> m3() => null;
- expect("{func: true, ret: [$List_rep, $int_rep]}",
+ expect('{$func: "List_", $ret: [$List_rep, $int_rep]}',
env.getElement('m3').computeType(env.compiler));
// m4() {}
- expect("{func: true}",
+ expect('{$func: "dynamic_"}',
env.getElement('m4').computeType(env.compiler));
// m5(int a, String b) {}
- expect("{func: true, args: [$int_rep, $String_rep]}",
+ expect('{$func: "dynamic__int_String", $args: [$int_rep, $String_rep]}',
env.getElement('m5').computeType(env.compiler));
// m6(int a, [String b]) {}
- expect("{func: true, args: [$int_rep], opt: [$String_rep]}",
+ expect('{$func: "dynamic__int__String", $args: [$int_rep],'
+ ' $opt: [$String_rep]}',
env.getElement('m6').computeType(env.compiler));
// m7(int a, String b, [List<int> c, d]) {}
- expect("{func: true, args: [$int_rep, $String_rep],"
- " opt: [[$List_rep, $int_rep], null]}",
+ expect('{$func: "dynamic__int_String__List_dynamic",'
+ ' $args: [$int_rep, $String_rep],'
+ ' $opt: [[$List_rep, $int_rep], null]}',
env.getElement('m7').computeType(env.compiler));
// m8(int a, {String b}) {}
- expect("{func: true, args: [$int_rep], named: {b: $String_rep}}",
+ expect('{$func: "dynamic__int__String0",'
+ ' $args: [$int_rep], $named: {b: $String_rep}}',
env.getElement('m8').computeType(env.compiler));
// m9(int a, String b, {List<int> c, d}) {}
- expect("{func: true, args: [$int_rep, $String_rep],"
- " named: {c: [$List_rep, $int_rep], d: null}}",
+ expect('{$func: "dynamic__int_String__List_dynamic0",'
+ ' $args: [$int_rep, $String_rep],'
+ ' $named: {c: [$List_rep, $int_rep], d: null}}',
env.getElement('m9').computeType(env.compiler));
// m10(void f(int a, [b])) {}
- expect("{func: true, args:"
- " [{func: true, retvoid: true, args: [$int_rep], opt: [null]}]}",
+ expect('{$func: "dynamic__void__int__dynamic", $args:'
+ ' [{$func: "void__int__dynamic",'
+ ' $retvoid: true, $args: [$int_rep], $opt: [null]}]}',
env.getElement('m10').computeType(env.compiler));
}
diff --git a/tests/compiler/dart2js/unneeded_part_js_test.dart b/tests/compiler/dart2js/unneeded_part_js_test.dart
index aa1e641..cebcd91 100644
--- a/tests/compiler/dart2js/unneeded_part_js_test.dart
+++ b/tests/compiler/dart2js/unneeded_part_js_test.dart
@@ -16,7 +16,7 @@
import 'dart:async';
main() {
- Uri script = currentDirectory.resolve(nativeToUriPath(new Options().script));
+ Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
Uri libraryRoot = script.resolve('../../../sdk/');
Uri packageRoot = script.resolve('./packages/');
diff --git a/tests/compiler/dart2js_foreign/dart2js_foreign.status b/tests/compiler/dart2js_foreign/dart2js_foreign.status
index d383e88..d5919cc 100644
--- a/tests/compiler/dart2js_foreign/dart2js_foreign.status
+++ b/tests/compiler/dart2js_foreign/dart2js_foreign.status
@@ -55,6 +55,12 @@
native_window1_test: Pass # For the wrong reason.
native_window2_test: Pass # For the wrong reason.
+native_checked_fields_test: Fail # TODO(ahe): Convert to metadata syntax.
+native_class_inheritance4_test: Fail # TODO(ahe): Convert to metadata syntax.
+native_class_with_dart_methods_test: Fail # TODO(ahe): Convert to metadata syntax.
+native_missing_method1_test: Fail # TODO(ahe): Convert to metadata syntax.
+native_missing_method2_test: Fail # TODO(ahe): Convert to metadata syntax.
+native_to_string_test: Fail # TODO(ahe): Convert to metadata syntax.
[ $compiler == dartc || $browser ]
*: Skip
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 6bd2384..9c67dd2 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -111,4 +111,11 @@
*: Skip
[ $arch == simmips ]
-*: Skip
+int_parse_radix_test: Skip # Timeout
+
+[ $arch == simmips && $checked ]
+hash_map2_test: Crash # Too far PC relative branch.
+collection_length_test: Skip # Timeout.
+
+[ $arch == simmips && $mode == debug ]
+collection_to_string_test: Pass, Crash # Issue: 11207
diff --git a/tests/corelib/duration_big_num_test.dart b/tests/corelib/duration_big_num_test.dart
new file mode 100644
index 0000000..789982d
--- /dev/null
+++ b/tests/corelib/duration_big_num_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ Duration d, d1;
+
+ d1 = new Duration(microseconds: pow(2, 53));
+ d = d1 * 2;
+ Expect.equals(pow(2, 54), d.inMicroseconds);
+ d = d1 * 1.5;
+ Expect.equals(pow(2, 53).toDouble() * 1.5, d.inMicroseconds);
+ Expect.isTrue(d.inMicroseconds is int);
+
+ // Test that we lose precision when multiplying with a double.
+ d = new Duration(microseconds: pow(2, 53) + 1) * 1.0;
+ Expect.equals(0, d.inMicroseconds % 2);
+}
+
diff --git a/tests/corelib/duration_double_multiplication_test.dart b/tests/corelib/duration_double_multiplication_test.dart
new file mode 100644
index 0000000..74ce559
--- /dev/null
+++ b/tests/corelib/duration_double_multiplication_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+main() {
+ Duration d, d1;
+
+ d1 = new Duration(milliseconds: 1);
+ d = d1 * 0.005;
+ Expect.equals(1000 * 0.005, d.inMicroseconds);
+ d = d1 * 0.0;
+ Expect.equals(0, d.inMicroseconds);
+ d = d1 * -0.005;
+ Expect.equals(1000 * -0.005, d.inMicroseconds);
+ d = d1 * 0.0015;
+ Expect.equals((1000 * 0.0015).round(), d.inMicroseconds);
+
+}
diff --git a/tests/corelib/iterable_contains2_test.dart b/tests/corelib/iterable_contains2_test.dart
new file mode 100644
index 0000000..889ad2d
--- /dev/null
+++ b/tests/corelib/iterable_contains2_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+// Tests for the contains methods on lists.
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var list = <B>[ new B() ];
+ var set = new Set<B>();
+ set.add(new B());
+ var iterable1 = list.map((x) => x);
+ var iterable2 = list.take(1);
+ var list2 = const <B>[ const B() ];
+ var iterable3 = list2.map((x) => x);
+ var iterable4 = list2.take(1);
+ var iterables =
+ [ list, set, iterable1, iterable2, list2, iterable3, iterable4 ];
+ for (var iterable in iterables) {
+ Expect.isFalse(iterable.contains(new A()));
+ }
+}
diff --git a/tests/corelib/iterable_skip_test.dart b/tests/corelib/iterable_skip_test.dart
index 2910d3b..59d604d 100644
--- a/tests/corelib/iterable_skip_test.dart
+++ b/tests/corelib/iterable_skip_test.dart
@@ -254,5 +254,6 @@
testSkipTake(collection, 15, 5);
testSkipTake(collection, 20, 0);
testSkipTake(collection, 20, 5);
+ Expect.throws(() => longList.skip(-1), (e) => e is RangeError);
}
}
diff --git a/tests/corelib/iterable_take_test.dart b/tests/corelib/iterable_take_test.dart
index eda953a..fdedb93 100644
--- a/tests/corelib/iterable_take_test.dart
+++ b/tests/corelib/iterable_take_test.dart
@@ -215,4 +215,15 @@
Expect.isNull(it.current);
Expect.isFalse(it.moveNext());
Expect.isNull(it.current);
+
+ Expect.throws(() => list1.skip(-1), (e) => e is RangeError);
+ Expect.throws(() => list2.skip(-1), (e) => e is RangeError);
+ Expect.throws(() => list3.skip(-1), (e) => e is RangeError);
+ Expect.throws(() => set1.skip(-1), (e) => e is RangeError);
+ Expect.throws(() => set2.skip(-1), (e) => e is RangeError);
+ Expect.throws(() => list1.map((x) => x).skip(-1), (e) => e is RangeError);
+ Expect.throws(() => list2.map((x) => x).skip(-1), (e) => e is RangeError);
+ Expect.throws(() => list3.map((x) => x).skip(-1), (e) => e is RangeError);
+ Expect.throws(() => set1.map((x) => x).skip(-1), (e) => e is RangeError);
+ Expect.throws(() => set2.map((x) => x).skip(-1), (e) => e is RangeError);
}
diff --git a/tests/corelib/list_filled_type_argument_test.dart b/tests/corelib/list_filled_type_argument_test.dart
new file mode 100644
index 0000000..6d361cc
--- /dev/null
+++ b/tests/corelib/list_filled_type_argument_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+main() {
+ var a = new List<int>.filled(42, 42);
+ Expect.isTrue(a is List<int>);
+ Expect.isFalse(a is List<String>);
+}
diff --git a/tests/corelib/list_index_of2_test.dart b/tests/corelib/list_index_of2_test.dart
new file mode 100644
index 0000000..56aec92
--- /dev/null
+++ b/tests/corelib/list_index_of2_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+void test(List<B> list) {
+ // Test that the list accepts a different type for indexOf.
+ // List<B>.indexOf(A)
+ Expect.equals(-1, list.indexOf(const A()));
+ Expect.equals(-1, list.lastIndexOf(const A()));
+}
+
+main() {
+ var list = new List<B>(1);
+ list[0] = const B();
+ test(list);
+ var list2 = new List<B>();
+ list2.add(const B());
+ test(list2);
+ test(<B>[const B()]);
+ test(const <B>[]);
+ test(<B>[const B()].toList());
+}
diff --git a/tests/corelib/list_index_of_test.dart b/tests/corelib/list_index_of_test.dart
index 4641adc..ebb2731 100644
--- a/tests/corelib/list_index_of_test.dart
+++ b/tests/corelib/list_index_of_test.dart
@@ -4,38 +4,32 @@
import "package:expect/expect.dart";
-class ListIndexOfTest {
- static testMain() {
- test(new List<int>(5));
- var l = new List<int>();
- l.length = 5;
- test(l);
- }
-
- static void test(List<int> list) {
- list[0] = 1;
- list[1] = 2;
- list[2] = 3;
- list[3] = 4;
- list[4] = 1;
-
- Expect.equals(3, list.indexOf(4, 0));
- Expect.equals(0, list.indexOf(1, 0));
- Expect.equals(4, list.lastIndexOf(1, list.length - 1));
-
- Expect.equals(4, list.indexOf(1, 1));
- Expect.equals(-1, list.lastIndexOf(4, 2));
-
- Expect.equals(3, list.indexOf(4, 2));
- Expect.equals(3, list.indexOf(4, -5));
- Expect.equals(-1, list.indexOf(4, 50));
-
- Expect.equals(-1, list.lastIndexOf(4, 2));
- Expect.equals(-1, list.lastIndexOf(4, -5));
- Expect.equals(3, list.lastIndexOf(4, 50));
- }
+main() {
+ test(new List<int>(5));
+ var l = new List<int>();
+ l.length = 5;
+ test(l);
}
-main() {
- ListIndexOfTest.testMain();
+void test(List<int> list) {
+ list[0] = 1;
+ list[1] = 2;
+ list[2] = 3;
+ list[3] = 4;
+ list[4] = 1;
+
+ Expect.equals(3, list.indexOf(4, 0));
+ Expect.equals(0, list.indexOf(1, 0));
+ Expect.equals(4, list.lastIndexOf(1, list.length - 1));
+
+ Expect.equals(4, list.indexOf(1, 1));
+ Expect.equals(-1, list.lastIndexOf(4, 2));
+
+ Expect.equals(3, list.indexOf(4, 2));
+ Expect.equals(3, list.indexOf(4, -5));
+ Expect.equals(-1, list.indexOf(4, 50));
+
+ Expect.equals(-1, list.lastIndexOf(4, 2));
+ Expect.equals(-1, list.lastIndexOf(4, -5));
+ Expect.equals(3, list.lastIndexOf(4, 50));
}
diff --git a/tests/corelib/map_contains_key_test.dart b/tests/corelib/map_contains_key_test.dart
new file mode 100644
index 0000000..32fd3db
--- /dev/null
+++ b/tests/corelib/map_contains_key_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var map1 = new Map<B, B>();
+ map1[const B()] = const B();
+ var map2 = new Map<B, B>();
+ var list = <B>[ const B() ];
+
+ var maps = [map1, map2];
+ for (var map in maps) {
+ // Test that the map accepts a key is not of the same type:
+ // Map<B, ?>.containsValue(A)
+ Expect.isFalse(map.containsKey(new A()));
+ }
+}
diff --git a/tests/corelib/map_contains_value_test.dart b/tests/corelib/map_contains_value_test.dart
new file mode 100644
index 0000000..84f02ae
--- /dev/null
+++ b/tests/corelib/map_contains_value_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var map1 = new Map<B, B>();
+ map1[const B()] = const B();
+ var map2 = new Map<B, B>();
+ var list = <B>[ const B() ];
+ Map<int, B> map3 = list.asMap();
+
+ var maps = [map1, map2, map3];
+ for (var map in maps) {
+ // Test that the map accepts a value is not of the same type:
+ // Map<?, B>.containsValue(A)
+ Expect.isFalse(map.containsValue(new A()));
+ }
+}
diff --git a/tests/corelib/map_index_test.dart b/tests/corelib/map_index_test.dart
new file mode 100644
index 0000000..5a0fc9a
--- /dev/null
+++ b/tests/corelib/map_index_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var map1 = new Map<B, B>();
+ map1[const B()] = const B();
+ var map2 = new Map<B, B>();
+ var list = <B>[ const B() ];
+
+ var maps = [map1, map2];
+ for (var map in maps) {
+ // Test that the map accepts a key is not of the same type:
+ // Map<B, ?>[A]
+ Expect.isNull(map[new A()]);
+ }
+}
diff --git a/tests/corelib/map_remove_test.dart b/tests/corelib/map_remove_test.dart
new file mode 100644
index 0000000..eecebf7
--- /dev/null
+++ b/tests/corelib/map_remove_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var map1 = new Map<B, B>();
+ map1[const B()] = const B();
+ var map2 = new Map<B, B>();
+ var list = <B>[ const B() ];
+
+ var maps = [map1, map2];
+ for (var map in maps) {
+ // Test that the map accepts a key is not of the same type:
+ // Map<B, ?>.remove(A)
+ Expect.isNull(map.remove(new A()));
+ }
+}
diff --git a/tests/corelib/set_containsAll_test.dart b/tests/corelib/set_containsAll_test.dart
new file mode 100644
index 0000000..9f6bae8d
--- /dev/null
+++ b/tests/corelib/set_containsAll_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var set1 = new Set<B>();
+ set1.add(const B());
+ var set2 = new Set<B>();
+ var list = <B>[ const B() ];
+ var set3 = list.toSet();
+
+ var sets = [set1, set2, set3];
+ for (var setToTest in sets) {
+ Expect.isFalse(setToTest.containsAll(<A>[new A()]));
+ }
+}
diff --git a/tests/corelib/set_contains_test.dart b/tests/corelib/set_contains_test.dart
new file mode 100644
index 0000000..07670a3
--- /dev/null
+++ b/tests/corelib/set_contains_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var set1 = new Set<B>();
+ set1.add(const B());
+ var set2 = new Set<B>();
+ var list = <B>[ const B() ];
+ var set3 = list.toSet();
+
+ var sets = [set1, set2, set3];
+ for (var setToTest in sets) {
+ // Test that the set accepts a value that is not of the same type
+ // Set<B>.contains(A)
+ Expect.isFalse(setToTest.contains(new A()));
+ }
+}
diff --git a/tests/corelib/set_intersection_test.dart b/tests/corelib/set_intersection_test.dart
new file mode 100644
index 0000000..bdfdda6
--- /dev/null
+++ b/tests/corelib/set_intersection_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var set1 = new Set<B>();
+ set1.add(const B());
+ var set2 = new Set<B>();
+ var list = <B>[ const B() ];
+ var set3 = list.toSet();
+
+ var setOther = new Set<A>();
+ setOther.add(new A());
+ var sets = [set1, set2, set3];
+ for (var setToTest in sets) {
+ // Test that the set accepts another set that is not of the same type:
+ // Set<B>.intersection(Set<A>)
+ Set result = setToTest.intersection(setOther);
+ Expect.isTrue(result.isEmpty);
+ }
+}
diff --git a/tests/corelib/set_removeAll_test.dart b/tests/corelib/set_removeAll_test.dart
new file mode 100644
index 0000000..abd4a2d
--- /dev/null
+++ b/tests/corelib/set_removeAll_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var set1 = new Set<B>();
+ set1.add(const B());
+ var set2 = new Set<B>();
+ var list = <B>[ const B() ];
+ var set3 = list.toSet();
+
+ var sets = [set1, set2, set3];
+ for (var setToTest in sets) {
+ // Test that the set accepts a list that is not of the same type:
+ // Set<B>.removeAll(List<A>)
+ Expect.isNull(setToTest.removeAll(<A>[new A()]));
+ }
+}
diff --git a/tests/corelib/set_remove_test.dart b/tests/corelib/set_remove_test.dart
new file mode 100644
index 0000000..de99304
--- /dev/null
+++ b/tests/corelib/set_remove_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var set1 = new Set<B>();
+ set1.add(const B());
+ var set2 = new Set<B>();
+ var list = <B>[ const B() ];
+ var set3 = list.toSet();
+
+ var sets = [set1, set2, set3];
+ for (var setToTest in sets) {
+ // Test that the set accepts a value that is not of the same type
+ // Set<B>.remove(A)
+ Expect.isFalse(setToTest.remove(new A()));
+ }
+}
diff --git a/tests/corelib/set_retainAll_test.dart b/tests/corelib/set_retainAll_test.dart
new file mode 100644
index 0000000..bd207f8
--- /dev/null
+++ b/tests/corelib/set_retainAll_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ var set1 = new Set<B>();
+ set1.add(const B());
+ var set2 = new Set<B>();
+ var list = <B>[ const B() ];
+ var set3 = list.toSet();
+
+ var sets = [set1, set2, set3];
+ for (var setToTest in sets) {
+ // Test that the set accepts a list that is not of the same type:
+ // Set<B>.retainAll(List<A>)
+ setToTest.retainAll(<A>[new A()]);
+ }
+}
diff --git a/tests/corelib/string_test.dart b/tests/corelib/string_test.dart
index 4519733..aeb00c3 100644
--- a/tests/corelib/string_test.dart
+++ b/tests/corelib/string_test.dart
@@ -127,6 +127,29 @@
Expect.isTrue("".startsWith(""));
Expect.isFalse("".startsWith("s"));
+ Expect.isFalse("strstr".startsWith("s", 1));
+ Expect.isFalse("strstr".startsWith("s", 2));
+ Expect.isTrue("strstr".startsWith("s", 3));
+ Expect.isFalse("strstr".startsWith("s", 4));
+
+ Expect.isFalse("strstr".startsWith("st", 1));
+ Expect.isFalse("strstr".startsWith("st", 2));
+ Expect.isTrue("strstr".startsWith("st", 3));
+ Expect.isFalse("strstr".startsWith("st", 4));
+
+ Expect.isFalse("strstr".startsWith("str", 1));
+ Expect.isFalse("strstr".startsWith("str", 2));
+ Expect.isTrue("strstr".startsWith("str", 3));
+ Expect.isFalse("strstr".startsWith("str", 4));
+
+ Expect.isTrue("str".startsWith("", 0));
+ Expect.isTrue("str".startsWith("", 1));
+ Expect.isTrue("str".startsWith("", 2));
+ Expect.isTrue("str".startsWith("", 3));
+
+ Expect.throws(() => "str".startsWith("", -1));
+ Expect.throws(() => "str".startsWith("", 4));
+
var regexp = new RegExp("s(?:tr?)?");
Expect.isTrue("s".startsWith(regexp));
Expect.isTrue("st".startsWith(regexp));
@@ -140,6 +163,30 @@
Expect.isTrue("".startsWith(new RegExp("")));
Expect.isTrue("".startsWith(new RegExp("a?")));
+
+ Expect.isFalse("strstr".startsWith(regexp, 1));
+ Expect.isFalse("strstr".startsWith(regexp, 2));
+ Expect.isTrue("strstr".startsWith(regexp, 3));
+ Expect.isFalse("strstr".startsWith(regexp, 4));
+
+ Expect.isTrue("str".startsWith(new RegExp(""), 0));
+ Expect.isTrue("str".startsWith(new RegExp(""), 1));
+ Expect.isTrue("str".startsWith(new RegExp(""), 2));
+ Expect.isTrue("str".startsWith(new RegExp(""), 3));
+ Expect.isTrue("str".startsWith(new RegExp("a?"), 0));
+ Expect.isTrue("str".startsWith(new RegExp("a?"), 1));
+ Expect.isTrue("str".startsWith(new RegExp("a?"), 2));
+ Expect.isTrue("str".startsWith(new RegExp("a?"), 3));
+
+ Expect.throws(() => "str".startsWith(regexp, -1));
+ Expect.throws(() => "str".startsWith(regexp, 4));
+
+ regexp = new RegExp("^str");
+ Expect.isTrue("strstr".startsWith(regexp));
+ Expect.isTrue("strstr".startsWith(regexp, 0));
+ Expect.isFalse("strstr".startsWith(regexp, 1));
+ Expect.isFalse("strstr".startsWith(regexp, 2));
+ Expect.isFalse("strstr".startsWith(regexp, 3)); // Second "str" isn't at ^.
}
static testIndexOf() {
diff --git a/tests/html/custom_element_bindings_test.dart b/tests/html/custom_element_bindings_test.dart
index 3b9d6a9..6548a7f 100644
--- a/tests/html/custom_element_bindings_test.dart
+++ b/tests/html/custom_element_bindings_test.dart
@@ -261,9 +261,9 @@
AttributeMapWrapper(this._map);
- bool containsValue(V value) => _map.containsValue(value);
- bool containsKey(K key) => _map.containsKey(key);
- V operator [](K key) => _map[key];
+ bool containsValue(Object value) => _map.containsValue(value);
+ bool containsKey(Object key) => _map.containsKey(key);
+ V operator [](Object key) => _map[key];
void operator []=(K key, V value) {
log.add(['[]=', key, value]);
@@ -272,7 +272,7 @@
V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent);
- V remove(K key) {
+ V remove(Object key) {
log.add(['remove', key]);
_map.remove(key);
}
diff --git a/tests/html/document_test.dart b/tests/html/document_test.dart
index fece53e..ca04a0f 100644
--- a/tests/html/document_test.dart
+++ b/tests/html/document_test.dart
@@ -61,5 +61,24 @@
expect(new Element.tag('a'), isAnchorElement);
expect(new Element.tag('bad_name'), isUnknownElement);
});
+
+ test('adoptNode', () {
+ var div = new Element.html('<div><div id="foo">bar</div></div>');
+ var doc = document.implementation.createHtmlDocument('');
+ expect(doc.adoptNode(div), div);
+ expect(div.document, doc);
+ doc.body.nodes.add(div);
+ expect(doc.query('#foo').text, 'bar');
+ });
+
+ test('importNode', () {
+ var div = new Element.html('<div><div id="foo">bar</div></div>');
+ var doc = document.implementation.createHtmlDocument('');
+ var div2 = doc.importNode(div, true);
+ expect(div2, isNot(equals(div)));
+ expect(div2.document, doc);
+ doc.body.nodes.add(div2);
+ expect(doc.query('#foo').text, 'bar');
+ });
});
}
diff --git a/tests/html/html.status b/tests/html/html.status
index 545b4c4..9aa3976 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -16,6 +16,9 @@
[ $compiler == none && $runtime == drt && $system == windows ]
worker_test/functional: Pass, Crash # Issue 9929.
+[ $compiler == dart2js && $checked ]
+template_element_test: Fail # BUG(11480): Triage.
+
[ $compiler == dart2js && ($runtime == ie9 || $runtime == ie10 || $runtime == safari || $runtime == ff || $runtime == chrome || $runtime == chromeOnAndroid || $runtime == opera || $runtime == drt || $runtime == dartium)]
dom_isolates_test: Skip # Need to migrate to new spawnDomFunction.
@@ -137,6 +140,7 @@
window_open_test: Skip # BUG(4016)
canvasrenderingcontext2d_test/drawImage_video_element: Fail # IE does not support drawImage w/ video element
canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # IE does not support drawImage w/ video element
+canvasrenderingcontext2d_test/drawImage_image_element: Pass, Fail # Issue: 11416
input_element_test/attributes: Fail # IE returns null while others ''
# IE9 Feature support statuses-
@@ -366,9 +370,3 @@
postmessage_structured_test: Skip # Test cannot run under CSP restrictions (times out).
safe_dom_test: Skip # Test cannot run under CSP restrictions (times out).
shadow_dom_layout_test: Fail, OK # Test cannot run under CSP restrictions.
-
-[ $compiler == dartanalyzer ]
-path_observer_test: Fail
-
-[ $compiler == dart2analyzer ]
-path_observer_test: Fail
diff --git a/tests/html/indexeddb_2_test.dart b/tests/html/indexeddb_2_test.dart
index 03a0fd4..d197585 100644
--- a/tests/html/indexeddb_2_test.dart
+++ b/tests/html/indexeddb_2_test.dart
@@ -23,22 +23,22 @@
var db;
// Delete any existing DBs.
- return html.window.indexedDB.deleteDatabase(dbName).then((_) {
+ return html.window.indexedDB.deleteDatabase(dbName).then(expectAsync1((_) {
return html.window.indexedDB.open(dbName, version: version,
onUpgradeNeeded: createObjectStore);
- }).then((result) {
+ })).then(expectAsync1((result) {
db = result;
var transaction = db.transaction([storeName], 'readwrite');
transaction.objectStore(storeName).put(value, key);
return transaction.completed;
- }).then((db) {
+ })).then(expectAsync1((db) {
var transaction = db.transaction(storeName, 'readonly');
return transaction.objectStore(storeName).getObject(key);
- }).then((object) {
+ })).then(expectAsync1((object) {
db.close();
check(value, object);
- }).catchError((e) {
+ })).catchError((e) {
if (db != null) {
db.close();
}
diff --git a/tests/isolate/global_error_handler2_test.dart b/tests/isolate/global_error_handler2_test.dart
index c0b1241..d038f88 100644
--- a/tests/isolate/global_error_handler2_test.dart
+++ b/tests/isolate/global_error_handler2_test.dart
@@ -7,6 +7,7 @@
import 'package:expect/expect.dart';
import 'dart:async';
import 'dart:isolate';
+import '../async_helper.dart';
runTest() {
SendPort mainIsolate;
@@ -34,9 +35,11 @@
SendPort otherIsolate = spawnFunction(runTest, globalErrorHandler);
otherIsolate.send(port.toSendPort());
otherIsolate.send("message 2");
+ asyncStart();
port.receive((msg, replyPort) {
Expect.equals("received", msg);
port.close();
timer.cancel();
+ asyncEnd();
});
}
diff --git a/tests/isolate/global_error_handler_stream2_test.dart b/tests/isolate/global_error_handler_stream2_test.dart
index b1093f5..8590046 100644
--- a/tests/isolate/global_error_handler_stream2_test.dart
+++ b/tests/isolate/global_error_handler_stream2_test.dart
@@ -7,6 +7,7 @@
import 'package:expect/expect.dart';
import 'dart:async';
import 'dart:isolate';
+import '../async_helper.dart';
runTest() {
IsolateSink mainIsolate;
@@ -37,10 +38,16 @@
// the handling of the previous event. We therefore delay the closing.
// Note: if the done is sent too early it won't lead to failing tests, but
// just won't make sure that the globalErrorHandler works.
- new Timer(const Duration(milliseconds: 10), otherIsolate.close);
+ asyncStart();
+ new Timer(const Duration(milliseconds: 10), () {
+ otherIsolate.close();
+ asyncEnd();
+ });
+ asyncStart();
box.stream.single.then((msg) {
Expect.equals("received done", msg);
timer.cancel();
keepRunningBox.stream.close();
+ asyncEnd();
});
}
diff --git a/tests/isolate/illegal_msg_stream_test.dart b/tests/isolate/illegal_msg_stream_test.dart
index bcc9135..2271ed5 100644
--- a/tests/isolate/illegal_msg_stream_test.dart
+++ b/tests/isolate/illegal_msg_stream_test.dart
@@ -6,6 +6,7 @@
import 'package:expect/expect.dart';
import 'dart:isolate';
+import '../async_helper.dart';
funcFoo(x) => x + 2;
@@ -29,7 +30,9 @@
snd.add(box.sink);
snd.close();
+ asyncStart();
box.stream.single.then((msg) {
Expect.equals(499, msg);
+ asyncEnd();
});
}
diff --git a/tests/isolate/illegal_msg_test.dart b/tests/isolate/illegal_msg_test.dart
index 434edc3..aa17b46 100644
--- a/tests/isolate/illegal_msg_test.dart
+++ b/tests/isolate/illegal_msg_test.dart
@@ -5,6 +5,7 @@
library illegal_msg_tests;
import "package:expect/expect.dart";
import 'dart:isolate';
+import '../async_helper.dart';
funcFoo(x) => x + 2;
@@ -26,8 +27,10 @@
if (caught_exception) {
port.close();
} else {
+ asyncStart();
port.receive((msg, reply) {
print("from worker ${msg}");
+ asyncEnd();
});
}
Expect.isTrue(caught_exception);
diff --git a/tests/isolate/isolate2_negative_test.dart b/tests/isolate/isolate2_negative_test.dart
index 720b825..01cf0ed 100644
--- a/tests/isolate/isolate2_negative_test.dart
+++ b/tests/isolate/isolate2_negative_test.dart
@@ -7,11 +7,16 @@
library isolate2_negative_test;
import 'dart:isolate';
+import '../async_helper.dart';
void entry() {
throw "foo";
}
main() {
+ // We start an asynchronous operation, but since we don't expect to get
+ // anything back except an exception there is no asyncEnd().
+ // If the exception is not thrown this test will timeout.
+ asyncStart();
SendPort port = spawnFunction(entry);
}
diff --git a/tests/language/disable_privacy_lib.dart b/tests/language/disable_privacy_lib.dart
deleted file mode 100644
index 6f373b8..0000000
--- a/tests/language/disable_privacy_lib.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// Dart test library checking that library privacy can be disabled.
-
-library DisablePrivacyLib;
-
-var _fooForTesting = 1;
diff --git a/tests/language/disable_privacy_test.dart b/tests/language/disable_privacy_test.dart
deleted file mode 100644
index 6e774e9..0000000
--- a/tests/language/disable_privacy_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// 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.
-// VMOptions=--disable_privacy
-//
-// Dart test program checking that library privacy can be disabled.
-
-library DisablePrivacyTest;
-import "package:expect/expect.dart";
-import "disable_privacy_lib.dart";
-
-main() {
- Expect.equals(1, _fooForTesting);
-}
diff --git a/tests/language/exhaustive_for_test.dart b/tests/language/exhaustive_for_test.dart
new file mode 100644
index 0000000..8aa4cde
--- /dev/null
+++ b/tests/language/exhaustive_for_test.dart
@@ -0,0 +1,808 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for testing for statement.
+
+import "package:expect/expect.dart";
+
+// Test several variations of for loops:
+// * With or without an initializer.
+// * With or without a test.
+// * With or without an update.
+// * With or without a continue.
+// * With or without a fall through exit from the body.
+// * With or without a break.
+
+// Note that some possibilities are infinite loops and so not tested.
+// Combinations that do not have a break or a test but do have a
+// fall through from the body or a continue will never exit the loop.
+
+// Each loop test function sets a status containing a bit for each part of
+// the loop that is present, and then clears the bit as that part of the
+// loop is executed. The test expectation should be 0 (all present parts
+// were executed), except for a few cases where an update expression is
+// unreachable due to a break or return in the loop body.
+
+const int INIT = 1;
+const int TEST = 2;
+const int UPDATE = 4;
+const int CONTINUE = 8;
+const int FALL = 16;
+const int BREAK = 32;
+
+var status;
+
+void loop0() {
+ status = 0;
+ for(;;) {
+ return;
+ }
+}
+
+void loop1() {
+ status = INIT;
+ for(status &= ~INIT;;) {
+ return;
+ }
+}
+
+void loop2() {
+ status = TEST;
+ for(; (status &= ~TEST) != 0;) {
+ return;
+ }
+}
+
+void loop3() {
+ status = INIT | TEST;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ return;
+ }
+}
+
+void loop4() {
+ status = UPDATE;
+ for(;; status &= ~UPDATE) {
+ return;
+ }
+}
+
+void loop5() {
+ status = INIT | UPDATE;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ return;
+ }
+}
+
+void loop6() {
+ status = TEST | UPDATE;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ return;
+ }
+}
+
+void loop7() {
+ status = INIT | TEST | UPDATE;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ return;
+ }
+}
+
+// Infinite loop not tested.
+void loop8() {
+ status = CONTINUE;
+ for(;;) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+// Infinite loop not tested.
+void loop9() {
+ status = INIT | CONTINUE;
+ for(status &= ~INIT;;) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+void loop10() {
+ status = TEST | CONTINUE;
+ for(; (status &= ~TEST) != 0;) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+void loop11() {
+ status = INIT | TEST | CONTINUE;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+// Infinite loop.
+void loop12() {
+ status = UPDATE | CONTINUE;
+ for(;; status &= ~UPDATE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+// Infinite loop.
+void loop13() {
+ status = INIT | UPDATE | CONTINUE;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+void loop14() {
+ status = TEST | UPDATE | CONTINUE;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+void loop15() {
+ status = INIT | TEST | UPDATE | CONTINUE;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+}
+
+// Infinite loop.
+void loop16() {
+ status = FALL;
+ for(;;) {
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop17() {
+ status = INIT | FALL;
+ for(status &= ~INIT;;) {
+ status &= ~FALL;
+ }
+}
+
+void loop18() {
+ status = TEST | FALL;
+ for(; (status &= ~TEST) != 0;) {
+ status &= ~FALL;
+ }
+}
+
+void loop19() {
+ status = INIT | TEST | FALL;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop20() {
+ status = UPDATE | FALL;
+ for(;; status &= ~UPDATE) {
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop21() {
+ status = INIT | UPDATE | FALL;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ status &= ~FALL;
+ }
+}
+
+void loop22() {
+ status = TEST | UPDATE | FALL;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ status &= ~FALL;
+ }
+}
+
+void loop23() {
+ status = INIT | TEST | UPDATE | FALL;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop24() {
+ status = CONTINUE | FALL;
+ for(;;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop25() {
+ status = INIT | CONTINUE | FALL;
+ for(status &= ~INIT;;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+void loop26() {
+ status = TEST | CONTINUE | FALL;
+ for(; (status &= ~TEST) != 0;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+void loop27() {
+ status = INIT | TEST | CONTINUE | FALL;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop28() {
+ status = UPDATE | CONTINUE | FALL;
+ for(;; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+// Infinite loop.
+void loop29() {
+ status = INIT | UPDATE | CONTINUE | FALL;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+void loop30() {
+ status = TEST | UPDATE | CONTINUE | FALL;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+void loop31() {
+ status = INIT | TEST | UPDATE | CONTINUE | FALL;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~FALL;
+ }
+}
+
+void loop32() {
+ status = BREAK;
+ for(;;) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop33() {
+ status = INIT | BREAK;
+ for(status &= ~INIT;;) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop34() {
+ status = TEST | BREAK;
+ for(; (status &= ~TEST) != 0;) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop35() {
+ status = INIT | TEST | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop36() {
+ status = UPDATE | BREAK;
+ for(;; status &= ~UPDATE) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop37() {
+ status = INIT | UPDATE | BREAK;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop38() {
+ status = TEST | UPDATE | BREAK;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop39() {
+ status = INIT | TEST | UPDATE | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop40() {
+ status = CONTINUE | BREAK;
+ for(;;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop41() {
+ status = INIT | CONTINUE | BREAK;
+ for(status &= ~INIT;;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop42() {
+ status = TEST | CONTINUE | BREAK;
+ for(; (status &= ~TEST) != 0;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop43() {
+ status = INIT | TEST | CONTINUE | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop44() {
+ status = UPDATE | CONTINUE | BREAK;
+ for(;; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop45() {
+ status = INIT | UPDATE | CONTINUE | BREAK;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop46() {
+ status = TEST | UPDATE | CONTINUE | BREAK;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop47() {
+ status = INIT | TEST | UPDATE | CONTINUE | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ status &= ~BREAK;
+ break;
+ }
+}
+
+void loop48() {
+ status = FALL | BREAK;
+ for(;;) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop49() {
+ status = INIT | FALL | BREAK;
+ for(status &= ~INIT;;) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop50() {
+ status = TEST | FALL | BREAK;
+ for(; (status &= ~TEST) != 0;) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop51() {
+ status = INIT | TEST | FALL | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop52() {
+ status = UPDATE | FALL | BREAK;
+ for(;; status &= ~UPDATE) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop53() {
+ status = INIT | UPDATE | FALL | BREAK;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop54() {
+ status = TEST | UPDATE | FALL | BREAK;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop55() {
+ status = INIT | TEST | UPDATE | FALL | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop56() {
+ status = CONTINUE | FALL | BREAK;
+ for(;;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop57() {
+ status = INIT | CONTINUE | FALL | BREAK;
+ for(status &= ~INIT;;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop58() {
+ status = TEST | CONTINUE | FALL | BREAK;
+ for(; (status &= ~TEST) != 0;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop59() {
+ status = INIT | TEST | CONTINUE | FALL | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0;) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop60() {
+ status = UPDATE | CONTINUE | FALL | BREAK;
+ for(;; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop61() {
+ status = INIT | UPDATE | CONTINUE | FALL | BREAK;
+ for(status &= ~INIT;; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop62() {
+ status = TEST | UPDATE | CONTINUE | FALL | BREAK;
+ for(; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void loop63() {
+ status = INIT | TEST | UPDATE | CONTINUE | FALL | BREAK;
+ for(status &= ~INIT; (status &= ~TEST) != 0; status &= ~UPDATE) {
+ if ((status & CONTINUE) == CONTINUE) {
+ status &= ~CONTINUE;
+ continue;
+ }
+ if ((status & FALL) == FALL) {
+ status &= ~FALL;
+ } else {
+ status &= ~BREAK;
+ break;
+ }
+ }
+}
+
+void main() {
+ loop0();
+ Expect.equals(0, status);
+ loop1();
+ Expect.equals(0, status);
+ loop2();
+ Expect.equals(0, status);
+ loop3();
+ Expect.equals(0, status);
+
+ // The next four tests return with status UPDATE because they return
+ // before the update expression is reached.
+ loop4();
+ Expect.equals(UPDATE, status);
+ loop5();
+ Expect.equals(UPDATE, status);
+ loop6();
+ Expect.equals(UPDATE, status);
+ loop7();
+ Expect.equals(UPDATE, status);
+
+ loop10();
+ Expect.equals(0, status);
+ loop11();
+ Expect.equals(0, status);
+ loop14();
+ Expect.equals(0, status);
+ loop15();
+ Expect.equals(0, status);
+ loop18();
+ Expect.equals(0, status);
+ loop19();
+ Expect.equals(0, status);
+ loop22();
+ Expect.equals(0, status);
+ loop23();
+ Expect.equals(0, status);
+ loop26();
+ Expect.equals(0, status);
+ loop27();
+ Expect.equals(0, status);
+ loop30();
+ Expect.equals(0, status);
+ loop31();
+ Expect.equals(0, status);
+ loop32();
+ Expect.equals(0, status);
+ loop33();
+ Expect.equals(0, status);
+ loop34();
+ Expect.equals(0, status);
+ loop35();
+ Expect.equals(0, status);
+
+ // The next four tests return with status UPDATE because they break from
+ // the loop before the update expression is reached.
+ loop36();
+ Expect.equals(4, status);
+ loop37();
+ Expect.equals(4, status);
+ loop38();
+ Expect.equals(4, status);
+ loop39();
+ Expect.equals(4, status);
+
+ loop40();
+ Expect.equals(0, status);
+ loop41();
+ Expect.equals(0, status);
+ loop42();
+ Expect.equals(0, status);
+ loop43();
+ Expect.equals(0, status);
+ loop44();
+ Expect.equals(0, status);
+ loop45();
+ Expect.equals(0, status);
+ loop46();
+ Expect.equals(0, status);
+ loop47();
+ Expect.equals(0, status);
+ loop48();
+ Expect.equals(0, status);
+ loop49();
+ Expect.equals(0, status);
+ loop50();
+ Expect.equals(0, status);
+ loop51();
+ Expect.equals(0, status);
+ loop52();
+ Expect.equals(0, status);
+ loop53();
+ Expect.equals(0, status);
+ loop54();
+ Expect.equals(0, status);
+ loop55();
+ Expect.equals(0, status);
+ loop56();
+ Expect.equals(0, status);
+ loop57();
+ Expect.equals(0, status);
+ loop58();
+ Expect.equals(0, status);
+ loop59();
+ Expect.equals(0, status);
+ loop60();
+ Expect.equals(0, status);
+ loop61();
+ Expect.equals(0, status);
+ loop62();
+ Expect.equals(0, status);
+ loop63();
+ Expect.equals(0, status);
+}
diff --git a/tests/language/function_subtype0_test.dart b/tests/language/function_subtype0_test.dart
new file mode 100644
index 0000000..1a39d92
--- /dev/null
+++ b/tests/language/function_subtype0_test.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+typedef t__();
+typedef void t_void_();
+typedef void t_void_2();
+typedef int t_int_();
+typedef int t_int_2();
+typedef Object t_Object_();
+typedef double t_double_();
+typedef void t_void__int(int i);
+typedef int t_int__int(int i);
+typedef int t_int__int2(int i);
+typedef int t_int__Object(Object o);
+typedef Object t_Object__int(int i);
+typedef int t_int__double(double d);
+typedef int t_int__int_int(int i1, int i2);
+typedef void t_inline_void_(void f());
+typedef void t_inline_void__int(void f(int i));
+
+void _() => null;
+void void_() {}
+void void_2() {}
+int int_() => 0;
+int int_2() => 0;
+Object Object_() => null;
+double double_() => 0.0;
+void void__int(int i) {}
+int int__int(int i) => 0;
+int int__int2(int i) => 0;
+int int__Object(Object o) => 0;
+Object Object__int(int i) => null;
+int int__double(double d) => 0;
+int int__int_int(int i1, int i2) => 0;
+void inline_void_(void f()) {}
+void inline_void__int(void f(int i)) {}
+
+main() {
+ // () -> int <: Function
+ Expect.isTrue(int_ is Function);
+ // () -> dynamic <: () -> dynamic
+ Expect.isTrue(_ is t__);
+ // () -> dynamic <: () -> void
+ Expect.isTrue(_ is t_void_);
+ // () -> void <: () -> dynamic
+ Expect.isTrue(void_ is t__);
+ // () -> int <: () -> void
+ Expect.isTrue(int_ is t_void_);
+ // () -> void <: () -> int
+ Expect.isFalse(void_ is t_int_);
+ // () -> void <: () -> void
+ Expect.isTrue(void_ is t_void_2);
+ // () -> int <: () -> int
+ Expect.isTrue(int_ is t_int_2);
+ // () -> int <: () -> Object
+ Expect.isTrue(int_ is t_Object_);
+ // () -> int <: () -> double
+ Expect.isFalse(int_ is t_double_);
+ // () -> int <: (int) -> void
+ Expect.isFalse(int_ is t_void__int);
+ // () -> void <: (int) -> int
+ Expect.isFalse(void_ is t_int__int);
+ // () -> void <: (int) -> void
+ Expect.isFalse(void_ is t_void__int);
+ // (int) -> int <: (int) -> int
+ Expect.isTrue(int__int is t_int__int2);
+ // (Object) -> int <: (int) -> Object
+ Expect.isTrue(int__Object is t_Object__int);
+ // (int) -> int <: (double) -> int
+ Expect.isFalse(int__int is t_int__double);
+ // () -> int <: (int) -> int
+ Expect.isFalse(int_ is t_int__int);
+ // (int) -> int <: (int,int) -> int
+ Expect.isFalse(int__int is t_int__int_int);
+ // (int,int) -> int <: (int) -> int
+ Expect.isFalse(int__int_int is t_int__int);
+ // (()->void) -> void <: ((int)->void) -> void
+ Expect.isFalse(inline_void_ is t_inline_void__int);
+ // ((int)->void) -> void <: (()->void) -> void
+ Expect.isFalse(inline_void__int is t_inline_void_);
+}
diff --git a/tests/language/function_subtype1_test.dart b/tests/language/function_subtype1_test.dart
new file mode 100644
index 0000000..a7bd199
--- /dev/null
+++ b/tests/language/function_subtype1_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+typedef _();
+typedef void void_();
+typedef void void_2();
+typedef int int_();
+typedef int int_2();
+typedef Object Object_();
+typedef double double_();
+typedef void void__int(int i);
+typedef int int__int(int i);
+typedef int int__int2(int i);
+typedef int int__Object(Object o);
+typedef Object Object__int(int i);
+typedef int int__double(double d);
+typedef int int__int_int(int i1, int i2);
+typedef void inline_void_(void f());
+typedef void inline_void__int(void f(int i));
+
+main() {
+ // () -> int <: Function
+ Expect.isTrue(new C<int_>() is C<Function>);
+ // Function <: () -> int
+ Expect.isFalse(new C<Function>() is C<int_>);
+ // () -> dynamic <: () -> dynamic
+ Expect.isTrue(new C<_>() is C<_>);
+ // () -> dynamic <: () -> void
+ Expect.isTrue(new C<_>() is C<void_>);
+ // () -> void <: () -> dynamic
+ Expect.isTrue(new C<void_>() is C<_>);
+ // () -> int <: () -> void
+ Expect.isTrue(new C<int_>() is C<void_>);
+ // () -> void <: () -> int
+ Expect.isFalse(new C<void_>() is C<int_>);
+ // () -> void <: () -> void
+ Expect.isTrue(new C<void_>() is C<void_2>);
+ // () -> int <: () -> int
+ Expect.isTrue(new C<int_>() is C<int_2>);
+ // () -> int <: () -> Object
+ Expect.isTrue(new C<int_>() is C<Object_>);
+ // () -> int <: () -> double
+ Expect.isFalse(new C<int_>() is C<double_>);
+ // () -> int <: (int) -> void
+ Expect.isFalse(new C<int_>() is C<void__int>);
+ // () -> void <: (int) -> int
+ Expect.isFalse(new C<void_>() is C<int__int>);
+ // () -> void <: (int) -> void
+ Expect.isFalse(new C<void_>() is C<void__int>);
+ // (int) -> int <: (int) -> int
+ Expect.isTrue(new C<int__int>() is C<int__int2>);
+ // (Object) -> int <: (int) -> Object
+ Expect.isTrue(new C<int__Object>() is C<Object__int>);
+ // (int) -> int <: (double) -> int
+ Expect.isFalse(new C<int__int>() is C<int__double>);
+ // () -> int <: (int) -> int
+ Expect.isFalse(new C<int_>() is C<int__int>);
+ // (int) -> int <: (int,int) -> int
+ Expect.isFalse(new C<int__int>() is C<int__int_int>);
+ // (int,int) -> int <: (int) -> int
+ Expect.isFalse(new C<int__int_int>() is C<int__int>);
+ // (()->void) -> void <: ((int)->void) -> void
+ Expect.isFalse(new C<inline_void_>() is C<inline_void__int>);
+ // ((int)->void) -> void <: (()->void) -> void
+ Expect.isFalse(new C<inline_void__int>() is C<inline_void_>);
+}
diff --git a/tests/language/function_subtype_bound_closure0_test.dart b/tests/language/function_subtype_bound_closure0_test.dart
new file mode 100644
index 0000000..16d36ff
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure0_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for bound closures.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo(bool a, [String b]);
+typedef int Bar(bool a, [String b]);
+typedef int Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+class C {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+ int boz(bool a, {int b}) => null;
+}
+
+main() {
+ var c = new C();
+ var foo = c.foo;
+ Expect.isTrue(foo is Foo, 'foo is Foo');
+ Expect.isTrue(foo is Bar, 'foo is Bar');
+ Expect.isFalse(foo is Baz, 'foo is Baz');
+ Expect.isTrue(foo is Boz, 'foo is Boz');
+
+ var baz = c.baz;
+ Expect.isFalse(baz is Foo, 'baz is Foo');
+ Expect.isFalse(baz is Bar, 'baz is Bar');
+ Expect.isTrue(baz is Baz, 'baz is Baz');
+ Expect.isTrue(baz is Boz, 'baz is Boz');
+
+ var boz = c.boz;
+ Expect.isFalse(boz is Foo, 'boz is Foo');
+ Expect.isFalse(boz is Bar, 'boz is Bar');
+ Expect.isFalse(boz is Baz, 'boz is Baz');
+ Expect.isTrue(boz is Boz, 'boz is Boz');
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_bound_closure1_test.dart b/tests/language/function_subtype_bound_closure1_test.dart
new file mode 100644
index 0000000..e3454e2
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure1_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for bound closures against generic typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+
+class C {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+}
+
+main() {
+ var c = new C();
+ var foo = c.foo;
+ Expect.isTrue(foo is Foo<bool>, 'foo is Foo<bool>');
+ Expect.isTrue(foo is Bar<bool>, 'foo is Bar<bool>');
+ Expect.isFalse(foo is Baz<bool>, 'foo is Baz<bool>');
+ Expect.isTrue(foo is Boz<bool>, 'foo is Boz<bool>');
+
+ Expect.isFalse(foo is Foo<int>, 'foo is Foo<int>');
+ Expect.isFalse(foo is Bar<int>, 'foo is Bar<int>');
+ Expect.isFalse(foo is Baz<int>, 'foo is Baz<int>');
+ Expect.isFalse(foo is Boz<int>, 'foo is Boz<int>');
+
+ Expect.isTrue(foo is Foo, 'foo is Foo');
+ Expect.isTrue(foo is Bar, 'foo is Bar');
+ Expect.isFalse(foo is Baz, 'foo is Baz');
+ Expect.isTrue(foo is Boz, 'foo is Boz');
+
+ var baz = c.baz;
+ Expect.isFalse(baz is Foo<bool>, 'baz is Foo<bool>');
+ Expect.isFalse(baz is Bar<bool>, 'baz is Bar<bool>');
+ Expect.isTrue(baz is Baz<bool>, 'baz is Baz<bool>');
+ Expect.isTrue(baz is Boz<bool>, 'baz is Boz<bool>');
+
+ Expect.isFalse(baz is Foo<int>, 'baz is Foo<int>');
+ Expect.isFalse(baz is Bar<int>, 'baz is Bar<int>');
+ Expect.isFalse(baz is Baz<int>, 'baz is Baz<int>');
+ Expect.isFalse(baz is Boz<int>, 'baz is Boz<int>');
+
+ Expect.isFalse(baz is Foo, 'baz is Foo');
+ Expect.isFalse(baz is Bar, 'baz is Bar');
+ Expect.isTrue(baz is Baz, 'baz is Baz');
+ Expect.isTrue(baz is Boz, 'baz is Boz');
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_bound_closure2_test.dart b/tests/language/function_subtype_bound_closure2_test.dart
new file mode 100644
index 0000000..9a7da9c
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure2_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for bound closures on generic type against generic
+// typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+typedef int Biz<T>(T a, int b);
+
+class C<T> {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+
+ void test(String nameOfT, bool expectedResult) {
+ Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.equals(expectedResult, foo is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(foo is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, foo is Boz<T>, 'foo is Boz<$nameOfT>');
+ Expect.isFalse(foo is Biz<T>, 'foo is Biz<$nameOfT>');
+
+ Expect.isFalse(baz is Foo<T>, 'baz is Foo<$nameOfT>');
+ Expect.isFalse(baz is Bar<T>, 'baz is Bar<$nameOfT>');
+ Expect.equals(expectedResult, baz is Baz<T>, 'baz is Baz<$nameOfT>');
+ Expect.equals(expectedResult, baz is Boz<T>, 'baz is Boz<$nameOfT>');
+ Expect.isFalse(baz is Biz<T>, 'bar is Biz<$nameOfT>');
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_bound_closure3_test.dart b/tests/language/function_subtype_bound_closure3_test.dart
new file mode 100644
index 0000000..1af7b97
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure3_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for generic bound closures.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+class C<T> {
+ void foo(T a, [String b]) {}
+ void baz(T a, {String b}) {}
+
+ void test(String nameOfT, bool expectedResult) {
+ Expect.equals(expectedResult, foo is Foo, 'C<$nameOfT>.foo is Foo');
+ Expect.equals(expectedResult, foo is Bar, 'C<$nameOfT>.foo is Bar');
+ Expect.isFalse(foo is Baz, 'C<$nameOfT>.foo is Baz');
+ Expect.isFalse(foo is Boz, 'C<$nameOfT>.foo is Boz');
+
+ Expect.isFalse(baz is Foo, 'C<$nameOfT>.baz is Foo');
+ Expect.isFalse(baz is Bar, 'C<$nameOfT>.baz is Bar');
+ Expect.equals(expectedResult, baz is Baz, 'C<$nameOfT>.baz is Baz');
+ Expect.isFalse(baz is Boz, 'C<$nameOfT>.baz is Boz');
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_bound_closure4_test.dart b/tests/language/function_subtype_bound_closure4_test.dart
new file mode 100644
index 0000000..99cd743
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure4_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for generic bound closures.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+class C<T> {
+ void foo(T a, [String b]) {}
+ void baz(T a, {String b}) {}
+
+ void test(String nameOfT, bool expectedResult) {
+ Expect.equals(expectedResult, foo is Foo, 'C<$nameOfT>.foo is Foo');
+ Expect.equals(expectedResult, foo is Bar, 'C<$nameOfT>.foo is Bar');
+ Expect.isFalse(foo is Baz, 'C<$nameOfT>.foo is Baz');
+ Expect.isFalse(foo is Boz, 'C<$nameOfT>.foo is Boz');
+
+ Expect.isFalse(baz is Foo, 'C<$nameOfT>.baz is Foo');
+ Expect.isFalse(baz is Bar, 'C<$nameOfT>.baz is Bar');
+ Expect.equals(expectedResult, baz is Baz, 'C<$nameOfT>.baz is Baz');
+ Expect.isFalse(baz is Boz, 'C<$nameOfT>.baz is Boz');
+ }
+}
+
+class D<S, T> extends C<T> {}
+
+main() {
+ new D<String, bool>().test('bool', true);
+ new D<bool, int>().test('int', false);
+ new D().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_bound_closure5_test.dart b/tests/language/function_subtype_bound_closure5_test.dart
new file mode 100644
index 0000000..8192b6f
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure5_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for bound closures on generic type against generic
+// typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+typedef int Biz<T>(T a, int b);
+
+class C<T> {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+
+ void test(String nameOfT, bool expectedResult) {
+ Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.equals(expectedResult, foo is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(foo is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, foo is Boz<T>, 'foo is Boz<$nameOfT>');
+ Expect.isFalse(foo is Biz<T>, 'foo is Biz<$nameOfT>');
+
+ Expect.isFalse(baz is Foo<T>, 'baz is Foo<$nameOfT>');
+ Expect.isFalse(baz is Bar<T>, 'baz is Bar<$nameOfT>');
+ Expect.equals(expectedResult, baz is Baz<T>, 'baz is Baz<$nameOfT>');
+ Expect.equals(expectedResult, baz is Boz<T>, 'baz is Boz<$nameOfT>');
+ Expect.isFalse(baz is Biz<T>, 'bar is Biz<$nameOfT>');
+ }
+}
+
+class D<S, T> extends C<T> {}
+
+main() {
+ new D<String, bool>().test('bool', true);
+ new D<bool, int>().test('int', false);
+ new D().test('dynamic', true);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_bound_closure6_test.dart b/tests/language/function_subtype_bound_closure6_test.dart
new file mode 100644
index 0000000..931e458
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure6_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for bound closures on generic type against generic
+// typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+typedef int Biz<T>(T a, int b);
+
+class C<T> {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+
+ void test(String nameOfT, bool expectedResult) {
+ void localMethod() {
+ Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.equals(expectedResult, foo is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(foo is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, foo is Boz<T>, 'foo is Boz<$nameOfT>');
+ Expect.isFalse(foo is Biz<T>, 'foo is Biz<$nameOfT>');
+
+ Expect.isFalse(baz is Foo<T>, 'baz is Foo<$nameOfT>');
+ Expect.isFalse(baz is Bar<T>, 'baz is Bar<$nameOfT>');
+ Expect.equals(expectedResult, baz is Baz<T>, 'baz is Baz<$nameOfT>');
+ Expect.equals(expectedResult, baz is Boz<T>, 'baz is Boz<$nameOfT>');
+ Expect.isFalse(baz is Biz<T>, 'bar is Biz<$nameOfT>');
+ }
+ localMethod();
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_bound_closure7_test.dart b/tests/language/function_subtype_bound_closure7_test.dart
new file mode 100644
index 0000000..5f24aa9
--- /dev/null
+++ b/tests/language/function_subtype_bound_closure7_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for bound closures.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+
+class Class<T> {
+ foo(Foo<T> o) => o is Foo<T>;
+}
+
+void bar(int i) {}
+
+void main() {
+ bool inCheckedMode = false;
+ try {
+ String a = 42;
+ } catch (e) {
+ inCheckedMode = true;
+ }
+
+ var f = new Class<int>().foo;
+ Expect.isTrue(f(bar));
+ if (inCheckedMode) {
+ Expect.throws(() => f(f), (e) => true);
+ } else {
+ Expect.isFalse(f(f));
+ }
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_call0_test.dart b/tests/language/function_subtype_call0_test.dart
new file mode 100644
index 0000000..d862683
--- /dev/null
+++ b/tests/language/function_subtype_call0_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for classes with call functions.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef void Boz(bool a);
+
+class C1 {
+ void call(bool a, [String b]) {}
+}
+
+class C2 {
+ void call(bool a, {String b}) {}
+}
+
+class C3 {
+ void call(bool a, {int b}) {}
+}
+
+main() {
+ Expect.isTrue(new C1() is Foo, 'new C1() is Foo');
+ Expect.isTrue(new C1() is Bar, 'new C1() is Bar');
+ Expect.isFalse(new C1() is Baz, 'new C1() is Baz');
+ Expect.isTrue(new C1() is Boz, 'new C1() is Boz');
+
+ Expect.isFalse(new C2() is Foo, 'new C2() is Foo');
+ Expect.isFalse(new C2() is Bar, 'new C2() is Bar');
+ Expect.isTrue(new C2() is Baz, 'new C2() is Baz');
+ Expect.isTrue(new C2() is Boz, 'new C2() is Boz');
+
+ Expect.isFalse(new C3() is Foo, 'new C3() is Foo');
+ Expect.isFalse(new C3() is Bar, 'new C3() is Bar');
+ Expect.isFalse(new C3() is Baz, 'new C3() is Baz');
+ Expect.isTrue(new C3() is Boz, 'new C3() is Boz');
+}
diff --git a/tests/language/function_subtype_call1_test.dart b/tests/language/function_subtype_call1_test.dart
new file mode 100644
index 0000000..2ac5e43
--- /dev/null
+++ b/tests/language/function_subtype_call1_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for classes with call functions.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef void Boz(bool a);
+
+class C1<T> {
+ void call(T a, [String b]) {}
+}
+
+class C2<T> {
+ void call(T a, {String b}) {}
+}
+
+main() {
+ Expect.isTrue(new C1<bool>() is Foo, 'new C1<bool>() is Foo');
+ Expect.isTrue(new C1<bool>() is Bar, 'new C1<bool>() is Bar');
+ Expect.isFalse(new C1<bool>() is Baz, 'new C1<bool>() is Baz');
+ Expect.isTrue(new C1<bool>() is Boz, 'new C1<bool>() is Boz');
+
+ Expect.isFalse(new C1<int>() is Foo, 'new C1<int>() is Foo');
+ Expect.isFalse(new C1<int>() is Bar, 'new C1<int>() is Bar');
+ Expect.isFalse(new C1<int>() is Baz, 'new C1<int>() is Baz');
+ Expect.isFalse(new C1<int>() is Boz, 'new C1<int>() is Boz');
+
+ Expect.isTrue(new C1() is Foo, 'new C1() is Foo');
+ Expect.isTrue(new C1() is Bar, 'new C1() is Bar');
+ Expect.isFalse(new C1() is Baz, 'new C1() is Baz');
+ Expect.isTrue(new C1() is Boz, 'new C1() is Boz');
+
+ Expect.isFalse(new C2<bool>() is Foo, 'new C2<bool>() is Foo');
+ Expect.isFalse(new C2<bool>() is Bar, 'new C2<bool>() is Bar');
+ Expect.isTrue(new C2<bool>() is Baz, 'new C2<bool>() is Baz');
+ Expect.isTrue(new C2<bool>() is Boz, 'new C2<bool>() is Boz');
+
+ Expect.isFalse(new C2<int>() is Foo, 'new C2<int>() is Foo');
+ Expect.isFalse(new C2<int>() is Bar, 'new C2<int>() is Bar');
+ Expect.isFalse(new C2<int>() is Baz, 'new C2<int>() is Baz');
+ Expect.isFalse(new C2<int>() is Boz, 'new C2<int>() is Boz');
+
+ Expect.isFalse(new C2() is Foo, 'new C2() is Foo');
+ Expect.isFalse(new C2() is Bar, 'new C2() is Bar');
+ Expect.isTrue(new C2() is Baz, 'new C2() is Baz');
+ Expect.isTrue(new C2() is Boz, 'new C2() is Boz');
+}
diff --git a/tests/language/function_subtype_call2_test.dart b/tests/language/function_subtype_call2_test.dart
new file mode 100644
index 0000000..8dabe8f
--- /dev/null
+++ b/tests/language/function_subtype_call2_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for classes with call functions.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef void Boz(bool a);
+
+class C1<T> {
+ void call(T a, [String b]) {}
+}
+
+class D1<S, T> extends C1<T> {}
+
+class C2<T> {
+ void call(T a, {String b}) {}
+}
+
+class D2<S, T> extends C2<T> {}
+
+main() {
+ Expect.isTrue(new D1<String, bool>() is Foo, 'new D1<String, bool>() is Foo');
+ Expect.isTrue(new D1<String, bool>() is Bar, 'new D1<String, bool>() is Bar');
+ Expect.isFalse(new D1<String, bool>() is Baz,
+ 'new D1<String, bool>() is Baz');
+ Expect.isTrue(new D1<String, bool>() is Boz, 'new D1<String, bool>() is Boz');
+
+ Expect.isFalse(new D1<bool, int>() is Foo, 'new D1<bool, int>() is Foo');
+ Expect.isFalse(new D1<bool, int>() is Bar, 'new D1<bool, int>() is Bar');
+ Expect.isFalse(new D1<bool, int>() is Baz, 'new D1<bool, int>() is Baz');
+ Expect.isFalse(new D1<bool, int>() is Boz, 'new D1<bool, int>() is Boz');
+
+ Expect.isTrue(new D1() is Foo, 'new D1() is Foo');
+ Expect.isTrue(new D1() is Bar, 'new D1() is Bar');
+ Expect.isFalse(new D1() is Baz, 'new D1() is Baz');
+ Expect.isTrue(new D1() is Boz, 'new D1() is Boz');
+
+ Expect.isFalse(new D2<String, bool>() is Foo,
+ 'new D2<String, bool>() is Foo');
+ Expect.isFalse(new D2<String, bool>() is Bar,
+ 'new D2<String, bool>() is Bar');
+ Expect.isTrue(new D2<String, bool>() is Baz, 'new D2<String, bool>() is Baz');
+ Expect.isTrue(new D2<String, bool>() is Boz, 'new D2<String, bool>() is Boz');
+
+ Expect.isFalse(new D2<bool, int>() is Foo, 'new D2<bool, int>() is Foo');
+ Expect.isFalse(new D2<bool, int>() is Bar, 'new D2<bool, int>() is Bar');
+ Expect.isFalse(new D2<bool, int>() is Baz, 'new D2<bool, int>() is Baz');
+ Expect.isFalse(new D2<bool, int>() is Boz, 'new D2<bool, int>() is Boz');
+
+ Expect.isFalse(new D2() is Foo, 'new D2() is Foo');
+ Expect.isFalse(new D2() is Bar, 'new D2() is Bar');
+ Expect.isTrue(new D2() is Baz, 'new D2() is Baz');
+ Expect.isTrue(new D2() is Boz, 'new D2() is Boz');
+}
diff --git a/tests/language/function_subtype_cast0_test.dart b/tests/language/function_subtype_cast0_test.dart
new file mode 100644
index 0000000..455d32b
--- /dev/null
+++ b/tests/language/function_subtype_cast0_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping casts.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+void bar(int i) {}
+
+void main() {
+ Expect.isNotNull(bar as Foo);
+ Expect.throws(() => bar as Foo<bool>, (e) => true);
+ Expect.isNotNull(bar as Foo<int>);
+ Expect.isNotNull(bar as Bar);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_cast1_test.dart b/tests/language/function_subtype_cast1_test.dart
new file mode 100644
index 0000000..74b694a
--- /dev/null
+++ b/tests/language/function_subtype_cast1_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping casts.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+class Class<T> {
+ void bar(T i) {}
+}
+
+void main() {
+ Expect.isNotNull(new Class().bar as Foo);
+ Expect.isNotNull(new Class().bar as Foo<bool>);
+ Expect.isNotNull(new Class().bar as Foo<int>);
+ Expect.isNotNull(new Class().bar as Bar);
+
+ Expect.isNotNull(new Class<int>().bar as Foo);
+ Expect.throws(() => new Class<int>().bar as Foo<bool>, (e) => true);
+ Expect.isNotNull(new Class<int>().bar as Foo<int>);
+ Expect.isNotNull(new Class<int>().bar as Bar);
+
+ Expect.isNotNull(new Class<bool>().bar as Foo);
+ Expect.isNotNull(new Class<bool>().bar as Foo<bool>);
+ Expect.throws(() => new Class<bool>().bar as Foo<int>, (e) => true);
+ Expect.throws(() => new Class<bool>().bar as Bar, (e) => true);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_cast2_test.dart b/tests/language/function_subtype_cast2_test.dart
new file mode 100644
index 0000000..3f1aaa6
--- /dev/null
+++ b/tests/language/function_subtype_cast2_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping casts.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+class Class<T> {
+ test(bool expectedResult, var o, String typeName) {
+ if (expectedResult) {
+ Expect.isNotNull(o as Foo<T>, "bar as Foo<$typeName>");
+ } else {
+ Expect.throws(() => o as Foo<T>, (e) => true, "bar as Foo<$typeName>");
+ }
+ Expect.isNotNull(o as Bar, "bar as Bar");
+ }
+}
+
+void bar(int i) {}
+
+void main() {
+ new Class().test(true, bar, "dynamic");
+ new Class<int>().test(true, bar, "int");
+ new Class<bool>().test(false, bar, "bool");
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_cast3_test.dart b/tests/language/function_subtype_cast3_test.dart
new file mode 100644
index 0000000..ba6f4ac
--- /dev/null
+++ b/tests/language/function_subtype_cast3_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping casts.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+class Class<T> {
+ test(bool expectedResult, var o, String typeName) {
+ void local() {
+ if (expectedResult) {
+ Expect.isNotNull(o as Foo<T>, "bar as Foo<$typeName>");
+ } else {
+ Expect.throws(() => o as Foo<T>, (e) => true, "bar as Foo<$typeName>");
+ }
+ Expect.isNotNull(o as Bar, "bar as Bar");
+ }
+ local();
+ }
+}
+
+void bar(int i) {}
+
+void main() {
+ new Class().test(true, bar, "dynamic");
+ new Class<int>().test(true, bar, "int");
+ new Class<bool>().test(false, bar, "bool");
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_checked0_test.dart b/tests/language/function_subtype_checked0_test.dart
new file mode 100644
index 0000000..ee293d6
--- /dev/null
+++ b/tests/language/function_subtype_checked0_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of typedef vs. inlined function types.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+
+int foo(bool a, [String b]) => null;
+int baz(bool a, {String b}) => null;
+int boz(bool a, {int b}) => null;
+
+class C<T> {
+ void test1a(Foo<T> f) {}
+ void test1b(Bar<T> f) {}
+ void test1c(int f(T a, [String b])) {}
+
+ void test2a(Baz<T> f) {}
+ void test2b(int f(T a, {String b})) {}
+
+ void test3a(Boz<T> f) {}
+ void test3b(int f(T a)) {}
+
+ void test(String nameOfT, bool expectedResult) {
+ check(bool expectedResult, f()) {
+ if (inCheckedMode() && !expectedResult) {
+ Expect.throws(f, (e) => true);
+ } else {
+ f();
+ }
+ }
+
+ check(expectedResult, () => test1a(foo));
+ check(expectedResult, () => test1b(foo));
+ check(expectedResult, () => test1b(foo));
+ check(false, () => test2a(foo));
+ check(false, () => test2b(foo));
+ check(expectedResult, () => test3a(foo));
+ check(expectedResult, () => test3b(foo));
+
+ check(false, () => test1a(baz));
+ check(false, () => test1b(baz));
+ check(false, () => test1b(baz));
+ check(expectedResult, () => test2a(baz));
+ check(expectedResult, () => test2b(baz));
+ check(expectedResult, () => test3a(baz));
+ check(expectedResult, () => test3b(baz));
+
+ check(false, () => test1a(boz));
+ check(false, () => test1b(boz));
+ check(false, () => test1b(boz));
+ check(false, () => test2a(boz));
+ check(false, () => test2b(boz));
+ check(expectedResult, () => test3a(boz));
+ check(expectedResult, () => test3b(boz));
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
+
+bool inCheckedMode() {
+ try {
+ var x = 42;
+ String a = x;
+ } catch (e) {
+ return true;
+ }
+ return false;
+}
diff --git a/tests/language/function_subtype_closure0_test.dart b/tests/language/function_subtype_closure0_test.dart
new file mode 100644
index 0000000..1d6437b
--- /dev/null
+++ b/tests/language/function_subtype_closure0_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of static functions.
+
+import 'package:expect/expect.dart';
+
+typedef I<T> f2<T>();
+
+class X {
+ static J<bool> f1() => null;
+}
+
+class C<T> {
+ C(f2<T> f);
+}
+
+class I<T> {}
+class J<T> extends I<int> {}
+
+main() {
+
+ bool inCheckedMode = false;
+ try {
+ String a = 42;
+ } catch (e) {
+ inCheckedMode = true;
+ }
+
+ new C<int>(X.f1);
+ if (inCheckedMode) {
+ Expect.throws(() => new C<bool>(X.f1), (e) => true);
+ }
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_closure1_test.dart b/tests/language/function_subtype_closure1_test.dart
new file mode 100644
index 0000000..5c62341
--- /dev/null
+++ b/tests/language/function_subtype_closure1_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of dynamic closures.
+
+import 'package:expect/expect.dart';
+
+typedef I<T> f2<T>();
+
+class X {
+ J<bool> f1() => null;
+}
+
+class C<T> {
+ C(f2<T> f);
+}
+
+class I<T> {}
+class J<T> extends I<int> {}
+
+main() {
+ bool inCheckedMode = false;
+ try {
+ String a = 42;
+ } catch (e) {
+ inCheckedMode = true;
+ }
+
+ new C<int>(new X().f1);
+ if (inCheckedMode) {
+ Expect.throws(() => new C<bool>(new X().f1), (e) => true);
+ }
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_factory0_test.dart b/tests/language/function_subtype_factory0_test.dart
new file mode 100644
index 0000000..91d6056
--- /dev/null
+++ b/tests/language/function_subtype_factory0_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping with type variables in factory constructors.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+
+class C<T> {
+ factory C(foo) {
+ if (foo is Foo<T>) {
+ return new C.internal();
+ }
+ return null;
+ }
+ C.internal();
+}
+
+void method(String s) {}
+
+void main() {
+ Expect.isNotNull(new C<String>(method));
+ Expect.isNull(new C<bool>(method));
+}
diff --git a/tests/language/function_subtype_factory1_test.dart b/tests/language/function_subtype_factory1_test.dart
new file mode 100644
index 0000000..2ad4d35
--- /dev/null
+++ b/tests/language/function_subtype_factory1_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping with type variables in factory constructors.
+
+import 'package:expect/expect.dart';
+
+class C<T> {
+ factory C(void foo(T t)) => new C.internal();
+ C.internal();
+}
+
+void method(String s) {}
+
+void main() {
+ Expect.isNotNull(new C<String>(method));
+ try {
+ new C<bool>(method);
+ Expect.isFalse(isCheckedMode());
+ } catch (e) {
+ Expect.isTrue(isCheckedMode());
+ }
+}
+
+isCheckedMode() {
+ try {
+ var i = 1;
+ String s = i;
+ return false;
+ } catch (e) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_inline0_test.dart b/tests/language/function_subtype_inline0_test.dart
new file mode 100644
index 0000000..40b49ef
--- /dev/null
+++ b/tests/language/function_subtype_inline0_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for generic bound closures.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+class C<T> {
+ void test(String nameOfT, bool expectedResult) {
+ Expect.equals(expectedResult, (T a, [String b]) {} is Foo,
+ '($nameOfT,[String])->void is Foo');
+ Expect.equals(expectedResult, (T a, [String b]) {} is Bar,
+ '($nameOfT,[String])->void is Bar');
+ Expect.isFalse((T a, [String b]) {} is Baz,
+ '($nameOfT,[String])->void is Baz');
+ Expect.equals(expectedResult, (T a, [String b]) {} is Boz,
+ '($nameOfT,[String])->void is Boz');
+
+ Expect.isFalse((T a, {String b}) {} is Foo,
+ '($nameOfT,{b:String})->void is Foo');
+ Expect.isFalse((T a, {String b}) {} is Bar,
+ '($nameOfT,{b:String})->void is Bar');
+ Expect.equals(expectedResult, (T a, {String b}) {} is Baz,
+ '($nameOfT,{b:String})->void is Baz');
+ Expect.equals(expectedResult, (T a, {String b}) {} is Boz,
+ '($nameOfT,{b:String})->void is Boz');
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_inline1_test.dart b/tests/language/function_subtype_inline1_test.dart
new file mode 100644
index 0000000..74491db
--- /dev/null
+++ b/tests/language/function_subtype_inline1_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+class A {}
+class B extends A {}
+class C extends A {}
+
+class Class<K,V> {
+ void forEach(void f(K k, V v)) {}
+}
+
+main() {
+ Class<B,C> c = new Class<B,C>();
+ c.forEach((A a, A b) {});
+ c.forEach((B a, C b) {});
+ try {
+ c.forEach((A a, B b) {});
+ Expect.isFalse(isCheckedMode());
+ } catch (e) {
+ Expect.isTrue(isCheckedMode());
+ }
+}
+
+
+isCheckedMode() {
+ try {
+ var i = 1;
+ String s = i;
+ return false;
+ } catch (e) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_local0_test.dart b/tests/language/function_subtype_local0_test.dart
new file mode 100644
index 0000000..bec28d3
--- /dev/null
+++ b/tests/language/function_subtype_local0_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for local functions.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo(bool a, [String b]);
+typedef int Bar(bool a, [String b]);
+typedef int Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+main() {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+ int boz(bool a, {int b}) => null;
+
+ Expect.isTrue(foo is Foo, 'foo is Foo');
+ Expect.isTrue(foo is Bar, 'foo is Bar');
+ Expect.isFalse(foo is Baz, 'foo is Baz');
+ Expect.isTrue(foo is Boz, 'foo is Boz');
+
+ Expect.isFalse(baz is Foo, 'baz is Foo');
+ Expect.isFalse(baz is Bar, 'baz is Bar');
+ Expect.isTrue(baz is Baz, 'baz is Baz');
+ Expect.isTrue(baz is Boz, 'baz is Boz');
+
+ Expect.isFalse(boz is Foo, 'boz is Foo');
+ Expect.isFalse(boz is Bar, 'boz is Bar');
+ Expect.isFalse(boz is Baz, 'boz is Baz');
+ Expect.isTrue(boz is Boz, 'boz is Boz');
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_local1_test.dart b/tests/language/function_subtype_local1_test.dart
new file mode 100644
index 0000000..f2755f7
--- /dev/null
+++ b/tests/language/function_subtype_local1_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for local functions against generic typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+
+main() {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+
+ Expect.isTrue(foo is Foo<bool>, 'foo is Foo<bool>');
+ Expect.isTrue(foo is Bar<bool>, 'foo is Bar<bool>');
+ Expect.isFalse(foo is Baz<bool>, 'foo is Baz<bool>');
+ Expect.isTrue(foo is Boz<bool>, 'foo is Boz<bool>');
+
+ Expect.isFalse(foo is Foo<int>, 'foo is Foo<int>');
+ Expect.isFalse(foo is Bar<int>, 'foo is Bar<int>');
+ Expect.isFalse(foo is Baz<int>, 'foo is Baz<int>');
+ Expect.isFalse(foo is Boz<int>, 'foo is Boz<int>');
+
+ Expect.isTrue(foo is Foo, 'foo is Foo');
+ Expect.isTrue(foo is Bar, 'foo is Bar');
+ Expect.isFalse(foo is Baz, 'foo is Baz');
+ Expect.isTrue(foo is Boz, 'foo is Boz');
+
+ Expect.isFalse(baz is Foo<bool>, 'baz is Foo<bool>');
+ Expect.isFalse(baz is Bar<bool>, 'baz is Bar<bool>');
+ Expect.isTrue(baz is Baz<bool>, 'baz is Baz<bool>');
+ Expect.isTrue(baz is Boz<bool>, 'baz is Boz<bool>');
+
+ Expect.isFalse(baz is Foo<int>, 'baz is Foo<int>');
+ Expect.isFalse(baz is Bar<int>, 'baz is Bar<int>');
+ Expect.isFalse(baz is Baz<int>, 'baz is Baz<int>');
+ Expect.isFalse(baz is Boz<int>, 'baz is Boz<int>');
+
+ Expect.isFalse(baz is Foo, 'baz is Foo');
+ Expect.isFalse(baz is Bar, 'baz is Bar');
+ Expect.isTrue(baz is Baz, 'baz is Baz');
+ Expect.isTrue(baz is Boz, 'baz is Boz');
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_local2_test.dart b/tests/language/function_subtype_local2_test.dart
new file mode 100644
index 0000000..65d470d
--- /dev/null
+++ b/tests/language/function_subtype_local2_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for local functions on generic type against generic
+// typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+typedef int Biz<T>(T a, int b);
+
+class C<T> {
+ void test(String nameOfT, bool expectedResult) {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+
+ Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.equals(expectedResult, foo is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(foo is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, foo is Boz<T>, 'foo is Boz<$nameOfT>');
+ Expect.isFalse(foo is Biz<T>, 'foo is Biz<$nameOfT>');
+
+ Expect.isFalse(baz is Foo<T>, 'baz is Foo<$nameOfT>');
+ Expect.isFalse(baz is Bar<T>, 'baz is Bar<$nameOfT>');
+ Expect.equals(expectedResult, baz is Baz<T>, 'baz is Baz<$nameOfT>');
+ Expect.equals(expectedResult, baz is Boz<T>, 'baz is Boz<$nameOfT>');
+ Expect.isFalse(baz is Biz<T>, 'bar is Biz<$nameOfT>');
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_local3_test.dart b/tests/language/function_subtype_local3_test.dart
new file mode 100644
index 0000000..344f7c2
--- /dev/null
+++ b/tests/language/function_subtype_local3_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for generic bound closures.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+class C<T> {
+ void test(String nameOfT, bool expectedResult) {
+ void foo(T a, [String b]) {}
+ void baz(T a, {String b}) {}
+
+ Expect.equals(expectedResult, foo is Foo, 'C<$nameOfT>.foo is Foo');
+ Expect.equals(expectedResult, foo is Bar, 'C<$nameOfT>.foo is Bar');
+ Expect.isFalse(foo is Baz, 'C<$nameOfT>.foo is Baz');
+ Expect.isFalse(foo is Boz, 'C<$nameOfT>.foo is Boz');
+
+ Expect.isFalse(baz is Foo, 'C<$nameOfT>.baz is Foo');
+ Expect.isFalse(baz is Bar, 'C<$nameOfT>.baz is Bar');
+ Expect.equals(expectedResult, baz is Baz, 'C<$nameOfT>.baz is Baz');
+ Expect.isFalse(baz is Boz, 'C<$nameOfT>.baz is Boz');
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_local4_test.dart b/tests/language/function_subtype_local4_test.dart
new file mode 100644
index 0000000..5219757
--- /dev/null
+++ b/tests/language/function_subtype_local4_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for generic bound closures. This also tests
+// type argument substitution.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+class C<T> {
+ void test(String nameOfT, bool expectedResult) {
+ void foo(T a, [String b]) {}
+ void baz(T a, {String b}) {}
+
+ Expect.equals(expectedResult, foo is Foo, 'C<$nameOfT>.foo is Foo');
+ Expect.equals(expectedResult, foo is Bar, 'C<$nameOfT>.foo is Bar');
+ Expect.isFalse(foo is Baz, 'C<$nameOfT>.foo is Baz');
+ Expect.isFalse(foo is Boz, 'C<$nameOfT>.foo is Boz');
+
+ Expect.isFalse(baz is Foo, 'C<$nameOfT>.baz is Foo');
+ Expect.isFalse(baz is Bar, 'C<$nameOfT>.baz is Bar');
+ Expect.equals(expectedResult, baz is Baz, 'C<$nameOfT>.baz is Baz');
+ Expect.isFalse(baz is Boz, 'C<$nameOfT>.baz is Boz');
+ }
+}
+
+class D<S, T> extends C<T> {}
+
+main() {
+ new D<String, bool>().test('bool', true);
+ new D<bool, int>().test('int', false);
+ new D().test('dynamic', true);
+}
diff --git a/tests/language/function_subtype_local5_test.dart b/tests/language/function_subtype_local5_test.dart
new file mode 100644
index 0000000..05cc7af
--- /dev/null
+++ b/tests/language/function_subtype_local5_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for local functions on generic type against generic
+// typedefs.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+typedef int Biz<T>(T a, int b);
+
+class C<T> {
+ void test(String nameOfT, bool expectedResult) {
+ int foo(bool a, [String b]) => null;
+ int baz(bool a, {String b}) => null;
+
+ Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.equals(expectedResult, foo is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(foo is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, foo is Boz<T>, 'foo is Boz<$nameOfT>');
+ Expect.isFalse(foo is Biz<T>, 'foo is Biz<$nameOfT>');
+
+ Expect.isFalse(baz is Foo<T>, 'baz is Foo<$nameOfT>');
+ Expect.isFalse(baz is Bar<T>, 'baz is Bar<$nameOfT>');
+ Expect.equals(expectedResult, baz is Baz<T>, 'baz is Baz<$nameOfT>');
+ Expect.equals(expectedResult, baz is Boz<T>, 'baz is Boz<$nameOfT>');
+ Expect.isFalse(baz is Biz<T>, 'bar is Biz<$nameOfT>');
+ }
+}
+
+class D<S,T> extends C<T> {}
+
+main() {
+ new D<String, bool>().test('bool', true);
+ new D<bool, int>().test('int', false);
+ new D().test('dynamic', true);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_named1_test.dart b/tests/language/function_subtype_named1_test.dart
new file mode 100644
index 0000000..f697a45
--- /dev/null
+++ b/tests/language/function_subtype_named1_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+void void_() {}
+void void__int(int i) {}
+void void___a_int({int a}) {}
+void void___a_int2({int a}) {}
+void void___b_int({int b}) {}
+void void___a_Object({Object a}) {}
+void void__int__a_int(int i1, {int a}) {}
+void void__int__a_int2(int i1, {int a}) {}
+void void___a_double({double a}) {}
+void void___a_int_b_int({int a, int b}) {}
+void void___a_int_b_int_c_int({int a, int b, int c}) {}
+void void___a_int_c_int({int a, int c}) {}
+void void___b_int_c_int({int b, int c}) {}
+void void___c_int({int c}) {}
+
+typedef void t_void_();
+typedef void t_void__int(int i);
+typedef void t_void___a_int({int a});
+typedef void t_void___a_int2({int a});
+typedef void t_void___b_int({int b});
+typedef void t_void___a_Object({Object a});
+typedef void t_void__int__a_int(int i1, {int a});
+typedef void t_void__int__a_int2(int i1, {int a});
+typedef void t_void___a_double({double a});
+typedef void t_void___a_int_b_int({int a, int b});
+typedef void t_void___a_int_b_int_c_int({int a, int b, int c});
+typedef void t_void___a_int_c_int({int a, int c});
+typedef void t_void___b_int_c_int({int b, int c});
+typedef void t_void___c_int({int c});
+
+main() {
+ // Test ({int a})->void <: ()->void.
+ Expect.isTrue(void___a_int is t_void_);
+ // Test ({int a})->void <: (int)->void.
+ Expect.isFalse(void___a_int is t_void__int);
+ // Test (int)->void <: ({int a})->void.
+ Expect.isFalse(void__int is t_void___a_int);
+ // Test ({int a})->void <: ({int a})->void.
+ Expect.isTrue(void___a_int is t_void___a_int2);
+ // Test ({int a})->void <: ({int b})->void.
+ Expect.isFalse(void___a_int is t_void___b_int);
+ // Test ({Object a})->void <: ({int a})->void.
+ Expect.isTrue(void___a_Object is t_void___a_int);
+ // Test ({int a})->void <: ({Object a})->void.
+ Expect.isTrue(void___a_int is t_void___a_Object);
+ // Test (int,{int a})->void <: (int,{int a})->void.
+ Expect.isTrue(void__int__a_int is t_void__int__a_int2);
+ // Test ({int a})->void <: ({double a})->void.
+ Expect.isFalse(void___a_int is t_void___a_double);
+ // Test ({int a})->void <: ({int a,int b})->void.
+ Expect.isFalse(void___a_int is t_void___a_int_b_int);
+ // Test ({int a,int b})->void <: ({int a})->void.
+ Expect.isTrue(void___a_int_b_int is t_void___a_int);
+ // Test ({int a,int b,int c})->void <: ({int a,int c})->void.
+ Expect.isTrue(void___a_int_b_int_c_int is t_void___a_int_c_int);
+ // Test ({int a,int b,int c})->void <: ({int b,int c})->void.
+ Expect.isTrue(void___a_int_b_int_c_int is t_void___b_int_c_int);
+ // Test ({int a,int b,int c})->void <: ({int c})->void.
+ Expect.isTrue(void___a_int_b_int_c_int is t_void___c_int);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_named2_test.dart b/tests/language/function_subtype_named2_test.dart
new file mode 100644
index 0000000..f2618bf
--- /dev/null
+++ b/tests/language/function_subtype_named2_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+typedef void void_();
+typedef void void__int(int i);
+typedef void void___a_int({int a});
+typedef void void___a_int2({int a});
+typedef void void___b_int({int b});
+typedef void void___a_Object({Object a});
+typedef void void__int__a_int(int i1, {int a});
+typedef void void__int__a_int2(int i1, {int a});
+typedef void void___a_double({double a});
+typedef void void___a_int_b_int({int a, int b});
+typedef void void___a_int_b_int_c_int({int a, int b, int c});
+typedef void void___a_int_c_int({int a, int c});
+typedef void void___b_int_c_int({int b, int c});
+typedef void void___c_int({int c});
+
+main() {
+ // Test ({int a})->void <: ()->void.
+ Expect.isTrue(new C<void___a_int>() is C<void_>);
+ // Test ({int a})->void <: (int)->void.
+ Expect.isFalse(new C<void___a_int>() is C<void__int>);
+ // Test (int)->void <: ({int a})->void.
+ Expect.isFalse(new C<void__int>() is C<void___a_int>);
+ // Test ({int a})->void <: ({int a})->void.
+ Expect.isTrue(new C<void___a_int>() is C<void___a_int2>);
+ // Test ({int a})->void <: ({int b})->void.
+ Expect.isFalse(new C<void___a_int>() is C<void___b_int>);
+ // Test ({Object a})->void <: ({int a})->void.
+ Expect.isTrue(new C<void___a_Object>() is C<void___a_int>);
+ // Test ({int a})->void <: ({Object a})->void.
+ Expect.isTrue(new C<void___a_int>() is C<void___a_Object>);
+ // Test (int,{int a})->void <: (int,{int a})->void.
+ Expect.isTrue(new C<void__int__a_int>() is C<void__int__a_int2>);
+ // Test ({int a})->void <: ({double a})->void.
+ Expect.isFalse(new C<void___a_int>() is C<void___a_double>);
+ // Test ({int a})->void <: ({int a,int b})->void.
+ Expect.isFalse(new C<void___a_int>() is C<void___a_int_b_int>);
+ // Test ({int a,int b})->void <: ({int a})->void.
+ Expect.isTrue(new C<void___a_int_b_int>() is C<void___a_int>);
+ // Test ({int a,int b,int c})->void <: ({int a,int c})->void.
+ Expect.isTrue(new C<void___a_int_b_int_c_int>() is C<void___a_int_c_int>);
+ // Test ({int a,int b,int c})->void <: ({int b,int c})->void.
+ Expect.isTrue(new C<void___a_int_b_int_c_int>() is C<void___b_int_c_int>);
+ // Test ({int a,int b,int c})->void <: ({int c})->void.
+ Expect.isTrue(new C<void___a_int_b_int_c_int>() is C<void___c_int>);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_not0_test.dart b/tests/language/function_subtype_not0_test.dart
new file mode 100644
index 0000000..7b8d864
--- /dev/null
+++ b/tests/language/function_subtype_not0_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check negative function subtyping tests.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+void bar(int i) {}
+
+void main() {
+ Expect.isFalse(bar is! Foo);
+ Expect.isTrue(bar is! Foo<bool>);
+ Expect.isFalse(bar is! Foo<int>);
+ Expect.isFalse(bar is! Bar);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_not1_test.dart b/tests/language/function_subtype_not1_test.dart
new file mode 100644
index 0000000..453197b5
--- /dev/null
+++ b/tests/language/function_subtype_not1_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check negative function subtyping tests.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+class Class<T> {
+ void bar(T i) {}
+}
+
+void main() {
+ Expect.isFalse(new Class().bar is! Foo);
+ Expect.isFalse(new Class().bar is! Foo<bool>);
+ Expect.isFalse(new Class().bar is! Foo<int>);
+ Expect.isFalse(new Class().bar is! Bar);
+
+ Expect.isFalse(new Class<int>().bar is! Foo);
+ Expect.isTrue(new Class<int>().bar is! Foo<bool>);
+ Expect.isFalse(new Class<int>().bar is! Foo<int>);
+ Expect.isFalse(new Class<int>().bar is! Bar);
+
+ Expect.isFalse(new Class<bool>().bar is! Foo);
+ Expect.isFalse(new Class<bool>().bar is! Foo<bool>);
+ Expect.isTrue(new Class<bool>().bar is! Foo<int>);
+ Expect.isTrue(new Class<bool>().bar is! Bar);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_not2_test.dart b/tests/language/function_subtype_not2_test.dart
new file mode 100644
index 0000000..c6daab5
--- /dev/null
+++ b/tests/language/function_subtype_not2_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check negative function subtyping tests.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+class Class<T> {
+ test(bool expectedResult, var o, String typeName) {
+ Expect.equals(expectedResult, o is! Foo<T>, "bar is! Foo<$typeName>");
+ Expect.isFalse(o is! Bar, "bar is! Bar");
+ }
+}
+
+void bar(int i) {}
+
+void main() {
+ new Class().test(false, bar, "dynamic");
+ new Class<int>().test(false, bar, "int");
+ new Class<bool>().test(true, bar, "bool");
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_not3_test.dart b/tests/language/function_subtype_not3_test.dart
new file mode 100644
index 0000000..27ff796
--- /dev/null
+++ b/tests/language/function_subtype_not3_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check negative function subtyping tests.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo<T>(T t);
+typedef void Bar(int i);
+
+class Class<T> {
+ test(bool expectedResult, var o, String typeName) {
+ void local() {
+ Expect.equals(expectedResult, o is! Foo<T>, "bar is! Foo<$typeName>");
+ Expect.isFalse(o is! Bar, "bar is! Bar");
+ }
+ local();
+ }
+}
+
+void bar(int i) {}
+
+void main() {
+ new Class().test(false, bar, "dynamic");
+ new Class<int>().test(false, bar, "int");
+ new Class<bool>().test(true, bar, "bool");
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_null.dart b/tests/language/function_subtype_null.dart
new file mode 100644
index 0000000..c235b81
--- /dev/null
+++ b/tests/language/function_subtype_null.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for null.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo(bool a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+
+main() {
+ Expect.isFalse(null is Foo, 'null is Foo');
+ Expect.isFalse(null is Bar<bool>, 'null is Bar<bool>');
+ Expect.isFalse(null is Bar, 'null is Bar');
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_optional1_test.dart b/tests/language/function_subtype_optional1_test.dart
new file mode 100644
index 0000000..f66fe14
--- /dev/null
+++ b/tests/language/function_subtype_optional1_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+void void_() {}
+void void__int(int i) {}
+void void___int([int i]) {}
+void void___int2([int i]) {}
+void void___Object([Object o]) {}
+void void__int__int(int i1, [int i2]) {}
+void void__int__int2(int i1, [int i2]) {}
+void void__int__int_int(int i1, [int i2, int i3]) {}
+void void___double(double d) {}
+void void___int_int([int i1, int i2]) {}
+void void___int_int_int([int i1, int i2, int i3]) {}
+void void___Object_int([Object o, int i]) {}
+
+typedef void t_void_();
+typedef void t_void__int(int i);
+typedef void t_void___int([int i]);
+typedef void t_void___int2([int i]);
+typedef void t_void___Object([Object o]);
+typedef void t_void__int__int(int i1, [int i2]);
+typedef void t_void__int__int2(int i1, [int i2]);
+typedef void t_void__int__int_int(int i1, [int i2, int i3]);
+typedef void t_void___double(double d);
+typedef void t_void___int_int([int i1, int i2]);
+typedef void t_void___int_int_int([int i1, int i2, int i3]);
+typedef void t_void___Object_int([Object o, int i]);
+
+main() {
+ // Test ([int])->void <: ()->void.
+ Expect.isTrue(void___int is t_void_);
+ // Test ([int])->void <: (int)->void.
+ Expect.isTrue(void___int is t_void__int);
+ // Test (int)->void <: ([int])->void.
+ Expect.isFalse(void__int is t_void___int);
+ // Test ([int])->void <: ([int])->void.
+ Expect.isTrue(void___int is t_void___int2);
+ // Test ([Object])->void <: ([int])->void.
+ Expect.isTrue(void___Object is t_void___int);
+ // Test ([int])->void <: ([Object])->void.
+ Expect.isTrue(void___int is t_void___Object);
+ // Test (int,[int])->void <: (int)->void.
+ Expect.isTrue(void__int__int is t_void__int);
+ // Test (int,[int])->void <: (int,[int])->void.
+ Expect.isTrue(void__int__int is t_void__int__int2);
+ // Test (int)->void <: ([int])->void.
+ Expect.isFalse(void__int is t_void___int);
+ // Test ([int,int])->void <: (int)->void.
+ Expect.isTrue(void___int_int is t_void__int);
+ // Test ([int,int])->void <: (int,[int])->void.
+ Expect.isTrue(void___int_int is t_void__int__int);
+ // Test ([int,int])->void <: (int,[int,int])->void.
+ Expect.isFalse(void___int_int is t_void__int__int_int);
+ // Test ([int,int,int])->void <: (int,[int,int])->void.
+ Expect.isTrue(void___int_int_int is t_void__int__int_int);
+ // Test ([int])->void <: ([double])->void.
+ Expect.isFalse(void___int is t_void___double);
+ // Test ([int])->void <: ([int,int])->void.
+ Expect.isFalse(void___int is t_void___int_int);
+ // Test ([int,int])->void <: ([int])->void.
+ Expect.isTrue(void___int_int is t_void___int);
+ // Test ([Object,int])->void <: ([int])->void.
+ Expect.isTrue(void___Object_int is t_void___int);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_optional2_test.dart b/tests/language/function_subtype_optional2_test.dart
new file mode 100644
index 0000000..4ca61e8
--- /dev/null
+++ b/tests/language/function_subtype_optional2_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+typedef void void_();
+typedef void void__int(int i);
+typedef void void___int([int i]);
+typedef void void___int2([int i]);
+typedef void void___Object([Object o]);
+typedef void void__int__int(int i1, [int i2]);
+typedef void void__int__int2(int i1, [int i2]);
+typedef void void__int__int_int(int i1, [int i2, int i3]);
+typedef void void___double(double d);
+typedef void void___int_int([int i1, int i2]);
+typedef void void___int_int_int([int i1, int i2, int i3]);
+typedef void void___Object_int([Object o, int i]);
+
+main() {
+ // Test ([int])->void <: ()->void.
+ Expect.isTrue(new C<void___int>() is C<void_>);
+ // Test ([int])->void <: (int)->void.
+ Expect.isTrue(new C<void___int>() is C<void__int>);
+ // Test (int)->void <: ([int])->void.
+ Expect.isFalse(new C<void__int>() is C<void___int>);
+ // Test ([int])->void <: ([int])->void.
+ Expect.isTrue(new C<void___int>() is C<void___int2>);
+ // Test ([Object])->void <: ([int])->void.
+ Expect.isTrue(new C<void___Object>() is C<void___int>);
+ // Test ([int])->void <: ([Object])->void.
+ Expect.isTrue(new C<void___int>() is C<void___Object>);
+ // Test (int,[int])->void <: (int)->void.
+ Expect.isTrue(new C<void__int__int>() is C<void__int>);
+ // Test (int,[int])->void <: (int,[int])->void.
+ Expect.isTrue(new C<void__int__int>() is C<void__int__int2>);
+ // Test (int)->void <: ([int])->void.
+ Expect.isFalse(new C<void__int>() is C<void___int>);
+ // Test ([int,int])->void <: (int)->void.
+ Expect.isTrue(new C<void___int_int>() is C<void__int>);
+ // Test ([int,int])->void <: (int,[int])->void.
+ Expect.isTrue(new C<void___int_int>() is C<void__int__int>);
+ // Test ([int,int])->void <: (int,[int,int])->void.
+ Expect.isFalse(new C<void___int_int>() is C<void__int__int_int>);
+ // Test ([int,int,int])->void <: (int,[int,int])->void.
+ Expect.isTrue(new C<void___int_int_int>() is C<void__int__int_int>);
+ // Test ([int])->void <: ([double])->void.
+ Expect.isFalse(new C<void___int>() is C<void___double>);
+ // Test ([int])->void <: ([int,int])->void.
+ Expect.isFalse(new C<void___int>() is C<void___int_int>);
+ // Test ([int,int])->void <: ([int])->void.
+ Expect.isTrue(new C<void___int_int>() is C<void___int>);
+ // Test ([Object,int])->void <: ([int])->void.
+ Expect.isTrue(new C<void___Object_int>() is C<void___int>);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_setter0_test.dart b/tests/language/function_subtype_setter0_test.dart
new file mode 100644
index 0000000..7f48f1b
--- /dev/null
+++ b/tests/language/function_subtype_setter0_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for implicit setters.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo();
+class A<T> {}
+
+class C {
+ Foo foo;
+ A<int> bar;
+}
+
+class D {
+ Foo foo;
+ A<int> bar;
+}
+
+test(var c) {
+ bool inCheckedMode = false;
+ try {
+ var x = 42;
+ String a = x;
+ } catch (e) {
+ inCheckedMode = true;
+ }
+ if (inCheckedMode) {
+ Expect.throws(() => c.foo = 1, (e) => true);
+ }
+ c.foo = () {};
+}
+
+void main() {
+ test(new C());
+ test(new D());
+}
diff --git a/tests/language/function_subtype_top_level0_test.dart b/tests/language/function_subtype_top_level0_test.dart
new file mode 100644
index 0000000..7e68c05
--- /dev/null
+++ b/tests/language/function_subtype_top_level0_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for top level functions.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo(bool a, [String b]);
+typedef int Bar(bool a, [String b]);
+typedef int Baz(bool a, {String b});
+typedef int Boz(bool a);
+
+int foo(bool a, [String b]) => null;
+int baz(bool a, {String b}) => null;
+int boz(bool a, {int b}) => null;
+
+main() {
+ Expect.isTrue(foo is Foo, 'foo is Foo');
+ Expect.isTrue(foo is Bar, 'foo is Bar');
+ Expect.isFalse(foo is Baz, 'foo is Baz');
+ Expect.isTrue(foo is Boz, 'foo is Boz');
+
+ Expect.isFalse(baz is Foo, 'foo is Foo');
+ Expect.isFalse(baz is Bar, 'foo is Bar');
+ Expect.isTrue(baz is Baz, 'foo is Baz');
+ Expect.isTrue(baz is Boz, 'foo is Boz');
+
+ Expect.isFalse(boz is Foo, 'foo is Foo');
+ Expect.isFalse(boz is Bar, 'foo is Bar');
+ Expect.isFalse(boz is Baz, 'foo is Baz');
+ Expect.isTrue(boz is Boz, 'foo is Boz');
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_top_level1_test.dart b/tests/language/function_subtype_top_level1_test.dart
new file mode 100644
index 0000000..b82bea1
--- /dev/null
+++ b/tests/language/function_subtype_top_level1_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for top level functions.
+
+import 'package:expect/expect.dart';
+
+typedef int Foo<T>(T a, [String b]);
+typedef int Bar<T>(T a, [String b]);
+typedef int Baz<T>(T a, {String b});
+typedef int Boz<T>(T a);
+
+int foo(bool a, [String b]) => null;
+int baz(bool a, {String b}) => null;
+int boz(bool a, {int b}) => null;
+
+class C<T> {
+ void test(String nameOfT, bool expectedResult) {
+ Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.equals(expectedResult, foo is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(foo is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, foo is Boz<T>, 'foo is Boz<$nameOfT>');
+
+ Expect.isFalse(baz is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.isFalse(baz is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.equals(expectedResult, baz is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, baz is Boz<T>, 'foo is Boz<$nameOfT>');
+
+ Expect.isFalse(boz is Foo<T>, 'foo is Foo<$nameOfT>');
+ Expect.isFalse(boz is Bar<T>, 'foo is Bar<$nameOfT>');
+ Expect.isFalse(boz is Baz<T>, 'foo is Baz<$nameOfT>');
+ Expect.equals(expectedResult, boz is Boz<T>, 'foo is Boz<$nameOfT>');
+ }
+}
+
+main() {
+ new C<bool>().test('bool', true);
+ new C<int>().test('int', false);
+ new C().test('dynamic', true);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_typearg0_test.dart b/tests/language/function_subtype_typearg0_test.dart
new file mode 100644
index 0000000..58f9d98
--- /dev/null
+++ b/tests/language/function_subtype_typearg0_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping with type variables in factory constructors.
+
+import 'package:expect/expect.dart';
+
+typedef void Foo();
+
+class A<T> {
+ bool foo(a) => a is T;
+}
+
+void bar1() {}
+void bar2(i) {}
+
+void main() {
+ void bar3() {}
+ void bar4(i) {}
+
+ Expect.isTrue(new A<Foo>().foo(bar1));
+ Expect.isFalse(new A<Foo>().foo(bar2));
+ Expect.isTrue(new A<Foo>().foo(bar3));
+ Expect.isFalse(new A<Foo>().foo(bar4));
+ Expect.isTrue(new A<Foo>().foo((){}));
+ Expect.isFalse(new A<Foo>().foo((i){}));
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_typearg1_test.dart b/tests/language/function_subtype_typearg1_test.dart
new file mode 100644
index 0000000..5575b91
--- /dev/null
+++ b/tests/language/function_subtype_typearg1_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of type arguments.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+class I {}
+class J extends I {}
+
+typedef void f1(C<J> c);
+typedef void f2(C<I> c);
+
+main() {
+ Expect.isTrue(new C<f2>() is C<f1>);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_typearg2_test.dart b/tests/language/function_subtype_typearg2_test.dart
new file mode 100644
index 0000000..0859133
--- /dev/null
+++ b/tests/language/function_subtype_typearg2_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of type arguments.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+class I {}
+class J extends I {}
+
+typedef void f1(C<J> c);
+typedef void f2(C<I> c);
+
+main() {
+ Expect.isTrue(new C<f1>() is C<f2>);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_typearg3_test.dart b/tests/language/function_subtype_typearg3_test.dart
new file mode 100644
index 0000000..723e090
--- /dev/null
+++ b/tests/language/function_subtype_typearg3_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of type arguments.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+class I {}
+class J extends I {}
+
+typedef J f1();
+typedef I f2();
+
+main() {
+ Expect.isTrue(new C<f1>() is C<f2>);
+}
\ No newline at end of file
diff --git a/tests/language/function_subtype_typearg4_test.dart b/tests/language/function_subtype_typearg4_test.dart
new file mode 100644
index 0000000..6d95de5
--- /dev/null
+++ b/tests/language/function_subtype_typearg4_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping of type arguments.
+
+import 'package:expect/expect.dart';
+
+class C<T> {}
+
+class I {}
+class J extends I {}
+
+typedef I f1();
+typedef J f2();
+
+main() {
+ Expect.isTrue(new C<f1>() is C<f2>);
+}
\ No newline at end of file
diff --git a/tests/language/int2_test.dart b/tests/language/int2_test.dart
new file mode 100644
index 0000000..633bd10
--- /dev/null
+++ b/tests/language/int2_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+// Regression test for dart2js that used to throw NoSuchMethod if an
+// int did not fit in the SMI range.
+
+import "package:expect/expect.dart";
+
+main() {
+ // dart2js knows that this list is int or null.
+ var b = [null, 10000000000000000000000000000000000000];
+
+ // Use b[1] twice to ensure dart2js realizes it's the same value
+ // after type propagation.
+
+ // dart2js will inline an ArgumentError check on b[a].
+ 42 + b[1];
+ // dart2js will inline a NoSuchMethodError check.
+ var c = b[1] & 1;
+ Expect.equals(0, c);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index e55fc34..ad8bd91 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -459,7 +459,6 @@
closure_in_initializer_test: Fail
super_first_constructor_test: Fail
# VM specific tests.
-disable_privacy_test: Pass, Fail, Ok
# This test hard codes name of file being run and precise position.
generic_test: Fail, Ok
# Minified mode failures.
@@ -515,6 +514,49 @@
bound_closure_equality_test: Fail # Issue 10849
[ $compiler == dart2dart && $minified ]
+dynamic_test: Fail # dartbug.com/11468
+function_subtype_bound_closure0_test: Fail # dartbug.com/11468
+function_subtype_bound_closure1_test: Fail # dartbug.com/11468
+function_subtype_bound_closure2_test: Fail # dartbug.com/11468
+function_subtype_bound_closure5_test: Fail # dartbug.com/11468
+function_subtype_bound_closure6_test: Fail # dartbug.com/11468
+function_subtype_bound_closure7_test: Fail # dartbug.com/11468
+function_subtype_cast0_test: Fail # dartbug.com/11468
+function_subtype_cast1_test: Fail # dartbug.com/11468
+function_subtype_cast2_test: Fail # dartbug.com/11468
+function_subtype_cast3_test: Fail # dartbug.com/11468
+function_subtype_factory0_test: Fail # dartbug.com/11468
+function_subtype_local1_test: Fail # dartbug.com/11468
+function_subtype_local5_test: Fail # dartbug.com/11468
+function_subtype_not0_test: Fail # dartbug.com/11468
+function_subtype_not1_test: Fail # dartbug.com/11468
+function_subtype_not2_test: Fail # dartbug.com/11468
+function_subtype_not3_test: Fail # dartbug.com/11468
+function_subtype_top_level1_test: Fail # dartbug.com/11468
+function_type_alias2_test: Fail # dartbug.com/11468
+function_type_alias3_test: Fail # dartbug.com/11468
+function_type_alias4_test: Fail # dartbug.com/11468
+function_type_alias6_test: Fail # dartbug.com/11468
+function_type_alias_test: Fail # dartbug.com/11468
+method_override_test: Fail # dartbug.com/11468
+
+function_subtype0_test: Fail # dartbug.com/11467
+function_subtype1_test: Fail # dartbug.com/11467
+function_subtype_bound_closure3_test: Fail # dartbug.com/11467
+function_subtype_bound_closure4_test: Fail # dartbug.com/11467
+function_subtype_call0_test: Fail # dartbug.com/11467
+function_subtype_call1_test: Fail # dartbug.com/11467
+function_subtype_call2_test: Fail # dartbug.com/11467
+function_subtype_inline0_test: Fail # dartbug.com/11467
+function_subtype_local0_test: Fail # dartbug.com/11467
+function_subtype_local2_test: Fail # dartbug.com/11467
+function_subtype_local3_test: Fail # dartbug.com/11467
+function_subtype_local4_test: Fail # dartbug.com/11467
+function_subtype_named1_test: Fail # dartbug.com/11467
+function_subtype_named2_test: Fail # dartbug.com/11467
+function_subtype_optional1_test: Fail # dartbug.com/11467
+function_subtype_optional2_test: Fail # dartbug.com/11467
+function_subtype_top_level0_test: Fail # dartbug.com/11467
super_getter_setter_test: Fail # Issue 11065.
@@ -526,44 +568,27 @@
invocation_mirror_test: Fail, OK # hardcoded names.
super_call4_test: Fail, OK # hardcoded names.
+
[ $arch == simarm || $arch == arm ]
-bit_operations_test: Crash, Fail
deopt_smi_op_test: Fail
gc_test: Crash
invocation_mirror_test: Fail
-load_to_load_forwarding_vm_test: Fail
-named_parameters_with_conversions_test: Pass, Crash
-arithmetic_test: Pass, Crash, Fail # Fails on Mac
-left_shift_test: Pass, Fail # Fails on Mac
-positive_bit_operations_test: Pass, Fail, Crash # Fails and crashes on Mac
+named_parameters_with_conversions_test: Pass, Crash # Passes on Mac.
+stack_overflow_test: Crash, Pass # Passes on HW in release mode.
+stack_overflow_stacktrace_test: Crash, Pass # Passes on HW in release mode.
-# large_implicit_getter_test Passes on ReleaseARM, Crashes in SIMARM and
-# DebugARM. Should crash on ReleaseARM, but there is no exception on an
-# unaligned access. stack_overflow_test and _stacktrace_test have the same
-# problem.
-large_implicit_getter_test: Crash, Pass
-stack_overflow_test: Crash, Pass
-stack_overflow_stacktrace_test: Crash, Pass
-
-[ ($arch == simarm || $arch == arm) && $mode == debug ]
-char_escape_test: Pass, Crash
-
[ $arch == mips ]
*: Skip
+
[ $arch == simmips ]
-arithmetic_test: Fail, Crash
-bit_operations_test: Crash, Fail
-char_escape_test: Pass, Crash
+arithmetic_test: Crash # Too far relative branch.
deopt_smi_op_test: Fail
-div_with_power_of_two_test: Fail
gc_test: Crash
invocation_mirror_test: Fail
+large_implicit_getter_test: Crash
load_to_load_forwarding_vm_test: Fail
named_parameters_with_conversions_test: Pass, Crash
-positive_bit_operations_test: Pass, Fail, Crash
-left_shift_test: Pass, Fail
-large_implicit_getter_test: Crash, Pass
-stack_overflow_test: Crash, Pass
-stack_overflow_stacktrace_test: Crash, Pass
+stack_overflow_test: Crash
+stack_overflow_stacktrace_test: Crash
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 27a984d..2d51605 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -10,9 +10,6 @@
bad_named_parameters_test: fail
bad_override_test/01: fail
bad_override_test/02: fail
-bad_override_test/03: fail
-bad_override_test/04: fail
-bad_override_test/05: fail
black_listed_test/11: fail
body_less_constructor_wrong_arg_negative_test: fail
built_in_identifier_prefix_test: fail
@@ -42,7 +39,6 @@
compile_time_constant_checked3_test/04: fail
compile_time_constant_checked3_test/06: fail
compile_time_constant_e_test: fail
-const_syntax_test/06: fail
constructor2_negative_test: fail
constructor3_negative_test: fail
constructor_call_wrong_argument_count_negative_test: fail
@@ -64,8 +60,6 @@
factory5_test/00: fail
factory_implementation_test/none: fail
factory_redirection2_test/01: fail
-fauxverride_test/03: fail
-fauxverride_test/05: fail
field_method4_negative_test: fail
field_override_test/01: fail
final_for_in_variable_test/01: fail
@@ -89,10 +83,7 @@
implicit_this_test/01: fail
implicit_this_test/04: fail
import_combinators_negative_test: fail
-inst_field_initializer1_negative_test: fail
instance_call_wrong_argument_count_negative_test: fail
-instance_method2_negative_test: fail
-instance_method_negative_test: fail
instantiate_type_variable_negative_test: fail
interface_static_non_final_fields_negative_test: fail
interface_test/00: fail
@@ -127,15 +118,9 @@
no_such_method_negative_test: fail
non_const_super_negative_test: fail
number_identifier_negative_test: fail
-override_field_method1_negative_test: fail
-override_field_method2_negative_test: fail
-override_field_method4_negative_test: fail
-override_field_method5_negative_test: fail
override_field_test/01: fail
override_field_test/02: fail
override_field_test/03: fail
-override_method_with_field_test/01: fail
-override_method_with_field_test/02: fail
prefix10_negative_test: fail
prefix11_negative_test: fail
prefix12_negative_test: fail
@@ -154,7 +139,6 @@
pseudo_kw_illegal_test/14: fail
pseudo_kw_test: fail
redirecting_factory_infinite_steps_test/01: fail
-redirecting_factory_infinite_steps_test/02: fail
scope_negative_test: fail
setter3_test/01: fail
setter3_test/02: fail
@@ -186,13 +170,8 @@
type_variable_bounds2_test/04: fail
type_variable_bounds2_test/06: fail
type_variable_bounds_test/00: fail
-type_variable_bounds_test/01: fail
-type_variable_bounds_test/02: fail
type_variable_bounds_test/03: fail
type_variable_bounds_test/04: fail
-type_variable_bounds_test/06: fail
-type_variable_bounds_test/07: fail
-type_variable_bounds_test/09: fail
type_variable_identifier_expression_negative_test: fail
type_variable_static_context_negative_test: fail
unresolved_in_factory_negative_test: fail
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status
index be8fb29..4043be7 100644
--- a/tests/language/language_analyzer2.status
+++ b/tests/language/language_analyzer2.status
@@ -135,7 +135,6 @@
override_field_test/02: fail
override_field_test/03: fail
override_method_with_field_test/01: fail
-override_method_with_field_test/02: fail
prefix10_negative_test: fail
prefix11_negative_test: fail
prefix12_negative_test: fail
@@ -173,7 +172,6 @@
syntax_test/31: fail
syntax_test/32: fail
syntax_test/33: fail
-ternary_test: fail
throw7_negative_test: fail
type_error_test: fail
type_parameter_test/01: fail
@@ -196,8 +194,6 @@
type_variable_bounds_test/09: fail
type_variable_identifier_expression_negative_test: fail
type_variable_static_context_negative_test: fail
-unary2_test: fail
-unary_test: fail
unresolved_in_factory_negative_test: fail
unresolved_top_level_method_negative_test: fail
unresolved_top_level_var_negative_test: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index cab3e41..a21901b 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -39,9 +39,6 @@
*vm_negative_test: Skip
[ $compiler == dart2js && $checked ]
-function_type_alias6_test: Crash # dartbug.com/9792
-
-prefix16_test: Fail # dartbug.com/7354
default_factory2_test/01: Fail
type_variable_bounds_test/01: Fail
type_variable_bounds_test/02: Fail
@@ -56,13 +53,13 @@
f_bounded_quantification_test/02: Fail
closure_type_test: Fail # does not detect type error in checked mode.
type_annotation_test/09: Fail # Named constructors interpreted as a type.
-prefix15_test: Fail # Issue 5022
-local_function2_test: Fail # Issue 5022
+function_subtype_setter0_test: Fail # dartbug.com/11273
[ $compiler == dart2js && $unchecked ]
factory_redirection_test/14: Fail # redirecting to redirecting factory
type_checks_in_factory_method_test: Fail # Expect.equals(expected: <true>, actual: <false>) fails. -- checked mode test.
+prefix16_test: Fail # dartbug.com/9056
assertion_test: Fail
type_variable_bounds_test/07: Fail # Wrongly reports compile-time error.
@@ -87,6 +84,7 @@
compile_time_constant_checked3_test/06: Fail, OK
[ $compiler == dart2js ]
+function_type_alias6_test: Crash # dartbug.com/9792
branch_canonicalization_test: Fail # Issue 638.
div_with_power_of_two_test: Fail # Issue 8301.
class_literal_test: Fail # Issue 7626.
@@ -122,30 +120,19 @@
infinity_test: Fail # Issue 4984
positive_bit_operations_test: Fail # (floitsch): This will be fixed when dart2js uses unsigned input for >>.
-compile_time_constant8_test: Fail # We don't take the generic type into account yet.
-canonical_const_test: Fail # We don't take the generic type into account yet.
# Support for optional parameters not conform to latest spec.
-function_type_alias_test: Fail # http://dartbug.com/9058
-function_type_alias2_test: Fail
named_parameters_type_test: Fail
positional_parameters_type_test: Fail
# Compilation errors.
const_var_test: Fail # Map literals take 2 type arguments.
map_literal3_test: Fail # Map literals take 2 type arguments.
-ct_const_test: Fail # We don't take the generic type into account yet.
-dynamic_test: Fail # cannot resolve type F1
constructor_redirect2_test/03: Fail # redirecting ctor with initializing formal
-factory3_test: Fail # internal error: visitIs for type variables not implemented
-function_type_alias2_test: Fail # cannot resolve type f1
-function_type_alias3_test: Fail # cannot resolve type F
-function_type_alias4_test: Fail # cannot resolve type F
function_type_alias5_test/00: Fail # visitIs for typedefs not implemented
function_type_alias5_test/01: Fail # visitIs for typedefs not implemented
function_type_alias5_test/02: Fail # visitIs for typedefs not implemented
function_type_alias7_test/00: Fail # wrongly accepts default values in typedef
-function_type_alias_test: Fail # cannot resolve type Fun
generic_test: Fail # cannot resolve type T
get_set_syntax_test/00: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
get_set_syntax_test/01: Fail # Fixed by https://chromiumcodereview.appspot.com/10915111
@@ -241,9 +228,7 @@
interface_factory3_negative_test: Fail # Negative language test.
interface_factory_constructor_negative_test: Fail # Negative language test.
list_literal1_negative_test: Fail # Negative language test.
-list_literal2_negative_test: Fail # Negative language test.
map_literal1_negative_test: Fail # Negative language test.
-map_literal2_negative_test: Fail # Negative language test.
number_identifier_negative_test: Fail # Negative language test.
operator1_negative_test: Fail # Negative language test.
prefix23_negative_test: Fail # Negative language test.
@@ -262,7 +247,6 @@
string_interpolation7_negative_test: Fail # Negative language test.
throw7_negative_test: Fail # Negative language test.
-disable_privacy_test: Fail, OK # VM specific test.
numbers_test: Fail, OK # (unintended?) VM specific test.
final_syntax_test/01: Fail # Missing error for uninitialized final field.
@@ -303,9 +287,9 @@
double_to_string_as_fixed_test: Fail
double_to_string_as_precision3_test: Fail
expect_test: Fail
-factory3_test: Fail
stack_overflow_test: Fail
stack_overflow_stacktrace_test: Fail
+inlined_throw_test: Fail # BUG(11480): Triage.
[ $compiler == dart2js && $runtime == safari ]
@@ -327,3 +311,6 @@
string_interpolate_npe_test: Fail
closure_call_wrong_argument_count_negative_test: Skip
label_test: Skip
+
+[ $compiler == dart2js && $minified ]
+function_subtype_inline0_test: Fail # Issue 11469
diff --git a/tests/language/load_to_load_forwarding_vm_test.dart b/tests/language/load_to_load_forwarding_vm_test.dart
index b77854f..2f0a766 100644
--- a/tests/language/load_to_load_forwarding_vm_test.dart
+++ b/tests/language/load_to_load_forwarding_vm_test.dart
@@ -51,7 +51,6 @@
return arr.length;
}
-
testPhiRepresentation(f, arr) {
if (f) {
arr[0] = arr[0] + arr[1];
@@ -61,7 +60,6 @@
return arr[0];
}
-
testPhiConvertions(f, arr) {
if (f) {
arr[0] = arr[1];
@@ -71,6 +69,130 @@
return arr[0];
}
+class M {
+ var x;
+ M(this.x);
+}
+
+fakeAliasing(arr) {
+ var a = new M(10);
+ var b = new M(10);
+ var c = arr.length;
+
+ if (c * c != c * c) {
+ arr[0] = a; // Escape.
+ arr[0] = b;
+ }
+
+ return c * c; // Deopt point.
+}
+
+class X {
+ var next;
+ X(this.next);
+}
+
+testPhiForwarding(obj) {
+ if (obj.next == null) {
+ return 1;
+ }
+
+ var len = 0;
+ while (obj != null) {
+ len++;
+ obj = obj.next; // This load should not be forwarded.
+ }
+
+ return len;
+}
+
+testPhiForwarding2(obj) {
+ if (obj.next == null) {
+ return 1;
+ }
+
+ var len = 0, next = null;
+ while ((obj != null) && len < 2) {
+ len++;
+ obj = obj.next; // This load should be forwarded.
+ next = obj.next;
+ }
+
+ return len;
+}
+
+class V {
+ final f;
+ V(this.f);
+}
+
+testPhiForwarding3() {
+ var a = new V(-0.1);
+ var c = new V(0.0);
+ var b = new V(0.1);
+
+ for (var i = 0; i < 3; i++) {
+ var af = a.f;
+ var bf = b.f;
+ var cf = c.f;
+ a = new V(cf);
+ b = new V(af);
+ c = new V(bf);
+ }
+
+ Expect.equals(-0.1, a.f);
+ Expect.equals(0.1, b.f);
+ Expect.equals(0.0, c.f);
+}
+
+testPhiForwarding4() {
+ var a = new V(-0.1);
+ var b = new V(0.1);
+ var c = new V(0.0);
+
+ var result = new List(9);
+ for (var i = 0, j = 0; i < 3; i++) {
+ result[j++] = a.f;
+ result[j++] = b.f;
+ result[j++] = c.f;
+ var xa = a;
+ var xb = b;
+ a = c;
+ b = xa;
+ c = xb;
+ }
+
+ Expect.listEquals([-0.1, 0.1, 0.0,
+ 0.0, -0.1, 0.1,
+ 0.1, 0.0, -0.1], result);
+}
+
+class U {
+ var x, y;
+ U() : x = 0, y = 0;
+}
+
+testEqualPhisElimination() {
+ var u = new U();
+ var v = new U();
+ var sum = 0;
+ for (var i = 0; i < 3; i++) {
+ u.x = i;
+ u.y = i;
+ if ((i & 1) == 1) {
+ v.x = i + 1;
+ v.y = i + 1;
+ } else {
+ v.x = i - 1;
+ v.y = i - 1;
+ }
+ sum += v.x + v.y;
+ }
+ Expect.equals(4, sum);
+ Expect.equals(2, u.x);
+ Expect.equals(2, u.y);
+}
+
main() {
final fixed = new List(10);
final growable = [];
@@ -82,12 +204,19 @@
testPhiRepresentation(true, f64List);
testPhiRepresentation(false, f64List);
+ final obj = new X(new X(new X(null)));
+
for (var i = 0; i < 2000; i++) {
Expect.listEquals([0x02010000, 0x03020100], foo(new A(0, 0)));
Expect.listEquals([0x02010000, 0x03020100], bar(new A(0, 0), false));
Expect.listEquals([0x04020000, 0x03020100], bar(new A(0, 0), true));
testImmutableVMFields(fixed, true);
testPhiRepresentation(true, f64List);
+ testPhiForwarding(obj);
+ testPhiForwarding2(obj);
+ testPhiForwarding3();
+ testPhiForwarding4();
+ testEqualPhisElimination();
}
Expect.equals(1, testImmutableVMFields([], false));
@@ -99,9 +228,14 @@
u32List[0] = 0;
u32List[1] = 0x3FFFFFFF;
u32List[2] = 0x7FFFFFFF;
-
+
for (var i = 0; i < 4000; i++) {
testPhiConvertions(true, u32List);
testPhiConvertions(false, u32List);
}
+
+ final escape = new List(1);
+ for (var i = 0; i < 10000; i++) {
+ fakeAliasing(escape);
+ }
}
diff --git a/tests/language/mixin_regress_11398_test.dart b/tests/language/mixin_regress_11398_test.dart
new file mode 100644
index 0000000..0336db4
--- /dev/null
+++ b/tests/language/mixin_regress_11398_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+void main() {
+ var hva = new HasValueA();
+ hva.value = '42';
+ Expect.equals('42', hva.value);
+
+ var hvb = new HasValueB();
+ hvb.value = '87';
+ Expect.equals('87', hvb.value);
+
+ var hvc = new HasValueC();
+ hvc.value = '99';
+ Expect.equals('99', hvc.value);
+}
+
+abstract class Delegate {
+ String invoke(String value);
+}
+
+abstract class DelegateMixin {
+ String invoke(String value) => value;
+}
+
+abstract class HasValueMixin implements Delegate {
+ String _value;
+ set value(String value) { _value = invoke(value); }
+ String get value => _value;
+}
+
+class HasValueA extends Object with HasValueMixin, DelegateMixin {
+}
+
+class HasValueB extends Object with DelegateMixin, HasValueMixin {
+}
+
+class HasValueC extends Object with HasValueMixin {
+ String invoke(String value) => value;
+}
diff --git a/tests/language/no_such_method_dispatcher_test.dart b/tests/language/no_such_method_dispatcher_test.dart
new file mode 100644
index 0000000..8686480
--- /dev/null
+++ b/tests/language/no_such_method_dispatcher_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+// VMOptions=--optimization-counter-threshold=100
+
+import "package:expect/expect.dart";
+
+// Test that noSuchMethod dispatching and auto-closurization work correctly.
+
+class A {
+ noSuchMethod(m) {
+ return 123;
+ }
+ bar(x) => x + 1;
+}
+
+class B extends A { }
+
+main() {
+ var a = new A();
+ for (var i = 0; i < 100; ++i) Expect.equals(123, a.foo());
+ Expect.throws(() => (a.foo)());
+ Expect.equals("123", (a.foo).toString());
+
+ var b = new B();
+ for (var i = 0; i < 100; ++i) {
+ Expect.equals(2, b.bar(1));
+ Expect.equals(123, b.bar());
+ Expect.equals(2, b.bar(1));
+ }
+}
+
diff --git a/tests/language/type_variable_closure_test.dart b/tests/language/type_variable_closure_test.dart
new file mode 100644
index 0000000..7fd7381
--- /dev/null
+++ b/tests/language/type_variable_closure_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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 "package:expect/expect.dart";
+
+class C<T> {
+ C.foo() {
+ x = (a) => a is T;
+ }
+ C.bar() {
+ x = (a) => a is! T;
+ }
+ C.baz() {
+ x = (a) => a as T;
+ }
+ var x;
+}
+
+main() {
+ Expect.isTrue(new C<int>.foo().x(1));
+ Expect.isFalse(new C<int>.foo().x('1'));
+ Expect.isFalse(new C<int>.bar().x(1));
+ Expect.isTrue(new C<int>.bar().x('1'));
+ Expect.equals(new C<int>.baz().x(1), 1);
+ Expect.throws(() => new C<int>.baz().x('1'));
+}
diff --git a/tests/lib/async/stream_first_where_test.dart b/tests/lib/async/stream_first_where_test.dart
new file mode 100644
index 0000000..41d7325
--- /dev/null
+++ b/tests/lib/async/stream_first_where_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library stream_controller_async_test;
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:isolate';
+import '../../../pkg/unittest/lib/unittest.dart';
+import 'event_helper.dart';
+import 'stream_state_helper.dart';
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ Events sentEvents = new Events()..close();
+
+ // Make sure that firstWhere allows to return instances of types that are
+ // different than the generic type of the stream.
+ test("firstWhere with super class", () {
+ StreamController c = new StreamController<B>();
+ Future f = c.stream.firstWhere((x) => false, defaultValue: () => const A());
+ f.then(expectAsync1((v) { Expect.equals(const A(), v); }));
+ sentEvents.replay(c);
+ });
+}
diff --git a/tests/lib/async/stream_last_where_test.dart b/tests/lib/async/stream_last_where_test.dart
new file mode 100644
index 0000000..c02d608
--- /dev/null
+++ b/tests/lib/async/stream_last_where_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library stream_controller_async_test;
+
+import "package:expect/expect.dart";
+import 'dart:async';
+import 'dart:isolate';
+import '../../../pkg/unittest/lib/unittest.dart';
+import 'event_helper.dart';
+import 'stream_state_helper.dart';
+
+class A { const A(); }
+class B extends A { const B(); }
+
+main() {
+ Events sentEvents = new Events()..close();
+
+ // Make sure that lastWhere allows to return instances of types that are
+ // different than the generic type of the stream.
+ test("lastWhere with super class", () {
+ StreamController c = new StreamController<B>();
+ Future f = c.stream.lastWhere((x) => false, defaultValue: () => const A());
+ f.then(expectAsync1((v) { Expect.equals(const A(), v); }));
+ sentEvents.replay(c);
+ });
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index e26f707..2488346 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -16,18 +16,19 @@
typed_data/float32x4_unbox_phi_test: Fail, OK
typed_data/float32x4_unbox_regress_test: Fail, OK
+[ $compiler == dart2js && $checked ]
+async/catch_errors20_test: Fail # Issue 11470
+
[ $compiler == dart2js && ($runtime == d8 || $runtime == ie9) ]
typed_data/byte_data_test: Fail, OK # d8/ie9 doesn't support DataView
[ $compiler == dart2js && $minified ]
-mirrors/disable_tree_shaking_test: Fail # Issue 6490
-mirrors/metadata_test: Fail
-mirrors/mirrors_resolve_fields_test: Fail # Issue 6490
mirrors/reflect_model_test: Fail # Issue 6490
-mirrors/reflectively_instantiate_uninstantiated_class_test: Fail # Issue 6490
mirrors/to_string_test: Fail # Issue 6490
[ $csp ]
+mirrors/intercepted_class_test: Fail # Issue 6490
+mirrors/intercepted_object_test: Fail # Issue 6490
mirrors/metadata_test: Fail # Issue 6490
mirrors/reflect_model_test: Fail # Issue 6490
mirrors/reflect_runtime_type_test: Fail # Issue 6490
@@ -35,9 +36,6 @@
mirrors/superclass_test: Fail # Issue 6490
mirrors/to_string_test: Fail # Issue 6490
-[ $compiler == dart2js && $checked ]
-async/stream_event_transform_test: Fail # Issue 7733.
-
[ $compiler == dart2js && $jscl ]
async/future_test: Fail # Timer interface not supported; dartbug.com/7728.
async/slow_consumer2_test: Fail # Timer interface not supported; dartbug.com/7728.
@@ -67,13 +65,8 @@
# implement timer (currently only in d8)
[ $compiler == dart2dart ]
-mirrors/metadata_test: Fail
-mirrors/mirrors_test: Fail # Issue 10957
-mirrors/library_uri_package_test: Fail # Issue 10957
+mirrors/*: Skip # http://dartbug.com/11511
async/run_async6_test: Fail # Issue 10957 - may be related to issue 10910
-mirrors/reflect_model_test: Fail # http://dartbug.com/11219
-mirrors/disable_tree_shaking_test: Fail
-mirrors/to_string_test: Fail
[ $compiler == dart2dart && $minified ]
json/json_test: Fail # Issue 10961
@@ -81,9 +74,6 @@
typed_data/float32x4_list_test: Fail # Issue 10961
typed_data/float32x4_unbox_phi_test: Fail # Issue 10961
typed_data/float32x4_unbox_regress_test: Fail # Issue 10961
-mirrors/reflect_runtime_type_test: Fail
-mirrors/reflect_uninstantiated_class_test: Fail
-
[ $runtime == ff ]
# FF setTimeout can fire early: https://bugzilla.mozilla.org/show_bug.cgi?id=291386
diff --git a/tests/lib/mirrors/constructors_test.dart b/tests/lib/mirrors/constructors_test.dart
new file mode 100644
index 0000000..1a717a7
--- /dev/null
+++ b/tests/lib/mirrors/constructors_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library test.constructors_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+import 'reflect_model_test.dart';
+
+class Foo {
+}
+
+class Bar {
+ Bar();
+}
+
+class Baz {
+ Baz.named();
+}
+
+class Biz {
+ Biz();
+ Biz.named();
+}
+
+main() {
+ MirrorSystem mirrors = currentMirrorSystem();
+ ClassMirror fooMirror = reflectClass(Foo);
+ Map<Symbol, MethodMirror> fooConstructors = fooMirror.constructors;
+ ClassMirror barMirror = reflectClass(Bar);
+ Map<Symbol, MethodMirror> barConstructors = barMirror.constructors;
+ ClassMirror bazMirror = reflectClass(Baz);
+ Map<Symbol, MethodMirror> bazConstructors = bazMirror.constructors;
+ ClassMirror bizMirror = reflectClass(Biz);
+ Map<Symbol, MethodMirror> bizConstructors = bizMirror.constructors;
+
+ expect('{Foo: Method(s(Foo) in s(Foo), constructor)}', fooConstructors);
+ expect('{Bar: Method(s(Bar) in s(Bar), constructor)}', barConstructors);
+ expect('{Baz.named: Method(s(Baz.named) in s(Baz), constructor)}',
+ bazConstructors);
+ expect('{Biz: Method(s(Biz) in s(Biz), constructor),'
+ ' Biz.named: Method(s(Biz.named) in s(Biz), constructor)}',
+ bizConstructors);
+ print(bizConstructors);
+}
diff --git a/tests/lib/mirrors/get_symbol_name_no_such_method_test.dart b/tests/lib/mirrors/get_symbol_name_no_such_method_test.dart
index 7210d98..1b60ae5 100644
--- a/tests/lib/mirrors/get_symbol_name_no_such_method_test.dart
+++ b/tests/lib/mirrors/get_symbol_name_no_such_method_test.dart
@@ -24,14 +24,12 @@
expect('foo', foo.foo);
expect('foo', foo.foo());
expect('foo', foo.foo(null));
- // TODO(ahe): Why does the following not work in dart2js/minified.
- // expect('foo', foo.foo(null, null));
+ expect('foo', foo.foo(null, null));
expect('foo', foo.foo(a: null, b: null));
expect('baz', foo.baz);
expect('baz', foo.baz());
expect('baz', foo.baz(null));
- // TODO(ahe): Why does the following not work in dart2js/minified.
- // expect('baz', foo.baz(null, null));
+ expect('baz', foo.baz(null, null));
expect('baz', foo.baz(a: null, b: null));
}
diff --git a/tests/lib/mirrors/libraries_test.dart b/tests/lib/mirrors/libraries_test.dart
new file mode 100644
index 0000000..70a5e58
--- /dev/null
+++ b/tests/lib/mirrors/libraries_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+library test.libraries_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+main() {
+ MirrorSystem mirrors = currentMirrorSystem();
+ Expect.isNotNull(mirrors, 'mirrors is null');
+
+ Map<Uri, LibraryMirror> libraries = mirrors.libraries;
+ Expect.isNotNull(libraries, 'libraries is null');
+
+ LibraryMirror mirrorsLibrary = libraries[Uri.parse('dart:mirrors')];
+ Expect.isNotNull(mirrorsLibrary, 'mirrorsLibrary is null');
+
+ print(mirrorsLibrary.classes);
+ ClassMirror cls = mirrorsLibrary.classes[const Symbol('LibraryMirror')];
+ Expect.isNotNull(cls, 'cls is null');
+
+ Expect.equals(const Symbol('dart.mirrors.LibraryMirror'), cls.qualifiedName);
+ // TODO(ahe): Enable when VM implements equality of class mirrors:
+ // Expect.equals(reflectClass(LibraryMirror), cls);
+ print(mirrorsLibrary);
+}
diff --git a/tests/lib/mirrors/library_uri_io_test.dart b/tests/lib/mirrors/library_uri_io_test.dart
index add283d..1ee7b4c 100644
--- a/tests/lib/mirrors/library_uri_io_test.dart
+++ b/tests/lib/mirrors/library_uri_io_test.dart
@@ -27,7 +27,7 @@
Uri cwd = new Uri(
scheme: 'file',
path: appendSlash(new Path(new File('.').fullPathSync()).toString()));
- Uri uri = cwd.resolve(new Path(new Options().script).toString());
+ Uri uri = cwd.resolve(new Path(Platform.script).toString());
testLibraryUri(new Class(), uri);
});
}
diff --git a/tests/lib/mirrors/mirrors_test.dart b/tests/lib/mirrors/mirrors_test.dart
index b044283..13f8587 100644
--- a/tests/lib/mirrors/mirrors_test.dart
+++ b/tests/lib/mirrors/mirrors_test.dart
@@ -208,7 +208,6 @@
if (!isMinified) // TODO(ahe): Remove this line.
test("Test field access", () { testFieldAccess(mirrors); });
test("Test closure mirrors", () { testClosureMirrors(mirrors); });
- if (!isMinified) // TODO(ahe): Remove this line.
test("Test invoke constructor", () { testInvokeConstructor(mirrors); });
test("Test current library uri", () {
testLibraryUri(new Class(),
diff --git a/tests/lib/mirrors/reflect_model_test.dart b/tests/lib/mirrors/reflect_model_test.dart
index e96124a..567651c 100644
--- a/tests/lib/mirrors/reflect_model_test.dart
+++ b/tests/lib/mirrors/reflect_model_test.dart
@@ -55,6 +55,7 @@
if (method.isStatic) buffer.write(', static');
if (method.isGetter) buffer.write(', getter');
if (method.isSetter) buffer.write(', setter');
+ if (method.isConstructor) buffer.write(', constructor');
return (buffer..write(')')).toString();
}
diff --git a/tests/standalone/53bit_overflow_test.dart b/tests/standalone/53bit_overflow_test.dart
index 256e66a..3bbc6e3 100644
--- a/tests/standalone/53bit_overflow_test.dart
+++ b/tests/standalone/53bit_overflow_test.dart
@@ -54,6 +54,9 @@
return min_literal;
}
+// We don't test for the _FiftyThreeBitOverflowError since it's not visible.
+// It's should not be visible since it doesn't exist on dart2js.
+bool is53BitError(e) => e is Error && "$e".startsWith("53-bit Overflow:");
main() {
Expect.equals(0xFFFFFFFFFFFFF, max_literal());
@@ -61,20 +64,20 @@
// Run the tests once before optimizations.
dti_arg = 1.9e16;
- Expect.throws(double_to_int, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(double_to_int, is53BitError);
ia_arg1 = (1 << 51);
ia_arg2 = (1 << 51);
- Expect.throws(integer_add, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(integer_add, is53BitError);
n_arg = -0xFFFFFFFFFFFFF - 1;
- Expect.throws(negate, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(negate, is53BitError);
is_arg = (1 << 51);
- Expect.throws(integer_shift, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(integer_shift, is53BitError);
- Expect.throws(max_add_throws, (e) => e is FiftyThreeBitOverflowError);
- Expect.throws(min_sub_throws, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(max_add_throws, is53BitError);
+ Expect.throws(min_sub_throws, is53BitError);
for (int i = 0; i < 20; i++) {
dti_arg = i.toDouble();
@@ -96,20 +99,20 @@
Expect.equals(i << 1, f());
}
- // The optimized functions should now deoptimize and throw the error.
+ // The optimized functions should now deoptimize and throw the error.
dti_arg = 1.9e16;
- Expect.throws(double_to_int, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(double_to_int, is53BitError);
ia_arg1 = (1 << 51);
ia_arg2 = (1 << 51);
- Expect.throws(integer_add, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(integer_add, is53BitError);
n_arg = -0xFFFFFFFFFFFFF - 1;
- Expect.throws(negate, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(negate, is53BitError);
is_arg = (1 << 51);
- Expect.throws(integer_shift, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(integer_shift, is53BitError);
- Expect.throws(max_add_throws, (e) => e is FiftyThreeBitOverflowError);
- Expect.throws(min_sub_throws, (e) => e is FiftyThreeBitOverflowError);
+ Expect.throws(max_add_throws, is53BitError);
+ Expect.throws(min_sub_throws, is53BitError);
}
diff --git a/tests/standalone/coverage_test.dart b/tests/standalone/coverage_test.dart
index b5a236e..b48d99b 100644
--- a/tests/standalone/coverage_test.dart
+++ b/tests/standalone/coverage_test.dart
@@ -47,11 +47,9 @@
}
void main() {
- var options = new Options();
-
// Compute paths for coverage tool and coverage target relative
// the the path of this script.
- var scriptPath = new Path(options.script).directoryPath;
+ var scriptPath = new Path(Platform.script).directoryPath;
var toolPath = scriptPath.join(new Path(coverageToolScript)).canonicalize();
targPath = scriptPath.join(new Path(coverageTargetScript)).canonicalize();
@@ -62,7 +60,7 @@
toolPath.toNativePath(),
targPath.toNativePath() ];
- Process.start(options.executable, processOpts).then((Process process) {
+ Process.start(Platform.executable, processOpts).then((Process process) {
coverageToolProcess = process;
coverageToolProcess.stdin.close();
var stdoutStringStream = coverageToolProcess.stdout
diff --git a/tests/standalone/debugger/breakpoint_resolved_test.dart b/tests/standalone/debugger/breakpoint_resolved_test.dart
index 9fef0df..4cf748b 100644
--- a/tests/standalone/debugger/breakpoint_resolved_test.dart
+++ b/tests/standalone/debugger/breakpoint_resolved_test.dart
@@ -6,14 +6,14 @@
main() {
if (RunScript(testScript)) return;
-
+
bar();
-
+
print("Hello from debuggee");
}
bar() {
-
+
print("bar");
}
diff --git a/tests/standalone/debugger/debug_lib.dart b/tests/standalone/debugger/debug_lib.dart
index 8532ac0..34500ba 100644
--- a/tests/standalone/debugger/debug_lib.dart
+++ b/tests/standalone/debugger/debug_lib.dart
@@ -231,6 +231,74 @@
}
+class LocalsMatcher extends Command {
+ Map locals = {};
+
+ LocalsMatcher(this.locals) {
+ template = {"id": 0, "command": "getStackTrace", "params": {"isolateId": 0}};
+ }
+
+ void matchResponse(Debugger debugger) {
+ super.matchResponse(debugger);
+
+ List frames = getJsonValue(debugger.currentMessage, "result:callFrames");
+ assert(frames != null);
+
+ String functionName = frames[0]['functionName'];
+ List localsList = frames[0]['locals'];
+ Map reportedLocals = {};
+ localsList.forEach((local) => reportedLocals[local['name']] = local['value']);
+ for (String key in locals.keys) {
+ if (reportedLocals[key] == null) {
+ debugger.error("Error in $functionName(): no value reported for local "
+ "variable $key");
+ return;
+ }
+ String expected = locals[key];
+ String actual = reportedLocals[key]['text'];
+ if (expected != actual) {
+ debugger.error("Error in $functionName(): got '$actual' for local "
+ "variable $key, but expected '$expected'");
+ return;
+ }
+ }
+ }
+}
+
+
+MatchLocals(Map localValues) {
+ return new LocalsMatcher(localValues);
+}
+
+
+class EventMatcher {
+ String eventName;
+ Map params;
+
+ EventMatcher(this.eventName, this.params);
+
+ void matchEvent(Debugger debugger) {
+ for (Event event in debugger.events) {
+ if (event.name == eventName) {
+ if (params == null || matchMaps(params, event.params)) {
+ // Remove the matched event, so we don't match against it in the future.
+ debugger.events.remove(event);
+ return;
+ }
+ }
+ }
+
+ String msg = params == null ? '' : params.toString();
+ debugger.error("Error: could not match event $eventName $msg");
+ }
+}
+
+
+ExpectEvent(String eventName, [Map params]) {
+ return new EventMatcher(eventName, params);
+}
+
+
class RunCommand extends Command {
RunCommand.resume() {
template = {"id": 0, "command": "resume", "params": {"isolateId": 0}};
@@ -276,6 +344,16 @@
SetBreakpoint(int line) => new SetBreakpointCommand(line);
+class Event {
+ String name;
+ Map params;
+
+ Event(Map json) {
+ name = json['event'];
+ params = json['params'];
+ }
+}
+
// A debug script is a list of Command objects.
class DebugScript {
@@ -285,6 +363,7 @@
entries.add(MatchFrame(0, "main"));
}
bool get isEmpty => entries.isEmpty;
+ bool get isNextEventMatcher => !isEmpty && currentEntry is EventMatcher;
get currentEntry => entries.last;
advance() => entries.removeLast();
add(entry) => entries.add(entry);
@@ -301,6 +380,7 @@
int seqNr = 0; // Sequence number of next debugger command message.
Command lastCommand = null; // Most recent command sent to target.
List<String> errors = new List();
+ List<Event> events = new List();
bool cleanupDone = false;
// Data collected from debug target.
@@ -334,6 +414,8 @@
// Handle debugger events, updating the debugger state.
void handleEvent(Map<String,dynamic> msg) {
+ events.add(new Event(msg));
+
if (msg["event"] == "isolate") {
if (msg["params"]["reason"] == "created") {
isolateId = msg["params"]["id"];
@@ -388,6 +470,12 @@
// Send next debugger command in the script, if a response
// form the last command has been received and processed.
void sendNextCommand() {
+ while (script.isNextEventMatcher) {
+ EventMatcher matcher = script.currentEntry;
+ script.advance();
+ matcher.matchEvent(this);
+ }
+
if (lastCommand == null) {
if (script.currentEntry is Command) {
script.currentEntry.send(this);
@@ -521,11 +609,11 @@
// Port number 0 means debug target picks a free port dynamically.
var targetOpts = [ "--debug:0" ];
- targetOpts.add(options.script);
+ targetOpts.add(Platform.script);
targetOpts.add("--debuggee");
print('args: ${targetOpts.join(" ")}');
- Process.start(options.executable, targetOpts).then((Process process) {
+ Process.start(Platform.executable, targetOpts).then((Process process) {
print("Debug target process started, pid ${process.pid}.");
process.stdin.close();
var debugger = new Debugger(process, new DebugScript(script));
diff --git a/tests/standalone/debugger/tostring_throws_test.dart b/tests/standalone/debugger/tostring_throws_test.dart
index f25050d..03fd322 100644
--- a/tests/standalone/debugger/tostring_throws_test.dart
+++ b/tests/standalone/debugger/tostring_throws_test.dart
@@ -6,9 +6,9 @@
main() {
if (RunScript(testScript)) return;
-
+
Foo foo = new Foo();
-
+
print("Hello from debuggee");
}
diff --git a/tests/standalone/http_launch_test.dart b/tests/standalone/http_launch_test.dart
index 06b647e..6f8021d 100644
--- a/tests/standalone/http_launch_test.dart
+++ b/tests/standalone/http_launch_test.dart
@@ -18,8 +18,8 @@
import 'dart:io';
import 'package:expect/expect.dart';
-String pathToExecutable = new Options().executable;
-String pathOfData = new File(new Options().script).directory.path +
+String pathToExecutable = Platform.executable;
+String pathOfData = new File(Platform.script).directory.path +
'/http_launch_data';
int port;
diff --git a/tests/standalone/io/dart_std_io_pipe_test.dart b/tests/standalone/io/dart_std_io_pipe_test.dart
index e3dfec0..cc37115 100644
--- a/tests/standalone/io/dart_std_io_pipe_test.dart
+++ b/tests/standalone/io/dart_std_io_pipe_test.dart
@@ -39,7 +39,7 @@
String pipeOutFile = "${dir.path}/pipe";
if (devNull) pipeOutFile = "/dev/null";
String redirectOutFile = "${dir.path}/redirect";
- String executable = new Options().executable;
+ String executable = Platform.executable;
List args =
[executable,
dartScript,
diff --git a/tests/standalone/io/directory_list_pause_test.dart b/tests/standalone/io/directory_list_pause_test.dart
index 178f59f..081b406 100644
--- a/tests/standalone/io/directory_list_pause_test.dart
+++ b/tests/standalone/io/directory_list_pause_test.dart
@@ -10,31 +10,34 @@
void testPauseList() {
var keepAlive = new ReceivePort();
+ // TOTAL should be bigger the our directory listing buffer.
+ const int TOTAL = 128;
new Directory("").createTemp().then((d) {
- // Linux reads 2K at a time, so be sure to be >>.
- int total = 4 * 1024 + 1;
- for (int i = 0; i < total; i++) {
- new File("${d.path}/$i").createSync();
+ for (int i = 0; i < TOTAL; i++) {
+ new Directory("${d.path}/$i").createSync();
+ new File("${d.path}/$i/file").createSync();
}
bool first = true;
var subscription;
int count = 0;
- subscription = d.list().listen((file) {
- if (first) {
- first = false;
- subscription.pause();
- Timer.run(() {
- for (int i = 0; i < total; i++) {
- new File("${d.path}/$i").deleteSync();
- }
- subscription.resume();
- });
+ subscription = d.list(recursive: true).listen((file) {
+ if (file is File) {
+ if (first) {
+ first = false;
+ subscription.pause();
+ Timer.run(() {
+ for (int i = 0; i < TOTAL; i++) {
+ new File("${d.path}/$i/file").deleteSync();
+ }
+ subscription.resume();
+ });
+ }
+ count++;
}
- count++;
}, onDone: () {
- Expect.notEquals(total, count);
- keepAlive.close();
- d.delete().then((ignore) => keepAlive.close());
+ Expect.notEquals(TOTAL, count);
+ Expect.isTrue(count > 0);
+ d.delete(recursive: true).then((ignore) => keepAlive.close());
});
});
}
diff --git a/tests/standalone/io/directory_test.dart b/tests/standalone/io/directory_test.dart
index 6592281..f9927d3 100644
--- a/tests/standalone/io/directory_test.dart
+++ b/tests/standalone/io/directory_test.dart
@@ -85,6 +85,24 @@
Expect.isFalse(listedFile);
}
+ static void testListingTailingPaths() {
+ Directory directory = new Directory("").createTempSync();
+ Directory subDirectory = new Directory("${directory.path}/subdir/");
+ subDirectory.createSync();
+ File f = new File('${subDirectory.path}/file.txt');
+ f.createSync();
+
+ void test(entry) {
+ Expect.isFalse(entry.path.contains(new RegExp('[\\/][\\/]')));
+ }
+
+ subDirectory.listSync().forEach(test);
+
+ subDirectory.list().listen(test, onDone: () {
+ directory.deleteSync(recursive: true);
+ });
+ }
+
static void testListNonExistent() {
setupListerHandlers(Stream<FileSystemEntity> stream) {
stream.listen(
@@ -397,6 +415,7 @@
static void testMain() {
testListing();
+ testListingTailingPaths();
testListNonExistent();
testListTooLongName();
testDeleteNonExistent();
diff --git a/tests/standalone/io/file_read_special_device_test.dart b/tests/standalone/io/file_read_special_device_test.dart
index c32db08..d9880f3 100644
--- a/tests/standalone/io/file_read_special_device_test.dart
+++ b/tests/standalone/io/file_read_special_device_test.dart
@@ -6,10 +6,9 @@
import 'dart:io';
void openAndWriteScript(String script) {
- var options = new Options();
- var dir = new Path(options.script).directoryPath;
+ var dir = new Path(Platform.script).directoryPath;
script = "$dir/$script";
- var executable = options.executable;
+ var executable = Platform.executable;
var file = script; // Use script as file.
Process.start("bash", ["-c", "$executable $script < $file"]).then((process) {
process.exitCode
diff --git a/tests/standalone/io/file_read_stdio_script.dart b/tests/standalone/io/file_read_stdio_script.dart
index b2043ff..966d914 100644
--- a/tests/standalone/io/file_read_stdio_script.dart
+++ b/tests/standalone/io/file_read_stdio_script.dart
@@ -5,7 +5,7 @@
import 'dart:io';
void main() {
- var expected = new File(new Options().script).readAsStringSync();
+ var expected = new File(Platform.script).readAsStringSync();
var stdin = new File('/dev/fd/0').readAsStringSync();
if (expected != stdin) {
throw "stdin not equal expected file";
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart
index c34b823..b159031 100644
--- a/tests/standalone/io/file_test.dart
+++ b/tests/standalone/io/file_test.dart
@@ -1106,7 +1106,7 @@
static void testLastModified() {
var port = new ReceivePort();
- new File(new Options().executable).lastModified().then((modified) {
+ new File(Platform.executable).lastModified().then((modified) {
Expect.isTrue(modified is DateTime);
Expect.isTrue(modified.isBefore(new DateTime.now()));
port.close();
@@ -1114,7 +1114,7 @@
}
static void testLastModifiedSync() {
- var modified = new File(new Options().executable).lastModifiedSync();
+ var modified = new File(Platform.executable).lastModifiedSync();
Expect.isTrue(modified is DateTime);
Expect.isTrue(modified.isBefore(new DateTime.now()));
}
diff --git a/tests/standalone/io/http_proxy_test.dart b/tests/standalone/io/http_proxy_test.dart
index 5e7bfe1..70e06b6 100644
--- a/tests/standalone/io/http_proxy_test.dart
+++ b/tests/standalone/io/http_proxy_test.dart
@@ -746,7 +746,7 @@
void InitializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append('pkcert/');
+ new Path(Platform.script).directoryPath.append('pkcert/');
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: 'dartdart');
}
diff --git a/tests/standalone/io/http_server_early_client_close2_test.dart b/tests/standalone/io/http_server_early_client_close2_test.dart
index 5f695de..0f3f73b 100644
--- a/tests/standalone/io/http_server_early_client_close2_test.dart
+++ b/tests/standalone/io/http_server_early_client_close2_test.dart
@@ -16,7 +16,7 @@
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen(
(request) {
- String name = new Options().script;
+ String name = Platform.script;
new File(name).openRead().pipe(request.response)
.catchError((e) { /* ignore */ });
});
diff --git a/tests/standalone/io/http_server_early_client_close_test.dart b/tests/standalone/io/http_server_early_client_close_test.dart
index 5062a70..4b481db 100644
--- a/tests/standalone/io/http_server_early_client_close_test.dart
+++ b/tests/standalone/io/http_server_early_client_close_test.dart
@@ -118,7 +118,7 @@
HttpServer.bind("127.0.0.1", 0).then((server) {
server.listen(
(request) {
- String name = new Options().script;
+ String name = Platform.script;
new File(name).openRead().pipe(request.response)
.catchError((e) { /* ignore */ });
});
diff --git a/tests/standalone/io/http_server_response_test.dart b/tests/standalone/io/http_server_response_test.dart
index 307cec1..e1deb8d 100644
--- a/tests/standalone/io/http_server_response_test.dart
+++ b/tests/standalone/io/http_server_response_test.dart
@@ -80,10 +80,10 @@
void testResponseAddStream() {
- int bytes = new File(new Options().script).lengthSync();
+ int bytes = new File(Platform.script).lengthSync();
testServerRequest((server, request) {
- request.response.addStream(new File(new Options().script).openRead())
+ request.response.addStream(new File(Platform.script).openRead())
.then((response) {
response.close();
response.done.then((_) => server.close());
@@ -91,9 +91,9 @@
}, bytes: bytes);
testServerRequest((server, request) {
- request.response.addStream(new File(new Options().script).openRead())
+ request.response.addStream(new File(Platform.script).openRead())
.then((response) {
- request.response.addStream(new File(new Options().script).openRead())
+ request.response.addStream(new File(Platform.script).openRead())
.then((response) {
response.close();
response.done.then((_) => server.close());
@@ -129,7 +129,7 @@
void testResponseAddStreamClosed() {
testServerRequest((server, request) {
- request.response.addStream(new File(new Options().script).openRead())
+ request.response.addStream(new File(Platform.script).openRead())
.then((response) {
response.close();
response.done.then((_) => server.close());
@@ -139,7 +139,7 @@
testServerRequest((server, request) {
int count = 0;
write() {
- request.response.addStream(new File(new Options().script).openRead())
+ request.response.addStream(new File(Platform.script).openRead())
.then((response) {
request.response.write("sync data");
count++;
@@ -158,14 +158,14 @@
void testResponseAddClosed() {
testServerRequest((server, request) {
- request.response.add(new File(new Options().script).readAsBytesSync());
+ request.response.add(new File(Platform.script).readAsBytesSync());
request.response.close();
request.response.done.then((_) => server.close());
}, closeClient: true);
testServerRequest((server, request) {
for (int i = 0; i < 1000; i++) {
- request.response.add(new File(new Options().script).readAsBytesSync());
+ request.response.add(new File(Platform.script).readAsBytesSync());
}
request.response.close();
request.response.done.then((_) => server.close());
@@ -174,7 +174,7 @@
testServerRequest((server, request) {
int count = 0;
write() {
- request.response.add(new File(new Options().script).readAsBytesSync());
+ request.response.add(new File(Platform.script).readAsBytesSync());
Timer.run(() {
count++;
if (count < 1000) {
diff --git a/tests/standalone/io/https_client_certificate_test.dart b/tests/standalone/io/https_client_certificate_test.dart
index 141470a..847b19a 100644
--- a/tests/standalone/io/https_client_certificate_test.dart
+++ b/tests/standalone/io/https_client_certificate_test.dart
@@ -45,7 +45,7 @@
void InitializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append('pkcert/');
+ new Path(Platform.script).directoryPath.append('pkcert/');
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: 'dartdart');
}
diff --git a/tests/standalone/io/https_server_test.dart b/tests/standalone/io/https_server_test.dart
index 2e0b2a0..6ca31bc 100644
--- a/tests/standalone/io/https_server_test.dart
+++ b/tests/standalone/io/https_server_test.dart
@@ -59,7 +59,7 @@
void InitializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append('pkcert/');
+ new Path(Platform.script).directoryPath.append('pkcert/');
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: 'dartdart');
}
diff --git a/tests/standalone/io/internet_address_test.dart b/tests/standalone/io/internet_address_test.dart
index 67216d4..22c4a66 100644
--- a/tests/standalone/io/internet_address_test.dart
+++ b/tests/standalone/io/internet_address_test.dart
@@ -6,7 +6,7 @@
import "package:expect/expect.dart";
-void test() {
+void testDefaultAddresses() {
var loopback4 = InternetAddress.LOOPBACK_IP_V4;
Expect.isNotNull(loopback4);
Expect.equals(InternetAddressType.IP_V4, loopback4.type);
@@ -32,6 +32,23 @@
Expect.equals("::", any6.address);
}
+void testReverseLookup() {
+ InternetAddress.lookup('localhost').then((addrs) {
+ addrs.first.reverse().then((addr) {
+ Expect.isNotNull(addr.host);
+ });
+ });
+
+ InternetAddress.lookup('127.0.0.1').then((addrs) {
+ Expect.equals('127.0.0.1', addrs.first.host);
+ addrs.first.reverse().then((addr) {
+ Expect.isNotNull(addr.host);
+ Expect.notEquals('127.0.0.1', addr.host);
+ });
+ });
+}
+
void main() {
- test();
+ testDefaultAddresses();
+ testReverseLookup();
}
diff --git a/tests/standalone/io/link_test.dart b/tests/standalone/io/link_test.dart
index 0562cb3b..7bef4c5 100644
--- a/tests/standalone/io/link_test.dart
+++ b/tests/standalone/io/link_test.dart
@@ -173,7 +173,15 @@
new Directory.fromPath(base).delete(recursive: true));
}
+void testLinkErrorSync() {
+ Expect.throws(() =>
+ new Link('some-dir-that-doent exist/some link file/bla/fisk').createSync(
+ 'bla bla bla/b lalal/blfir/sdfred/es'),
+ (e) => e is LinkException);
+}
+
main() {
testCreateSync();
testCreateLoopingLink();
+ testLinkErrorSync();
}
diff --git a/tests/standalone/io/network_interface_test.dart b/tests/standalone/io/network_interface_test.dart
new file mode 100644
index 0000000..ee6a25e
--- /dev/null
+++ b/tests/standalone/io/network_interface_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// 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:io';
+
+import "package:expect/expect.dart";
+
+
+void testListLoopback() {
+ NetworkInterface.list(includeLoopback: false).then((list) {
+ for (var i in list) {
+ for (var a in i.addresses) {
+ Expect.isFalse(a.isLoopback);
+ }
+ }
+ });
+
+ NetworkInterface.list(includeLoopback: true).then((list) {
+ Expect.isTrue(list.any((i) => i.addresses.any((a) => a.isLoopback)));
+ });
+}
+
+
+void testListLinkLocal() {
+ NetworkInterface.list(includeLinkLocal: false).then((list) {
+ for (var i in list) {
+ for (var a in i.addresses) {
+ Expect.isFalse(a.isLinkLocal);
+ }
+ }
+ });
+}
+
+
+void main() {
+ testListLoopback();
+ testListLinkLocal();
+}
diff --git a/tests/standalone/io/options_test.dart b/tests/standalone/io/options_test.dart
index cad7d91..9f61e35 100644
--- a/tests/standalone/io/options_test.dart
+++ b/tests/standalone/io/options_test.dart
@@ -16,9 +16,6 @@
Expect.equals(10, int.parse(opts.arguments[0]));
Expect.equals("options_test", opts.arguments[1]);
Expect.equals(20, int.parse(opts.arguments[2]));
- Expect.isTrue(opts.executable.contains('dart'));
- Expect.isTrue(opts.script.replaceAll('\\', '/').
- endsWith('tests/standalone/io/options_test.dart'));
// Now add an additional argument.
opts.arguments.add("Fourth");
diff --git a/tests/standalone/io/platform_test.dart b/tests/standalone/io/platform_test.dart
index 4a42683a..ce6e977 100644
--- a/tests/standalone/io/platform_test.dart
+++ b/tests/standalone/io/platform_test.dart
@@ -10,10 +10,17 @@
var os = Platform.operatingSystem;
Expect.isTrue(os == "android" || os == "linux" || os == "macos" ||
os == "windows");
+ Expect.equals(Platform.isLinux, Platform.operatingSystem == "linux");
+ Expect.equals(Platform.isMacOS, Platform.operatingSystem == "macos");
+ Expect.equals(Platform.isWindows, Platform.operatingSystem == "windows");
+ Expect.equals(Platform.isAndroid, Platform.operatingSystem == "android");
var sep = Platform.pathSeparator;
Expect.isTrue(sep == '/' || (os == 'windows' && sep == '\\'));
var hostname = Platform.localHostname;
Expect.isTrue(hostname is String && hostname != "");
var environment = Platform.environment;
Expect.isTrue(environment is Map<String, String>);
+ Expect.isTrue(Platform.executable.contains('dart'));
+ Expect.isTrue(Platform.script.replaceAll('\\', '/').
+ endsWith('tests/standalone/io/platform_test.dart'));
}
diff --git a/tests/standalone/io/process_broken_pipe_test.dart b/tests/standalone/io/process_broken_pipe_test.dart
index 01451bf..7791fd4 100644
--- a/tests/standalone/io/process_broken_pipe_test.dart
+++ b/tests/standalone/io/process_broken_pipe_test.dart
@@ -12,7 +12,7 @@
main() {
// Running dart without arguments makes it close right away.
- var future = Process.start(new Options().executable, []);
+ var future = Process.start(Platform.executable, []);
future.then((process) {
process.stdin.done.catchError((e) {
// Accept errors on stdin.
diff --git a/tests/standalone/io/process_check_arguments_script.dart b/tests/standalone/io/process_check_arguments_script.dart
index 4e933b9..183beaf 100644
--- a/tests/standalone/io/process_check_arguments_script.dart
+++ b/tests/standalone/io/process_check_arguments_script.dart
@@ -23,7 +23,8 @@
main() {
var options = new Options();
- Expect.isTrue(options.script.endsWith('process_check_arguments_script.dart'));
+ Expect.isTrue(Platform.script.endsWith(
+ 'process_check_arguments_script.dart'));
var expected_num_args = int.parse(options.arguments[0]);
var contains_quote = int.parse(options.arguments[1]);
Expect.equals(expected_num_args, options.arguments.length);
diff --git a/tests/standalone/io/process_check_arguments_test.dart b/tests/standalone/io/process_check_arguments_test.dart
index 68da4a2..da5324e 100644
--- a/tests/standalone/io/process_check_arguments_test.dart
+++ b/tests/standalone/io/process_check_arguments_test.dart
@@ -7,7 +7,7 @@
import "process_test_util.dart";
test(args) {
- var future = Process.start(new Options().executable, args);
+ var future = Process.start(Platform.executable, args);
future.then((process) {
process.exitCode.then((exitCode) {
Expect.equals(0, exitCode);
diff --git a/tests/standalone/io/process_environment_test.dart b/tests/standalone/io/process_environment_test.dart
index 24cc73d..cb60471 100644
--- a/tests/standalone/io/process_environment_test.dart
+++ b/tests/standalone/io/process_environment_test.dart
@@ -7,15 +7,16 @@
import "dart:isolate";
import "process_test_util.dart";
-runEnvironmentProcess(Map environment, name, callback) {
- var dartExecutable = new Options().executable;
+runEnvironmentProcess(Map environment, name, includeParent, callback) {
+ var dartExecutable = Platform.executable;
var printEnv = 'tests/standalone/io/print_env.dart';
if (!new File(printEnv).existsSync()) {
printEnv = '../$printEnv';
}
Process.run(dartExecutable,
[printEnv, name],
- environment: environment)
+ environment: environment,
+ includeParentEnvironment: includeParent)
.then((result) {
Expect.equals(0, result.exitCode);
callback(result.stdout);
@@ -29,7 +30,7 @@
// Check that some value in the environment stays the same when passed
// to another process.
for (var k in env.keys) {
- runEnvironmentProcess(env, k, (output) {
+ runEnvironmentProcess({}, k, true, (output) {
// Only check startsWith. The print statements will add
// newlines at the end.
Expect.isTrue(output.startsWith(env[k]));
@@ -39,7 +40,7 @@
var name = 'MYENVVAR';
while (env.containsKey(name)) name = '${name}_';
copy[name] = 'value';
- runEnvironmentProcess(copy, name, (output) {
+ runEnvironmentProcess(copy, name, true, (output) {
Expect.isTrue(output.startsWith('value'));
donePort.close();
});
@@ -50,6 +51,18 @@
}
}
+testNoIncludeEnvironment() {
+ var donePort = new ReceivePort();
+ var env = Platform.environment;
+ Expect.isTrue(env.containsKey('PATH'));
+ env.remove('PATH');
+ runEnvironmentProcess(env, "PATH", false, (output) {
+ donePort.close();
+ Expect.isTrue(output.startsWith("null"));
+ });
+}
+
main() {
testEnvironment();
+ testNoIncludeEnvironment();
}
diff --git a/tests/standalone/io/process_non_ascii_test.dart b/tests/standalone/io/process_non_ascii_test.dart
index bd8a683..f590cff 100644
--- a/tests/standalone/io/process_non_ascii_test.dart
+++ b/tests/standalone/io/process_non_ascii_test.dart
@@ -8,7 +8,7 @@
main() {
var port = new ReceivePort();
- var executable = new File(new Options().executable).fullPathSync();
+ var executable = new File(Platform.executable).fullPathSync();
var tempDir = new Directory('').createTempSync();
var nonAsciiDir = new Directory('${tempDir.path}/æøå');
nonAsciiDir.createSync();
diff --git a/tests/standalone/io/process_pid_test.dart b/tests/standalone/io/process_pid_test.dart
index c83a6d9..0016058 100644
--- a/tests/standalone/io/process_pid_test.dart
+++ b/tests/standalone/io/process_pid_test.dart
@@ -13,8 +13,8 @@
var port = new ReceivePort();
Expect.isTrue(pid > 0);
var futures = [];
- futures.add(Process.start(new Options().executable,['--version']));
- futures.add(Process.run(new Options().executable,['--version']));
+ futures.add(Process.start(Platform.executable,['--version']));
+ futures.add(Process.run(Platform.executable,['--version']));
Future.wait(futures).then((results) {
Expect.isTrue(results[0].pid > 0);
Expect.isTrue(results[1].pid > 0);
diff --git a/tests/standalone/io/process_run_output_test.dart b/tests/standalone/io/process_run_output_test.dart
index f8b06d4..efa9892 100644
--- a/tests/standalone/io/process_run_output_test.dart
+++ b/tests/standalone/io/process_run_output_test.dart
@@ -35,7 +35,7 @@
}
if (stream == 'stdout') {
- Process.run(new Options().executable,
+ Process.run(Platform.executable,
[scriptFile, encoding, stream],
stdoutEncoding: enc). then((result) {
Expect.equals(result.exitCode, 0);
@@ -43,7 +43,7 @@
checkOutput(encoding, result.stdout);
});
} else {
- Process.run(new Options().executable,
+ Process.run(Platform.executable,
[scriptFile, encoding, stream],
stderrEncoding: enc).then((result) {
Expect.equals(result.exitCode, 0);
diff --git a/tests/standalone/io/process_set_exit_code_test.dart b/tests/standalone/io/process_set_exit_code_test.dart
index 1b0f767..39aa9b0 100644
--- a/tests/standalone/io/process_set_exit_code_test.dart
+++ b/tests/standalone/io/process_set_exit_code_test.dart
@@ -10,9 +10,8 @@
import "dart:io";
main() {
- var options = new Options();
- var executable = options.executable;
- var script = options.script;
+ var executable = Platform.executable;
+ var script = Platform.script;
var scriptDirectory = new Path(script).directoryPath;
var exitCodeScript =
scriptDirectory.append('process_set_exit_code_script.dart');
diff --git a/tests/standalone/io/process_shell_test.dart b/tests/standalone/io/process_shell_test.dart
index fd962d9..3d0f6a8 100644
--- a/tests/standalone/io/process_shell_test.dart
+++ b/tests/standalone/io/process_shell_test.dart
@@ -7,10 +7,9 @@
void testRunShell() {
test(args) {
- var options = new Options();
- var path = new Path(options.script);
+ var path = new Path(Platform.script);
path = path.directoryPath.join(new Path("process_echo_util.dart"));
- Process.run(options.executable,
+ Process.run(Platform.executable,
[path.toString()]..addAll(args),
runInShell: true)
.then((result) {
@@ -44,8 +43,7 @@
void testBadRunShell() {
test(exe, [args = const []]) {
- var options = new Options();
- var path = new Path(options.script);
+ var path = new Path(Platform.script);
path = path.directoryPath.join(new Path("process_echo_util.dart"));
Process.run(exe, args, runInShell: true)
.then((result) {
diff --git a/tests/standalone/io/process_stderr_test.dart b/tests/standalone/io/process_stderr_test.dart
index 8292b99..6c821d9 100644
--- a/tests/standalone/io/process_stderr_test.dart
+++ b/tests/standalone/io/process_stderr_test.dart
@@ -65,5 +65,5 @@
scriptFile = new File("../tests/standalone/io/process_std_io_script.dart");
}
Expect.isTrue(scriptFile.existsSync());
- test(Process.start(new Options().executable, [scriptFile.path, "1"]), 0);
+ test(Process.start(Platform.executable, [scriptFile.path, "1"]), 0);
}
diff --git a/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
index 94085a4..8b10d73 100644
--- a/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
+++ b/tests/standalone/io/process_stdin_transform_unsubscribe_test.dart
@@ -35,5 +35,5 @@
scriptFile = new File("../tests/standalone/io/$scriptName");
}
Expect.isTrue(scriptFile.existsSync());
- test(Process.start(new Options().executable, [scriptFile.path]), 0);
+ test(Process.start(Platform.executable, [scriptFile.path]), 0);
}
diff --git a/tests/standalone/io/process_stdout_test.dart b/tests/standalone/io/process_stdout_test.dart
index 0bce7aa..8b117fe 100644
--- a/tests/standalone/io/process_stdout_test.dart
+++ b/tests/standalone/io/process_stdout_test.dart
@@ -65,5 +65,5 @@
scriptFile = new File("../tests/standalone/io/process_std_io_script.dart");
}
Expect.isTrue(scriptFile.existsSync());
- test(Process.start(new Options().executable, [scriptFile.path, "0"]), 0);
+ test(Process.start(Platform.executable, [scriptFile.path, "0"]), 0);
}
diff --git a/tests/standalone/io/process_test_util.dart b/tests/standalone/io/process_test_util.dart
index f60c239..36325b1 100644
--- a/tests/standalone/io/process_test_util.dart
+++ b/tests/standalone/io/process_test_util.dart
@@ -14,7 +14,7 @@
String getProcessTestFileName() {
var extension = getPlatformExecutableExtension();
- var executable = new Options().executable;
+ var executable = Platform.executable;
var dirIndex = executable.lastIndexOf('dart$extension');
var buffer = new StringBuffer(executable.substring(0, dirIndex));
buffer.write('process_test$extension');
diff --git a/tests/standalone/io/raw_secure_server_closing_test.dart b/tests/standalone/io/raw_secure_server_closing_test.dart
index c1b7ddc..a629d45 100644
--- a/tests/standalone/io/raw_secure_server_closing_test.dart
+++ b/tests/standalone/io/raw_secure_server_closing_test.dart
@@ -143,7 +143,7 @@
main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/raw_secure_server_socket_argument_test.dart b/tests/standalone/io/raw_secure_server_socket_argument_test.dart
index 6c78cbc..ee35920 100644
--- a/tests/standalone/io/raw_secure_server_socket_argument_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_argument_test.dart
@@ -17,17 +17,44 @@
void testArguments() {
+ bool isArgOrTypeError(e) => e is ArgumentError || e is TypeError;
Expect.throws(() =>
- RawSecureServerSocket.bind(SERVER_ADDRESS, 65536, 5, CERTIFICATE));
+ RawSecureServerSocket.bind(SERVER_ADDRESS, 65536, CERTIFICATE),
+ isArgOrTypeError);
Expect.throws(() =>
- RawSecureServerSocket.bind(SERVER_ADDRESS, -1, CERTIFICATE));
- Expect.throws(() =>
- RawSecureServerSocket.bind(SERVER_ADDRESS, 0, -1, CERTIFICATE));
+ RawSecureServerSocket.bind(SERVER_ADDRESS, -1, CERTIFICATE),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureServerSocket.bind(SERVER_ADDRESS, 0,
+ CERTIFICATE, backlog: -1),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, 3456,
+ sendClientCertificate: true,
+ certificateName: 12.3),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, null),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, -1),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, 345656),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, 'hest'),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(null, 0),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, 0,
+ certificateName: 77),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, 0,
+ sendClientCertificate: 'fisk'),
+ isArgOrTypeError);
+ Expect.throws(() => RawSecureSocket.connect(SERVER_ADDRESS, 0,
+ onBadCertificate: 'hund'),
+ isArgOrTypeError);
}
main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
index fb5f916..dbc0391 100644
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -86,13 +86,13 @@
Expect.fail("No client connection expected.");
})
.catchError((error) {
- Expect.isTrue(error is SocketException);
+ Expect.isTrue(error is HandshakeException);
});
server.listen((serverEnd) {
Expect.fail("No server connection expected.");
},
onError: (error) {
- Expect.isTrue(error is SocketException);
+ Expect.isTrue(error is CertificateException);
clientEndFuture.then((_) {
if (!cancelOnError) server.close();
port.close();
@@ -150,10 +150,13 @@
// server will not happen until the first TLS handshake data has been
// received from the client. This argument only takes effect when
// handshakeBeforeSecure is true.
-void testSimpleReadWrite(bool listenSecure,
- bool connectSecure,
- bool handshakeBeforeSecure,
- [bool postponeSecure = false]) {
+void testSimpleReadWrite({bool listenSecure,
+ bool connectSecure,
+ bool handshakeBeforeSecure,
+ bool postponeSecure,
+ bool dropReads}) {
+ int clientReads = 0;
+ int serverReads = 0;
if (handshakeBeforeSecure == true &&
(listenSecure == true || connectSecure == true)) {
Expect.fail("Invalid arguments to testSimpleReadWrite");
@@ -206,6 +209,14 @@
subscription = client.listen((event) {
switch (event) {
case RawSocketEvent.READ:
+ if (dropReads) {
+ if (serverReads != 10) {
+ ++serverReads;
+ break;
+ } else {
+ serverReads = 0;
+ }
+ }
Expect.isTrue(bytesWritten == 0);
Expect.isTrue(client.available() > 0);
var buffer = client.read();
@@ -257,6 +268,14 @@
switch (event) {
case RawSocketEvent.READ:
Expect.isTrue(socket.available() > 0);
+ if (dropReads) {
+ if (clientReads != 10) {
+ ++clientReads;
+ break;
+ } else {
+ clientReads = 0;
+ }
+ }
var buffer = socket.read();
if (buffer != null) {
dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
@@ -296,6 +315,14 @@
Expect.isTrue(bytesWritten == 0);
}
Expect.isTrue(client.available() > 0);
+ if (dropReads) {
+ if (serverReads != 10) {
+ ++serverReads;
+ break;
+ } else {
+ serverReads = 0;
+ }
+ }
var buffer = client.read();
if (buffer != null) {
if (bytesRead == data.length) {
@@ -354,6 +381,14 @@
subscription = socket.listen((event) {
switch (event) {
case RawSocketEvent.READ:
+ if (dropReads) {
+ if (clientReads != 10) {
+ ++clientReads;
+ break;
+ } else {
+ clientReads = 0;
+ }
+ }
Expect.isTrue(socket.available() > 0);
var buffer = socket.read();
if (buffer != null) {
@@ -435,7 +470,7 @@
}
main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
@@ -449,10 +484,44 @@
testSimpleConnectFail("not_a_nickname", true);
testSimpleConnectFail("CN=notARealDistinguishedName", true);
testServerListenAfterConnect();
- testSimpleReadWrite(true, true, false);
- testSimpleReadWrite(true, false, false);
- testSimpleReadWrite(false, true, false);
- testSimpleReadWrite(false, false, false);
- testSimpleReadWrite(false, false, true, true);
- testSimpleReadWrite(false, false, true, false);
+ testSimpleReadWrite(listenSecure: true,
+ connectSecure: true,
+ handshakeBeforeSecure: false,
+ postponeSecure: false,
+ dropReads: false);
+ testSimpleReadWrite(listenSecure: true,
+ connectSecure: false,
+ handshakeBeforeSecure: false,
+ postponeSecure: false,
+ dropReads: false);
+ testSimpleReadWrite(listenSecure: false,
+ connectSecure: true,
+ handshakeBeforeSecure: false,
+ postponeSecure: false,
+ dropReads: false);
+ testSimpleReadWrite(listenSecure: false,
+ connectSecure: false,
+ handshakeBeforeSecure: false,
+ postponeSecure: false,
+ dropReads: false);
+ testSimpleReadWrite(listenSecure: false,
+ connectSecure: false,
+ handshakeBeforeSecure: true,
+ postponeSecure: true,
+ dropReads: false);
+ testSimpleReadWrite(listenSecure: false,
+ connectSecure: false,
+ handshakeBeforeSecure: true,
+ postponeSecure: false,
+ dropReads: false);
+ testSimpleReadWrite(listenSecure: true,
+ connectSecure: true,
+ handshakeBeforeSecure: false,
+ postponeSecure: false,
+ dropReads: true);
+ testSimpleReadWrite(listenSecure: false,
+ connectSecure: false,
+ handshakeBeforeSecure: true,
+ postponeSecure: true,
+ dropReads: true);
}
diff --git a/tests/standalone/io/raw_secure_socket_pause_test.dart b/tests/standalone/io/raw_secure_socket_pause_test.dart
index a8d01de..a0d678f 100644
--- a/tests/standalone/io/raw_secure_socket_pause_test.dart
+++ b/tests/standalone/io/raw_secure_socket_pause_test.dart
@@ -35,7 +35,7 @@
void InitializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append('pkcert/');
+ new Path(Platform.script).directoryPath.append('pkcert/');
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: 'dartdart');
}
diff --git a/tests/standalone/io/raw_secure_socket_test.dart b/tests/standalone/io/raw_secure_socket_test.dart
index 06d6b83..228bfd3 100644
--- a/tests/standalone/io/raw_secure_socket_test.dart
+++ b/tests/standalone/io/raw_secure_socket_test.dart
@@ -35,7 +35,7 @@
void InitializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append('pkcert/');
+ new Path(Platform.script).directoryPath.append('pkcert/');
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: 'dartdart');
}
diff --git a/tests/standalone/io/raw_socket_test.dart b/tests/standalone/io/raw_socket_test.dart
index 08ed693..1b1b23f 100644
--- a/tests/standalone/io/raw_socket_test.dart
+++ b/tests/standalone/io/raw_socket_test.dart
@@ -123,7 +123,7 @@
});
}
-void testSimpleReadWrite() {
+void testSimpleReadWrite({bool dropReads}) {
// This test creates a server and a client connects. The client then
// writes and the server echos. When the server has finished its
// echo it half-closes. When the client gets the close event is
@@ -131,6 +131,8 @@
ReceivePort port = new ReceivePort();
const messageSize = 1000;
+ int serverReadCount = 0;
+ int clientReadCount = 0;
List<int> createTestData() {
return new List<int>.generate(messageSize, (index) => index & 0xff);
@@ -154,9 +156,17 @@
client.listen((event) {
switch (event) {
case RawSocketEvent.READ:
+ if (dropReads) {
+ if (serverReadCount != 10) {
+ serverReadCount++;
+ break;
+ } else {
+ serverReadCount = 0;
+ }
+ }
Expect.isTrue(bytesWritten == 0);
Expect.isTrue(client.available() > 0);
- var buffer = client.read();
+ var buffer = client.read(200);
data.setRange(bytesRead, bytesRead + buffer.length, buffer);
bytesRead += buffer.length;
if (bytesRead == data.length) {
@@ -192,6 +202,14 @@
switch (event) {
case RawSocketEvent.READ:
Expect.isTrue(socket.available() > 0);
+ if (dropReads) {
+ if (clientReadCount != 10) {
+ clientReadCount++;
+ break;
+ } else {
+ clientReadCount = 0;
+ }
+ }
var buffer = socket.read();
data.setRange(bytesRead, bytesRead + buffer.length, buffer);
bytesRead += buffer.length;
@@ -241,7 +259,7 @@
// sockets.
subscription.pause();
var connectCount = 0;
- for (int i = 0; i <= socketCount / 2; i++) {
+ for (int i = 0; i < socketCount / 2; i++) {
RawSocket.connect("127.0.0.1", server.port).then((_) {
if (++connectCount == socketCount / 2) {
subscription.resume();
@@ -343,7 +361,8 @@
testInvalidBind();
testSimpleConnect();
testServerListenAfterConnect();
- testSimpleReadWrite();
+ testSimpleReadWrite(dropReads: false);
+ testSimpleReadWrite(dropReads: true);
testPauseServerSocket();
testPauseSocket();
}
diff --git a/tests/standalone/io/regress_7191_script.dart b/tests/standalone/io/regress_7191_script.dart
index 7bc7a3e..9f7c780 100644
--- a/tests/standalone/io/regress_7191_script.dart
+++ b/tests/standalone/io/regress_7191_script.dart
@@ -11,8 +11,7 @@
// Start sub-process when receiving data.
var subscription;
subscription = stdin.listen((data) {
- var options = new Options();
- Process.start(options.executable, [options.script]).then((p) {
+ Process.start(Platform.executable, [Platform.script]).then((p) {
p.stdout.listen((_) { });
p.stderr.listen((_) { });
// When receiving data again, kill sub-process and exit.
diff --git a/tests/standalone/io/regress_7191_test.dart b/tests/standalone/io/regress_7191_test.dart
index 8c56fb3..4e6abf1 100644
--- a/tests/standalone/io/regress_7191_test.dart
+++ b/tests/standalone/io/regress_7191_test.dart
@@ -14,9 +14,8 @@
main() {
var port = new ReceivePort();
- var options = new Options();
- var executable = options.executable;
- var scriptDir = new Path(options.script).directoryPath;
+ var executable = Platform.executable;
+ var scriptDir = new Path(Platform.script).directoryPath;
var script = scriptDir.append('regress_7191_script.dart').toNativePath();
Process.start(executable, [script]).then((process) {
process.stdin.add([0]);
diff --git a/tests/standalone/io/regress_7679_test.dart b/tests/standalone/io/regress_7679_test.dart
index 30b45d37..9f4c324 100644
--- a/tests/standalone/io/regress_7679_test.dart
+++ b/tests/standalone/io/regress_7679_test.dart
@@ -34,7 +34,7 @@
});
}
""");
- String executable = new File(new Options().executable).fullPathSync();
+ String executable = new File(Platform.executable).fullPathSync();
Process.run(executable, ['script.dart'], workingDirectory: temp.path)
.then((result) {
temp.deleteSync(recursive: true);
diff --git a/tests/standalone/io/secure_builtin_roots_database_test.dart b/tests/standalone/io/secure_builtin_roots_database_test.dart
index 6b55c71..884123b 100644
--- a/tests/standalone/io/secure_builtin_roots_database_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_database_test.dart
@@ -23,7 +23,7 @@
// If the built-in root certificates aren't loaded, the connection
// should signal an error. Even when an external database is loaded,
// they should not be loaded.
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/secure_client_raw_server_test.dart b/tests/standalone/io/secure_client_raw_server_test.dart
index 1fce350..4f6fa0c 100644
--- a/tests/standalone/io/secure_client_raw_server_test.dart
+++ b/tests/standalone/io/secure_client_raw_server_test.dart
@@ -77,7 +77,7 @@
}
void main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart');
diff --git a/tests/standalone/io/secure_client_server_test.dart b/tests/standalone/io/secure_client_server_test.dart
index 11cf433..9806444b 100644
--- a/tests/standalone/io/secure_client_server_test.dart
+++ b/tests/standalone/io/secure_client_server_test.dart
@@ -42,7 +42,7 @@
}
void main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart');
diff --git a/tests/standalone/io/secure_multiple_client_server_test.dart b/tests/standalone/io/secure_multiple_client_server_test.dart
index e0e91e4..b5af21a 100644
--- a/tests/standalone/io/secure_multiple_client_server_test.dart
+++ b/tests/standalone/io/secure_multiple_client_server_test.dart
@@ -45,7 +45,7 @@
}
void main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart');
diff --git a/tests/standalone/io/secure_no_builtin_roots_database_test.dart b/tests/standalone/io/secure_no_builtin_roots_database_test.dart
index b5a06af..1affafb 100644
--- a/tests/standalone/io/secure_no_builtin_roots_database_test.dart
+++ b/tests/standalone/io/secure_no_builtin_roots_database_test.dart
@@ -14,7 +14,7 @@
.then((request) => request.close())
.then((response) => Expect.fail("Unexpected successful connection"))
.catchError((error) {
- Expect.isTrue(error is SocketException);
+ Expect.isTrue(error is HandshakeException);
keepAlive.close();
client.close();
});
@@ -24,7 +24,7 @@
// If the built-in root certificates aren't loaded, the connection
// should signal an error. Even when an external database is loaded,
// they should not be loaded.
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/secure_no_builtin_roots_test.dart b/tests/standalone/io/secure_no_builtin_roots_test.dart
index 9bc5ef6..4bcdac8 100644
--- a/tests/standalone/io/secure_no_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_no_builtin_roots_test.dart
@@ -14,7 +14,7 @@
.then((request) => request.close())
.then((response) => Expect.fail("Unexpected successful connection"))
.catchError((error) {
- Expect.isTrue(error is SocketException);
+ Expect.isTrue(error is HandshakeException);
keepAlive.close();
client.close();
});
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 35475e2..4aafbc6 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -110,7 +110,7 @@
}
void main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/secure_server_closing_test.dart b/tests/standalone/io/secure_server_closing_test.dart
index 0d27cb2..67b70fd 100644
--- a/tests/standalone/io/secure_server_closing_test.dart
+++ b/tests/standalone/io/secure_server_closing_test.dart
@@ -151,7 +151,7 @@
main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/secure_server_socket_test.dart b/tests/standalone/io/secure_server_socket_test.dart
index 9563fc9..2d36fed 100644
--- a/tests/standalone/io/secure_server_socket_test.dart
+++ b/tests/standalone/io/secure_server_socket_test.dart
@@ -83,13 +83,13 @@
Expect.fail("No client connection expected.");
})
.catchError((error) {
- Expect.isTrue(error is SocketException);
+ Expect.isTrue(error is HandshakeException);
});
server.listen((serverEnd) {
Expect.fail("No server connection expected.");
},
onError: (error) {
- Expect.isTrue(error is SocketException);
+ Expect.isTrue(error is CertificateException);
clientEndFuture.then((_) {
if (!cancelOnError) server.close();
port.close();
@@ -186,7 +186,7 @@
}
main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/secure_session_resume_test.dart b/tests/standalone/io/secure_session_resume_test.dart
index 17873e8..e287e37 100644
--- a/tests/standalone/io/secure_session_resume_test.dart
+++ b/tests/standalone/io/secure_session_resume_test.dart
@@ -54,7 +54,7 @@
}
void main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart');
diff --git a/tests/standalone/io/secure_socket_bad_certificate_test.dart b/tests/standalone/io/secure_socket_bad_certificate_test.dart
index 85b1cd3..dbd13d1e 100644
--- a/tests/standalone/io/secure_socket_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_socket_bad_certificate_test.dart
@@ -31,12 +31,9 @@
}
Future testCertificateCallback({String host, bool acceptCertificate}) {
- try {
- var x = 7;
- SecureSocket.connect(host, 443, onBadCertificate: x)
- .catchError((e) {}, test: (e) => e is ArgumentError);
- } on TypeError catch (e) {
- }
+ var x = 7;
+ Expect.throws(() => SecureSocket.connect(host, 443, onBadCertificate: x),
+ (e) => e is ArgumentError || e is TypeError);
bool badCertificateCallback(X509Certificate certificate) {
Expect.isTrue(certificate.subject.contains("O=Google Inc"));
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index 84a9fb8..d9ff854 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -34,7 +34,7 @@
void InitializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append('pkcert/');
+ new Path(Platform.script).directoryPath.append('pkcert/');
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: 'dartdart');
}
diff --git a/tests/standalone/io/skipping_dart2js_compilations_helper.dart b/tests/standalone/io/skipping_dart2js_compilations_helper.dart
index 1728e3a..88a26c2 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_helper.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_helper.dart
@@ -5,7 +5,7 @@
import 'dart:io';
main() {
- var outputFile = new Options().arguments[0];
+ var outputFile = Platform.arguments[0];
var file = new File(outputFile);
file.createSync();
}
diff --git a/tests/standalone/io/skipping_dart2js_compilations_test.dart b/tests/standalone/io/skipping_dart2js_compilations_test.dart
index d018541..dfb71a5 100644
--- a/tests/standalone/io/skipping_dart2js_compilations_test.dart
+++ b/tests/standalone/io/skipping_dart2js_compilations_test.dart
@@ -146,10 +146,10 @@
runner.TestCase makeTestCase(String testName, FileUtils fileUtils) {
var config = new options.TestOptionsParser().parse(['--timeout', '2'])[0];
- var scriptDirPath = new Path(new Options().script).directoryPath;
+ var scriptDirPath = new Path(Platform.script).directoryPath;
var createFileScript = scriptDirPath.
append('skipping_dart2js_compilations_helper.dart').toNativePath();
- var executable = new Options().executable;
+ var executable = Platform.executable;
var arguments = [createFileScript, fileUtils.scriptOutputPath.toNativePath()];
var bootstrapDeps = [
Uri.parse("file://${fileUtils.testSnapshotFilePath}")];
diff --git a/tests/standalone/io/socket_upgrade_to_secure_test.dart b/tests/standalone/io/socket_upgrade_to_secure_test.dart
index cc66ce8..8564c98 100644
--- a/tests/standalone/io/socket_upgrade_to_secure_test.dart
+++ b/tests/standalone/io/socket_upgrade_to_secure_test.dart
@@ -211,7 +211,7 @@
}
main() {
- Path scriptDir = new Path(new Options().script).directoryPath;
+ Path scriptDir = new Path(Platform.script).directoryPath;
Path certificateDatabase = scriptDir.append('pkcert');
SecureSocket.initialize(database: certificateDatabase.toNativePath(),
password: 'dartdart',
diff --git a/tests/standalone/io/string_decoder_test.dart b/tests/standalone/io/string_decoder_test.dart
index df808ae..6e96000 100644
--- a/tests/standalone/io/string_decoder_test.dart
+++ b/tests/standalone/io/string_decoder_test.dart
@@ -6,7 +6,7 @@
import "dart:async";
import "dart:io";
-void test() {
+void testTransform() {
// Code point U+10FFFF is the largest code point supported by Dart.
var controller = new StreamController(sync: true);
controller.add([0xf0, 0x90, 0x80, 0x80]); // U+10000
@@ -40,6 +40,33 @@
});
}
+void testDecode() {
+ // Code point U+10FFFF is the largest code point supported by Dart.
+ var controller = new StreamController(sync: true);
+ controller.add([0xf0, 0x90, 0x80, 0x80]); // U+10000
+ controller.add([0xf4, 0x8f, 0xbf, 0xbf]); // U+10FFFF
+ controller.add([0xf4, 0x90, 0x80, 0x80]); // U+110000
+ controller.add([0xfa, 0x80, 0x80, 0x80, 0x80]); // U+2000000
+ controller.add([0xfd, 0x80, 0x80, 0x80, 0x80, 0x80]); // U+40000000
+ controller.close();
+
+ StringDecoder.decode(controller.stream,
+ Encoding.UTF_8,
+ '?'.codeUnitAt(0)).then((decoded) {
+ Expect.equals(8, decoded.length);
+
+ var replacementChar = '?'.codeUnitAt(0);
+ Expect.equals(0xd800, decoded.codeUnitAt(0));
+ Expect.equals(0xdc00, decoded.codeUnitAt(1));
+ Expect.equals(0xdbff, decoded.codeUnitAt(2));
+ Expect.equals(0xdfff, decoded.codeUnitAt(3));
+ Expect.equals(replacementChar, decoded.codeUnitAt(4));
+ Expect.equals(replacementChar, decoded.codeUnitAt(5));
+ Expect.equals(replacementChar, decoded.codeUnitAt(6));
+ Expect.equals(replacementChar, decoded.codeUnitAt(7));
+ });
+}
+
void testInvalid() {
void invalid(var bytes, var outputLength) {
var controller = new StreamController(sync: true);
@@ -61,6 +88,7 @@
}
void main() {
- test();
+ testTransform();
+ testDecode();
testInvalid();
}
diff --git a/tests/standalone/io/test_extension_fail_test.dart b/tests/standalone/io/test_extension_fail_test.dart
index 96d0a3a..aa10592 100644
--- a/tests/standalone/io/test_extension_fail_test.dart
+++ b/tests/standalone/io/test_extension_fail_test.dart
@@ -37,10 +37,8 @@
}
void main() {
- Options options = new Options();
-
- Path scriptDirectory = new Path(options.script).directoryPath;
- Path buildDirectory = new Path(options.executable).directoryPath;
+ Path scriptDirectory = new Path(Platform.script).directoryPath;
+ Path buildDirectory = new Path(Platform.executable).directoryPath;
Directory tempDirectory = new Directory('').createTempSync();
Path testDirectory = new Path(tempDirectory.path);
@@ -56,7 +54,7 @@
return copyFileToDirectory(testExtensionTesterFile, testDirectory);
}).then((_) {
Path script = testDirectory.append('test_extension_fail_tester.dart');
- return Process.run(options.executable, [script.toNativePath()]);
+ return Process.run(Platform.executable, [script.toNativePath()]);
}).then((ProcessResult result) {
print("ERR: ${result.stderr}\n\n");
print("OUT: ${result.stdout}\n\n");
diff --git a/tests/standalone/io/test_extension_test.dart b/tests/standalone/io/test_extension_test.dart
index 9961daf..f4b73c8 100644
--- a/tests/standalone/io/test_extension_test.dart
+++ b/tests/standalone/io/test_extension_test.dart
@@ -37,10 +37,8 @@
}
void main() {
- Options options = new Options();
-
- Path scriptDirectory = new Path(options.script).directoryPath;
- Path buildDirectory = new Path(options.executable).directoryPath;
+ Path scriptDirectory = new Path(Platform.script).directoryPath;
+ Path buildDirectory = new Path(Platform.executable).directoryPath;
Directory tempDirectory = new Directory('').createTempSync();
Path testDirectory = new Path(tempDirectory.path);
@@ -56,7 +54,7 @@
return copyFileToDirectory(testExtensionTesterFile, testDirectory);
}).then((_) {
Path script = testDirectory.append('test_extension_tester.dart');
- return Process.run(options.executable, [script.toNativePath()]);
+ return Process.run(Platform.executable, [script.toNativePath()]);
})..then((ProcessResult result) {
Expect.equals(0, result.exitCode);
tempDirectory.deleteSync(recursive: true);
diff --git a/tests/standalone/io/test_runner_exit_code_script.dart b/tests/standalone/io/test_runner_exit_code_script.dart
index 1cfe603..02ca770 100644
--- a/tests/standalone/io/test_runner_exit_code_script.dart
+++ b/tests/standalone/io/test_runner_exit_code_script.dart
@@ -10,7 +10,7 @@
import "../../../tools/testing/dart/test_options.dart";
main() {
- var progressType = new Options().arguments[0];
+ var progressType = Platform.arguments[0];
// Build a progress indicator.
var startTime = new DateTime.now();
var progress =
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index f4a975d..fa276c2 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -71,8 +71,8 @@
}
TestCase _makeNormalTestCase(name, expectations) {
- var command = new Command(new Options().executable,
- [new Options().script, name]);
+ var command = new Command(Platform.executable,
+ [Platform.script, name]);
return _makeTestCase(name, DEFAULT_TIMEOUT, command, expectations);
}
@@ -109,7 +109,7 @@
// Run the test_runner_test if there are no command-line options.
// Otherwise, run one of the component tests that always pass,
// fail, or timeout.
- var arguments = new Options().arguments;
+ var arguments = Platform.arguments;
if (arguments.isEmpty) {
testProcessQueue();
} else {
diff --git a/tests/standalone/io/web_socket_test.dart b/tests/standalone/io/web_socket_test.dart
index cd72efa..96db483 100644
--- a/tests/standalone/io/web_socket_test.dart
+++ b/tests/standalone/io/web_socket_test.dart
@@ -405,7 +405,7 @@
void initializeSSL() {
var testPkcertDatabase =
- new Path(new Options().script).directoryPath.append("pkcert/");
+ new Path(Platform.script).directoryPath.append("pkcert/");
SecureSocket.initialize(database: testPkcertDatabase.toNativePath(),
password: "dartdart");
}
diff --git a/tests/standalone/io/windows_environment_test.dart b/tests/standalone/io/windows_environment_test.dart
index 6508da8..017132f 100644
--- a/tests/standalone/io/windows_environment_test.dart
+++ b/tests/standalone/io/windows_environment_test.dart
@@ -16,9 +16,8 @@
set SCRIPTDIR=%~dp0
%1 %2
""");
- var options = new Options();
- var dart = options.executable;
- var scriptDir = new Path(options.script).directoryPath;
+ var dart = Platform.executable;
+ var scriptDir = new Path(Platform.script).directoryPath;
var script = scriptDir.append('windows_environment_script.dart');
Process.run('cmd',
['/c', funkyFile.path, dart, script.toNativePath()]).then((p) {
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index e08da8e..c855cff 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -15,6 +15,7 @@
# Fails because checked-in dart executable is not up to date.
# Skip this because it is leaving temp directories behind when it fails.
io/skipping_dart2js_compilations_test: Skip
+io/web_socket_test: Pass, Crash # Issue 11502
[ $runtime == vm ]
package/package_isolate_test: Fail # http://dartbug.com/7520.
@@ -81,15 +82,24 @@
[ $compiler == dartanalyzer ]
-io/file_constructor_test: fail
-io/http_cookie_date_test: fail
-io/http_headers_test: fail
-io/http_parser_test: fail
-io/process_exit_negative_test: fail
-io/url_encoding_test: fail
-io/web_socket_protocol_processor_test: fail
53bit_overflow_literal_test/01: fail, ok
+# test issue https://code.google.com/p/dart/issues/detail?id=11518
+io/file_constructor_test: fail
+
+# The dart:io library is created at build time from separate files, and
+# there is no language-spec compatible way to run unit tests on the private
+# members and methods of dart:io.
+# Dart analyzer spots the misuse of 'part' directives in these unit tests.
+io/http_headers_test: Skip
+io/http_cookie_date_test: Skip
+io/url_encoding_test: Skip
+io/http_parser_test: Skip
+io/web_socket_protocol_processor_test: Skip
+
+# This is runtime test.
+io/process_exit_negative_test: Skip
+
# Fails because checked-in dart executable is not up to date.
io/test_runner_test: fail
io/skipping_dart2js_compilations_test: fail
@@ -153,22 +163,15 @@
[ $compiler == dart2js && $checked ]
io/http_read_test: Skip # Timeout TODO(ngeoffray): investigate
io/list_input_stream_test: Skip # Timeout TODO(ngeoffray): investigate
+io/http_parser_test: Fail # dartbug.com/11273
[ $compiler == dart2dart ]
# Skip until we stabilize language tests.
*: Skip
[ $arch == arm || $arch == simarm ]
-coverage_test: Crash # Issue: 11207
-debugger/basic_debugger_test: Crash # Issue: 11207
-debugger/closure_debugger_test: Crash # Issue: 11207
-http_launch_test: Fail, Crash # Issue: 11207
-left_shift_bit_and_op_test: Fail # Issue: 11207
-package/package_isolate_test: Pass, Crash # Issue: 11207
-out_of_memory_test: Pass, Crash # Issue: 11207 (Pass on Mac)
-typed_data_test: Timeout, Crash # Issue: 11207
-typed_data_isolate_test: Pass, Crash # Issue: 11207
-io/*: Skip # Skip IO tests for now as they are still quite flaky.
+*: Skip # Many of these tests are still flaky on arm, so skipping until we
+ # actually start working on implementing the needed features.
[ $arch == mips ]
*: Skip
diff --git a/tests/standalone/typed_data_isolate_test.dart b/tests/standalone/typed_data_isolate_test.dart
index 086a20f..852cc1e 100644
--- a/tests/standalone/typed_data_isolate_test.dart
+++ b/tests/standalone/typed_data_isolate_test.dart
@@ -22,7 +22,7 @@
}
main() {
- new File(new Options().script).readAsBytes().then((List<int> data) {
+ new File(Platform.script).readAsBytes().then((List<int> data) {
spawnFunction(second).call(data).then((reply) {
print('got reply');
port.close();
diff --git a/tools/VERSION b/tools/VERSION
index ed3d747..9ed370f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
-MINOR 5
-BUILD 20
-PATCH 4
+MINOR 6
+BUILD 0
+PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 9dab287..82eafe2 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -164,6 +164,8 @@
if UseBrowserController(runtime, system):
cmd.append('--use_browser_controller')
+ if runtime == 'safari':
+ cmd.append('--clear_safari_cache')
global IsFirstTestStepCall
if IsFirstTestStepCall:
diff --git a/tools/bots/editor.py b/tools/bots/editor.py
index 80d85d4..6879b93 100755
--- a/tools/bots/editor.py
+++ b/tools/bots/editor.py
@@ -4,12 +4,22 @@
# BSD-style license that can be found in the LICENSE file.
import os
+import re
import shutil
import sys
import tempfile
import bot
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+sys.path.append(os.path.join(SCRIPT_DIR, '..'))
+import utils
+
+
+GSUTIL = utils.GetBuildbotGSUtilPath()
+GCS_DARTIUM_BUCKET = "gs://dartium-archive/continuous"
+GCS_EDITOR_BUCKET = "gs://continuous-editor-archive"
+
class TempDir(object):
def __enter__(self):
self._temp_dir = tempfile.mkdtemp('eclipse-workspace')
@@ -18,31 +28,95 @@
def __exit__(self, *_):
shutil.rmtree(self._temp_dir, ignore_errors = True)
-def GetEditorExecutable(mode, arch):
+def GetBuildDirectory(mode, arch):
configuration_dir = mode + arch.upper()
- linux_path = os.path.join('out', configuration_dir, 'editor')
- win_path = os.path.join('build', configuration_dir, 'editor')
- mac_path = os.path.join('xcodebuild', configuration_dir, 'editor')
+ build_directory_dict = {
+ 'linux2' : os.path.join('out', configuration_dir),
+ 'darwin' : os.path.join('xcodebuild', configuration_dir),
+ 'win32' : os.path.join('build', configuration_dir),
+ }
+ if sys.platform == 'darwin':
+ # TODO(kustermann,ricow): Maybe we're able to get rid of this in the future.
+ # We use ninja on bots which use out/ (i.e. what linux2 does) instead of
+ # xcodebuild/
+ if (os.path.exists(build_directory_dict['linux2']) and
+ os.path.isdir(build_directory_dict['linux2'])):
+ return build_directory_dict['linux2']
+ return build_directory_dict[sys.platform]
+def GetEditorDirectory(mode, arch):
+ return os.path.join(GetBuildDirectory(mode, arch), 'editor')
+
+def GetDartSdkDirectory(mode, arch):
+ return os.path.join(GetBuildDirectory(mode, arch), 'dart-sdk')
+
+def GetEditorExecutable(mode, arch):
+ editor_dir = GetEditorDirectory(mode, arch)
if sys.platform == 'darwin':
executable = os.path.join('DartEditor.app', 'Contents', 'MacOS',
'DartEditor')
- # TODO(kustermann,ricow): Maybe we're able to get rid of this in the future.
- # We use ninja on bots which use out/ instead of xcodebuild/
- if os.path.exists(linux_path) and os.path.isdir(linux_path):
- return os.path.join(linux_path, executable)
- else:
- return os.path.join(mac_path, executable)
elif sys.platform == 'win32':
- return os.path.join(win_path, 'DartEditor.exe')
+ executable = 'DartEditor.exe'
elif sys.platform == 'linux2':
- return os.path.join(linux_path, 'DartEditor')
+ executable = 'DartEditor'
else:
raise Exception('Unknown platform %s' % sys.platform)
+ return os.path.join(editor_dir, executable)
+def RunProcess(args):
+ print 'Running: %s' % (' '.join(args))
+ sys.stdout.flush()
+ bot.RunProcess(args)
+
+def DownloadDartium(temp_dir, zip_file):
+ """Returns the filename of the unpacked archive"""
+ local_path = os.path.join(temp_dir, zip_file)
+ uri = "%s/%s" % (GCS_DARTIUM_BUCKET, zip_file)
+ RunProcess([GSUTIL, 'cp', uri, local_path])
+ RunProcess(['unzip', local_path, '-d', temp_dir])
+ for filename in os.listdir(temp_dir):
+ match = re.search('^dartium-.*-inc-([0-9]+)\.0$', filename)
+ if match:
+ return os.path.join(temp_dir, match.group(0))
+ raise Exception("Couldn't find dartium archive")
+
+def UploadInstaller(dart_editor_dmg, directory):
+ directory = directory % {'revision' : utils.GetSVNRevision()}
+ uri = '%s/%s' % (GCS_EDITOR_BUCKET, directory)
+ RunProcess([GSUTIL, 'cp', dart_editor_dmg, uri])
+
+def CreateAndUploadMacInstaller(arch):
+ dart_icns = os.path.join(
+ 'editor', 'tools', 'plugins', 'com.google.dart.tools.deploy',
+ 'icons', 'dart.icns')
+ mac_build_bundle_py = os.path.join('tools', 'mac_build_editor_bundle.sh')
+ mac_build_dmg_py = os.path.join('tools', 'mac_build_editor_dmg.sh')
+ editor_dir = GetEditorDirectory('Release', arch)
+ dart_sdk = GetDartSdkDirectory('Release', arch)
+ with TempDir() as temp_dir:
+ # Get dartium
+ dartium_directory = DownloadDartium(temp_dir, 'dartium-mac.zip')
+ dartium_bundle_dir = os.path.join(dartium_directory,
+ 'Chromium.app')
+
+ # Build the editor bundle
+ darteditor_bundle_dir = os.path.join(temp_dir, 'DartEditor.app')
+ args = [mac_build_bundle_py, darteditor_bundle_dir, editor_dir,
+ dart_sdk, dartium_bundle_dir, dart_icns]
+ RunProcess(args)
+
+ # Build the dmg installer from the editor bundle
+ dart_editor_dmg = os.path.join(temp_dir, 'DartEditor.dmg')
+ args = [mac_build_dmg_py, dart_editor_dmg, darteditor_bundle_dir,
+ dart_icns, 'Dart Editor']
+ RunProcess(args)
+
+ # Upload the dmg installer
+ UploadInstaller(dart_editor_dmg, 'dart-editor-mac-%(revision)s.dmg')
def main():
build_py = os.path.join('tools', 'build.py')
+
architectures = ['ia32', 'x64']
test_architectures = ['x64']
if sys.platform == 'win32':
@@ -52,19 +126,24 @@
for arch in architectures:
with bot.BuildStep('Build Editor %s' % arch):
args = [sys.executable, build_py,
- '-mrelease', '--arch=%s' % arch, 'editor']
- print 'Running: %s' % (' '.join(args))
- sys.stdout.flush()
- bot.RunProcess(args)
+ '-mrelease', '--arch=%s' % arch, 'editor', 'create_sdk']
+ RunProcess(args)
for arch in test_architectures:
editor_executable = GetEditorExecutable('Release', arch)
with bot.BuildStep('Test Editor %s' % arch):
with TempDir() as temp_dir:
args = [editor_executable, '--test', '--auto-exit', '-data', temp_dir]
- print 'Running: %s' % (' '.join(args))
- sys.stdout.flush()
- bot.RunProcess(args)
+ RunProcess(args)
+
+ # TODO: Permissions need to be clarified
+ for arch in test_architectures:
+ with bot.BuildStep('Build Installer %s' % arch):
+ if sys.platform == 'darwin':
+ CreateAndUploadMacInstaller(arch)
+ else:
+ print ("We currently don't build installers for sys.platform=%s"
+ % sys.platform)
return 0
if __name__ == '__main__':
diff --git a/tools/build.py b/tools/build.py
index c666fbab..8b6fbf3 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -344,112 +344,113 @@
# Determine which targets to build. By default we build the "all" target.
if len(args) == 0:
if HOST_OS == 'macos':
- target = 'All'
+ targets = ['All']
else:
- target = 'all'
+ targets = ['all']
else:
- target = args[0]
+ targets = args
filter_xcodebuild_output = False
# Remember path
old_path = os.environ['PATH']
- # Build the targets for each requested configuration.
- for target_os in options.os:
- for mode in options.mode:
- for arch in options.arch:
- os.environ['DART_BUILD_MODE'] = mode
- build_config = utils.GetBuildConf(mode, arch)
- if HOST_OS == 'macos':
- filter_xcodebuild_output = True
- project_file = 'dart.xcodeproj'
- if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
- project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName()
- args = ['xcodebuild',
- '-project',
- project_file,
- '-target',
- target,
- '-configuration',
- build_config,
- 'SYMROOT=%s' % os.path.abspath('xcodebuild')
- ]
- elif HOST_OS == 'win32':
- project_file = 'dart.sln'
- if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
- project_file = 'dart-%s.sln' % CurrentDirectoryBaseName()
- if target == 'all':
- args = [options.devenv + os.sep + options.executable,
- '/build',
- build_config,
- project_file
- ]
- else:
- args = [options.devenv + os.sep + options.executable,
- '/build',
- build_config,
- '/project',
+ # Build all targets for each requested configuration.
+ for target in targets:
+ for target_os in options.os:
+ for mode in options.mode:
+ for arch in options.arch:
+ os.environ['DART_BUILD_MODE'] = mode
+ build_config = utils.GetBuildConf(mode, arch)
+ if HOST_OS == 'macos':
+ filter_xcodebuild_output = True
+ project_file = 'dart.xcodeproj'
+ if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
+ project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName()
+ args = ['xcodebuild',
+ '-project',
+ project_file,
+ '-target',
target,
- project_file
- ]
- else:
- make = 'make'
- if HOST_OS == 'freebsd':
- make = 'gmake'
- # work around lack of flock
- os.environ['LINK'] = '$(CXX)'
- args = [make,
- '-j',
- options.j,
- 'BUILDTYPE=' + build_config,
- ]
- if target_os != HOST_OS:
- args += ['builddir_name=' + utils.GetBuildDir(HOST_OS, target_os)]
- if options.verbose:
- args += ['V=1']
-
- args += [target]
-
- if target_os != HOST_OS:
- SetCrossCompilationEnvironment(
- HOST_OS, target_os, arch, old_path)
-
- RunhooksIfNeeded(HOST_OS, mode, arch, target_os)
-
- toolchainprefix = None
- if target_os == 'android':
- toolchainprefix = ('%s/i686-linux-android'
- % os.environ['ANDROID_TOOLCHAIN'])
- toolsOverride = SetTools(arch, toolchainprefix)
- if toolsOverride:
- printToolOverrides = target_os != 'android'
- for k, v in toolsOverride.iteritems():
- args.append( k + "=" + v)
- if printToolOverrides:
- print k + " = " + v
- if not os.path.isfile(toolsOverride['CC.target']):
- if arch == 'arm':
- print arm_cc_error
+ '-configuration',
+ build_config,
+ 'SYMROOT=%s' % os.path.abspath('xcodebuild')
+ ]
+ elif HOST_OS == 'win32':
+ project_file = 'dart.sln'
+ if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
+ project_file = 'dart-%s.sln' % CurrentDirectoryBaseName()
+ if target == 'all':
+ args = [options.devenv + os.sep + options.executable,
+ '/build',
+ build_config,
+ project_file
+ ]
else:
- print "Couldn't find compiler: %s" % toolsOverride['CC.target']
+ args = [options.devenv + os.sep + options.executable,
+ '/build',
+ build_config,
+ '/project',
+ target,
+ project_file
+ ]
+ else:
+ make = 'make'
+ if HOST_OS == 'freebsd':
+ make = 'gmake'
+ # work around lack of flock
+ os.environ['LINK'] = '$(CXX)'
+ args = [make,
+ '-j',
+ options.j,
+ 'BUILDTYPE=' + build_config,
+ ]
+ if target_os != HOST_OS:
+ args += ['builddir_name=' + utils.GetBuildDir(HOST_OS, target_os)]
+ if options.verbose:
+ args += ['V=1']
+
+ args += [target]
+
+ if target_os != HOST_OS:
+ SetCrossCompilationEnvironment(
+ HOST_OS, target_os, arch, old_path)
+
+ RunhooksIfNeeded(HOST_OS, mode, arch, target_os)
+
+ toolchainprefix = None
+ if target_os == 'android':
+ toolchainprefix = ('%s/i686-linux-android'
+ % os.environ['ANDROID_TOOLCHAIN'])
+ toolsOverride = SetTools(arch, toolchainprefix)
+ if toolsOverride:
+ printToolOverrides = target_os != 'android'
+ for k, v in toolsOverride.iteritems():
+ args.append( k + "=" + v)
+ if printToolOverrides:
+ print k + " = " + v
+ if not os.path.isfile(toolsOverride['CC.target']):
+ if arch == 'arm':
+ print arm_cc_error
+ else:
+ print "Couldn't find compiler: %s" % toolsOverride['CC.target']
+ return 1
+
+
+ print ' '.join(args)
+ process = None
+ if filter_xcodebuild_output:
+ process = subprocess.Popen(args,
+ stdin=None,
+ bufsize=1, # Line buffered.
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ FilterEmptyXcodebuildSections(process)
+ else:
+ process = subprocess.Popen(args, stdin=None)
+ process.wait()
+ if process.returncode != 0:
+ print "BUILD FAILED"
return 1
-
- print ' '.join(args)
- process = None
- if filter_xcodebuild_output:
- process = subprocess.Popen(args,
- stdin=None,
- bufsize=1, # Line buffered.
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- FilterEmptyXcodebuildSections(process)
- else:
- process = subprocess.Popen(args, stdin=None)
- process.wait()
- if process.returncode != 0:
- print "BUILD FAILED"
- return 1
-
return 0
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index 3ba329e..5c8279d 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -257,7 +257,7 @@
" * var ctx = canvas.context2D",
" * ..fillStyle = \"rgb(200,0,0)\"",
" * ..fillRect(10, 10, 55, 50);",
- " * var dataUrl = canvas.toDataURL(\"image/jpeg\", 0.95);",
+ " * var dataUrl = canvas.toDataUrl(\"image/jpeg\", 0.95);",
" * // The Data Uri would look similar to",
" * // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA",
" * // AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO",
@@ -363,7 +363,7 @@
" *",
" * To receive data on the WebSocket, register a listener for message events.",
" *",
- " * webSocket.on.message.add((MessageEvent e) {",
+ " * webSocket.onMessage.listen((MessageEvent e) {",
" * receivedData(e.data);",
" * });",
" *",
diff --git a/tools/dom/dom.json b/tools/dom/dom.json
index 67bf2043..0fba769 100644
--- a/tools/dom/dom.json
+++ b/tools/dom/dom.json
@@ -2153,7 +2153,8 @@
"DRAW_BUFFER8_EXT": {},
"DRAW_BUFFER9_EXT": {},
"MAX_COLOR_ATTACHMENTS_EXT": {},
- "MAX_DRAW_BUFFERS_EXT": {}
+ "MAX_DRAW_BUFFERS_EXT": {},
+ "drawBuffersEXT": {}
},
"support_level": "stable"
},
diff --git a/tools/dom/scripts/dartgenerator.py b/tools/dom/scripts/dartgenerator.py
index 4f6de3a..8635eff 100755
--- a/tools/dom/scripts/dartgenerator.py
+++ b/tools/dom/scripts/dartgenerator.py
@@ -85,7 +85,10 @@
if (type_name is not None and
self._IsCompoundType(database, type_name)):
continue
- _logger.warn('removing %s in %s which has unidentified type %s' %
+ # Ignore constructor warnings.
+ if not (interface.id in ['DOMWindow', 'WorkerContext'] and
+ type_name.endswith('Constructor')):
+ _logger.warn('removing %s in %s which has unidentified type %s' %
(node_name, interface.id, type_name))
return False
return True
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index 34d151a..4d1b866 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -198,7 +198,7 @@
"@Returns('int|String|Null')",
],
- 'MessageEvent.ports': ["@Creates('=List')"],
+ 'MessageEvent.ports': ["@Creates('JSExtendableArray')"],
'MessageEvent.data': [
"@annotation_Creates_SerializedScriptValue",
@@ -271,8 +271,10 @@
],
'WebGLRenderingContext.getUniform': [
- "@Creates('Null|num|String|bool|=List|Float32List|Int32List|Uint32List')",
- "@Returns('Null|num|String|bool|=List|Float32List|Int32List|Uint32List')",
+ "@Creates('Null|num|String|bool|JSExtendableArray|Float32List|Int32List"
+ "|Uint32List')",
+ "@Returns('Null|num|String|bool|JSExtendableArray|Float32List|Int32List"
+ "|Uint32List')",
],
'WebGLRenderingContext.getVertexAttrib': [
@@ -283,14 +285,15 @@
'WebGLRenderingContext.getParameter': [
# Taken from http://www.khronos.org/registry/webgl/specs/latest/
# Section 5.14.3 Setting and getting state
- "@Creates('Null|num|String|bool|=List|Float32List|Int32List|Uint32List"
- "|Framebuffer|Renderbuffer|Texture')",
- "@Returns('Null|num|String|bool|=List|Float32List|Int32List|Uint32List"
- "|Framebuffer|Renderbuffer|Texture')",
+ "@Creates('Null|num|String|bool|JSExtendableArray|Float32List|Int32List"
+ "|Uint32List|Framebuffer|Renderbuffer|Texture')",
+ "@Returns('Null|num|String|bool|JSExtendableArray|Float32List|Int32List"
+ "|Uint32List|Framebuffer|Renderbuffer|Texture')",
],
'XMLHttpRequest.response': [
- "@Creates('ByteBuffer|Blob|Document|=Object|=List|String|num')",
+ "@Creates('ByteBuffer|Blob|Document|=Object|JSExtendableArray|String"
+ "|num')",
],
}, dart2jsOnly=True)
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 5f2a6d3..da2a88f 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -1028,6 +1028,8 @@
'Future': TypeData(clazz='Interface', dart_type='Future'),
'GamepadList': TypeData(clazz='Interface', item_type='Gamepad',
suppress_interface=True),
+ 'GLenum': TypeData(clazz='Primitive', dart_type='int',
+ native_type='unsigned'),
'HTMLAllCollection': TypeData(clazz='Interface', item_type='Node'),
'HTMLCollection': TypeData(clazz='Interface', item_type='Node'),
'NamedNodeMap': TypeData(clazz='Interface', item_type='Node'),
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 53b2328..3d013e4 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -388,7 +388,6 @@
'DOMWindow.webkitCancelRequestAnimationFrame',
'DOMWindow.webkitIndexedDB',
'DOMWindow.webkitRequestAnimationFrame',
- 'Document.adoptNode',
'Document.alinkColor',
'Document.all',
'Document.applets',
@@ -424,7 +423,6 @@
'Document.getOverrideStyle',
'Document.getSelection',
'Document.images',
- 'Document.importNode',
'Document.linkColor',
'Document.location',
'Document.open',
diff --git a/tools/dom/src/WrappedList.dart b/tools/dom/src/WrappedList.dart
index b725b96..145c9ab 100644
--- a/tools/dom/src/WrappedList.dart
+++ b/tools/dom/src/WrappedList.dart
@@ -37,9 +37,9 @@
void sort([int compare(E a, E b)]) { _list.sort(compare); }
- int indexOf(E element, [int start = 0]) => _list.indexOf(element, start);
+ int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
- int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start);
+ int lastIndexOf(Object element, [int start]) => _list.lastIndexOf(element, start);
void insert(int index, E element) => _list.insert(index, element);
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index b9885df..e213565 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -7,6 +7,10 @@
// Auto-generated dart:html library.
/// The Dart HTML library.
+///
+/// For examples, see
+/// [Dart HTML5 Samples](https://github.com/dart-lang/dart-html5-samples)
+/// on Github.
library dart.dom.html;
import 'dart:async';
@@ -25,7 +29,7 @@
import 'dart:web_gl' as gl;
import 'dart:web_sql';
import 'dart:_js_helper' show convertDartClosureToJS, Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
-import 'dart:_interceptors' show Interceptor;
+import 'dart:_interceptors' show Interceptor, JSExtendableArray;
import 'dart:_isolate_helper' show IsolateNatives;
import 'dart:_foreign_helper' show JS;
@@ -42,7 +46,6 @@
part '$AUXILIARY_DIR/KeyCode.dart';
part '$AUXILIARY_DIR/KeyLocation.dart';
part '$AUXILIARY_DIR/KeyName.dart';
-part '$AUXILIARY_DIR/PathObserver.dart';
part '$AUXILIARY_DIR/Point.dart';
part '$AUXILIARY_DIR/ReadyState.dart';
part '$AUXILIARY_DIR/Rectangle.dart';
diff --git a/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate b/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
index 7c4b25a..cea5133 100644
--- a/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
+++ b/tools/dom/templates/html/dart2js/impl_KeyboardEvent.darttemplate
@@ -3,6 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
+/**
+ * An event that describes user interaction with the keyboard.
+ *
+ * The [type] of the event identifies what kind of interaction occurred.
+ *
+ * See also:
+ *
+ * * [KeyboardEvent](https://developer.mozilla.org/en/DOM/KeyboardEvent) at MDN.
+ */
$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
factory $CLASSNAME(String type,
diff --git a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
index 8a96fbb..06d1e31 100644
--- a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
@@ -14,6 +14,7 @@
import 'dart:typed_data';
import 'dart:_js_helper' show Creates, Returns, JSName, Null;
import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSExtendableArray;
$!GENERATED_DART_FILES
@@ -127,7 +128,7 @@
return convertNativeToDart_AcceptStructuredClone(object, mustCopy: false);
}
-
-const String _idbKey = '=List|=Object|num|String'; // TODO(sra): Add DateTime.
+// TODO(sra): Add DateTime.
+const String _idbKey = 'JSExtendableArray|=Object|num|String';
const _annotation_Creates_IDBKey = const Creates(_idbKey);
const _annotation_Returns_IDBKey = const Returns(_idbKey);
diff --git a/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate b/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
index ad41aba..a4124e7 100644
--- a/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/web_gl_dart2js.darttemplate
@@ -11,7 +11,7 @@
import 'dart:typed_data';
import 'dart:_js_helper' show Creates, JSName, Null, Returns, convertDartClosureToJS;
import 'dart:_foreign_helper' show JS;
-import 'dart:_interceptors' show Interceptor;
+import 'dart:_interceptors' show Interceptor, JSExtendableArray;
part '$AUXILIARY_DIR/WebGLConstants.dart';
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate
index 9c7b733..2cdb23b 100644
--- a/tools/dom/templates/html/dartium/html_dartium.darttemplate
+++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -6,6 +6,10 @@
// Auto-generated dart:html library.
/// The Dart HTML library.
+///
+/// For examples, see
+/// [Dart HTML5 Samples](https://github.com/dart-lang/dart-html5-samples)
+/// on Github.
library dart.dom.html;
import 'dart:async';
@@ -38,7 +42,6 @@
part '$AUXILIARY_DIR/KeyCode.dart';
part '$AUXILIARY_DIR/KeyLocation.dart';
part '$AUXILIARY_DIR/KeyName.dart';
-part '$AUXILIARY_DIR/PathObserver.dart';
part '$AUXILIARY_DIR/Point.dart';
part '$AUXILIARY_DIR/ReadyState.dart';
part '$AUXILIARY_DIR/Rectangle.dart';
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index a6e165d..c5bf740 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -13,7 +13,7 @@
: _childElements = element.$dom_children,
_element = element;
- bool contains(Element element) => _childElements.contains(element);
+ bool contains(Object element) => _childElements.contains(element);
bool get isEmpty {
diff --git a/tools/gyp/configurations_make.gypi b/tools/gyp/configurations_make.gypi
index eec4dc5..ba2445a 100644
--- a/tools/gyp/configurations_make.gypi
+++ b/tools/gyp/configurations_make.gypi
@@ -90,9 +90,7 @@
},
'Dart_Release': {
- 'cflags': [ '-O3',
- '-fno-omit-frame-pointer',
- ],
+ 'cflags': [ '-O3', ],
},
},
},
diff --git a/tools/mac_build_editor_bundle.sh b/tools/mac_build_editor_bundle.sh
new file mode 100755
index 0000000..14b8054
--- /dev/null
+++ b/tools/mac_build_editor_bundle.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by
+# BSD-style license that can be found in the LICENSE file.
+
+# Fail if a command failed
+set -e
+
+if [ $# -ne 5 ]; then
+ echo "Usage $0 <app-folder> <editor-build-directory> <dart-sdk> " \
+ "<Chromium.app> <icon.icns>"
+ exit 1
+fi
+
+OUTPUT_APP_FOLDER=$1
+INPUT_EDITOR_BUILD_DIRECTORY=$2
+INPUT_DART_SDK_DIRECTORY=$3
+INPUT_CHROMIUM_APP_DIRECTORY=$4
+INPUT_ICON_PATH=$5
+
+# Input validations
+if [ "${OUTPUT_APP_FOLDER##*.}" != "app" ]; then
+ echo "Application folder has to end in '.app' " \
+ "(but was $APP_FOLDER_NAME)."
+ exit 1
+fi
+if [ "${INPUT_ICON_PATH##*.}" != "icns" ]; then
+ echo "Application icon has to end in '.icns'."
+ exit 1
+fi
+
+function ensure_exists {
+ if [ ! -e "$1" ]; then
+ echo "Directory or file does not exist: $1."
+ exit 1
+ fi
+}
+ensure_exists "$INPUT_EDITOR_BUILD_DIRECTORY"
+ensure_exists "$INPUT_DART_SDK_DIRECTORY"
+
+# Remove old directory if present
+if [ -e "$OUTPUT_APP_FOLDER" ]; then
+ rm -r "$OUTPUT_APP_FOLDER"
+fi
+
+# Make directory structure and copy necessary files
+mkdir -p "$OUTPUT_APP_FOLDER/Contents/MacOS"
+LAUNCHER_SUBPATH="DartEditor.app/Contents/MacOS/DartEditor"
+cp "$INPUT_EDITOR_BUILD_DIRECTORY/$LAUNCHER_SUBPATH" \
+ "$OUTPUT_APP_FOLDER/Contents/MacOS/"
+cp "$INPUT_EDITOR_BUILD_DIRECTORY/$LAUNCHER_SUBPATH.ini" \
+ "$OUTPUT_APP_FOLDER/Contents/MacOS/"
+mkdir -p "$OUTPUT_APP_FOLDER/Contents/Resources"
+cp "$INPUT_ICON_PATH" "$OUTPUT_APP_FOLDER/Contents/Resources/dart.icns"
+cp -R "$INPUT_DART_SDK_DIRECTORY" \
+ "$OUTPUT_APP_FOLDER/Contents/Resources/dart-sdk"
+cp -R "$INPUT_CHROMIUM_APP_DIRECTORY" \
+ "$OUTPUT_APP_FOLDER/Contents/Resources/Chromium.app"
+for dirname in $(echo configuration plugins features samples); do
+ cp -R "$INPUT_EDITOR_BUILD_DIRECTORY/$dirname" \
+ "$OUTPUT_APP_FOLDER/Contents/Resources/"
+done
+
+EQUINOX_LAUNCHER_JARFILE=$(cd "$OUTPUT_APP_FOLDER"; \
+ ls Contents/Resources/plugins/org.eclipse.equinox.launcher_*.jar);
+
+EQUINOX_LAUNCHER_LIBRARY=$(cd "$OUTPUT_APP_FOLDER"; ls \
+ Contents/Resources/plugins/org.eclipse.equinox.launcher.cocoa.*/eclipse_*.so);
+
+cat > "$OUTPUT_APP_FOLDER/Contents/Info.plist" << EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+ <dict>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+ <key>CFBundleExecutable</key>
+ <string>DartEditor</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Eclipse 3.7 for Mac OS X, Copyright IBM Corp. and others 2002,
+ 2011. All rights reserved.</string>
+ <key>CFBundleIconFile</key>
+ <string>dart.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.eclipse.eclipse</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>DartEditor</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>3.7</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>3.7</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleLocalizations</key>
+ <array>
+ <string>en</string>
+ <key>WorkingDirectory</key>
+ <string>\$APP_PACKAGE/Contents/Resources</string>
+ </array>
+ <key>Eclipse</key>
+ <array>
+ <string>-startup</string>
+ <string>\$APP_PACKAGE/$EQUINOX_LAUNCHER_JARFILE</string>
+ <string>--launcher.library</string>
+ <string>\$APP_PACKAGE/$EQUINOX_LAUNCHER_LIBRARY</string>
+ <string>-keyring</string><string>~/.eclipse_keyring</string>
+ <string>-showlocation</string>
+ <key>WorkingDirectory</key>
+ <string>\$APP_PACKAGE/Contents/Resources</string>
+ </array>
+ </dict>
+</plist>
+EOF
+
diff --git a/tools/mac_build_editor_dmg.sh b/tools/mac_build_editor_dmg.sh
new file mode 100755
index 0000000..2da8c0f
--- /dev/null
+++ b/tools/mac_build_editor_dmg.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by
+# BSD-style license that can be found in the LICENSE file.
+
+# This is partly based on
+# https://bitbucket.org/rmacnak/nsvm/src/
+# b2de52432a2baff9c4ada099430fb16a771d34ef/vm/onebuild/installer-Darwin.gmk
+
+# Fail if a command failed
+set -e
+
+if [ $# -ne 4 ]; then
+ echo "Usage $0 <output.dmg> <app-folder> <icon.icns> <volume-name>"
+ exit 1
+fi
+
+OUTPUT_DMG_FILE=$1
+INPUT_APP_FOLDER_PATH=$2
+INPUT_ICON=$3
+INPUT_VOLUME_NAME=$4
+
+APP_FOLDER_NAME=$(basename "$INPUT_APP_FOLDER_PATH")
+VOLUME_MOUNTPOINT="/Volumes/$INPUT_VOLUME_NAME"
+SPARSEIMAGE="$OUTPUT_DMG_FILE.sparseimage"
+
+# Input validations
+if [ "${INPUT_APP_FOLDER_PATH##*.}" != "app" ]; then
+ echo "Application folder has to end in '.app' " \
+ "(but was $INPUT_APP_FOLDER_PATH)."
+ exit 1
+fi
+if [ "${INPUT_ICON##*.}" != "icns" ]; then
+ echo "Volume icon has to end in '.icns'."
+ exit 1
+fi
+
+# If an old image is still mounted, umount it
+if [ -e "$VOLUME_MOUNTPOINT" ]; then
+ hdiutil eject "$VOLUME_MOUNTPOINT"
+fi
+
+# Remove old output files
+if [ -f "$SPARSEIMAGE" ]; then
+ rm "$SPARSEIMAGE"
+fi
+if [ -f "$OUTPUT_DMG_FILE" ]; then
+ rm "$OUTPUT_DMG_FILE"
+fi
+
+# Create a new image and attach it
+hdiutil create -size 300m -type SPARSE -volname "$INPUT_VOLUME_NAME" -fs \
+ 'Journaled HFS+' "$SPARSEIMAGE"
+hdiutil attach "$SPARSEIMAGE"
+
+# Add link to /Applications (so the user can drag-and-drop into it)
+ln -s /Applications "$VOLUME_MOUNTPOINT/"
+# Copy our application
+ditto "$INPUT_APP_FOLDER_PATH" "$VOLUME_MOUNTPOINT/$APP_FOLDER_NAME"
+# Make sure that the folder gets opened when mounting the image
+bless --folder "$VOLUME_MOUNTPOINT" --openfolder "$VOLUME_MOUNTPOINT"
+# Copy the volume icon
+cp "$INPUT_ICON" "$VOLUME_MOUNTPOINT/.VolumeIcon.icns"
+
+# Set the 'custom-icon' attribute on the volume
+SetFile -a C "$VOLUME_MOUNTPOINT"
+
+# Use an applescript to setup the layout of the folder.
+osascript << EOF
+tell application "Finder"
+ tell disk "$INPUT_VOLUME_NAME"
+ open
+ tell container window
+ set current view to icon view
+ set toolbar visible to false
+ set statusbar visible to false
+ set position to {100, 100}
+ set bounds to {100, 100, 512, 256}
+ end tell
+ tell icon view options of container window
+ set arrangement to not arranged
+ set icon size to 128
+ end tell
+ set position of item "$APP_FOLDER_NAME" to {64, 64}
+ set position of item "Applications" to {320, 64}
+ eject
+ end tell
+end tell
+EOF
+
+# Wait until the script above has umounted the image
+while [ -e "$VOLUME_MOUNTPOINT" ]; do
+ echo "Waiting for Finder to eject $VOLUME_MOUNTPOINT"
+ sleep 2
+done
+
+# Compress the sparse image
+hdiutil convert "$SPARSEIMAGE" -format UDBZ -o "$OUTPUT_DMG_FILE"
+
+# Remove sparse image
+rm "$SPARSEIMAGE"
+
diff --git a/tools/test.dart b/tools/test.dart
index c2da69a..fc789bf 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -27,6 +27,7 @@
import "dart:async";
import "dart:io";
import "dart:math" as math;
+import "testing/dart/browser_controller.dart";
import "testing/dart/http_server.dart";
import "testing/dart/record_and_replay.dart";
import "testing/dart/test_options.dart";
@@ -92,6 +93,10 @@
var recordingPath = firstConf['record_to_file'];
var recordingOutputPath = firstConf['replay_from_file'];
+ // We set a special flag in the safari browser if we need to clear out
+ // the cache before running.
+ Safari.deleteCache = firstConf['clear_safari_cache'];
+
if (recordingPath != null && recordingOutputPath != null) {
print("Fatal: Can't have the '--record_to_file' and '--replay_from_file'"
"at the same time. Exiting ...");
@@ -164,10 +169,9 @@
maxBrowserProcesses = 1;
} else if (conf['runtime'].startsWith('safari') &&
conf['use_browser_controller']) {
- // FIXME(kustermann/ricow): Remove this once the new browser_controller is
- // stable.
- maxBrowserProcesses = math.max(maxProcesses - 3, 1);
- maxProcesses = math.max(maxProcesses -1, 1);
+ // Safari does not allow us to run from a fresh profile, so we can only
+ // use one browser.
+ maxBrowserProcesses = 1;
}
for (String key in selectors.keys) {
@@ -245,7 +249,6 @@
}
eventListener.add(new ExitCodeSetter());
-
void startProcessQueue() {
// Start process queue.
new ProcessQueue(maxProcesses,
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 52628f1..f3d0acc 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -15,12 +15,11 @@
StringBuffer _stdout = new StringBuffer();
StringBuffer _stderr = new StringBuffer();
StringBuffer _usageLog = new StringBuffer();
- // This function is called when the process is closed.
- Completer _processClosedCompleter = new Completer();
- // This is called after the process is closed, after _processClosedCompleter
- // has been called, but before onExit. Subclasses can use this to cleanup
- // any browser specific resources (temp directories, profiles, etc)
- // The function is expected to do it's work synchronously.
+ // This is called after the process is closed, before the done future
+ // is completed.
+ // Subclasses can use this to cleanup any browser specific resources
+ // (temp directories, profiles, etc). The function is expected to do
+ // it's work synchronously.
Function _cleanup;
/** The version of the browser - normally set when starting a browser */
@@ -42,9 +41,9 @@
/** Print everything (stdout, stderr, usageLog) whenever we add to it */
bool debugPrint = false;
- // This future will be lazily set when calling close() and will complete once
- // the process did exit.
- Future browserTerminationFuture;
+ // This future returns when the process exits. It is also the return value
+ // of close()
+ Future done;
Browser();
@@ -90,30 +89,17 @@
Future close() {
_logEvent("Close called on browser");
- if (browserTerminationFuture == null) {
- var completer = new Completer();
- browserTerminationFuture = completer.future;
-
- if (process != null) {
- _processClosedCompleter.future.then((_) {
- process = null;
- completer.complete(true);
- if (_cleanup != null) {
- _cleanup();
- }
- });
-
- if (process.kill(ProcessSignal.SIGKILL)) {
- _logEvent("Successfully sent kill signal to process.");
- } else {
- _logEvent("Sending kill signal failed.");
- }
+ if (process != null) {
+ if (process.kill(ProcessSignal.SIGKILL)) {
+ _logEvent("Successfully sent kill signal to process.");
} else {
- _logEvent("The process is already dead.");
- completer.complete(true);
+ _logEvent("Sending kill signal failed.");
}
+ return done;
+ } else {
+ _logEvent("The process is already dead.");
+ return new Future.immediate(true);
}
- return browserTerminationFuture;
}
/**
@@ -123,6 +109,11 @@
Future<bool> startBrowser(String command, List<String> arguments) {
return Process.start(command, arguments).then((startedProcess) {
process = startedProcess;
+ // Used to notify when exiting, and as a return value on calls to
+ // close().
+ var doneCompleter = new Completer();
+ done = doneCompleter.future;
+
Completer stdoutDone = new Completer();
Completer stderrDone = new Completer();
@@ -149,7 +140,11 @@
process.exitCode.then((exitCode) {
_logEvent("Browser closed with exitcode $exitCode");
Future.wait([stdoutDone.future, stderrDone.future]).then((_) {
- _processClosedCompleter.complete(exitCode);
+ process = null;
+ if (_cleanup != null) {
+ _cleanup();
+ }
+ doneCompleter.complete(exitCode);
});
});
return true;
@@ -183,6 +178,16 @@
*/
const String versionFile = "/Applications/Safari.app/Contents/version.plist";
+ /**
+ * Directories where safari stores state. We delete these if the deleteCache
+ * is set
+ */
+ static const List<String> CACHE_DIRECTORIES =
+ const ["Library/Caches/com.apple.Safari",
+ "Library/Safari",
+ "Library/Saved Application State/com.apple.Safari.savedState",
+ "Library/Caches/Metadata/Safari"];
+
Future<bool> allowPopUps() {
var command = "defaults";
@@ -191,14 +196,42 @@
"WebKit2JavaScriptCanOpenWindowsAutomatically",
"1"];
return Process.run(command, args).then((result) {
- if (result.exitCode != 0) {
- _logEvent("Could not disable pop-up blocking for safari");
- return false;
- }
- return true;
+ if (result.exitCode != 0) {
+ _logEvent("Could not disable pop-up blocking for safari");
+ return false;
+ }
+ return true;
});
}
+ Future<bool> deleteIfExists(Iterator<String> paths) {
+ if (!paths.moveNext()) return new Future.immediate(true);
+ Directory directory = new Directory(paths.current);
+ return directory.exists().then((exists) {
+ if (exists) {
+ _logEvent("Deleting ${paths.current}");
+ return directory.delete(recursive: true)
+ .then((_) => deleteIfExists(paths))
+ .catchError((error) {
+ _logEvent("Failure trying to delete ${paths.current}: $error");
+ return false;
+ });
+ } else {
+ _logEvent("${paths.current} is not present");
+ return deleteIfExists(paths);
+ }
+ });
+ }
+
+ // Clears the cache if the static deleteCache flag is set.
+ // Returns false if the command to actually clear the cache did not complete.
+ Future<bool> clearCache() {
+ if (!deleteCache) return new Future.immediate(true);
+ var home = Platform.environment['HOME'];
+ Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
+ return deleteIfExists(iterator);
+ }
+
Future<String> getVersion() {
/**
* Example of the file:
@@ -242,28 +275,38 @@
Future<bool> start(String url) {
_logEvent("Starting Safari browser on: $url");
- // Get the version and log that.
return allowPopUps().then((success) {
if (!success) {
- return new Future.immediate(false);
- }
- return getVersion().then((version) {
- _logEvent("Got version: $version");
- var args = ["'$url'"];
- return new Directory('').createTemp().then((userDir) {
- _cleanup = () { userDir.deleteSync(recursive: true); };
- _createLaunchHTML(userDir.path, url);
- var args = ["${userDir.path}/launch.html"];
- return startBrowser(binary, args);
- });
- }).catchError((e) {
- _logEvent("Running $binary --version failed with $e");
return false;
+ }
+ return clearCache().then((cleared) {
+ if (!cleared) {
+ _logEvent("Could not clear cache");
+ return false;
+ }
+ // Get the version and log that.
+ return getVersion().then((version) {
+ _logEvent("Got version: $version");
+ return new Directory('').createTemp().then((userDir) {
+ _cleanup = () { userDir.deleteSync(recursive: true); };
+ _createLaunchHTML(userDir.path, url);
+ var args = ["${userDir.path}/launch.html"];
+ return startBrowser(binary, args);
+ });
+ }).catchError((error) {
+ _logEvent("Running $binary --version failed with $error");
+ return false;
+ });
});
});
}
String toString() => "Safari";
+
+ // Delete the user specific browser cache and profile data.
+ // Safari only have one per user, and you can't specify one by command line.
+ static bool deleteCache = false;
+
}
@@ -609,12 +652,7 @@
status.timeout = true;
timedOut.add(status.currentTest.url);
var id = status.browser.id;
- status.browser.close().then((closed) {
- if (!closed) {
- // Very bad, we could not kill the browser.
- print("could not kill browser $id");
- return;
- }
+ status.browser.close().then((_) {
// We don't want to start a new browser if we are terminating.
if (underTermination) return;
var browser;
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index a26a8b3..d241705 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -315,6 +315,14 @@
'bool'
),
new _TestOptionSpecification(
+ 'clear_safari_cache',
+ 'Clear the safari cache (i.e., delete it).',
+ ['--clear_safari_cache'],
+ [],
+ false,
+ 'bool'
+ ),
+ new _TestOptionSpecification(
'local_ip',
'IP address the http servers should listen on.'
'This address is also used for browsers to connect.',
@@ -454,9 +462,56 @@
List<Map> expandedConfigs = _expandConfigurations(configuration);
List<Map> result = expandedConfigs.where(_isValidConfig).toList();
+ for (var config in result) {
+ config['_reproducing_arguments_'] =
+ _constructReproducingCommandArguments(config);
+ }
return result.isEmpty ? null : result;
}
+ // For printing out reproducing command lines, we don't want to add these
+ // options.
+ Set<String> _blacklistedOptions = new Set<String>.from([
+ 'progress', 'failure-summary', 'step_name', 'report', 'tasks', 'verbose',
+ 'time', 'dart', 'drt', 'dartium', 'build_directory', 'append_logs',
+ 'write_debug_log', 'local_ip', 'shard', 'shards',
+ ]);
+
+ List<String> _constructReproducingCommandArguments(Map config) {
+ var arguments = new List<String>();
+ for (var configKey in config.keys) {
+ if (!_blacklistedOptions.contains(configKey)) {
+ for (var option in _options) {
+ var configValue = config[configKey];
+ // We only include entries of [conf] if we find an option for it.
+ if (configKey == option.name && configValue != option.defaultValue) {
+ var isBooleanOption = option.type == 'bool';
+ // Sort by length, so we get the shortest variant.
+ var possibleOptions = new List.from(option.keys);
+ possibleOptions.sort((a, b) => (a.length < b.length ? -1 : 1));
+ var key = possibleOptions[0];
+ if (key.startsWith('--')) {
+ // long version
+ arguments.add(key);
+ if (!isBooleanOption) {
+ arguments.add("$configValue");
+ }
+ } else {
+ // short version
+ assert(key.startsWith('-'));
+ if (!isBooleanOption) {
+ arguments.add("$key$configValue");
+ } else {
+ arguments.add(key);
+ }
+ }
+ }
+ }
+ }
+ }
+ return arguments;
+ }
+
/**
* Determine if a particular configuration has a valid combination of compiler
* and runtime elements.
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index f105505..8c8d7830 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -128,9 +128,24 @@
}
for (var i = 0; i < test.commands.length; i++) {
var command = test.commands[i];
+ var commandOutput = test.commandOutputs[command];
output.add('');
output.add('Command[$i]: $command');
+ if (commandOutput != null) {
+ output.add('Took ${commandOutput.time}');
+ } else {
+ output.add('Did not run');
+ }
}
+
+ var arguments = ['python', 'tools/test.py'];
+ arguments.addAll(test.configuration['_reproducing_arguments_']);
+ arguments.add(test.displayName);
+ var testPyCommandline = arguments.map(escapeCommandLineArgument).join(' ');
+
+ output.add('');
+ output.add('Short reproduction command (experimental):');
+ output.add(" $testPyCommandline");
return output;
}
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 63c8164..73c9cba 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -116,8 +116,9 @@
executable = executable.replaceAll('/', '\\');
}
var quotedArguments = [];
- arguments.forEach((argument) => quotedArguments.add('"$argument"'));
- commandLine = "\"$executable\" ${quotedArguments.join(' ')}";
+ quotedArguments.add(escapeCommandLineArgument(executable));
+ quotedArguments.addAll(arguments.map(escapeCommandLineArgument));
+ commandLine = quotedArguments.join(' ');
}
String toString() => commandLine;
diff --git a/tools/testing/dart/utils.dart b/tools/testing/dart/utils.dart
index 4c8170f..3ddf330 100644
--- a/tools/testing/dart/utils.dart
+++ b/tools/testing/dart/utils.dart
@@ -75,3 +75,12 @@
return utf.decodeUtf8(bytes);
}
+// This function is pretty stupid and only puts quotes around an argument if
+// it the argument contains a space.
+String escapeCommandLineArgument(String argument) {
+ if (argument.contains(' ')) {
+ return '"$argument"';
+ }
+ return argument;
+}
+
diff --git a/tools/utils.py b/tools/utils.py
index da42666..8346d09 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -239,9 +239,11 @@
return output.strip()
def GetSVNRevision():
+ custom_env = dict(os.environ)
+ custom_env['LC_MESSAGES'] = 'en_GB'
p = subprocess.Popen(['svn', 'info'], stdout = subprocess.PIPE,
stderr = subprocess.STDOUT, shell=IsWindows(),
- env = {'LC_MESSAGES' : 'en_GB'})
+ env = custom_env)
output, not_used = p.communicate()
revision = ParseSvnInfoOutput(output)
if revision:
diff --git a/utils/apidoc/apidoc.dart b/utils/apidoc/apidoc.dart
index ef6bae5..3a4d605 100644
--- a/utils/apidoc/apidoc.dart
+++ b/utils/apidoc/apidoc.dart
@@ -148,7 +148,7 @@
}
if (new File.fromPath(libPath).existsSync()) {
- apidocLibraries.add(_pathToFileUri(libPath.toNativePath()));
+ apidocLibraries.add(pathos.toUri(libPath.toNativePath()));
includedLibraries.add(libName);
} else {
print('Warning: could not find package at $path');
@@ -162,7 +162,7 @@
for (var lib in extraLibraries) {
var libPath = new Path('../../$lib');
if (new File.fromPath(libPath).existsSync()) {
- apidocLibraries.add(_pathToFileUri(libPath.toNativePath()));
+ apidocLibraries.add(pathos.toUri(libPath.toNativePath()));
var libName = libPath.filename.replaceAll('.dart', '');
includedLibraries.add(libName);
}
@@ -211,11 +211,9 @@
*/
String mdnUrl = null;
- Apidoc(this.mdn, Path outputDir, int mode,
- bool generateAppCache, [excludedLibraries, String version]) {
- if (?excludedLibraries) {
- this.excludedLibraries = excludedLibraries;
- }
+ Apidoc(this.mdn, Path outputDir, int mode, bool generateAppCache,
+ [List<String> excludedLibraries, String version]) {
+ if (excludedLibraries != null) this.excludedLibraries = excludedLibraries;
this.version = version;
this.outputDir = outputDir;
this.mode = mode;
@@ -481,13 +479,3 @@
}
}
-/** Converts a local path string to a `file:` [Uri]. */
-Uri _pathToFileUri(String path) {
- path = pathos.absolute(path);
- if (Platform.operatingSystem != 'windows') {
- return Uri.parse('file://$path');
- } else {
- return Uri.parse('file:///${path.replaceAll("\\", "/")}');
- }
-}
-
diff --git a/utils/apidoc/apidoc.gyp b/utils/apidoc/apidoc.gyp
index d393354..67e31b2 100644
--- a/utils/apidoc/apidoc.gyp
+++ b/utils/apidoc/apidoc.gyp
@@ -87,8 +87,10 @@
'--exclude-lib=analyzer_experimental',
'--exclude-lib=browser',
'--exclude-lib=dartdoc',
+ '--exclude-lib=docgen',
'--exclude-lib=expect',
'--exclude-lib=http',
+ '--exclude-lib=http_server',
'--exclude-lib=oauth2',
'--exclude-lib=pathos',
'--exclude-lib=scheduled_test',