Version 2.0.0-dev.24.0
Merge commit '23fe39e89fcaeda926fb0fef1378ef48cad6a558' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0fd7c1c..204f682 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,10 @@
* Added support for starting `async` functions synchronously. All tools (VM,
dart2js, DDC) have now a flag `--sync-async` to enable this behavior.
Currently this behavior is opt-in. It will become the default.
+* The type `void` is now a Top type like `dynamic`, and `Object`. It also now
+ has new errors for being used where not allowed (such as being assigned to any
+ non-`void`-typed parameter). Some libraries (importantly, mockito) may need to
+ be updated to accept void values to keep their APIs working.
#### Strong Mode
diff --git a/DEPS b/DEPS
index 79b32bc..9b0a5cc 100644
--- a/DEPS
+++ b/DEPS
@@ -83,7 +83,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164
"dart_style_tag": "@1.0.9", # Please see the note above before updating.
- "dartdoc_tag" : "@v0.15.1",
+ "dartdoc_tag" : "@v0.16.0",
"fixnum_tag": "@0.10.5",
"func_rev": "@25eec48146a58967d75330075ab376b3838b18a8",
"glob_tag": "@1.1.5",
diff --git a/docs/language/Dart.g b/docs/language/Dart.g
index aa70500..827db76 100644
--- a/docs/language/Dart.g
+++ b/docs/language/Dart.g
@@ -802,9 +802,15 @@
postfixExpression
: (assignableExpression postfixOperator) =>
assignableExpression postfixOperator
+ | (typeName typeArguments '.') =>
+ constructorInvocation ((selector) => selector)*
| primary ((selector) => selector)*
;
+constructorInvocation
+ : typeName typeArguments '.' identifier arguments
+ ;
+
postfixOperator
: incrementOperator
;
@@ -834,8 +840,11 @@
: (SUPER unconditionalAssignableSelector
~('<' | '(' | '[' | '.' | '?.')) =>
SUPER unconditionalAssignableSelector
+ | (typeName typeArguments '.' identifier '(') =>
+ constructorInvocation
+ ((assignableSelectorPart) => assignableSelectorPart)+
| (identifier ~('<' | '(' | '[' | '.' | '?.')) => identifier
- | (primary argumentPart* assignableSelector) =>
+ | (primary assignableSelectorPart) =>
primary ((assignableSelectorPart) => assignableSelectorPart)+
| identifier
;
@@ -947,7 +956,8 @@
| breakStatement
| continueStatement
| returnStatement
- | (functionSignature functionBodyPrefix) => localFunctionDeclaration
+ | (metadata functionSignature functionBodyPrefix) =>
+ localFunctionDeclaration
| assertStatement
| (YIELD ~'*') => yieldStatement
| yieldEachStatement
@@ -967,7 +977,7 @@
;
localFunctionDeclaration
- : functionSignature functionBody
+ : metadata functionSignature functionBody
;
ifStatement
diff --git a/docs/language/informal/implicit-creation.md b/docs/language/informal/implicit-creation.md
new file mode 100644
index 0000000..af5069c
--- /dev/null
+++ b/docs/language/informal/implicit-creation.md
@@ -0,0 +1,310 @@
+# Implicit Creation
+
+Author: eernst@.
+
+Version: 0.5 (2018-01-04)
+
+Status: Under implementation.
+
+**This document** is an informal specification of the *implicit creation* feature.
+**The feature** adds support for omitting some occurrences of the reserved words
+`new` and `const` in instance creation expressions.
+
+This feature specification was written with a
+[combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
+as the starting point. That proposal presents optional new and optional const
+together with several other features.
+
+
+## Motivation
+
+In Dart without implicit creation, the reserved word `new` is present in
+almost all expressions whose evaluation invokes a constructor at run time,
+and `const` is present in the corresponding constant expressions. These
+expressions are known as *instance creation expressions*. If `new` or
+`const` is removed from such an instance creation expression, the remaining
+phrase is still syntactically correct in most cases. This feature
+specification updates the grammar to make them all syntactically correct.
+
+With that grammar update, all instance creation expressions can technically
+omit `new` or `const` because tools (compilers, analyzers) are able to
+parse these expressions. The tools are able to recognize that these
+expressions denote instance creations (rather than, say, static function
+invocations), because the part before the arguments is statically known to
+denote a constructor.
+
+For instance, `p.C.foo` may resolve statically to a constructor named `foo` in
+a class `C` imported with prefix `p`. Similarly, `D` may resolve to a class, in
+which case `D(42)` is statically known to be a constructor invocation because
+the other interpretation is statically known to be incorrect (that is, cf.
+section '16.14.3 Unqualified Invocation' in the language specification,
+evaluating `(D)(42)`: `(D)` is an instance of `Type` which is not a function
+type and does not have a method named `call`, so we cannot call `(D)`).
+
+In short, even without the keyword, we can still unambiguously recognize the
+expressions that create objects. In that sense, the keywords are superfluous.
+
+For human readers, however, it may be helpful to document that a particular
+expression will yield a fresh instance, and this is the most common argument why
+`new` should *not* be omitted: It can be good documentation. But Dart already
+allows instance creation expressions to invoke a factory constructor, which is
+not guaranteed to return a newly created object, so Dart developers never had
+any firm local guarantees that any particular expression would yield a fresh
+object. This means that it may very well be justified to have an explicit `new`,
+but it will never be a rigorous guarantee of freshness.
+
+Similarly, it may be important for developers to ensure that certain expressions
+are constant, because of the improved performance and the guaranteed
+canonicalization. This is a compelling argument in favor of making certain
+instance creation expressions constant: It is simply a bug for that same
+expression to have `new` because object identity is an observable
+characteristic, and it may be crucial for performance that the expression is
+constant.
+
+In summary, both `new` and `const` may always be omitted from an instance
+creation expression, but it is useful and reasonable to allow an explicit `new`,
+and it is necessary to allow an explicit `const`. Based on that line of
+reasoning, we've decided to make them optional. It will then be possible for
+developers to make many expressions considerably more concise, and they can
+still enforce the desired semantics as needed.
+
+Obviously, this underscores the importance of the default: When a given instance
+creation expression omits the keyword, should it be `const` or `new`?
+
+**For instance creation expressions we have chosen** to use `const` whenever
+possible, and otherwise `new`.
+
+This implies that `const` is the preferred choice for instance creation. There
+is a danger that `const` is chosen by default in some cases where this is not
+intended by the developer, and the affected software will have bugs which are
+hard to spot. In particular, `e1 == e2` may evaluate to true in cases where it
+would have yielded false with `new` objects.
+
+We consider that danger to be rather small, because `const` can only be chosen
+in cases where the denoted constructor is constant, and with a class with a
+constant constructor it is necessary for developers to treat all accesses to its
+instances in such a way that the software will still work correctly even when
+any given instance was obtained by evaluation of a constant expression. The
+point is that, for such a class, we can never know for sure that any given
+instance is _not_ a constant object.
+
+With composite literals such as lists and maps, a `const` modifier may be
+included in order to make it a constant expression (which will of course fail if
+it contains something which is not a constant expression). In this case the
+presence of `const` may again be crucial, for the same reasons as with an
+instance creation expression, but it may also be crucial that `const` is _not_
+present, because the list or map will be mutated.
+
+**For composite literals we have chosen** to implicitly introduce `const`
+whenever it is required by the context.
+
+The choice to include `const` only when required by context (rather than
+whenever possible) is strictly less aggressive than the approach with instance
+creations. This choice is necessary because there is no way for developers to
+ensure that a literal like `[1, 2]` is mutable, if permitted by the context,
+other than omitting `const`. Furthermore, we expect this choice to be
+convenient in practice, because mutable data structures are used frequently. So
+developers must expect to write an explicit `const` on composite literals now
+and then.
+
+In summary, the implicit creation feature allows for concise construction of
+objects, with a slight preference for constant expressions, and it still allows
+developers to explicitly specify `new` or `const`, whenever needed and whenever
+it is considered to be good documentation.
+
+
+## Syntax
+
+The syntax changes associated with this feature are the following:
+
+```
+postfixExpression ::=
+ assignableExpression postfixOperator |
+ constructorInvocation selector* | // NEW
+ primary selector*
+constructorInvocation ::= // NEW
+ typeName typeArguments '.' identifier arguments
+assignableExpression ::=
+ SUPER unconditionalAssignableSelector |
+ constructorInvocation assignableSelectorPart+ | // NEW
+ identifier |
+ primary assignableSelectorPart+
+assignableSelectorPart ::=
+ argumentPart* assignableSelector
+```
+
+
+## Static analysis
+
+We specify a type directed source code transformation which eliminates the
+feature by expressing the same semantics with different syntax. The static
+analysis proceeds to work on the transformed program.
+
+*This means that the feature is "static semantic sugar". We do not specify the
+dynamic semantics for this feature, because the feature is eliminated in this
+transformation step.*
+
+We need to treat expressions differently in different locations, hence the
+following definition: An expression _e_ is said to *occur in a constant
+context*,
+
+- if _e_ is an element of a constant list literal, or a key or value of
+ an entry of a constant map literal.
+- if _e_ is an actual argument of a constant object expression or of a
+ metadata annotation.
+- if _e_ is the initializing expression of a constant variable declaration.
+- if _e_ is a switch case expression.
+- if _e_ is an immediate subexpression of an expression _e1_ which occurs in
+ a constant context, unless _e1_ is a `throw` expression or a function
+ literal.
+
+*This roughly means that everything which is inside a syntactically
+constant expression is in a constant context. Note that a `const` modifier
+which is introduced by the source code transformation does not create a
+constant context, it is only the explicit occurrences of `const` in the
+program that create a constant context. Also note that a `throw` expression
+is currently not allowed in a constant expression, but extensions affecting
+that status may be considered. A similar situation arises for function
+literals.*
+
+The transformation consists of two steps. In the first step, every literal
+list and literal map _e_ which occurs in a constant context and does not
+have the modifier `const` is replaced by `const` _e_.
+
+We define *new/const insertion* as the following transformation, which will
+be applied to specific parts of the program as specified below:
+
+- if the expression _e_ occurs in a constant context, replace _e_ by
+ `const` _e_,
+- if the expression _e_ does not occur in a constant context, but `const`
+ _e_ is a correct constant expression, replace _e_ by `const` _e_,
+- otherwise replace _e_ by `new` _e_.
+
+*Note that this transformation is applied in a bottom-up order which implies
+that all relevant transformations have already been applied on subexpressions
+of _e_. Also note that this transformation is only applied to syntactic
+constructs where the outcome is a syntactically correct instance creation
+expression. On the other hand, the outcome may have static semantic errors,
+e.g., actual arguments to a constructor invocation may have wrong types
+because that's how the program was written.*
+
+We define *new insertion* as the following transformation, which will be
+applied as specified below:
+
+- replace _e_ by `new` _e_.
+
+*We specify the second step of the transformation as based on a depth-first
+traversal of an abstract syntax tree (AST). This means that the program is
+assumed to be free of syntax errors, and when the current AST is, e.g., a
+`postfixExpression`, the program as a whole has such a structure that the
+current location was parsed as a `postfixExpression`. This is different
+from the situation where we just require that a given subsequence of the
+tokens of the program allows for such a parsing in isolation. For instance,
+an identifier like `x` parses as an `assignableExpression` in isolation,
+but if it occurs in the context `var x = 42;` or `var y = x;` then it will
+not be parsed as an `assignableExpression`, it will be parsed as a plain
+`identifier` which is part of a `declaredIdentifier` in the first case, and
+as a `primary` which is a `postfixExpression`, which is a
+`unaryExpression`, etc., in the second case. In short, we are transforming
+the AST of the program as a whole, not isolated snippets of code.*
+
+*In scientific literature, this kind of transformation is commonly
+specified as an inductive transformation where `[[e1 e2]] = [[e1]] [[e2]]`
+when the language supports a construct of the form `e1 e2`, etc. The reader
+may prefer to view the transformation in that light, and we would then say
+that we have omitted all the congruence rules.*
+
+An expression of one of the following forms must be modified in bottom-up
+order to be or contain a `constantObjectExpression` or `newExpression`
+as described:
+
+With a `postfixExpression` _e_,
+
+- if _e_ is of the form `constructorInvocation selector*`, i.e.,
+ `typeName typeArguments '.' identifier arguments selector*` then perform
+ new/const insertion on the initial `constructorInvocation`.
+- if _e_ is of the form
+ `typeIdentifier arguments` where `typeIdentifier` denotes a class then
+ perform new/const insertion on _e_.
+- if _e_ is of the form
+ `identifier1 '.' identifier2 arguments` where `identifier1` denotes
+ a class and `identifier2` is the name of a named constructor in that class,
+ or `identifier1` denotes a prefix for a library _L_ and `identifier2` denotes
+ a class exported by _L_, perform new/const insertion on _e_.
+- if _e_ is of the form
+ `identifier1 '.' typeIdentifier '.' identifier2 arguments` where
+ `identifier1` denotes a library prefix for a library _L_, `typeIdentifier`
+ denotes a class _C_ exported by _L_, and `identifier2` is the name of a named
+ constructor in _C_, perform new/const insertion on _e_.
+
+For the purposes of describing the transformation on assignable expressions
+we need the following syntactic entity:
+
+```
+assignableExpressionTail ::=
+ arguments assignableSelector assignableSelectorPart*
+```
+
+With an `assignableExpression` _e_,
+
+- if _e_ is of the form
+ `constructorInvocation assignableSelectorPart+`
+ then perform new/const insertion on the initial
+ `constructorInvocation`.
+- if _e_ is of the form
+ `typeIdentifier assignableExpressionTail`
+ where `typeIdentifier` denotes a class then perform new/const insertion on
+ the initial `typeIdentifier arguments`.
+- if _e_ is of the form
+ `typeIdentifier '.' identifier assignableExpressionTail`
+ where `typeIdentifier` denotes a class and `identifier` is the name of
+ a named constructor in that class, or `typeIdentifier` denotes a prefix
+ for a library _L_ and `identifier` denotes a class exported by _L_
+ then perform new/const insertion on the initial
+ `typeIdentifier '.' identifier arguments`.
+- if _e_ is of the form
+ `typeIdentifier1 '.' typeIdentifier2 '.' identifier assignableExpressionTail`
+ Where `typeIdentifier1` denotes a library prefix for a library _L_,
+ `typeIdentifier2` denotes a class _C_ exported by _L_, and `identifier`
+ is the name of a named constructor in _C_ then perform new/const insertion
+ on the initial
+ `typeIdentifier1 '.' typeIdentifier2 '.' identifier arguments`.
+
+*In short, add `const` wherever possible on terms that invoke a
+constructor, and otherwise add `new`. It is easy to verify that each of the
+replacements can be derived from `postfixExpression` via `primary
+selector*` and similarly for `assignableExpression`. Hence, the
+transformation preserves syntactic correctness.*
+
+
+## Dynamic Semantics
+
+There is no dynamic semantics to specify for this feature because it is
+eliminated by code transformation.
+
+
+## Revisions
+
+- 0.5 (2018-01-04) Rewritten to use `const` whenever possible (aka "magic
+ const") and adjusted to specify optional const as well as optional new
+ together, because they are now very closely connected. This document was
+ renamed to 'implicit-creation.md', and the document 'optional-const.md'
+ was deleted.
+
+- 0.4 (2017-10-17) Reverted to use 'immediate subexpression' again, for
+ correctness. Adjusted terminology for consistency. Clarified the semantics
+ of the transformation.
+
+- 0.3 (2017-09-08) Included missing rule for transformation of composite
+ literals (lists and maps). Eliminated the notion of an immediate
+ subexpression, for improved precision.
+
+- 0.2 (2017-07-30) Updated the document to specify the previously missing
+ transformations for `assignableExpression`, and to specify a no-magic
+ approach (where no `const` is introduced except when forced by the
+ syntactic context).
+
+- 0.1 (2017-08-15) Stand-alone informal specification for optional new created,
+ using version 0.8 of the combined proposal
+ [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
+ as the starting point.
diff --git a/docs/language/informal/optional-const.md b/docs/language/informal/optional-const.md
deleted file mode 100644
index 9b79649..0000000
--- a/docs/language/informal/optional-const.md
+++ /dev/null
@@ -1,191 +0,0 @@
-# Optional const
-
-Author: eernst@.
-
-Version: 0.3 (2017-09-08)
-
-Status: Under implementation.
-
-**This document** is an informal specification of the *optional const* feature.
-**The feature** adds support for omitting the reserved word `const` in list and
-map literals and constant object expressions, in locations where `const` is
-currently required.
-
-This informal specification is built on a
-[combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
-which presents optional const and several other features.
-
-## Motivation
-
-In Dart without optional const, complex constant expressions often contain many
-occurrences of `const` on list and map literals, and on constant object
-expressions. Subexpressions of constant expressions are themselves required to
-be constant expressions, and this means that `const` on a nested list or map
-literal provides no extra information: It is a compile-time error if that
-`const` is omitted. Similarly, it is a compile-time error if a nested constant
-object expression is modified to use `new` rather than `const`. In that
-situation it carries no extra information whether `new` or `const` is used, and
-it is even possible to omit the reserved word entirely. It is also required for
-certain other expressions to be constant, e.g., initializing expressions for
-constant variables.
-
-In all these cases the presence of `const` is required, and hence such a
-`const` may be inferred by compilers and similar tools if it is omitted.
-
-Developers reading the source code are likely to find it easy to understand
-that a required `const` was omitted and is implied, because the reason for
-the requirement is visible in the enclosing syntax: The expression where
-`const` is inferred is a subexpression of an expression with `const` or it
-is used in another situation where a constant value is required, e.g., to
-initialize a constant variable.
-
-In summary, tools do not need the required occurrences of `const`, and they
-are also unimportant for developers. Conversely, omitting required occurrences
-of `const` will sometimes make large expressions substantially more concise
-and readable, and also more convenient to write. Here is an example:
-
-```dart
-const myMap = const {
- "a": const [const C("able"), const C("apple"), const C("axis")],
- "b": const [const C("banana"), const C("bold"), const C("burglary")],
-};
-```
-
-Removing the required occurrences of `const` yields the following:
-
-```dart
-const myMap = {
- "a": [C("able"), C("apple"), C("axis")],
- "b": [C("banana"), C("bold"), C("burglary")],
-};
-```
-
-This proposal specifies that these previously required occurrences of `const`
-can be omitted, and will then be inferred.
-
-For a more detailed discussion and motivation, please consult the
-[combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
-which covers optional const as well as several other proposals. That document
-was the starting point for this informal specification.
-
-## Syntax
-
-In order to support the optional const feature, the Dart grammar is modified as
-follows.
-
-```
-postfixExpression ::=
- assignableExpression postfixOperator |
- constructorInvocation | // NEW
- primary selector*
-constructorInvocation ::= // NEW
- typeName typeArguments '.' identifier arguments
-```
-
-*The grammar only needs to be adjusted for one case, namely invocations of named
-constructors for generic classes. In this case we can derive expressions like
-`const Foo<int>.bar()`, and the corresponding `Foo<int>.bar()` is not derivable
-in the same situations where the variant with `const` can be derived. In other
-words, we must add support for constructs like `Foo<int>.bar()` as part of a
-`postfixExpression`. For all other situations, the variant with `const` becomes
-a construct which is already syntactically correct Dart when the `const` is
-removed. For instance `const C(42)` becomes `C(42)` which is already allowed
-syntactically (it could be a function invocation).*
-
-## Static analysis
-
-We specify a type directed source code transformation which eliminates the
-feature. The static analysis proceeds to work on the transformed program.
-
-*This means that the feature is "sugar", but because of the need to refer
-to types it could be described as static semantic sugar rather than
-syntactic sugar. We do not specify the dynamic semantics for this feature,
-because the feature is eliminated in this transformation step.*
-
-We need to treat expressions differently in different locations, hence the
-following definition: An expression _e_ is said to *occur in a constant
-context*,
-
-- if _e_ is an element of a constant list literal, or a key or value of
- an entry of a constant map literal.
-- if _e_ is an actual argument of a constant object expression or of a
- metadata annotation.
-- if _e_ is the initializing expression of a constant variable declaration.
-- if _e_ is a switch case expression.
-- if _e_ is an immediate subexpression of an expression _e1_ which occurs in
- a constant context, unless _e1_ is a `throw` expression or a function
- literal.
-
-*This roughly means that everything which is inside a syntactically
-constant expression is in a constant context. A `throw` expression is
-currently not allowed in a constant expression, but extensions affecting
-that status may be considered. A similar situation arises for function
-literals.*
-
-*Note that the default value of an optional formal parameter is not a
-constant context. This choice reserves some freedom to modify the
-semantics of default values.*
-
-An expression on one of the following forms must be modified in top-down order
-to be or contain a `constantObjectExpression` as described:
-
-With a `postfixExpression` _e_ occurring in a constant context,
-
-- if _e_ is on the form `constructorInvocation` then replace _e_ by
- `const` _e_.
-- if _e_ is on the form
- `typeIdentifier arguments` where `typeIdentifier` denotes a class then
- replace _e_ by `const` _e_.
-- if _e_ is on the form
- `identifier1 '.' identifier2 arguments` where `identifier1` denotes
- a class and `identifier2` is the name of a named constructor in that
- class, or `identifier1` denotes a prefix for a library _L_ and
- `identifier2` denotes a class exported by _L_, replace _e_ by
- `const` _e_.
-- if _e_ is on the form
- `identifier1 '.' typeIdentifier '.' identifier2 arguments` where
- `identifier1` denotes a library prefix for a library _L_,
- `typeIdentifier` denotes a class _C_ exported by _L_, and `identifier2`
- is the name of a named constructor in _C_, replace _e_ by
- `const` _e_.
-
-For a list literal _e_ occurring in a constant context, replace _e_ by
-`const` _e_. For a map literal _e_ occurring in a constant context,
-replace _e_ by `const` _e_.
-
-*In short, in these specific situations: "just add `const`". It is easy to
-verify that each of the replacements can be derived from
-`constObjectExpression`, which can be derived from `postfixExpression` via
-`primary selector*`. Hence, the transformation preserves syntactic
-correctness.*
-
-The remaining static analysis proceeds to work on the transformed program.
-
-*It is possible that this transformation will create
-`constObjectExpressions` which violate the constraints on constant object
-expressions, e.g., when `const [[new A()]]` is transformed to
-`const [const [new A()]]` where the inner list is an error that was created
-by the transformation (so the error was moved from the outer to the inner
-list). It is recommended that the error messages emitted by tools in response
-to such violations include information about the transformation.*
-
-## Dynamic Semantics
-
-There is no dynamic semantics to specify for this feature because it is
-eliminated by code transformation.
-
-
-## Revisions
-
-- 0.3 (2017-09-08) Eliminated the notion of an immediate subexpression,
- for improved precision.
-
-- 0.2 (2017-08-30) Updated the document to specify the previously missing
- transformations for composite literals (lists and maps), and to specify a
- no-magic approach (where no `const` is introduced except when forced by
- the syntactic context).
-
-- 0.1 (2017-08-10) Stand-alone informal specification for optional const
- created, using version 0.8 of the combined proposal
- [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
- as the starting point.
diff --git a/docs/language/informal/optional-new.md b/docs/language/informal/optional-new.md
deleted file mode 100644
index 139f866..0000000
--- a/docs/language/informal/optional-new.md
+++ /dev/null
@@ -1,244 +0,0 @@
-# Optional new
-
-Author: eernst@.
-
-Version: 0.4 (2017-10-17)
-
-Status: Under implementation.
-
-**This document** is an informal specification of the *optional new* feature.
-**The feature** adds support for omitting the reserved word `new` in instance
-creation expressions.
-
-This feature extends and includes the
-[optional const feature](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-const.md),
-and it is assumed that the reader knows about optional const. Beyond
-that, this informal specification is derived from a
-[combined proposal](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
-which presents optional new together with several other features.
-
-
-## Motivation
-
-In Dart without optional new, the reserved word `new` is present in every
-expression whose evaluation invokes a constructor (except constant
-expressions). These expressions are known as *instance creation expressions*. If
-`new` is removed from such an instance creation expression, the remaining phrase
-is still syntactically correct in almost all cases. The required grammar
-update that makes them all syntactically correct is a superset of the one that
-is specified for
-[optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-const.md).
-
-With that grammar update, all instance creation expressions can technically
-omit the `new` because tools (compilers, analyzers) are able to parse these
-expressions, and they are able to recognize that they denote instance creations
-(rather than, say, static function invocations), because the part before the
-left parenthesis is statically known to denote a constructor.
-
-For instance, `p.C.foo` may resolve statically to a constructor named `foo` in
-a class `C` imported with prefix `p`. Similarly, `D` may resolve to a class, in
-which case `D(42)` is statically known to be a constructor invocation because
-the other interpretation is statically known to be incorrect (that is, cf.
-section '16.14.3 Unqualified Invocation' in the language specification,
-evaluating `(D)(42)`: `(D)` is an instance of `Type` which is not a function
-type and does not have a method named `call`).
-
-For human readers, it may be helpful to document that a particular expression
-is guaranteed to yield a fresh instance, and this is the most common argument
-why `new` should *not* be omitted. However, Dart already allows instance
-creation expressions to invoke a factory constructor, so Dart developers never
-had any firm local guarantees that any particular expression would yield a
-fresh object.
-
-Developers may thus prefer to omit `new` in order to obtain more concise code,
-and possibly also in order to achieve greater uniformity among invocations of
-constructors and other invocations, e.g., of static or global functions.
-
-With that in mind, this proposal allows instance creation expressions to omit
-the `new` in all cases, but also preserves the permission to include `new` in
-all cases. It is a matter of style to use `new` in a manner that developers
-find helpful.
-
-
-## Syntax
-
-The syntax changes associated with this feature are the following:
-
-```
-postfixExpression ::=
- assignableExpression postfixOperator |
- constructorInvocation | // NEW
- primary selector*
-constructorInvocation ::= // NEW
- typeName typeArguments '.' identifier arguments
-assignableExpression ::=
- SUPER unconditionalAssignableSelector |
- constructorInvocation (arguments* assignableSelector)+ | // NEW
- identifier |
- primary (arguments* assignableSelector)+
-```
-
-*As mentioned, this grammar update is a superset of the grammar update for
-[optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-const.md).*
-
-
-## Static analysis
-
-We specify a type directed source code transformation which eliminates the
-feature by expressing the same semantics with different syntax. The static
-analysis proceeds to work on the transformed program.
-
-*Similarly to optional const, this means that the feature is "static semantic
-sugar". We do not specify the dynamic semantics for this feature, because the
-feature is eliminated in this transformation step.*
-
-We need to treat expressions differently in different locations, hence the
-following definition, which is identical to the one in
-[optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-const.md):
-
-An expression _e_ is said to *occur in a constant context*,
-
-- if _e_ is an element of a constant list literal, or a key or value of
- an entry of a constant map literal.
-- if _e_ is an actual argument of a constant object expression or of a
- metadata annotation.
-- if _e_ is the initializing expression of a constant variable declaration.
-- if _e_ is a switch case expression.
-- if _e_ is an immediate subexpression of an expression _e1_ which occurs in
- a constant context, unless _e1_ is a `throw` expression or a function
- literal.
-
-*This roughly means that everything which is inside a syntactically
-constant expression is in a constant context. A `throw` expression is
-currently not allowed in a constant expression, but extensions affecting
-that status may be considered. A similar situation arises for function
-literals.*
-
-We define *new/const insertion* as the following transformation:
-
-- if the expression _e_ occurs in a constant context, replace _e_ by
- `const` _e_,
-- otherwise replace _e_ by `new` _e_.
-
-We define *new insertion* as the following transformation:
-
-- replace _e_ by `new` _e_.
-
-For the purposes of describing the main transformation we need the following
-syntactic entity:
-
-```
-assignableExpressionTail ::=
- arguments assignableSelector (arguments* assignableSelector)*
-```
-
-*We specify the transformation as based on a top-down traversal of an
-abstract syntax tree (AST). This means that the program is assumed to be
-free of syntax errors, and when the current AST is, e.g., a
-`postfixExpression`, the program as a whole has such a structure that
-the current location was parsed as a `postfixExpression`. This is
-different from the situation where we just require a given subsequence of the
-tokens of the program allows for such a parsing in isolation. For instance,
-an identifier like `x` parses as an `assignableExpression` in isolation,
-but if it occurs in the context `var x = 42;` or `var y = x;` then it
-will not be parsed as an `assignableExpression`, it will be parsed as a
-plain `identifier` which is part of a `declaredIdentifier` in the first
-case, and as a `primary` which is a `postfixExpression`, which is a
-`unaryExpression`, etc., in the second case. In short, we are
-transforming the AST of the program as a whole, not isolated snippets of
-code.*
-
-An expression of one of the following forms must be modified in top-down
-order to be or contain a `constantObjectExpression` or `newExpression`
-as described:
-
-With a `postfixExpression` _e_,
-
-- if _e_ is of the form `constructorInvocation`, i.e.,
- `typeName typeArguments '.' identifier arguments` then perform
- new/const insertion on _e_.
-- if _e_ is of the form
- `typeIdentifier arguments` where `typeIdentifier` denotes a class then
- perform new/const insertion on _e_.
-- if _e_ is of the form
- `identifier1 '.' identifier2 arguments` where `identifier1` denotes
- a class and `identifier2` is the name of a named constructor in that class,
- or `identifier1` denotes a prefix for a library _L_ and `identifier2` denotes
- a class exported by _L_, perform new/const insertion on _e_.
-- if _e_ is of the form
- `identifier1 '.' typeIdentifier '.' identifier2 arguments` where
- `identifier1` denotes a library prefix for a library _L_, `typeIdentifier`
- denotes a class _C_ exported by _L_, and `identifier2` is the name of a named
- constructor in _C_, perform new/const insertion on _e_.
-
-With an `assignableExpression` _e_,
-
-- if _e_ is of the form
- `constructorInvocation assignableExpressionTail`
- then perform new insertion on the initial
- `constructorInvocation arguments`.
-- if _e_ is of the form
- `typeIdentifier assignableExpressionTail`
- where `typeIdentifier` denotes a class then perform new insertion on the
- initial `typeIdentifier arguments`.
-- if _e_ is of the form
- `identifier1 '.' identifier2 assignableExpressionTail`
- where `identifier1` denotes a class and `identifier2` is the name of
- a named constructor in that class, or `identifier1` denotes a prefix
- for a library _L_ and `identifier2` denotes a class exported by _L_
- then perform new insertion on the initial
- `identifier1 '.' identifier2 arguments`.
-- if _e_ is of the form
- `identifier1 '.' typeIdentifier '.' identifier2 assignableExpressionTail`
- where `identifier1` denotes a library prefix for a library _L_,
- `typeIdentifier` denotes a class _C_ exported by _L_, and `identifier2`
- is the name of a named constructor in _C_ then perform new insertion
- on the initial
- `identifier1 '.' typeIdentifier '.' identifier2 arguments`.
-
-For a list literal _e_ occurring in a constant context, replace _e_ by
-`const` _e_. For a map literal _e_ occurring in a constant context,
-replace _e_ by `const` _e_.
-
-*In short, add `const` in const contexts and otherwise add `new`. With
-`assignableExpression` we always add `new`, because such an expression
-can never be a subexpression of a correct constant expression. It is easy
-to verify that each of the replacements can be derived from
-`postfixExpression` via `primary selector*` and similarly for
-`assignableExpression`. Hence, the transformation preserves syntactic
-correctness.*
-
-
-## Dynamic Semantics
-
-There is no dynamic semantics to specify for this feature because it is
-eliminated by code transformation.
-
-
-## Interplay with optional const
-
-This informal specification includes optional const as well as optional new,
-that is, if this specification is implemented then
-[optional const](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-const.md)
-may be considered as background material.
-
-
-## Revisions
-
-- 0.4 (2017-10-17) Reverted to use 'immediate subexpression' again, for
- correctness. Adjusted terminology for consistency. Clarified the semantics
- of the transformation.
-
-- 0.3 (2017-09-08) Included missing rule for transformation of composite
- literals (lists and maps). Eliminated the notion of an immediate
- subexpression, for improved precision.
-
-- 0.2 (2017-07-30) Updated the document to specify the previously missing
- transformations for `assignableExpression`, and to specify a no-magic
- approach (where no `const` is introduced except when forced by the
- syntactic context).
-
-- 0.1 (2017-08-15) Stand-alone informal specification for optional new created,
- using version 0.8 of the combined proposal
- [optional-new-const.md](https://github.com/dart-lang/sdk/blob/master/docs/language/informal/optional-new-const.md)
- as the starting point.
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 40612c7..a459c82 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -2808,6 +2808,13 @@
additionally insert a template for the parameters. The information
required in order to do so is contained in other fields.
</p>
+ </dd><dt class="field"><b>displayText: String<span style="color:#999999"> (optional)</span></b></dt><dd>
+
+ <p>
+ Text to be displayed in, for example, a completion pop-up. This field
+ is only defined if the displayed text should be different than the
+ completion. Otherwise it is omitted.
+ </p>
</dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
<p>
@@ -2834,7 +2841,7 @@
<p>
An abbreviated version of the Dartdoc associated with the element
- being suggested, This field is omitted if there is no Dartdoc
+ being suggested. This field is omitted if there is no Dartdoc
associated with the element.
</p>
</dd><dt class="field"><b>docComplete: String<span style="color:#999999"> (optional)</span></b></dt><dd>
@@ -2968,7 +2975,12 @@
suggestions of this kind, the completion is the named argument
identifier including a trailing ':' and a space.
</p>
- </dd><dt class="value">OPTIONAL_ARGUMENT</dt><dt class="value">PARAMETER</dt></dl></dd><dt class="typeDefinition"><a name="type_ContextData">ContextData: object</a></dt><dd>
+ </dd><dt class="value">OPTIONAL_ARGUMENT</dt><dt class="value">OVERRIDE</dt><dd>
+
+ <p>
+ An overriding implementation of a class member is being suggested.
+ </p>
+ </dd><dt class="value">PARAMETER</dt></dl></dd><dt class="typeDefinition"><a name="type_ContextData">ContextData: object</a></dt><dd>
<p>
Information about an analysis context.
</p>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index de63821..43aab94 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -372,6 +372,7 @@
defaultContextOptions.generateImplicitErrors = false;
defaultContextOptions.useFastaParser = options.useCFE;
+ defaultContextOptions.previewDart2 = options.previewDart2;
{
String name = options.newAnalysisDriverLog;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 6e50eb5..5442592 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -14,8 +14,8 @@
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
const ASYNC_STAR = 'async*';
-const DEFERRED_AS = 'deferred as';
const DEFAULT_COLON = 'default:';
+const DEFERRED_AS = 'deferred as';
const EXPORT_STATEMENT = "export '';";
const IMPORT_STATEMENT = "import '';";
const PART_STATEMENT = "part '';";
@@ -31,6 +31,12 @@
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
+
+ // Don't suggest anything right after double or integer literals.
+ if (request.target.isDoubleOrIntLiteral()) {
+ return suggestions;
+ }
+
request.target.containingNode
.accept(new _KeywordVisitor(request, suggestions));
return suggestions;
@@ -220,8 +226,14 @@
@override
visitConstructorDeclaration(ConstructorDeclaration node) {
- if (node.initializers.isNotEmpty && node.initializers.last == entity) {
- _addSuggestion(Keyword.SUPER);
+ if (node.initializers.isNotEmpty) {
+ if (entity is ConstructorInitializer) {
+ _addSuggestion(Keyword.ASSERT);
+ }
+ if (node.initializers.last == entity) {
+ _addSuggestion(Keyword.SUPER);
+ _addSuggestion(Keyword.THIS);
+ }
}
}
@@ -347,23 +359,6 @@
}
@override
- visitParenthesizedExpression(ParenthesizedExpression node) {
- Expression expression = node.expression;
- if (expression is Identifier || expression is PropertyAccess) {
- if (entity == node.rightParenthesis) {
- var next = expression.endToken.next;
- if (next == entity || next == droppedToken) {
- // Fasta parses `if (x i^)` as `if (x ^) where the `i` is in the token
- // stream but not part of the ParenthesizedExpression.
- _addSuggestion(Keyword.IS, DART_RELEVANCE_HIGH);
- return;
- }
- }
- }
- _addExpressionKeywords(node);
- }
-
- @override
visitIfStatement(IfStatement node) {
if (_isPreviousTokenSynthetic(entity, TokenType.CLOSE_PAREN)) {
// Actual: if (x i^)
@@ -456,6 +451,23 @@
}
@override
+ visitParenthesizedExpression(ParenthesizedExpression node) {
+ Expression expression = node.expression;
+ if (expression is Identifier || expression is PropertyAccess) {
+ if (entity == node.rightParenthesis) {
+ var next = expression.endToken.next;
+ if (next == entity || next == droppedToken) {
+ // Fasta parses `if (x i^)` as `if (x ^) where the `i` is in the token
+ // stream but not part of the ParenthesizedExpression.
+ _addSuggestion(Keyword.IS, DART_RELEVANCE_HIGH);
+ return;
+ }
+ }
+ }
+ _addExpressionKeywords(node);
+ }
+
+ @override
visitPrefixedIdentifier(PrefixedIdentifier node) {
if (entity != node.identifier) {
_addExpressionKeywords(node);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index bce108a..4f58799 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -63,13 +63,17 @@
* Return a template for an override of the given [element]. If selected, the
* template will replace [targetId].
*/
- Future<String> _buildReplacementText(AnalysisResult result,
- SimpleIdentifier targetId, ExecutableElement element) async {
+ Future<String> _buildReplacementText(
+ AnalysisResult result,
+ SimpleIdentifier targetId,
+ ExecutableElement element,
+ StringBuffer displayTextBuffer) async {
DartChangeBuilder builder =
new DartChangeBuilder(result.driver.currentSession);
await builder.addFileEdit(result.path, (DartFileEditBuilder builder) {
builder.addReplacement(range.node(targetId), (DartEditBuilder builder) {
- builder.writeOverrideOfInheritedMember(element);
+ builder.writeOverrideOfInheritedMember(element,
+ displayTextBuffer: displayTextBuffer);
});
});
return builder.sourceChange.edits[0].edits[0].replacement.trim();
@@ -81,11 +85,14 @@
*/
Future<CompletionSuggestion> _buildSuggestion(DartCompletionRequest request,
SimpleIdentifier targetId, ExecutableElement element) async {
- String completion =
- await _buildReplacementText(request.result, targetId, element);
+ StringBuffer displayTextBuffer = new StringBuffer();
+ String completion = await _buildReplacementText(
+ request.result, targetId, element, displayTextBuffer);
if (completion == null || completion.length == 0) {
return null;
}
+ String displayText =
+ displayTextBuffer.isNotEmpty ? displayTextBuffer.toString() : null;
CompletionSuggestion suggestion = new CompletionSuggestion(
CompletionSuggestionKind.OVERRIDE,
DART_RELEVANCE_HIGH,
@@ -93,7 +100,8 @@
targetId.offset,
0,
element.isDeprecated,
- false);
+ false,
+ displayText: displayText);
suggestion.element = protocol.convertElement(element);
return suggestion;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index d983f08..b880b53 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1466,7 +1466,9 @@
}
Future<Null> _addFix_createMissingOverrides() async {
- // prepare target
+ if (node.parent is! ClassDeclaration) {
+ return;
+ }
ClassDeclaration targetClass = node.parent as ClassDeclaration;
ClassElement targetClassElement = targetClass.element;
utils.targetClassElement = targetClassElement;
@@ -1613,6 +1615,9 @@
}
Future<Null> _addFix_createNoSuchMethod() async {
+ if (node.parent is! ClassDeclaration) {
+ return;
+ }
ClassDeclaration targetClass = node.parent as ClassDeclaration;
// prepare environment
String prefix = utils.getIndent(1);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 7173f6e..91b0f0d 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -201,6 +201,7 @@
* "kind": CompletionSuggestionKind
* "relevance": int
* "completion": String
+ * "displayText": optional String
* "selectionOffset": int
* "selectionLength": int
* "isDeprecated": bool
@@ -231,6 +232,7 @@
"isDeprecated": isBool,
"isPotential": isBool
}, optionalFields: {
+ "displayText": isString,
"docSummary": isString,
"docComplete": isString,
"declaringType": isString,
@@ -258,6 +260,7 @@
* KEYWORD
* NAMED_ARGUMENT
* OPTIONAL_ARGUMENT
+ * OVERRIDE
* PARAMETER
* }
*/
@@ -270,6 +273,7 @@
"KEYWORD",
"NAMED_ARGUMENT",
"OPTIONAL_ARGUMENT",
+ "OVERRIDE",
"PARAMETER"
]);
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 3a8cfb8..bc58223 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -157,8 +157,8 @@
Future<Response> waitForResponse(Request request) {
String id = request.id;
- return new Future<Response>(() => responseController.stream
- .firstWhere((response) => response.id == id) as Future<Response>);
+ return responseController.stream
+ .firstWhere((response) => response.id == id);
}
}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 425178b..8568c03 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -837,6 +837,18 @@
assertSuggestKeywords([]);
}
+ test_constructor_initializers_first() async {
+ addTestSource('class A { int f; A() : ^, f = 1; }');
+ await computeSuggestions();
+ assertSuggestKeywords([Keyword.ASSERT]);
+ }
+
+ test_constructor_initializers_last() async {
+ addTestSource('class A { A() : ^; }');
+ await computeSuggestions();
+ assertSuggestKeywords([Keyword.ASSERT, Keyword.SUPER, Keyword.THIS]);
+ }
+
test_constructor_param() async {
addTestSource('class A { A(^) {});}');
await computeSuggestions();
@@ -1411,6 +1423,18 @@
relevance: DART_RELEVANCE_HIGH);
}
+ test_integerLiteral_inArgumentList() async {
+ addTestSource('main() { print(42^); }');
+ await computeSuggestions();
+ assertSuggestKeywords([]);
+ }
+
+ test_integerLiteral_inListLiteral() async {
+ addTestSource('main() { var items = [42^]; }');
+ await computeSuggestions();
+ assertSuggestKeywords([]);
+ }
+
test_is_expression() async {
addTestSource('main() {if (x is^)}');
await computeSuggestions();
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 1fcab846..fd1701b 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -3113,7 +3113,20 @@
''');
}
- test_createNoSuchMethod() async {
+ test_createNoSuchMethod_BAD_classTypeAlias() async {
+ await resolveTestUnit('''
+abstract class A {
+ m();
+}
+
+class B = Object with A;
+''');
+ await assertNoFix(
+ DartFixKind.CREATE_NO_SUCH_METHOD,
+ );
+ }
+
+ test_createNoSuchMethod_OK() async {
await resolveTestUnit('''
abstract class A {
m1();
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index 7a8ebc3..582d655 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -54,6 +54,12 @@
private final String completion;
/**
+ * Text to be displayed in, for example, a completion pop-up. This field is only defined if the
+ * displayed text should be different than the completion. Otherwise it is omitted.
+ */
+ private final String displayText;
+
+ /**
* The offset, relative to the beginning of the completion, of where the selection should be placed
* after insertion.
*/
@@ -76,7 +82,7 @@
private final boolean isPotential;
/**
- * An abbreviated version of the Dartdoc associated with the element being suggested, This field is
+ * An abbreviated version of the Dartdoc associated with the element being suggested. This field is
* omitted if there is no Dartdoc associated with the element.
*/
private final String docSummary;
@@ -163,10 +169,11 @@
/**
* Constructor for {@link CompletionSuggestion}.
*/
- public CompletionSuggestion(String kind, int relevance, String completion, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String importUri) {
+ public CompletionSuggestion(String kind, int relevance, String completion, String displayText, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, String importUri) {
this.kind = kind;
this.relevance = relevance;
this.completion = completion;
+ this.displayText = displayText;
this.selectionOffset = selectionOffset;
this.selectionLength = selectionLength;
this.isDeprecated = isDeprecated;
@@ -195,6 +202,7 @@
ObjectUtilities.equals(other.kind, kind) &&
other.relevance == relevance &&
ObjectUtilities.equals(other.completion, completion) &&
+ ObjectUtilities.equals(other.displayText, displayText) &&
other.selectionOffset == selectionOffset &&
other.selectionLength == selectionLength &&
other.isDeprecated == isDeprecated &&
@@ -221,6 +229,7 @@
String kind = jsonObject.get("kind").getAsString();
int relevance = jsonObject.get("relevance").getAsInt();
String completion = jsonObject.get("completion").getAsString();
+ String displayText = jsonObject.get("displayText") == null ? null : jsonObject.get("displayText").getAsString();
int selectionOffset = jsonObject.get("selectionOffset").getAsInt();
int selectionLength = jsonObject.get("selectionLength").getAsInt();
boolean isDeprecated = jsonObject.get("isDeprecated").getAsBoolean();
@@ -239,7 +248,7 @@
String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
String importUri = jsonObject.get("importUri") == null ? null : jsonObject.get("importUri").getAsString();
- return new CompletionSuggestion(kind, relevance, completion, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, importUri);
+ return new CompletionSuggestion(kind, relevance, completion, displayText, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, importUri);
}
public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -290,6 +299,14 @@
}
/**
+ * Text to be displayed in, for example, a completion pop-up. This field is only defined if the
+ * displayed text should be different than the completion. Otherwise it is omitted.
+ */
+ public String getDisplayText() {
+ return displayText;
+ }
+
+ /**
* The Dartdoc associated with the element being suggested. This field is omitted if there is no
* Dartdoc associated with the element.
*/
@@ -298,7 +315,7 @@
}
/**
- * An abbreviated version of the Dartdoc associated with the element being suggested, This field is
+ * An abbreviated version of the Dartdoc associated with the element being suggested. This field is
* omitted if there is no Dartdoc associated with the element.
*/
public String getDocSummary() {
@@ -426,6 +443,7 @@
builder.append(kind);
builder.append(relevance);
builder.append(completion);
+ builder.append(displayText);
builder.append(selectionOffset);
builder.append(selectionLength);
builder.append(isDeprecated);
@@ -452,6 +470,9 @@
jsonObject.addProperty("kind", kind);
jsonObject.addProperty("relevance", relevance);
jsonObject.addProperty("completion", completion);
+ if (displayText != null) {
+ jsonObject.addProperty("displayText", displayText);
+ }
jsonObject.addProperty("selectionOffset", selectionOffset);
jsonObject.addProperty("selectionLength", selectionLength);
jsonObject.addProperty("isDeprecated", isDeprecated);
@@ -523,6 +544,8 @@
builder.append(relevance + ", ");
builder.append("completion=");
builder.append(completion + ", ");
+ builder.append("displayText=");
+ builder.append(displayText + ", ");
builder.append("selectionOffset=");
builder.append(selectionOffset + ", ");
builder.append("selectionLength=");
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java
index 32a42db..84048b8 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestionKind.java
@@ -51,6 +51,11 @@
public static final String OPTIONAL_ARGUMENT = "OPTIONAL_ARGUMENT";
+ /**
+ * An overriding implementation of a class member is being suggested.
+ */
+ public static final String OVERRIDE = "OVERRIDE";
+
public static final String PARAMETER = "PARAMETER";
}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index dcfe176..29e93e1 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -5046,7 +5046,7 @@
/* TODO(leafp) Delete most of these.
*/
static const StrongModeCode TOP_LEVEL_CYCLE = const StrongModeCode(
- ErrorType.HINT,
+ ErrorType.COMPILE_TIME_ERROR,
'TOP_LEVEL_CYCLE',
"The type of '{0}' can't be inferred because it depends on itself through the cycle: {1}.",
"Try adding an explicit type to one or more of the variables in the cycle in order to break the cycle.");
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index dc832df..c0be389 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -10567,8 +10567,7 @@
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
listener.assertErrors([
- expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER,
- usingFastaParser ? 6 : 11, 1)
+ expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 1)
]);
expect(member, new isInstanceOf<ConstructorDeclaration>());
NodeList<ConstructorInitializer> initializers =
@@ -10590,15 +10589,18 @@
createParser('C() : this {}');
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
- listener.assertErrors([
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
- usingFastaParser
- ? expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
- : expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 11, 1)
- ]);
+ listener.assertErrors(usingFastaParser
+ ? [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
+ expectedError(
+ ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
+ ]
+ : [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1),
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
+ expectedError(
+ ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 11, 1)
+ ]);
}
void test_incomplete_constructorInitializers_thisField() {
@@ -10606,11 +10608,7 @@
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
listener.assertErrors([
- usingFastaParser
- ? expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
- : expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 8, 1)
+ expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
]);
}
@@ -10620,11 +10618,7 @@
expectNotNullIfNoErrors(member);
listener.assertErrors([
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
- usingFastaParser
- ? expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
- : expectedError(
- ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 11, 1)
+ expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 4)
]);
}
@@ -10633,8 +10627,7 @@
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
listener.assertErrors([
- expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER,
- usingFastaParser ? 6 : 8, 1)
+ expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 6, 1)
]);
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart
index f8078ad..1b2fdee 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/annotation_test.dart
@@ -14,19 +14,70 @@
buildAll() {
List<TestDescriptor> descriptors = <TestDescriptor>[
new TestDescriptor(
- 'ampersand', '@', [ParserErrorCode.MISSING_IDENTIFIER], '@_s_',
- allFailing: true),
+ 'ampersand',
+ '@',
+ [ParserErrorCode.MISSING_IDENTIFIER],
+ '@_s_',
+ allFailing: true,
+ ),
new TestDescriptor(
- 'leftParen', '@a(', [ParserErrorCode.EXPECTED_TOKEN], '@a()',
- allFailing: true),
+ 'leftParen',
+ '@a(',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ '@a()',
+ allFailing: true,
+ ),
];
- buildTests('annotation_topLevel', descriptors,
- PartialCodeTest.declarationSuffixes);
- buildTests('annotation_classMember', descriptors,
- PartialCodeTest.classMemberSuffixes,
- head: 'class C { ', tail: ' }');
buildTests(
- 'annotation_local', descriptors, PartialCodeTest.statementSuffixes,
- head: 'f() { ', tail: ' }');
+ 'annotation_topLevel',
+ expectErrors(descriptors, [ParserErrorCode.EXPECTED_EXECUTABLE]),
+ [],
+ );
+ buildTests(
+ 'annotation_topLevel',
+ descriptors,
+ PartialCodeTest.declarationSuffixes,
+ includeEof: false,
+ );
+ buildTests(
+ 'annotation_classMember',
+ descriptors,
+ PartialCodeTest.classMemberSuffixes,
+ head: 'class C { ',
+ tail: ' }',
+ );
+ buildTests(
+ 'annotation_local',
+ expectErrors(descriptors, [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_TYPE_NAME,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ]),
+ [],
+ head: 'f() { ',
+ tail: ' }',
+ );
+ // TODO(brianwilkerson) Many of the combinations produced by the following
+ // produce "valid" code that is not valid. Even when we recover the
+ // annotation, the following statement is not allowed to have an annotation.
+ buildTests(
+ 'annotation_local',
+ descriptors,
+ PartialCodeTest.statementSuffixes,
+ head: 'f() { ',
+ includeEof: false,
+ tail: ' }',
+ );
}
+
+ /**
+ * Return a list of descriptors just like the given [descriptors] except that
+ * they have the given list of [errors] as the errors that are expected to be
+ * in the valid code.
+ */
+ List<TestDescriptor> expectErrors(
+ List<TestDescriptor> descriptors, List<ParserErrorCode> errors) =>
+ descriptors
+ .map((descriptor) => descriptor.withExpectedErrorsInValidCode(errors))
+ .toList();
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/field_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/field_declaration_test.dart
index d1f7a02..5c42722 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/field_declaration_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/field_declaration_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
import 'partial_code_support.dart';
@@ -22,217 +23,268 @@
'setter'
];
buildTests(
- 'field_declaration',
- [
- //
- // Instance field, const.
- //
- new TestDescriptor(
- 'const_noName',
- 'const',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'const _s_;',
- allFailing: true),
- new TestDescriptor('const_name', 'const f',
- [ParserErrorCode.EXPECTED_TOKEN], 'const f;',
- allFailing: true),
- new TestDescriptor(
- 'const_equals',
- 'const f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'const f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('const_initializer', 'const f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'const f = 0;'),
- //
- // Instance field, final.
- //
- new TestDescriptor(
- 'final_noName',
- 'final',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'final _s_;',
- failing: allExceptEof),
- new TestDescriptor('final_name', 'final f',
- [ParserErrorCode.EXPECTED_TOKEN], 'final f;',
- failing: ['methodNonVoid', 'getter', 'setter']),
- new TestDescriptor(
- 'final_equals',
- 'final f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'final f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('final_initializer', 'final f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'final f = 0;'),
- //
- // Instance field, var.
- //
- new TestDescriptor(
- 'var_noName',
- 'var',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'var _s_;',
- failing: allExceptEof),
- new TestDescriptor(
- 'var_name', 'var f', [ParserErrorCode.EXPECTED_TOKEN], 'var f;',
- failing: ['methodNonVoid', 'getter', 'setter']),
- new TestDescriptor(
- 'var_equals',
- 'var f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'var f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('var_initializer', 'var f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'var f = 0;'),
- //
- // Instance field, type.
- //
- new TestDescriptor(
- 'type_noName',
- 'A',
- [
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'A _s_;',
- allFailing: true),
- new TestDescriptor(
- 'type_name', 'A f', [ParserErrorCode.EXPECTED_TOKEN], 'A f;'),
- new TestDescriptor(
- 'type_equals',
- 'A f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'A f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('type_initializer', 'A f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'A f = 0;'),
- //
- // Static field, const.
- //
- new TestDescriptor(
- 'static_const_noName',
- 'static const',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static const _s_;',
- allFailing: true),
- new TestDescriptor('static_const_name', 'static const f',
- [ParserErrorCode.EXPECTED_TOKEN], 'static const f;',
- allFailing: true),
- new TestDescriptor(
- 'static_const_equals',
- 'static const f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static const f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('static_const_initializer', 'static const f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'static const f = 0;'),
- //
- // Static field, final.
- //
- new TestDescriptor(
- 'static_final_noName',
- 'static final',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static final _s_;',
- failing: allExceptEof),
- new TestDescriptor('static_final_name', 'static final f',
- [ParserErrorCode.EXPECTED_TOKEN], 'static final f;',
- failing: ['methodNonVoid', 'getter', 'setter']),
- new TestDescriptor(
- 'static_final_equals',
- 'static final f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static final f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('static_final_initializer', 'static final f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'static final f = 0;'),
- //
- // Static field, var.
- //
- new TestDescriptor(
- 'static_var_noName',
- 'static var',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static var _s_;',
- failing: allExceptEof),
- new TestDescriptor('static_var_name', 'static var f',
- [ParserErrorCode.EXPECTED_TOKEN], 'static var f;',
- failing: ['methodNonVoid', 'getter', 'setter']),
- new TestDescriptor(
- 'static_var_equals',
- 'static var f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static var f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('static_var_initializer', 'static var f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'static var f = 0;'),
- //
- // Static field, type.
- //
- new TestDescriptor(
- 'static_type_noName',
- 'static A',
- [
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static A _s_;',
- allFailing: true),
- new TestDescriptor('static_type_name', 'static A f',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A f;'),
- new TestDescriptor(
- 'static_type_equals',
- 'static A f =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static A f = _s_;',
- failing: allExceptEof),
- new TestDescriptor('static_type_initializer', 'static A f = 0',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A f = 0;'),
- ],
- PartialCodeTest.classMemberSuffixes,
- head: 'class C { ',
- tail: ' }');
+ 'field_declaration',
+ [
+ //
+ // Instance field, const.
+ //
+ new TestDescriptor(
+ 'const_noName',
+ 'const',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'const _s_;',
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
+ new TestDescriptor(
+ 'const_name',
+ 'const f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'const f;',
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
+ new TestDescriptor(
+ 'const_equals',
+ 'const f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'const f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'const_initializer',
+ 'const f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'const f = 0;',
+ ),
+ //
+ // Instance field, final.
+ //
+ new TestDescriptor(
+ 'final_noName',
+ 'final',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'final _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'final_name',
+ 'final f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'final f;',
+ failing: ['methodNonVoid', 'getter', 'setter'],
+ ),
+ new TestDescriptor(
+ 'final_equals',
+ 'final f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'final f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'final_initializer',
+ 'final f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'final f = 0;',
+ ),
+ //
+ // Instance field, var.
+ //
+ new TestDescriptor(
+ 'var_noName',
+ 'var',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'var _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'var_name',
+ 'var f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'var f;',
+ failing: ['methodNonVoid', 'getter', 'setter'],
+ ),
+ new TestDescriptor(
+ 'var_equals',
+ 'var f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'var f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'var_initializer',
+ 'var f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'var f = 0;',
+ ),
+ //
+ // Instance field, type.
+ //
+ new TestDescriptor(
+ 'type_noName',
+ 'A',
+ [
+ ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ 'A _s_;',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_name',
+ 'A f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A f;',
+ ),
+ new TestDescriptor(
+ 'type_equals',
+ 'A f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'A f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'type_initializer',
+ 'A f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A f = 0;',
+ ),
+ //
+ // Static field, const.
+ //
+ new TestDescriptor(
+ 'static_const_noName',
+ 'static const',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static const _s_;',
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
+ new TestDescriptor(
+ 'static_const_name',
+ 'static const f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static const f;',
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
+ new TestDescriptor(
+ 'static_const_equals',
+ 'static const f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static const f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'static_const_initializer',
+ 'static const f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static const f = 0;',
+ ),
+ //
+ // Static field, final.
+ //
+ new TestDescriptor(
+ 'static_final_noName',
+ 'static final',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static final _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'static_final_name',
+ 'static final f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static final f;',
+ failing: ['methodNonVoid', 'getter', 'setter'],
+ ),
+ new TestDescriptor(
+ 'static_final_equals',
+ 'static final f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static final f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'static_final_initializer',
+ 'static final f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static final f = 0;',
+ ),
+ //
+ // Static field, var.
+ //
+ new TestDescriptor(
+ 'static_var_noName',
+ 'static var',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static var _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'static_var_name',
+ 'static var f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static var f;',
+ failing: ['methodNonVoid', 'getter', 'setter'],
+ ),
+ new TestDescriptor(
+ 'static_var_equals',
+ 'static var f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static var f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'static_var_initializer',
+ 'static var f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static var f = 0;',
+ ),
+ //
+ // Static field, type.
+ //
+ new TestDescriptor(
+ 'static_type_noName',
+ 'static A',
+ [
+ ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ 'static A _s_;',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'static_type_name',
+ 'static A f',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A f;',
+ ),
+ new TestDescriptor(
+ 'static_type_equals',
+ 'static A f =',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static A f = _s_;',
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'static_type_initializer',
+ 'static A f = 0',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A f = 0;',
+ ),
+ ],
+ PartialCodeTest.classMemberSuffixes,
+ head: 'class C { ',
+ tail: ' }',
+ );
}
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/if_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/if_statement_test.dart
index 7f8ac54..6402a1c 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/if_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/if_statement_test.dart
@@ -13,33 +13,70 @@
class IfStatementTest extends PartialCodeTest {
buildAll() {
buildTests(
- 'if_statement',
- [
- new TestDescriptor(
- 'keyword',
- 'if',
- [
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "if (_s_)",
- failing: ['eof']),
- new TestDescriptor(
- 'leftParen',
- 'if (',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "if (_s_)",
- allFailing: true),
- new TestDescriptor(
- 'condition', 'if (a', [ParserErrorCode.EXPECTED_TOKEN], "if (a)",
- allFailing: true),
- ],
- PartialCodeTest.statementSuffixes,
- head: 'f() { ',
- tail: ' }');
+ 'if_statement',
+ [
+ new TestDescriptor(
+ 'keyword',
+ 'if',
+ [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "if (_s_)",
+ ),
+ new TestDescriptor(
+ 'leftParen',
+ 'if (',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ "if (_s_)",
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'condition',
+ 'if (a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "if (a)",
+ allFailing: true,
+ ),
+ ],
+ PartialCodeTest.statementSuffixes,
+ head: 'f() { ',
+ includeEof: false,
+ tail: ' }',
+ );
+ buildTests(
+ 'if_statement',
+ [
+ new TestDescriptor(
+ 'keyword',
+ 'if',
+ [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "if (_s_);",
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'leftParen',
+ 'if (',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ "if (_s_);",
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'condition',
+ 'if (a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "if (a);",
+ allFailing: true,
+ ),
+ ],
+ [],
+ head: 'f() { ',
+ tail: ' }',
+ );
}
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/method_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/method_declaration_test.dart
index 432d9d4..a2c8624 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/method_declaration_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/method_declaration_test.dart
@@ -13,183 +13,276 @@
class MethodTest extends PartialCodeTest {
buildAll() {
buildTests(
- 'method_declaration',
- [
- //
- // Instance method, no return type.
- //
- new TestDescriptor('noType_leftParen', 'm(',
- [ParserErrorCode.EXPECTED_TOKEN], 'm();',
- allFailing: true),
- new TestDescriptor('noType_paramName', 'm(B',
- [ParserErrorCode.EXPECTED_TOKEN], 'm(B);',
- allFailing: true),
- new TestDescriptor('noType_paramTypeAndName', 'm(B b',
- [ParserErrorCode.EXPECTED_TOKEN], 'm(B b);',
- allFailing: true),
- new TestDescriptor(
- 'noType_paramAndComma',
- 'm(B b,',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'm(B b, _s_);',
- allFailing: true),
- new TestDescriptor('noType_noParams', 'm()',
- [ParserErrorCode.EXPECTED_TOKEN], 'm();',
- allFailing: true),
- new TestDescriptor('noType_params', 'm(b, c)',
- [ParserErrorCode.EXPECTED_TOKEN], 'm(b, c);',
- allFailing: true),
- new TestDescriptor(
- 'noType_emptyOptional',
- 'm(B b, [])',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'm(B b, [_s_]){}'),
- new TestDescriptor(
- 'noType_emptyNamed',
- 'm(B b, {})',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'm(B b, {_s_}){}'),
- //
- // Instance method, with simple return type.
- //
- new TestDescriptor('type_leftParen', 'A m(',
- [ParserErrorCode.EXPECTED_TOKEN], 'A m();',
- allFailing: true),
- new TestDescriptor('type_paramName', 'A m(B',
- [ParserErrorCode.EXPECTED_TOKEN], 'A m(B);',
- allFailing: true),
- new TestDescriptor('type_paramTypeAndName', 'A m(B b',
- [ParserErrorCode.EXPECTED_TOKEN], 'A m(B b);',
- allFailing: true),
- new TestDescriptor(
- 'type_paramAndComma',
- 'A m(B b,',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'A m(B b, _s_);',
- allFailing: true),
- new TestDescriptor('type_noParams', 'A m()',
- [ParserErrorCode.EXPECTED_TOKEN], 'A m();',
- allFailing: true),
- new TestDescriptor('type_params', 'A m(b, c)',
- [ParserErrorCode.EXPECTED_TOKEN], 'A m(b, c);',
- allFailing: true),
- new TestDescriptor(
- 'type_emptyOptional',
- 'A m(B b, [])',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'A m(B b, [_s_]){}'),
- new TestDescriptor(
- 'type_emptyNamed',
- 'A m(B b, {})',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'A m(B b, {_s_}){}'),
- //
- // Static method, no return type.
- //
- new TestDescriptor('static_noType_leftParen', 'static m(',
- [ParserErrorCode.EXPECTED_TOKEN], 'static m();',
- allFailing: true),
- new TestDescriptor('static_noType_paramName', 'static m(B',
- [ParserErrorCode.EXPECTED_TOKEN], 'static m(B);',
- allFailing: true),
- new TestDescriptor('static_noType_paramTypeAndName', 'static m(B b',
- [ParserErrorCode.EXPECTED_TOKEN], 'static m(B b);',
- allFailing: true),
- new TestDescriptor(
- 'static_noType_paramAndComma',
- 'static m(B b,',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static m(B b, _s_);',
- allFailing: true),
- new TestDescriptor('static_noType_noParams', 'static m()',
- [ParserErrorCode.EXPECTED_TOKEN], 'static m();',
- allFailing: true),
- new TestDescriptor('static_noType_params', 'static m(b, c)',
- [ParserErrorCode.EXPECTED_TOKEN], 'static m(b, c);',
- allFailing: true),
- new TestDescriptor(
- 'static_noType_emptyOptional',
- 'static m(B b, [])',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'static m(B b, [_s_]){}'),
- new TestDescriptor(
- 'static_noType_emptyNamed',
- 'static m(B b, {})',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'static m(B b, {_s_}){}'),
- //
- // Static method, with simple return type.
- //
- new TestDescriptor('static_type_leftParen', 'static A m(',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A m();',
- allFailing: true),
- new TestDescriptor('static_type_paramName', 'static A m(B',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A m(B);',
- allFailing: true),
- new TestDescriptor('static_type_paramTypeAndName', 'static A m(B b',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A m(B b);',
- allFailing: true),
- new TestDescriptor(
- 'static_type_paramAndComma',
- 'static A m(B b,',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- 'static A m(B b, _s_);',
- allFailing: true),
- new TestDescriptor('static_type_noParams', 'static A m()',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A m();',
- allFailing: true),
- new TestDescriptor('static_type_params', 'static A m(b, c)',
- [ParserErrorCode.EXPECTED_TOKEN], 'static A m(b, c);',
- allFailing: true),
- new TestDescriptor(
- 'static_type_emptyOptional',
- 'static A m(B b, [])',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'static A m(B b, [_s_]){}'),
- new TestDescriptor(
- 'static_type_emptyNamed',
- 'static A m(B b, {})',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_FUNCTION_BODY
- ],
- 'static A m(B b, {_s_}){}'),
- ],
- PartialCodeTest.classMemberSuffixes,
- head: 'class C { ',
- tail: ' }');
+ 'method_declaration',
+ [
+ //
+ // Instance method, no return type.
+ //
+ new TestDescriptor(
+ 'noType_leftParen',
+ 'm(',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'm();',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'noType_paramName',
+ 'm(B',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'm(B);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'noType_paramTypeAndName',
+ 'm(B b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'm(B b);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'noType_paramAndComma',
+ 'm(B b,',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'm(B b, _s_);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'noType_noParams',
+ 'm()',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'm();',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'noType_params',
+ 'm(b, c)',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'm(b, c);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'noType_emptyOptional',
+ 'm(B b, [])',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'm(B b, [_s_]){}',
+ ),
+ new TestDescriptor(
+ 'noType_emptyNamed',
+ 'm(B b, {})',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'm(B b, {_s_}){}',
+ ),
+ //
+ // Instance method, with simple return type.
+ //
+ new TestDescriptor(
+ 'type_leftParen',
+ 'A m(',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A m();',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_paramName',
+ 'A m(B',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A m(B);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_paramTypeAndName',
+ 'A m(B b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A m(B b);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_paramAndComma',
+ 'A m(B b,',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'A m(B b, _s_);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_noParams',
+ 'A m()',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A m();',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_params',
+ 'A m(b, c)',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'A m(b, c);',
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'type_emptyOptional',
+ 'A m(B b, [])',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'A m(B b, [_s_]){}',
+ ),
+ new TestDescriptor(
+ 'type_emptyNamed',
+ 'A m(B b, {})',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'A m(B b, {_s_}){}',
+ ),
+ //
+ // Static method, no return type.
+ //
+ new TestDescriptor(
+ 'static_noType_leftParen',
+ 'static m(',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static m();',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_noType_paramName',
+ 'static m(B',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static m(B);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_noType_paramTypeAndName',
+ 'static m(B b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static m(B b);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_noType_paramAndComma',
+ 'static m(B b,',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static m(B b, _s_);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_noType_noParams',
+ 'static m()',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static m();',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_noType_params',
+ 'static m(b, c)',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static m(b, c);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_noType_emptyOptional',
+ 'static m(B b, [])',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'static m(B b, [_s_]){}',
+ ),
+ new TestDescriptor(
+ 'static_noType_emptyNamed',
+ 'static m(B b, {})',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'static m(B b, {_s_}){}',
+ ),
+ //
+ // Static method, with simple return type.
+ //
+ new TestDescriptor(
+ 'static_type_leftParen',
+ 'static A m(',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A m();',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_type_paramName',
+ 'static A m(B',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A m(B);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_type_paramTypeAndName',
+ 'static A m(B b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A m(B b);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_type_paramAndComma',
+ 'static A m(B b,',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ 'static A m(B b, _s_);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_type_noParams',
+ 'static A m()',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A m();',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_type_params',
+ 'static A m(b, c)',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ 'static A m(b, c);',
+ allFailing: true,
+ expectedErrorsInValidCode: [ParserErrorCode.MISSING_FUNCTION_BODY],
+ ),
+ new TestDescriptor(
+ 'static_type_emptyOptional',
+ 'static A m(B b, [])',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'static A m(B b, [_s_]){}',
+ ),
+ new TestDescriptor(
+ 'static_type_emptyNamed',
+ 'static A m(B b, {})',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.MISSING_FUNCTION_BODY
+ ],
+ 'static A m(B b, {_s_}){}',
+ ),
+ ],
+ PartialCodeTest.classMemberSuffixes,
+ head: 'class C { ',
+ tail: ' }',
+ );
}
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
index ebb09d2..faaddf6 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/partial_code_support.dart
@@ -101,11 +101,13 @@
*/
buildTests(String groupName, List<TestDescriptor> descriptors,
List<TestSuffix> suffixes,
- {String head, String tail}) {
+ {String head, bool includeEof: true, String tail}) {
group(groupName, () {
for (TestDescriptor descriptor in descriptors) {
- _buildTestForDescriptorAndSuffix(
- descriptor, TestSuffix.eof, 0, head, tail);
+ if (includeEof) {
+ _buildTestForDescriptorAndSuffix(
+ descriptor, TestSuffix.eof, 0, head, tail);
+ }
for (int i = 0; i < suffixes.length; i++) {
_buildTestForDescriptorAndSuffix(
descriptor, suffixes[i], i + 1, head, tail);
@@ -113,9 +115,13 @@
if (descriptor.failing != null) {
test('${descriptor.name}_failingList', () {
Set<String> failing = new Set.from(descriptor.failing);
- failing.remove('eof');
+ if (includeEof) {
+ failing.remove('eof');
+ }
failing.removeAll(suffixes.map((TestSuffix suffix) => suffix.name));
- expect(failing, isEmpty);
+ expect(failing, isEmpty,
+ reason:
+ 'There are tests marked as failing that are not being run');
});
}
}
@@ -155,8 +161,8 @@
base.write(tail);
}
//
- // Determine the existing errors in the code
- // without either valid or invalid code.
+ // Determine the existing errors in the code without either valid or
+ // invalid code.
//
GatheringErrorListener listener =
new GatheringErrorListener(checkRanges: true);
@@ -181,7 +187,6 @@
if (descriptor.errorCodes != null) {
expectedInvalidCodeErrors.addAll(descriptor.errorCodes);
}
-
//
// Run the test.
//
@@ -255,6 +260,17 @@
*/
TestDescriptor(this.name, this.invalid, this.errorCodes, this.valid,
{this.allFailing: false, this.failing, this.expectedErrorsInValidCode});
+
+ /**
+ * Return a new description that is exactly like this descriptor except with
+ * the given [expectedErrorsInValidCode].
+ */
+ TestDescriptor withExpectedErrorsInValidCode(
+ List<ErrorCode> expectedErrorsInValidCode) =>
+ new TestDescriptor(name, invalid, errorCodes, valid,
+ allFailing: allFailing,
+ failing: failing,
+ expectedErrorsInValidCode: expectedErrorsInValidCode);
}
/**
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
index 206cec2..17a1456 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/error/codes.dart';
import 'partial_code_support.dart';
@@ -27,93 +28,170 @@
'top_level_variable',
[
new TestDescriptor(
- 'const',
- 'const',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "const _s_;",
- allFailing: true),
- new TestDescriptor('constName', 'const a',
- [ParserErrorCode.EXPECTED_TOKEN], "const a;",
- allFailing: true),
- new TestDescriptor('constTypeName', 'const int a',
- [ParserErrorCode.EXPECTED_TOKEN], "const int a;",
- allFailing: true),
+ 'const',
+ 'const',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "const _s_;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'constNameComma',
- 'const a,',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "const a, _s_;",
- allFailing: true),
+ 'constName',
+ 'const a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "const a;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'constTypeNameComma',
- 'const int a,',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "const int a, _s_;",
- allFailing: true),
- new TestDescriptor('constNameCommaName', 'const a, b',
- [ParserErrorCode.EXPECTED_TOKEN], "const a, b;",
- allFailing: true),
- new TestDescriptor('constTypeNameCommaName', 'const int a, b',
- [ParserErrorCode.EXPECTED_TOKEN], "const int a, b;",
- allFailing: true),
+ 'constTypeName',
+ 'const int a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "const int a;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'final',
- 'final',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "final _s_;",
- allFailing: true),
- new TestDescriptor('finalName', 'final a',
- [ParserErrorCode.EXPECTED_TOKEN], "final a;",
- allFailing: true),
- new TestDescriptor('finalTypeName', 'final int a',
- [ParserErrorCode.EXPECTED_TOKEN], "final int a;",
- allFailing: true),
+ 'constNameComma',
+ 'const a,',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "const a, _s_;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED,
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'type',
- 'int',
- [
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "int _s_;",
- allFailing: true),
+ 'constTypeNameComma',
+ 'const int a,',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "const int a, _s_;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED,
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;"),
+ 'constNameCommaName',
+ 'const a, b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "const a, b;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED,
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'var',
- 'var',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "var _s_;",
- failing: allExceptEof),
+ 'constTypeNameCommaName',
+ 'const int a, b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "const int a, b;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED,
+ CompileTimeErrorCode.CONST_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'varName', 'var a', [ParserErrorCode.EXPECTED_TOKEN], "var a;",
- failing: ['typedef', 'functionNonVoid', 'getter', 'setter']),
+ 'final',
+ 'final',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "final _s_;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ StaticWarningCode.FINAL_NOT_INITIALIZED
+ ],
+ ),
new TestDescriptor(
- 'varNameEquals',
- 'var a =',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "var a = _s_;",
- failing: allExceptEof),
- new TestDescriptor('varNameEqualsExpression', 'var a = b',
- [ParserErrorCode.EXPECTED_TOKEN], "var a = b;"),
+ 'finalName',
+ 'final a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "final a;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ StaticWarningCode.FINAL_NOT_INITIALIZED
+ ],
+ ),
+ new TestDescriptor(
+ 'finalTypeName',
+ 'final int a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "final int a;",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ StaticWarningCode.FINAL_NOT_INITIALIZED
+ ],
+ ),
+ new TestDescriptor(
+ 'type',
+ 'int',
+ [
+ ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "int _s_;",
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'typeName',
+ 'int a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "int a;",
+ ),
+ new TestDescriptor(
+ 'var',
+ 'var',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "var _s_;",
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'varName',
+ 'var a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "var a;",
+ failing: ['typedef', 'functionNonVoid', 'getter', 'setter'],
+ ),
+ new TestDescriptor(
+ 'varNameEquals',
+ 'var a =',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "var a = _s_;",
+ failing: allExceptEof,
+ ),
+ new TestDescriptor(
+ 'varNameEqualsExpression',
+ 'var a = b',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "var a = b;",
+ ),
],
PartialCodeTest.declarationSuffixes);
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart
index c7aa796..29040d2 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/while_statement_test.dart
@@ -13,33 +13,83 @@
class WhileStatementTest extends PartialCodeTest {
buildAll() {
buildTests(
- 'while_statement',
- [
- new TestDescriptor(
- 'keyword',
- 'while',
- [
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "while (_s_)",
- failing: ['eof', 'break', 'continue']),
- new TestDescriptor(
- 'leftParen',
- 'while (',
- [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN
- ],
- "while (_s_)",
- allFailing: true),
- new TestDescriptor('condition', 'while (a',
- [ParserErrorCode.EXPECTED_TOKEN], "while (a)",
- allFailing: true),
- ],
- PartialCodeTest.statementSuffixes,
- head: 'f() { ',
- tail: ' }');
+ 'while_statement',
+ <TestDescriptor>[
+ new TestDescriptor(
+ 'keyword',
+ 'while',
+ [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "while (_s_)",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ ),
+ new TestDescriptor(
+ 'leftParen',
+ 'while (',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ "while (_s_)",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ ),
+ new TestDescriptor(
+ 'condition',
+ 'while (a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "while (a)",
+ allFailing: true,
+ expectedErrorsInValidCode: [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ ),
+ ],
+ [],
+ head: 'f() { ',
+ tail: ' }',
+ );
+ buildTests(
+ 'while_statement',
+ <TestDescriptor>[
+ new TestDescriptor(
+ 'keyword',
+ 'while',
+ [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "while (_s_)",
+ failing: ['break', 'continue'],
+ ),
+ new TestDescriptor(
+ 'leftParen',
+ 'while (',
+ [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN],
+ "while (_s_)",
+ allFailing: true,
+ ),
+ new TestDescriptor(
+ 'condition',
+ 'while (a',
+ [ParserErrorCode.EXPECTED_TOKEN],
+ "while (a)",
+ allFailing: true,
+ ),
+ ],
+ PartialCodeTest.statementSuffixes,
+ head: 'f() { ',
+ includeEof: false,
+ tail: ' }',
+ );
}
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
index 9a48970..af7574a 100644
--- a/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/recovery_test_support.dart
@@ -27,8 +27,11 @@
validUnit =
parseCompilationUnit(validCode, codes: expectedErrorsInValidCode);
} catch (e) {
- print('*** Valid code did not parse correctly');
- print(validCode);
+ print('');
+ print(' Errors in valid code.');
+ print(' Error: $e');
+ print(' Code: $validCode');
+ print('');
rethrow;
}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 60c028e..ebbb2f5 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -316,7 +316,7 @@
@override
void writeOverrideOfInheritedMember(ExecutableElement member,
- {String returnTypeGroupName}) {
+ {StringBuffer, displayTextBuffer, String returnTypeGroupName}) {
// prepare environment
String prefix = getIndent(1);
// may be property
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index b0dac1f..1ec6942 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -314,6 +314,19 @@
}
/**
+ * Return `true` if the target is a double or int literal.
+ */
+ bool isDoubleOrIntLiteral() {
+ var entity = this.entity;
+ if (entity is Token) {
+ TokenType previousTokenType = entity.previous?.type;
+ return previousTokenType == TokenType.DOUBLE ||
+ previousTokenType == TokenType.INT;
+ }
+ return false;
+ }
+
+ /**
* Return `true` if the target is a functional argument in an argument list.
* The target [AstNode] hierarchy *must* be resolved for this to work.
* See [maybeFunctionalArgument].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 49cc0ea..171f216 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -113,6 +113,12 @@
*/
factory OpType.forCompletion(CompletionTarget target, int offset) {
OpType optype = new OpType._();
+
+ // Don't suggest anything right after double or integer literals.
+ if (target.isDoubleOrIntLiteral()) {
+ return optype;
+ }
+
target.containingNode
.accept(new _OpTypeAstVisitor(optype, target.entity, offset));
var mthDecl =
@@ -280,6 +286,14 @@
}
@override
+ void visitAssertInitializer(AssertInitializer node) {
+ if (identical(entity, node.condition)) {
+ optype.includeReturnValueSuggestions = true;
+ optype.includeTypeNameSuggestions = true;
+ }
+ }
+
+ @override
void visitAssertStatement(AssertStatement node) {
if (identical(entity, node.condition)) {
optype.includeReturnValueSuggestions = true;
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index 79d3f3c..a14dffc 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -169,8 +169,11 @@
/**
* Append a placeholder for an override of the specified inherited [member].
+ * If provided, write a string value suitable for display (e.g., in a
+ * completion popup) in the given [displayTextBuffer].
*/
- void writeOverrideOfInheritedMember(ExecutableElement member);
+ void writeOverrideOfInheritedMember(ExecutableElement member,
+ {StringBuffer displayTextBuffer});
/**
* Write the code for a parameter that would match the given [argument]. The
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index e696ed4..4acdff3 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -985,20 +985,25 @@
}
test_writeOverrideOfInheritedMember_method_nullAsTypeArgument() async {
- await _assertWriteOverrideOfInheritedMethod('''
+ await _assertWriteOverrideOfInheritedMethod(
+ '''
abstract class A {
List<Null> foo();
}
class B extends A {
}
-''', '''
+''',
+ '''
@override
List<Null> foo() {
// TODO: implement foo
return null;
}
-''');
+''',
+ // TODO(pquitslund): Add tests once implemented.
+ //displayText: 'foo() { ... }'
+ );
}
test_writeOverrideOfInheritedMember_method_voidAsTypeArgument() async {
@@ -1440,20 +1445,26 @@
* an inherited method is to be added, assert that the text of the overridden
* member matches the [expected] text (modulo white space).
*/
- _assertWriteOverrideOfInheritedMethod(String content, String expected) async {
+ _assertWriteOverrideOfInheritedMethod(String content, String expected,
+ {String displayText}) async {
String path = provider.convertPath('/test.dart');
addSource(path, content);
ClassElement classA = await _getClassElement(path, 'A');
+ StringBuffer displayBuffer =
+ displayText != null ? new StringBuffer() : null;
+
DartChangeBuilderImpl builder = new DartChangeBuilder(session);
await builder.addFileEdit(path, (FileEditBuilder builder) {
builder.addInsertion(content.length - 2, (EditBuilder builder) {
- (builder as DartEditBuilder)
- .writeOverrideOfInheritedMember(classA.methods[0]);
+ (builder as DartEditBuilder).writeOverrideOfInheritedMember(
+ classA.methods[0],
+ displayTextBuffer: displayBuffer);
});
});
SourceEdit edit = getEdit(builder);
expect(edit.replacement, equalsIgnoringWhitespace(expected));
+ expect(displayBuffer?.toString(), displayText);
}
Future<ClassElement> _getClassElement(String path, String name) async {
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index ddc6cc8..fff6171 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -223,6 +223,11 @@
await assertOpType(returnValue: true, typeNames: true);
}
+ test_AssertInitializer() async {
+ addTestSource('class C { C() : assert(^); }');
+ await assertOpType(returnValue: true, typeNames: true);
+ }
+
test_AssignmentExpression_name() async {
// SimpleIdentifier VariableDeclaration VariableDeclarationList
// VariableDeclarationStatement Block
@@ -1173,6 +1178,21 @@
await assertOpType(returnValue: true, typeNames: true);
}
+ test_IntegerLiteral_inArgumentList() async {
+ addTestSource('main() { print(1^); }');
+ await assertOpType();
+ }
+
+ test_IntegerLiteral_inListLiteral() async {
+ addTestSource('main() { var items = [1^]; }');
+ await assertOpType();
+ }
+
+ test_DoubleLiteral() async {
+ addTestSource('main() { print(1.2^); }');
+ await assertOpType();
+ }
+
test_IsExpression_type_partial() async {
// SimpleIdentifier TypeName IsExpression IfStatement
addTestSource('main(){var a; if (a is Obj^)}');
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 19d3b29..36ac2da 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -289,6 +289,8 @@
void setUseKernel(String argument) {
useKernel = true;
+ // TODO(sigmund): reenable hints (Issue #32111)
+ showHints = false;
passThrough(argument);
}
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 5ea9202..4313798 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -1166,6 +1166,8 @@
InterfaceType getSupertype(ClassEntity cls);
/// Returns all supertypes of [cls].
+ // TODO(johnniwinther): This should include `Function` if [cls] declares
+ // a `call` method.
Iterable<InterfaceType> getSupertypes(ClassEntity cls);
/// Returns all types directly implemented by [cls].
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 1131467..9a025ac 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -987,15 +987,11 @@
BackendImpacts impacts =
new BackendImpacts(compiler.options, closedWorld.commonElements);
if (compiler.options.disableRtiOptimization) {
- _rtiSubstitutions = new TrivialRuntimeTypesSubstitutions(
- closedWorld.elementEnvironment, closedWorld.dartTypes);
+ _rtiSubstitutions = new TrivialRuntimeTypesSubstitutions(closedWorld);
_rtiChecksBuilder =
new TrivialRuntimeTypesChecksBuilder(closedWorld, _rtiSubstitutions);
} else {
- RuntimeTypesImpl runtimeTypesImpl = new RuntimeTypesImpl(
- closedWorld.commonElements,
- closedWorld.elementEnvironment,
- closedWorld.dartTypes);
+ RuntimeTypesImpl runtimeTypesImpl = new RuntimeTypesImpl(closedWorld);
_rtiChecksBuilder = runtimeTypesImpl;
_rtiSubstitutions = runtimeTypesImpl;
}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 90cbe16..3a880dc 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -27,7 +27,7 @@
/// For each class, stores the possible class subtype tests that could succeed.
abstract class TypeChecks {
/// Get the set of checks required for class [element].
- Iterable<TypeCheck> operator [](ClassEntity element);
+ ClassChecks operator [](ClassEntity element);
/// Get the iterable for all classes that need type checks.
Iterable<ClassEntity> get classes;
@@ -167,8 +167,8 @@
/// in the return type or the argument types.
Iterable<ClassEntity> getReferencedClasses(FunctionType type);
- /// Return all classes that use type arguments.
- Iterable<ClassEntity> getRequiredArgumentClasses();
+ /// Return all classes needed for runtime type information.
+ Iterable<ClassEntity> get requiredClasses;
/// Return all classes immediately used in explicit or implicit is-tests.
///
@@ -202,7 +202,7 @@
TypeChecks get requiredChecks => _typeChecks;
@override
- Iterable<ClassEntity> getRequiredArgumentClasses() => _allClasses;
+ Iterable<ClassEntity> get requiredClasses => _allClasses;
@override
Iterable<ClassEntity> getReferencedClasses(FunctionType type) => _allClasses;
@@ -245,13 +245,20 @@
@override
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder) {
- Set<ClassEntity> classes = _closedWorld
- .getClassSet(_closedWorld.commonElements.objectClass)
- .subtypes()
- .toSet();
rtiChecksBuilderClosed = true;
+ ClassUse classUse = new ClassUse()
+ ..instance = true
+ ..checkedInstance = true
+ ..typeArgument = true
+ ..checkedTypeArgument = true;
+ Map<ClassEntity, ClassUse> classUseMap = <ClassEntity, ClassUse>{};
+ for (ClassEntity cls in _closedWorld
+ .getClassSet(_closedWorld.commonElements.objectClass)
+ .subtypes()) {
+ classUseMap[cls] = classUse;
+ }
TypeChecks typeChecks = _substitutions._requiredChecks =
- _substitutions._computeChecks(classes, classes);
+ _substitutions._computeChecks(classUseMap);
return new TrivialTypesChecks(typeChecks);
}
@@ -285,31 +292,215 @@
abstract class RuntimeTypesSubstitutionsMixin
implements RuntimeTypesSubstitutions {
- ElementEnvironment get _elementEnvironment;
- DartTypes get _types;
+ ClosedWorld get _closedWorld;
TypeChecks get _requiredChecks;
- TypeChecks _computeChecks(
- Iterable<ClassEntity> instantiated, Iterable<ClassEntity> checked) {
+ ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
+ DartTypes get _types => _closedWorld.dartTypes;
+ RuntimeTypesNeed get _rtiNeed => _closedWorld.rtiNeed;
+
+ /// Compute the required type checks and substitutions for the given
+ /// instantiated and checked classes.
+ TypeChecks _computeChecks(Map<ClassEntity, ClassUse> classUseMap) {
// Run through the combination of instantiated and checked
// arguments and record all combination where the element of a checked
// argument is a superclass of the element of an instantiated type.
TypeCheckMapping result = new TypeCheckMapping();
- for (ClassEntity element in instantiated) {
- if (checked.contains(element)) {
- result.add(element, element, null);
+ Set<ClassEntity> handled = new Set<ClassEntity>();
+
+ // Empty usage object for classes with no direct rti usage.
+ final ClassUse emptyUse = new ClassUse();
+
+ /// Compute the $isX and $asX functions need for [cls].
+ ClassChecks computeChecks(ClassEntity cls) {
+ if (!handled.add(cls)) return result[cls];
+
+ ClassChecks checks = new ClassChecks();
+ result[cls] = checks;
+ ClassUse classUse = classUseMap[cls] ?? emptyUse;
+
+ // Find the superclass from which [cls] inherits checks.
+ ClassEntity superClass = _elementEnvironment.getSuperClass(cls,
+ skipUnnamedMixinApplications: true);
+ ClassChecks superChecks;
+ bool extendsSuperClassTrivially = false;
+ if (superClass != null) {
+ // Compute the checks inherited from [superClass].
+ superChecks = computeChecks(superClass);
+
+ // Does [cls] extend [superClass] trivially?
+ //
+ // For instance:
+ //
+ // class A<T> {}
+ // class B<S> extends A<S> {}
+ // class C<U, V> extends A<U> {}
+ // class D extends A<int> {}
+ //
+ // here `B` extends `A` trivially, but `C` and `D` don't.
+ extendsSuperClassTrivially = isTrivialSubstitution(cls, superClass);
}
- // Find all supertypes of [element] in [checkedArguments] and add checks
- // and precompute the substitutions for them.
- for (InterfaceType supertype in _types.getSupertypes(element)) {
- ClassEntity superelement = supertype.element;
- if (checked.contains(superelement)) {
- Substitution substitution =
- computeSubstitution(element, superelement);
- result.add(element, superelement, substitution);
+
+ bool isNativeClass = _closedWorld.nativeData.isNativeClass(cls);
+ if (classUse.typeArgument ||
+ (isNativeClass && classUse.checkedInstance)) {
+ // We need [cls] at runtime - even if [cls] is not instantiated. Either
+ // as a type argument or for an is-test if [cls] is native.
+ checks.add(new TypeCheck(cls, null, needsIs: isNativeClass));
+ }
+
+ // Compute the set of classes that [cls] inherited properties from.
+ //
+ // This set reflects the emitted class hierarchy and therefore uses
+ // `getEffectiveMixinClass` to find the inherited mixins.
+ Set<ClassEntity> inheritedClasses = new Set<ClassEntity>();
+ ClassEntity other = cls;
+ while (other != null) {
+ inheritedClasses.add(other);
+ if (_elementEnvironment.isMixinApplication(other)) {
+ inheritedClasses
+ .add(_elementEnvironment.getEffectiveMixinClass(other));
+ }
+ other = _elementEnvironment.getSuperClass(other);
+ }
+
+ /// Compute the needed check for [cls] against the class of the super
+ /// [type].
+ void processSupertype(InterfaceType type) {
+ ClassEntity checkedClass = type.element;
+ ClassUse checkedClassUse = classUseMap[checkedClass] ?? emptyUse;
+
+ // Where [cls] inherits properties for [checkedClass].
+ bool inheritsFromCheckedClass = inheritedClasses.contains(checkedClass);
+
+ // If [cls] inherits properties from [checkedClass] and [checkedClass]
+ // needs type arguments, [cls] must provide a substitution for
+ // [checkedClass].
+ //
+ // For instance:
+ //
+ // class M<T> {
+ // m() => T;
+ // }
+ // class S {}
+ // class C extends S with M<int> {}
+ //
+ // Here `C` needs an `$asM` substitution function to provide the value
+ // of `T` in `M.m`.
+ bool needsTypeArgumentsForCheckedClass = inheritsFromCheckedClass &&
+ _rtiNeed.classNeedsTypeArguments(checkedClass);
+
+ // Whether [checkedClass] is used in an instance test or type argument
+ // test.
+ //
+ // For instance:
+ //
+ // class A {}
+ // class B {}
+ // test(o) => o is A || o is List<B>;
+ //
+ // Here `A` is used in an instance test and `B` is used in a type
+ // argument test.
+ bool isChecked = checkedClassUse.checkedTypeArgument ||
+ checkedClassUse.checkedInstance;
+
+ if (isChecked || needsTypeArgumentsForCheckedClass) {
+ // We need an $isX and/or $asX property on [cls] for [checkedClass].
+
+ // Whether `cls` implements `checkedClass` trivially.
+ //
+ // For instance:
+ //
+ // class A<T> {}
+ // class B<S> implements A<S> {}
+ // class C<U, V> implements A<U> {}
+ // class D implements A<int> {}
+ //
+ // here `B` implements `A` trivially, but `C` and `D` don't.
+ bool implementsCheckedTrivially =
+ isTrivialSubstitution(cls, checkedClass);
+
+ // Whether [checkedClass] is generic.
+ //
+ // Currently [isTrivialSubstitution] reports that [cls] implements
+ // [checkedClass] trivially if [checkedClass] is not generic. In this
+ // case the substitution is not only trivial it is also not needed.
+ bool isCheckedGeneric =
+ _elementEnvironment.isGenericClass(checkedClass);
+
+ // The checks for [checkedClass] inherited for [superClass].
+ TypeCheck checkFromSuperClass =
+ superChecks != null ? superChecks[checkedClass] : null;
+
+ // Whether [cls] need an explicit $isX property for [checkedClass].
+ //
+ // If [cls] inherits from [checkedClass] it also inherits the $isX
+ // property automatically generated on [checkedClass].
+ bool needsIs = !inheritsFromCheckedClass && isChecked;
+
+ if (checkFromSuperClass != null) {
+ // The superclass has a substitution function for [checkedClass].
+ // Check if we can reuse this it of need to override it.
+ //
+ // The inherited $isX property does _not_ need to be overriding.
+ if (extendsSuperClassTrivially) {
+ // [cls] implements [checkedClass] the same way as [superClass]
+ // so the inherited substitution function already works.
+ checks.add(new TypeCheck(checkedClass, null, needsIs: false));
+ } else {
+ // [cls] implements [checkedClass] differently from [superClass]
+ // so the inherited substitution function needs to be replaced.
+ if (implementsCheckedTrivially) {
+ // We need an explicit trivial substitution function for
+ // [checkedClass] that overrides the inherited function.
+ checks.add(new TypeCheck(checkedClass,
+ isCheckedGeneric ? const Substitution.trivial() : null,
+ needsIs: false));
+ } else {
+ // We need a non-trivial substitution function for
+ // [checkedClass].
+ checks.add(new TypeCheck(
+ checkedClass, computeSubstitution(cls, checkedClass),
+ needsIs: false));
+ }
+ }
+ } else {
+ // The superclass has no substitution function for [checkedClass].
+ if (implementsCheckedTrivially) {
+ // We don't add an explicit substitution function for
+ // [checkedClass] because the substitution is trivial and doesn't
+ // need to override an inherited function.
+ checks.add(new TypeCheck(checkedClass, null, needsIs: needsIs));
+ } else {
+ // We need a non-trivial substitution function for
+ // [checkedClass].
+ checks.add(new TypeCheck(
+ checkedClass, computeSubstitution(cls, checkedClass),
+ needsIs: needsIs));
+ }
+ }
}
}
+
+ for (InterfaceType type in _types.getSupertypes(cls)) {
+ processSupertype(type);
+ }
+ FunctionType callType = _types.getCallType(_types.getThisType(cls));
+ if (callType != null) {
+ processSupertype(_closedWorld.commonElements.functionType);
+ }
+ return checks;
}
+
+ for (ClassEntity cls in classUseMap.keys) {
+ ClassUse classUse = classUseMap[cls] ?? emptyUse;
+ if (classUse.instance || classUse.typeArgument) {
+ // Add checks only for classes that are live either as instantiated
+ // classes or type arguments passed at runtime.
+ computeChecks(cls);
+ }
+ }
+
return result;
}
@@ -318,11 +509,14 @@
Set<ClassEntity> instantiated = new Set<ClassEntity>();
ArgumentCollector collector = new ArgumentCollector();
for (ClassEntity target in checks.classes) {
- instantiated.add(target);
- for (TypeCheck check in checks[target]) {
- Substitution substitution = check.substitution;
- if (substitution != null) {
- collector.collectAll(substitution.arguments);
+ ClassChecks classChecks = checks[target];
+ if (classChecks.isNotEmpty) {
+ instantiated.add(target);
+ for (TypeCheck check in classChecks.checks) {
+ Substitution substitution = check.substitution;
+ if (substitution != null) {
+ collector.collectAll(substitution.arguments);
+ }
}
}
}
@@ -371,7 +565,7 @@
@override
Substitution getSubstitution(ClassEntity cls, ClassEntity other) {
// Look for a precomputed check.
- for (TypeCheck check in _requiredChecks[cls]) {
+ for (TypeCheck check in _requiredChecks[cls].checks) {
if (check.cls == other) {
return check.substitution;
}
@@ -400,17 +594,10 @@
}
class TrivialRuntimeTypesSubstitutions extends RuntimeTypesSubstitutionsMixin {
- final ElementEnvironment _elementEnvironment;
- final DartTypes _types;
+ final ClosedWorld _closedWorld;
TypeChecks _requiredChecks;
- TrivialRuntimeTypesSubstitutions(this._elementEnvironment, this._types);
-
- @override
- TypeChecks computeChecks(
- Iterable<ClassEntity> instantiated, Iterable<ClassEntity> checked) {
- return _requiredChecks;
- }
+ TrivialRuntimeTypesSubstitutions(this._closedWorld);
}
/// Interface for computing substitutions need for runtime type checks.
@@ -419,11 +606,6 @@
Substitution getSubstitution(ClassEntity cls, ClassEntity other);
- /// Compute the required type checks and substitutions for the given
- /// instantiated and checked classes.
- TypeChecks computeChecks(
- Iterable<ClassEntity> instantiated, Iterable<ClassEntity> checked);
-
Set<ClassEntity> getClassesUsedInSubstitutions(TypeChecks checks);
static bool hasTypeArguments(DartType type) {
@@ -1168,30 +1350,18 @@
}
class _RuntimeTypesChecks implements RuntimeTypesChecks {
- final RuntimeTypesSubstitutions substitutions;
+ final RuntimeTypesSubstitutions _substitutions;
final TypeChecks requiredChecks;
- final Iterable<ClassEntity> directlyInstantiatedArguments;
- final Iterable<ClassEntity> checkedArguments;
final Iterable<ClassEntity> checkedClasses;
final Iterable<FunctionType> checkedFunctionTypes;
- final TypeVariableTests typeVariableTests;
+ final TypeVariableTests _typeVariableTests;
- _RuntimeTypesChecks(
- this.substitutions,
- this.requiredChecks,
- this.directlyInstantiatedArguments,
- this.checkedArguments,
- this.checkedClasses,
- this.checkedFunctionTypes,
- this.typeVariableTests);
+ _RuntimeTypesChecks(this._substitutions, this.requiredChecks,
+ this.checkedClasses, this.checkedFunctionTypes, this._typeVariableTests);
@override
- Iterable<ClassEntity> getRequiredArgumentClasses() {
- Set<ClassEntity> requiredArgumentClasses = new Set<ClassEntity>.from(
- substitutions.getClassesUsedInSubstitutions(requiredChecks));
- return requiredArgumentClasses
- ..addAll(directlyInstantiatedArguments)
- ..addAll(checkedArguments);
+ Iterable<ClassEntity> get requiredClasses {
+ return _substitutions.getClassesUsedInSubstitutions(requiredChecks);
}
@override
@@ -1203,14 +1373,13 @@
@override
Iterable<ClassEntity> get classesUsingTypeVariableTests =>
- typeVariableTests.classTests;
+ _typeVariableTests.classTests;
}
class RuntimeTypesImpl extends _RuntimeTypesBase
with RuntimeTypesSubstitutionsMixin
implements RuntimeTypesChecksBuilder {
- final CommonElements _commentElements;
- final ElementEnvironment _elementEnvironment;
+ final ClosedWorld _closedWorld;
// The set of type arguments tested against type variable bounds.
final Set<DartType> checkedTypeArguments = new Set<DartType>();
@@ -1221,16 +1390,15 @@
bool rtiChecksBuilderClosed = false;
- RuntimeTypesImpl(
- this._commentElements, this._elementEnvironment, DartTypes types)
- : super(types);
+ RuntimeTypesImpl(this._closedWorld) : super(_closedWorld.dartTypes);
+
+ CommonElements get _commonElements => _closedWorld.commonElements;
+ ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
+ RuntimeTypesNeed get _rtiNeed => _closedWorld.rtiNeed;
@override
TypeChecks get _requiredChecks => cachedRequiredChecks;
- Set<ClassEntity> directlyInstantiatedArguments;
- Set<ClassEntity> allInstantiatedArguments;
-
@override
void registerTypeVariableBoundsSubtypeCheck(
DartType typeArgument, DartType bound) {
@@ -1241,42 +1409,85 @@
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder) {
TypeVariableTests typeVariableTests = new TypeVariableTests(
- _elementEnvironment, _commentElements, _types, codegenWorldBuilder);
+ _elementEnvironment, _commonElements, _types, codegenWorldBuilder);
Set<DartType> explicitIsChecks = typeVariableTests.explicitIsChecks;
Set<DartType> implicitIsChecks = typeVariableTests.implicitIsChecks;
+ Map<ClassEntity, ClassUse> classUseMap = <ClassEntity, ClassUse>{};
+
Set<ClassEntity> checkedClasses = new Set<ClassEntity>();
Set<FunctionType> checkedFunctionTypes = new Set<FunctionType>();
+ TypeVisitor liveTypeVisitor =
+ new TypeVisitor(onClass: (ClassEntity cls, {bool inTypeArgument}) {
+ ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
+ if (inTypeArgument) {
+ classUse.typeArgument = true;
+ }
+ });
+
+ TypeVisitor testedTypeVisitor =
+ new TypeVisitor(onClass: (ClassEntity cls, {bool inTypeArgument}) {
+ ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
+ if (inTypeArgument) {
+ classUse.typeArgument = true;
+ classUse.checkedTypeArgument = true;
+ } else {
+ classUse.checkedInstance = true;
+ }
+ });
+
void processType(DartType t) {
if (t is FunctionType) {
checkedFunctionTypes.add(t);
} else if (t is InterfaceType) {
checkedClasses.add(t.element);
}
+ testedTypeVisitor.visitType(t, false);
}
+ codegenWorldBuilder.instantiatedTypes.forEach((t) {
+ liveTypeVisitor.visitType(t, false);
+ ClassUse classUse =
+ classUseMap.putIfAbsent(t.element, () => new ClassUse());
+ classUse.instance = true;
+ });
+ Set<FunctionType> instantiatedClosureTypes =
+ computeInstantiatedClosureTypes(codegenWorldBuilder);
+ instantiatedClosureTypes.forEach((t) {
+ testedTypeVisitor.visitType(t, false);
+ });
+
explicitIsChecks.forEach(processType);
implicitIsChecks.forEach(processType);
- // These types are needed for is-checks against function types.
- Set<DartType> instantiatedTypesAndClosures =
- computeInstantiatedTypesAndClosures(codegenWorldBuilder);
- computeInstantiatedArguments(
- instantiatedTypesAndClosures, explicitIsChecks, implicitIsChecks);
- Set<ClassEntity> checkedArguments = computeCheckedArguments(
- instantiatedTypesAndClosures, explicitIsChecks, implicitIsChecks);
- cachedRequiredChecks =
- computeChecks(allInstantiatedArguments, checkedArguments);
+ cachedRequiredChecks = _computeChecks(classUseMap);
rtiChecksBuilderClosed = true;
- return new _RuntimeTypesChecks(
- this,
- cachedRequiredChecks,
- directlyInstantiatedArguments,
- checkedArguments,
- checkedClasses,
- checkedFunctionTypes,
- typeVariableTests);
+ return new _RuntimeTypesChecks(this, cachedRequiredChecks, checkedClasses,
+ checkedFunctionTypes, typeVariableTests);
+ }
+
+ Set<FunctionType> computeInstantiatedClosureTypes(
+ CodegenWorldBuilder codegenWorldBuilder) {
+ Set<FunctionType> instantiatedClosureTypes = new Set<FunctionType>();
+ for (InterfaceType instantiatedType
+ in codegenWorldBuilder.instantiatedTypes) {
+ FunctionType callType = _types.getCallType(instantiatedType);
+ if (callType != null) {
+ instantiatedClosureTypes.add(callType);
+ }
+ }
+ for (FunctionEntity element
+ in codegenWorldBuilder.staticFunctionsNeedingGetter) {
+ instantiatedClosureTypes
+ .add(_elementEnvironment.getFunctionType(element));
+ }
+
+ for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
+ instantiatedClosureTypes
+ .add(_elementEnvironment.getFunctionType(element));
+ }
+ return instantiatedClosureTypes;
}
Set<DartType> computeInstantiatedTypesAndClosures(
@@ -1300,99 +1511,6 @@
}
return instantiatedTypes;
}
-
- /**
- * Collects all types used in type arguments of instantiated types.
- *
- * This includes type arguments used in supertype relations, because we may
- * have a type check against this supertype that includes a check against
- * the type arguments.
- */
- void computeInstantiatedArguments(Set<DartType> instantiatedTypes,
- Set<DartType> isChecks, Set<DartType> implicitIsChecks) {
- ArgumentCollector superCollector = new ArgumentCollector();
- ArgumentCollector directCollector = new ArgumentCollector();
- FunctionArgumentCollector functionArgumentCollector =
- new FunctionArgumentCollector();
-
- // We need to add classes occurring in function type arguments, like for
- // instance 'I' for [: o is C<f> :] where f is [: typedef I f(); :].
- void collectFunctionTypeArguments(Iterable<DartType> types) {
- for (DartType type in types) {
- functionArgumentCollector.collect(type);
- }
- }
-
- collectFunctionTypeArguments(isChecks);
- collectFunctionTypeArguments(implicitIsChecks);
- collectFunctionTypeArguments(checkedBounds);
-
- void collectTypeArguments(Iterable<DartType> types,
- {bool isTypeArgument: false}) {
- for (DartType type in types) {
- directCollector.collect(type, isTypeArgument: isTypeArgument);
- if (type is InterfaceType) {
- ClassEntity cls = type.element;
- for (InterfaceType supertype in _types.getSupertypes(cls)) {
- superCollector.collect(supertype, isTypeArgument: isTypeArgument);
- }
- }
- }
- }
-
- collectTypeArguments(instantiatedTypes);
- collectTypeArguments(checkedTypeArguments, isTypeArgument: true);
-
- for (ClassEntity cls in superCollector.classes.toList()) {
- for (InterfaceType supertype in _types.getSupertypes(cls)) {
- superCollector.collect(supertype);
- }
- }
-
- directlyInstantiatedArguments = directCollector.classes
- ..addAll(functionArgumentCollector.classes);
- allInstantiatedArguments = superCollector.classes
- ..addAll(directlyInstantiatedArguments);
- }
-
- /// Collects all type arguments used in is-checks.
- Set<ClassEntity> computeCheckedArguments(Set<DartType> instantiatedTypes,
- Set<DartType> isChecks, Set<DartType> implicitIsChecks) {
- ArgumentCollector collector = new ArgumentCollector();
- FunctionArgumentCollector functionArgumentCollector =
- new FunctionArgumentCollector();
-
- // We need to add types occurring 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'.
- void collectFunctionTypeArguments(Iterable<DartType> types) {
- for (DartType type in types) {
- functionArgumentCollector.collect(type);
- }
- }
-
- collectFunctionTypeArguments(instantiatedTypes);
- collectFunctionTypeArguments(checkedTypeArguments);
-
- void collectTypeArguments(Iterable<DartType> types,
- {bool isTypeArgument: false}) {
- for (DartType type in types) {
- collector.collect(type, isTypeArgument: isTypeArgument);
- }
- }
-
- collectTypeArguments(isChecks);
- collectTypeArguments(implicitIsChecks);
- collectTypeArguments(checkedBounds, isTypeArgument: true);
-
- return collector.classes..addAll(functionArgumentCollector.classes);
- }
-
- @override
- TypeChecks computeChecks(
- Iterable<ClassEntity> instantiated, Iterable<ClassEntity> checked) {
- return _computeChecks(instantiated, checked);
- }
}
class RuntimeTypesEncoderImpl implements RuntimeTypesEncoder {
@@ -1509,6 +1627,10 @@
@override
jsAst.Expression getSubstitutionCode(
Emitter emitter, Substitution substitution) {
+ if (substitution.isTrivial) {
+ return new jsAst.LiteralNull();
+ }
+
jsAst.Expression declaration(TypeVariableType variable) {
return new jsAst.Parameter(getVariableName(variable.element.name));
}
@@ -1799,17 +1921,15 @@
}
class TypeCheckMapping implements TypeChecks {
- final Map<ClassEntity, Set<TypeCheck>> map =
- new Map<ClassEntity, Set<TypeCheck>>();
+ final Map<ClassEntity, ClassChecks> map = new Map<ClassEntity, ClassChecks>();
- Iterable<TypeCheck> operator [](ClassEntity element) {
- Set<TypeCheck> result = map[element];
- return result != null ? result : const <TypeCheck>[];
+ ClassChecks operator [](ClassEntity element) {
+ ClassChecks result = map[element];
+ return result != null ? result : const ClassChecks.empty();
}
- void add(ClassEntity cls, ClassEntity check, Substitution substitution) {
- map.putIfAbsent(cls, () => new Set<TypeCheck>());
- map[cls].add(new TypeCheck(check, substitution));
+ void operator []=(ClassEntity element, ClassChecks checks) {
+ map[element] = checks;
}
Iterable<ClassEntity> get classes => map.keys;
@@ -1817,7 +1937,7 @@
String toString() {
StringBuffer sb = new StringBuffer();
for (ClassEntity holder in classes) {
- for (TypeCheck check in this[holder]) {
+ for (TypeCheck check in this[holder].checks) {
sb.write('${holder.name} <: ${check.cls.name}, ');
}
}
@@ -1904,18 +2024,28 @@
/// representation consult the documentation of [getSupertypeSubstitution].
//TODO(floitsch): Remove support for non-function substitutions.
class Substitution {
+ final bool isTrivial;
final bool isFunction;
final List<DartType> arguments;
final List<DartType> parameters;
- Substitution.list(this.arguments)
- : isFunction = false,
+ const Substitution.trivial()
+ : isTrivial = true,
+ isFunction = false,
+ arguments = const <DartType>[],
parameters = const <DartType>[];
- Substitution.function(this.arguments, this.parameters) : isFunction = true;
+ Substitution.list(this.arguments)
+ : isTrivial = false,
+ isFunction = false,
+ parameters = const <DartType>[];
- String toString() => 'Substitution(isFunction=$isFunction,'
- 'arguments=$arguments,parameters=$parameters)';
+ Substitution.function(this.arguments, this.parameters)
+ : isTrivial = false,
+ isFunction = true;
+
+ String toString() => 'Substitution(isTrivial=$isTrivial,'
+ 'isFunction=$isFunction,arguments=$arguments,parameters=$parameters)';
}
/**
@@ -1924,11 +2054,148 @@
*/
class TypeCheck {
final ClassEntity cls;
+ final bool needsIs;
final Substitution substitution;
final int hashCode = _nextHash = (_nextHash + 100003).toUnsigned(30);
static int _nextHash = 0;
- TypeCheck(this.cls, this.substitution);
+ TypeCheck(this.cls, this.substitution, {this.needsIs: true});
- String toString() => 'TypeCheck(cls=$cls,substitution=$substitution)';
+ String toString() =>
+ 'TypeCheck(cls=$cls,needsIs=$needsIs,substitution=$substitution)';
+}
+
+class TypeVisitor extends ResolutionDartTypeVisitor<void, bool> {
+ final void Function(ClassEntity entity, {bool inTypeArgument}) onClass;
+ final void Function(TypeVariableEntity entity, {bool inTypeArgument})
+ onTypeVariable;
+ final void Function(FunctionType type, {bool inTypeArgument}) onFunctionType;
+
+ TypeVisitor({this.onClass, this.onTypeVariable, this.onFunctionType});
+
+ visitType(DartType type, bool inTypeArgument) =>
+ type.accept(this, inTypeArgument);
+
+ visitTypes(List<DartType> types, bool inTypeArgument) {
+ for (DartType type in types) {
+ visitType(type, inTypeArgument);
+ }
+ }
+
+ @override
+ void visitTypeVariableType(TypeVariableType type, bool inTypeArgument) {
+ if (onTypeVariable != null) {
+ onTypeVariable(type.element, inTypeArgument: inTypeArgument);
+ }
+ }
+
+ @override
+ visitInterfaceType(InterfaceType type, bool inTypeArgument) {
+ if (onClass != null) {
+ onClass(type.element, inTypeArgument: inTypeArgument);
+ }
+ visitTypes(type.typeArguments, true);
+ }
+
+ @override
+ visitFunctionType(FunctionType type, bool inTypeArgument) {
+ if (onFunctionType != null) {
+ onFunctionType(type, inTypeArgument: inTypeArgument);
+ }
+ // Visit all nested types as type arguments; these types are not runtime
+ // instances but runtime type representations.
+ visitType(type.returnType, true);
+ visitTypes(type.parameterTypes, true);
+ visitTypes(type.optionalParameterTypes, true);
+ visitTypes(type.namedParameterTypes, true);
+ }
+
+ @override
+ visitTypedefType(TypedefType type, bool inTypeArgument) {
+ visitType(type.unaliased, inTypeArgument);
+ }
+
+ @override
+ visitFunctionTypeVariable(FunctionTypeVariable type, bool inTypeArgument) {
+ visitType(type.bound, inTypeArgument);
+ }
+}
+
+/// [TypeCheck]s need for a single class.
+class ClassChecks {
+ final Map<ClassEntity, TypeCheck> _map;
+
+ ClassChecks() : _map = <ClassEntity, TypeCheck>{};
+
+ const ClassChecks.empty() : _map = const <ClassEntity, TypeCheck>{};
+
+ void add(TypeCheck check) {
+ _map[check.cls] = check;
+ }
+
+ TypeCheck operator [](ClassEntity cls) => _map[cls];
+
+ Iterable<TypeCheck> get checks => _map.values;
+
+ bool get isNotEmpty => _map.isNotEmpty;
+
+ String toString() {
+ return 'ClassChecks($checks)';
+ }
+}
+
+/// Runtime type usage for a class.
+class ClassUse {
+ /// Whether the class is instantiated.
+ ///
+ /// For instance `A` in:
+ ///
+ /// class A {}
+ /// main() => new A();
+ ///
+ bool instance = false;
+
+ /// Whether objects are checked to be instances of the class.
+ ///
+ /// For instance `A` in:
+ ///
+ /// class A {}
+ /// main() => null is A;
+ ///
+ bool checkedInstance = false;
+
+ /// Whether the class is passed as a type argument at runtime.
+ ///
+ /// For instance `A` in:
+ ///
+ /// class A {}
+ /// main() => new List<A>() is List<String>();
+ ///
+ bool typeArgument = false;
+
+ /// Whether the class is checked as a type argument at runtime.
+ ///
+ /// For instance `A` in:
+ ///
+ /// class A {}
+ /// main() => new List<String>() is List<A>();
+ ///
+ bool checkedTypeArgument = false;
+
+ String toString() {
+ List<String> properties = <String>[];
+ if (instance) {
+ properties.add('instance');
+ }
+ if (checkedInstance) {
+ properties.add('checkedInstance');
+ }
+ if (typeArgument) {
+ properties.add('typeArgument');
+ }
+ if (checkedTypeArgument) {
+ properties.add('checkedTypeArgument');
+ }
+ return 'ClassUse(${properties.join(',')})';
+ }
}
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index d9cf761..cb3ae06 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -199,7 +199,6 @@
backend.superMemberData,
typeTestRegistry.rtiChecks,
backend.rtiEncoder,
- backend.rtiSubstitutions,
backend.jsInteropAnalysis,
backend.oneShotInterceptorData,
backend.customElementsCodegenAnalysis,
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 70e3e35..12110ab 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -76,10 +76,8 @@
* [classesModifiedByEmitRTISupport] contains the list of classes that must
* exist, because runtime-type support adds information to the class.
*/
- Set<Class> prepareNativeClasses(
- List<Class> classes,
- Set<ClassEntity> interceptorClassesNeededByConstants,
- Set<ClassEntity> classesModifiedByEmitRTISupport) {
+ Set<Class> prepareNativeClasses(List<Class> classes,
+ Set<ClassEntity> interceptorClassesNeededByConstants) {
assert(classes.every((Class cls) => cls != null));
hasNativeClasses = classes.isNotEmpty;
@@ -136,10 +134,6 @@
needed = true;
} else if (interceptorClassesNeededByConstants.contains(classElement)) {
needed = true;
- } else if (classesModifiedByEmitRTISupport.contains(classElement)) {
- // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
- // adds information to a class prototype or constructor.
- needed = true;
} else if (extensionPoints.containsKey(cls)) {
needed = true;
}
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 8b04d86..7877cdb 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -86,7 +86,7 @@
* Return a function that returns true if its argument is a class
* that needs to be emitted.
*/
- Function computeClassFilter() {
+ Function computeClassFilter(Iterable<ClassEntity> backendTypeHelpers) {
if (_mirrorsData.isTreeShakingDisabled) {
return (ClassEntity cls) => true;
}
@@ -117,16 +117,26 @@
}
// These classes are just helpers for the backend's type system.
- unneededClasses.add(_commonElements.jsMutableArrayClass);
- unneededClasses.add(_commonElements.jsFixedArrayClass);
- unneededClasses.add(_commonElements.jsExtendableArrayClass);
- unneededClasses.add(_commonElements.jsUInt32Class);
- unneededClasses.add(_commonElements.jsUInt31Class);
- unneededClasses.add(_commonElements.jsPositiveIntClass);
+ unneededClasses.addAll(backendTypeHelpers);
return (ClassEntity cls) => !unneededClasses.contains(cls);
}
+ // Return the classes that are just helpers for the backend's type system.
+ static Iterable<ClassEntity> getBackendTypeHelpers(
+ CommonElements commonElements) {
+ return <ClassEntity>[
+ commonElements.jsMutableArrayClass,
+ commonElements.jsFixedArrayClass,
+ commonElements.jsExtendableArrayClass,
+ // TODO(johnniwinther): Mark this as a backend type helper:
+ //commonElements.jsUnmodifiableArrayClass,
+ commonElements.jsUInt32Class,
+ commonElements.jsUInt31Class,
+ commonElements.jsPositiveIntClass
+ ];
+ }
+
/**
* Compute all the constants that must be emitted.
*/
@@ -193,6 +203,9 @@
/// Compute all the classes and typedefs that must be emitted.
void computeNeededDeclarations() {
+ Set<ClassEntity> backendTypeHelpers =
+ getBackendTypeHelpers(_commonElements).toSet();
+
// Compute needed typedefs.
typedefsNeededForReflection = _sorter.sortTypedefs(_closedWorld.allTypedefs
.where(_mirrorsData.isTypedefAccessibleByReflection)
@@ -203,7 +216,7 @@
// TODO(johnniwinther): This should be accessed from a codegen closed
// world.
_worldBuilder.directlyInstantiatedClasses
- .where(computeClassFilter())
+ .where(computeClassFilter(backendTypeHelpers))
.toSet();
void addClassWithSuperclasses(ClassEntity cls) {
@@ -240,6 +253,7 @@
// fields, etc.
classesOnlyNeededForRti = new Set<ClassEntity>();
for (ClassEntity cls in _rtiNeededClasses) {
+ if (backendTypeHelpers.contains(cls)) continue;
while (cls != null && !neededClasses.contains(cls)) {
if (!classesOnlyNeededForRti.add(cls)) break;
cls = _elementEnvironment.getSuperClass(cls);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index a6eb6fa..3a68f98 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -32,11 +32,7 @@
import '../../js_backend/mirrors_data.dart';
import '../../js_backend/js_interop_analysis.dart';
import '../../js_backend/runtime_types.dart'
- show
- RuntimeTypesChecks,
- RuntimeTypesNeed,
- RuntimeTypesEncoder,
- RuntimeTypesSubstitutions;
+ show RuntimeTypesChecks, RuntimeTypesNeed, RuntimeTypesEncoder;
import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
import '../../options.dart';
import '../../universe/selector.dart' show Selector;
@@ -82,7 +78,6 @@
final SuperMemberData _superMemberData;
final RuntimeTypesChecks _rtiChecks;
final RuntimeTypesEncoder _rtiEncoder;
- final RuntimeTypesSubstitutions _rtiSubstitutions;
final JsInteropAnalysis _jsInteropAnalysis;
final OneShotInterceptorData _oneShotInterceptorData;
final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;
@@ -130,7 +125,6 @@
this._superMemberData,
this._rtiChecks,
this._rtiEncoder,
- this._rtiSubstitutions,
this._jsInteropAnalysis,
this._oneShotInterceptorData,
this._customElementsCodegenAnalysis,
@@ -248,13 +242,9 @@
Set<ClassEntity> interceptorClassesNeededByConstants =
collector.computeInterceptorsReferencedFromConstants();
- Set<ClassEntity> classesModifiedByEmitRTISupport =
- _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport();
_unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses(
- nativeClasses,
- interceptorClassesNeededByConstants,
- classesModifiedByEmitRTISupport);
+ nativeClasses, interceptorClassesNeededByConstants);
_addJsInteropStubs(_registry.mainLibrariesMap);
@@ -688,17 +678,12 @@
RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator(
_elementEnvironment,
_commonElements,
- _types,
- _closedWorld,
_closureDataLookup,
_outputUnitData,
_task,
_namer,
- _nativeData,
_rtiChecks,
_rtiEncoder,
- _rtiNeed,
- _rtiSubstitutions,
_jsInteropAnalysis);
void visitMember(MemberEntity member) {
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index 751aa63..bb68ca8 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -20,21 +20,17 @@
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_backend/js_interop_analysis.dart';
-import '../js_backend/native_data.dart';
import '../js_backend/namer.dart' show Namer;
import '../js_backend/runtime_types.dart'
show
RuntimeTypesChecks,
- RuntimeTypesNeed,
RuntimeTypesEncoder,
- RuntimeTypesSubstitutions,
Substitution,
TypeCheck,
TypeChecks;
import '../js_emitter/sorter.dart';
import '../js_model/closure.dart' show JClosureField;
import '../util/util.dart' show Setlet;
-import '../world.dart';
import 'code_emitter_task.dart' show CodeEmitterTask;
import 'type_test_registry.dart' show TypeTestRegistry;
@@ -43,8 +39,6 @@
typedef void FunctionTypeSignatureEmitter(
FunctionEntity method, FunctionType methodType);
-typedef void SubstitutionEmitter(ClassEntity element, {bool emitNull});
-
class TypeTest {
final jsAst.Name name;
final jsAst.Node expression;
@@ -108,33 +102,23 @@
class RuntimeTypeGenerator {
final ElementEnvironment _elementEnvironment;
final CommonElements _commonElements;
- final DartTypes _types;
- final ClosedWorld _closedWorld;
final ClosureConversionTask _closureDataLookup;
final OutputUnitData _outputUnitData;
final CodeEmitterTask emitterTask;
final Namer _namer;
- final NativeData _nativeData;
final RuntimeTypesChecks _rtiChecks;
final RuntimeTypesEncoder _rtiEncoder;
- final RuntimeTypesNeed _rtiNeed;
- final RuntimeTypesSubstitutions _rtiSubstitutions;
final JsInteropAnalysis _jsInteropAnalysis;
RuntimeTypeGenerator(
this._elementEnvironment,
this._commonElements,
- this._types,
- this._closedWorld,
this._closureDataLookup,
this._outputUnitData,
this.emitterTask,
this._namer,
- this._nativeData,
this._rtiChecks,
this._rtiEncoder,
- this._rtiNeed,
- this._rtiSubstitutions,
this._jsInteropAnalysis);
TypeTestRegistry get _typeTestRegistry => emitterTask.typeTestRegistry;
@@ -165,18 +149,7 @@
assert(!(classElement is ClassElement && !classElement.isDeclaration),
failedAt(classElement));
- /// Generates an is-test if the test is not inherited from a superclass
- /// This assumes that for every class an is-tests is generated
- /// dynamically at runtime. We also always generate tests against
- /// native classes.
- /// TODO(herhut): Generate tests for native classes dynamically, as well.
- void generateIsTest(ClassEntity other) {
- if (_nativeData.isNativeClass(classElement) ||
- !_closedWorld.isSubclassOf(classElement, other)) {
- result.addIsTest(other, _namer.operatorIs(other), js('1'));
- }
- }
-
+ // TODO(johnniwinther): Include function signatures in [ClassChecks].
void generateFunctionTypeSignature(
FunctionEntity method, FunctionType type) {
assert(!(method is MethodElement && !method.isImplementation));
@@ -207,28 +180,12 @@
}
}
- void generateSubstitution(ClassEntity cls, {bool emitNull: false}) {
- if (!_elementEnvironment.isGenericClass(cls)) return;
- jsAst.Expression expression;
- bool needsNativeCheck =
- emitterTask.nativeEmitter.requiresNativeIsCheck(cls);
- Substitution substitution =
- _rtiSubstitutions.getSubstitution(classElement, cls);
- if (substitution != null) {
- expression =
- _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution);
- }
- if (expression == null && (emitNull || needsNativeCheck)) {
- expression = new jsAst.LiteralNull();
- }
- if (expression != null) {
- result.addSubstitution(cls, _namer.substitutionName(cls), expression);
- }
- }
-
void generateTypeCheck(TypeCheck check) {
ClassEntity checkedClass = check.cls;
- generateIsTest(checkedClass);
+ if (check.needsIs) {
+ result.addIsTest(
+ checkedClass, _namer.operatorIs(checkedClass), js('1'));
+ }
Substitution substitution = check.substitution;
if (substitution != null) {
jsAst.Expression body =
@@ -239,12 +196,7 @@
}
_generateIsTestsOn(
- classElement,
- generateIsTest,
- generateFunctionTypeSignature,
- (ClassEntity e, {bool emitNull: false}) =>
- generateSubstitution(e, emitNull: emitNull),
- generateTypeCheck);
+ classElement, generateFunctionTypeSignature, generateTypeCheck);
if (classElement == _commonElements.jsJavaScriptFunctionClass) {
var type = _jsInteropAnalysis.buildJsFunctionType();
@@ -268,21 +220,13 @@
*/
void _generateIsTestsOn(
ClassEntity cls,
- void generateIsTest(ClassEntity element),
FunctionTypeSignatureEmitter generateFunctionTypeSignature,
- SubstitutionEmitter generateSubstitution,
void emitTypeCheck(TypeCheck check)) {
Setlet<ClassEntity> generated = new Setlet<ClassEntity>();
- if (checkedClasses.contains(cls)) {
- generateIsTest(cls);
- generateSubstitution(cls);
- generated.add(cls);
- }
-
// Precomputed is checks.
TypeChecks typeChecks = _rtiChecks.requiredChecks;
- Iterable<TypeCheck> classChecks = typeChecks[cls];
+ Iterable<TypeCheck> classChecks = typeChecks[cls].checks;
if (classChecks != null) {
for (TypeCheck check in classChecks) {
if (!generated.contains(check.cls)) {
@@ -292,59 +236,6 @@
}
}
- ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
-
- bool haveSameTypeVariables(ClassEntity a, ClassEntity b) {
- if (a.isClosure) return true;
- return _rtiSubstitutions.isTrivialSubstitution(a, b);
- }
-
- bool supertypesNeedSubstitutions = false;
-
- if (superclass != null &&
- superclass != _commonElements.objectClass &&
- !haveSameTypeVariables(cls, superclass)) {
- // We cannot inherit the generated substitutions, because the type
- // variable layout for this class is different. Instead we generate
- // substitutions for all checks and make emitSubstitution a NOP for the
- // rest of this function.
-
- // TODO(karlklose): move the computation of these checks to
- // RuntimeTypeInformation.
- while (superclass != null) {
- if (_rtiNeed.classNeedsTypeArguments(superclass)) {
- generateSubstitution(superclass, emitNull: true);
- generated.add(superclass);
- }
- superclass = _elementEnvironment.getSuperClass(superclass);
- }
- supertypesNeedSubstitutions = true;
- }
-
- if (_elementEnvironment.isMixinApplication(cls)) {
- supertypesNeedSubstitutions = true;
- }
-
- if (supertypesNeedSubstitutions) {
- _elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
- ClassEntity superclass = supertype.element;
- if (generated.contains(superclass)) return;
-
- if (classesUsingTypeVariableTests.contains(superclass) ||
- _rtiNeed.classUsesTypeVariableLiteral(superclass) ||
- checkedClasses.contains(superclass)) {
- // Generate substitution. If no substitution is necessary, emit
- // `null` to overwrite a (possibly) existing substitution from the
- // super classes.
- generateSubstitution(superclass, emitNull: true);
- }
- });
-
- void emitNothing(_, {emitNull}) {}
-
- generateSubstitution = emitNothing;
- }
-
// 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(_commonElements.functionClass) ||
@@ -353,57 +244,10 @@
_elementEnvironment.lookupLocalClassMember(cls, Identifiers.call);
if (call != null && call.isFunction) {
FunctionEntity callFunction = call;
- // A superclass might already implement the Function interface. In such
- // a case, we can avoid emitting the is test here.
- ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
- if (!_closedWorld.isSubtypeOf(
- superclass, _commonElements.functionClass)) {
- _generateInterfacesIsTests(_commonElements.functionClass,
- generateIsTest, generateSubstitution, generated);
- }
FunctionType callType =
_elementEnvironment.getFunctionType(callFunction);
generateFunctionTypeSignature(callFunction, callType);
}
}
-
- for (InterfaceType interfaceType in _types.getInterfaces(cls)) {
- _generateInterfacesIsTests(interfaceType.element, generateIsTest,
- generateSubstitution, generated);
- }
- }
-
- /**
- * Generate "is tests" where [cls] is being implemented.
- */
- void _generateInterfacesIsTests(
- ClassEntity cls,
- void generateIsTest(ClassEntity element),
- SubstitutionEmitter generateSubstitution,
- Set<ClassEntity> alreadyGenerated) {
- void tryEmitTest(ClassEntity check) {
- if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) {
- alreadyGenerated.add(check);
- generateIsTest(check);
- generateSubstitution(check);
- }
- }
-
- tryEmitTest(cls);
-
- for (InterfaceType interfaceType in _types.getInterfaces(cls)) {
- ClassEntity element = interfaceType.element;
- tryEmitTest(element);
- _generateInterfacesIsTests(
- element, generateIsTest, generateSubstitution, alreadyGenerated);
- }
-
- // We need to also emit "is checks" for the superclass and its supertypes.
- ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
- if (superclass != null) {
- tryEmitTest(superclass);
- _generateInterfacesIsTests(
- superclass, generateIsTest, generateSubstitution, alreadyGenerated);
- }
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
index 0e31b7c..a740fb0 100644
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
@@ -12,8 +12,7 @@
show
RuntimeTypesChecks,
RuntimeTypesChecksBuilder,
- RuntimeTypesSubstitutions,
- TypeChecks;
+ RuntimeTypesSubstitutions;
import '../js_backend/mirrors_data.dart';
import '../universe/world_builder.dart';
import '../world.dart' show ClosedWorld;
@@ -49,22 +48,6 @@
return _rtiNeededClasses;
}
- /**
- * Returns the classes with constructors used as a 'holder' in
- * [emitRuntimeTypeSupport].
- * TODO(9556): Some cases will go away when the class objects are created as
- * complete. Not all classes will go away while constructors are referenced
- * from type substitutions.
- */
- Set<ClassEntity> computeClassesModifiedByEmitRuntimeTypeSupport() {
- TypeChecks typeChecks = rtiChecks.requiredChecks;
- Set<ClassEntity> result = new Set<ClassEntity>();
- for (ClassEntity cls in typeChecks.classes) {
- if (typeChecks[cls].isNotEmpty) result.add(cls);
- }
- return result;
- }
-
void computeRtiNeededClasses(RuntimeTypesSubstitutions rtiSubstitutions,
MirrorsData mirrorsData, Iterable<MemberEntity> liveMembers) {
_rtiNeededClasses = new Set<ClassEntity>();
@@ -86,19 +69,9 @@
// 1. Add classes that are referenced by type arguments or substitutions in
// argument checks.
- // TODO(karlklose): merge this case with 2 when unifying argument and
- // object checks.
- rtiChecks
- .getRequiredArgumentClasses()
- .forEach((e) => addClassWithSuperclasses(e));
+ addClassesWithSuperclasses(rtiChecks.requiredClasses);
- // 2. Add classes that are referenced by substitutions in object checks and
- // their superclasses.
- Set<ClassEntity> classesUsedInSubstitutions = rtiSubstitutions
- .getClassesUsedInSubstitutions(rtiChecks.requiredChecks);
- addClassesWithSuperclasses(classesUsedInSubstitutions);
-
- // 3. Add classes that contain checked generic function types. These are
+ // 2. Add classes that contain checked generic function types. These are
// needed to store the signature encoding.
for (FunctionType type in rtiChecks.checkedFunctionTypes) {
ClassEntity contextClass = DartTypes.getClassContext(type);
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 30d7a36..ab6b21e 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -260,6 +260,10 @@
_memberClosureRepresentationMap[closureClassInfo.signatureMethod] =
closureClassInfo;
_globalLocalsMap.setLocalsMap(closureClassInfo.callMethod, localsMap);
+ if (_strongMode) {
+ _globalLocalsMap.setLocalsMap(
+ closureClassInfo.signatureMethod, localsMap);
+ }
if (node.parent is ir.Member) {
assert(_elementMap.getMember(node.parent) == member);
_memberClosureRepresentationMap[member] = closureClassInfo;
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 7c42e2c..9d4b34a 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -900,7 +900,7 @@
/// that no corresponding ir.Node actually exists for it. We just use the
/// targetElement.
void buildMethodSignature(ir.FunctionNode originalClosureNode) {
- openFunction(targetElement);
+ openFunction(targetElement, originalClosureNode);
List<HInstruction> typeArguments = <HInstruction>[];
// Add function type variables.
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
new file mode 100755
index 0000000..4bead5f
--- /dev/null
+++ b/pkg/dev_compiler/tool/ddb
@@ -0,0 +1,209 @@
+#!/usr/bin/env dart
+// Copyright (c) 2018, 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.
+
+//
+// Compiles code with DDC and runs the resulting code with either node or
+// chrome.
+//
+// The first script supplied should be the one with `main()`.
+//
+// Saves the output in the same directory as the sources for convenient
+// inspection, modification or rerunning the code.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:args/args.dart' show ArgParser;
+import 'package:path/path.dart' as path;
+
+void main(List<String> args) {
+ // Parse flags.
+ var parser = new ArgParser()
+ ..addFlag('kernel',
+ abbr: 'k', help: 'Compile with the new kernel-based front end.')
+ ..addFlag('debug',
+ abbr: 'd',
+ help: 'Use current source instead of built SDK.',
+ defaultsTo: false)
+ ..addOption('runtime',
+ abbr: 'r',
+ help: 'Platform to run on (node|d8|chrome). Default is node.',
+ allowed: ['node', 'd8', 'chrome'],
+ defaultsTo: 'node')
+ ..addOption('binary', abbr: 'b', help: 'Runtime binary path.');
+
+ var options = parser.parse(args);
+ if (options.rest.length != 1) {
+ throw 'Expected a single dart entrypoint.';
+ }
+ var entry = options.rest.first;
+ var libRoot = path.dirname(entry);
+ var basename = path.basenameWithoutExtension(entry);
+
+ var debug = options['debug'] as bool;
+ var kernel = options['kernel'] as bool;
+ var binary = options['binary'] as String;
+
+ var dartBinary = Platform.resolvedExecutable;
+ var dartPath = path.dirname(dartBinary);
+ var dartSdk = path.dirname(dartPath);
+ var toolPath = Platform.script.normalizePath().toFilePath();
+ var ddcPath = path.dirname(path.dirname(toolPath));
+
+ ProcessResult runDdc(String command, List<String> args) {
+ if (debug) {
+ // Use unbuilt script. This only works from a source checkout.
+ args.insertAll(0, ['-c', path.join(ddcPath, 'bin', '${command}.dart')]);
+ command = dartBinary;
+ } else {
+ // Use built snapshot.
+ command = path.join(dartPath, command);
+ }
+ return Process.runSync(command, args);
+ }
+
+ String mod;
+ bool chrome = false;
+ bool node = false;
+ bool d8 = false;
+ switch (options['runtime']) {
+ case 'node':
+ node = true;
+ mod = 'common';
+ break;
+ case 'd8':
+ d8 = true;
+ mod = 'es6';
+ break;
+ case 'chrome':
+ chrome = true;
+ mod = 'amd';
+ break;
+ }
+ var sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', mod);
+
+ ProcessResult result;
+ if (kernel) {
+ var ddcSdk = path.join(dartSdk, 'lib', '_internal', 'ddc_sdk.dill');
+ result = runDdc('dartdevk', [
+ '--modules=$mod',
+ '--dart-sdk-summary=$ddcSdk',
+ '-o',
+ '$basename.js',
+ entry
+ ]);
+ } else {
+ result = runDdc('dartdevc', [
+ '--modules=$mod',
+ '--library-root=$libRoot',
+ '-o',
+ '$basename.js',
+ entry
+ ]);
+ }
+
+ print(result.stdout);
+ if (result.exitCode != 0) {
+ print(result.stderr);
+ exit(result.exitCode);
+ }
+
+ if (chrome) {
+ String chromeBinary;
+ if (binary != null) {
+ chromeBinary = binary;
+ } else if (Platform.isWindows) {
+ chromeBinary =
+ 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe';
+ } else if (Platform.isMacOS) {
+ chromeBinary =
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
+ } else {
+ // Assume Linux
+ chromeBinary = 'google-chrome';
+ }
+
+ var html = """
+<script src='$sdkJsPath/require.js'></script>
+<script>
+ require.config({
+ baseUrl: '$libRoot',
+ paths: {
+ 'dart_sdk': '$sdkJsPath/dart_sdk'
+ },
+ waitSeconds: 15
+ });
+ require(['dart_sdk', '$basename'],
+ function(sdk, app) {
+ 'use strict';
+ sdk._debugger.registerDevtoolsFormatter();
+ sdk.dart.ignoreWhitelistedErrors(false);
+ sdk._isolate_helper.startRootIsolate(() => {}, []);
+ app.$basename.main();
+ });
+</script>
+""";
+ var htmlFile = '$libRoot/$basename.html';
+ new File(htmlFile).writeAsStringSync(html);
+ var tmp = path.join(Directory.systemTemp.path, 'ddc');
+
+ result = Process.runSync(chromeBinary,
+ ['--auto-open-devtools-for-tabs', '--user-data-dir=$tmp', htmlFile]);
+ } else if (node) {
+ var nodePath = '$sdkJsPath:$libRoot';
+ var runjs = '''
+ let source_maps;
+ try {
+ source_maps = require('source-map-support');
+ source_maps.install();
+ } catch(e) {
+ }
+ let sdk = require(\"dart_sdk\");
+ let main = require(\"./$basename\").$basename.main;
+ sdk.dart.ignoreWhitelistedErrors(false);
+ try {
+ sdk._isolate_helper.startRootIsolate(main, []);
+ } catch(e) {
+ if (!source_maps) {
+ console.log('For Dart source maps: npm install source-map-support');
+ }
+ console.error(e.toString(), sdk.dart.stackTrace(e).toString());
+ process.exit(1);
+ }
+ ''';
+ var nodeFile = '$libRoot/$basename.run.js';
+ new File(nodeFile).writeAsStringSync(runjs);
+ var nodeBinary = binary ?? 'node';
+ result = Process
+ .runSync(nodeBinary, [nodeFile], environment: {'NODE_PATH': nodePath});
+ stdout
+ ..write(result.stdout)
+ ..flush();
+ } else if (d8) {
+ var runjs = '''
+ import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
+ import { $basename } from '$basename.js';
+ let main = $basename.main;
+ dart.ignoreWhitelistedErrors(false);
+ try {
+ _isolate_helper.startRootIsolate(() => {}, []);
+ main();
+ } catch(e) {
+ console.error(e.toString(), dart.stackTrace(e).toString());
+ }
+ ''';
+ var d8File = '$libRoot/$basename.d8.js';
+ new File(d8File).writeAsStringSync(runjs);
+ var d8Binary = binary ?? 'd8';
+ result = Process.runSync(binary, ['--module', d8File]);
+ stdout
+ ..write(result.stdout)
+ ..flush();
+ }
+ if (result.exitCode != 0) {
+ print(result.stderr);
+ exit(result.exitCode);
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 2c46b7b..9f07a92 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -3289,64 +3289,81 @@
Token parseInitializer(Token token) {
Token next = token.next;
listener.beginInitializer(next);
+ Token beforeExpression = token;
if (optional('assert', next)) {
token = parseAssert(token, Assert.Initializer);
+ listener.endInitializer(token.next);
+ return token;
} else if (optional('super', next)) {
- token = parseExpression(token);
+ return parseInitializerExpressionRest(token);
} else if (optional('this', next)) {
- if (!optional('(', next.next)) {
- if (!optional('.', next.next)) {
+ token = next;
+ next = token.next;
+ if (optional('.', next)) {
+ token = next;
+ next = token.next;
+ if (next.isIdentifier) {
+ token = next;
+ } else {
// Recovery
- reportRecoverableError(
- next.next, fasta.templateExpectedButGot.withArguments('.'));
- rewriter.insertTokenAfter(
- next, new SyntheticToken(TokenType.PERIOD, next.next.offset));
+ token = insertSyntheticIdentifier(
+ token, IdentifierContext.fieldInitializer);
}
- next = next.next;
- if (!next.next.isIdentifier) {
- // Recovery
- insertSyntheticIdentifier(next, IdentifierContext.fieldInitializer);
+ next = token.next;
+ if (optional('=', next)) {
+ return parseInitializerExpressionRest(beforeExpression);
}
- next = next.next;
}
- if (optional('(', next.next)) {
- token = parseExpression(token);
+ if (optional('(', next)) {
+ token = parseInitializerExpressionRest(beforeExpression);
next = token.next;
if (optional('{', next) || optional('=>', next)) {
reportRecoverableError(
next, fasta.messageRedirectingConstructorWithBody);
}
- } else {
- if (!optional('=', next.next)) {
- // Recovery
- reportRecoverableError(
- token.next, fasta.messageMissingAssignmentInInitializer);
- next = rewriter
- .insertTokenAfter(
- next, new SyntheticToken(TokenType.EQ, next.next.offset))
- .next;
- rewriter.insertTokenAfter(next,
- new SyntheticStringToken(TokenType.IDENTIFIER, '', next.offset));
- }
- token = parseExpression(token);
+ return token;
}
- } else if (next.isIdentifier) {
- if (!optional('=', next.next)) {
- // Recovery
- next = insertSyntheticIdentifier(
- token, IdentifierContext.fieldInitializer,
- message: fasta.messageMissingAssignmentInInitializer,
- messageOnToken: next);
+ // Recovery
+ if (optional('this', token)) {
+ // TODO(danrubel): Consider a better error message indicating that
+ // `this.<fieldname>=` is expected.
+ reportRecoverableError(
+ next, fasta.templateExpectedButGot.withArguments('.'));
rewriter.insertTokenAfter(
- next, new SyntheticToken(TokenType.EQ, next.offset));
+ token, new SyntheticToken(TokenType.PERIOD, next.offset));
+ token = token.next;
+ rewriter.insertTokenAfter(token,
+ new SyntheticStringToken(TokenType.IDENTIFIER, '', next.offset));
+ token = token.next;
+ next = token.next;
}
- token = parseExpression(token);
+ // Fall through to recovery
+ } else if (next.isIdentifier) {
+ if (optional('=', next.next)) {
+ return parseInitializerExpressionRest(token);
+ }
+ // Fall through to recovery
} else {
// Recovery
insertSyntheticIdentifier(token, IdentifierContext.fieldInitializer,
message: fasta.messageExpectedAnInitializer, messageOnToken: token);
- token = parseExpression(token);
+ return parseInitializerExpressionRest(beforeExpression);
}
+ // Recovery
+ // Insert a sythetic assignment to ensure that the expression is indeed
+ // an assignment. Failing to do so causes this test to fail:
+ // pkg/front_end/testcases/regress/issue_31192.dart
+ // TODO(danrubel): Investigate better recovery.
+ token = insertSyntheticIdentifier(
+ beforeExpression, IdentifierContext.fieldInitializer,
+ message: fasta.messageMissingAssignmentInInitializer);
+ rewriter.insertTokenAfter(
+ token, new SyntheticToken(TokenType.EQ, token.offset));
+ return parseInitializerExpressionRest(beforeExpression);
+ }
+
+ Token parseInitializerExpressionRest(Token token) {
+ token = parseExpression(token);
listener.endInitializer(token.next);
return token;
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.md b/pkg/front_end/lib/src/fasta/parser/parser.md
index bf4999c..acbc13e 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.md
+++ b/pkg/front_end/lib/src/fasta/parser/parser.md
@@ -12,8 +12,6 @@
* In parseSwitchCase, the parser uses peekPastLabels to select between case
labels and statement labels.
- * The parser uses isGeneralizedFunctionType in parseType, and findMemberName.
-
- * The parser uses findMemberName in parseTopLevelMember, and parseMember.
+ * The parser uses isGeneralizedFunctionType in parseType.
* The parser uses isValidMethodTypeArguments in parseSend.
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 375def5..ab381f5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -216,10 +216,17 @@
if (!dottedName.startsWith(prefix)) return "";
dottedName = dottedName.substring(prefix.length);
- LibraryBuilder coreLibrary =
- loader.read(resolve(this.uri, "dart:core", -1), -1);
LibraryBuilder imported =
- coreLibrary.loader.builders[new Uri(scheme: 'dart', path: dottedName)];
+ loader.builders[new Uri(scheme: "dart", path: dottedName)];
+
+ if (imported == null) {
+ LibraryBuilder coreLibrary = loader.read(
+ resolve(
+ this.uri, new Uri(scheme: "dart", path: "core").toString(), -1),
+ -1);
+ imported = coreLibrary
+ .loader.builders[new Uri(scheme: 'dart', path: dottedName)];
+ }
return imported != null ? "true" : "";
}
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index 8f8133e..72a0d20 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -413,16 +413,31 @@
// The statements are in reverse order, so name the result first if
// necessary and then add the two other statements in reverse.
if (shouldName) result = name(result);
- statements.add(R.createContinuationPoint()..fileOffset = expr.fileOffset);
Arguments arguments = new Arguments(<Expression>[
expr.operand,
new VariableGet(R.thenContinuationVariable),
new VariableGet(R.catchErrorContinuationVariable),
new VariableGet(R.nestedClosureVariable),
]);
- statements.add(new ExpressionStatement(
- new StaticInvocation(R.helper.awaitHelper, arguments)
- ..fileOffset = expr.fileOffset));
+
+ // We are building
+ //
+ // [yield] (let _ = _awaitHelper(...) in null)
+ //
+ // to ensure that :await_jump_var and :await_jump_ctx are updated
+ // before _awaitHelper is invoked (see BuildYieldStatement in
+ // StreamingFlowGraphBuilder for details of how [yield] is translated to
+ // IL). This guarantees that recursive invocation of the current function
+ // would continue from the correct "jump" position. Recursive invocations
+ // arise if future we are awaiting completes synchronously. Builtin Future
+ // implementation don't complete synchronously, but Flutter's
+ // SynchronousFuture do (see bug http://dartbug.com/32098 for more details).
+ statements.add(R.createContinuationPoint(new Let(
+ new VariableDeclaration(null,
+ initializer: new StaticInvocation(R.helper.awaitHelper, arguments)
+ ..fileOffset = expr.fileOffset),
+ new NullLiteral()))
+ ..fileOffset = expr.fileOffset);
seenAwait = false;
var index = nameIndex;
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index 9d8e50e..d6ff80f 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -27,6 +27,13 @@
return rewriter.rewriteProgram(program);
}
+Procedure transformProcedure(
+ CoreTypes coreTypes, Procedure procedure, bool syncAsync) {
+ var helper = new HelperNodes.fromCoreTypes(coreTypes);
+ var rewriter = new RecursiveContinuationRewriter(helper, syncAsync);
+ return rewriter.visitProcedure(procedure);
+}
+
class RecursiveContinuationRewriter extends Transformer {
final HelperNodes helper;
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index d0277e0..24936b7 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -150,14 +150,12 @@
exit(exit_code);
}
-bool Platform::SaveConsoleConfiguration() {
+void Platform::SaveConsoleConfiguration() {
UNIMPLEMENTED();
- return false;
}
-bool Platform::RestoreConsoleConfiguration() {
+void Platform::RestoreConsoleConfiguration() {
UNIMPLEMENTED();
- return false;
}
} // namespace bin
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3b57ef0..3a95a1a 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -3019,16 +3019,12 @@
intptr_t type_args_len,
const Array& argument_names,
PushArgumentsArray* arguments,
- TokenPosition token_pos,
- intptr_t argument_check_bits = 0,
- intptr_t type_argument_check_bits = 0)
+ TokenPosition token_pos)
: TemplateDefinition<kInputCount, Throws>(deopt_id),
type_args_len_(type_args_len),
argument_names_(argument_names),
arguments_(arguments),
- token_pos_(token_pos),
- argument_check_bits_(argument_check_bits),
- type_argument_check_bits_(type_argument_check_bits) {
+ token_pos_(token_pos) {
ASSERT(argument_names.IsZoneHandle() || argument_names.InVMHeap());
}
@@ -3047,13 +3043,7 @@
virtual TokenPosition token_pos() const { return token_pos_; }
RawArray* GetArgumentsDescriptor() const {
return ArgumentsDescriptor::New(
- type_args_len(), ArgumentCountWithoutTypeArgs(), argument_names(),
- argument_check_bits(), type_argument_check_bits());
- }
-
- intptr_t argument_check_bits() const { return argument_check_bits_; }
- intptr_t type_argument_check_bits() const {
- return type_argument_check_bits_;
+ type_args_len(), ArgumentCountWithoutTypeArgs(), argument_names());
}
private:
@@ -3062,12 +3052,6 @@
PushArgumentsArray* arguments_;
TokenPosition token_pos_;
- // One bit per argument (up to word size) which helps the callee decide which
- // arguments it needs to check. See the comments in ArgumentsDescriptor for
- // more information on strong-mode checked calls.
- intptr_t argument_check_bits_;
- intptr_t type_argument_check_bits_;
-
DISALLOW_COPY_AND_ASSIGN(TemplateDartCall);
};
@@ -3128,16 +3112,12 @@
intptr_t checked_argument_count,
const ZoneGrowableArray<const ICData*>& ic_data_array,
intptr_t deopt_id,
- const Function& interface_target = Function::null_function(),
- intptr_t argument_check_bits = 0,
- intptr_t type_argument_check_bits = 0)
+ const Function& interface_target = Function::null_function())
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
arguments,
- token_pos,
- argument_check_bits,
- type_argument_check_bits),
+ token_pos),
ic_data_(NULL),
function_name_(function_name),
token_kind_(token_kind),
@@ -3168,16 +3148,12 @@
const Array& argument_names,
intptr_t checked_argument_count,
intptr_t deopt_id,
- const Function& interface_target = Function::null_function(),
- intptr_t argument_check_bits = 0,
- intptr_t type_argument_check_bits = 0)
+ const Function& interface_target = Function::null_function())
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
arguments,
- token_pos,
- argument_check_bits,
- type_argument_check_bits),
+ token_pos),
ic_data_(NULL),
function_name_(function_name),
token_kind_(token_kind),
@@ -3638,16 +3614,12 @@
PushArgumentsArray* arguments,
const ZoneGrowableArray<const ICData*>& ic_data_array,
intptr_t deopt_id,
- ICData::RebindRule rebind_rule,
- intptr_t argument_check_bits = 0,
- intptr_t type_argument_check_bits = 0)
+ ICData::RebindRule rebind_rule)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
arguments,
- token_pos,
- argument_check_bits,
- type_argument_check_bits),
+ token_pos),
ic_data_(NULL),
call_count_(0),
function_(function),
@@ -3667,14 +3639,12 @@
PushArgumentsArray* arguments,
intptr_t deopt_id,
intptr_t call_count,
- ICData::RebindRule rebind_rule,
- intptr_t argument_check_bits = 0)
+ ICData::RebindRule rebind_rule)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
arguments,
- token_pos,
- argument_check_bits),
+ token_pos),
ic_data_(NULL),
call_count_(call_count),
function_(function),
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index ec29c10e..dd4a560 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1766,7 +1766,7 @@
case kYieldStatement: {
builder_->ReadPosition(); // read position.
word flags = builder_->ReadByte(); // read flags.
- builder_->SkipExpression(); // read expression.
+ VisitExpression(); // read expression.
ASSERT(flags == kNativeYieldFlags);
if (depth_.function_ == 0) {
@@ -5827,13 +5827,10 @@
const Array& argument_names,
ICData::RebindRule rebind_rule,
const InferredTypeMetadata* result_type,
- intptr_t type_args_count,
- intptr_t argument_check_bits,
- intptr_t type_argument_check_bits) {
+ intptr_t type_args_count) {
return flow_graph_builder_->StaticCall(
position, target, argument_count, argument_names, rebind_rule,
- result_type, type_args_count, argument_check_bits,
- type_argument_check_bits);
+ result_type, type_args_count);
}
Fragment StreamingFlowGraphBuilder::InstanceCall(
@@ -5857,13 +5854,10 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
- const InferredTypeMetadata* result_type,
- intptr_t argument_check_bits,
- intptr_t type_argument_check_bits) {
+ const InferredTypeMetadata* result_type) {
return flow_graph_builder_->InstanceCall(
position, name, kind, type_args_len, argument_count, argument_names,
- checked_argument_count, interface_target, result_type,
- argument_check_bits, type_argument_check_bits);
+ checked_argument_count, interface_target, result_type);
}
Fragment StreamingFlowGraphBuilder::ThrowException(TokenPosition position) {
@@ -6291,7 +6285,7 @@
const TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
- uint8_t flags = ReadFlags(); // read flags
+ ReadFlags(); // skip flags
instructions += BuildExpression(); // read receiver.
@@ -6319,12 +6313,6 @@
ASSERT(setter_name.raw() == interface_target->name());
}
- intptr_t argument_check_bits = 0;
- if (I->strong()) {
- argument_check_bits = ArgumentCheckBitsForSetter(
- *interface_target, static_cast<DispatchCategory>(flags & 3));
- }
-
if (direct_call.check_receiver_for_null_) {
instructions += CheckNull(position, receiver);
}
@@ -6333,15 +6321,14 @@
ASSERT(FLAG_precompiled_mode);
instructions +=
StaticCall(position, direct_call.target_, 2, Array::null_array(),
- ICData::kNoRebind, /* result_type = */ NULL,
- /*type_args_len=*/0, argument_check_bits);
+ ICData::kNoRebind, /* result_type = */ NULL);
} else {
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgsChecked = 1;
instructions +=
InstanceCall(position, setter_name, Token::kSET, kTypeArgsLen, 2,
Array::null_array(), kNumArgsChecked, *interface_target,
- /* result_type = */ NULL, argument_check_bits);
+ /* result_type = */ NULL);
}
instructions += Drop(); // Drop result of the setter invocation.
@@ -6624,7 +6611,7 @@
const TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
- uint8_t flags = ReadFlags(); // read flags.
+ ReadFlags(); // skip flags.
Fragment instructions(NullConstant());
LocalVariable* value = MakeTemporary();
@@ -6643,9 +6630,6 @@
instructions += StoreLocal(TokenPosition::kNoSource, value);
instructions += PushArgument();
- intptr_t argument_check_bits = ArgumentCheckBitsForSetter(
- target, static_cast<DispatchCategory>(flags & 3));
-
// Static calls are marked as "no-rebind", which is currently safe because
// DirectPropertyGet are only used in enums (index in toString) and enums
// can't change their structure during hot reload.
@@ -6653,9 +6637,7 @@
// have to be adjusted.
instructions +=
StaticCall(position, target, 2, Array::null_array(), ICData::kNoRebind,
- /* result_type = */ NULL,
- /*type_args_len=*/0, argument_check_bits,
- /*type_argument_check_bits=*/0);
+ /* result_type = */ NULL);
return instructions + Drop();
}
@@ -6752,177 +6734,6 @@
tag == kSpecialIntLiteral || tag == kDoubleLiteral;
}
-intptr_t StreamingFlowGraphBuilder::ArgumentCheckBitsForSetter(
- const Function& interface_target,
- DispatchCategory category) {
- intptr_t argument_check_bits = 0;
-
- switch (category) {
- case DynamicDispatch:
- argument_check_bits = 2; // 1 for value, 0 for receiver
- break;
- case Closure:
- // A property set cannot be a closure call.
- UNREACHABLE();
- case ViaThis:
- // All bits are 0.
- break;
- case Interface: {
- // TODO(sjindel): Revise checking interface target for null.
- if (interface_target.IsNull() ||
- !interface_target.IsImplicitGetterOrSetter()) {
- intptr_t type_argument_check_bits_unused;
- ArgumentCheckBitsForInvocation(
- 1, 0, 1, Array::null_array(), interface_target, category,
- &argument_check_bits, &type_argument_check_bits_unused);
- break;
- }
-
- const Field& target_field =
- Field::Handle(interface_target.LookupImplicitGetterSetterField());
- ASSERT(!target_field.IsNull());
- TypedData& kernel_data = TypedData::Handle(Z, target_field.KernelData());
- ASSERT(!kernel_data.IsNull());
- AlternativeReadingScope r(reader_, &kernel_data,
- target_field.kernel_offset());
- AlternativeScriptScope s(&translation_helper_,
- Script::Handle(target_field.Script()), script());
-
- FieldHelper helper(this);
- helper.ReadUntilIncluding(FieldHelper::kFlags);
-
- argument_check_bits = 1; // indicate dispatch category
- if (helper.IsGenericCovariantInterface()) {
- argument_check_bits |= 1 << 1;
- }
- }
- }
-
- return argument_check_bits;
-}
-
-void StreamingFlowGraphBuilder::ArgumentCheckBitsForInvocation(
- intptr_t argument_count, // excluding receiver
- intptr_t type_argument_count,
- intptr_t positional_argument_count,
- const Array& argument_names,
- const Function& interface_target,
- DispatchCategory category,
- intptr_t* argument_bits /*out*/,
- intptr_t* type_argument_bits /*out*/) {
- intptr_t argument_check_bits = 0;
- intptr_t type_argument_check_bits = 0;
-
- // If there are more than 'kBitsPerWord - 1' arguments, the rest will be
- // assumed to be marked as 1 (the '-1' is because of the receiver).
- int strong_checked_arguments =
- Utils::Minimum<intptr_t>(argument_count, kBitsPerWord - 1);
- int strong_checked_type_arguments =
- Utils::Minimum<intptr_t>(type_argument_count, kBitsPerWord);
-
- switch (category) {
- case DynamicDispatch:
- // All bits are 1 except the receiver which is 0.
- argument_check_bits = Utils::SignedNBitMask(strong_checked_arguments)
- << 1;
- type_argument_check_bits =
- Utils::SignedNBitMask(strong_checked_type_arguments);
- case ViaThis:
- // All bits are 0.
- break;
- case Closure:
- // All bits at 1.
- argument_check_bits = Utils::SignedNBitMask(strong_checked_arguments + 1);
- type_argument_check_bits =
- Utils::SignedNBitMask(strong_checked_type_arguments);
- break;
- case Interface: {
- ASSERT(!interface_target.IsNull() || !I->strong());
- if (interface_target.IsNull()) {
- argument_check_bits =
- Utils::SignedNBitMask(strong_checked_arguments + 1);
- type_argument_check_bits =
- Utils::SignedNBitMask(strong_checked_type_arguments);
- break;
- }
- argument_check_bits = 1;
- TypedData& kernel_data =
- TypedData::Handle(Z, interface_target.KernelData());
- ASSERT(!kernel_data.IsNull());
- AlternativeReadingScope _r(reader_, &kernel_data,
- interface_target.kernel_offset());
- AlternativeScriptScope _s(&translation_helper_,
- Script::Handle(interface_target.script()),
- script());
- ReadUntilFunctionNode();
-
- FunctionNodeHelper fn_helper(this);
- fn_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
- intptr_t num_interface_type_params = ReadListLength();
- // Maybe this can be ==?
- ASSERT(num_interface_type_params >= type_argument_count);
-
- for (intptr_t i = 0; i < num_interface_type_params; ++i) {
- uint8_t flags = ReadFlags();
- SkipListOfExpressions();
- SkipStringReference();
- SkipDartType();
- if (i >= strong_checked_type_arguments) continue;
- if (flags & TypeParameterHelper::kIsGenericCovariantInterface) {
- type_argument_check_bits |= Utils::Bit(i);
- }
- }
-
- fn_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
- fn_helper.ReadUntilExcluding(FunctionNodeHelper::kPositionalParameters);
- intptr_t num_interface_pos_params = ReadListLength();
- ASSERT(num_interface_pos_params >= positional_argument_count);
-
- intptr_t arg = 0;
- for (; arg < num_interface_pos_params; ++arg) {
- VariableDeclarationHelper var_helper(this);
- var_helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
- if (arg >= strong_checked_arguments) continue;
- if (var_helper.IsGenericCovariantInterface()) {
- argument_check_bits |= Utils::Bit(arg + 1); // +1 for the receiver
- }
- }
-
- fn_helper.SetJustRead(FunctionNodeHelper::kPositionalParameters);
- if (argument_names.IsNull()) break;
-
- fn_helper.ReadUntilExcluding(FunctionNodeHelper::kNamedParameters);
- intptr_t num_interface_named_params = ReadListLength();
- for (intptr_t i = 0;
- i < argument_names.Length() && arg <= strong_checked_arguments;
- ++i, ++arg) {
- const String& arg_name =
- String::Handle(Z, String::RawCast(argument_names.At(i)));
-
- // Scan through the named parameters of the interface target to find
- // the right one.
- AlternativeReadingScope _(reader_);
- for (intptr_t j = 0; j < num_interface_named_params; ++j) {
- VariableDeclarationHelper var_helper(this);
- var_helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
- const String& param_name = H.DartSymbol(var_helper.name_index_);
- if (!param_name.Equals(arg_name)) continue;
- if (var_helper.IsGenericCovariantInterface()) {
- argument_check_bits |= Utils::NBitMask(arg + 1);
- }
- break;
- }
- }
- break;
- }
- default:
- UNREACHABLE();
- }
-
- *argument_bits = argument_check_bits;
- *type_argument_bits = type_argument_check_bits;
-}
-
Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
const intptr_t offset = ReaderOffset() - 1; // Include the tag.
const TokenPosition position = ReadPosition(); // read position.
@@ -6933,7 +6744,7 @@
const InferredTypeMetadata result_type =
inferred_type_metadata_helper_.GetInferredType(offset);
- uint8_t flags = ReadFlags(); // read flags.
+ ReadFlags(); // skip flags.
const Tag receiver_tag = PeekTag(); // peek tag for receiver.
if (IsNumberLiteral(receiver_tag) &&
@@ -7068,27 +6879,15 @@
instructions += CheckNull(position, receiver_temp);
}
- intptr_t argument_check_bits = 0;
- intptr_t type_argument_check_bits = 0;
- if (I->strong()) {
- ArgumentCheckBitsForInvocation(
- argument_count - 1, type_args_len, positional_argument_count,
- argument_names, *interface_target,
- static_cast<DispatchCategory>(flags & 3), &argument_check_bits,
- &type_argument_check_bits);
- }
-
if (!direct_call.target_.IsNull()) {
ASSERT(FLAG_precompiled_mode);
instructions += StaticCall(position, direct_call.target_, argument_count,
argument_names, ICData::kNoRebind, &result_type,
- type_args_len, argument_check_bits,
- type_argument_check_bits);
+ type_args_len);
} else {
instructions += InstanceCall(
position, name, token_kind, type_args_len, argument_count,
- argument_names, checked_argument_count, *interface_target, &result_type,
- argument_check_bits, type_argument_check_bits);
+ argument_names, checked_argument_count, *interface_target, &result_type);
}
// Drop temporaries preserving result on the top of the stack.
@@ -7120,7 +6919,7 @@
const InferredTypeMetadata result_type =
inferred_type_metadata_helper_.GetInferredType(offset);
- uint8_t flags = ReadFlags(); // read flags.
+ ReadFlags(); // skip flags.
Tag receiver_tag = PeekTag(); // peek tag for receiver.
@@ -7177,16 +6976,9 @@
&positional_argument_count); // read arguments.
++argument_count;
- intptr_t argument_check_bits, type_argument_check_bits;
- ArgumentCheckBitsForInvocation(
- argument_count, type_args_len, positional_argument_count, argument_names,
- target, static_cast<DispatchCategory>(flags & 3), &argument_check_bits,
- &type_argument_check_bits);
-
return instructions +
StaticCall(position, target, argument_count, argument_names,
- ICData::kNoRebind, &result_type, type_args_len,
- argument_check_bits, type_argument_check_bits);
+ ICData::kNoRebind, &result_type, type_args_len);
}
Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index b99111b..34df86f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -1148,9 +1148,7 @@
const Array& argument_names,
ICData::RebindRule rebind_rule,
const InferredTypeMetadata* result_type = NULL,
- intptr_t type_args_len = 0,
- intptr_t argument_check_bits = 0,
- intptr_t type_argument_check_bits = 0);
+ intptr_t type_args_len = 0);
Fragment InstanceCall(TokenPosition position,
const String& name,
Token::Kind kind,
@@ -1164,9 +1162,7 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
- const InferredTypeMetadata* result_type = NULL,
- intptr_t argument_check_bits = 0,
- intptr_t type_argument_check_bits = 0);
+ const InferredTypeMetadata* result_type = NULL);
enum TypeChecksToBuild {
kDefaultTypeChecks,
@@ -1332,19 +1328,6 @@
bool is_closure,
FunctionNodeHelper* function_node_helper);
- intptr_t ArgumentCheckBitsForSetter(const Function& interface_target,
- DispatchCategory category);
-
- void ArgumentCheckBitsForInvocation(
- intptr_t argument_count, // excluding receiver
- intptr_t type_argument_count,
- intptr_t positional_argument_count,
- const Array& argument_names,
- const Function& interface_target,
- DispatchCategory category,
- intptr_t* argument_bits,
- intptr_t* type_argument_bits);
-
const Script& script() { return script_; }
// Scan through metadata mappings section and cache offsets for recognized
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index f004628..ede8726 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1235,15 +1235,13 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
- const InferredTypeMetadata* result_type,
- intptr_t argument_bits,
- intptr_t type_argument_bits) {
+ const InferredTypeMetadata* result_type) {
const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0);
ArgumentArray arguments = GetArguments(total_count);
InstanceCallInstr* call = new (Z) InstanceCallInstr(
position, name, kind, arguments, type_args_len, argument_names,
checked_argument_count, ic_data_array_, GetNextDeoptId(),
- interface_target, argument_bits, type_argument_bits);
+ interface_target);
if (result_type != NULL) {
call->SetResultType(Z, CompileType::CreateNullable(result_type->nullable,
result_type->cid));
@@ -1512,15 +1510,12 @@
const Array& argument_names,
ICData::RebindRule rebind_rule,
const InferredTypeMetadata* result_type,
- intptr_t type_args_count,
- intptr_t argument_bits,
- intptr_t type_argument_check_bits) {
+ intptr_t type_args_count) {
const intptr_t total_count = argument_count + (type_args_count > 0 ? 1 : 0);
ArgumentArray arguments = GetArguments(total_count);
StaticCallInstr* call = new (Z)
StaticCallInstr(position, target, type_args_count, argument_names,
- arguments, ic_data_array_, GetNextDeoptId(), rebind_rule,
- argument_bits, type_argument_check_bits);
+ arguments, ic_data_array_, GetNextDeoptId(), rebind_rule);
const intptr_t list_cid =
GetResultCidOfListFactory(Z, target, argument_count);
if (list_cid != kDynamicCid) {
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 6d9948d..13df421 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -700,9 +700,7 @@
const Array& argument_names,
intptr_t checked_argument_count,
const Function& interface_target,
- const InferredTypeMetadata* result_type = NULL,
- intptr_t argument_bits = 0,
- intptr_t type_argument_bits = 0);
+ const InferredTypeMetadata* result_type = NULL);
Fragment ClosureCall(intptr_t type_args_len,
intptr_t argument_count,
const Array& argument_names);
@@ -731,9 +729,7 @@
const Array& argument_names,
ICData::RebindRule rebind_rule,
const InferredTypeMetadata* result_type = NULL,
- intptr_t type_args_len = 0,
- intptr_t argument_bits = 0,
- intptr_t type_argument_check_bits = 0);
+ intptr_t type_args_len = 0);
Fragment StoreIndexed(intptr_t class_id);
Fragment StoreInstanceFieldGuarded(const Field& field,
bool is_initialization_store);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 21580bd..840ca2f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -22574,15 +22574,45 @@
}
}
}
+
+ // Workaround for http://dartbug.com/32087: currently Kernel front-end
+ // embeds absolute build-time paths to core library sources into Kernel
+ // binaries this introduces discrepancy between how stack traces were
+ // looked like in legacy pipeline and how they look in Dart 2 pipeline and
+ // breaks users' code that attempts to pattern match and filter various
+ // irrelevant frames (e.g. frames from dart:async).
+ // To work around this issue we reformat urls of scripts belonging to
+ // dart:-scheme libraries to look like they looked like in legacy pipeline:
+ //
+ // dart:libname/filename.dart
+ //
+ const char* url_string = url.ToCString();
+ if (script.kernel_program_info() != KernelProgramInfo::null()) {
+ const Class& owner = Class::Handle(function.Owner());
+ const Library& lib = Library::Handle(owner.library());
+ if (lib.is_dart_scheme()) {
+ // Search backwards until '/' is found. That gives us the filename.
+ intptr_t pos = strlen(url_string) - 1;
+ while (pos >= 0 && url_string[pos] != '/') {
+ pos--;
+ }
+ const char* filename = url_string + (pos + 1);
+
+ // Glue together canonic library url (e.g. dart:async) and filename.
+ url_string = zone->PrintToString(
+ "%s/%s", String::Handle(lib.url()).ToCString(), filename);
+ }
+ }
+
if (column >= 0) {
buffer->Printf("#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index,
- function_name.ToCString(), url.ToCString(), line, column);
+ function_name.ToCString(), url_string, line, column);
} else if (line >= 0) {
buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index,
- function_name.ToCString(), url.ToCString(), line);
+ function_name.ToCString(), url_string, line);
} else {
buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index,
- function_name.ToCString(), url.ToCString());
+ function_name.ToCString(), url_string);
}
}
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index c15a3f0..9c20289 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -10,6 +10,10 @@
/// import 'dart:typed_data';
library dart.typed_data;
+import "dart:_internal" show UnmodifiableListBase;
+
+part "unmodifiable_typed_data.dart";
+
/**
* A sequence of bytes underlying a typed data object.
*
diff --git a/sdk/lib/typed_data/typed_data_sources.gni b/sdk/lib/typed_data/typed_data_sources.gni
index daa50aa..23ba0f0 100644
--- a/sdk/lib/typed_data/typed_data_sources.gni
+++ b/sdk/lib/typed_data/typed_data_sources.gni
@@ -5,4 +5,5 @@
typed_data_sdk_sources = [
"typed_data.dart",
# The above file needs to be first if additional parts are added to the lib.
+ "unmodifiable_typed_data.dart",
]
diff --git a/sdk/lib/typed_data/unmodifiable_typed_data.dart b/sdk/lib/typed_data/unmodifiable_typed_data.dart
new file mode 100644
index 0000000..4cc5af7
--- /dev/null
+++ b/sdk/lib/typed_data/unmodifiable_typed_data.dart
@@ -0,0 +1,303 @@
+// Copyright (c) 2018, 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 dart.typed_data;
+
+/**
+ * A read-only view of a [ByteBuffer].
+ */
+class UnmodifiableByteBufferView implements ByteBuffer {
+ final ByteBuffer _data;
+
+ UnmodifiableByteBufferView(ByteBuffer data) : _data = data;
+
+ int get lengthInBytes => _data.lengthInBytes;
+
+ Uint8List asUint8List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableUint8ListView(_data.asUint8List(offsetInBytes, length));
+
+ Int8List asInt8List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableInt8ListView(_data.asInt8List(offsetInBytes, length));
+
+ Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableUint8ClampedListView(
+ _data.asUint8ClampedList(offsetInBytes, length));
+
+ Uint16List asUint16List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableUint16ListView(_data.asUint16List(offsetInBytes, length));
+
+ Int16List asInt16List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableInt16ListView(_data.asInt16List(offsetInBytes, length));
+
+ Uint32List asUint32List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableUint32ListView(_data.asUint32List(offsetInBytes, length));
+
+ Int32List asInt32List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableInt32ListView(_data.asInt32List(offsetInBytes, length));
+
+ Uint64List asUint64List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableUint64ListView(_data.asUint64List(offsetInBytes, length));
+
+ Int64List asInt64List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableInt64ListView(_data.asInt64List(offsetInBytes, length));
+
+ Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableInt32x4ListView(
+ _data.asInt32x4List(offsetInBytes, length));
+
+ Float32List asFloat32List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableFloat32ListView(
+ _data.asFloat32List(offsetInBytes, length));
+
+ Float64List asFloat64List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableFloat64ListView(
+ _data.asFloat64List(offsetInBytes, length));
+
+ Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableFloat32x4ListView(
+ _data.asFloat32x4List(offsetInBytes, length));
+
+ Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableFloat64x2ListView(
+ _data.asFloat64x2List(offsetInBytes, length));
+
+ ByteData asByteData([int offsetInBytes = 0, int length]) =>
+ new UnmodifiableByteDataView(_data.asByteData(offsetInBytes, length));
+}
+
+/**
+ * A read-only view of a [ByteData].
+ */
+class UnmodifiableByteDataView implements ByteData {
+ final ByteData _data;
+
+ UnmodifiableByteDataView(ByteData data) : _data = data;
+
+ int getInt8(int byteOffset) => _data.getInt8(byteOffset);
+
+ void setInt8(int byteOffset, int value) => _unsupported();
+
+ int getUint8(int byteOffset) => _data.getUint8(byteOffset);
+
+ void setUint8(int byteOffset, int value) => _unsupported();
+
+ int getInt16(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getInt16(byteOffset, endian);
+
+ void setInt16(int byteOffset, int value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ int getUint16(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getUint16(byteOffset, endian);
+
+ void setUint16(int byteOffset, int value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ int getInt32(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getInt32(byteOffset, endian);
+
+ void setInt32(int byteOffset, int value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ int getUint32(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getUint32(byteOffset, endian);
+
+ void setUint32(int byteOffset, int value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ int getInt64(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getInt64(byteOffset, endian);
+
+ void setInt64(int byteOffset, int value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ int getUint64(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getUint64(byteOffset, endian);
+
+ void setUint64(int byteOffset, int value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ double getFloat32(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getFloat32(byteOffset, endian);
+
+ void setFloat32(int byteOffset, double value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ double getFloat64(int byteOffset, [Endian endian = Endian.big]) =>
+ _data.getFloat64(byteOffset, endian);
+
+ void setFloat64(int byteOffset, double value, [Endian endian = Endian.big]) =>
+ _unsupported();
+
+ int get elementSizeInBytes => _data.elementSizeInBytes;
+
+ int get offsetInBytes => _data.offsetInBytes;
+
+ int get lengthInBytes => _data.lengthInBytes;
+
+ ByteBuffer get buffer => new UnmodifiableByteBufferView(_data.buffer);
+
+ void _unsupported() {
+ throw new UnsupportedError(
+ "An UnmodifiableByteDataView may not be modified");
+ }
+}
+
+abstract class _UnmodifiableListMixin<N, L extends List<N>,
+ TD extends TypedData> {
+ L get _list;
+ TD get _data => (_list as TD);
+
+ int get length => _list.length;
+
+ N operator [](int index) => _list[index];
+
+ int get elementSizeInBytes => _data.elementSizeInBytes;
+
+ int get offsetInBytes => _data.offsetInBytes;
+
+ int get lengthInBytes => _data.lengthInBytes;
+
+ ByteBuffer get buffer => new UnmodifiableByteBufferView(_data.buffer);
+}
+
+/**
+ * View of a [Uint8List] that disallows modification.
+ */
+class UnmodifiableUint8ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Uint8List, Uint8List>
+ implements Uint8List {
+ final Uint8List _list;
+ UnmodifiableUint8ListView(Uint8List list) : _list = list;
+}
+
+/**
+ * View of a [Int8List] that disallows modification.
+ */
+class UnmodifiableInt8ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Int8List, Int8List>
+ implements Int8List {
+ final Int8List _list;
+ UnmodifiableInt8ListView(Int8List list) : _list = list;
+}
+
+/**
+ * View of a [Uint8ClampedList] that disallows modification.
+ */
+class UnmodifiableUint8ClampedListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Uint8ClampedList, Uint8ClampedList>
+ implements Uint8ClampedList {
+ final Uint8ClampedList _list;
+ UnmodifiableUint8ClampedListView(Uint8ClampedList list) : _list = list;
+}
+
+/**
+ * View of a [Uint16List] that disallows modification.
+ */
+class UnmodifiableUint16ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Uint16List, Uint16List>
+ implements Uint16List {
+ final Uint16List _list;
+ UnmodifiableUint16ListView(Uint16List list) : _list = list;
+}
+
+/**
+ * View of a [Int16List] that disallows modification.
+ */
+class UnmodifiableInt16ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Int16List, Int16List>
+ implements Int16List {
+ final Int16List _list;
+ UnmodifiableInt16ListView(Int16List list) : _list = list;
+}
+
+/**
+ * View of a [Uint32List] that disallows modification.
+ */
+class UnmodifiableUint32ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Uint32List, Uint32List>
+ implements Uint32List {
+ final Uint32List _list;
+ UnmodifiableUint32ListView(Uint32List list) : _list = list;
+}
+
+/**
+ * View of a [Int32List] that disallows modification.
+ */
+class UnmodifiableInt32ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Int32List, Int32List>
+ implements Int32List {
+ final Int32List _list;
+ UnmodifiableInt32ListView(Int32List list) : _list = list;
+}
+
+/**
+ * View of a [Uint64List] that disallows modification.
+ */
+class UnmodifiableUint64ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Uint64List, Uint64List>
+ implements Uint64List {
+ final Uint64List _list;
+ UnmodifiableUint64ListView(Uint64List list) : _list = list;
+}
+
+/**
+ * View of a [Int64List] that disallows modification.
+ */
+class UnmodifiableInt64ListView extends UnmodifiableListBase<int>
+ with _UnmodifiableListMixin<int, Int64List, Int64List>
+ implements Int64List {
+ final Int64List _list;
+ UnmodifiableInt64ListView(Int64List list) : _list = list;
+}
+
+/**
+ * View of a [Int32x4List] that disallows modification.
+ */
+class UnmodifiableInt32x4ListView extends UnmodifiableListBase<Int32x4>
+ with _UnmodifiableListMixin<Int32x4, Int32x4List, Int32x4List>
+ implements Int32x4List {
+ final Int32x4List _list;
+ UnmodifiableInt32x4ListView(Int32x4List list) : _list = list;
+}
+
+/**
+ * View of a [Float32x4List] that disallows modification.
+ */
+class UnmodifiableFloat32x4ListView extends UnmodifiableListBase<Float32x4>
+ with _UnmodifiableListMixin<Float32x4, Float32x4List, Float32x4List>
+ implements Float32x4List {
+ final Float32x4List _list;
+ UnmodifiableFloat32x4ListView(Float32x4List list) : _list = list;
+}
+
+/**
+ * View of a [Float64x2List] that disallows modification.
+ */
+class UnmodifiableFloat64x2ListView extends UnmodifiableListBase<Float64x2>
+ with _UnmodifiableListMixin<Float64x2, Float64x2List, Float64x2List>
+ implements Float64x2List {
+ final Float64x2List _list;
+ UnmodifiableFloat64x2ListView(Float64x2List list) : _list = list;
+}
+
+/**
+ * View of a [Float32List] that disallows modification.
+ */
+class UnmodifiableFloat32ListView extends UnmodifiableListBase<double>
+ with _UnmodifiableListMixin<double, Float32List, Float32List>
+ implements Float32List {
+ final Float32List _list;
+ UnmodifiableFloat32ListView(Float32List list) : _list = list;
+}
+
+/**
+ * View of a [Float64List] that disallows modification.
+ */
+class UnmodifiableFloat64ListView extends UnmodifiableListBase<double>
+ with _UnmodifiableListMixin<double, Float64List, Float64List>
+ implements Float64List {
+ final Float64List _list;
+ UnmodifiableFloat64ListView(Float64List list) : _list = list;
+}
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 0e0083a..c7649a6 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -37,7 +37,8 @@
old_frontend/resolver_test: RuntimeError # Test must be updated given new parser recovery
packages/*: Skip # Skip packages folder
quarantined/http_test: Pass, Slow
-rti/rti_need_test: Pass, Slow, Fail # Issue 32055
+rti/rti_emission_test: Pass, Slow
+rti/rti_need_test: Pass, Slow
serialization/analysis1_test: Skip # Skip most serialization tests. These are very slow and are no longer a priority.
serialization/analysis3_test: Skip # Skip most serialization tests. These are very slow and are no longer a priority.
serialization/analysis4_test: Skip # Skip most serialization tests. These are very slow and are no longer a priority.
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index b51545e..23dfb6f 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -855,10 +855,17 @@
/// Set of features used in annotations.
class Features {
- Map<String, String> _features = <String, String>{};
+ Map<String, Object> _features = <String, Object>{};
void add(String key, {var value: ''}) {
- _features[key] = value;
+ _features[key] = value.toString();
+ }
+
+ void addElement(String key, [var value]) {
+ List<String> list = _features.putIfAbsent(key, () => <String>[]);
+ if (value != null) {
+ list.add(value.toString());
+ }
}
bool containsKey(String key) {
@@ -879,12 +886,15 @@
StringBuffer sb = new StringBuffer();
bool needsComma = false;
for (String name in _features.keys.toList()..sort()) {
- String value = _features[name];
+ dynamic value = _features[name];
if (value != null) {
if (needsComma) {
sb.write(',');
}
sb.write(name);
+ if (value is List<String>) {
+ value = '[${(value..sort()).join(',')}]';
+ }
if (value != '') {
sb.write('=');
sb.write(value);
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index c3ef07a..5b1b8b1 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -36,7 +36,7 @@
}
Class getClass(ClassEntity element) {
- return getClassData(element).cls;
+ return getClassData(element)?.cls;
}
Method getMethod(FunctionEntity function) {
diff --git a/tests/compiler/dart2js/old_frontend/analyze_test_test.dart b/tests/compiler/dart2js/old_frontend/analyze_test_test.dart
index 3cf3f42..495ce73 100644
--- a/tests/compiler/dart2js/old_frontend/analyze_test_test.dart
+++ b/tests/compiler/dart2js/old_frontend/analyze_test_test.dart
@@ -28,6 +28,7 @@
const List<String> SKIP_LIST = const <String>[
// Helper files:
"/data/",
+ "/emission/",
"/side_effects/",
"quarantined/http_launch_data/",
"mirrors_helper.dart",
diff --git a/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
index f0e1c8d..2de14d2 100644
--- a/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
+++ b/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
@@ -58,6 +58,10 @@
"pkg/kernel/lib/transformations/closure/": const [
"Duplicated library name 'kernel.transformations.closure.converter'",
],
+
+ "pkg/compiler/lib/src/js_backend/runtime_types.dart": const [
+ "'void' is not a subtype of bound 'Object' for type variable",
+ ],
};
void main() {
diff --git a/tests/compiler/dart2js/old_frontend/size_test.dart b/tests/compiler/dart2js/old_frontend/size_test.dart
index af9817a..95a1946 100644
--- a/tests/compiler/dart2js/old_frontend/size_test.dart
+++ b/tests/compiler/dart2js/old_frontend/size_test.dart
@@ -30,7 +30,7 @@
compileAll(TEST, coreSource: DEFAULT_CORELIB_WITH_LIST).then((generated) {
return MockCompiler.create((MockCompiler compiler) {
// Make sure no class is emitted.
- Expect.isFalse(generated.contains('finishClasses'));
+ Expect.isFalse(generated.contains('finishClasses'), generated);
});
}));
}
diff --git a/tests/compiler/dart2js/rti/backend_type_helper_test.dart b/tests/compiler/dart2js/rti/backend_type_helper_test.dart
new file mode 100644
index 0000000..6d47050
--- /dev/null
+++ b/tests/compiler/dart2js/rti/backend_type_helper_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2018, 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:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/js_emitter/program_builder/program_builder.dart';
+import 'package:compiler/src/world.dart';
+import 'package:expect/expect.dart';
+import '../helpers/program_lookup.dart';
+import '../memory_compiler.dart';
+
+main() {
+ runTest({bool useKernel}) async {
+ CompilationResult result = await runCompiler(
+ entryPoint: Platform.script.resolve('data/subtype_named_args.dart'),
+ options: useKernel ? [Flags.useKernel] : []);
+ Expect.isTrue(result.isSuccess);
+ Compiler compiler = result.compiler;
+ ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+ ProgramLookup programLookup = new ProgramLookup(compiler);
+
+ List<ClassEntity> found = <ClassEntity>[];
+ for (ClassEntity element
+ in Collector.getBackendTypeHelpers(closedWorld.commonElements)) {
+ if (programLookup.getClass(element) != null) {
+ found.add(element);
+ }
+ }
+ Expect.isTrue(found.isEmpty, "Classes ${found} should not be emitted");
+ }
+
+ asyncTest(() async {
+ print('--test from ast---------------------------------------------------');
+ await runTest(useKernel: false);
+ print('--test from kernel------------------------------------------------');
+ await runTest(useKernel: true);
+ });
+}
diff --git a/tests/compiler/dart2js/rti/data/function_subtype_local5.dart b/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
new file mode 100644
index 0000000..5acd91f
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
@@ -0,0 +1,44 @@
+// 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:explicit=[int Function(C.T),int Function(C.T,[String]),int Function(C.T,int),int Function(C.T,{,b:String})],needsArgs*/
+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:needsArgs*/
+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/compiler/dart2js/rti/data/generic_class_instantiate.dart b/tests/compiler/dart2js/rti/data/generic_class_instantiate.dart
index 8bf986a..65a7e4d 100644
--- a/tests/compiler/dart2js/rti/data/generic_class_instantiate.dart
+++ b/tests/compiler/dart2js/rti/data/generic_class_instantiate.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.
-/*class: A:arg,explicit=[B<A>]*/
+/*class: A:explicit=[B<A>]*/
class A {}
/*class: B:deps=[C],explicit=[B<A>],needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/generic_class_is.dart b/tests/compiler/dart2js/rti/data/generic_class_is.dart
index d82f758..acfcaac 100644
--- a/tests/compiler/dart2js/rti/data/generic_class_is.dart
+++ b/tests/compiler/dart2js/rti/data/generic_class_is.dart
@@ -4,7 +4,7 @@
import 'package:meta/dart2js.dart';
-/*class: A:arg,checked,implicit=[A]*/
+/*class: A:implicit=[A]*/
class A {}
/*class: B:direct,explicit=[B.T],needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/generic_class_is2.dart b/tests/compiler/dart2js/rti/data/generic_class_is2.dart
index 612fe1d..508466d 100644
--- a/tests/compiler/dart2js/rti/data/generic_class_is2.dart
+++ b/tests/compiler/dart2js/rti/data/generic_class_is2.dart
@@ -5,12 +5,9 @@
import 'package:expect/expect.dart';
import 'package:meta/dart2js.dart';
-// TODO(johnniwinther): A, C and C2 should be checked or A1, C1, and C2 should
-// have checks againts A, C and C, respectively.
-/*class: A:arg,checks=[A],implicit=[List<A<C2>>,List<A<C>>]*/
+/*class: A:implicit=[List<A<C2>>,List<A<C>>]*/
class A<T> {}
-/*class: A1:arg,checks=[A]*/
class A1 implements A<C1> {}
/*class: B:direct,explicit=[B.T],needsArgs*/
@@ -19,13 +16,12 @@
method(var t) => t is T;
}
-/*class: C:arg,checks=[C],implicit=[List<A<C>>]*/
+/*class: C:implicit=[List<A<C>>]*/
class C {}
-/*class: C1:arg*/
class C1 implements C {}
-/*class: C2:arg,checks=[C,C2],implicit=[List<A<C2>>]*/
+/*class: C2:implicit=[List<A<C2>>]*/
class C2 implements C {}
main() {
diff --git a/tests/compiler/dart2js/rti/data/generic_closure_instantiate.dart b/tests/compiler/dart2js/rti/data/generic_closure_instantiate.dart
index cc83ed0..635ac78 100644
--- a/tests/compiler/dart2js/rti/data/generic_closure_instantiate.dart
+++ b/tests/compiler/dart2js/rti/data/generic_closure_instantiate.dart
@@ -5,8 +5,7 @@
/*class: A:explicit=[B<A>]*/
class A {}
-/*ast.class: B:deps=[closure],explicit=[B<A>],needsArgs*/
-/*kernel.class: B:arg,checks=[B],deps=[closure],explicit=[B<A>],needsArgs*/
+/*class: B:deps=[closure],explicit=[B<A>],needsArgs*/
class B<T> {}
main() {
diff --git a/tests/compiler/dart2js/rti/data/generic_creation.dart b/tests/compiler/dart2js/rti/data/generic_creation.dart
new file mode 100644
index 0000000..56adaeb
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/generic_creation.dart
@@ -0,0 +1,56 @@
+// 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";
+
+/*class: A:needsArgs*/
+/*element: A.:needsSignature*/
+class A<X, Y, Z> {
+ /*element: A.shift:needsSignature*/
+ shift() => new A<Z, X, Y>();
+ /*element: A.swap:needsSignature*/
+ swap() => new A<Z, Y, X>();
+ /*element: A.first:needsSignature*/
+ first() => new A<X, X, X>();
+ /*element: A.last:needsSignature*/
+ last() => new A<Z, Z, Z>();
+ /*element: A.wrap:needsSignature*/
+ wrap() => new A<A<X, X, X>, A<Y, Y, Y>, A<Z, Z, Z>>();
+}
+
+/*element: B.:needsSignature*/
+class B extends A<U, V, W> {}
+
+/*class: C:needsArgs*/
+/*element: C.:needsSignature*/
+class C<T> extends A<U, T, W> {}
+
+/*class: D:needsArgs*/
+/*element: D.:needsSignature*/
+class D<X, Y, Z> extends A<Y, Z, X> {}
+
+class U {}
+
+class V {}
+
+class W {}
+
+/*element: sameType:needsSignature*/
+sameType(a, b) => Expect.equals(a.runtimeType, b.runtimeType);
+
+/*element: main:needsSignature*/
+main() {
+ A a = new A<U, V, W>();
+ sameType(new A<W, U, V>(), a.shift());
+ sameType(new A<W, V, U>(), a.swap());
+ sameType(new A<U, U, U>(), a.first());
+ sameType(new A<W, W, W>(), a.last());
+ sameType(new A<A<U, U, U>, A<V, V, V>, A<W, W, W>>(), a.wrap());
+ B b = new B();
+ sameType(new A<A<U, U, U>, A<V, V, V>, A<W, W, W>>(), b.wrap());
+ C c = new C<V>();
+ sameType(new A<A<U, U, U>, A<V, V, V>, A<W, W, W>>(), c.wrap());
+ D d = new D<U, V, W>();
+ sameType(new A<A<V, V, V>, A<W, W, W>, A<U, U, U>>(), d.wrap());
+}
diff --git a/tests/compiler/dart2js/rti/data/generic_instanceof4.dart b/tests/compiler/dart2js/rti/data/generic_instanceof4.dart
index b035806..16b3327 100644
--- a/tests/compiler/dart2js/rti/data/generic_instanceof4.dart
+++ b/tests/compiler/dart2js/rti/data/generic_instanceof4.dart
@@ -12,7 +12,7 @@
}
}
-/*class: BB:arg,checked,implicit=[BB]*/
+/*class: BB:implicit=[BB]*/
class BB {}
/*class: B:implicit=[B.T],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/generic_method1_strong.dart b/tests/compiler/dart2js/rti/data/generic_method1_strong.dart
index 376861d..651976b 100644
--- a/tests/compiler/dart2js/rti/data/generic_method1_strong.dart
+++ b/tests/compiler/dart2js/rti/data/generic_method1_strong.dart
@@ -13,9 +13,7 @@
}
}
-// TODO(johnniwinther): Should include 'arg'. Update the 'checkedArguments'
-// computation to take method type arguments into account.
-/*class: BB:checked,implicit=[BB]*/
+/*class: BB:implicit=[BB]*/
class BB {}
/*element: method2:deps=[B],implicit=[method2.T],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/generic_method2_strong.dart b/tests/compiler/dart2js/rti/data/generic_method2_strong.dart
index 1235481..27a1d49 100644
--- a/tests/compiler/dart2js/rti/data/generic_method2_strong.dart
+++ b/tests/compiler/dart2js/rti/data/generic_method2_strong.dart
@@ -13,9 +13,7 @@
}
}
-// TODO(johnniwinther): Should include 'arg'. Update the 'checkedArguments'
-// computation to take method type arguments into account.
-/*class: BB:checked,implicit=[BB]*/
+/*class: BB:implicit=[BB]*/
class BB {}
/*class: B:deps=[method1],implicit=[B.T],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/generic_method3_strong.dart b/tests/compiler/dart2js/rti/data/generic_method3_strong.dart
index dddc5f0..46ecef3c 100644
--- a/tests/compiler/dart2js/rti/data/generic_method3_strong.dart
+++ b/tests/compiler/dart2js/rti/data/generic_method3_strong.dart
@@ -13,7 +13,7 @@
}
}
-/*class: BB:arg,checked,implicit=[BB]*/
+/*class: BB:implicit=[BB]*/
class BB {}
/*element: method2:deps=[B],implicit=[method2.T],indirect,needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/generic_method_is_strong.dart b/tests/compiler/dart2js/rti/data/generic_method_is_strong.dart
index bcd1f4b..db9a3f7 100644
--- a/tests/compiler/dart2js/rti/data/generic_method_is_strong.dart
+++ b/tests/compiler/dart2js/rti/data/generic_method_is_strong.dart
@@ -12,30 +12,29 @@
class B2 {}
-/*class: C1:checked,implicit=[C1]*/
+/*class: C1:implicit=[C1]*/
class C1 {}
class C2 {}
-/*class: C3:checked*/
class C3 {}
-/*class: D1:checked,implicit=[D1]*/
+/*class: D1:implicit=[D1]*/
class D1 {}
class D2 {}
-/*class: E1:checked,implicit=[E1]*/
+/*class: E1:implicit=[E1]*/
class E1 {}
class E2 {}
-/*class: F1:checked,implicit=[F1]*/
+/*class: F1:implicit=[F1]*/
class F1 {}
class F2 {}
-/*class: F3:checked,implicit=[F3]*/
+/*class: F3:implicit=[F3]*/
class F3 {}
/*element: topLevelMethod1:direct,explicit=[topLevelMethod1.T],needsArgs*/
diff --git a/tests/compiler/dart2js/rti/data/list_to_set.dart b/tests/compiler/dart2js/rti/data/list_to_set.dart
index b8598de..f858a43 100644
--- a/tests/compiler/dart2js/rti/data/list_to_set.dart
+++ b/tests/compiler/dart2js/rti/data/list_to_set.dart
@@ -2,8 +2,10 @@
// 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.
-/*class: global#List:deps=[Class,EmptyIterable,Iterable,JSArray,ListIterable,SetMixin,SubListIterable],explicit=[List],implicit=[List.E],indirect,needsArgs*/
-/*class: global#JSArray:checked,deps=[EmptyIterable,List,ListIterable,SetMixin,SubListIterable],explicit=[JSArray],implicit=[JSArray.E],indirect,needsArgs*/
+/*ast.class: global#List:deps=[Class,EmptyIterable,Iterable,JSArray,ListIterable,SetMixin,SubListIterable],explicit=[List],implicit=[List.E],indirect,needsArgs*/
+/*kernel.class: global#List:deps=[Class,EmptyIterable,Iterable,JSArray,ListIterable,SetMixin],explicit=[List],implicit=[List.E],indirect,needsArgs*/
+/*ast.class: global#JSArray:deps=[List],explicit=[JSArray],implicit=[JSArray.E],indirect,needsArgs*/
+/*kernel.class: global#JSArray:deps=[EmptyIterable,List,ListIterable,SetMixin,SubListIterable],explicit=[JSArray],implicit=[JSArray.E],indirect,needsArgs*/
main() {
var c = new Class<int>();
diff --git a/tests/compiler/dart2js/rti/data/map_literal.dart b/tests/compiler/dart2js/rti/data/map_literal.dart
index 409bb7d..1643414 100644
--- a/tests/compiler/dart2js/rti/data/map_literal.dart
+++ b/tests/compiler/dart2js/rti/data/map_literal.dart
@@ -5,7 +5,7 @@
/*class: global#Map:*/
/*class: global#LinkedHashMap:deps=[Map]*/
/*class: global#JsLinkedHashMap:deps=[LinkedHashMap]*/
-/*class: global#double:arg,explicit=[double]*/
+/*class: global#double:explicit=[double]*/
/*class: global#JSDouble:*/
main() {
diff --git a/tests/compiler/dart2js/rti/data/map_literal_checked.dart b/tests/compiler/dart2js/rti/data/map_literal_checked.dart
index d7534bf..9c6733f 100644
--- a/tests/compiler/dart2js/rti/data/map_literal_checked.dart
+++ b/tests/compiler/dart2js/rti/data/map_literal_checked.dart
@@ -2,10 +2,10 @@
// 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.
-/*class: global#Map:checked,explicit=[Map],indirect,needsArgs*/
-/*class: global#LinkedHashMap:checked,deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
-/*class: global#JsLinkedHashMap:checked,deps=[LinkedHashMap],direct,explicit=[Iterable<JsLinkedHashMap.K>,JsLinkedHashMap.K,JsLinkedHashMap.V,JsLinkedHashMap<JsLinkedHashMap.K,JsLinkedHashMap.V>,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
-/*class: global#double:arg,checked,explicit=[double],implicit=[double]*/
+/*class: global#Map:explicit=[Map],indirect,needsArgs*/
+/*class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],indirect,needsArgs*/
+/*class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[Iterable<JsLinkedHashMap.K>,JsLinkedHashMap.K,JsLinkedHashMap.V,JsLinkedHashMap<JsLinkedHashMap.K,JsLinkedHashMap.V>,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*class: global#double:explicit=[double],implicit=[double]*/
/*class: global#JSDouble:*/
main() {
diff --git a/tests/compiler/dart2js/rti/data/map_to_set.dart b/tests/compiler/dart2js/rti/data/map_to_set.dart
index 2d8037c..4cfda0e 100644
--- a/tests/compiler/dart2js/rti/data/map_to_set.dart
+++ b/tests/compiler/dart2js/rti/data/map_to_set.dart
@@ -5,7 +5,7 @@
/*class: global#Map:deps=[Class],needsArgs*/
/*class: global#LinkedHashMap:deps=[Map],needsArgs*/
/*class: global#JsLinkedHashMap:deps=[LinkedHashMap],implicit=[JsLinkedHashMap.K],needsArgs*/
-/*class: global#double:arg,explicit=[double]*/
+/*class: global#double:explicit=[double]*/
/*class: global#JSDouble:*/
main() {
diff --git a/tests/compiler/dart2js/rti/data/subtype_named_args.dart b/tests/compiler/dart2js/rti/data/subtype_named_args.dart
index 10e7145..d7014bf 100644
--- a/tests/compiler/dart2js/rti/data/subtype_named_args.dart
+++ b/tests/compiler/dart2js/rti/data/subtype_named_args.dart
@@ -6,30 +6,28 @@
import 'package:expect/expect.dart';
-/*ast.class: A:arg,checks=[A,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
-/*kernel.class: A:arg,checks=[A,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*ast.class: A:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*kernel.class: A:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
class A {}
-/*class: A1:arg,checks=[A1,Object]*/
class A1 {}
-/*class: A2:arg,checks=[A2,Object]*/
class A2 {}
-/*ast.class: B:arg,checks=[A,A1,A2,B,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
-/*kernel.class: B:arg,checks=[A,A1,A2,B,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*ast.class: B:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*kernel.class: B:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
class B implements A, A1, A2 {}
-/*ast.class: C:arg,checks=[A,A1,A2,B,C,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
-/*kernel.class: C:arg,checks=[A,A1,A2,B,C,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*ast.class: C:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*kernel.class: C:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
class C implements B {}
-/*ast.class: D:arg,checks=[A,A1,A2,B,C,D,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
-/*kernel.class: D:arg,checks=[A,A1,A2,B,C,D,Object],explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*ast.class: D:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*kernel.class: D:explicit=[dynamic Function({a:A,b:B,c:C,d:D}),dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
class D implements C {}
-/*ast.class: G:arg,checks=[G,Object],explicit=[dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
-/*kernel.class: G:arg,checks=[G,Object],explicit=[dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*ast.class: G:explicit=[dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
+/*kernel.class: G:explicit=[dynamic Function({f1:dynamic Function({a:A,b:B,c:C,d:D}),f2:dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>}),f3:dynamic Function({v:dynamic,x:dynamic,y:dynamic,z:dynamic})}),dynamic Function({g:G<A,B,C,D>,l:List<List<B>>,m:Map<num,int>})]*/
class G<T, S, U, W> {}
typedef classesFunc({A a, B b, C c, D d});
diff --git a/tests/compiler/dart2js/rti/data/subtype_named_args1.dart b/tests/compiler/dart2js/rti/data/subtype_named_args1.dart
new file mode 100644
index 0000000..0312132
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/subtype_named_args1.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2018, 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.
+
+// From co19/Language/Types/Function_Types/subtype_named_args_t01.
+
+import "package:expect/expect.dart";
+
+class A {}
+
+/*ast.class: B:explicit=[dynamic Function({a:B})]*/
+/*kernel.class: B:explicit=[dynamic Function({a:B}),dynamic Function({f:dynamic Function({a:B})})]*/
+class B implements A {}
+
+/*class: C:explicit=[dynamic Function({c:C})]*/
+class C implements B {}
+
+class D implements C {}
+
+typedef t1({B a});
+typedef t2({C c});
+typedef t3({int i});
+typedef t4({var v});
+typedef t5({Map m});
+typedef t6({Map<int, num> m});
+typedef t7({t1 f});
+typedef t8({Object a});
+
+typedef okWithT1_1({A a});
+typedef okWithT1_2({B a});
+typedef okWithT1_3({C a});
+typedef okWithT1_4({D a});
+
+main() {
+ Expect.isTrue(({A a}) {} is t1);
+ Expect.isTrue(({B a}) {} is t1);
+ Expect.isTrue(({C a}) {} is t1);
+ Expect.isTrue(({D a}) {} is t1);
+ Expect.isTrue(({Object a}) {} is t1);
+ Expect.isTrue(({var a}) {} is t1);
+
+ Expect.isTrue(({A c}) {} is t2);
+ Expect.isTrue(({B c}) {} is t2);
+ Expect.isTrue(({C c}) {} is t2);
+ Expect.isTrue(({D c}) {} is t2);
+ Expect.isTrue(({Object c}) {} is t2);
+ Expect.isTrue(({var c}) {} is t2);
+
+ Expect.isTrue(({num i}) {} is t3);
+ Expect.isTrue(({int i}) {} is t3);
+ Expect.isTrue(({Object i}) {} is t3);
+ Expect.isTrue(({var i}) {} is t3);
+
+ Expect.isTrue(({A v}) {} is t4);
+ Expect.isTrue(({B v}) {} is t4);
+ Expect.isTrue(({C v}) {} is t4);
+ Expect.isTrue(({D v}) {} is t4);
+ Expect.isTrue(({Object v}) {} is t4);
+ Expect.isTrue(({var v}) {} is t4);
+ Expect.isTrue(({num v}) {} is t4);
+ Expect.isTrue(({int v}) {} is t4);
+ Expect.isTrue(({Map v}) {} is t4);
+ Expect.isTrue(({Map<List<Map<List, List<int>>>, List> v}) {} is t4);
+ Expect.isTrue(({List v}) {} is t4);
+ Expect.isTrue(({t8 v}) {} is t4);
+ Expect.isTrue(({t7 v}) {} is t4);
+
+ Expect.isTrue(({Map m}) {} is t5);
+ Expect.isTrue(({Map<List, t8> m}) {} is t5);
+ Expect.isTrue(({Object m}) {} is t5);
+ Expect.isTrue(({var m}) {} is t5);
+ Expect.isTrue(({Map<List, List> m}) {} is t5);
+ Expect.isTrue(({Map<int, t8> m}) {} is t5);
+
+ Expect.isTrue(({Map<num, num> m}) {} is t6);
+ Expect.isTrue(({Map<int, int> m}) {} is t6);
+ Expect.isTrue(({Map m}) {} is t6);
+ Expect.isTrue(({Object m}) {} is t6);
+ Expect.isTrue(({var m}) {} is t6);
+
+ Expect.isTrue(({okWithT1_1 f}) {} is t7);
+ Expect.isTrue(({okWithT1_2 f}) {} is t7);
+ Expect.isTrue(({okWithT1_3 f}) {} is t7);
+ Expect.isTrue(({okWithT1_4 f}) {} is t7);
+
+ Expect.isTrue(({A a}) {} is t8);
+ Expect.isTrue(({B a}) {} is t8);
+ Expect.isTrue(({C a}) {} is t8);
+ Expect.isTrue(({D a}) {} is t8);
+ Expect.isTrue(({Object a}) {} is t8);
+ Expect.isTrue(({var a}) {} is t8);
+ Expect.isTrue(({num a}) {} is t8);
+ Expect.isTrue(({int a}) {} is t8);
+ Expect.isTrue(({Map a}) {} is t8);
+ Expect.isTrue(({Map<List<Map<List, List<int>>>, List> a}) {} is t8);
+ Expect.isTrue(({List a}) {} is t8);
+}
diff --git a/tests/compiler/dart2js/rti/data/type_argument_substitution.dart b/tests/compiler/dart2js/rti/data/type_argument_substitution.dart
index c1e227e..635ad13 100644
--- a/tests/compiler/dart2js/rti/data/type_argument_substitution.dart
+++ b/tests/compiler/dart2js/rti/data/type_argument_substitution.dart
@@ -7,16 +7,14 @@
import 'package:expect/expect.dart';
-/*class: K:arg*/
class K {}
-/*class: A:arg,checks=[A],explicit=[X<A<String>>]*/
+/*class: A:explicit=[X<A<String>>]*/
class A<T> {}
-/*class: B:arg,checks=[A]*/
class B extends A<K> {}
-/*class: X:checked,explicit=[X<A<String>>],needsArgs*/
+/*class: X:explicit=[X<A<String>>],needsArgs*/
class X<T> {}
main() {
diff --git a/tests/compiler/dart2js/rti/data/type_literal2.dart b/tests/compiler/dart2js/rti/data/type_literal2.dart
new file mode 100644
index 0000000..a1e3e6b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/type_literal2.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, 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.
+
+/*class: A:deps=[B],exp,needsArgs*/
+class A<T> {
+ method1() => T;
+}
+
+/*class: B:needsArgs*/
+class B<S> {
+ method2() => new A<S>().method1();
+}
+
+main() {
+ var b = new B<int>();
+ b.method2();
+}
diff --git a/tests/compiler/dart2js/rti/emission/arguments.dart b/tests/compiler/dart2js/rti/emission/arguments.dart
new file mode 100644
index 0000000..328e684
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/arguments.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A {}
+
+/*class: B:checks=[]*/
+class B {}
+
+/*class: C:checks=[]*/
+class C<T> {}
+
+@noInline
+test(o) => o is C<A>;
+
+main() {
+ test(new C<A>());
+ test(new C<B>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/call.dart b/tests/compiler/dart2js/rti/emission/call.dart
new file mode 100644
index 0000000..d603eab
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/call.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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 'package:meta/dart2js.dart';
+
+/*class: A:checks=[$isFunction]*/
+class A {
+ call() {}
+}
+
+@noInline
+test(o) => o is Function;
+
+main() {
+ Expect.isTrue(test(new A()));
+ Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/rti/emission/closure_function.dart b/tests/compiler/dart2js/rti/emission/closure_function.dart
new file mode 100644
index 0000000..82d8712
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/closure_function.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+@noInline
+test(o) => o is Function;
+
+main() {
+ test(/*checks=[]*/ () {});
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/closure_function_type.dart b/tests/compiler/dart2js/rti/emission/closure_function_type.dart
new file mode 100644
index 0000000..0c7e05b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/closure_function_type.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+@noInline
+test(o) => o is Function();
+
+main() {
+ test(/*checks=[]*/ () {});
+ test(/*checks=[]*/ (a) {});
+}
diff --git a/tests/compiler/dart2js/rti/emission/generic_instanceof4.dart b/tests/compiler/dart2js/rti/emission/generic_instanceof4.dart
new file mode 100644
index 0000000..45ab17f
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/generic_instanceof4.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {
+ @noInline
+ foo(x) {
+ return x is T;
+ }
+}
+
+/*class: BB:checks=[]*/
+class BB {}
+
+/*class: B:checks=[$isBB]*/
+class B<T> implements BB {
+ @noInline
+ foo() {
+ return new A<T>().foo(new B());
+ }
+}
+
+main() {
+ new B<BB>().foo();
+}
diff --git a/tests/compiler/dart2js/rti/emission/inherited_is.dart b/tests/compiler/dart2js/rti/emission/inherited_is.dart
new file mode 100644
index 0000000..618b16f
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/inherited_is.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, 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 'package:meta/dart2js.dart';
+
+class A {}
+
+/*class: B:checks=[]*/
+class B implements A {}
+
+/*class: C:checks=[$isA]*/
+class C = Object with B;
+
+/*class: D:checks=[]*/
+class D extends C {}
+
+@noInline
+test(o) => o is A;
+
+main() {
+ Expect.isTrue(test(new D()));
+ Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/rti/emission/inherited_is2.dart b/tests/compiler/dart2js/rti/emission/inherited_is2.dart
new file mode 100644
index 0000000..a703a2b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/inherited_is2.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, 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 'package:meta/dart2js.dart';
+
+class A {}
+
+/*class: B:checks=[$isA]*/
+class B implements A {}
+
+/*class: C:checks=[]*/
+class C extends B {}
+
+/*class: D:checks=[]*/
+class D extends C {}
+
+@noInline
+test(o) => o is A;
+
+main() {
+ Expect.isTrue(test(new D()));
+ Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/rti/emission/list.dart b/tests/compiler/dart2js/rti/emission/list.dart
new file mode 100644
index 0000000..b5d777c
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/list.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: global#JSArray:checks=[$isIterable]*/
+/*class: global#Iterable:*/
+
+/*class: A:checks=[]*/
+class A {}
+
+/*class: B:checks=[]*/
+class B {}
+
+@noInline
+test(o) => o is Iterable<A>;
+
+main() {
+ test(<A>[]);
+ test(<B>[]);
+}
diff --git a/tests/compiler/dart2js/rti/emission/map_literal.dart b/tests/compiler/dart2js/rti/emission/map_literal.dart
new file mode 100644
index 0000000..1b86df4
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/map_literal.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+/*class: global#Map:*/
+/*class: global#LinkedHashMap:*/
+/*class: global#JsLinkedHashMap:checks=[]*/
+/*class: global#double:checks=[]*/
+/*class: global#JSDouble:checks=[]*/
+
+main() {
+ <int, double>{}[0] = 0.5;
+}
diff --git a/tests/compiler/dart2js/rti/emission/map_literal_checked.dart b/tests/compiler/dart2js/rti/emission/map_literal_checked.dart
new file mode 100644
index 0000000..bda462b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/map_literal_checked.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+/*class: global#Map:checks=[]*/
+/*class: global#LinkedHashMap:*/
+/*class: global#JsLinkedHashMap:checks=[$isLinkedHashMap]*/
+/*class: global#double:checks=[]*/
+/*class: global#JSDouble:checks=[$isdouble]*/
+
+main() {
+ <int, double>{}[0] = 0.5;
+}
diff --git a/tests/compiler/dart2js/rti/emission/mixin_mixin2.dart b/tests/compiler/dart2js/rti/emission/mixin_mixin2.dart
new file mode 100644
index 0000000..747c430
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/mixin_mixin2.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";
+
+/*class: M:checks=[]*/
+class M<T> {
+ t() {
+ return T;
+ }
+}
+
+/*class: A:checks=[]*/
+class A<U> = Object with M<U>;
+
+/*class: B:checks=[]*/
+class B<V> = Object with A<V>;
+
+/*class: C:checks=[$asM]*/
+class C<U> = Object with M<List<U>>;
+
+/*class: D:checks=[$asM]*/
+class D<V> = Object with C<Set<V>>;
+
+/*class: E:checks=[$asM]*/
+class E extends A<num> {}
+
+/*class: F:checks=[$asM]*/
+class F extends B<String> {}
+
+/*class: G:checks=[]*/
+class G<T> extends C<T> {}
+
+/*class: H:checks=[$asM]*/
+class H<T> extends D<Map<String, T>> {}
+
+main() {
+ Expect.equals("num", new E().t().toString());
+ Expect.equals("String", new F().t().toString());
+ Expect.equals("List<bool>", new G<bool>().t().toString());
+ Expect.equals("List<Set<Map<String, int>>>", new H<int>().t().toString());
+}
diff --git a/tests/compiler/dart2js/rti/emission/mixin_mixin4.dart b/tests/compiler/dart2js/rti/emission/mixin_mixin4.dart
new file mode 100644
index 0000000..7d42422
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/mixin_mixin4.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.
+
+import "package:expect/expect.dart";
+
+class I<T> {}
+
+class J<T> {}
+
+/*class: S:checks=[]*/
+class S<T> {}
+
+/*class: M:checks=[]*/
+class M<T> {
+ t() {
+ return T;
+ }
+}
+
+class A<U, V> = Object with M<Map<U, V>> implements I<V>;
+
+/*class: C:checks=[$asA,$asI,$asJ,$asM,$asS,$isA,$isI,$isJ]*/
+class C<T, K> = S<T> with A<T, List<K>> implements J<K>;
+
+@NoInline()
+test(c) {
+ Expect.equals("Map<int, List<bool>>", c.t().toString());
+ Expect.isTrue(c is I<List<bool>>);
+ Expect.isTrue(c is J<bool>);
+ Expect.isTrue(c is S<int>);
+ Expect.isTrue(c is A<int, List<bool>>);
+ Expect.isTrue(c is M<Map<int, List<bool>>>);
+}
+
+main() {
+ test(new C<int, bool>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/mixin_type_arguments.dart b/tests/compiler/dart2js/rti/emission/mixin_type_arguments.dart
new file mode 100644
index 0000000..6067cef
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/mixin_type_arguments.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2018, 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' show Expect;
+
+/*class: A:checks=[]*/
+class A {}
+
+/*class: B:checks=[]*/
+class B {}
+
+/*class: C:checks=[]*/
+class C {}
+
+/*class: D:checks=[]*/
+class D {}
+
+/*class: E:checks=[]*/
+class E {}
+
+/*class: F:checks=[]*/
+class F {}
+
+/*class: M1:checks=[]*/
+class M1<Tm1> {
+ m1() => "M1<$Tm1>";
+}
+
+/*class: M2:checks=[]*/
+class M2<Tm2> {
+ m2() => "M2<$Tm2>";
+}
+
+/*class: M3:checks=[]*/
+class M3<Tm3> {
+ m3() => "M3<$Tm3>";
+}
+
+/*class: M4:checks=[]*/
+class M4<Tm4> {
+ m4() => "M4<$Tm4>";
+}
+
+/*class: M5:checks=[]*/
+class M5<Tm5> {
+ m5() => "M5<$Tm5>";
+}
+
+/*class: C1:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C1 = Object with M1, M2<A>, M3, M4<B>, M5<C>;
+
+/*class: C2:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C2 = Object with M1<A>, M2<B>, M3<C>, M4<D>, M5<E>;
+
+/*class: C3:checks=[$asM1,$asM3,$asM4,$asM5]*/
+class C3<T> = Object with M1<A>, M2<T>, M3, M4, M5<B>;
+
+/*class: C4:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C4 extends Object with M1, M2<A>, M3, M4<B>, M5<C> {}
+
+/*class: C5:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C5 extends Object with M1<A>, M2<B>, M3<C>, M4<D>, M5<E> {}
+
+/*class: C6:checks=[$asM1,$asM3,$asM4,$asM5]*/
+class C6<T> extends Object with M1<A>, M2<T>, M3, M4, M5<B> {}
+
+/*class: C7:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C7 = Object with M1<A>, M2<A>, M3<A>, M4<A>, M5<A>;
+
+/*class: C8:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C8 extends Object with M1<A>, M2<A>, M3<A>, M4<A>, M5<A> {}
+
+/*class: C9:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class C9 = Object
+ with M1<List<A>>, M2<List<A>>, M3<List<A>>, M4<List<A>>, M5<List<A>>;
+
+/*class: CA:checks=[$asM1,$asM2,$asM3,$asM4,$asM5]*/
+class CA extends Object
+ with M1<List<A>>, M2<List<A>>, M3<List<A>>, M4<List<A>>, M5<List<A>> {}
+
+trace(x) => "${x.m1()}, ${x.m2()}, ${x.m3()}, ${x.m4()}, ${x.m5()}";
+
+main() {
+ Expect.stringEquals(
+ "M1<dynamic>, M2<A>, M3<dynamic>, M4<B>, M5<C>", trace(new C1()));
+ Expect.stringEquals("M1<A>, M2<B>, M3<C>, M4<D>, M5<E>", trace(new C2()));
+ Expect.stringEquals(
+ "M1<A>, M2<dynamic>, M3<dynamic>, M4<dynamic>, M5<B>", trace(new C3()));
+ Expect.stringEquals(
+ "M1<A>, M2<F>, M3<dynamic>, M4<dynamic>, M5<B>", trace(new C3<F>()));
+ Expect.stringEquals(
+ "M1<dynamic>, M2<A>, M3<dynamic>, M4<B>, M5<C>", trace(new C4()));
+ Expect.stringEquals("M1<A>, M2<B>, M3<C>, M4<D>, M5<E>", trace(new C5()));
+ Expect.stringEquals(
+ "M1<A>, M2<dynamic>, M3<dynamic>, M4<dynamic>, M5<B>", trace(new C6()));
+ Expect.stringEquals(
+ "M1<A>, M2<F>, M3<dynamic>, M4<dynamic>, M5<B>", trace(new C6<F>()));
+ Expect.stringEquals("M1<A>, M2<A>, M3<A>, M4<A>, M5<A>", trace(new C7()));
+ Expect.stringEquals("M1<A>, M2<A>, M3<A>, M4<A>, M5<A>", trace(new C8()));
+ Expect.stringEquals(
+ "M1<List<A>>, M2<List<A>>, M3<List<A>>, M4<List<A>>, M5<List<A>>",
+ trace(new C9()));
+ Expect.stringEquals(
+ "M1<List<A>>, M2<List<A>>, M3<List<A>>, M4<List<A>>, M5<List<A>>",
+ trace(new CA()));
+}
diff --git a/tests/compiler/dart2js/rti/emission/native.dart b/tests/compiler/dart2js/rti/emission/native.dart
new file mode 100644
index 0000000..c7bfb9f
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/native.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2015, 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";
+// ignore: import_internal_library
+import 'dart:_js_helper' show Native;
+// ignore: import_internal_library
+import 'dart:_foreign_helper' show JS;
+
+/*class: Purple:checks=[$isPurple]*/
+@Native('PPPP')
+class Purple {}
+
+@Native('QQQQ')
+class Q {}
+
+@NoInline()
+makeP() => JS('returns:;creates:Purple', 'null');
+
+@NoInline()
+makeQ() => JS('Q', 'null');
+
+@NoInline()
+testNative() {
+ var x = makeP();
+ Expect.isTrue(x is Purple);
+ x = makeQ();
+ Expect.isFalse(x is Purple);
+}
+
+main() {
+ testNative();
+}
diff --git a/tests/compiler/dart2js/rti/emission/regress_18713.dart b/tests/compiler/dart2js/rti/emission/regress_18713.dart
new file mode 100644
index 0000000..8d0ff99
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/regress_18713.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, 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: T:checks=[]*/
+class T<X> {
+ final Type tType = X;
+ Type get getTType => X;
+}
+
+/*class: S:checks=[]*/
+class S<Y> {
+ final Type sType = Y;
+ Type get getSType => Y;
+}
+
+/*class: TS:checks=[$asS0,$asT]*/
+class TS<A, B> = T<A> with S<B>;
+
+@NoInline()
+@AssumeDynamic()
+dyn(x) => x;
+
+main() {
+ var ts = new TS<int, String>();
+
+ Expect.equals("String", ts.sType.toString());
+ Expect.equals("int", ts.tType.toString());
+ Expect.equals("String", ts.getSType.toString());
+ Expect.equals("int", ts.getTType.toString());
+
+ Expect.equals("String", dyn(ts).sType.toString());
+ Expect.equals("int", dyn(ts).tType.toString());
+ Expect.equals("String", dyn(ts).getSType.toString());
+ Expect.equals("int", dyn(ts).getTType.toString());
+}
diff --git a/tests/compiler/dart2js/rti/emission/runtime_type.dart b/tests/compiler/dart2js/rti/emission/runtime_type.dart
new file mode 100644
index 0000000..c9973eb
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/runtime_type.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, 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.
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[]*/
+class B<T> {}
+
+main() {
+ print("A<B<int>>" == new A<B<int>>().runtimeType.toString());
+}
diff --git a/tests/compiler/dart2js/rti/emission/self.dart b/tests/compiler/dart2js/rti/emission/self.dart
new file mode 100644
index 0000000..76c29c4
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/self.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: C:checks=[]*/
+class C {}
+
+@noInline
+test(o) => o is C;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/self_generic.dart b/tests/compiler/dart2js/rti/emission/self_generic.dart
new file mode 100644
index 0000000..793f276
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/self_generic.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: C:checks=[]*/
+class C<T> {}
+
+@noInline
+test(o) => o is C<String>;
+
+main() {
+ test(new C<String>());
+ test(new C<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/subtype_named_args.dart b/tests/compiler/dart2js/rti/emission/subtype_named_args.dart
new file mode 100644
index 0000000..b2b1cc7
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/subtype_named_args.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2018, 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.
+
+// From co19/Language/Types/Function_Types/subtype_named_args_t02.
+
+import 'package:expect/expect.dart';
+
+/*class: A:checks=[]*/
+class A {}
+
+/*class: A1:checks=[]*/
+class A1 {}
+
+/*class: A2:checks=[]*/
+class A2 {}
+
+/*class: B:checks=[$isA,$isA1,$isA2]*/
+class B implements A, A1, A2 {}
+
+/*class: C:checks=[$isA,$isA1,$isA2,$isB]*/
+class C implements B {}
+
+/*class: D:checks=[$isA,$isA1,$isA2,$isB,$isC]*/
+class D implements C {}
+
+/*class: G:checks=[]*/
+class G<T, S, U, W> {}
+
+typedef classesFunc({A a, B b, C c, D d});
+typedef genericsFunc({Map<num, int> m, List<List<B>> l, G<A, B, C, D> g});
+typedef dynamicFunc({var x, var y, var z, var v});
+typedef funcFunc({classesFunc f1, genericsFunc f2, dynamicFunc f3});
+typedef mixFunc({var x, B b, G<A, B, C, D> g, funcFunc f});
+
+typedef okWithClassesFunc_1({A a, A1 b, A1 c, A1 d});
+typedef okWithClassesFunc_2({D a, D b, D c, D d});
+
+typedef okWithGenericsFunc_1(
+ {Map<num, num> m, List<List<A1>> l, G<A, A1, A1, A1> g});
+typedef okWithGenericsFunc_2(
+ {Map<int, int> m, List<List<D>> l, G<D, D, D, D> g});
+
+typedef okWithDynamicFunc_1({A x, G y, mixFunc z, var v});
+typedef okWithDynamicFunc_2({int x, bool y, List<Map> z, classesFunc v});
+
+main() {
+ Expect.isTrue(/*checks=[]*/ ({D a, B b, C c, A d}) {} is classesFunc);
+ Expect.isTrue(/*checks=[]*/ ({A a, A b, A c, A d}) {} is classesFunc);
+ Expect.isTrue(/*checks=[]*/ ({D a, A1 b, A1 c, A1 d}) {} is classesFunc);
+ Expect.isTrue(/*checks=[]*/ ({D a, A2 b, A2 c, A2 d}) {} is classesFunc);
+ Expect.isTrue(/*checks=[]*/ ({D a, D b, D c, D d}) {} is classesFunc);
+ Expect.isTrue(/*checks=[]*/ ({var a, var b, var c, var d}) {} is classesFunc);
+ Expect.isTrue(/*checks=[]*/ ({Object a, Object b, Object c, Object d}) {}
+ is classesFunc);
+
+ Expect.isTrue(/*checks=[]*/ (
+ {Map<num, num> m,
+ List<List<A1>> l,
+ G<A, A1, A1, A1> g}) {} is genericsFunc);
+ Expect.isTrue(
+ /*checks=[]*/ ({Map<int, int> m, List<List<D>> l, G<D, D, D, D> g}) {}
+ is genericsFunc);
+ Expect.isTrue(/*checks=[]*/ ({var m, var l, var g}) {} is genericsFunc);
+ Expect.isTrue(
+ /*checks=[]*/ ({Object m, Object l, Object g}) {} is genericsFunc);
+
+ Expect.isTrue(/*checks=[]*/ ({A x, G y, mixFunc z, var v}) {} is dynamicFunc);
+ Expect.isTrue(/*checks=[]*/ ({int x, bool y, List<Map> z, classesFunc v}) {}
+ is dynamicFunc);
+
+ Expect.isTrue(/*checks=[]*/ (
+ {okWithClassesFunc_1 f1,
+ okWithGenericsFunc_1 f2,
+ okWithDynamicFunc_1 f3}) {} is funcFunc);
+ Expect.isTrue(/*checks=[]*/ (
+ {okWithClassesFunc_2 f1,
+ okWithGenericsFunc_2 f2,
+ okWithDynamicFunc_2 f3}) {} is funcFunc);
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass.dart b/tests/compiler/dart2js/rti/emission/superclass.dart
new file mode 100644
index 0000000..4270537
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: B:checks=[]*/
+class B {}
+
+/*class: C:checks=[]*/
+class C extends B {}
+
+@noInline
+test(o) => o is B;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_as.dart b/tests/compiler/dart2js/rti/emission/superclass_as.dart
new file mode 100644
index 0000000..e780a0e
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_as.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2018, 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 'package:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[]*/
+class B<T, S> {
+ @noInline
+ method() => new A<S>();
+}
+
+/*class: C:checks=[$asB]*/
+class C<T> extends B<T, T> {}
+
+@noInline
+test(o) => o is A<int>;
+
+main() {
+ Expect.isTrue(test(new C<int>().method()));
+ Expect.isFalse(test(new C<String>().method()));
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_complex.dart b/tests/compiler/dart2js/rti/emission/superclass_complex.dart
new file mode 100644
index 0000000..d2f9bb5
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_complex.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[]*/
+class B<T> {}
+
+/*class: C:checks=[$asB]*/
+class C<T> extends B<A<T>> {}
+
+@noInline
+test(o) => o is B<A<String>>;
+
+main() {
+ test(new C<String>());
+ test(new C<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_fixed.dart b/tests/compiler/dart2js/rti/emission/superclass_fixed.dart
new file mode 100644
index 0000000..5c86698
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_fixed.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: B:checks=[]*/
+class B<T> {}
+
+/*class: C:checks=[$asB]*/
+class C extends B<String> {}
+
+@noInline
+test(o) => o is B<String>;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_supertype.dart b/tests/compiler/dart2js/rti/emission/superclass_supertype.dart
new file mode 100644
index 0000000..fa9bad0
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_supertype.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A {}
+
+/*class: B:*/
+class B {}
+
+/*class: C:checks=[$isB]*/
+class C extends A implements B {}
+
+@noInline
+test(o) => o is B;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_supertype_complex.dart b/tests/compiler/dart2js/rti/emission/superclass_supertype_complex.dart
new file mode 100644
index 0000000..29bcaa7
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_supertype_complex.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:*/
+class B<T> {}
+
+/*class: C:checks=[]*/
+class C<T> {}
+
+/*class: D:checks=[$asB,$isB]*/
+class D<T> extends C<T> implements B<A<T>> {}
+
+@noInline
+test(o) => o is B<A<String>>;
+
+main() {
+ test(new D<String>());
+ test(new D<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_supertype_fixed.dart b/tests/compiler/dart2js/rti/emission/superclass_supertype_fixed.dart
new file mode 100644
index 0000000..3c5a8d0
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_supertype_fixed.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A {}
+
+/*class: B:*/
+class B<T> {}
+
+/*class: C:checks=[$asB,$isB]*/
+class C extends A implements B<String> {}
+
+@noInline
+test(o) => o is B<String>;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_supertype_trivial.dart b/tests/compiler/dart2js/rti/emission/superclass_supertype_trivial.dart
new file mode 100644
index 0000000..73f6b8b
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_supertype_trivial.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:*/
+class B<T> {}
+
+/*class: C:checks=[$isB]*/
+class C<T> extends A<T> implements B<T> {}
+
+@noInline
+test(o) => o is B<String>;
+
+main() {
+ test(new C<String>());
+ test(new C<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclass_trivial.dart b/tests/compiler/dart2js/rti/emission/superclass_trivial.dart
new file mode 100644
index 0000000..b9d8ac1
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclass_trivial.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: B:checks=[]*/
+class B<T> {}
+
+/*class: C:checks=[]*/
+class C<T> extends B<T> {}
+
+@noInline
+test(o) => o is B<String>;
+
+main() {
+ test(new C<String>());
+ test(new C<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclasses_non_trivial.dart b/tests/compiler/dart2js/rti/emission/superclasses_non_trivial.dart
new file mode 100644
index 0000000..c3ff5dd
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclasses_non_trivial.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[$asA]*/
+class B<S, T> extends A<T> {} // Non-trivial substitution of A.
+
+/*class: C:checks=[]*/
+class C<S, T> extends B<S, T> {} // Non-trivial substitution of A
+
+@noInline
+test(o) => o is A<String>;
+
+main() {
+ test(new C<int, String>());
+ test(new B<String, int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/superclasses_trivial.dart b/tests/compiler/dart2js/rti/emission/superclasses_trivial.dart
new file mode 100644
index 0000000..a552926
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/superclasses_trivial.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[$asA]*/
+class B<S, T> extends A<T> {} // Non-trivial substitution of A.
+
+/*class: C:checks=[$asA,$asB]*/
+class C<T> extends B<T, T> {} // Trivial substitution of A
+
+@noInline
+test(o) => o is A<String>;
+
+main() {
+ test(new C<String>());
+ test(new B<String, int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertype.dart b/tests/compiler/dart2js/rti/emission/supertype.dart
new file mode 100644
index 0000000..763d175
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertype.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: B:*/
+class B {}
+
+/*class: C:checks=[$isB]*/
+class C implements B {}
+
+@noInline
+test(o) => o is B;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertype_complex.dart b/tests/compiler/dart2js/rti/emission/supertype_complex.dart
new file mode 100644
index 0000000..8a70382
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertype_complex.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:*/
+class B<T> {}
+
+/*class: C:checks=[$asB,$isB]*/
+class C<T> implements B<A<T>> {}
+
+@noInline
+test(o) => o is B<A<String>>;
+
+main() {
+ test(new C<String>());
+ test(new C<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertype_fixed.dart b/tests/compiler/dart2js/rti/emission/supertype_fixed.dart
new file mode 100644
index 0000000..ce5d6d7
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertype_fixed.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: B:*/
+class B<T> {}
+
+/*class: C:checks=[$asB,$isB]*/
+class C implements B<String> {}
+
+@noInline
+test(o) => o is B<String>;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertype_trivial.dart b/tests/compiler/dart2js/rti/emission/supertype_trivial.dart
new file mode 100644
index 0000000..4cc95f5
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertype_trivial.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: B:*/
+class B<T> {}
+
+/*class: C:checks=[$isB]*/
+class C<T> implements B<T> {}
+
+@noInline
+test(o) => o is B<String>;
+
+main() {
+ test(new C<String>());
+ test(new C<int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertypes_extends.dart b/tests/compiler/dart2js/rti/emission/supertypes_extends.dart
new file mode 100644
index 0000000..ab679a8
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertypes_extends.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:*/
+class A {}
+
+/*class: B:checks=[$isA]*/
+class B implements A {}
+
+/*class: C:checks=[]*/
+class C extends B {} // Implements A through `extends B`.
+
+@noInline
+test(o) => o is A;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertypes_extends2.dart b/tests/compiler/dart2js/rti/emission/supertypes_extends2.dart
new file mode 100644
index 0000000..772ef53
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertypes_extends2.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+class A {}
+
+/*class: B:checks=[$isA]*/
+class B implements A {}
+
+/*class: C:checks=[]*/
+class C extends B {} // Implements A through `extends B`.
+
+@noInline
+test(o) => o is A;
+
+main() {
+ test(new C());
+ test(new B());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertypes_extends3.dart b/tests/compiler/dart2js/rti/emission/supertypes_extends3.dart
new file mode 100644
index 0000000..894e130
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertypes_extends3.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:*/
+class A {}
+
+/*class: B:checks=[$isA]*/
+class B implements A {}
+
+/*class: C:checks=[]*/
+class C extends B {} // Implements A through `extends B`.
+
+/*class: D:checks=[]*/
+class D extends C {} // Implements A through `extends C`.
+
+@noInline
+test(o) => o is A;
+
+main() {
+ test(new D());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertypes_implements.dart b/tests/compiler/dart2js/rti/emission/supertypes_implements.dart
new file mode 100644
index 0000000..ac984b7
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertypes_implements.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:*/
+class A {}
+
+/*class: B:*/
+class B extends A {}
+
+/*class: C:checks=[$isA]*/
+class C implements B {} // Implements A through `implements B`.
+
+@noInline
+test(o) => o is A;
+
+main() {
+ test(new C());
+ test(null);
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertypes_non_trivial.dart b/tests/compiler/dart2js/rti/emission/supertypes_non_trivial.dart
new file mode 100644
index 0000000..27fd588
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertypes_non_trivial.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[$asA]*/
+class B<S, T> extends A<T> {} // Non-trivial substitution of A.
+
+/*class: C:checks=[$asA,$isA]*/
+class C<S, T> implements B<S, T> {} // Non-trivial substitution of A
+
+@noInline
+test(o) => o is A<String>;
+
+main() {
+ test(new C<int, String>());
+ test(new B<String, int>());
+}
diff --git a/tests/compiler/dart2js/rti/emission/supertypes_trivial.dart b/tests/compiler/dart2js/rti/emission/supertypes_trivial.dart
new file mode 100644
index 0000000..340c2f4
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/supertypes_trivial.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, 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:meta/dart2js.dart';
+
+/*class: A:checks=[]*/
+class A<T> {}
+
+/*class: B:checks=[$asA]*/
+class B<S, T> extends A<T> {} // Non-trivial substitution of A.
+
+/*class: C:checks=[$isA]*/
+class C<T> implements B<T, T> {} // Trivial substitution of A
+
+@noInline
+test(o) => o is A<String>;
+
+main() {
+ test(new C<String>());
+ test(new B<String, int>());
+}
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
new file mode 100644
index 0000000..2dcdc43
--- /dev/null
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2018, 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:async_helper/async_helper.dart';
+import 'package:compiler/src/closure.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
+import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/js_emitter/model.dart';
+import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:compiler/src/kernel/element_map.dart';
+import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
+import 'package:compiler/src/ssa/builder.dart' as ast;
+import 'package:kernel/ast.dart' as ir;
+import '../equivalence/id_equivalence.dart';
+import '../equivalence/id_equivalence_helper.dart';
+import '../helpers/program_lookup.dart';
+
+main(List<String> args) {
+ asyncTest(() async {
+ Directory dataDir =
+ new Directory.fromUri(Platform.script.resolve('emission'));
+ await checkTests(
+ dataDir, computeAstRtiMemberEmission, computeKernelRtiMemberEmission,
+ computeClassDataFromAst: computeAstRtiClassEmission,
+ computeClassDataFromKernel: computeKernelRtiClassEmission,
+ args: args,
+ options: [
+ Flags.strongMode
+ ],
+ skipForKernel: [
+ // TODO(johnniwinther): Fix this. It triggers a crash in the ssa
+ // builder.
+ 'runtime_type.dart',
+ ]);
+ });
+}
+
+class Tags {
+ static const String isChecks = 'checks';
+}
+
+void computeAstRtiMemberEmission(
+ Compiler compiler, MemberEntity _member, Map<Id, ActualData> actualMap,
+ {bool verbose: false}) {
+ MemberElement member = _member;
+ ResolvedAst resolvedAst = member.resolvedAst;
+ compiler.reporter.withCurrentElement(member.implementation, () {
+ new RtiMemberEmissionAstComputer(
+ compiler.reporter, actualMap, resolvedAst, compiler)
+ .run();
+ });
+}
+
+void computeAstRtiClassEmission(
+ Compiler compiler, ClassEntity cls, Map<Id, ActualData> actualMap,
+ {bool verbose: false}) {
+ new RtiClassEmissionAstComputer(compiler, actualMap).computeClassValue(cls);
+}
+
+abstract class ComputeValueMixin<T> {
+ Compiler get compiler;
+ ProgramLookup lookup;
+
+ String getClassValue(ClassEntity element) {
+ lookup ??= new ProgramLookup(compiler);
+ Class cls = lookup.getClass(element);
+ Features features = new Features();
+ if (cls != null) {
+ features.addElement(Tags.isChecks);
+ for (StubMethod stub in cls.isChecks) {
+ features.addElement(Tags.isChecks, stub.name.key);
+ }
+ }
+ return features.getText();
+ }
+
+ String getMemberValue(MemberEntity member) {
+ if (member.enclosingClass != null && member.enclosingClass.isClosure) {
+ return getClassValue(member.enclosingClass);
+ }
+ return null;
+ }
+}
+
+class RtiClassEmissionAstComputer extends DataRegistry
+ with ComputeValueMixin<ast.Node> {
+ final Compiler compiler;
+ final Map<Id, ActualData> actualMap;
+
+ RtiClassEmissionAstComputer(this.compiler, this.actualMap);
+
+ DiagnosticReporter get reporter => compiler.reporter;
+
+ void computeClassValue(covariant ClassElement cls) {
+ Id id = new ClassId(cls.name);
+ registerValue(cls.sourcePosition, id, getClassValue(cls), cls);
+ }
+}
+
+class RtiMemberEmissionAstComputer extends AstDataExtractor
+ with ComputeValueMixin<ast.Node> {
+ final Compiler compiler;
+
+ RtiMemberEmissionAstComputer(DiagnosticReporter reporter,
+ Map<Id, ActualData> actualMap, ResolvedAst resolvedAst, this.compiler)
+ : super(reporter, actualMap, resolvedAst);
+
+ @override
+ String computeElementValue(Id id, AstElement element) {
+ if (element.isParameter) {
+ return null;
+ } else if (element.isLocal && element.isFunction) {
+ LocalFunctionElement localFunction = element;
+ return getMemberValue(localFunction.callMethod);
+ } else {
+ MemberElement member = element.declaration;
+ return getMemberValue(member);
+ }
+ }
+
+ @override
+ String computeNodeValue(Id id, ast.Node node, [AstElement element]) {
+ if (element != null && element.isLocal && element.isFunction) {
+ return computeElementValue(id, element);
+ }
+ return null;
+ }
+}
+
+void computeKernelRtiMemberEmission(
+ Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
+ {bool verbose: false}) {
+ KernelBackendStrategy backendStrategy = compiler.backendStrategy;
+ KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
+ MemberDefinition definition = elementMap.getMemberDefinition(member);
+ new RtiMemberEmissionIrComputer(
+ compiler.reporter,
+ actualMap,
+ elementMap,
+ member,
+ compiler,
+ backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>)
+ .run(definition.node);
+}
+
+void computeKernelRtiClassEmission(
+ Compiler compiler, ClassEntity cls, Map<Id, ActualData> actualMap,
+ {bool verbose: false}) {
+ KernelBackendStrategy backendStrategy = compiler.backendStrategy;
+ KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
+ new RtiClassEmissionIrComputer(compiler, elementMap, actualMap)
+ .computeClassValue(cls);
+}
+
+class RtiClassEmissionIrComputer extends DataRegistry
+ with ComputeValueMixin<ir.Node> {
+ final Compiler compiler;
+ final KernelToElementMapForBuilding _elementMap;
+ final Map<Id, ActualData> actualMap;
+
+ RtiClassEmissionIrComputer(this.compiler, this._elementMap, this.actualMap);
+
+ DiagnosticReporter get reporter => compiler.reporter;
+
+ void computeClassValue(ClassEntity cls) {
+ Id id = new ClassId(cls.name);
+ ir.TreeNode node = _elementMap.getClassDefinition(cls).node;
+ registerValue(
+ computeSourceSpanFromTreeNode(node), id, getClassValue(cls), cls);
+ }
+}
+
+class RtiMemberEmissionIrComputer extends IrDataExtractor
+ with ComputeValueMixin<ir.Node> {
+ final KernelToElementMapForBuilding _elementMap;
+ final ClosureDataLookup<ir.Node> _closureDataLookup;
+ final Compiler compiler;
+
+ RtiMemberEmissionIrComputer(
+ DiagnosticReporter reporter,
+ Map<Id, ActualData> actualMap,
+ this._elementMap,
+ MemberEntity member,
+ this.compiler,
+ this._closureDataLookup)
+ : super(reporter, actualMap);
+
+ @override
+ String computeMemberValue(Id id, ir.Member node) {
+ return getMemberValue(_elementMap.getMember(node));
+ }
+
+ @override
+ String computeNodeValue(Id id, ir.TreeNode node) {
+ if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
+ ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
+ return getMemberValue(info.callMethod);
+ }
+ return null;
+ }
+}
diff --git a/tests/compiler/dart2js/rti/rti_need_test.dart b/tests/compiler/dart2js/rti/rti_need_test.dart
index 75a94d4..1acbf8f 100644
--- a/tests/compiler/dart2js/rti/rti_need_test.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test.dart
@@ -34,7 +34,14 @@
computeClassDataFromAst: computeAstRtiClassNeed,
computeClassDataFromKernel: computeKernelRtiClassNeed,
args: args,
- options: [Flags.strongMode]);
+ options: [
+ Flags.strongMode
+ ],
+ skipForKernel: [
+ // TODO(johnniwinther): Fix this. It triggers a crash in the ssa
+ // builder.
+ 'generic_creation.dart',
+ ]);
});
}
@@ -71,23 +78,6 @@
static const String directTypeArgumentTest = 'direct';
static const String indirectTypeArgumentTest = 'indirect';
static const String typeLiteral = 'exp';
- static const String typeChecks = 'checks';
-
- /// This class is needed as a checked type argument.
- ///
- /// For instance directly in `String` in `o is List<String>` or indirectly
- /// as `String` in
- ///
- /// class C<T> {
- /// method(o) => o is T;
- /// }
- /// main() => new C<String>().method('');
- static const String argumentClass = 'arg';
-
- // Objects are checked against this class.
- //
- // For instance `String` in `o is String`.
- static const String checkedClass = 'checked';
}
abstract class ComputeValueMixin<T> {
@@ -98,9 +88,6 @@
RuntimeTypesNeedBuilderImpl get rtiNeedBuilder =>
compiler.frontendStrategy.runtimeTypesNeedBuilderForTesting;
RuntimeTypesNeed get rtiNeed => compiler.backendClosedWorldForTesting.rtiNeed;
- RuntimeTypesChecks get rtiChecks =>
- compiler.backend.emitter.typeTestRegistry.rtiChecks;
- TypeChecks get requiredChecks => rtiChecks.requiredChecks;
ClassEntity getFrontendClass(ClassEntity cls);
MemberEntity getFrontendMember(MemberEntity member);
Local getFrontendClosure(MemberEntity member);
@@ -152,17 +139,6 @@
rtiNeedBuilder.typeVariableTests.explicitIsChecks);
findChecks(features, Tags.implicitTypeCheck, frontendClass,
rtiNeedBuilder.typeVariableTests.implicitIsChecks);
- if (rtiChecks.checkedClasses.contains(backendClass)) {
- features.add(Tags.checkedClass);
- }
- if (rtiChecks.getRequiredArgumentClasses().contains(backendClass)) {
- features.add(Tags.argumentClass);
- }
- Iterable<TypeCheck> checks = requiredChecks[backendClass];
- if (checks.isNotEmpty) {
- features[Tags.typeChecks] =
- '[${(checks.map((c) => c.cls.name).toList()..sort()).join(',')}]';
- }
return features.getText();
}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 4f5250d..5047aea 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -250,7 +250,6 @@
symbol_reserved_word_test/03: RuntimeError
type_hashcode_test: Crash # Assertion failure: Only 2 of 3 arguments have been read from: [HRef(HForeignCode("# ? Object.keys(#) : []")), literal: NullConstant, literal: NullConstant]
uri_base_test: RuntimeError
-uri_query_test: Crash # Assertion failure: Cannot find value local(testQueryParameters#normalizedQuery) in (BoxLocal(_box_0)) for j:signature(testQueryParameters_test.$signature).
[ $compiler == dart2js && $dart2js_with_kernel && $minified && $strong ]
apply3_test: CompileTimeError
@@ -293,7 +292,6 @@
symbol_operator_test/none: RuntimeError
symbol_reserved_word_test/03: RuntimeError
uri_base_test: RuntimeError
-uri_query_test: Crash # Assertion failure: Cannot find value local(testQueryParameters#normalizedQuery) in (BoxLocal(_box_0)) for j:signature(testQueryParameters_test.$signature).
[ $compiler == dart2js && $dart2js_with_kernel && !$strong ]
*: SkipByDesign
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 368ba6a..f4ca4f4 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -277,8 +277,6 @@
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
mixin_issue10216_2_test: RuntimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
mixin_mixin4_test: RuntimeError
mixin_mixin5_test: RuntimeError
mixin_mixin6_test: RuntimeError
@@ -286,7 +284,6 @@
mixin_mixin_bound2_test: RuntimeError
mixin_mixin_bound_test: RuntimeError
mixin_mixin_test: RuntimeError
-mixin_mixin_type_arguments_test: Crash # NoSuchMethodError: The method 'hasSubclass' was called on null.
mixin_of_mixin_test/01: CompileTimeError
mixin_of_mixin_test/02: CompileTimeError
mixin_of_mixin_test/03: CompileTimeError
@@ -642,8 +639,6 @@
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
mixin_issue10216_2_test: RuntimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
mixin_mixin4_test: RuntimeError
mixin_mixin5_test: RuntimeError
mixin_mixin6_test: RuntimeError
@@ -651,7 +646,6 @@
mixin_mixin_bound2_test: RuntimeError
mixin_mixin_bound_test: RuntimeError
mixin_mixin_test: RuntimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/01: CompileTimeError
mixin_of_mixin_test/02: CompileTimeError
mixin_of_mixin_test/03: CompileTimeError
@@ -949,9 +943,6 @@
mixin_illegal_superclass_test/28: MissingCompileTimeError
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/01: CompileTimeError
mixin_of_mixin_test/02: CompileTimeError
mixin_of_mixin_test/03: CompileTimeError
@@ -1259,7 +1250,6 @@
mixin_illegal_superclass_test/28: MissingCompileTimeError
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/01: CompileTimeError
mixin_of_mixin_test/02: CompileTimeError
mixin_of_mixin_test/03: CompileTimeError
@@ -1460,9 +1450,6 @@
mixin_forwarding_constructor4_test/01: MissingCompileTimeError # Issue 15101
mixin_forwarding_constructor4_test/02: MissingCompileTimeError # Issue 15101
mixin_forwarding_constructor4_test/03: MissingCompileTimeError # Issue 15101
-mixin_mixin2_test: RuntimeError # Issue 13109.
-mixin_mixin3_test: RuntimeError # Issue 13109.
-mixin_mixin_type_arguments_test: RuntimeError # Issue 29587
mixin_of_mixin_test: CompileTimeError # Issue 23773
mixin_super_2_test: CompileTimeError # Issue 23773
mixin_super_bound2_test: CompileTimeError # Issue 23773
@@ -1585,18 +1572,19 @@
symbol_conflict_test: RuntimeError # Issue 23857
[ $compiler == dart2js && $minified ]
-cyclic_type2_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-cyclic_type_test/0*: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-f_bounded_quantification4_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-generic_closure_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_generic_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin2_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin3_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin4_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin5_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin6_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin_bound2_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-mixin_mixin_bound_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
-regress_21795_test: RuntimeError, OK # runtimeType.toString not preserved in minified code.
+cyclic_type2_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+cyclic_type_test/0*: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+f_bounded_quantification4_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+generic_closure_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_generic_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin2_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin3_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin4_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin5_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin6_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin_bound2_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin_bound_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+mixin_mixin_type_arguments_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
+regress_21795_test: RuntimeError, OK # Issue 31054: runtimeType.toString not preserved in minified code.
stack_trace_test: RuntimeError, OK # Stack trace not preserved in minified code.
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 2902b0f..f24119b 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -1205,7 +1205,6 @@
super_setter_test: StaticWarning # Issue 28823
switch_case_test/none: CompileTimeError
type_inference_accessor_ref_test/06: MissingCompileTimeError
-type_inference_circularity_test: MissingCompileTimeError
type_promotion_functions_test/01: Pass
type_promotion_functions_test/05: Pass
type_promotion_functions_test/06: Pass
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 22eab3f..d7f5dbe 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -263,9 +263,6 @@
implicit_downcast_during_while_statement_test: RuntimeError
inferrer_synthesized_constructor_test: RuntimeError
malformed2_test/00: MissingCompileTimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_type_parameters_super_test: RuntimeError
type_parameter_test/05: MissingCompileTimeError
typevariable_substitution2_test/02: RuntimeError
@@ -637,8 +634,6 @@
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
mixin_issue10216_2_test: RuntimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
mixin_mixin4_test: RuntimeError
mixin_mixin5_test: RuntimeError
mixin_mixin6_test: RuntimeError
@@ -646,7 +641,6 @@
mixin_mixin_bound2_test: RuntimeError
mixin_mixin_bound_test: RuntimeError
mixin_mixin_test: RuntimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/none: CompileTimeError
mixin_super_2_test/none: CompileTimeError
mixin_super_constructor_named_test/01: MissingCompileTimeError
@@ -1229,8 +1223,6 @@
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
mixin_issue10216_2_test: RuntimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
mixin_mixin4_test: RuntimeError
mixin_mixin5_test: RuntimeError
mixin_mixin6_test: RuntimeError
@@ -1238,7 +1230,6 @@
mixin_mixin_bound2_test: RuntimeError
mixin_mixin_bound_test: RuntimeError
mixin_mixin_test: RuntimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/none: CompileTimeError
mixin_super_2_test/none: CompileTimeError
mixin_super_constructor_named_test/01: MissingCompileTimeError
@@ -1798,9 +1789,6 @@
mixin_invalid_bound_test/08: MissingCompileTimeError
mixin_invalid_bound_test/09: MissingCompileTimeError
mixin_invalid_bound_test/10: MissingCompileTimeError
-mixin_mixin2_test: RuntimeError
-mixin_mixin3_test: RuntimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/none: CompileTimeError
mixin_regress_13688_test: Crash # Assertion failure: Only 2 of 3 arguments have been read from: [HRef(HForeignCode("# ? Object.keys(#) : []")), literal: NullConstant, literal: NullConstant]
mixin_super_2_test/none: CompileTimeError
@@ -2567,7 +2555,6 @@
mixin_invalid_bound_test/08: MissingCompileTimeError
mixin_invalid_bound_test/09: MissingCompileTimeError
mixin_invalid_bound_test/10: MissingCompileTimeError
-mixin_mixin_type_arguments_test: RuntimeError
mixin_of_mixin_test/none: CompileTimeError
mixin_super_2_test/none: CompileTimeError
mixin_super_bound_test/01: MissingCompileTimeError
@@ -3437,9 +3424,6 @@
mixin_invalid_bound_test/08: MissingCompileTimeError
mixin_invalid_bound_test/09: MissingCompileTimeError
mixin_invalid_bound_test/10: MissingCompileTimeError
-mixin_mixin2_test: RuntimeError # Issue 13109.
-mixin_mixin3_test: RuntimeError # Issue 13109.
-mixin_mixin_type_arguments_test: RuntimeError # Issue 29587
mixin_of_mixin_test/none: CompileTimeError
mixin_super_2_test/none: CompileTimeError
mixin_super_bound2_test: CompileTimeError # Issue 23773
@@ -3873,6 +3857,7 @@
mixin_mixin6_test: RuntimeError # Issue 31054
mixin_mixin_bound2_test: RuntimeError # Issue 31054
mixin_mixin_bound_test: RuntimeError # Issue 31054
+mixin_mixin_type_arguments_test: RuntimeError # Issue 31054
[ $compiler == dart2js && !$strong ]
dynamic_test: RuntimeError
diff --git a/tests/language_2/vm/await_synchronous_future_test.dart b/tests/language_2/vm/await_synchronous_future_test.dart
new file mode 100644
index 0000000..9ccf5dc
--- /dev/null
+++ b/tests/language_2/vm/await_synchronous_future_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2018, 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.
+
+// Test that async/await syntax works for synchronously completed futures.
+// Such futures are used by Flutter (see http://dartbug.com/32098).
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+class SynchronousFuture<T> implements Future<T> {
+ final T v;
+
+ SynchronousFuture(this.v);
+
+ Future<E> then<E>(FutureOr<E> f(T v), {Function onError}) {
+ final u = f(v);
+ return u is Future<dynamic>
+ ? (u as Future<dynamic>).then((v) => v as E)
+ : new SynchronousFuture<E>(u);
+ }
+
+ Stream<T> asStream() => throw 'unimplemented';
+ Future<T> catchError(Function onError, {bool test(dynamic error)}) =>
+ throw 'unimplemented';
+ Future<T> timeout(Duration timeLimit, {dynamic onTimeout()}) =>
+ throw 'unimplemented';
+ Future<T> whenComplete(dynamic action()) => throw 'unimplemented';
+}
+
+void main() {
+ var stage = 0;
+ asyncTest(() async {
+ int v;
+ Expect.equals(0, stage++);
+ v = await new SynchronousFuture<int>(stage);
+ Expect.equals(1, v);
+ Expect.equals(1, stage++);
+ v = await new SynchronousFuture<int>(stage);
+ Expect.equals(2, v);
+ Expect.equals(2, stage++);
+ v = await new SynchronousFuture<int>(stage);
+ Expect.equals(3, v);
+ Expect.equals(3, stage++);
+ });
+}
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 21b3a73..87a6273 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -68,6 +68,7 @@
typed_data/int32x4_arithmetic_test/int64: RuntimeError # Issue 1533
typed_data/int64_list_load_store_test: RuntimeError # Issue 10275
typed_data/typed_data_hierarchy_int64_test: RuntimeError # Issue 10275
+typed_data/unmodifiable_typed_data_test: RuntimeError # Issue 10275
[ $compiler != dart2js ]
async/dart2js_uncaught_error_test: Skip # JS-integration only test
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index dd36b16..c90982c 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -130,4 +130,4 @@
typed_data/int32x4_arithmetic_test/int64: RuntimeError # Issue 29922
typed_data/int64_list_load_store_test: RuntimeError # Issue 29922
typed_data/typed_data_hierarchy_int64_test: RuntimeError # Issue 29922
-
+typed_data/unmodifiable_typed_data_test: RuntimeError # Issue 10275
diff --git a/tests/lib_2/typed_data/unmodifiable_typed_data_test.dart b/tests/lib_2/typed_data/unmodifiable_typed_data_test.dart
new file mode 100644
index 0000000..70708c5
--- /dev/null
+++ b/tests/lib_2/typed_data/unmodifiable_typed_data_test.dart
@@ -0,0 +1,165 @@
+// Copyright (c) 2018, 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:typed_data';
+import 'package:expect/expect.dart';
+
+List<int> intList = <int>[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+checkReadable(List<int> list) {
+ for (int i = 0; i < intList.length; i++) {
+ Expect.equals(list[i], intList[i]);
+ }
+}
+
+checkUnmodifiable(List<int> list) {
+ var zero = 0;
+ var one = 1;
+ var two = 2;
+ Expect.throwsUnsupportedError(() => list.add(zero));
+ Expect.throwsUnsupportedError(() => list.addAll([one, two]));
+ Expect.throwsUnsupportedError(() => list.clear());
+ Expect.throwsUnsupportedError(() => list.insert(0, zero));
+ Expect.throwsUnsupportedError(() => list.insertAll(0, [one, two]));
+ Expect.throwsUnsupportedError(() => list.remove(one));
+ Expect.throwsUnsupportedError(() => list.removeAt(0));
+ Expect.throwsUnsupportedError(() => list.removeLast());
+ Expect.throwsUnsupportedError(() => list.removeRange(0, 1));
+ Expect.throwsUnsupportedError(() => list.removeWhere((x) => true));
+ Expect.throwsUnsupportedError(() => list.replaceRange(0, 1, []));
+ Expect.throwsUnsupportedError(() => list.retainWhere((x) => false));
+ Expect.throwsUnsupportedError(() => list[0] = zero);
+ Expect.throwsUnsupportedError(() => list.setRange(0, 1, [one]));
+ Expect.throwsUnsupportedError(() => list.setAll(0, [one]));
+}
+
+int8ListTest() {
+ Int8List i8l = new Int8List.fromList(intList);
+ UnmodifiableInt8ListView list = new UnmodifiableInt8ListView(i8l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+uint8ListTest() {
+ Uint8List u8l = new Uint8List.fromList(intList);
+ UnmodifiableUint8ListView list = new UnmodifiableUint8ListView(u8l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+int16ListTest() {
+ Int16List i16l = new Int16List.fromList(intList);
+ UnmodifiableInt16ListView list = new UnmodifiableInt16ListView(i16l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+uint16ListTest() {
+ Uint16List u16l = new Uint16List.fromList(intList);
+ UnmodifiableUint16ListView list = new UnmodifiableUint16ListView(u16l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+int32ListTest() {
+ Int32List i32l = new Int32List.fromList(intList);
+ UnmodifiableInt32ListView list = new UnmodifiableInt32ListView(i32l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+uint32ListTest() {
+ Uint32List u32l = new Uint32List.fromList(intList);
+ UnmodifiableUint32ListView list = new UnmodifiableUint32ListView(u32l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+int64ListTest() {
+ Int64List i64l = new Int64List.fromList(intList);
+ UnmodifiableInt64ListView list = new UnmodifiableInt64ListView(i64l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+uint64ListTest() {
+ Uint64List u64l = new Uint64List.fromList(intList);
+ UnmodifiableUint64ListView list = new UnmodifiableUint64ListView(u64l);
+ checkReadable(list);
+ checkUnmodifiable(list);
+}
+
+List<double> doubleList = <double>[1.0, 2.0, 3.0, 4.0, 5.0];
+
+checkDoubleReadable(List<double> list) {
+ for (int i = 0; i < doubleList.length; i++) {
+ Expect.equals(list[i], doubleList[i]);
+ }
+}
+
+checkDoubleUnmodifiable(List<double> list) {
+ var zero = 0.0;
+ var one = 1.0;
+ var two = 2.0;
+ Expect.throwsUnsupportedError(() => list.add(zero));
+ Expect.throwsUnsupportedError(() => list.addAll([one, two]));
+ Expect.throwsUnsupportedError(() => list.clear());
+ Expect.throwsUnsupportedError(() => list.insert(0, zero));
+ Expect.throwsUnsupportedError(() => list.insertAll(0, [one, two]));
+ Expect.throwsUnsupportedError(() => list.remove(one));
+ Expect.throwsUnsupportedError(() => list.removeAt(0));
+ Expect.throwsUnsupportedError(() => list.removeLast());
+ Expect.throwsUnsupportedError(() => list.removeRange(0, 1));
+ Expect.throwsUnsupportedError(() => list.removeWhere((x) => true));
+ Expect.throwsUnsupportedError(() => list.replaceRange(0, 1, []));
+ Expect.throwsUnsupportedError(() => list.retainWhere((x) => false));
+ Expect.throwsUnsupportedError(() => list[0] = zero);
+ Expect.throwsUnsupportedError(() => list.setRange(0, 1, [one]));
+ Expect.throwsUnsupportedError(() => list.setAll(0, [one]));
+}
+
+float32ListTest() {
+ Float32List f32l = new Float32List.fromList(doubleList);
+ UnmodifiableFloat32ListView list = new UnmodifiableFloat32ListView(f32l);
+ checkDoubleReadable(list);
+ checkDoubleUnmodifiable(list);
+}
+
+float64ListTest() {
+ Float64List f64l = new Float64List.fromList(doubleList);
+ UnmodifiableFloat64ListView list = new UnmodifiableFloat64ListView(f64l);
+ checkDoubleReadable(list);
+ checkDoubleUnmodifiable(list);
+}
+
+byteDataTest() {
+ ByteBuffer buffer = new Uint8List.fromList(intList).buffer;
+ ByteData bd = new ByteData.view(buffer);
+ UnmodifiableByteDataView ubdv = new UnmodifiableByteDataView(bd);
+
+ Expect.throwsUnsupportedError(() => ubdv.setInt8(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setUint8(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setInt16(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setUint16(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setInt32(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setUint32(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setInt64(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setUint64(0, 0));
+ Expect.throwsUnsupportedError(() => ubdv.setFloat32(0, 0.0));
+ Expect.throwsUnsupportedError(() => ubdv.setFloat64(0, 0.0));
+}
+
+main() {
+ int8ListTest();
+ uint8ListTest();
+ int16ListTest();
+ uint16ListTest();
+ int32ListTest();
+ uint32ListTest();
+ int64ListTest();
+ uint64ListTest();
+ float32ListTest();
+ float64ListTest();
+ byteDataTest();
+}
diff --git a/tools/VERSION b/tools/VERSION
index 1145d30..f6a0fd2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 23
+PRERELEASE 24
PRERELEASE_PATCH 0
diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart
index 0a25554..b2680ca 100644
--- a/tools/testing/dart/command.dart
+++ b/tools/testing/dart/command.dart
@@ -115,6 +115,24 @@
return new MakeSymlinkCommand._(link, target);
}
+ static Command fasta(
+ Uri compilerLocation,
+ Uri outputFile,
+ List<Uri> bootstrapDependencies,
+ Uri executable,
+ List<String> arguments,
+ Map<String, String> environment,
+ Uri workingDirectory) {
+ return new FastaCompilationCommand._(
+ compilerLocation,
+ outputFile,
+ bootstrapDependencies,
+ executable,
+ arguments,
+ environment,
+ workingDirectory);
+ }
+
/// A descriptive name for this command.
final String displayName;
@@ -282,6 +300,73 @@
deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
}
+class FastaCompilationCommand extends CompilationCommand {
+ final Uri _compilerLocation;
+
+ FastaCompilationCommand._(
+ this._compilerLocation,
+ Uri outputFile,
+ List<Uri> bootstrapDependencies,
+ Uri executable,
+ List<String> arguments,
+ Map<String, String> environmentOverrides,
+ Uri workingDirectory)
+ : super._("fasta", outputFile.toFilePath(), true, bootstrapDependencies,
+ executable.toFilePath(), arguments, environmentOverrides,
+ workingDirectory: workingDirectory?.toFilePath());
+
+ @override
+ List<String> get batchArguments {
+ return <String>[
+ _compilerLocation.resolve("batch.dart").toFilePath(),
+ ];
+ }
+
+ @override
+ String get reproductionCommand {
+ String relativizeAndEscape(String argument) {
+ if (workingDirectory != null) {
+ argument = argument.replaceAll(
+ workingDirectory, new Uri.directory(".").toFilePath());
+ }
+ return escapeCommandLineArgument(argument);
+ }
+
+ StringBuffer buffer = new StringBuffer();
+ if (workingDirectory != null && !io.Platform.isWindows) {
+ buffer.write("(cd ");
+ buffer.write(escapeCommandLineArgument(workingDirectory));
+ buffer.write(" ; ");
+ }
+ environmentOverrides?.forEach((key, value) {
+ if (io.Platform.isWindows) {
+ buffer.write("set ");
+ }
+ buffer.write(key);
+ buffer.write("=");
+ buffer.write(relativizeAndEscape(value));
+ if (io.Platform.isWindows) {
+ buffer.write(" &");
+ }
+ buffer.write(" ");
+ });
+ buffer.writeAll(
+ (<String>[executable]
+ ..add(_compilerLocation.toFilePath())
+ ..addAll(arguments))
+ .map(relativizeAndEscape),
+ " ");
+ if (workingDirectory != null) {
+ if (io.Platform.isWindows) {
+ buffer.write(" (working directory: $workingDirectory)");
+ } else {
+ buffer.write(" )");
+ }
+ }
+ return "$buffer";
+ }
+}
+
class VMKernelCompilationCommand extends CompilationCommand {
VMKernelCompilationCommand._(
String outputFile,
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 8cb66ae..ac20f0b 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -85,8 +85,10 @@
case Compiler.specParser:
return new SpecParserCompilerConfiguration(configuration);
+ case Compiler.fasta:
+ return new FastaCompilerConfiguration(configuration);
+
case Compiler.none:
- case Compiler.fasta: // TODO(ahe): Implement a real fasta compiler.
return new NoneCompilerConfiguration(configuration);
}
@@ -161,7 +163,6 @@
List<String> sharedOptions,
List<String> originalArguments,
CommandArtifact artifact) {
- var buildDir = _configuration.buildDirectory;
var args = <String>[];
if (useDfe) {
// DFE+strong configuration is a Dart 2.0 configuration which uses
@@ -1080,3 +1081,117 @@
genKernel, args, environmentOverrides);
}
}
+
+class FastaCompilerConfiguration extends CompilerConfiguration {
+ static const String mimeType = "application/x.dill";
+
+ final Uri _compilerLocation;
+
+ final Uri _plaformDill;
+
+ final Uri _vmExecutable;
+
+ final bool _isLegacy;
+
+ FastaCompilerConfiguration(Configuration configuration)
+ : this._(
+ Uri.base.resolve("pkg/front_end/tool/_fasta/compile.dart"),
+ Uri.base
+ .resolveUri(new Uri.directory(configuration.buildDirectory)),
+ !configuration.isStrong,
+ configuration.useSdk,
+ configuration);
+
+ FastaCompilerConfiguration._(this._compilerLocation, Uri buildDirectory,
+ this._isLegacy, bool useSdk, Configuration configuration)
+ : _plaformDill = (useSdk
+ ? buildDirectory.resolve("dart-sdk/lib/_internal/")
+ : buildDirectory)
+ .resolve(
+ _isLegacy ? "vm_platform.dill" : "vm_platform_strong.dill"),
+ _vmExecutable = useSdk
+ ? buildDirectory.resolve("dart-sdk/bin/dart")
+ : buildDirectory.resolve("dart"),
+ super._subclass(configuration);
+
+ @override
+ bool get useDfe => true;
+
+ @override
+ bool get runRuntimeDespiteMissingCompileTimeError => true;
+
+ @override
+ int get timeoutMultiplier => 1;
+
+ @override
+ bool get hasCompiler => true;
+
+ @override
+ List<Uri> bootstrapDependencies() => <Uri>[_plaformDill];
+
+ @override
+ Command createCommand(String inputFile, String outputFile,
+ List<String> sharedOptions, Map<String, String> environment) {
+ throw "not implemented yet";
+ }
+
+ @override
+ CommandArtifact computeCompilationArtifact(String tempDir,
+ List<String> arguments, Map<String, String> environmentOverrides) {
+ Uri output =
+ Uri.base.resolveUri(new Uri.directory(tempDir)).resolve("out.dill");
+ String outputFileName = output.toFilePath();
+ String vmPath = _vmExecutable.toFilePath();
+ if (Platform.isWindows) {
+ vmPath += ".exe";
+ }
+ List<String> compilerArguments = <String>[
+ "-o",
+ outputFileName,
+ "--platform",
+ _plaformDill.toFilePath(),
+ ]..addAll(arguments);
+
+ return new CommandArtifact(
+ [
+ Command.fasta(
+ _compilerLocation,
+ output,
+ bootstrapDependencies(),
+ _vmExecutable,
+ compilerArguments,
+ environmentOverrides,
+ Uri.base,
+ )
+ ],
+ outputFileName,
+ mimeType,
+ );
+ }
+
+ @override
+ List<String> computeCompilerArguments(
+ List<String> vmOptions,
+ List<String> sharedOptions,
+ List<String> dart2jsOptions,
+ List<String> args) {
+ List<String> arguments = <String>[];
+ for (String argument in args) {
+ if (argument != "--ignore-unrecognized-flags") {
+ arguments.add(argument);
+ }
+ }
+ return arguments;
+ }
+
+ @override
+ List<String> computeRuntimeArguments(
+ RuntimeConfiguration runtimeConfiguration,
+ TestInformation info,
+ List<String> vmOptions,
+ List<String> sharedOptions,
+ List<String> originalArguments,
+ CommandArtifact artifact) {
+ return <String>[];
+ }
+}
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 2cb2950..5c743b3 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -572,6 +572,10 @@
}
class BatchRunnerProcess {
+ /// When true, the command line is passed to the test runner as a
+ /// JSON-encoded list of strings.
+ final bool _jsonCommandLine;
+
Completer<CommandOutput> _completer;
ProcessCommand _command;
List<String> _arguments;
@@ -593,6 +597,8 @@
Timer _timer;
int _testCount = 0;
+ BatchRunnerProcess(this._jsonCommandLine);
+
Future<CommandOutput> runCommand(String runnerType, ProcessCommand command,
int timeout, List<String> arguments) {
assert(_completer == null);
@@ -664,7 +670,11 @@
}
String _createArgumentsLine(List<String> arguments, int timeout) {
- return arguments.join(' ') + '\n';
+ if (_jsonCommandLine) {
+ return "${JSON.encode(arguments)}\n";
+ } else {
+ return arguments.join(' ') + '\n';
+ }
}
void _reportResult() {
@@ -1161,7 +1171,8 @@
.runCommand(command.displayName, command, timeout, command.arguments);
} else if (command is CompilationCommand &&
(command.displayName == 'dartdevc' ||
- command.displayName == 'dartdevk') &&
+ command.displayName == 'dartdevk' ||
+ command.displayName == 'fasta') &&
globalConfiguration.batch) {
return _getBatchRunner(command.displayName)
.runCommand(command.displayName, command, timeout, command.arguments);
@@ -1269,7 +1280,7 @@
if (runners == null) {
runners = new List<BatchRunnerProcess>(maxProcesses);
for (int i = 0; i < maxProcesses; i++) {
- runners[i] = new BatchRunnerProcess();
+ runners[i] = new BatchRunnerProcess(identifier == "fasta");
}
_batchProcesses[identifier] = runners;
}