Version 2.1.1-dev.2.0
Merge commit 'd9944433af2fa90899a1787d48f7e64eb2f129e8' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 165e23f..910c41c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,60 @@
+## 2.1.1-dev.2.0
+
+### Core library changes
+
+#### `dart:core`
+
+* Made `DateTime.parse()` also recognize `,` as a valid decimal separator
+ when parsing from a string. (Issue [35576][])
+
+[35576]: https://github.com/dart-lang/sdk/issues/35576
+
+### Tool Changes
+
+#### Analyzer
+
+* New hints added:
+
+ * `NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR` and
+ `NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW` when a `@literal`
+ const constructor is called in a non-const context (or with `new`).
+
+#### dart2js
+
+* `--fast-startup` is forced on. The flag is silently ignored and will be
+ deprecated and then removed at a later date.
+
+ The alternative 'full emitter' is no longer available. The generated code for
+ `--fast-startup` is optimized to load faster, even though it can be slightly
+ larger.
+
## 2.1.1-dev.1.0
+### Dart VM
+
+In previous releases it was possible to violate static types using dart:mirrors but this bug is fixed now. Meaning that the code below would run without any TypeErrors and print "impossible" output.
+
+```dart
+import 'dart:mirrors';
+
+class A {
+ void method(int v) {
+ if (v != null && v is! int) {
+ print("This should be impossible: expected null or int got ${v}");
+ }
+ }
+}
+
+void main() {
+ final obj = A();
+ reflect(obj).invoke(#method, ['not-an-number']);
+}
+```
+
+Only code that already violates static typing will break.
+
+See Issue [#35611](https://github.com/dart-lang/sdk/issues/35611) for more details.
+
### Tool Changes
#### Analyzer
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 88ffd12..80cdf8e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,7 +11,7 @@
click that icon to report a bug on the page.
* To report an API doc bug,
[create an SDK issue](https://github.com/dart-lang/sdk/issues/new?title=API%20doc%20issue:).
- * Contribute to the Dart developer websites such as [www.dartlang.org](https://www.dartlang.org) (repo: [dart-lang/site-www](https://github.com/dart-lang/site-www)) and [webdev.dartlang.org](https://webdev.dartlang.org) (repo: [dart-lang/site-webdev](https://github.com/dart-lang/site-webdev)). For more information, see [Writing for *.dartlang.org](https://github.com/dart-lang/site-www/wiki/Writing-for-dartlang.org).
+ * Contribute to the Dart developer websites such as [www.dartlang.org](https://www.dartlang.org) (repo: [dart-lang/site-www](https://github.com/dart-lang/site-www)) and [webdev.dartlang.org](https://webdev.dartlang.org) (repo: [dart-lang/site-webdev](https://github.com/dart-lang/site-webdev)). For more information, see [Writing for Dart and Flutter websites](https://github.com/dart-lang/site-shared/wiki/Writing-for-Dart-and-Flutter-websites).
* Improve the API reference docs at [api.dartlang.org](https://api.dartlang.org) by editing doc comments in the [Dart SDK repo](https://github.com/dart-lang/sdk/tree/master/sdk/lib). For more information on how to write API docs, see [Effective Dart: Documentation](https://www.dartlang.org/guides/language/effective-dart/documentation).
## Before you contribute
diff --git a/DEPS b/DEPS
index 2798d2c..f44b9ec 100644
--- a/DEPS
+++ b/DEPS
@@ -161,7 +161,7 @@
"packages": [
{
"package": "dart/dart-sdk/${{platform}}",
- "version": "version:2.1.1-dev.0.1",
+ "version": "version:2.1.1-dev.1.0",
},
],
"dep_type": "cipd",
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 57b7bfa..f7291e8 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -168,15 +168,40 @@
'DEPS file must have only dependencies from allowed hosts.',
long_text=error.output)]
+def _CheckLayering(input_api, output_api):
+ """Run VM layering check.
+
+ This check validates that sources from one layer do not reference sources
+ from another layer accidentally.
+ """
+ # Run only if .cc or .h file was modified.
+ def is_cpp_file(path):
+ return path.endswith('.cc') or path.endswith('.h')
+ if all(not is_cpp_file(f.LocalPath()) for f in input_api.AffectedFiles()):
+ return []
+
+ local_root = input_api.change.RepositoryRoot()
+ layering_check = imp.load_source('layering_check',
+ os.path.join(local_root, 'runtime', 'tools', 'layering_check.py'))
+ errors = layering_check.DoCheck(local_root)
+ if errors:
+ return [output_api.PresubmitError(
+ 'Layering check violation for C++ sources.',
+ long_text='\n'.join(errors))]
+ else:
+ return []
+
def CheckChangeOnCommit(input_api, output_api):
return (_CheckValidHostsInDEPS(input_api, output_api) +
_CheckBuildStatus(input_api, output_api) +
_CheckDartFormat(input_api, output_api) +
- _CheckStatusFiles(input_api, output_api))
+ _CheckStatusFiles(input_api, output_api) +
+ _CheckLayering(input_api, output_api))
def CheckChangeOnUpload(input_api, output_api):
return (_CheckValidHostsInDEPS(input_api, output_api) +
_CheckDartFormat(input_api, output_api) +
- _CheckStatusFiles(input_api, output_api))
+ _CheckStatusFiles(input_api, output_api) +
+ _CheckLayering(input_api, output_api))
diff --git a/docs/language/Makefile b/docs/language/Makefile
index aecfd61..1bdd95a 100644
--- a/docs/language/Makefile
+++ b/docs/language/Makefile
@@ -39,7 +39,7 @@
@echo " clean: remove all generated files"
cleanish:
- rm -f *.aux *.log *.toc *.out *.idx *.ilg
+ rm -f *.aux *.log *.toc *.out
clean: cleanish
- rm -f *.dvi *.pdf *.ind $(HASH) $(LIST)
+ rm -f *.dvi *.pdf $(HASH) $(LIST)
diff --git a/docs/language/dart.sty b/docs/language/dart.sty
index 27433a7..0776ec0 100644
--- a/docs/language/dart.sty
+++ b/docs/language/dart.sty
@@ -184,7 +184,7 @@
{#1}_1\FunctionTypeExtends{#2}_1,\,\ldots,\ %
{#1}_{#3}\FunctionTypeExtends{#2}_{#3}}}
-% Used to specify function types: Same syntax as in source.
+% Used to specify non-generic function types: Same syntax as in source.
% Arguments: Return type, formal parameter declarations.
\newcommand{\FunctionTypeSimple}[2]{\code{\ensuremath{#1}\ \FUNCTION({#2})}}
@@ -199,33 +199,51 @@
\newcommand{\RawFunctionType}[5]{\code{%
\ensuremath{#1}\ \FUNCTION<\FTTypeParameters{#2}{#3}{#4}>({#5})}}
+% Used to specify function type parameter lists with positional optionals.
+% Arguments: Parameter type, number of required parameters,
+% number of optional parameters.
+\newcommand{\FunctionTypePositionalArguments}[3]{%
+ \List{#1}{1}{#2},\ [\List{#1}{{#2}+1}{{#2}+{#3}}]}
+
+\newcommand{\FunctionTypePositionalArgumentsStd}{%
+ \FunctionTypePositionalArguments{T}{n}{k}}
+
% Used to specify function types with positional optionals:
% Arguments: Return type, spacer, type parameter name, bound name,
% number of type parameters, parameter type, number of required parameters,
% number of optional parameters.
\newcommand{\FunctionTypePositional}[8]{%
- \FunctionType{#1}{#2}{#3}{#4}{#5}{\List{#6}{1}{#7},\ %
- [\List{#6}{{#7}+1}{{#7}+{#8}}]}}
+ \FunctionType{#1}{#2}{#3}{#4}{#5}{%
+ \FunctionTypePositionalArguments{#6}{#7}{#8}}}
% Same as \FunctionTypePositional except suitable for inline usage,
% hence omitting the spacer argument.
\newcommand{\RawFunctionTypePositional}[7]{%
- \RawFunctionType{#1}{#2}{#3}{#4}{\List{#5}{1}{#6},\ %
- [\List{#5}{{#6}+1}{{#6}+{#7}}]}}
+ \RawFunctionType{#1}{#2}{#3}{#4}{%
+ \FunctionTypePositionalArguments{#5}{#6}{#7}}}
+
+% Used to specify function type parameter lists with named optionals.
+% Arguments: Parameter type, number of required parameters,
+% name of optional parameters, number of optional parameters.
+\newcommand{\FunctionTypeNamedArguments}[4]{%
+ \List{#1}{1}{#2},\ \{\PairList{#1}{#3}{{#2}+1}{{#2}+{#4}}\}}
+
+\newcommand{\FunctionTypeNamedArgumentsStd}{%
+ \FunctionTypeNamedArguments{T}{n}{x}{k}}
% Used to specify function types with named parameters:
% Arguments: Return type, spacer, type parameter name, bound name,
% number of type parameters, parameter type, number of required parameters,
% name of optional parameters, number of optional parameters.
\newcommand{\FunctionTypeNamed}[9]{%
- \FunctionType{#1}{#2}{#3}{#4}{#5}{\List{#6}{1}{#7},\ %
- \{\PairList{#6}{#8}{{#7}+1}{{#7}+{#9}}\}}}
+ \FunctionType{#1}{#2}{#3}{#4}{#5}{%
+ \FunctionTypePositionalArguments{#6}{#7}{#8}{#9}}}
% Same as \FunctionType except suitable for inline usage, hence omitting
% the spacer argument.
\newcommand{\RawFunctionTypeNamed}[8]{%
- \RawFunctionType{#1}{#2}{#3}{#4}{\List{#5}{1}{#6},\ %
- \{\PairList{#5}{#7}{{#6}+1}{{#6}+{#8}}\}}}
+ \RawFunctionType{#1}{#2}{#3}{#4}{%
+ \FunctionTypePositionalArguments{#5}{#6}{#7}{#8}}}
% Used to specify function types with no optional parameters:
% Arguments: Return type, spacer, type parameter name, bound name,
@@ -237,9 +255,15 @@
\newcommand{\FunctionTypePositionalStd}[1]{%
\FunctionTypePositional{#1}{ }{X}{B}{s}{T}{n}{k}}
+\newcommand{\RawFunctionTypePositionalStd}[1]{%
+ \RawFunctionTypePositional{#1}{X}{B}{s}{T}{n}{k}}
+
\newcommand{\FunctionTypeNamedStd}[1]{%
\FunctionTypeNamed{#1}{ }{X}{B}{s}{T}{n}{x}{k}}
+\newcommand{\RawFunctionTypeNamedStd}[1]{%
+ \RawFunctionTypeNamed{#1}{X}{B}{s}{T}{n}{x}{k}}
+
\newcommand{\FunctionTypeAllRequiredStd}[1]{%
\FunctionTypeAllRequired{#1}{ }{X}{B}{s}{T}{n}}
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index a781f90..2202ec5 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -32,6 +32,10 @@
% - Specify that a getter/setter and a method with the same basename is
% an error, also in the case where a class obtains both from its
% superinterfaces.
+% - Specify the Dart 2.0 rule that you cannot implement, extend or mix-in
+% Function.
+% - Generalize specification of type aliases such that they can denote any
+% type, not just function types.
%
% 2.1
% - Remove 64-bit constraint on integer literals compiled to JavaScript numbers.
@@ -3440,12 +3444,20 @@
\LMHash{}%
It is a compile-time error if the type in the \EXTENDS{} clause of a class $C$ is
-a type variable (\ref{generics}), a type alias (\ref{typedef}),
+a type variable (\ref{generics}), a type alias that does not denote a class (\ref{typedef}),
an enumerated type (\ref{enums}), a malformed type (\ref{staticTypes}),
a deferred type (\ref{staticTypes}), type \DYNAMIC{} (\ref{typeDynamic}),
or type \code{FutureOr<$T$>} for any $T$ (\ref{typeFutureOr}).
-\commentary{
+\commentary{%
+Note that \VOID{} is a reserved word,
+which implies that the same restrictions apply for the type \VOID,
+and similar restrictions are specified for other types like
+\code{Null} (\ref{null}) and
+\code{String} (\ref{strings}).%
+}
+
+\commentary{%
The type parameters of a generic class are available in the lexical scope of the superclass clause, potentially shadowing classes in the surrounding scope.
The following code is therefore illegal and should cause a compile-time error:
}
@@ -3622,7 +3634,7 @@
\LMHash{}%
It is a compile-time error if an element in the type list of the \IMPLEMENTS{} clause of a class $C$ is
-a type variable (\ref{generics}), a type alias (\ref{typedef}),
+a type variable (\ref{generics}), a type alias that does not denote a class (\ref{typedef}),
an enumerated type (\ref{enums}), a malformed type (\ref{staticTypes}),
a deferred type (\ref{staticTypes}), type \DYNAMIC{} (\ref{typeDynamic}),
or type \code{FutureOr<$T$>} for any $T$ (\ref{typeFutureOr}).
@@ -4194,7 +4206,7 @@
$p'$ is the parameter of $m'$ corresponding to $p$,
$p$ has default value $d$ and $p'$ has default value $d'$,
then $d$ and $d'$ must be identical,
- or a compile-time warning occurs.
+ or a static warning occurs.
\item
If $m$ and $m'$ are both getters:
The return type of $m$ must be a subtype of the return type of $m'$.
@@ -4229,7 +4241,7 @@
The mixin application may be used to extend a class per section \ref{classes};
alternatively, a class may be defined as a mixin application as described in this section.
It is a compile-time error if an element in the type list of the \WITH{} clause of a mixin application is
-a type variable (\ref{generics}), a type alias (\ref{typedef}),
+a type variable (\ref{generics}), a type alias that does not denote a class (\ref{typedef}),
an enumerated type (\ref{enums}), a malformed type (\ref{staticTypes}),
a deferred type (\ref{staticTypes}), type \DYNAMIC{} (\ref{typeDynamic}),
or type \code{FutureOr<$T$>} for any $T$ (\ref{typeFutureOr}).
@@ -4319,6 +4331,14 @@
It is a compile-time error if $M$ (respectively, any of $M_1, \ldots, M_k$) is an enumerated type (\ref{enums}) or a malformed type.
It is a compile-time error if a well formed mixin cannot be derived from $M$ (respectively, from each of $M_1, \ldots, M_k$).
+\commentary{%
+Note that \VOID{} is a reserved word,
+which implies that the same restrictions apply for the type \VOID,
+and similar restrictions are specified for other types like
+\code{Null} (\ref{null}) and
+\code{String} (\ref{strings}).%
+}
+
\LMHash{}%
Let $K$ be a class declaration with the same constructors, superclass and interfaces as $C$, and the instance members declared by $M$ (respectively $M_1, \ldots, M_k$).
It is a compile-time error if the declaration of $K$ would cause a compile-time error.
@@ -4457,9 +4477,9 @@
introduces a generic class into the enclosing library scope.
A \IndexCustom{generic class}{class!generic}
is a mapping that accepts a list of actual type arguments and maps them to a class.
-Consider a generic class declaration $G$ named \code{C} with formal type parameter declarations
+Consider a generic class declaration $G$ named $C$ with formal type parameter declarations
$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
-and a parameterized type $T$ of the form \code{C<$T_1, \ldots,\ T_l$>}.
+and a parameterized type $T$ of the form \code{$C$<$T_1, \ldots,\ T_l$>}.
\LMHash{}%
It is a compile-time error if $m \not= l$.
@@ -4467,8 +4487,8 @@
(\ref{superBoundedTypes}).
\LMHash{}%
-Otherwise, said parameterized type \code{C<$T_1, \ldots,\ T_m$>} denotes an application of the generic class declared by $G$ to the type arguments $T_1, \ldots, T_m$.
-This yields a class $C'$ whose members are equivalent to those of a class declaration which is obtained from the declaration of $G$ by replacing each occurrence of $X_j$ by $T_j$.
+Otherwise, said parameterized type \code{$C$<$T_1, \ldots,\ T_m$>} denotes an application of the generic class declared by $G$ to the type arguments $T_1, \ldots, T_m$.
+This yields a class $C'$ whose members are equivalent to those of a class declaration which is obtained from the declaration $G$ by replacing each occurrence of $X_j$ by $T_j$.
\commentary{
% TODO(eernst): make sure this list of properties is complete.
@@ -4478,47 +4498,76 @@
\LMHash{}%
A \IndexCustom{generic type alias}{type alias!generic}
-introduces a mapping from actual type argument lists to types.
-Consider a generic type alias declaration $G$ named \code{F}
-with formal type parameter declarations
-$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
-%% TODO(eernst): 'right hand side' works only for a type alias using `=`.
-%% Explain what "the right hand side" means for an old-style declaration.
-and right hand side $T$.
+is a declaration $D$ of one of the following forms:
+
+\begin{itemize}
+\item \code{$m$ \TYPEDEF{} \id<\TypeParametersStd> = $T$;}
+\item \code{$m$ \TYPEDEF{} $S$?\ \id<\TypeParametersStd>(\\
+ \mbox\quad\PairList{T}{p}{1}{n},\ [\PairList{T}{p}{n+1}{n+k}]);}
+\item \code{$m$ \TYPEDEF{} $S$?\ \id<\TypeParametersStd>(\\
+ \mbox\quad\PairList{T}{p}{1}{n},\ \{\PairList{T}{p}{n+1}{n+k}\});}
+\end{itemize}
+
+\noindent
+where $m$ is derived from \synt{metadata},
+$T$ is a type,
+and \code{$S$?} is a type or the empty string.
+Let $S'$ be \code{$S$?} if it is a type, otherwise let $S'$ be \DYNAMIC.
+The associated function type of $D$, call it $F$, is, respectively:
+
+\begin{itemize}
+\item $T$
+\item \FunctionTypeSimple{S'}{\FunctionTypePositionalArgumentsStd}
+\item \FunctionTypeSimple{S'}{\FunctionTypeNamedArgumentsStd}
+\end{itemize}
\LMHash{}%
-Under the assumption that $X_1,\ \ldots,\ X_m$ are types such that
-$X_j <: B_j$, for all $j \in 1 .. m$,
-it is a compile-time error if any type in $T$ is not regular-bounded.
+$D$ introduces a mapping from actual type argument lists to types.
+Under the assumption that \List{X}{1}{s} are types such that
+$X_j <: B_j$, for all $j \in 1 .. s$,
+it is a compile-time error if $T$ is not regular-bounded,
+and it is a compile-time error if any type occurring in $T$ is not well-bounded.
\commentary{
This means that the bounds declared for
the formal type parameters of a generic type alias
must be such that when they are satisfied,
-the bounds that pertain to any type in the body must also be satisfied.
+the bounds that pertain to the body are also satisfied,
+and a type occurring as a subterm of the body can violate its bounds,
+but only if it is a correct super-bounded type.
}
\LMHash{}%
-Let $G$, \code{F}, and $X_1,\ \ldots,\ X_m$ be as defined above,
-let $T_1,\ \ldots,\ T_l$ be types,
-and let $S$ be the parameterized type \code{F<$T_1, \ldots,\ T_l$>}.
-It is a compile-time error if $m \not= l$.
-It is a compile-time error if $S$ is not well-bounded
+Moreover,
+let $T_1,\ \ldots,\ T_l$ be types
+and let $U$ be the parameterized type \code{\id<$T_1, \ldots,\ T_l$>}
+in a location where \id{} denotes $D$.
+It is a compile-time error if $l \not= s$.
+It is a compile-time error if $U$ is not well-bounded
(\ref{superBoundedTypes}).
\LMHash{}%
-Otherwise, said parameterized type
-\code{F<$T_1, \ldots,\ T_m$>}
-denotes an application of the mapping denoted by $G$ to the type arguments
-$T_1, \ldots, T_m$.
-This yields the type
-$[T_1/X_1, \ldots, T_m/X_m]T$.
+Otherwise,
+$U$ denotes an application of the mapping denoted by $D$ to the type arguments
+$T_1, \ldots, T_s$,
+yielding the type
+$[T_1/X_1, \ldots, T_s/X_s]F$.
+
+\commentary{%
+Note that the type alias syntax without \syntax{`='}
+can only express function types,
+and it cannot express the type of a generic function.
+When such a type alias is generic,
+it always expresses a family of non-generic function types.
+These restrictions exist because that syntax was defined
+before generic functions were added to Dart.%
+}
\rationale{
The requirement that satisfaction of the bounds on
-the formal type parameters of a generic type alias $G$
+the formal type parameters of a generic type alias $D$
must imply satisfaction of all bounds pertaining to
-every type that occurs in the body of $G$
+every type that occurs in the body of $D$
limits the expressive power of generic type aliases.
However, it would require the constraints on formal type parameters
to be expressed in a much more powerful language
@@ -7170,7 +7219,8 @@
a class or a parameterized type accessible in the current scope,
or if $T$ is a parameterized type which is not a class.
\commentary{
-For instance, \code{\NEW{} F<int>()} is an error if \code{F} is a type alias.
+For instance, \code{\NEW{} F<int>()} is an error if \code{F} is a type alias
+that does not denote a class.
}
\LMHash{}%
@@ -8799,7 +8849,7 @@
Let $T$ be the static type of $e$.
It is a compile-time error if $T$ does not have a method or getter named \id{}
unless $T$ is \DYNAMIC{},
-or $T$ is \FUNCTION{} and \id{} is \code{call}.
+or $T$ is \FUNCTION{} and \id{} is \CALL{}.
The static type of $i$ is:
\begin{itemize}
@@ -11427,7 +11477,7 @@
\end{itemize}
\commentary{
-In other words, a warning will be emitted if a switch statement over an enum is not exhaustive.
+In other words, a static warning will be emitted if a switch statement over an enum is not exhaustive.
}
@@ -12773,29 +12823,94 @@
\LMLabel{staticTypes}
\LMHash{}%
-Type annotations are used in variable declarations (\ref{variables}) (including formal parameters (\ref{formalParameters})), in the return types of functions (\ref{functions}) and in the bounds of type variables.
+Type annotations can occur in variable declarations (\ref{variables}),
+including formal parameters (\ref{formalParameters}),
+in the return types of functions (\ref{functions}),
+and in the bounds of type variables (\ref{generics}).
Type annotations are used during static checking and when running programs.
+Types are specified using the following grammar rules.
+
+%% TODO(eernst): The following non-terminal is currently undefined (it will
+%% be defined when more rules are transferred from Dart.g): <typeIdentifier>.
+%% The precise rules are slightly different than the following sentence, but
+%% we should be able to make do with that for now.
+\LMHash{}%
+In the grammar rules below, \synt{typeIdentifier} denotes an identifier which can be
+the name of a type, that is, it denotes an \synt{IDENTIFIER} which is not a
+\synt{BUILT\_IN\_IDENTIFIER}.
+
+%% TODO(eernst): The following non-terminals are currently unused (they will
+%% be used when we transfer more grammar rules from Dart.g): <typeNotVoid>
+%% and <typeNotVoidNotFunctionList>. They are used in the syntax for
+%% \EXTENDS{}, \WITH{}, \IMPLEMENTS{} syntax and for mixin applications
+%% in Dart.g, and it seems likely that we will use them here as well.
+
+\commentary{
+Non-terminals with names of the form \synt{\ldots{}NotFunction}
+derive terms which are types that are not function types.
+Note that it \emph{does} derive the type \FUNCTION{},
+which is not itself a function type,
+but it is the least upper bound of all function types.
+}
\begin{grammar}
-<type> ::= <typeNotVoid> | \VOID{}
+<type> ::= <functionTypeTails>
+ \alt <typeNotFunction> <functionTypeTails>
+ \alt <typeNotFunction>
-<typeNotVoid> ::= <typeName> <typeArguments>?
+<typeNotFunction> ::= <typeNotVoidNotFunction>
+ \alt \VOID{}
-<typeName> ::= <qualified>
+<typeNotVoidNotFunction> ::= <typeName> <typeArguments>?
+ \alt \FUNCTION{}
+
+<typeName> ::= <typeIdentifier> (`.' <typeIdentifier>)?
<typeArguments> ::= `<' <typeList> `>'
<typeList> ::= <type> (`,' <type>)*
+
+<typeNotVoidNotFunctionList> ::=
+ <typeNotVoidNotFunction> (`,' <typeNotVoidNotFunction>)*
+
+<typeNotVoid> ::= <functionType>
+ \alt <typeNotVoidNotFunction>
+
+<functionType> ::= <functionTypeTails>
+ \alt <typeNotFunction> <functionTypeTails>
+
+<functionTypeTails> ::= <functionTypeTail> <functionTypeTails>
+ \alt <functionTypeTail>
+
+<functionTypeTail> ::= \FUNCTION{} <typeParameters>? <parameterTypeList>
+
+<parameterTypeList> ::= `(' `)'
+ \alt `(' <normalParameterTypes> `,' <optionalParameterTypes> `)'
+ \alt `(' <normalParameterTypes> `,'? `)'
+ \alt `(' <optionalParameterTypes> `)'
+
+<normalParameterTypes> ::= <normalParameterType> (`,' <normalParameterType>)*
+
+<normalParameterType> ::= <typedIdentifier>
+ \alt <type>
+
+<optionalParameterTypes> ::= <optionalPositionalParameterTypes>
+ \alt <namedParameterTypes>
+
+<optionalPositionalParameterTypes> ::= `[' <normalParameterTypes> `,'? `]'
+
+<namedParameterTypes> ::=
+ `\{' <typedIdentifier> (`,' <typedIdentifier>)* `,'? `\}'
+
+<typedIdentifier> ::= <type> <identifier>
\end{grammar}
\LMHash{}%
-A Dart implementation must provide a static checker that detects and reports exactly those situations this specification identifies as compile-time errors,
+A Dart implementation must provide a static checker that detects and reports
+exactly those situations this specification identifies as compile-time errors,
and only those situations.
-However:
-\begin{itemize}
-\item Running the static checker on a program $P$ is not required for compiling and running $P$.
-\item Running the static checker on a program $P$ must not prevent successful compilation of $P$ nor may it prevent the execution of $P$, regardless of whether any compile-time errors occur.
-\end{itemize}
+Similarly, the static checker must emit static warnings
+for at least the situations specified as such in this specification.
\commentary{
Nothing precludes additional tools that implement alternative static analyses (e.g., interpreting the existing type annotations in a sound manner such as either non-variant generics, or inferring declaration based variance from the actual declarations).
@@ -12956,7 +13071,7 @@
\}
\end{dartCode}
-\LMHash{}
+\LMHash{}%
\commentary{
Instances of \code{Type} can be obtained in various ways,
for example by using reflection,
@@ -12964,7 +13079,7 @@
or by evaluating a \emph{type literal} expression.
}
-\LMHash{}
+\LMHash{}%
An expression is a \emph{type literal} if it is an identifier,
or a qualified identifier,
which denotes a class, mixin or type alias declaration, or it is
@@ -12975,53 +13090,126 @@
A constant type literal is a constant expression (\ref{constants}).
}
-\subsection{Type Declarations}
-\LMLabel{typeDeclarations}
-
-
-\subsubsection{Typedef}
+\subsection{Type Aliases}
\LMLabel{typedef}
\LMHash{}%
A \Index{type alias} declares a name for a type expression.
+\commentary{
+It is common to use the phrase ``a typedef'' for such a declaration,
+because of the prominent occurrence of the token \TYPEDEF.
+}
+
+% TODO(eernst): We include <metadata> in <typeAlias> even though it is not
+% there in Dart.g, because <libraryDefinition> in Dart.g allows metadata
+% before every <topLevelDefinition>, but that's not yet been transferred to
+% this document. So we'll need to remove the <metadata> below _when_ it is
+% made redundant by changing <libraryDefinition> to be like in Dart.g.
+
\begin{grammar}
-<typeAlias> ::= <metadata> \TYPEDEF{} <typeAliasBody>
+<typeAlias> ::=
+ <metadata> \TYPEDEF{} <typeIdentifier> <typeParameters>? `=' <type> `;'
+ \alt <metadata> \TYPEDEF{} <functionTypeAlias>
-<typeAliasBody> ::= <functionTypeAlias>
-
-<functionTypeAlias> ::= \gnewline{}
- <functionPrefix> <typeParameters>? <formalParameterList> `;'
+<functionTypeAlias> ::= <functionPrefix> <formalParameterPart> `;'
<functionPrefix> ::= <type>? <identifier>
\end{grammar}
-% TODO(eernst): Introduce new type aliases and new function type syntax, then
-% include support for generic functions here.
+\LMHash{}%
+The effect of a type alias of the form
+\code{\TYPEDEF{} \id{} = $T$;}
+declared in a library $L$ is to introduce the name \id{} into the scope of $L$,
+bound to the type $T$.
\LMHash{}%
The effect of a type alias of the form
-\code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}]$)}
+\noindent
+\code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}]$);}
\noindent
declared in a library $L$ is to introduce the name \id{} into the scope of $L$, bound to the function type
-$(T_1, \ldots,\ T_n, [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k} p_{n+k}]) \rightarrow T$.
+\FunctionTypeSimple{T}{\List{T}{1}{n},\ [\List{T}{n+1}{n+k}]}.
+
+\LMHash{}%
The effect of a type alias of the form
-\code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ \{T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}\}$)}
+\noindent
+\code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ \{T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}\}$);}
\noindent
declared in a library $L$ is to introduce the name \id{} into the scope of $L$, bound to the function type
-$(T_1, \ldots,\ T_n, \{T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}\}) \rightarrow T$.
+\FunctionTypeSimple{T}{\List{T}{1}{n},\ \{\PairList{T}{p}{n+1}{n+k}\}}.
+
+\LMHash{}%
In either case, if{}f no return type is specified, it is taken to be \DYNAMIC{}.
Likewise, if a type annotation is omitted on a formal parameter, it is taken to be \DYNAMIC{}.
\LMHash{}%
-It is a compile-time error if any default values are specified in the signature of a function type alias.
+It is a compile-time error if any default values are specified
+in the signature of a function type in a type alias.
%A typedef may only refer to itself via the bounds of its generic parameters.
-Any self reference in a typedef, either directly, or recursively via another typedef, is a compile-time error.
-%via a chain of references that does not include a class declaration.
+Any self reference in a type alias,
+either directly or recursively via another type declaration,
+is a compile-time error.
+
+\commentary{
+This kind of error may also arise when type arguments have been
+omitted in the program, but are added during static analysis
+via instantiation to bound
+(\ref{instantiationToBound})
+or via type inference
+(\commentary{which will be specified later (\ref{overview})}).
+}
+
+\commentary{%
+A type alias can be used as a type annotation,
+as a return type or parameter type in a function declaration,
+in a function type,
+as a type argument,
+in a type test,
+in a type cast,
+and in an \ON{} clause of a \TRY{} statement.
+
+Consider the case where the body of a given type alias $F$
+is a \synt{typeName} that denotes a non-generic class,
+or it is a parameterized type that starts with
+a \synt{typeName} that denotes a generic class,
+or one of these cases occur indirectly via another type alias.
+In this case $F$ or a parameterized type that starts with $F$,
+whichever is not an error,
+can also be used to name a constructor in an instance creation expression
+(\ref{instanceCreation}),
+and it can be used as a superclass, mixin, or superinterface
+(\ref{superclasses}, \ref{superinterfaces}, \ref{mixinApplication}).
+Moreover, $F$ or a parameterized type that starts with $F$,
+whichever is not an error,
+can be used to invoke static methods of the denoted class.
+}
+
+\rationale{%
+This indirectly allows an invocation of a static method to pass
+a list of actual type arguments to the class.
+This is currently an error when it occurs directly
+(e.g., \code{List<int>.castFrom(xs)}).
+But it may be part of a future language extension to allow
+static methods to use the type parameters declared by the enclosing class,
+in which case both the direct and indirect approach will be allowed.
+At that time,
+existing invocations where type arguments are passed indirectly will not break,
+because it is currently an error for a static method to depend on the value
+of a formal type parameter of the enclosing class.
+}
+
+%% TODO(eernst): Move specification of generic type aliases to this
+%% section, change the non-generic case to a special case.
+\commentary{
+The generic variants of type alias declarations are specified
+in the section about generics
+(\ref{generics}).
+}
\subsection{Subtypes}
@@ -13680,33 +13868,26 @@
\subsection{Function Types}
\LMLabel{functionTypes}
-%% TODO(eernst): This section is heavily updated in CL 81263 as well as
-%% in this CL 84027. Double-check the merge when 81263 has been landed.
-%% In particular, we do _not_ change the notation in this CL to use the
-%% function types that we use in section 'Subtypes', that's done in 81263.
-
\LMHash{}%
Function types come in two variants:
\begin{enumerate}
\item
-The types of functions that only have positional parameters.
-These have the general form
-
-\code{<$X_1\ \EXTENDS\ B_1, \ldots,\ X_s\ \EXTENDS\ B_s$>}
-
-\code{($T_1, \ldots,\ T_n,\ $[$T_{n+1}, \ldots,\ T_{n+k}$]) $ \rightarrow T$}.
+ The types of functions that only have positional parameters.
+ These have the general form
+ \FunctionTypePositionalStd{T}.
\item
-The types of functions with named parameters.
-These have the general form
-
-\code{<$X_1\ \EXTENDS\ B_1, \ldots,\ X_s\ \EXTENDS\ B_s$>}
-
-\code{($T_1, \ldots,\ T_n,\ $\{$T_{x_1}\ x_1, \ldots,\ T_{x_k}\ x_k$\}) $ \rightarrow T$}.
+ The types of functions with named parameters.
+ These have the general form
+ \FunctionTypeNamedStd{T}.
\end{enumerate}
\commentary{
-Note that the non-generic case is covered by using $s = 0$,
-in which case the type parameter declarations are omitted (\ref{generics}).
+Note that the non-generic case is covered by having $s = 0$,
+in which case the type parameter declarations are omitted
+(\ref{generics}).
+The case with no optional parameters is covered by having $k = 0$;
+note that all rules involving function types of the two kinds
+coincide in this case.
}
\LMHash{}%
@@ -13722,13 +13903,49 @@
}
\LMHash{}%
-A function object is always an instance of some class that implements the class \FUNCTION{}.
+A function object is always an instance of some class that implements the class \FUNCTION{} (\ref{functionType}).
\commentary{%
Consequently, all function types are subtypes of \FUNCTION{}
(\ref{subtypes}).
}
+\subsection{Type \FUNCTION{}}
+\LMLabel{functionType}
+
+\LMHash{}%
+The built-in class \FUNCTION{} is a supertype of all function types
+(\ref{functionTypes}).
+It is impossible to extend, implement, or mix in the class \FUNCTION{}.
+
+\LMHash{}%
+If a class declaration or mixin application has \FUNCTION{} as superclass,
+it instead uses \code{Object} as superclass.
+
+\LMHash{}%
+If a class or mixin declaration implements \FUNCTION{}, it has no effect.
+It is as if the \FUNCTION was removed from the \code{implements} clause
+(and if it's the only implemented interface, the entire clause is removed).
+The resulting class or mixin interface
+does not have \FUNCTION{} as a superinterface.
+
+\LMHash{}%
+If a mixin application mixes \FUNCTION{} onto a superclass, it follows the
+normal rules for mixin-application, but since the result of that mixin
+application is equivalent to a class with \code{implements Function}, and
+that clause has no effect, the resulting class also does not
+implement \FUNCTION{}. \commentary{The \FUNCTION{} class declares no
+concrete instance members, so the mixin application creates a sub-class
+of the superclass with no new members and no new interfaces.}
+
+\rationale{Since using \FUNCTION{} in these ways has no effect, it would be
+reasonable to disallow it completely, like we do extending, implementing or
+mixing in types like \code{int} or \code{String}.
+For backwards compatibility with Dart 1 programs,
+the syntax is allowed to remain, even if it has no effect.
+Tools may choose to warn users that their code has no effect.}
+
+
\subsection{Type \DYNAMIC{}}
\LMLabel{typeDynamic}
@@ -13826,7 +14043,7 @@
function expression invocation where an entity of static type \code{Type} is
invoked. Note that it could actually succeed: An overriding implementation
of \code{runtimeType} could return an instance whose dynamic type is a subtype
- of \code{Type} that has a \code{call} method.
+ of \code{Type} that has a \CALL{} method.
We decided to make it an error because it is likely to be a mistake,
especially in cases like \code{$d$.hashCode()}
where a developer might have forgotten that \code{hashCode} is a getter.
@@ -14442,6 +14659,9 @@
% Function types
+%% TODO(eernst): This section should use the new syntax for function types
+%% (\FunctionTypePositionalStd{} etc.); these updates are made by CL 84908.
+
\LMHash{}%
The least upper bound of a function type and an interface type $T$ is the least upper bound of \FUNCTION{} and $T$.
Let $F$ and $G$ be function types.
diff --git a/docs/language/informal/generic-function-type-alias.md b/docs/language/informal/generic-function-type-alias.md
index f03c5cc..2318146 100644
--- a/docs/language/informal/generic-function-type-alias.md
+++ b/docs/language/informal/generic-function-type-alias.md
@@ -1,6 +1,6 @@
# Feature: Generic Function Type Alias
-**Status**: Implemented.
+**Status**: Background material. Normative text is now in dartLangSpec.tex.
**This document** is an informal specification of a feature supporting the
definition of function type aliases using a more expressive syntax than the
diff --git a/pkg/analysis_server/benchmark/benchmarks.dart b/pkg/analysis_server/benchmark/benchmarks.dart
index 713177c..1448599 100644
--- a/pkg/analysis_server/benchmark/benchmarks.dart
+++ b/pkg/analysis_server/benchmark/benchmarks.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/benchmark/integration/driver.dart b/pkg/analysis_server/benchmark/integration/driver.dart
index da92839..f3b7032 100644
--- a/pkg/analysis_server/benchmark/integration/driver.dart
+++ b/pkg/analysis_server/benchmark/integration/driver.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/integration/input_converter.dart b/pkg/analysis_server/benchmark/integration/input_converter.dart
index fdf4066..c28b9f9 100644
--- a/pkg/analysis_server/benchmark/integration/input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/input_converter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
index 0058fdf..85f6a7f 100644
--- a/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/instrumentation_input_converter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/integration/local_runner.dart b/pkg/analysis_server/benchmark/integration/local_runner.dart
index 28ef5bb..8986e1f 100644
--- a/pkg/analysis_server/benchmark/integration/local_runner.dart
+++ b/pkg/analysis_server/benchmark/integration/local_runner.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart b/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart
index 2ef5e6a..cb4bd81 100644
--- a/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/log_file_input_converter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/integration/main.dart b/pkg/analysis_server/benchmark/integration/main.dart
index 2182796..a1be95e 100644
--- a/pkg/analysis_server/benchmark/integration/main.dart
+++ b/pkg/analysis_server/benchmark/integration/main.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/integration/operation.dart b/pkg/analysis_server/benchmark/integration/operation.dart
index 75cf2a7..470756b 100644
--- a/pkg/analysis_server/benchmark/integration/operation.dart
+++ b/pkg/analysis_server/benchmark/integration/operation.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
index 0c460c2..56aca72 100644
--- a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
+++ b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
index 3d0957e..0634a11 100644
--- a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
+++ b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/bin/server.dart b/pkg/analysis_server/bin/server.dart
index 8c669ff..9dedc84 100644
--- a/pkg/analysis_server/bin/server.dart
+++ b/pkg/analysis_server/bin/server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 713507e..bf31832 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- 1.21.1
+ 1.22.1
</h1>
<p>
This document contains a specification of the API provided by the
@@ -2918,6 +2918,12 @@
is only defined if the displayed text should be different than the
completion. Otherwise it is omitted.
</p>
+ </dd><dt class="field"><b>elementUri: String<span style="color:#999999"> (optional)</span></b></dt><dd>
+
+ <p>
+ The URI of the element corresponding to this suggestion. It will be
+ set whenever analysis server is able to compute it.
+ </p>
</dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
<p>
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 55623c1..8e0f2a2 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -474,6 +474,9 @@
class CodeActionOptions implements ToJsonable {
CodeActionOptions(this.codeActionKinds);
static CodeActionOptions fromJson(Map<String, dynamic> json) {
+ if (CodeActionRegistrationOptions.canParse(json)) {
+ return CodeActionRegistrationOptions.fromJson(json);
+ }
final codeActionKinds = json['codeActionKinds']
?.map((item) => item != null ? CodeActionKind.fromJson(item) : null)
?.cast<CodeActionKind>()
@@ -2548,11 +2551,7 @@
}
class DidChangeConfigurationParams implements ToJsonable {
- DidChangeConfigurationParams(this.settings) {
- if (settings == null) {
- throw 'settings is required but was not provided';
- }
- }
+ DidChangeConfigurationParams(this.settings);
static DidChangeConfigurationParams fromJson(Map<String, dynamic> json) {
final settings = json['settings'];
return new DidChangeConfigurationParams(settings);
@@ -2563,8 +2562,7 @@
Map<String, dynamic> toJson() {
Map<String, dynamic> __result = {};
- __result['settings'] =
- settings ?? (throw 'settings is required but was not set');
+ __result['settings'] = settings;
return __result;
}
@@ -3932,6 +3930,7 @@
/// Defined by the protocol.
static const RequestCancelled = const ErrorCodes(-32800);
+ static const ContentModified = const ErrorCodes(-32801);
Object toJson() => _value;
@@ -4682,12 +4681,7 @@
/// The capabilities provided by the client (editor or tool)
final ClientCapabilities capabilities;
- /// Client provided initialization options. Usually these are options that
- /// could equally be command line options passed when starting the server.
- /// This property shouldn't be used to pass any user configuration to the
- /// server. If a user configuration is needed the server should use
- /// `workspace/configuration` requests together with dynamic registration to
- /// obtain them.
+ /// User provided initialization options.
final dynamic initializationOptions;
/// The process Id of the parent process that started the server. Is null if
@@ -4961,6 +4955,9 @@
if (targetRange == null) {
throw 'targetRange is required but was not provided';
}
+ if (targetSelectionRange == null) {
+ throw 'targetSelectionRange is required but was not provided';
+ }
}
static LocationLink fromJson(Map<String, dynamic> json) {
final originSelectionRange = json['originSelectionRange'] != null
@@ -5108,7 +5105,7 @@
/// https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting
///
/// Here is an example how such a string can be constructed using JavaScript /
-/// TypeScript: ```ts let markdown: MarkdownContent = {
+/// TypeScript: ```typescript let markdown: MarkdownContent = {
///
/// kind: MarkupKind.Markdown,
/// value: [
@@ -5222,6 +5219,15 @@
}
}
static Message fromJson(Map<String, dynamic> json) {
+ if (RequestMessage.canParse(json)) {
+ return RequestMessage.fromJson(json);
+ }
+ if (ResponseMessage.canParse(json)) {
+ return ResponseMessage.fromJson(json);
+ }
+ if (NotificationMessage.canParse(json)) {
+ return NotificationMessage.fromJson(json);
+ }
final jsonrpc = json['jsonrpc'];
return new Message(jsonrpc);
}
@@ -5685,9 +5691,13 @@
/// The label of this parameter information.
///
/// Either a string or an inclusive start and exclusive end offsets within its
- /// containing signature label. (see SignatureInformation.label). *Note*: A
- /// label of type string must be a substring of its containing signature
- /// label.
+ /// containing signature label. (see SignatureInformation.label). The offsets
+ /// are based on a UTF-16 string representation as `Position` and `Range`
+ /// does.
+ ///
+ /// *Note*: a label of type string should be a substring of its containing
+ /// signature label. Its intended use case is to highlight the parameter label
+ /// part in the `SignatureInformation.label`.
final String label;
Map<String, dynamic> toJson() {
@@ -5910,6 +5920,60 @@
String toString() => jsonEncoder.convert(toJson());
}
+class RangeAndPlaceholder implements ToJsonable {
+ RangeAndPlaceholder(this.range, this.placeholder) {
+ if (range == null) {
+ throw 'range is required but was not provided';
+ }
+ if (placeholder == null) {
+ throw 'placeholder is required but was not provided';
+ }
+ }
+ static RangeAndPlaceholder fromJson(Map<String, dynamic> json) {
+ final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+ final placeholder = json['placeholder'];
+ return new RangeAndPlaceholder(range, placeholder);
+ }
+
+ final String placeholder;
+ final Range range;
+
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> __result = {};
+ __result['range'] = range ?? (throw 'range is required but was not set');
+ __result['placeholder'] =
+ placeholder ?? (throw 'placeholder is required but was not set');
+ return __result;
+ }
+
+ static bool canParse(Object obj) {
+ return obj is Map<String, dynamic> &&
+ obj.containsKey('range') &&
+ Range.canParse(obj['range']) &&
+ obj.containsKey('placeholder') &&
+ obj['placeholder'] is String;
+ }
+
+ @override
+ bool operator ==(other) {
+ if (other is RangeAndPlaceholder) {
+ return range == other.range && placeholder == other.placeholder && true;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, range.hashCode);
+ hash = JenkinsSmiHash.combine(hash, placeholder.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+
+ @override
+ String toString() => jsonEncoder.convert(toJson());
+}
+
class ReferenceContext implements ToJsonable {
ReferenceContext(this.includeDeclaration) {
if (includeDeclaration == null) {
@@ -6689,14 +6753,15 @@
Map<String, dynamic> toJson() {
Map<String, dynamic> __result = {};
__result['id'] = id;
- if (result != null) {
- __result['result'] = result;
- }
- if (error != null) {
- __result['error'] = error;
- }
__result['jsonrpc'] =
jsonrpc ?? (throw 'jsonrpc is required but was not set');
+ if (error != null && result != null) {
+ throw 'result and error cannot both be set';
+ } else if (error != null) {
+ __result['error'] = error;
+ } else {
+ __result['result'] = result;
+ }
return __result;
}
@@ -7202,13 +7267,7 @@
static ServerCapabilitiesWorkspaceFolders fromJson(
Map<String, dynamic> json) {
final supported = json['supported'];
- final changeNotifications = json['changeNotifications'] is String
- ? new Either2<String, bool>.t1(json['changeNotifications'])
- : (json['changeNotifications'] is bool
- ? new Either2<String, bool>.t2(json['changeNotifications'])
- : (json['changeNotifications'] == null
- ? null
- : (throw '''${json['changeNotifications']} was not one of (String, bool)''')));
+ final changeNotifications = json['changeNotifications'];
return new ServerCapabilitiesWorkspaceFolders(
supported, changeNotifications);
}
@@ -7219,7 +7278,7 @@
/// notification is registered on the client side. The ID can be used to
/// unregister for these events using the `client/unregisterCapability`
/// request.
- final Either2<String, bool> changeNotifications;
+ final bool changeNotifications;
/// The server has support for workspace folders
final bool supported;
@@ -8106,7 +8165,9 @@
/// Capabilities specific to the `textDocument/declaration`
final TextDocumentClientCapabilitiesDeclaration declaration;
- /// Capabilities specific to the `textDocument/definition`
+ /// Capabilities specific to the `textDocument/definition`.
+ ///
+ /// Since 3.14.0
final TextDocumentClientCapabilitiesDefinition definition;
/// Capabilities specific to the `textDocument/documentHighlight`
@@ -8793,6 +8854,8 @@
final bool dynamicRegistration;
/// The client supports additional metadata in the form of declaration links.
+ ///
+ /// Since 3.14.0
final bool linkSupport;
Map<String, dynamic> toJson() {
@@ -9230,6 +9293,8 @@
final bool dynamicRegistration;
/// The client supports additional metadata in the form of definition links.
+ ///
+ /// Since 3.14.0
final bool linkSupport;
Map<String, dynamic> toJson() {
@@ -9323,6 +9388,8 @@
/// The client supports processing label offsets instead of a simple label
/// string.
+ ///
+ /// Since 3.14.0
final bool labelOffsetSupport;
Map<String, dynamic> toJson() {
@@ -9803,6 +9870,8 @@
final bool dynamicRegistration;
/// The client supports additional metadata in the form of definition links.
+ ///
+ /// Since 3.14.0
final bool linkSupport;
Map<String, dynamic> toJson() {
@@ -9981,6 +10050,9 @@
}
}
static TextDocumentIdentifier fromJson(Map<String, dynamic> json) {
+ if (VersionedTextDocumentIdentifier.canParse(json)) {
+ return VersionedTextDocumentIdentifier.fromJson(json);
+ }
final uri = json['uri'];
return new TextDocumentIdentifier(uri);
}
@@ -10114,6 +10186,12 @@
}
}
static TextDocumentPositionParams fromJson(Map<String, dynamic> json) {
+ if (CompletionParams.canParse(json)) {
+ return CompletionParams.fromJson(json);
+ }
+ if (ReferenceParams.canParse(json)) {
+ return ReferenceParams.fromJson(json);
+ }
final textDocument = json['textDocument'] != null
? TextDocumentIdentifier.fromJson(json['textDocument'])
: null;
@@ -10170,6 +10248,33 @@
class TextDocumentRegistrationOptions implements ToJsonable {
TextDocumentRegistrationOptions(this.documentSelector);
static TextDocumentRegistrationOptions fromJson(Map<String, dynamic> json) {
+ if (TextDocumentChangeRegistrationOptions.canParse(json)) {
+ return TextDocumentChangeRegistrationOptions.fromJson(json);
+ }
+ if (TextDocumentSaveRegistrationOptions.canParse(json)) {
+ return TextDocumentSaveRegistrationOptions.fromJson(json);
+ }
+ if (CompletionRegistrationOptions.canParse(json)) {
+ return CompletionRegistrationOptions.fromJson(json);
+ }
+ if (SignatureHelpRegistrationOptions.canParse(json)) {
+ return SignatureHelpRegistrationOptions.fromJson(json);
+ }
+ if (CodeActionRegistrationOptions.canParse(json)) {
+ return CodeActionRegistrationOptions.fromJson(json);
+ }
+ if (CodeLensRegistrationOptions.canParse(json)) {
+ return CodeLensRegistrationOptions.fromJson(json);
+ }
+ if (DocumentLinkRegistrationOptions.canParse(json)) {
+ return DocumentLinkRegistrationOptions.fromJson(json);
+ }
+ if (DocumentOnTypeFormattingRegistrationOptions.canParse(json)) {
+ return DocumentOnTypeFormattingRegistrationOptions.fromJson(json);
+ }
+ if (RenameRegistrationOptions.canParse(json)) {
+ return RenameRegistrationOptions.fromJson(json);
+ }
final documentSelector = json['documentSelector']
?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
?.cast<DocumentFilter>()
@@ -10961,6 +11066,8 @@
}
/// Did change watched files notification supports dynamic registration.
+ /// Please note that the current protocol doesn't support static configuration
+ /// for file changes from the server side.
final bool dynamicRegistration;
Map<String, dynamic> toJson() {
diff --git a/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart b/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart
index 22a85fd..9267bc4 100644
--- a/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart
+++ b/pkg/analysis_server/lib/plugin/analysis/occurrences/occurrences_core.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart b/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart
index 06bbf6b..adc7fd9 100644
--- a/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart
+++ b/pkg/analysis_server/lib/plugin/edit/assist/assist_core.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
index 08fe4f3..fe2c234 100644
--- a/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/assist/assist_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
index ccc79a9..32834a2 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_core.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
index 1d115fa..fb3c5ec 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index cab3a80..aaecbef 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/protocol/protocol.dart b/pkg/analysis_server/lib/protocol/protocol.dart
index f3253cf..b769bd4 100644
--- a/pkg/analysis_server/lib/protocol/protocol.dart
+++ b/pkg/analysis_server/lib/protocol/protocol.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 15c626a..fd21adb 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.21.1';
+const String PROTOCOL_VERSION = '1.22.1';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/lib/src/analysis_logger.dart b/pkg/analysis_server/lib/src/analysis_logger.dart
index 3391196..768ab01 100644
--- a/pkg/analysis_server/lib/src/analysis_logger.dart
+++ b/pkg/analysis_server/lib/src/analysis_logger.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 03fd356..a917fb1 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
@@ -16,7 +16,6 @@
import 'package:analysis_server/src/analysis_logger.dart';
import 'package:analysis_server/src/analysis_server_abstract.dart';
import 'package:analysis_server/src/channel/channel.dart';
-import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/computer/computer_highlights.dart';
import 'package:analysis_server/src/computer/computer_highlights2.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
@@ -50,6 +49,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/context/builder.dart';
@@ -76,9 +76,6 @@
/// Instances of the class [AnalysisServer] implement a server that listens on a
/// [CommunicationChannel] for analysis requests and process them.
class AnalysisServer extends AbstractAnalysisServer {
- /// The options of this server instance.
- AnalysisServerOptions options;
-
/// The channel from which requests are received and to which responses should
/// be sent.
final ServerCommunicationChannel channel;
@@ -124,22 +121,6 @@
/// notifications should be sent.
Map<FlutterService, Set<String>> flutterServices = {};
- /// Performance information before initial analysis is complete.
- final ServerPerformance performanceDuringStartup = new ServerPerformance();
-
- /// Performance information after initial analysis is complete
- /// or `null` if the initial analysis is not yet complete
- ServerPerformance performanceAfterStartup;
-
- /// A [RecentBuffer] of the most recent exceptions encountered by the analysis
- /// server.
- final RecentBuffer<ServerException> exceptions = new RecentBuffer(10);
-
- /// The class into which performance information is currently being recorded.
- /// During startup, this will be the same as [performanceDuringStartup]
- /// and after startup is complete, this switches to [performanceAfterStartup].
- ServerPerformance _performance;
-
/// The [Completer] that completes when analysis is complete.
Completer _onAnalysisCompleteCompleter;
@@ -191,18 +172,16 @@
AnalysisServer(
this.channel,
ResourceProvider baseResourceProvider,
- this.options,
+ AnalysisServerOptions options,
this.sdkManager,
this.instrumentationService, {
this.diagnosticServer,
ResolverProvider fileResolverProvider: null,
ResolverProvider packageResolverProvider: null,
this.detachableFileSystemManager: null,
- }) : super(baseResourceProvider) {
+ }) : super(options, baseResourceProvider) {
notificationManager = new NotificationManager(channel, resourceProvider);
- _performance = performanceDuringStartup;
-
pluginManager = new PluginManager(
resourceProvider,
_getByteStorePath(),
@@ -252,7 +231,7 @@
onAnalysisStarted.first.then((_) {
onAnalysisComplete.then((_) {
performanceAfterStartup = new ServerPerformance();
- _performance = performanceAfterStartup;
+ performance = performanceAfterStartup;
});
});
searchEngine = new SearchEngineImpl(driverMap.values);
@@ -302,13 +281,6 @@
return _onAnalysisStartedController.stream;
}
- /// Return the total time the server's been alive.
- Duration get uptime {
- DateTime start = new DateTime.fromMillisecondsSinceEpoch(
- performanceDuringStartup.startTime);
- return new DateTime.now().difference(start);
- }
-
/// The socket from which requests are being read has been closed.
void done() {}
@@ -340,7 +312,7 @@
/// Handle a [request] that was read from the communication channel.
void handleRequest(Request request) {
- _performance.logRequest(request);
+ performance.logRequestTiming(request.clientRequestTime);
runZoned(() {
ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() {
int count = handlers.length;
@@ -686,9 +658,12 @@
/// Return the path to the location of the byte store on disk, or `null` if
/// there is no on-disk byte store.
String _getByteStorePath() {
- if (resourceProvider is PhysicalResourceProvider) {
- Folder stateLocation =
- resourceProvider.getStateLocation('.analysis-driver');
+ ResourceProvider provider = resourceProvider;
+ if (provider is OverlayResourceProvider) {
+ provider = (provider as OverlayResourceProvider).baseProvider;
+ }
+ if (provider is PhysicalResourceProvider) {
+ Folder stateLocation = provider.getStateLocation('.analysis-driver');
if (stateLocation != null) {
return stateLocation.path;
}
@@ -1071,6 +1046,9 @@
/// The number of requests.
int requestCount = 0;
+ /// The number of requests that recorded latency information.
+ int latencyCount = 0;
+
/// The total latency (milliseconds) for all recorded requests.
int requestLatency = 0;
@@ -1080,12 +1058,13 @@
/// The number of requests with latency > 150 milliseconds.
int slowRequestCount = 0;
- /// Log performance information about the given request.
- void logRequest(Request request) {
+ /// Log timing information for a request.
+ void logRequestTiming(int clientRequestTime) {
++requestCount;
- if (request.clientRequestTime != null) {
+ if (clientRequestTime != null) {
int latency =
- new DateTime.now().millisecondsSinceEpoch - request.clientRequestTime;
+ new DateTime.now().millisecondsSinceEpoch - clientRequestTime;
+ ++latencyCount;
requestLatency += latency;
maxLatency = max(maxLatency, latency);
if (latency > 150) {
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index bdc364e..f784b71 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -1,10 +1,12 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:core';
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
@@ -29,10 +31,29 @@
/// Implementations of [AbstractAnalysisServer] implement a server that listens
/// on a [CommunicationChannel] for analysis messages and process them.
abstract class AbstractAnalysisServer {
+ /// The options of this server instance.
+ AnalysisServerOptions options;
+
/// The [ContextManager] that handles the mapping from analysis roots to
/// context directories.
ContextManager contextManager;
+ /// A [RecentBuffer] of the most recent exceptions encountered by the analysis
+ /// server.
+ final RecentBuffer<ServerException> exceptions = new RecentBuffer(10);
+
+ /// Performance information after initial analysis is complete
+ /// or `null` if the initial analysis is not yet complete
+ ServerPerformance performanceAfterStartup;
+
+ /// The class into which performance information is currently being recorded.
+ /// During startup, this will be the same as [performanceDuringStartup]
+ /// and after startup is complete, this switches to [performanceAfterStartup].
+ ServerPerformance performance;
+
+ /// Performance information before initial analysis is complete.
+ final ServerPerformance performanceDuringStartup = new ServerPerformance();
+
/// The set of the files that are currently priority.
final Set<String> priorityFiles = new Set<String>();
@@ -52,8 +73,10 @@
/// list is lazily created and should be accessed using [analyzedFilesGlobs].
List<Glob> _analyzedFilesGlobs = null;
- AbstractAnalysisServer(ResourceProvider baseResourceProvider)
- : resourceProvider = OverlayResourceProvider(baseResourceProvider);
+ AbstractAnalysisServer(this.options, ResourceProvider baseResourceProvider)
+ : resourceProvider = OverlayResourceProvider(baseResourceProvider) {
+ performance = performanceDuringStartup;
+ }
/// Return a list of the globs used to determine which files should be
/// analyzed.
@@ -82,6 +105,13 @@
/// A table mapping [Folder]s to the [AnalysisDriver]s associated with them.
Map<Folder, nd.AnalysisDriver> get driverMap => contextManager.driverMap;
+ /// Return the total time the server's been alive.
+ Duration get uptime {
+ DateTime start = new DateTime.fromMillisecondsSinceEpoch(
+ performanceDuringStartup.startTime);
+ return new DateTime.now().difference(start);
+ }
+
/// If the state location can be accessed, return the file byte store,
/// otherwise return the memory byte store.
ByteStore createByteStore(ResourceProvider resourceProvider) {
diff --git a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
index 8bdb5d5..7fa2439 100644
--- a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
+++ b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/channel/channel.dart b/pkg/analysis_server/lib/src/channel/channel.dart
index 0f580f1..152c820 100644
--- a/pkg/analysis_server/lib/src/channel/channel.dart
+++ b/pkg/analysis_server/lib/src/channel/channel.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/collections.dart b/pkg/analysis_server/lib/src/collections.dart
index afde613..a20dd6b 100644
--- a/pkg/analysis_server/lib/src/collections.dart
+++ b/pkg/analysis_server/lib/src/collections.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 0905fe7..eb20b24 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 24af9ba..c11bac0 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
index 92be0a4..cd1ff67 100644
--- a/pkg/analysis_server/lib/src/computer/computer_overrides.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/computer/computer_signature.dart b/pkg/analysis_server/lib/src/computer/computer_signature.dart
index b213ef1..518a488 100644
--- a/pkg/analysis_server/lib/src/computer/computer_signature.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_signature.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index 7973eed..00f2cfc 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/computer/new_notifications.dart b/pkg/analysis_server/lib/src/computer/new_notifications.dart
index 06aabc7..a7c00bf 100644
--- a/pkg/analysis_server/lib/src/computer/new_notifications.dart
+++ b/pkg/analysis_server/lib/src/computer/new_notifications.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 7808ce0..b7312d6 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/domain_abstract.dart b/pkg/analysis_server/lib/src/domain_abstract.dart
index 3c01cbf..6a50a2d 100644
--- a/pkg/analysis_server/lib/src/domain_abstract.dart
+++ b/pkg/analysis_server/lib/src/domain_abstract.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index fd6e154..9d2cbe9 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/domain_analytics.dart b/pkg/analysis_server/lib/src/domain_analytics.dart
index 220fe27..e006ab8 100644
--- a/pkg/analysis_server/lib/src/domain_analytics.dart
+++ b/pkg/analysis_server/lib/src/domain_analytics.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index ce73d98..2b61900 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/domain_diagnostic.dart b/pkg/analysis_server/lib/src/domain_diagnostic.dart
index 6c03067..dcd24ed 100644
--- a/pkg/analysis_server/lib/src/domain_diagnostic.dart
+++ b/pkg/analysis_server/lib/src/domain_diagnostic.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/domain_execution.dart b/pkg/analysis_server/lib/src/domain_execution.dart
index 52bf9d6..8930def 100644
--- a/pkg/analysis_server/lib/src/domain_execution.dart
+++ b/pkg/analysis_server/lib/src/domain_execution.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
index 2bfc8c0..ecfcc43 100644
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/domain_server.dart b/pkg/analysis_server/lib/src/domain_server.dart
index 728a4dd..c7d5f28 100644
--- a/pkg/analysis_server/lib/src/domain_server.dart
+++ b/pkg/analysis_server/lib/src/domain_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
index cff08c1..2885948 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index 74bbf87..d8fbb56 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart b/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart
index eedb605..2c44ad4 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/occurrences.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
index 6b9cde3..ee06820 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/occurrences_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index a8a55f1..dbba4ea 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index 073e434..c9b2ff1 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
@@ -6,6 +6,7 @@
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
import 'package:analysis_server/src/edit/fix/prefer_int_literals_fix.dart';
import 'package:analysis_server/src/edit/fix/prefer_mixin_fix.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
@@ -43,7 +44,8 @@
EditDartFix(this.server, this.request);
- void addFix(String description, Location location, SourceChange change) {
+ void addSourceChange(
+ String description, Location location, SourceChange change) {
suggestions.add(new DartFixSuggestion(description, location: location));
for (SourceFileEdit fileEdit in change.edits) {
for (SourceEdit sourceEdit in fileEdit.edits) {
@@ -52,6 +54,14 @@
}
}
+ void addSourceFileEdit(
+ String description, Location location, SourceFileEdit fileEdit) {
+ suggestions.add(new DartFixSuggestion(description, location: location));
+ for (SourceEdit sourceEdit in fileEdit.edits) {
+ sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
+ }
+ }
+
void addRecommendation(String description, [Location location]) {
otherSuggestions
.add(new DartFixSuggestion(description, location: location));
@@ -89,6 +99,7 @@
final preferIntLiterals = lintRules['prefer_int_literals'];
final preferIntLiteralsFix = new PreferIntLiteralsFix(this);
+ final nonNullableFix = new NonNullableFix(this);
preferIntLiterals?.reporter = preferIntLiteralsFix;
// Setup
@@ -163,6 +174,9 @@
for (LinterFix fix in fixes) {
await fix.applyLocalFixes(result);
}
+ if (isIncluded(source.fullName)) {
+ nonNullableFix.applyLocalFixes(result);
+ }
}
break;
} on InconsistentAnalysisException catch (_) {
@@ -219,7 +233,7 @@
Fix fix = await processor.computeFix();
final location = locationFor(result, error.offset, error.length);
if (fix != null) {
- addFix(fix.change.message, location, fix.change);
+ addSourceChange(fix.change.message, location, fix.change);
} else {
// TODO(danrubel): Determine why the fix could not be applied
// and report that in the description.
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index f2a9cda..2e1f6e2 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
@@ -938,38 +938,14 @@
var node = new NodeLocator(offset).searchWithin(resolvedUnit.unit);
var element = server.getElementOfNode(node);
if (node != null && element != null) {
- int feedbackOffset = node.offset;
- int feedbackLength = node.length;
-
- if (element is FieldFormalParameterElement) {
- element = (element as FieldFormalParameterElement).field;
- }
-
- // Use the prefix offset/length when renaming an import directive.
- if (node is ImportDirective && element is ImportElement) {
- if (node.prefix != null) {
- feedbackOffset = node.prefix.offset;
- feedbackLength = node.prefix.length;
- } else {
- feedbackOffset = -1;
- feedbackLength = 0;
- }
- }
-
- // Rename the class when on `new` in an instance creation.
- if (node is InstanceCreationExpression) {
- InstanceCreationExpression creation = node;
- var typeIdentifier = creation.constructorName.type.name;
- element = typeIdentifier.staticElement;
- feedbackOffset = typeIdentifier.offset;
- feedbackLength = typeIdentifier.length;
- }
+ final renameElement =
+ RenameRefactoring.getElementToRename(node, element);
// do create the refactoring
- refactoring = new RenameRefactoring(
- refactoringWorkspace, resolvedUnit.session, element);
+ refactoring = new RenameRefactoring(refactoringWorkspace,
+ resolvedUnit.session, renameElement.element);
feedback = new RenameFeedback(
- feedbackOffset, feedbackLength, 'kind', 'oldName');
+ renameElement.offset, renameElement.length, 'kind', 'oldName');
}
}
}
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
new file mode 100644
index 0000000..14bad20
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -0,0 +1,82 @@
+import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+class NonNullableFix {
+ final EditDartFix dartFix;
+
+ /// The current source being "fixed"
+ Source source;
+
+ /// The source file change or `null` if none
+ SourceFileEdit fileEdit;
+
+ int firstOffset;
+ int firstLength;
+
+ NonNullableFix(this.dartFix);
+
+ void addEdit(int offset, int length, String replacementText) {
+ fileEdit ??= new SourceFileEdit(source.fullName, 0);
+ fileEdit.edits.add(new SourceEdit(offset, length, replacementText));
+ }
+
+ /// Update the source to be non-nullable by
+ /// 1) adding trailing '?' to type references of nullable variables, and
+ /// 2) removing trailing '?' from type references of non-nullable variables.
+ void applyLocalFixes(ResolvedUnitResult result) {
+ final context = result.session.analysisContext;
+ AnalysisOptionsImpl options = context.analysisOptions;
+ if (!options.experimentStatus.non_nullable) {
+ return;
+ }
+
+ final unit = result.unit;
+ source = unit.declaredElement.source;
+
+ // find and fix types
+ unit.accept(new _NonNullableTypeVisitor(this));
+
+ // add source changes to the collection of fixes
+ source = null;
+ if (fileEdit != null) {
+ dartFix.addSourceFileEdit('Update non-nullable type references',
+ dartFix.locationFor(result, firstOffset, firstLength), fileEdit);
+ }
+ }
+}
+
+class _NonNullableTypeVisitor extends RecursiveAstVisitor<void> {
+ final NonNullableFix fix;
+
+ _NonNullableTypeVisitor(this.fix);
+
+ @override
+ void visitConstructorName(ConstructorName node) {
+ // skip the type name associated with the constructor
+ node.type?.typeArguments?.accept(this);
+ }
+
+ @override
+ void visitTypeName(TypeName node) {
+ // TODO(danrubel): Replace this braindead implementation
+ // with something that determines whether or not the type should be nullable
+ // and adds or removes the trailing `?` to match.
+ if (node.question == null) {
+ final identifier = node.name;
+ if (identifier is SimpleIdentifier) {
+ if (identifier.name == 'void') {
+ return;
+ }
+ }
+ fix.addEdit(node.end, 0, '?');
+ fix.firstOffset ??= node.offset;
+ fix.firstLength ??= node.length;
+ }
+ super.visitTypeName(node);
+ }
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
index 619cad3..871eb2b 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
@@ -34,8 +34,10 @@
dartFix.locationFor(result, literal.offset, literal.length);
if (assists.isNotEmpty) {
for (Assist assist in assists) {
- dartFix.addFix('Replace a double literal with an int literal',
- location, assist.change);
+ dartFix.addSourceChange(
+ 'Replace a double literal with an int literal',
+ location,
+ assist.change);
}
} else {
// TODO(danrubel): If assists is empty, then determine why
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
index 7f66a47..2972f49 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
@@ -50,8 +50,8 @@
dartFix.locationFor(result, elem.nameOffset, elem.nameLength);
if (assists.isNotEmpty) {
for (Assist assist in assists) {
- dartFix.addFix('Convert ${elem.displayName} to a mixin', location,
- assist.change);
+ dartFix.addSourceChange('Convert ${elem.displayName} to a mixin',
+ location, assist.change);
}
} else {
// TODO(danrubel): If assists is empty, then determine why
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
index 34e2864..3f92193 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
index 7bc3713..27d5268 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index b387156..054a199 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index 5d503b4..d6fae03 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 74a7949..464ab95 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -23,6 +23,7 @@
// We have to explicitly list this for the client to enable built-in command.
CodeActionKind.SourceOrganizeImports,
SortMembers,
+ CodeActionKind.QuickFix,
];
static const SortMembers = const CodeActionKind('source.sortMembers');
}
@@ -39,6 +40,7 @@
static const FileNotAnalyzed = const ErrorCodes(-32007);
static const FileHasErrors = const ErrorCodes(-32008);
static const ClientFailedToApplyEdit = const ErrorCodes(-32009);
+ static const RenameNotValid = const ErrorCodes(-32010);
/// An error raised when the server detects that the server and client are out
/// of sync and cannot recover. For example if a textDocument/didChange notification
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
new file mode 100644
index 0000000..6823eb8
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+
+class WorkspaceFoldersHandler
+ extends MessageHandler<DidChangeWorkspaceFoldersParams, void> {
+ WorkspaceFoldersHandler(LspAnalysisServer server) : super(server);
+ Method get handlesMessage => Method.workspace_didChangeWorkspaceFolders;
+
+ @override
+ DidChangeWorkspaceFoldersParams convertParams(Map<String, dynamic> json) =>
+ DidChangeWorkspaceFoldersParams.fromJson(json);
+
+ ErrorOr<void> handle(DidChangeWorkspaceFoldersParams params) {
+ final added = params?.event?.added
+ ?.map((wf) => Uri.parse(wf.uri).toFilePath())
+ ?.toList();
+
+ final removed = params?.event?.removed
+ ?.map((wf) => Uri.parse(wf.uri).toFilePath())
+ ?.toList();
+
+ server.updateAnalysisRoots(added, removed);
+
+ return success();
+ }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index dc83f4f..41d3014 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -13,8 +13,6 @@
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
-import 'package:analysis_server/src/lsp/source_edits.dart';
-import 'package:analysis_server/src/protocol_server.dart' show SourceChange;
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
@@ -90,7 +88,7 @@
assist.change.message,
CodeActionKind.Refactor,
const [],
- _createWorkspaceEdit(assist.change),
+ createWorkspaceEdit(server, assist.change),
null,
));
}
@@ -105,25 +103,11 @@
fix.change.message,
CodeActionKind.QuickFix,
[diagnostic],
- _createWorkspaceEdit(fix.change),
+ createWorkspaceEdit(server, fix.change),
null,
));
}
- /// Note: This code will fetch the version of each document being modified so
- /// it's important to call this immediately after computing edits to ensure
- /// the document is not modified before the version number is read.
- WorkspaceEdit _createWorkspaceEdit(SourceChange change) {
- return toWorkspaceEdit(
- server.clientCapabilities?.workspace,
- change.edits
- .map((e) => new FileEditInformation(
- server.getVersionedDocumentIdentifier(e.file),
- server.getLineInfo(e.file),
- e.edits))
- .toList());
- }
-
Future<List<Either2<Command, CodeAction>>> _getAssistActions(
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
bool clientSupportsLiteralCodeActions,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 6bf8c1c..bc81078 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -77,12 +77,22 @@
int offset,
) async {
final performance = new CompletionPerformance();
+ performance.path = unit.path;
+ performance.setContentsAndOffset(unit.content, offset);
+ server.performanceStats.completion.add(performance);
+
final completionRequest =
new CompletionRequestImpl(unit, offset, performance);
try {
CompletionContributor contributor = new DartCompletionManager();
final items = await contributor.computeSuggestions(completionRequest);
+
+ performance.notificationCount = 1;
+ performance.suggestionCountFirst = items.length;
+ performance.suggestionCountLast = items.length;
+ performance.complete();
+
return success(items
.map((item) => toCompletionItem(
completionCapabilities,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
new file mode 100644
index 0000000..9f6822e
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/domains/analysis/occurrences.dart';
+import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+
+class DocumentHighlightsHandler extends MessageHandler<
+ TextDocumentPositionParams, List<DocumentHighlight>> {
+ DocumentHighlightsHandler(LspAnalysisServer server) : super(server);
+ Method get handlesMessage => Method.textDocument_documentHighlight;
+
+ @override
+ TextDocumentPositionParams convertParams(Map<String, dynamic> json) =>
+ TextDocumentPositionParams.fromJson(json);
+
+ Future<ErrorOr<List<DocumentHighlight>>> handle(
+ TextDocumentPositionParams params) async {
+ final pos = params.position;
+ final path = pathOfDoc(params.textDocument);
+ final unit = await path.mapResult(requireUnit);
+ final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
+
+ return offset.mapResult((requestedOffset) {
+ final collector = new OccurrencesCollectorImpl();
+ addDartOccurrences(collector, unit.result.unit);
+
+ // Find an occurrence that has an instance that spans the position.
+ for (final occurrence in collector.allOccurrences) {
+ bool spansRequestedPosition(int offset) {
+ return offset <= requestedOffset &&
+ offset + occurrence.length >= requestedOffset;
+ }
+
+ if (occurrence.offsets.any(spansRequestedPosition)) {
+ return success(toHighlights(unit.result.lineInfo, occurrence));
+ }
+ }
+
+ // No matches.
+ return success(null);
+ });
+ }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index 7783434..e1a72f6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -31,14 +31,23 @@
openWorkspacePaths.add(Uri.parse(params.rootUri).toFilePath());
// ignore: deprecated_member_use
} else if (params.rootPath != null) {
- openWorkspacePaths.add(params.rootUri);
+ // This is deprecated according to LSP spec, but we still want to support
+ // it in case older clients send us it.
+ // ignore: deprecated_member_use
+ openWorkspacePaths.add(params.rootPath);
}
- server.setClientCapabilities(params.capabilities);
+ server.handleClientConnection(params.capabilities);
server.messageHandler =
new InitializingStateMessageHandler(server, openWorkspacePaths);
- return success(new InitializeResult(new ServerCapabilities(
+ final codeActionLiteralSupport =
+ params.capabilities.textDocument?.codeAction?.codeActionLiteralSupport;
+
+ final renameOptionsSupport =
+ params.capabilities.textDocument?.rename?.prepareSupport ?? false;
+
+ server.capabilities = new ServerCapabilities(
Either2<TextDocumentSyncOptions, num>.t1(new TextDocumentSyncOptions(
true,
TextDocumentSyncKind.Incremental,
@@ -66,21 +75,31 @@
null,
null,
true, // referencesProvider
- null,
+ true, // documentHighlightProvider
true, // documentSymbolProvider
null,
- Either2<bool, CodeActionOptions>.t2(
- new CodeActionOptions(DartCodeActionKind.serverSupportedKinds)),
+ // "The `CodeActionOptions` return type is only valid if the client
+ // signals code action literal support via the property
+ // `textDocument.codeAction.codeActionLiteralSupport`."
+ codeActionLiteralSupport != null
+ ? Either2<bool, CodeActionOptions>.t2(
+ new CodeActionOptions(DartCodeActionKind.serverSupportedKinds))
+ : Either2<bool, CodeActionOptions>.t1(true),
null,
true, // documentFormattingProvider
false, // documentRangeFormattingProvider
new DocumentOnTypeFormattingOptions('}', [';']),
- null,
+ renameOptionsSupport
+ ? Either2<bool, RenameOptions>.t2(new RenameOptions(true))
+ : Either2<bool, RenameOptions>.t1(true),
null,
null,
null,
new ExecuteCommandOptions(Commands.serverSupportedCommands),
- null,
- null)));
+ new ServerCapabilitiesWorkspace(
+ new ServerCapabilitiesWorkspaceFolders(true, true)),
+ null);
+
+ return success(new InitializeResult(server.capabilities));
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index 8201ae8..3462d78 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -21,7 +21,7 @@
ErrorOr<void> handle(InitializedParams params) {
server.messageHandler = new InitializedStateMessageHandler(server);
- server.setAnalysisRoots(openWorkspacePaths, [], {});
+ server.setAnalysisRoots(openWorkspacePaths);
return success();
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
new file mode 100644
index 0000000..3a9075e
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+
+class PrepareRenameHandler
+ extends MessageHandler<TextDocumentPositionParams, RangeAndPlaceholder> {
+ PrepareRenameHandler(LspAnalysisServer server) : super(server);
+ Method get handlesMessage => Method.textDocument_prepareRename;
+
+ @override
+ TextDocumentPositionParams convertParams(Map<String, dynamic> json) =>
+ TextDocumentPositionParams.fromJson(json);
+
+ @override
+ Future<ErrorOr<RangeAndPlaceholder>> handle(
+ TextDocumentPositionParams params) async {
+ final pos = params.position;
+ final path = pathOfDoc(params.textDocument);
+ final unit = await path.mapResult(requireUnit);
+ final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
+
+ return offset.mapResult((offset) async {
+ final node = await server.getNodeAtOffset(path.result, offset);
+ final element = server.getElementOfNode(node);
+ if (node == null || element == null) {
+ return success(null);
+ }
+
+ final refactorDetails =
+ RenameRefactoring.getElementToRename(node, element);
+ final refactoring = new RenameRefactoring(server.refactoringWorkspace,
+ unit.result.session, refactorDetails.element);
+
+ // Check the rename is valid here.
+ final initStatus = await refactoring.checkInitialConditions();
+ if (initStatus.hasFatalError) {
+ return error(
+ ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
+ }
+
+ return success(new RangeAndPlaceholder(
+ toRange(
+ unit.result.lineInfo,
+ // If the offset is set to -1 it means there is no location for the
+ // old name. However since we must provide a range for LSP, we'll use
+ // a 0-character span at the originally requested location to ensure
+ // it's valid.
+ refactorDetails.offset == -1 ? offset : refactorDetails.offset,
+ refactorDetails.length,
+ ),
+ refactoring.oldName,
+ ));
+ });
+ }
+}
+
+class RenameHandler extends MessageHandler<RenameParams, WorkspaceEdit> {
+ RenameHandler(LspAnalysisServer server) : super(server);
+
+ Method get handlesMessage => Method.textDocument_rename;
+
+ @override
+ RenameParams convertParams(Map<String, dynamic> json) =>
+ RenameParams.fromJson(json);
+
+ @override
+ Future<ErrorOr<WorkspaceEdit>> handle(RenameParams params) async {
+ final pos = params.position;
+ final path = pathOfDoc(params.textDocument);
+ // If the client provided us a version doc identifier, we'll use it to ensure
+ // we're not computing a rename for an old document. If not, we'll just assume
+ // the version the server had at the time of recieving the request is valid
+ // and then use it to verify the document hadn't changed again before we
+ // send the edits.
+ final docIdentifier = await path.mapResult((path) => success(
+ params.textDocument is VersionedTextDocumentIdentifier
+ ? params.textDocument
+ : server.getVersionedDocumentIdentifier(path)));
+ final unit = await path.mapResult(requireUnit);
+ final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
+
+ return offset.mapResult((offset) async {
+ final node = await server.getNodeAtOffset(path.result, offset);
+ final element = server.getElementOfNode(node);
+ if (node == null || element == null) {
+ return success(null);
+ }
+
+ final refactorDetails =
+ RenameRefactoring.getElementToRename(node, element);
+ final refactoring = new RenameRefactoring(server.refactoringWorkspace,
+ unit.result.session, refactorDetails.element);
+
+ // TODO(dantup): Consider using window/showMessageRequest to prompt
+ // the user to see if they'd like to proceed with a rename if there
+ // are non-fatal errors or warnings. For now we will reject all errors
+ // (fatal and not) as this seems like the most logical behaviour when
+ // without a prompt.
+
+ // Check the rename is valid here.
+ final initStatus = await refactoring.checkInitialConditions();
+ if (initStatus.hasError) {
+ return error(
+ ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
+ }
+
+ // Check the name is valid.
+ refactoring.newName = params.newName;
+ final optionsStatus = refactoring.checkNewName();
+ if (optionsStatus.hasError) {
+ return error(ServerErrorCodes.RenameNotValid,
+ optionsStatus.problem.message, null);
+ }
+
+ // Final validation.
+ final finalStatus = await refactoring.checkFinalConditions();
+ if (finalStatus.hasError) {
+ return error(
+ ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
+ }
+
+ // Compute the actual change.
+ final change = await refactoring.createChange();
+
+ // Before we send anything back, ensure the original file didn't change
+ // while we were computing changes.
+ if (server.getVersionedDocumentIdentifier(path.result) !=
+ docIdentifier.result) {
+ return error(ErrorCodes.ContentModified,
+ 'Document was modified while rename was being computed', null);
+ }
+
+ final workspaceEdit = createWorkspaceEdit(server, change);
+ return success(workspaceEdit);
+ });
+ }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index b1e6c2b..9375b8b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -10,6 +10,7 @@
import 'package:analysis_server/src/lsp/handlers/handler_code_actions.dart';
import 'package:analysis_server/src/lsp/handlers/handler_completion.dart';
import 'package:analysis_server/src/lsp/handlers/handler_definition.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_document_highlights.dart';
import 'package:analysis_server/src/lsp/handlers/handler_document_symbols.dart';
import 'package:analysis_server/src/lsp/handlers/handler_execute_command.dart';
import 'package:analysis_server/src/lsp/handlers/handler_format_on_type.dart';
@@ -18,8 +19,10 @@
import 'package:analysis_server/src/lsp/handlers/handler_initialize.dart';
import 'package:analysis_server/src/lsp/handlers/handler_initialized.dart';
import 'package:analysis_server/src/lsp/handlers/handler_references.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_rename.dart';
import 'package:analysis_server/src/lsp/handlers/handler_signature_help.dart';
import 'package:analysis_server/src/lsp/handlers/handler_text_document_changes.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_change_workspace_folders.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
@@ -54,9 +57,13 @@
registerHandler(new ReferencesHandler(server));
registerHandler(new FormattingHandler(server));
registerHandler(new FormatOnTypeHandler(server));
+ registerHandler(new DocumentHighlightsHandler(server));
registerHandler(new DocumentSymbolHandler(server));
registerHandler(new CodeActionHandler(server));
registerHandler(new ExecuteCommandHandler(server));
+ registerHandler(new WorkspaceFoldersHandler(server));
+ registerHandler(new PrepareRenameHandler(server));
+ registerHandler(new RenameHandler(server));
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 245c116a..925e5a7 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:collection';
import 'dart:io' as io;
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -10,7 +11,10 @@
import 'package:analysis_server/protocol/protocol_generated.dart' as protocol;
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/analysis_server_abstract.dart';
+import 'package:analysis_server/src/collections.dart';
import 'package:analysis_server/src/context_manager.dart';
+import 'package:analysis_server/src/domain_completion.dart'
+ show CompletionDomainHandler;
import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
@@ -18,9 +22,13 @@
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analysis_server/src/services/completion/completion_performance.dart'
+ show CompletionPerformance;
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
+import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/line_info.dart';
@@ -45,11 +53,6 @@
ClientCapabilities _clientCapabilities;
/**
- * The options of this server instance.
- */
- AnalysisServerOptions options;
-
- /**
* The channel from which messages are received and to which responses should
* be sent.
*/
@@ -77,6 +80,15 @@
final AnalysisOptionsImpl defaultContextOptions = new AnalysisOptionsImpl();
/**
+ * The workspace for rename refactorings. Should be accessed through the
+ * refactoringWorkspace getter to be automatically created (lazily).
+ */
+ RefactoringWorkspace _refactoringWorkspace;
+
+ RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
+ new RefactoringWorkspace(driverMap.values, searchEngine);
+
+ /**
* The versions of each document known to the server (keyed by path), used to
* send back to the client for server-initiated edits so that the client can
* ensure they have a matching version of the document before applying them.
@@ -112,17 +124,25 @@
final Map<int, Completer<ResponseMessage>> completers = {};
/**
+ * Capabilities of the server. Will be null prior to initialization as
+ * the server capabilities depend on the client capabilities.
+ */
+ ServerCapabilities capabilities;
+
+ LspPerformance performanceStats = new LspPerformance();
+
+ /**
* Initialize a newly created server to send and receive messages to the given
* [channel].
*/
LspAnalysisServer(
this.channel,
ResourceProvider baseResourceProvider,
- this.options,
+ AnalysisServerOptions options,
this.sdkManager,
this.instrumentationService, {
ResolverProvider packageResolverProvider: null,
- }) : super(baseResourceProvider) {
+ }) : super(options, baseResourceProvider) {
messageHandler = new UninitializedStateMessageHandler(this);
defaultContextOptions.generateImplicitErrors = false;
defaultContextOptions.useFastaParser = options.useFastaParser;
@@ -206,6 +226,13 @@
null, new Uri.file(path).toString());
}
+ void handleClientConnection(ClientCapabilities capabilities) {
+ _clientCapabilities = capabilities;
+
+ performanceAfterStartup = new ServerPerformance();
+ performance = performanceAfterStartup;
+ }
+
/// Handles a response from the client by invoking the completer that the
/// outbound request created.
void handleClientResponse(ResponseMessage message) {
@@ -235,8 +262,7 @@
* Handle a [message] that was read from the communication channel.
*/
void handleMessage(Message message) {
- // TODO(dantup): Put in all the things this server is missing, like:
- // _performance.logRequest(message);
+ performance.logRequestTiming(null);
runZoned(() {
ServerPerformanceStatistics.serverRequests.makeCurrentWhile(() async {
try {
@@ -290,6 +316,17 @@
));
}
+ void publishDiagnostics(String path, List<Diagnostic> errors) {
+ final params =
+ new PublishDiagnosticsParams(Uri.file(path).toString(), errors);
+ final message = new NotificationMessage(
+ Method.textDocument_publishDiagnostics,
+ params,
+ jsonRpcVersion,
+ );
+ sendNotification(message);
+ }
+
removePriorityFile(String path) {
final didRemove = priorityFiles.remove(path);
assert(didRemove);
@@ -375,15 +412,22 @@
// Log the full message since showMessage above may be truncated or formatted
// badly (eg. VS Code takes the newlines out).
logError(fullError.toString());
+
+ // remember the last few exceptions
+ if (exception is CaughtException) {
+ stackTrace ??= exception.stackTrace;
+ }
+ exceptions.add(new ServerException(
+ message,
+ exception,
+ stackTrace is StackTrace ? stackTrace : null,
+ false,
+ ));
}
- void setAnalysisRoots(List<String> includedPaths, List<String> excludedPaths,
- Map<String, String> packageRoots) {
- contextManager.setRoots(includedPaths, excludedPaths, packageRoots);
- }
-
- void setClientCapabilities(ClientCapabilities capabilities) {
- _clientCapabilities = capabilities;
+ void setAnalysisRoots(List<String> includedPaths) {
+ final uniquePaths = HashSet<String>.of(includedPaths ?? const []);
+ contextManager.setRoots(uniquePaths.toList(), [], {});
}
/**
@@ -412,6 +456,16 @@
return new Future.value();
}
+ void updateAnalysisRoots(List<String> addedPaths, List<String> removedPaths) {
+ // TODO(dantup): This is currently case-sensitive!
+ final newPaths =
+ HashSet<String>.of(contextManager.includedPaths ?? const [])
+ ..addAll(addedPaths ?? const [])
+ ..removeAll(removedPaths ?? const []);
+
+ contextManager.setRoots(newPaths.toList(), [], {});
+ }
+
void updateOverlay(String path, String contents) {
if (contents != null) {
resourceProvider.setOverlay(path,
@@ -429,6 +483,14 @@
}
}
+class LspPerformance {
+ /// A list of code completion performance measurements for the latest
+ /// completion operation up to [performanceListMaxLength] measurements.
+ final RecentBuffer<CompletionPerformance> completion =
+ new RecentBuffer<CompletionPerformance>(
+ CompletionDomainHandler.performanceListMaxLength);
+}
+
class LspServerContextManagerCallbacks extends ContextManagerCallbacks {
// TODO(dantup): Lots of copy/paste from the Analysis Server one here.
@@ -459,14 +521,7 @@
result.errors,
toDiagnostic);
- final params = new PublishDiagnosticsParams(
- Uri.file(result.path).toString(), serverErrors);
- final message = new NotificationMessage(
- Method.textDocument_publishDiagnostics,
- params,
- jsonRpcVersion,
- );
- analysisServer.sendNotification(message);
+ analysisServer.publishDiagnostics(result.path, serverErrors);
}
});
analysisDriver.exceptions.listen((nd.ExceptionResult result) {
@@ -504,7 +559,7 @@
@override
void applyFileRemoved(nd.AnalysisDriver driver, String file) {
driver.removeFile(file);
- // sendAnalysisNotificationFlushResults(analysisServer, [file]);
+ analysisServer.publishDiagnostics(file, []);
}
@override
@@ -547,8 +602,10 @@
@override
void removeContext(Folder folder, List<String> flushedFiles) {
- // sendAnalysisNotificationFlushResults(analysisServer, flushedFiles);
nd.AnalysisDriver driver = analysisServer.driverMap.remove(folder);
+ // Flush any errors for these files that the client may be displaying.
+ flushedFiles
+ ?.forEach((path) => analysisServer.publishDiagnostics(path, const []));
driver.dispose();
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
index 47261dc..25a15e1 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
@@ -19,7 +19,7 @@
* the SocketServer is to manage the lifetime of the AnalysisServer and to
* encode and decode the JSON messages exchanged with the client.
*/
-class LspSocketServer {
+class LspSocketServer implements AbstractSocketServer {
final AnalysisServerOptions analysisServerOptions;
/**
* The analysis server that was created when a client established a
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index e97f557..d69d15d 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -1,9 +1,11 @@
import 'dart:collection';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
-import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart'
+ show ResponseError;
import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
-import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart'
+ show ErrorOr, Either2, Either4;
import 'package:analysis_server/src/lsp/constants.dart' as lsp;
import 'package:analysis_server/src/lsp/dartdoc.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart' as lsp;
@@ -30,6 +32,21 @@
_asMarkup(preferredFormats, content));
}
+/// Note: This code will fetch the version of each document being modified so
+/// it's important to call this immediately after computing edits to ensure
+/// the document is not modified before the version number is read.
+lsp.WorkspaceEdit createWorkspaceEdit(
+ lsp.LspAnalysisServer server, server.SourceChange change) {
+ return toWorkspaceEdit(
+ server.clientCapabilities?.workspace,
+ change.edits
+ .map((e) => new FileEditInformation(
+ server.getVersionedDocumentIdentifier(e.file),
+ server.getLineInfo(e.file),
+ e.edits))
+ .toList());
+}
+
lsp.CompletionItemKind elementKindToCompletionItemKind(
HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
server.ElementKind kind,
@@ -212,7 +229,7 @@
return null;
}
- return new Location(
+ return new lsp.Location(
Uri.file(targetFilePath).toString(),
toRange(lineInfo, target.offset, target.length),
);
@@ -261,7 +278,7 @@
return null;
}
- return new Location(
+ return new lsp.Location(
Uri.file(result.location.file).toString(),
toRange(lineInfo, location.offset, location.length),
);
@@ -400,6 +417,14 @@
}
}
+List<lsp.DocumentHighlight> toHighlights(
+ server.LineInfo lineInfo, server.Occurrences occurrences) {
+ return occurrences.offsets
+ .map((offset) => new lsp.DocumentHighlight(
+ toRange(lineInfo, offset, occurrences.length), null))
+ .toList();
+}
+
ErrorOr<int> toOffset(
server.LineInfo lineInfo,
lsp.Position pos, {
@@ -505,41 +530,41 @@
}
lsp.TextDocumentEdit toTextDocumentEdit(FileEditInformation edit) {
- return new TextDocumentEdit(
+ return new lsp.TextDocumentEdit(
edit.doc,
edit.edits.map((e) => toTextEdit(edit.lineInfo, e)).toList(),
);
}
lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
- return new TextEdit(
+ return new lsp.TextEdit(
toRange(lineInfo, edit.offset, edit.length),
edit.replacement,
);
}
lsp.WorkspaceEdit toWorkspaceEdit(
- WorkspaceClientCapabilities capabilities,
+ lsp.WorkspaceClientCapabilities capabilities,
List<FileEditInformation> edits,
) {
final clientSupportsTextDocumentEdits =
capabilities?.workspaceEdit?.documentChanges == true;
if (clientSupportsTextDocumentEdits) {
- return new WorkspaceEdit(
+ return new lsp.WorkspaceEdit(
null,
Either2<
- List<TextDocumentEdit>,
+ List<lsp.TextDocumentEdit>,
List<
- Either4<TextDocumentEdit, CreateFile, RenameFile,
- DeleteFile>>>.t1(
+ Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
+ lsp.DeleteFile>>>.t1(
edits.map(toTextDocumentEdit).toList(),
));
} else {
- return new WorkspaceEdit(toWorkspaceEditChanges(edits), null);
+ return new lsp.WorkspaceEdit(toWorkspaceEditChanges(edits), null);
}
}
-Map<String, List<TextEdit>> toWorkspaceEditChanges(
+Map<String, List<lsp.TextEdit>> toWorkspaceEditChanges(
List<FileEditInformation> edits) {
createEdit(FileEditInformation file) {
final edits =
@@ -547,7 +572,7 @@
return new MapEntry(file.doc.uri, edits);
}
- return Map<String, List<TextEdit>>.fromEntries(edits.map(createEdit));
+ return Map<String, List<lsp.TextEdit>>.fromEntries(edits.map(createEdit));
}
lsp.MarkupContent _asMarkup(
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 9943cbd..87aa99d 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/notification_manager.dart b/pkg/analysis_server/lib/src/plugin/notification_manager.dart
index 344697c..120afe9 100644
--- a/pkg/analysis_server/lib/src/plugin/notification_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/notification_manager.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
index ba53ab3..14c7069 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index 63be71f..de2cccf 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart b/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart
index e937e26..ecfe285 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_watcher.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/request_converter.dart b/pkg/analysis_server/lib/src/plugin/request_converter.dart
index 5caa071..9f0a071 100644
--- a/pkg/analysis_server/lib/src/plugin/request_converter.dart
+++ b/pkg/analysis_server/lib/src/plugin/request_converter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/result_collector.dart b/pkg/analysis_server/lib/src/plugin/result_collector.dart
index 04c3f09..dbee3d3 100644
--- a/pkg/analysis_server/lib/src/plugin/result_collector.dart
+++ b/pkg/analysis_server/lib/src/plugin/result_collector.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/result_converter.dart b/pkg/analysis_server/lib/src/plugin/result_converter.dart
index 40a5d2b..b73a280 100644
--- a/pkg/analysis_server/lib/src/plugin/result_converter.dart
+++ b/pkg/analysis_server/lib/src/plugin/result_converter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/plugin/result_merger.dart b/pkg/analysis_server/lib/src/plugin/result_merger.dart
index 43d0a56..1db0891 100644
--- a/pkg/analysis_server/lib/src/plugin/result_merger.dart
+++ b/pkg/analysis_server/lib/src/plugin/result_merger.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/protocol/protocol_internal.dart b/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
index a36fc49..1d6ed2d 100644
--- a/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
+++ b/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
index 2d6adce..a73691d 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/completion_core.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index f96c93e..c5ee92f 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/search/element_references.dart b/pkg/analysis_server/lib/src/search/element_references.dart
index 79f3714f..37a6872 100644
--- a/pkg/analysis_server/lib/src/search/element_references.dart
+++ b/pkg/analysis_server/lib/src/search/element_references.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index 65be43a..ae98245 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/search/type_hierarchy.dart b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
index 65eee55..e4bcfe5 100644
--- a/pkg/analysis_server/lib/src/search/type_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart b/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart
index dc2cead..1f45e5d 100644
--- a/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart
+++ b/pkg/analysis_server/lib/src/server/detachable_filesystem_manager.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/server/dev_server.dart b/pkg/analysis_server/lib/src/server/dev_server.dart
index 44bb21c..c8f52ea 100644
--- a/pkg/analysis_server/lib/src/server/dev_server.dart
+++ b/pkg/analysis_server/lib/src/server/dev_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/server/diagnostic_server.dart b/pkg/analysis_server/lib/src/server/diagnostic_server.dart
index b147a43..011c926 100644
--- a/pkg/analysis_server/lib/src/server/diagnostic_server.dart
+++ b/pkg/analysis_server/lib/src/server/diagnostic_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 21d5cc8..29d59bb 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
@@ -407,37 +407,10 @@
defaultSdk.sdkVersion);
AnalysisEngine.instance.instrumentationService = instrumentationService;
- if (analysisServerOptions.useLanguageServerProtocol) {
- startLspServer(results, analysisServerOptions, dartSdkManager,
- instrumentationService);
- } else {
- startAnalysisServer(results, analysisServerOptions, parser,
- dartSdkManager, instrumentationService, analytics);
- }
- }
-
- void startAnalysisServer(
- ArgResults results,
- AnalysisServerOptions analysisServerOptions,
- CommandLineParser parser,
- DartSdkManager dartSdkManager,
- InstrumentationService instrumentationService,
- telemetry.Analytics analytics) {
- String trainDirectory = results[TRAIN_USING];
- if (trainDirectory != null) {
- if (!FileSystemEntity.isDirectorySync(trainDirectory)) {
- print("Training directory '$trainDirectory' not found.\n");
- exitCode = 1;
- return null;
- }
- }
-
- int port;
- bool serve_http = false;
+ int diagnosticServerPort;
if (results[PORT_OPTION] != null) {
try {
- port = int.parse(results[PORT_OPTION]);
- serve_http = true;
+ diagnosticServerPort = int.parse(results[PORT_OPTION]);
} on FormatException {
print('Invalid port number: ${results[PORT_OPTION]}');
print('');
@@ -447,6 +420,40 @@
}
}
+ if (analysisServerOptions.useLanguageServerProtocol) {
+ startLspServer(results, analysisServerOptions, dartSdkManager,
+ instrumentationService, diagnosticServerPort);
+ } else {
+ startAnalysisServer(
+ results,
+ analysisServerOptions,
+ parser,
+ dartSdkManager,
+ instrumentationService,
+ analytics,
+ diagnosticServerPort);
+ }
+ }
+
+ void startAnalysisServer(
+ ArgResults results,
+ AnalysisServerOptions analysisServerOptions,
+ CommandLineParser parser,
+ DartSdkManager dartSdkManager,
+ InstrumentationService instrumentationService,
+ telemetry.Analytics analytics,
+ int diagnosticServerPort,
+ ) {
+ String trainDirectory = results[TRAIN_USING];
+ if (trainDirectory != null) {
+ if (!FileSystemEntity.isDirectorySync(trainDirectory)) {
+ print("Training directory '$trainDirectory' not found.\n");
+ exitCode = 1;
+ return null;
+ }
+ }
+ final serve_http = diagnosticServerPort != null;
+
//
// Process all of the plugins so that extensions are registered.
//
@@ -474,7 +481,7 @@
diagnosticServer.httpServer = httpServer;
if (serve_http) {
- diagnosticServer.startOnPort(port);
+ diagnosticServer.startOnPort(diagnosticServerPort);
}
if (trainDirectory != null) {
@@ -539,13 +546,25 @@
AnalysisServerOptions analysisServerOptions,
DartSdkManager dartSdkManager,
InstrumentationService instrumentationService,
+ int diagnosticServerPort,
) {
+ final serve_http = diagnosticServerPort != null;
+
+ _DiagnosticServerImpl diagnosticServer = new _DiagnosticServerImpl();
+
final socketServer = new LspSocketServer(
analysisServerOptions,
dartSdkManager,
instrumentationService,
);
+ httpServer = new HttpAnalysisServer(socketServer);
+
+ diagnosticServer.httpServer = httpServer;
+ if (serve_http) {
+ diagnosticServer.startOnPort(diagnosticServerPort);
+ }
+
_captureLspExceptions(socketServer, instrumentationService, () {
LspStdioAnalysisServer stdioServer =
new LspStdioAnalysisServer(socketServer);
diff --git a/pkg/analysis_server/lib/src/server/http_server.dart b/pkg/analysis_server/lib/src/server/http_server.dart
index 5b51304..95e4d34 100644
--- a/pkg/analysis_server/lib/src/server/http_server.dart
+++ b/pkg/analysis_server/lib/src/server/http_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
@@ -35,7 +35,7 @@
* An object that can handle either a WebSocket connection or a connection
* to the client over stdio.
*/
- SocketServer socketServer;
+ AbstractSocketServer socketServer;
/**
* An object that can handle GET requests.
diff --git a/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart b/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart
index 016bd11..1b5cde5 100644
--- a/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart
+++ b/pkg/analysis_server/lib/src/server/lsp_stdio_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/server/stdio_server.dart b/pkg/analysis_server/lib/src/server/stdio_server.dart
index 1895444..f7e9305 100644
--- a/pkg/analysis_server/lib/src/server/stdio_server.dart
+++ b/pkg/analysis_server/lib/src/server/stdio_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 02e617b..8b5b0a2 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
index 37ee54e..61df502 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index a2857e1..f7ddb32 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart b/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart
index 6b74935..7da0e3e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.g.dart b/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.g.dart
index f065701..91975c7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.g.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/common_usage_sorter.g.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/contribution_sorter.dart b/pkg/analysis_server/lib/src/services/completion/dart/contribution_sorter.dart
index 6dfbf6f..eedd4d9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/contribution_sorter.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/contribution_sorter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index 6f9d9b3..0f4025b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index 0f6f992..ef19706 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
index d580fcd..77b4ebf 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index 7a21679..35826f0 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index 6b46436..e9d2506 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index 4d8b351..3318bb5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index 007465e..f881357 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 66a5fc6..a883a59 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index 57a2f27..cc21160 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
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 405b772..aa25fba 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
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index 087b39e..3f98f7e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index e1ba6f9..7c65f43 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index a4e03b3..f3974ce 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
index 6226346..46910af 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index 0f2b10b..409b979 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index af2d9e3..82555b4 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 1c15d65..86231ae 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 08a56a1..8601163 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/change_workspace.dart b/pkg/analysis_server/lib/src/services/correction/change_workspace.dart
index b7a2a23..c206924 100644
--- a/pkg/analysis_server/lib/src/services/correction/change_workspace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/change_workspace.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 29c0b2f..e9bf18d 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
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 ebbf645..0db0fb2 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1334,14 +1334,19 @@
if (constructorElement.enclosingElement is! ClassElement) {
return;
}
- ClassElement targetElement = constructorElement.enclosingElement;
- // prepare location for a new constructor
- var targetNode = await _getClassDeclaration(targetElement);
- if (targetNode == null) {
+
+ // prepare target ClassDeclaration
+ var targetElement = constructorElement.enclosingElement;
+ var targetResult = await sessionHelper.getElementDeclaration(targetElement);
+ if (targetResult.node is! ClassOrMixinDeclaration) {
return;
}
- ClassMemberLocation targetLocation =
- utils.prepareNewConstructorLocation(targetNode);
+ ClassOrMixinDeclaration targetNode = targetResult.node;
+
+ // prepare location
+ var targetLocation = CorrectionUtils(targetResult.resolvedUnit)
+ .prepareNewConstructorLocation(targetNode);
+
Source targetSource = targetElement.source;
String targetFile = targetSource.fullName;
var changeBuilder = _newDartChangeBuilder();
@@ -1390,17 +1395,22 @@
if (targetType is! InterfaceType) {
return;
}
- // prepare location for a new constructor
- ClassElement targetElement = targetType.element as ClassElement;
- var targetNode = await _getClassDeclaration(targetElement);
- if (targetNode == null) {
+
+ // prepare target ClassDeclaration
+ ClassElement targetElement = targetType.element;
+ var targetResult = await sessionHelper.getElementDeclaration(targetElement);
+ if (targetResult.node is! ClassOrMixinDeclaration) {
return;
}
- ClassMemberLocation targetLocation =
- utils.prepareNewConstructorLocation(targetNode);
+ ClassOrMixinDeclaration targetNode = targetResult.node;
+
+ // prepare location
+ var targetLocation = CorrectionUtils(targetResult.resolvedUnit)
+ .prepareNewConstructorLocation(targetNode);
+
String targetFile = targetElement.source.fullName;
var changeBuilder = _newDartChangeBuilder();
- await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+ await changeBuilder.addFileEdit(targetFile, (DartFileEditBuilder builder) {
builder.addInsertion(targetLocation.offset, (DartEditBuilder builder) {
builder.write(targetLocation.prefix);
builder.writeConstructorDeclaration(targetElement.name,
@@ -2147,8 +2157,10 @@
_addFixFromBuilder(changeBuilder, kind, args: [uriText]);
}
- Future<void> _addFix_importLibrary_withElement(String name,
- List<ElementKind> elementKinds, TopLevelDeclarationKind kind2) async {
+ Future<void> _addFix_importLibrary_withElement(
+ String name,
+ List<ElementKind> elementKinds,
+ List<TopLevelDeclarationKind> kinds2) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
// ignore if private
@@ -2221,7 +2233,7 @@
var declarations = await session.getTopLevelDeclarations(name);
for (TopLevelDeclarationInSource declaration in declarations) {
// Check the kind.
- if (declaration.declaration.kind != kind2) {
+ if (!kinds2.contains(declaration.declaration.kind)) {
continue;
}
// Check the source.
@@ -2259,8 +2271,13 @@
MethodInvocation invocation = node.parent as MethodInvocation;
if (invocation.realTarget == null && invocation.methodName == node) {
String name = (node as SimpleIdentifier).name;
- await _addFix_importLibrary_withElement(name,
- const [ElementKind.FUNCTION], TopLevelDeclarationKind.function);
+ await _addFix_importLibrary_withElement(name, const [
+ ElementKind.FUNCTION,
+ ElementKind.TOP_LEVEL_VARIABLE
+ ], const [
+ TopLevelDeclarationKind.function,
+ TopLevelDeclarationKind.variable
+ ]);
}
}
}
@@ -2273,7 +2290,7 @@
await _addFix_importLibrary_withElement(
name,
const [ElementKind.TOP_LEVEL_VARIABLE],
- TopLevelDeclarationKind.variable);
+ const [TopLevelDeclarationKind.variable]);
}
}
@@ -2285,11 +2302,11 @@
await _addFix_importLibrary_withElement(
typeName,
const [ElementKind.CLASS, ElementKind.FUNCTION_TYPE_ALIAS],
- TopLevelDeclarationKind.type);
+ const [TopLevelDeclarationKind.type]);
} else if (_mayBeImplicitConstructor(node)) {
String typeName = (node as SimpleIdentifier).name;
- await _addFix_importLibrary_withElement(
- typeName, const [ElementKind.CLASS], TopLevelDeclarationKind.type);
+ await _addFix_importLibrary_withElement(typeName,
+ const [ElementKind.CLASS], const [TopLevelDeclarationKind.type]);
}
}
diff --git a/pkg/analysis_server/lib/src/services/correction/levenshtein.dart b/pkg/analysis_server/lib/src/services/correction/levenshtein.dart
index 61cb493..13e16c2 100644
--- a/pkg/analysis_server/lib/src/services/correction/levenshtein.dart
+++ b/pkg/analysis_server/lib/src/services/correction/levenshtein.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
index 79e14d0..14e218e 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index 04baf5f..a4bc4a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/source_buffer.dart b/pkg/analysis_server/lib/src/services/correction/source_buffer.dart
index a414cd5..382bd1a 100644
--- a/pkg/analysis_server/lib/src/services/correction/source_buffer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/source_buffer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index db39ca8..184c81b 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/status.dart b/pkg/analysis_server/lib/src/services/correction/status.dart
index 5cc4cc3..67ec9f8 100644
--- a/pkg/analysis_server/lib/src/services/correction/status.dart
+++ b/pkg/analysis_server/lib/src/services/correction/status.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/correction/strings.dart b/pkg/analysis_server/lib/src/services/correction/strings.dart
index 125fc14..87b6fe3 100644
--- a/pkg/analysis_server/lib/src/services/correction/strings.dart
+++ b/pkg/analysis_server/lib/src/services/correction/strings.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/kythe/schema.dart b/pkg/analysis_server/lib/src/services/kythe/schema.dart
index c354abb..339564a 100644
--- a/pkg/analysis_server/lib/src/services/kythe/schema.dart
+++ b/pkg/analysis_server/lib/src/services/kythe/schema.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 94010f7..34908db 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index a068451..0963233 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
index 94bfd73..e830d48 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 223d699..7bcbb7b 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
@@ -434,6 +434,14 @@
}
}
+class RenameRefactoringElement {
+ final Element element;
+ final int offset;
+ final int length;
+
+ RenameRefactoringElement(this.element, this.offset, this.length);
+}
+
/**
* Abstract [Refactoring] for renaming some [Element].
*/
@@ -475,6 +483,41 @@
return null;
}
+ /// Given a node/element, finds the best element to rename (for example
+ /// the class when on the `new` keyword).
+ static RenameRefactoringElement getElementToRename(
+ AstNode node, Element element) {
+ int offset = node.offset;
+ int length = node.length;
+
+ if (element is FieldFormalParameterElement) {
+ element = (element as FieldFormalParameterElement).field;
+ }
+
+ // Use the prefix offset/length when renaming an import directive.
+ if (node is ImportDirective && element is ImportElement) {
+ if (node.prefix != null) {
+ offset = node.prefix.offset;
+ length = node.prefix.length;
+ } else {
+ // -1 means the name does not exist yet.
+ offset = -1;
+ length = 0;
+ }
+ }
+
+ // Rename the class when on `new` in an instance creation.
+ if (node is InstanceCreationExpression) {
+ InstanceCreationExpression creation = node;
+ var typeIdentifier = creation.constructorName.type.name;
+ element = typeIdentifier.staticElement;
+ offset = typeIdentifier.offset;
+ length = typeIdentifier.length;
+ }
+
+ return new RenameRefactoringElement(element, offset, length);
+ }
+
/**
* Returns the human-readable description of the kind of element being renamed
* (such as “class” or “function type alias”).
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
index 2a81869..9fc3d94 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename.dart b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
index b7663c0..e33f397 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index df98b9e..4f8afd4 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
index 6baadf4..e8d7555 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 2bc3c99..aebeba1 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart
index 012f500..7dbe5bb 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_label.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart
index 8ad6912..cb88700 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_library.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
index 5d20312..cb8683f 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/search/element_visitors.dart b/pkg/analysis_server/lib/src/services/search/element_visitors.dart
index 560edbb7..8dc34d9 100644
--- a/pkg/analysis_server/lib/src/services/search/element_visitors.dart
+++ b/pkg/analysis_server/lib/src/services/search/element_visitors.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/search/hierarchy.dart b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
index 8862eda..5689c32 100644
--- a/pkg/analysis_server/lib/src/services/search/hierarchy.dart
+++ b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine.dart b/pkg/analysis_server/lib/src/services/search/search_engine.dart
index 74445c4..aa5aec9 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index f16268b..2868b74 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index 9e22d01..b9cdaf0 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -1,10 +1,11 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/analysis_server_abstract.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
@@ -13,13 +14,18 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/plugin/resolver_provider.dart';
+abstract class AbstractSocketServer {
+ AnalysisServerOptions get analysisServerOptions;
+ AbstractAnalysisServer get analysisServer;
+}
+
/**
* Instances of the class [SocketServer] implement the common parts of
* http-based and stdio-based analysis servers. The primary responsibility of
* the SocketServer is to manage the lifetime of the AnalysisServer and to
* encode and decode the JSON messages exchanged with the client.
*/
-class SocketServer {
+class SocketServer implements AbstractSocketServer {
final AnalysisServerOptions analysisServerOptions;
/**
diff --git a/pkg/analysis_server/lib/src/status/ast_writer.dart b/pkg/analysis_server/lib/src/status/ast_writer.dart
index 5458b27..060cf6f 100644
--- a/pkg/analysis_server/lib/src/status/ast_writer.dart
+++ b/pkg/analysis_server/lib/src/status/ast_writer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 44fff0a..793b9c3 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
@@ -11,7 +11,10 @@
show PROTOCOL_VERSION;
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/analysis_server_abstract.dart';
import 'package:analysis_server/src/domain_completion.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart'
+ show LspAnalysisServer;
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/server/http_server.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
@@ -145,6 +148,8 @@
}
''';
+/// TODO(devoncarew): We're not currently tracking the time spent in specific
+/// lints by default (analysisOptions / driverOptions enableTiming)
final bool _showLints = false;
String get _sdkVersion {
@@ -159,6 +164,74 @@
return '$name: <code>$value</code><br> ';
}
+abstract class AbstractCompletionPage extends DiagnosticPageWithNav {
+ AbstractCompletionPage(DiagnosticsSite site)
+ : super(site, 'completion', 'Code Completion',
+ description: 'Latency statistics for code completion.');
+
+ pathPackage.Context get pathContext;
+ List<CompletionPerformance> get performanceItems;
+
+ @override
+ Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+
+ List<CompletionPerformance> completions = performanceItems;
+
+ if (completions.isEmpty) {
+ blankslate('No completions recorded.');
+ return;
+ }
+
+ int fastCount =
+ completions.where((c) => c.elapsedInMilliseconds <= 100).length;
+ p('${completions.length} results; ${printPercentage(fastCount / completions.length)} within 100ms.');
+
+ // draw a chart
+ buf.writeln(
+ '<div id="chart-div" style="width: 700px; height: 300px;"></div>');
+ StringBuffer rowData = new StringBuffer();
+ for (int i = completions.length - 1; i >= 0; i--) {
+ // [' ', 101.5]
+ if (rowData.isNotEmpty) {
+ rowData.write(',');
+ }
+ rowData.write("[' ', ${completions[i].elapsedInMilliseconds}]");
+ }
+ buf.writeln('''
+ <script type="text/javascript">
+ google.charts.load('current', {'packages':['bar']});
+ google.charts.setOnLoadCallback(drawChart);
+ function drawChart() {
+ var data = google.visualization.arrayToDataTable([
+ ['Completions', 'Time'],
+ $rowData
+ ]);
+ var options = { bars: 'vertical', vAxis: {format: 'decimal'}, height: 300 };
+ var chart = new google.charts.Bar(document.getElementById('chart-div'));
+ chart.draw(data, google.charts.Bar.convertOptions(options));
+ }
+ </script>
+''');
+
+ // emit the data as a table
+ buf.writeln('<table>');
+ buf.writeln(
+ '<tr><th>Time</th><th>Results</th><th>Source</th><th>Snippet</th></tr>');
+ for (CompletionPerformance completion in completions) {
+ String shortName = pathContext.basename(completion.path);
+ buf.writeln('<tr>'
+ '<td class="pre right">${printMilliseconds(completion.elapsedInMilliseconds)}</td>'
+ '<td class="right">${completion.suggestionCount}</td>'
+ '<td>${escape(shortName)}</td>'
+ '<td><code>${escape(completion.snippet)}</code></td>'
+ '</tr>');
+ }
+ buf.writeln('</table>');
+ }
+}
+
class AstPage extends DiagnosticPageWithNav {
String _description;
@@ -222,6 +295,7 @@
Future generateContent(Map<String, String> params) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
+
void writeRow(List<String> data, {List<String> classes}) {
buf.write("<tr>");
for (int i = 0; i < data.length; i++) {
@@ -237,28 +311,11 @@
buf.writeln('<div class="columns">');
- ServerPerformance perf = server.performanceAfterStartup;
- if (perf != null) {
+ if (server.performanceAfterStartup != null) {
buf.writeln('<div class="column one-half">');
+
h3('Current');
-
- int requestCount = perf.requestCount;
- int averageLatency =
- requestCount > 0 ? (perf.requestLatency ~/ requestCount) : 0;
- int maximumLatency = perf.maxLatency;
- double slowRequestPercent =
- requestCount > 0 ? (perf.slowRequestCount / requestCount) : 0.0;
-
- buf.write('<table>');
- writeRow([printInteger(requestCount), 'requests'],
- classes: ["right", null]);
- writeRow([printMilliseconds(averageLatency), 'average latency'],
- classes: ["right", null]);
- writeRow([printMilliseconds(maximumLatency), 'maximum latency'],
- classes: ["right", null]);
- writeRow([printPercentage(slowRequestPercent), '> 150 ms latency'],
- classes: ["right", null]);
- buf.write('</table>');
+ _writePerformanceTable(server.performanceAfterStartup, writeRow);
String time = server.uptime.toString();
if (time.contains('.')) {
@@ -270,106 +327,64 @@
}
buf.writeln('<div class="column one-half">');
- h3('Startup');
- perf = server.performanceDuringStartup;
+ h3('Startup');
+ _writePerformanceTable(server.performanceDuringStartup, writeRow);
+
+ if (server.performanceAfterStartup != null) {
+ int startupTime = server.performanceAfterStartup.startTime -
+ server.performanceDuringStartup.startTime;
+ buf.writeln(
+ writeOption('Initial analysis time', printMilliseconds(startupTime)));
+ }
+
+ buf.write('</div>');
+
+ buf.write('</div>');
+ }
+
+ void _writePerformanceTable(ServerPerformance perf,
+ void writeRow(List<String> data, {List<String> classes})) {
int requestCount = perf.requestCount;
+ int latencyCount = perf.latencyCount;
int averageLatency =
- requestCount > 0 ? (perf.requestLatency ~/ requestCount) : 0;
+ latencyCount > 0 ? (perf.requestLatency ~/ latencyCount) : 0;
int maximumLatency = perf.maxLatency;
double slowRequestPercent =
- requestCount > 0 ? (perf.slowRequestCount / requestCount) : 0.0;
+ latencyCount > 0 ? (perf.slowRequestCount / latencyCount) : 0.0;
buf.write('<table>');
writeRow([printInteger(requestCount), 'requests'],
classes: ["right", null]);
- writeRow([printMilliseconds(averageLatency), 'average latency'],
+ writeRow([printInteger(latencyCount), 'requests with latency information'],
classes: ["right", null]);
- writeRow([printMilliseconds(maximumLatency), 'maximum latency'],
- classes: ["right", null]);
- writeRow([printPercentage(slowRequestPercent), '> 150 ms latency'],
- classes: ["right", null]);
- buf.write('</table>');
-
- if (server.performanceAfterStartup != null) {
- int startupTime =
- server.performanceAfterStartup.startTime - perf.startTime;
- buf.writeln(
- writeOption('Initial analysis time', printMilliseconds(startupTime)));
+ if (latencyCount > 0) {
+ writeRow([printMilliseconds(averageLatency), 'average latency'],
+ classes: ["right", null]);
+ writeRow([printMilliseconds(maximumLatency), 'maximum latency'],
+ classes: ["right", null]);
+ writeRow([printPercentage(slowRequestPercent), '> 150 ms latency'],
+ classes: ["right", null]);
}
- buf.write('</div>');
-
- buf.write('</div>');
+ buf.write('</table>');
}
}
-class CompletionPage extends DiagnosticPageWithNav {
- CompletionPage(DiagnosticsSite site)
- : super(site, 'completion', 'Code Completion',
- description: 'Latency statistics for code completion.');
+class CompletionPage extends AbstractCompletionPage {
+ @override
+ AnalysisServer server;
+ CompletionPage(DiagnosticsSite site, this.server) : super(site);
+
+ CompletionDomainHandler get completionDomain => server.handlers
+ .firstWhere((handler) => handler is CompletionDomainHandler);
@override
- Future generateContent(Map<String, String> params) async {
- // TODO(brianwilkerson) Determine whether this await is necessary.
- await null;
- CompletionDomainHandler completionDomain = server.handlers
- .firstWhere((handler) => handler is CompletionDomainHandler);
+ pathPackage.Context get pathContext =>
+ completionDomain.server.resourceProvider.pathContext;
- List<CompletionPerformance> completions =
- completionDomain.performanceList.items.toList();
-
- if (completions.isEmpty) {
- blankslate('No completions recorded.');
- return;
- }
-
- int fastCount =
- completions.where((c) => c.elapsedInMilliseconds <= 100).length;
- p('${completions.length} results; ${printPercentage(fastCount / completions.length)} within 100ms.');
-
- // draw a chart
- buf.writeln(
- '<div id="chart-div" style="width: 700px; height: 300px;"></div>');
- StringBuffer rowData = new StringBuffer();
- for (int i = completions.length - 1; i >= 0; i--) {
- // [' ', 101.5]
- if (rowData.isNotEmpty) {
- rowData.write(',');
- }
- rowData.write("[' ', ${completions[i].elapsedInMilliseconds}]");
- }
- buf.writeln('''
- <script type="text/javascript">
- google.charts.load('current', {'packages':['bar']});
- google.charts.setOnLoadCallback(drawChart);
- function drawChart() {
- var data = google.visualization.arrayToDataTable([
- ['Completions', 'Time'],
- $rowData
- ]);
- var options = { bars: 'vertical', vAxis: {format: 'decimal'}, height: 300 };
- var chart = new google.charts.Bar(document.getElementById('chart-div'));
- chart.draw(data, google.charts.Bar.convertOptions(options));
- }
- </script>
-''');
-
- // emit the data as a table
- buf.writeln('<table>');
- buf.writeln(
- '<tr><th>Time</th><th>Results</th><th>Source</th><th>Snippet</th></tr>');
- var pathContext = completionDomain.server.resourceProvider.pathContext;
- for (CompletionPerformance completion in completions) {
- String shortName = pathContext.basename(completion.path);
- buf.writeln('<tr>'
- '<td class="pre right">${printMilliseconds(completion.elapsedInMilliseconds)}</td>'
- '<td class="right">${completion.suggestionCount}</td>'
- '<td>${escape(shortName)}</td>'
- '<td><code>${escape(completion.snippet)}</code></td>'
- '</tr>');
- }
- buf.writeln('</table>');
- }
+ @override
+ List<CompletionPerformance> get performanceItems =>
+ completionDomain.performanceList.items.toList();
}
class ContextsPage extends DiagnosticPageWithNav {
@@ -575,15 +590,14 @@
/// A page with a proscriptive notion of layout.
abstract class DiagnosticPage extends Page {
- final Site site;
+ final DiagnosticsSite site;
DiagnosticPage(this.site, String id, String title, {String description})
: super(id, title, description: description);
bool get isNavPage => false;
- AnalysisServer get server =>
- (site as DiagnosticsSite).socketServer.analysisServer;
+ AbstractAnalysisServer get server => site.socketServer.analysisServer;
Future<void> generateContainer(Map<String, String> params) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
@@ -661,7 +675,7 @@
}
abstract class DiagnosticPageWithNav extends DiagnosticPage {
- DiagnosticPageWithNav(Site site, String id, String title,
+ DiagnosticPageWithNav(DiagnosticsSite site, String id, String title,
{String description})
: super(site, id, title, description: description);
@@ -711,22 +725,31 @@
class DiagnosticsSite extends Site implements AbstractGetHandler {
/// An object that can handle either a WebSocket connection or a connection
/// to the client over stdio.
- SocketServer socketServer;
+ AbstractSocketServer socketServer;
/// The last few lines printed.
final List<String> lastPrintedLines;
DiagnosticsSite(this.socketServer, this.lastPrintedLines)
: super('Analysis Server') {
- pages.add(new CompletionPage(this));
pages.add(new CommunicationsPage(this));
pages.add(new ContextsPage(this));
pages.add(new EnvironmentVariablesPage(this));
pages.add(new ExceptionsPage(this));
pages.add(new InstrumentationPage(this));
- pages.add(new PluginsPage(this));
pages.add(new ProfilePage(this));
- pages.add(new SubscriptionsPage(this));
+
+ // Add server-specific pages. Ordering doesn't matter as the items are
+ // sorted later.
+ final server = this.socketServer.analysisServer;
+ if (server is AnalysisServer) {
+ pages.add(new CompletionPage(this, server));
+ pages.add(new PluginsPage(this, server));
+ pages.add(new SubscriptionsPage(this, server));
+ } else if (server is LspAnalysisServer) {
+ pages.add(new LspCompletionPage(this, server));
+ pages.add(new LspCapabilitiesPage(this, server));
+ }
ProcessProfiler profiler = ProcessProfiler.getProfilerForPlatform();
if (profiler != null) {
@@ -831,7 +854,7 @@
class ExceptionPage extends DiagnosticPage {
final StackTrace trace;
- ExceptionPage(Site site, String message, this.trace)
+ ExceptionPage(DiagnosticsSite site, String message, this.trace)
: super(site, '', '500 Oops', description: message);
Future generateContent(Map<String, String> params) async {
@@ -948,6 +971,51 @@
}
}
+class LspCapabilitiesPage extends DiagnosticPageWithNav {
+ @override
+ LspAnalysisServer server;
+
+ LspCapabilitiesPage(DiagnosticsSite site, this.server)
+ : super(site, 'lsp_capabilities', 'LSP Capabilities',
+ description: 'Client and Server LSP Capabilities.');
+
+ @override
+ Future generateContent(Map<String, String> params) async {
+ buf.writeln('<div class="columns">');
+
+ buf.writeln('<div class="column one-half">');
+ h3('Client Capabilities');
+ if (server.clientCapabilities == null) {
+ p('Client capabilities have not yet been received.');
+ } else {
+ prettyJson(server.clientCapabilities.toJson());
+ }
+ buf.writeln('</div>');
+
+ buf.writeln('<div class="column one-half">');
+ h3('Server Capabilities');
+ if (server.capabilities == null) {
+ p('Server capabilities have not yet been computed.');
+ } else {
+ prettyJson(server.capabilities.toJson());
+ }
+ buf.writeln('</div>');
+ }
+}
+
+class LspCompletionPage extends AbstractCompletionPage {
+ @override
+ LspAnalysisServer server;
+ LspCompletionPage(DiagnosticsSite site, this.server) : super(site);
+
+ @override
+ pathPackage.Context get pathContext => server.resourceProvider.pathContext;
+
+ @override
+ List<CompletionPerformance> get performanceItems =>
+ server.performanceStats.completion.items.toList();
+}
+
class MemoryAndCpuPage extends DiagnosticPageWithNav {
final ProcessProfiler profiler;
@@ -1018,7 +1086,7 @@
class NotFoundPage extends DiagnosticPage {
final String path;
- NotFoundPage(Site site, this.path)
+ NotFoundPage(DiagnosticsSite site, this.path)
: super(site, '', '404 Not found', description: "'$path' not found.");
Future generateContent(Map<String, String> params) async {
@@ -1027,16 +1095,18 @@
}
}
-// TODO(devoncarew): We're not currently tracking the time spent in specific
-// lints by default (analysisOptions / driverOptions enableTiming)
class PluginsPage extends DiagnosticPageWithNav {
- PluginsPage(DiagnosticsSite site)
+ @override
+ AnalysisServer server;
+
+ PluginsPage(DiagnosticsSite site, this.server)
: super(site, 'plugins', 'Plugins', description: 'Plugins in use.');
@override
Future generateContent(Map<String, String> params) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
+
h3('Analysis plugins');
List<PluginInfo> analysisPlugins = server.pluginManager.plugins;
@@ -1255,6 +1325,7 @@
buf.writeln('<div class="column one-half">');
h3('Status');
+ buf.writeln(writeOption('Server type', server.runtimeType));
buf.writeln(writeOption('Instrumentation enabled',
AnalysisEngine.instance.instrumentationService.isActive));
bool uxExp1 =
@@ -1276,7 +1347,7 @@
buf.writeln('</div>');
- List<String> lines = (site as DiagnosticsSite).lastPrintedLines;
+ List<String> lines = site.lastPrintedLines;
if (lines.isNotEmpty) {
h3('Debug output');
p(lines.join('\n'), style: 'white-space: pre');
@@ -1285,7 +1356,10 @@
}
class SubscriptionsPage extends DiagnosticPageWithNav {
- SubscriptionsPage(DiagnosticsSite site)
+ @override
+ AnalysisServer server;
+
+ SubscriptionsPage(DiagnosticsSite site, this.server)
: super(site, 'subscriptions', 'Subscriptions',
description: 'Registered subscriptions to analysis server events.');
@@ -1293,6 +1367,7 @@
Future generateContent(Map<String, String> params) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
+
// server domain
h3('Server domain subscriptions');
ul(ServerService.VALUES, (item) {
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index 3b6ac79..4e8d3ec 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/status/pages.dart b/pkg/analysis_server/lib/src/status/pages.dart
index 41b9b80..ff199b9 100644
--- a/pkg/analysis_server/lib/src/status/pages.dart
+++ b/pkg/analysis_server/lib/src/status/pages.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
@@ -122,6 +122,13 @@
buf.writeln('</pre>');
}
+ void prettyJson(Map<String, dynamic> data) {
+ const jsonEncoder = const JsonEncoder.withIndent(' ');
+ pre(() {
+ buf.write(jsonEncoder.convert(data));
+ });
+ }
+
void ul<T>(Iterable<T> items, void gen(T item), {String classes}) {
buf.writeln('<ul${classes == null ? '' : ' class=$classes'}>');
for (T item in items) {
diff --git a/pkg/analysis_server/lib/src/status/tree_writer.dart b/pkg/analysis_server/lib/src/status/tree_writer.dart
index 62b07f1..130c4ad 100644
--- a/pkg/analysis_server/lib/src/status/tree_writer.dart
+++ b/pkg/analysis_server/lib/src/status/tree_writer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/utilities/documentation.dart b/pkg/analysis_server/lib/src/utilities/documentation.dart
index 2cc837e..b47bb2f 100644
--- a/pkg/analysis_server/lib/src/utilities/documentation.dart
+++ b/pkg/analysis_server/lib/src/utilities/documentation.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index 6e754c3..3c63b01 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/utilities/null_string_sink.dart b/pkg/analysis_server/lib/src/utilities/null_string_sink.dart
index 27fef3a..d43c821 100644
--- a/pkg/analysis_server/lib/src/utilities/null_string_sink.dart
+++ b/pkg/analysis_server/lib/src/utilities/null_string_sink.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/src/utilities/profiling.dart b/pkg/analysis_server/lib/src/utilities/profiling.dart
index 9dbd260..d283e10 100644
--- a/pkg/analysis_server/lib/src/utilities/profiling.dart
+++ b/pkg/analysis_server/lib/src/utilities/profiling.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/lib/src/watch_manager.dart b/pkg/analysis_server/lib/src/watch_manager.dart
index 8a3fc97..f7bd8c9 100644
--- a/pkg/analysis_server/lib/src/watch_manager.dart
+++ b/pkg/analysis_server/lib/src/watch_manager.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/lib/starter.dart b/pkg/analysis_server/lib/starter.dart
index 949e761..170c4b8 100644
--- a/pkg/analysis_server/lib/starter.dart
+++ b/pkg/analysis_server/lib/starter.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/analysis/get_errors_test.dart b/pkg/analysis_server/test/analysis/get_errors_test.dart
index cb0baa7..db150ad 100644
--- a/pkg/analysis_server/test/analysis/get_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/get_errors_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index ac43af1..faadc26 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index d620a0d..cc31c34 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart
index 10567ce..e91c889 100644
--- a/pkg/analysis_server/test/analysis/get_signature_test.dart
+++ b/pkg/analysis_server/test/analysis/get_signature_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart b/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart
index 90b04f2..4f5ed10 100644
--- a/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_analysis_options_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart b/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
index 305acd3..bd83a7d 100644
--- a/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_closingLabels_test.dart b/pkg/analysis_server/test/analysis/notification_closingLabels_test.dart
index d09ef04..a8a2d10 100644
--- a/pkg/analysis_server/test/analysis/notification_closingLabels_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_closingLabels_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index 773fd9f..a270f6c 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_folding_test.dart b/pkg/analysis_server/test/analysis/notification_folding_test.dart
index 3adbf5b..492718f 100644
--- a/pkg/analysis_server/test/analysis/notification_folding_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_folding_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 54793b6..1046cbe 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_highlights_test.dart b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
index f36e5d8..030addf 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_implemented_test.dart b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
index ebcd3a7..4401087 100644
--- a/pkg/analysis_server/test/analysis/notification_implemented_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 8035395..7a7aa0f 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_occurrences_test.dart b/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
index df66d76..be5f9ff 100644
--- a/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_occurrences_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_outline_test.dart b/pkg/analysis_server/test/analysis/notification_outline_test.dart
index a358bba..c9b26aa 100644
--- a/pkg/analysis_server/test/analysis/notification_outline_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_outline_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/notification_overrides_test.dart b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
index aa9a69d..dfaec37 100644
--- a/pkg/analysis_server/test/analysis/notification_overrides_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/reanalyze_test.dart b/pkg/analysis_server/test/analysis/reanalyze_test.dart
index 1606a84..3d745d7 100644
--- a/pkg/analysis_server/test/analysis/reanalyze_test.dart
+++ b/pkg/analysis_server/test/analysis/reanalyze_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index 993fb07..bb6530d 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/test_all.dart b/pkg/analysis_server/test/analysis/test_all.dart
index 9628319..5b8b7e9 100644
--- a/pkg/analysis_server/test/analysis/test_all.dart
+++ b/pkg/analysis_server/test/analysis/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index 079ec1c..5ab9a4e 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/benchmarks_test.dart b/pkg/analysis_server/test/benchmarks_test.dart
index 96c4c0f..21e70e5 100644
--- a/pkg/analysis_server/test/benchmarks_test.dart
+++ b/pkg/analysis_server/test/benchmarks_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.=> defineTests();
diff --git a/pkg/analysis_server/test/channel/byte_stream_channel_test.dart b/pkg/analysis_server/test/channel/byte_stream_channel_test.dart
index f6a0692..a11b461 100644
--- a/pkg/analysis_server/test/channel/byte_stream_channel_test.dart
+++ b/pkg/analysis_server/test/channel/byte_stream_channel_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/channel/test_all.dart b/pkg/analysis_server/test/channel/test_all.dart
index ce5e85a..3edd228 100644
--- a/pkg/analysis_server/test/channel/test_all.dart
+++ b/pkg/analysis_server/test/channel/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index 50b8449..d0cd508 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/completion_test_support.dart b/pkg/analysis_server/test/completion_test_support.dart
index 06829ed..0af04a9 100644
--- a/pkg/analysis_server/test/completion_test_support.dart
+++ b/pkg/analysis_server/test/completion_test_support.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 3c5a3e7..4a7e95d 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -1681,7 +1681,7 @@
]);
AnalysisError invalid_assignment_error =
- new AnalysisError(null, 0, 1, HintCode.INVALID_ASSIGNMENT, [
+ new AnalysisError(null, 0, 1, StaticTypeWarningCode.INVALID_ASSIGNMENT, [
['x'],
['y']
]);
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 5c57465..f22f2f2 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 7d0721b..190c397 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index 7a84c54..987506c 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index 16bcdd2..edd543c 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -111,6 +111,55 @@
''');
}
+ test_dartfix_non_nullable() async {
+ // Add analysis options to enable non-nullable analysis
+ newFile('/project/analysis_options.yaml', content: '''
+analyzer:
+ enable-experiment:
+ - non-nullable
+''');
+
+ createProject();
+ addTestFile('''
+main() {
+ functionWithNullableParam(new List<Object>(1));
+ functionWithNullableParam(null);
+}
+
+void functionWithNullableParam(Object object) {
+ if (object == null) {
+ print('object is null');
+ } else {
+ print('object is not-null');
+ }
+ List<Object> list = null;
+ list = <Object>[];
+ list.add(object);
+}
+''');
+ EditDartfixResult result = await performFix();
+ expect(result.suggestions, hasLength(1));
+ expect(result.hasErrors, isFalse);
+ expectSuggestion(result.suggestions[0], 'non-nullable', 46, 6);
+ expectEdits(result.edits, '''
+main() {
+ functionWithNullableParam(new List<Object?>(1));
+ functionWithNullableParam(null);
+}
+
+void functionWithNullableParam(Object? object) {
+ if (object == null) {
+ print('object is null');
+ } else {
+ print('object is not-null');
+ }
+ List<Object?>? list = null;
+ list = <Object?>[];
+ list.add(object);
+}
+''');
+ }
+
test_dartfix_excludedSource() async {
// Add analysis options to exclude the lib directory then reanalyze
newFile('/project/analysis_options.yaml', content: '''
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 1d8389f..120b2de 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/edit/assists_test.dart b/pkg/analysis_server/test/edit/assists_test.dart
index 399706d..d8a77f0 100644
--- a/pkg/analysis_server/test/edit/assists_test.dart
+++ b/pkg/analysis_server/test/edit/assists_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/edit/format_test.dart b/pkg/analysis_server/test/edit/format_test.dart
index ced5eab..1c18cbf 100644
--- a/pkg/analysis_server/test/edit/format_test.dart
+++ b/pkg/analysis_server/test/edit/format_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
index 9ca4c06..e8424aa 100644
--- a/pkg/analysis_server/test/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/edit/postfix_completion_test.dart b/pkg/analysis_server/test/edit/postfix_completion_test.dart
index 7a64a92..00139e5 100644
--- a/pkg/analysis_server/test/edit/postfix_completion_test.dart
+++ b/pkg/analysis_server/test/edit/postfix_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index b696ea8..da70280 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index 2da9a0a..04828b6 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/edit/statement_completion_test.dart b/pkg/analysis_server/test/edit/statement_completion_test.dart
index 7df82ba..50f834b 100644
--- a/pkg/analysis_server/test/edit/statement_completion_test.dart
+++ b/pkg/analysis_server/test/edit/statement_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/edit/test_all.dart b/pkg/analysis_server/test/edit/test_all.dart
index 1376ea6..79cc139 100644
--- a/pkg/analysis_server/test/edit/test_all.dart
+++ b/pkg/analysis_server/test/edit/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/analysis_options_test.dart b/pkg/analysis_server/test/integration/analysis/analysis_options_test.dart
index e27f275..6088003 100644
--- a/pkg/analysis_server/test/integration/analysis/analysis_options_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/analysis_options_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index 1c32caa..4da91dc 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
index 4b102a6..c9be4cd 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_errors_test.dart b/pkg/analysis_server/test/integration/analysis/get_errors_test.dart
index d549e9e..f9e0c95 100644
--- a/pkg/analysis_server/test/integration/analysis/get_errors_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_errors_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index 8c179cc..e2f25af 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_imported_elements_test.dart b/pkg/analysis_server/test/integration/analysis/get_imported_elements_test.dart
index 65deb3b..29e8ec6 100644
--- a/pkg/analysis_server/test/integration/analysis/get_imported_elements_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_imported_elements_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_library_dependencies_test.dart b/pkg/analysis_server/test/integration/analysis/get_library_dependencies_test.dart
index 51a7659..7f30150 100644
--- a/pkg/analysis_server/test/integration/analysis/get_library_dependencies_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_library_dependencies_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_navigation_test.dart b/pkg/analysis_server/test/integration/analysis/get_navigation_test.dart
index 9725e58..b3943bc 100644
--- a/pkg/analysis_server/test/integration/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_navigation_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart b/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart
index eb2ea8b..286a24e 100644
--- a/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/highlights2_test.dart b/pkg/analysis_server/test/integration/analysis/highlights2_test.dart
index d9f1ebc..d837ff2 100644
--- a/pkg/analysis_server/test/integration/analysis/highlights2_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/highlights2_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/highlights_test.dart b/pkg/analysis_server/test/integration/analysis/highlights_test.dart
index 613a45d..95dfea5 100644
--- a/pkg/analysis_server/test/integration/analysis/highlights_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/highlights_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
index 6703374..585120f 100644
--- a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/integration/analysis/lint_test.dart b/pkg/analysis_server/test/integration/analysis/lint_test.dart
index 699b43b..ebe8986 100644
--- a/pkg/analysis_server/test/integration/analysis/lint_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/lint_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/navigation_test.dart b/pkg/analysis_server/test/integration/analysis/navigation_test.dart
index 1302b67..61c3f86 100644
--- a/pkg/analysis_server/test/integration/analysis/navigation_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/navigation_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/occurrences_test.dart b/pkg/analysis_server/test/integration/analysis/occurrences_test.dart
index 35a9416..787aa63 100644
--- a/pkg/analysis_server/test/integration/analysis/occurrences_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/occurrences_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/outline_test.dart b/pkg/analysis_server/test/integration/analysis/outline_test.dart
index eafefe8..41ec2b9 100644
--- a/pkg/analysis_server/test/integration/analysis/outline_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/outline_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/overrides_test.dart b/pkg/analysis_server/test/integration/analysis/overrides_test.dart
index 32c238c..a045fb6 100644
--- a/pkg/analysis_server/test/integration/analysis/overrides_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/overrides_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/package_root_test.dart b/pkg/analysis_server/test/integration/analysis/package_root_test.dart
index 0491f9b..09c94a4 100644
--- a/pkg/analysis_server/test/integration/analysis/package_root_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/package_root_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/reanalyze_concurrent_test.dart b/pkg/analysis_server/test/integration/analysis/reanalyze_concurrent_test.dart
index cb707e2..e79a1e1 100644
--- a/pkg/analysis_server/test/integration/analysis/reanalyze_concurrent_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/reanalyze_concurrent_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/reanalyze_test.dart b/pkg/analysis_server/test/integration/analysis/reanalyze_test.dart
index 8740ef0..60fe554 100644
--- a/pkg/analysis_server/test/integration/analysis/reanalyze_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/reanalyze_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/set_analysis_roots_test.dart b/pkg/analysis_server/test/integration/analysis/set_analysis_roots_test.dart
index f6c1d61..c0aa33e 100644
--- a/pkg/analysis_server/test/integration/analysis/set_analysis_roots_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/set_analysis_roots_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart b/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
index ce90165..eeef19e 100644
--- a/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/integration/analysis/set_priority_files_test.dart
index 10cb1a0..e1ef4cf 100644
--- a/pkg/analysis_server/test/integration/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/set_priority_files_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/set_subscriptions_test.dart b/pkg/analysis_server/test/integration/analysis/set_subscriptions_test.dart
index 9524b4d..b5d60d4 100644
--- a/pkg/analysis_server/test/integration/analysis/set_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/set_subscriptions_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/test_all.dart b/pkg/analysis_server/test/integration/analysis/test_all.dart
index d85814a..a0cdc52 100644
--- a/pkg/analysis_server/test/integration/analysis/test_all.dart
+++ b/pkg/analysis_server/test/integration/analysis/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/update_content_list_test.dart b/pkg/analysis_server/test/integration/analysis/update_content_list_test.dart
index d44cce7..6c28e46 100644
--- a/pkg/analysis_server/test/integration/analysis/update_content_list_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/update_content_list_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/update_content_test.dart b/pkg/analysis_server/test/integration/analysis/update_content_test.dart
index cc4ceae..c25b133 100644
--- a/pkg/analysis_server/test/integration/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/update_content_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/analysis/update_options_test.dart b/pkg/analysis_server/test/integration/analysis/update_options_test.dart
index 1172d78..b61db22 100644
--- a/pkg/analysis_server/test/integration/analysis/update_options_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/update_options_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analytics/enable_test.dart b/pkg/analysis_server/test/integration/analytics/enable_test.dart
index 72e261d..19296ee 100644
--- a/pkg/analysis_server/test/integration/analytics/enable_test.dart
+++ b/pkg/analysis_server/test/integration/analytics/enable_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analytics/is_enabled_test.dart b/pkg/analysis_server/test/integration/analytics/is_enabled_test.dart
index 8e2ffd5..15b5cf8 100644
--- a/pkg/analysis_server/test/integration/analytics/is_enabled_test.dart
+++ b/pkg/analysis_server/test/integration/analytics/is_enabled_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analytics/send_event_test.dart b/pkg/analysis_server/test/integration/analytics/send_event_test.dart
index fbeb48a..5a0b09e 100644
--- a/pkg/analysis_server/test/integration/analytics/send_event_test.dart
+++ b/pkg/analysis_server/test/integration/analytics/send_event_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analytics/send_timing_test.dart b/pkg/analysis_server/test/integration/analytics/send_timing_test.dart
index fb65d8a..141e3b7 100644
--- a/pkg/analysis_server/test/integration/analytics/send_timing_test.dart
+++ b/pkg/analysis_server/test/integration/analytics/send_timing_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/analytics/test_all.dart b/pkg/analysis_server/test/integration/analytics/test_all.dart
index d4352b7..f9e7963 100644
--- a/pkg/analysis_server/test/integration/analytics/test_all.dart
+++ b/pkg/analysis_server/test/integration/analytics/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart b/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
index cf031cf..888a1d2 100644
--- a/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
+++ b/pkg/analysis_server/test/integration/completion/get_suggestions_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/completion/test_all.dart b/pkg/analysis_server/test/integration/completion/test_all.dart
index f07053b..1b5962b 100644
--- a/pkg/analysis_server/test/integration/completion/test_all.dart
+++ b/pkg/analysis_server/test/integration/completion/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/coverage_test.dart b/pkg/analysis_server/test/integration/coverage_test.dart
index b8b3c14..a1e5284 100644
--- a/pkg/analysis_server/test/integration/coverage_test.dart
+++ b/pkg/analysis_server/test/integration/coverage_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart b/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart
index e8bf76e..1eb2a17 100644
--- a/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart
+++ b/pkg/analysis_server/test/integration/diagnostic/get_diagnostics_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/diagnostic/get_server_port_test.dart b/pkg/analysis_server/test/integration/diagnostic/get_server_port_test.dart
index 37efe2c..6005964 100644
--- a/pkg/analysis_server/test/integration/diagnostic/get_server_port_test.dart
+++ b/pkg/analysis_server/test/integration/diagnostic/get_server_port_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/diagnostic/test_all.dart b/pkg/analysis_server/test/integration/diagnostic/test_all.dart
index 4e45dea..5265193 100644
--- a/pkg/analysis_server/test/integration/diagnostic/test_all.dart
+++ b/pkg/analysis_server/test/integration/diagnostic/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/format_test.dart b/pkg/analysis_server/test/integration/edit/format_test.dart
index 8906109..8380c5b 100644
--- a/pkg/analysis_server/test/integration/edit/format_test.dart
+++ b/pkg/analysis_server/test/integration/edit/format_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/get_assists_test.dart b/pkg/analysis_server/test/integration/edit/get_assists_test.dart
index 69e10f0..f2b57dc 100644
--- a/pkg/analysis_server/test/integration/edit/get_assists_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_assists_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/get_available_refactorings_test.dart b/pkg/analysis_server/test/integration/edit/get_available_refactorings_test.dart
index 820b586..ddbcfe6 100644
--- a/pkg/analysis_server/test/integration/edit/get_available_refactorings_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_available_refactorings_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/get_fixes_test.dart b/pkg/analysis_server/test/integration/edit/get_fixes_test.dart
index cfe923e..81af6dea 100644
--- a/pkg/analysis_server/test/integration/edit/get_fixes_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_fixes_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart b/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart
index 598b4c0..4e0257e 100644
--- a/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/get_refactoring_test.dart b/pkg/analysis_server/test/integration/edit/get_refactoring_test.dart
index c3e5553..93c34fe 100644
--- a/pkg/analysis_server/test/integration/edit/get_refactoring_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_refactoring_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/get_statement_completion_test.dart b/pkg/analysis_server/test/integration/edit/get_statement_completion_test.dart
index 610ece0..b3caa20 100644
--- a/pkg/analysis_server/test/integration/edit/get_statement_completion_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_statement_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/import_elements_test.dart b/pkg/analysis_server/test/integration/edit/import_elements_test.dart
index 9beed5a..842f470 100644
--- a/pkg/analysis_server/test/integration/edit/import_elements_test.dart
+++ b/pkg/analysis_server/test/integration/edit/import_elements_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/is_postfix_completion_applicable_test.dart b/pkg/analysis_server/test/integration/edit/is_postfix_completion_applicable_test.dart
index be1ff11..7c65699 100644
--- a/pkg/analysis_server/test/integration/edit/is_postfix_completion_applicable_test.dart
+++ b/pkg/analysis_server/test/integration/edit/is_postfix_completion_applicable_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/list_postfix_completion_templates_test.dart b/pkg/analysis_server/test/integration/edit/list_postfix_completion_templates_test.dart
index f248e06..63f13e4 100644
--- a/pkg/analysis_server/test/integration/edit/list_postfix_completion_templates_test.dart
+++ b/pkg/analysis_server/test/integration/edit/list_postfix_completion_templates_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/organize_directives_test.dart b/pkg/analysis_server/test/integration/edit/organize_directives_test.dart
index 0e372f4..e5b0a46 100644
--- a/pkg/analysis_server/test/integration/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/integration/edit/organize_directives_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/sort_members_test.dart b/pkg/analysis_server/test/integration/edit/sort_members_test.dart
index 3ff78a7..1896537 100644
--- a/pkg/analysis_server/test/integration/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/integration/edit/sort_members_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/edit/test_all.dart b/pkg/analysis_server/test/integration/edit/test_all.dart
index 81aa121..6706806 100644
--- a/pkg/analysis_server/test/integration/edit/test_all.dart
+++ b/pkg/analysis_server/test/integration/edit/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/execution/create_context_test.dart b/pkg/analysis_server/test/integration/execution/create_context_test.dart
index 6564810..f73fe9a 100644
--- a/pkg/analysis_server/test/integration/execution/create_context_test.dart
+++ b/pkg/analysis_server/test/integration/execution/create_context_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/execution/delete_context_test.dart b/pkg/analysis_server/test/integration/execution/delete_context_test.dart
index c807fa5..a22a9e8 100644
--- a/pkg/analysis_server/test/integration/execution/delete_context_test.dart
+++ b/pkg/analysis_server/test/integration/execution/delete_context_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/execution/map_uri_test.dart b/pkg/analysis_server/test/integration/execution/map_uri_test.dart
index f5abbc0..8038545 100644
--- a/pkg/analysis_server/test/integration/execution/map_uri_test.dart
+++ b/pkg/analysis_server/test/integration/execution/map_uri_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart b/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart
index 441093b..a95fc27 100644
--- a/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/execution/test_all.dart b/pkg/analysis_server/test/integration/execution/test_all.dart
index 6da630d..4f6af5d 100644
--- a/pkg/analysis_server/test/integration/execution/test_all.dart
+++ b/pkg/analysis_server/test/integration/execution/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/kythe/get_kythe_entries_test.dart b/pkg/analysis_server/test/integration/kythe/get_kythe_entries_test.dart
index ccd3c49..0d823a9 100644
--- a/pkg/analysis_server/test/integration/kythe/get_kythe_entries_test.dart
+++ b/pkg/analysis_server/test/integration/kythe/get_kythe_entries_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/kythe/test_all.dart b/pkg/analysis_server/test/integration/kythe/test_all.dart
index d65cff4..0573a6c 100644
--- a/pkg/analysis_server/test/integration/kythe/test_all.dart
+++ b/pkg/analysis_server/test/integration/kythe/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/search/find_element_references_test.dart b/pkg/analysis_server/test/integration/search/find_element_references_test.dart
index 6ea7f6e..eac13f5 100644
--- a/pkg/analysis_server/test/integration/search/find_element_references_test.dart
+++ b/pkg/analysis_server/test/integration/search/find_element_references_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/search/find_member_declarations_test.dart b/pkg/analysis_server/test/integration/search/find_member_declarations_test.dart
index 81148c0..f91ba02 100644
--- a/pkg/analysis_server/test/integration/search/find_member_declarations_test.dart
+++ b/pkg/analysis_server/test/integration/search/find_member_declarations_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/search/find_member_references_test.dart b/pkg/analysis_server/test/integration/search/find_member_references_test.dart
index 36fccbc..9ffc95f 100644
--- a/pkg/analysis_server/test/integration/search/find_member_references_test.dart
+++ b/pkg/analysis_server/test/integration/search/find_member_references_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/search/find_top_level_declarations_test.dart b/pkg/analysis_server/test/integration/search/find_top_level_declarations_test.dart
index 66352f8..4d37e1e 100644
--- a/pkg/analysis_server/test/integration/search/find_top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/integration/search/find_top_level_declarations_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/integration/search/get_type_hierarchy_test.dart b/pkg/analysis_server/test/integration/search/get_type_hierarchy_test.dart
index da44055..2758ed1 100644
--- a/pkg/analysis_server/test/integration/search/get_type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/integration/search/get_type_hierarchy_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/search/test_all.dart b/pkg/analysis_server/test/integration/search/test_all.dart
index bf7e7a4..c7cc8b8 100644
--- a/pkg/analysis_server/test/integration/search/test_all.dart
+++ b/pkg/analysis_server/test/integration/search/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/server/get_version_test.dart b/pkg/analysis_server/test/integration/server/get_version_test.dart
index c3dc407..7fca35a 100644
--- a/pkg/analysis_server/test/integration/server/get_version_test.dart
+++ b/pkg/analysis_server/test/integration/server/get_version_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/server/set_subscriptions_invalid_service_test.dart b/pkg/analysis_server/test/integration/server/set_subscriptions_invalid_service_test.dart
index c95e046..6bfde08 100644
--- a/pkg/analysis_server/test/integration/server/set_subscriptions_invalid_service_test.dart
+++ b/pkg/analysis_server/test/integration/server/set_subscriptions_invalid_service_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/server/set_subscriptions_test.dart b/pkg/analysis_server/test/integration/server/set_subscriptions_test.dart
index d6de65b..6e9e672 100644
--- a/pkg/analysis_server/test/integration/server/set_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/server/set_subscriptions_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/server/shutdown_test.dart b/pkg/analysis_server/test/integration/server/shutdown_test.dart
index 8478d48..ce7e5d4 100644
--- a/pkg/analysis_server/test/integration/server/shutdown_test.dart
+++ b/pkg/analysis_server/test/integration/server/shutdown_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/server/status_test.dart b/pkg/analysis_server/test/integration/server/status_test.dart
index 72163c3..411d1bc 100644
--- a/pkg/analysis_server/test/integration/server/status_test.dart
+++ b/pkg/analysis_server/test/integration/server/status_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/server/test_all.dart b/pkg/analysis_server/test/integration/server/test_all.dart
index 6ab8ac9..2ef3625 100644
--- a/pkg/analysis_server/test/integration/server/test_all.dart
+++ b/pkg/analysis_server/test/integration/server/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 3e82faf..6630dbe 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -202,6 +202,7 @@
* "relevance": int
* "completion": String
* "displayText": optional String
+ * "elementUri": optional String
* "selectionOffset": int
* "selectionLength": int
* "isDeprecated": bool
@@ -233,6 +234,7 @@
"isPotential": isBool
}, optionalFields: {
"displayText": isString,
+ "elementUri": isString,
"docSummary": isString,
"docComplete": isString,
"declaringType": isString,
diff --git a/pkg/analysis_server/test/integration/test_all.dart b/pkg/analysis_server/test/integration/test_all.dart
index c69d15b..ce11216 100644
--- a/pkg/analysis_server/test/integration/test_all.dart
+++ b/pkg/analysis_server/test/integration/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
new file mode 100644
index 0000000..fd0e3c0
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ChangeWorkspaceFoldersTest);
+ });
+}
+
+@reflectiveTest
+class ChangeWorkspaceFoldersTest extends AbstractLspAnalysisServerTest {
+ String workspaceFolder1Path, workspaceFolder2Path, workspaceFolder3Path;
+ Uri workspaceFolder1Uri, workspaceFolder2Uri, workspaceFolder3Uri;
+
+ @override
+ void setUp() {
+ super.setUp();
+ workspaceFolder1Path = convertPath('/workspace1');
+ workspaceFolder2Path = convertPath('/workspace2');
+ workspaceFolder3Path = convertPath('/workspace3');
+ workspaceFolder1Uri = Uri.file(workspaceFolder1Path);
+ workspaceFolder2Uri = Uri.file(workspaceFolder2Path);
+ workspaceFolder3Uri = Uri.file(workspaceFolder3Path);
+ }
+
+ test_changeWorkspaceFolders_add() async {
+ await initialize(rootUri: workspaceFolder1Uri);
+ await changeWorkspaceFolders(
+ add: [workspaceFolder2Uri, workspaceFolder3Uri]);
+
+ expect(
+ server.contextManager.includedPaths,
+ unorderedEquals([
+ workspaceFolder1Path,
+ workspaceFolder2Path,
+ workspaceFolder3Path,
+ ]),
+ );
+ }
+
+ test_changeWorkspaceFolders_addAndRemove() async {
+ await initialize(
+ workspaceFolders: [workspaceFolder1Uri, workspaceFolder2Uri],
+ );
+
+ await changeWorkspaceFolders(
+ add: [workspaceFolder3Uri],
+ remove: [workspaceFolder2Uri],
+ );
+ expect(
+ server.contextManager.includedPaths,
+ unorderedEquals([workspaceFolder1Path, workspaceFolder3Path]),
+ );
+ }
+
+ test_changeWorkspaceFolders_remove() async {
+ await initialize(
+ workspaceFolders: [workspaceFolder1Uri, workspaceFolder2Uri],
+ );
+
+ await changeWorkspaceFolders(
+ remove: [workspaceFolder2Uri],
+ );
+ expect(
+ server.contextManager.includedPaths,
+ unorderedEquals([workspaceFolder1Path]),
+ );
+ }
+
+ test_changeWorkspaceFolders_removeFlushesDiagnostics() async {
+ // Add our standard test project as well as a dummy project.
+ await initialize(workspaceFolders: [projectFolderUri, workspaceFolder1Uri]);
+
+ // Generate an error in the test project.
+ final firstDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+ await openFile(mainFileUri, 'String a = 1;');
+ final initialDiagnostics = await firstDiagnosticsUpdate;
+ expect(initialDiagnostics, hasLength(1));
+
+ // Ensure the error is removed if we removed the workspace folder.
+ final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+ await changeWorkspaceFolders(remove: [projectFolderUri]);
+ final updatedDiagnostics = await secondDiagnosticsUpdate;
+ expect(updatedDiagnostics, hasLength(0));
+ }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 2f824c3..4d692a1 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -50,7 +50,7 @@
// Ensure applying the changes will give us the expected content.
final contents = {
- mainFilePath: content,
+ mainFilePath: withoutMarkers(content),
};
applyDocumentChanges(contents, fixAction.edit.documentChanges);
expect(contents[mainFilePath], equals(expectedContent));
@@ -88,7 +88,7 @@
// Ensure applying the changes will give us the expected content.
final contents = {
- mainFilePath: content,
+ mainFilePath: withoutMarkers(content),
};
applyChanges(contents, fixAction.edit.changes);
expect(contents[mainFilePath], equals(expectedContent));
diff --git a/pkg/analysis_server/test/lsp/code_actions_source_test.dart b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
index e064771..3ea0d20 100644
--- a/pkg/analysis_server/test/lsp/code_actions_source_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
@@ -72,7 +72,7 @@
// Ensure applying the changes will give us the expected content.
final contents = {
- mainFilePath: content,
+ mainFilePath: withoutMarkers(content),
};
applyDocumentChanges(contents, editParams.edit.documentChanges);
expect(contents[mainFilePath], equals(expectedContent));
@@ -129,7 +129,7 @@
// Ensure applying the changes will give us the expected content.
final contents = {
- mainFilePath: content,
+ mainFilePath: withoutMarkers(content),
};
applyChanges(contents, editParams.edit.changes);
expect(contents[mainFilePath], equals(expectedContent));
@@ -270,7 +270,7 @@
// Ensure applying the changes will give us the expected content.
final contents = {
- mainFilePath: content,
+ mainFilePath: withoutMarkers(content),
};
applyDocumentChanges(contents, editParams.edit.documentChanges);
expect(contents[mainFilePath], equals(expectedContent));
@@ -320,7 +320,7 @@
// Ensure applying the changes will give us the expected content.
final contents = {
- mainFilePath: content,
+ mainFilePath: withoutMarkers(content),
};
applyChanges(contents, editParams.edit.changes);
expect(contents[mainFilePath], equals(expectedContent));
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 189b82b..802d3be 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -19,21 +19,40 @@
const initialContents = 'int a = 1;';
newFile(mainFilePath, content: initialContents);
+ final firstDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
await initialize();
- final initialDiagnostics = await waitForDiagnostics(mainFileUri);
+ final initialDiagnostics = await firstDiagnosticsUpdate;
expect(initialDiagnostics, hasLength(0));
await openFile(mainFileUri, initialContents);
+
+ final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
await replaceFile(222, mainFileUri, 'String a = 1;');
- final updatedDiagnostics = await waitForDiagnostics(mainFileUri);
+ final updatedDiagnostics = await secondDiagnosticsUpdate;
expect(updatedDiagnostics, hasLength(1));
}
+ test_deletedFile() async {
+ newFile(mainFilePath, content: 'String a = 1;');
+
+ final firstDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+ await initialize();
+ final originalDiagnostics = await firstDiagnosticsUpdate;
+ expect(originalDiagnostics, hasLength(1));
+
+ // Deleting the file should result in an update to remove the diagnostics.
+ final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
+ await deleteFile(mainFilePath);
+ final updatedDiagnostics = await secondDiagnosticsUpdate;
+ expect(updatedDiagnostics, hasLength(0));
+ }
+
test_initialAnalysis() async {
newFile(mainFilePath, content: 'String a = 1;');
+ final diagnosticsUpdate = waitForDiagnostics(mainFileUri);
await initialize();
- final diagnostics = await waitForDiagnostics(mainFileUri);
+ final diagnostics = await diagnosticsUpdate;
expect(diagnostics, hasLength(1));
final diagnostic = diagnostics.first;
expect(diagnostic.code, equals('invalid_assignment'));
diff --git a/pkg/analysis_server/test/lsp/document_highlights_test.dart b/pkg/analysis_server/test/lsp/document_highlights_test.dart
new file mode 100644
index 0000000..7f002b4
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/document_highlights_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2019, 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DocumentHighlightsTest);
+ });
+}
+
+@reflectiveTest
+class DocumentHighlightsTest extends AbstractLspAnalysisServerTest {
+ test_functions() => _testMarkedContent('''
+ [[main]]() {
+ [[mai^n]]();
+ }
+ ''');
+
+ test_localVariable() => _testMarkedContent('''
+ main() {
+ var [[f^oo]] = 1;
+ print([[foo]]);
+ [[foo]] = 2;
+ }
+ ''');
+
+ test_noResult() => _testMarkedContent('''
+ main() {
+ // This one is in a ^ comment!
+ }
+ ''');
+
+ test_onlySelf() => _testMarkedContent('''
+ main() {
+ [[prin^t]]();
+ }
+ ''');
+
+ test_shadow_inner() => _testMarkedContent('''
+ main() {
+ var foo = 1;
+ func() {
+ var [[fo^o]] = 2;
+ print([[foo]]);
+ }
+ }
+ ''');
+
+ test_shadow_outer() => _testMarkedContent('''
+ main() {
+ var [[foo]] = 1;
+ func() {
+ var foo = 2;
+ print(foo);
+ }
+ print([[fo^o]]);
+ }
+ ''');
+
+ test_topLevelVariable() => _testMarkedContent('''
+ String [[foo]] = 'bar';
+ main() {
+ print([[foo]]);
+ [[fo^o]] = 2;
+ }
+ ''');
+
+ /// Tests highlights in a Dart file using the provided content.
+ /// The content should be marked with a ^ where the highlights request should
+ /// be invoked and with `[[double brackets]]` around each range expected to
+ /// be highlighted (eg. all references to the symbol under ^).
+ /// If the content does not include any `[[double brackets]]` then the response
+ /// is expected to be `null`.
+ _testMarkedContent(String content) async {
+ final expectedRanges = rangesFromMarkers(content);
+
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+
+ final pos = positionFromMarker(content);
+ final highlights = await getDocumentHighlights(mainFileUri, pos);
+
+ if (expectedRanges.isEmpty) {
+ expect(highlights, isNull);
+ } else {
+ final highlightRanges = highlights.map((h) => h.range).toList();
+ expect(highlightRanges, equals(expectedRanges));
+ }
+ }
+}
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 86699ed..7afb2a5 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -48,6 +48,21 @@
response.error.code, equals(ServerErrorCodes.ServerAlreadyInitialized));
}
+ test_initialize_rootPath() async {
+ await initialize(rootPath: projectFolderPath);
+ expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+ }
+
+ test_initialize_rootUri() async {
+ await initialize(rootUri: projectFolderUri);
+ expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+ }
+
+ test_initialize_workspaceFolders() async {
+ await initialize(workspaceFolders: [projectFolderUri]);
+ expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+ }
+
test_uninitialized_dropsNotifications() async {
final notification =
makeNotification(new Method.fromJson('randomNotification'), null);
diff --git a/pkg/analysis_server/test/lsp/rename_test.dart b/pkg/analysis_server/test/lsp/rename_test.dart
new file mode 100644
index 0000000..6226b60
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/rename_test.dart
@@ -0,0 +1,348 @@
+// Copyright (c) 2019, 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:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RenameTest);
+ });
+}
+
+@reflectiveTest
+class RenameTest extends AbstractLspAnalysisServerTest {
+ // TODO(dantup): send a rename without a version
+ // TODO(dantup): send an old version of the doc?
+ // TODO(dantup): check the version returned matches?
+ // TODO(dantup): renames across multiple files
+
+ test_prepare_class() {
+ const content = '''
+ class MyClass {}
+ final a = new [[My^Class]]();
+ ''';
+
+ return _test_prepare(content, 'MyClass');
+ }
+
+ test_prepare_classNewKeyword() async {
+ const content = '''
+ class MyClass {}
+ final a = n^ew [[MyClass]]();
+ ''';
+
+ return _test_prepare(content, 'MyClass');
+ }
+
+ test_prepare_importPrefix() async {
+ const content = '''
+ import 'dart:async' as [[myPr^efix]];
+ ''';
+
+ return _test_prepare(content, 'myPrefix');
+ }
+
+ test_prepare_importWithoutPrefix() async {
+ const content = '''
+ imp[[^]]ort 'dart:async';
+ ''';
+
+ return _test_prepare(content, '');
+ }
+
+ test_prepare_importWithPrefix() async {
+ const content = '''
+ imp^ort 'dart:async' as [[myPrefix]];
+ ''';
+
+ return _test_prepare(content, 'myPrefix');
+ }
+
+ test_prepare_invalidRenameLocation() async {
+ const content = '''
+ main() {
+ // comm^ent
+ }
+ ''';
+
+ return _test_prepare(content, null);
+ }
+
+ test_prepare_sdkClass() async {
+ const content = '''
+ final a = new [[Ob^ject]]();
+ ''';
+
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+
+ final request = makeRequest(
+ Method.textDocument_prepareRename,
+ new TextDocumentPositionParams(
+ new TextDocumentIdentifier(mainFileUri.toString()),
+ positionFromMarker(content),
+ ),
+ );
+ final response = await channel.sendRequestToServer(request);
+
+ expect(response.id, equals(request.id));
+ expect(response.result, isNull);
+ expect(response.error, isNotNull);
+ expect(response.error.code, ServerErrorCodes.RenameNotValid);
+ expect(response.error.message, contains('is defined in the SDK'));
+ }
+
+ test_prepare_variable() async {
+ const content = '''
+ main() {
+ var variable = 0;
+ print([[vari^able]]);
+ }
+ ''';
+
+ return _test_prepare(content, 'variable');
+ }
+
+ test_rename_class() {
+ const content = '''
+ class MyClass {}
+ final a = new [[My^Class]]();
+ ''';
+ const expectedContent = '''
+ class MyNewClass {}
+ final a = new MyNewClass();
+ ''';
+ return _test_rename_withDocumentChanges(
+ content, 'MyNewClass', expectedContent);
+ }
+
+ test_rename_classNewKeyword() async {
+ const content = '''
+ class MyClass {}
+ final a = n^ew MyClass();
+ ''';
+ const expectedContent = '''
+ class MyNewClass {}
+ final a = new MyNewClass();
+ ''';
+ return _test_rename_withDocumentChanges(
+ content, 'MyNewClass', expectedContent);
+ }
+
+ test_rename_importPrefix() {
+ const content = '''
+ import 'dart:async' as myPr^efix;
+ ''';
+ const expectedContent = '''
+ import 'dart:async' as myNewPrefix;
+ ''';
+ return _test_rename_withDocumentChanges(
+ content, 'myNewPrefix', expectedContent);
+ }
+
+ test_rename_importWithoutPrefix() {
+ const content = '''
+ imp^ort 'dart:async';
+ ''';
+ const expectedContent = '''
+ import 'dart:async' as myAddedPrefix;
+ ''';
+ return _test_rename_withDocumentChanges(
+ content, 'myAddedPrefix', expectedContent);
+ }
+
+ test_rename_importWithPrefix() {
+ const content = '''
+ imp^ort 'dart:async' as myPrefix;
+ ''';
+ const expectedContent = '''
+ import 'dart:async' as myNewPrefix;
+ ''';
+ return _test_rename_withDocumentChanges(
+ content, 'myNewPrefix', expectedContent);
+ }
+
+ test_rename_invalidRenameLocation() {
+ const content = '''
+ main() {
+ // comm^ent
+ }
+ ''';
+ return _test_rename_withDocumentChanges(content, 'MyNewClass', null);
+ }
+
+ test_rename_rejectedForBadName() async {
+ const content = '''
+ class MyClass {}
+ final a = n^ew MyClass();
+ ''';
+ final error = await _test_rename_failure(content, 'not a valid class name');
+ expect(error.code, equals(ServerErrorCodes.RenameNotValid));
+ expect(error.message, contains('name must not contain'));
+ }
+
+ test_rename_rejectedForDuplicateName() async {
+ const content = '''
+ class MyOtherClass {}
+ class MyClass {}
+ final a = n^ew MyClass();
+ ''';
+ final error = await _test_rename_failure(content, 'MyOtherClass');
+ expect(error.code, equals(ServerErrorCodes.RenameNotValid));
+ expect(error.message, contains('already declares class with name'));
+ }
+
+ test_rename_rejectedForStaleDocument() async {
+ const content = '''
+ class MyClass {}
+ final a = n^ew MyClass();
+ ''';
+ final error =
+ await _test_rename_failure(content, 'MyNewClass', openFileVersion: 111);
+ expect(error.code, equals(ErrorCodes.ContentModified));
+ expect(error.message, contains('Document was modified'));
+ }
+
+ test_rename_sdkClass() async {
+ const content = '''
+ final a = new [[Ob^ject]]();
+ ''';
+
+ await newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize();
+
+ final request = makeRequest(
+ Method.textDocument_rename,
+ new RenameParams(
+ new TextDocumentIdentifier(mainFileUri.toString()),
+ positionFromMarker(content),
+ 'Object2',
+ ),
+ );
+ final response = await channel.sendRequestToServer(request);
+
+ expect(response.id, equals(request.id));
+ expect(response.result, isNull);
+ expect(response.error, isNotNull);
+ expect(response.error.code, ServerErrorCodes.RenameNotValid);
+ expect(response.error.message, contains('is defined in the SDK'));
+ }
+
+ test_rename_usingLegacyChangeInterface() async {
+ // This test initializes without support for DocumentChanges (versioning)
+ // whereas the other tests all use DocumentChanges support (preferred).
+ const content = '''
+ class MyClass {}
+ final a = new My^Class();
+ ''';
+ const expectedContent = '''
+ class MyNewClass {}
+ final a = new MyNewClass();
+ ''';
+
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content), version: 222);
+
+ final result = await rename(
+ mainFileUri,
+ 222,
+ positionFromMarker(content),
+ 'MyNewClass',
+ );
+
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyChanges(contents, result.changes);
+ expect(contents[mainFilePath], equals(expectedContent));
+ }
+
+ test_rename_variable() {
+ const content = '''
+ main() {
+ var variable = 0;
+ print([[vari^able]]);
+ }
+ ''';
+ const expectedContent = '''
+ main() {
+ var foo = 0;
+ print(foo);
+ }
+ ''';
+ return _test_rename_withDocumentChanges(content, 'foo', expectedContent);
+ }
+
+ _test_prepare(String content, String expectedPlaceholder) async {
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+
+ final result =
+ await prepareRename(mainFileUri, positionFromMarker(content));
+
+ if (expectedPlaceholder == null) {
+ expect(result, isNull);
+ } else {
+ expect(result.range, equals(rangeFromMarkers(content)));
+ expect(result.placeholder, equals(expectedPlaceholder));
+ }
+ }
+
+ Future<ResponseError> _test_rename_failure(
+ String content,
+ String newName, {
+ int openFileVersion = 222,
+ int renameRequestFileVersion = 222,
+ }) async {
+ await initialize(
+ workspaceCapabilities:
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+ );
+ await openFile(mainFileUri, withoutMarkers(content),
+ version: openFileVersion);
+
+ final result = await renameRaw(
+ mainFileUri,
+ renameRequestFileVersion,
+ positionFromMarker(content),
+ newName,
+ );
+
+ expect(result.result, isNull);
+ expect(result.error, isNotNull);
+ return result.error;
+ }
+
+ _test_rename_withDocumentChanges(
+ String content, String newName, String expectedContent) async {
+ await initialize(
+ workspaceCapabilities:
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+ );
+ await openFile(mainFileUri, withoutMarkers(content), version: 222);
+
+ final result = await rename(
+ mainFileUri,
+ 222,
+ positionFromMarker(content),
+ newName,
+ );
+ if (expectedContent == null) {
+ expect(result, isNull);
+ } else {
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyDocumentChanges(contents, result.documentChanges);
+ expect(contents[mainFilePath], equals(expectedContent));
+ }
+ }
+}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 45e2ad9..fad7baf 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -15,6 +15,7 @@
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:meta/meta.dart';
+import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import '../mocks.dart';
@@ -41,7 +42,7 @@
int _id = 0;
String projectFolderPath, mainFilePath;
- Uri mainFileUri;
+ Uri projectFolderUri, mainFileUri;
void applyChanges(
Map<String, String> fileContents,
@@ -111,11 +112,29 @@
// number of inserts followed by a single remove or replace edit. If multiple
// inserts have the same position, the order in the array defines the order in
// which the inserted strings appear in the resulting text.
- if (changes.length > 1) {
- // TODO(dantup): Implement multi-edit edits.
- throw 'Test helper applyTextEdits does not support applying multiple edits';
- } else if (changes.length == 1) {
- newContent = applyTextEdit(newContent, changes.single);
+
+ /// Ensures changes are simple enough to apply easily without any complicated
+ /// logic.
+ void validateChangesCanBeApplied() {
+ bool intersectsWithOrComesAfter(Position pos, Position other) =>
+ pos.line > other.line ||
+ (pos.line == other.line || pos.character >= other.character);
+
+ Position earliestPositionChanged;
+ for (final change in changes) {
+ if (earliestPositionChanged != null &&
+ intersectsWithOrComesAfter(
+ change.range.end, earliestPositionChanged)) {
+ throw 'Test helper applyTextEdits does not support applying multiple edits '
+ 'where the edits are not in reverse order.';
+ }
+ earliestPositionChanged = change.range.start;
+ }
+ }
+
+ validateChangesCanBeApplied();
+ for (final change in changes) {
+ newContent = applyTextEdit(newContent, change);
}
return newContent;
@@ -137,6 +156,20 @@
await pumpEventQueue();
}
+ Future changeWorkspaceFolders({List<Uri> add, List<Uri> remove}) async {
+ var notification = makeNotification(
+ Method.workspace_didChangeWorkspaceFolders,
+ new DidChangeWorkspaceFoldersParams(
+ new WorkspaceFoldersChangeEvent(
+ add?.map(toWorkspaceFolder)?.toList() ?? const [],
+ remove?.map(toWorkspaceFolder)?.toList() ?? const [],
+ ),
+ ),
+ );
+ channel.sendNotificationToServer(notification);
+ await pumpEventQueue();
+ }
+
Future closeFile(Uri uri) async {
var notification = makeNotification(
Method.textDocument_didClose,
@@ -198,7 +231,7 @@
}
}
- Future<List<TextEdit>> formatDocument(String fileUri) async {
+ Future<List<TextEdit>> formatDocument(String fileUri) {
final request = makeRequest(
Method.textDocument_formatting,
new DocumentFormattingParams(
@@ -210,7 +243,7 @@
}
Future<List<TextEdit>> formatOnType(
- String fileUri, Position pos, String character) async {
+ String fileUri, Position pos, String character) {
final request = makeRequest(
Method.textDocument_onTypeFormatting,
new DocumentOnTypeFormattingParams(
@@ -227,7 +260,7 @@
String fileUri, {
Range range,
List<CodeActionKind> kinds,
- }) async {
+ }) {
final request = makeRequest(
Method.textDocument_codeAction,
new CodeActionParams(
@@ -242,7 +275,7 @@
}
Future<List<CompletionItem>> getCompletion(Uri uri, Position pos,
- {CompletionContext context}) async {
+ {CompletionContext context}) {
final request = makeRequest(
Method.textDocument_completion,
new CompletionParams(
@@ -254,7 +287,7 @@
return expectSuccessfulResponseTo<List<CompletionItem>>(request);
}
- Future<List<Location>> getDefinition(Uri uri, Position pos) async {
+ Future<List<Location>> getDefinition(Uri uri, Position pos) {
final request = makeRequest(
Method.textDocument_definition,
new TextDocumentPositionParams(
@@ -265,8 +298,19 @@
return expectSuccessfulResponseTo<List<Location>>(request);
}
+ Future<List<DocumentHighlight>> getDocumentHighlights(Uri uri, Position pos) {
+ final request = makeRequest(
+ Method.textDocument_documentHighlight,
+ new TextDocumentPositionParams(
+ new TextDocumentIdentifier(uri.toString()),
+ pos,
+ ),
+ );
+ return expectSuccessfulResponseTo<List<DocumentHighlight>>(request);
+ }
+
Future<Either2<List<DocumentSymbol>, List<SymbolInformation>>>
- getDocumentSymbols(String fileUri) async {
+ getDocumentSymbols(String fileUri) {
final request = makeRequest(
Method.textDocument_documentSymbol,
new DocumentSymbolParams(
@@ -276,7 +320,7 @@
return expectSuccessfulResponseTo(request);
}
- Future<Hover> getHover(Uri uri, Position pos) async {
+ Future<Hover> getHover(Uri uri, Position pos) {
final request = makeRequest(
Method.textDocument_hover,
new TextDocumentPositionParams(
@@ -289,7 +333,7 @@
Uri uri,
Position pos, {
includeDeclarations = false,
- }) async {
+ }) {
final request = makeRequest(
Method.textDocument_references,
new ReferenceParams(
@@ -301,7 +345,7 @@
return expectSuccessfulResponseTo<List<Location>>(request);
}
- Future<SignatureHelp> getSignatureHelp(Uri uri, Position pos) async {
+ Future<SignatureHelp> getSignatureHelp(Uri uri, Position pos) {
final request = makeRequest(
Method.textDocument_signatureHelp,
new TextDocumentPositionParams(
@@ -362,16 +406,22 @@
/// match the spec exactly and are not verified.
Future<ResponseMessage> initialize({
String rootPath,
+ Uri rootUri,
+ List<Uri> workspaceFolders,
TextDocumentClientCapabilities textDocumentCapabilities,
WorkspaceClientCapabilities workspaceCapabilities,
}) async {
- final rootUri = Uri.file(rootPath ?? projectFolderPath).toString();
+ // Assume if none of the project options were set, that we want to default to
+ // opening the test project folder.
+ if (rootPath == null && rootUri == null && workspaceFolders == null) {
+ rootUri = Uri.file(projectFolderPath);
+ }
final request = makeRequest(
Method.initialize,
new InitializeParams(
null,
- null,
- rootUri,
+ rootPath,
+ rootUri?.toString(),
null,
new ClientCapabilities(
workspaceCapabilities,
@@ -379,13 +429,14 @@
null,
),
null,
- null));
+ workspaceFolders?.map(toWorkspaceFolder)?.toList()));
final response = await channel.sendRequestToServer(request);
expect(response.id, equals(request.id));
if (response.error == null) {
final notification = makeNotification(Method.initialized, null);
channel.sendNotificationToServer(notification);
+ await pumpEventQueue();
}
return response;
@@ -395,6 +446,18 @@
return new NotificationMessage(method, params, jsonRpcVersion);
}
+ RequestMessage makeRenameRequest(
+ int version, Uri uri, Position pos, String newName) {
+ final docIdentifier = version != null
+ ? new VersionedTextDocumentIdentifier(version, uri.toString())
+ : new TextDocumentIdentifier(uri.toString());
+ final request = makeRequest(
+ Method.textDocument_rename,
+ new RenameParams(docIdentifier, pos, newName),
+ );
+ return request;
+ }
+
RequestMessage makeRequest(Method method, ToJsonable params) {
final id = Either2<num, String>.t1(_id++);
return new RequestMessage(id, method, params, jsonRpcVersion);
@@ -411,34 +474,97 @@
}
Position positionFromMarker(String contents) =>
- positionFromOffset(contents.indexOf('^'), contents);
+ positionFromOffset(withoutRangeMarkers(contents).indexOf('^'), contents);
Position positionFromOffset(int offset, String contents) {
- final lineInfo = LineInfo.fromContent(contents);
+ final lineInfo = LineInfo.fromContent(withoutMarkers(contents));
return toPosition(lineInfo.getLocation(offset));
}
+ Future<RangeAndPlaceholder> prepareRename(Uri uri, Position pos) {
+ final request = makeRequest(
+ Method.textDocument_prepareRename,
+ new TextDocumentPositionParams(
+ new TextDocumentIdentifier(uri.toString()),
+ pos,
+ ),
+ );
+ return expectSuccessfulResponseTo<RangeAndPlaceholder>(request);
+ }
+
/// Returns the range surrounded by `[[markers]]` in the provided string,
/// excluding the markers themselves (as well as position markers `^` from
/// the offsets).
Range rangeFromMarkers(String contents) {
- contents = contents.replaceAll(positionMarker, '');
- final start = contents.indexOf(rangeMarkerStart);
- if (start == -1) {
- throw 'Contents did not contain $rangeMarkerStart';
+ final ranges = rangesFromMarkers(contents);
+ if (ranges.length == 1) {
+ return ranges.first;
+ } else if (ranges.isEmpty) {
+ throw 'Contents did not include a marked range';
+ } else {
+ throw 'Contents contained multiple ranges but only one was expected';
}
- final end = contents.indexOf(rangeMarkerEnd);
- if (end == -1) {
- throw 'Contents did not contain $rangeMarkerEnd';
- }
- return new Range(
- positionFromOffset(start, contents),
- positionFromOffset(end - rangeMarkerStart.length, contents),
- );
}
- Future replaceFile(int newVersion, Uri uri, String content) async {
- await changeFile(
+ /// Returns all ranges surrounded by `[[markers]]` in the provided string,
+ /// excluding the markers themselves (as well as position markers `^` from
+ /// the offsets).
+ List<Range> rangesFromMarkers(String content) {
+ Iterable<Range> rangesFromMarkersImpl(String content) sync* {
+ content = content.replaceAll(positionMarker, '');
+ final contentsWithoutMarkers = withoutMarkers(content);
+ var searchStartIndex = 0;
+ var offsetForEarlierMarkers = 0;
+ while (true) {
+ final startMarker = content.indexOf(rangeMarkerStart, searchStartIndex);
+ if (startMarker == -1) {
+ return; // Exit if we didn't find any more.
+ }
+ final endMarker = content.indexOf(rangeMarkerEnd, startMarker);
+ if (endMarker == -1) {
+ throw 'Found unclosed range starting at offset $startMarker';
+ }
+ yield new Range(
+ positionFromOffset(
+ startMarker + offsetForEarlierMarkers, contentsWithoutMarkers),
+ positionFromOffset(
+ endMarker + offsetForEarlierMarkers - rangeMarkerStart.length,
+ contentsWithoutMarkers),
+ );
+ // Start the next search after this one, but remember to offset the future
+ // results by the lengths of these markers since they shouldn't affect the
+ // offsets.
+ searchStartIndex = endMarker;
+ offsetForEarlierMarkers -=
+ rangeMarkerStart.length + rangeMarkerEnd.length;
+ }
+ }
+
+ return rangesFromMarkersImpl(content).toList();
+ }
+
+ Future<WorkspaceEdit> rename(
+ Uri uri,
+ int version,
+ Position pos,
+ String newName,
+ ) {
+ final request = makeRenameRequest(version, uri, pos, newName);
+ return expectSuccessfulResponseTo<WorkspaceEdit>(request);
+ }
+
+ Future<ResponseMessage> renameRaw(
+ Uri uri,
+ int version,
+ Position pos,
+ String newName,
+ ) {
+ final request = makeRenameRequest(version, uri, pos, newName);
+ return channel.sendRequestToServer(request);
+ }
+
+ Future replaceFile(int newVersion, Uri uri, String content) {
+ return changeFile(
newVersion,
uri,
[new TextDocumentContentChangeEvent(null, null, content)],
@@ -447,7 +573,7 @@
/// Sends [responseParams] to the server as a successful response to
/// a server-initiated [request].
- void respondTo<T>(RequestMessage request, T responseParams) async {
+ void respondTo<T>(RequestMessage request, T responseParams) {
channel.sendResponseToServer(
new ResponseMessage(request.id, responseParams, null, jsonRpcVersion));
}
@@ -464,6 +590,7 @@
InstrumentationService.NULL_SERVICE);
projectFolderPath = convertPath('/project');
+ projectFolderUri = Uri.file(projectFolderPath);
newFolder(projectFolderPath);
newFolder(join(projectFolderPath, 'lib'));
// Create a folder and file to aid testing that includes imports/completion.
@@ -478,6 +605,10 @@
await server.shutdown();
}
+ WorkspaceFolder toWorkspaceFolder(Uri uri) {
+ return WorkspaceFolder(uri.toString(), path.basename(uri.toFilePath()));
+ }
+
Future<List<Diagnostic>> waitForDiagnostics(Uri uri) async {
PublishDiagnosticsParams diagnosticParams;
await channel.serverToClient.firstWhere((message) {
@@ -496,6 +627,10 @@
/// positions/ranges in strings to avoid hard-coding positions in tests.
String withoutMarkers(String contents) =>
contents.replaceAll(allMarkersPattern, '');
+
+ /// Removes range markers from strings to give accurate position offsets.
+ String withoutRangeMarkers(String contents) =>
+ contents.replaceAll(rangeMarkerStart, '').replaceAll(rangeMarkerEnd, '');
}
mixin ClientCapabilitiesHelperMixin {
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index c9942f1..d1e29ad 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -12,6 +12,7 @@
import 'completion_test.dart' as completion_test;
import 'definition_test.dart' as definition_test;
import 'diagnostic_test.dart' as diagnostic_test;
+import 'document_highlights_test.dart' as document_highlights_test;
import 'document_symbols_test.dart' as document_symbols_test;
import 'file_modification_test.dart' as file_modification_test;
import 'format_test.dart' as format_test;
@@ -19,6 +20,7 @@
import 'initialization_test.dart' as initialization_test;
import 'priority_files_test.dart' as priority_files_test;
import 'references_test.dart' as references_test;
+import 'rename_test.dart' as rename_test;
import 'server_test.dart' as server_test;
import 'signature_help_test.dart' as signature_help_test;
@@ -28,6 +30,7 @@
definition_test.main();
diagnostic_test.main();
document_symbols_test.main();
+ document_highlights_test.main();
file_modification_test.main();
priority_files_test.main();
format_test.main();
@@ -40,5 +43,6 @@
fixes_code_action_tests.main();
assists_code_action_tests.main();
packet_transformer_tests.main();
+ rename_test.main();
}, name: 'lsp');
}
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
index ed8e850..1568d90 100644
--- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart
+++ b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/plugin/test_all.dart b/pkg/analysis_server/test/plugin/test_all.dart
index 8390a16..284a4a3 100644
--- a/pkg/analysis_server/test/plugin/test_all.dart
+++ b/pkg/analysis_server/test/plugin/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 9d2e9ca..553f0a8 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/abstract_search_domain.dart b/pkg/analysis_server/test/search/abstract_search_domain.dart
index d4d1465..e16bc24 100644
--- a/pkg/analysis_server/test/search/abstract_search_domain.dart
+++ b/pkg/analysis_server/test/search/abstract_search_domain.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 8af7bf4..000ba70 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/search/element_references_test.dart b/pkg/analysis_server/test/search/element_references_test.dart
index 6473f65..ff75b70 100644
--- a/pkg/analysis_server/test/search/element_references_test.dart
+++ b/pkg/analysis_server/test/search/element_references_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/member_declarations_test.dart b/pkg/analysis_server/test/search/member_declarations_test.dart
index 644912e..71509db 100644
--- a/pkg/analysis_server/test/search/member_declarations_test.dart
+++ b/pkg/analysis_server/test/search/member_declarations_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/member_references_test.dart b/pkg/analysis_server/test/search/member_references_test.dart
index 3f29142..56bebb9 100644
--- a/pkg/analysis_server/test/search/member_references_test.dart
+++ b/pkg/analysis_server/test/search/member_references_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/search_result_test.dart b/pkg/analysis_server/test/search/search_result_test.dart
index 47a8560..2f2ff83 100644
--- a/pkg/analysis_server/test/search/search_result_test.dart
+++ b/pkg/analysis_server/test/search/search_result_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/test_all.dart b/pkg/analysis_server/test/search/test_all.dart
index 56465f1..2e85dae 100644
--- a/pkg/analysis_server/test/search/test_all.dart
+++ b/pkg/analysis_server/test/search/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/top_level_declarations_test.dart b/pkg/analysis_server/test/search/top_level_declarations_test.dart
index 7e1fd99..913f821 100644
--- a/pkg/analysis_server/test/search/top_level_declarations_test.dart
+++ b/pkg/analysis_server/test/search/top_level_declarations_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/search/type_hierarchy_test.dart b/pkg/analysis_server/test/search/type_hierarchy_test.dart
index dfeea6a..3461a4f 100644
--- a/pkg/analysis_server/test/search/type_hierarchy_test.dart
+++ b/pkg/analysis_server/test/search/type_hierarchy_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index a14a0a9..cedde60 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
index 44aae62..8afed8b 100644
--- a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart b/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart
index c6f9a95..a1ba82c 100644
--- a/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 7cf8eb5..9bb1010 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 5f6e857..6e09724 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
index 28fcdbe..2bdff61 100644
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
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 f2e2ba2..73f5b37 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
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart
index 0cd2068..01dd324 100644
--- a/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
index 09f41e9..e13ad70 100644
--- a/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
index d4fb175..7309c20 100644
--- a/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
index d58e6fe..36a37e9 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_constructor_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
index 3191090..8e5f942 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart
index f4722d5..579a063 100644
--- a/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
index 52caf6e..49a5e34 100644
--- a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
index 256e647..1d3e804 100644
--- a/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 72c87931..1298dca 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index c9da1a4..5fd129a 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
index c283cde..49f69ca 100644
--- a/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
index 36c4d2d..2d776e06 100644
--- a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart b/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
index 1fa242e..bf67079 100644
--- a/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/services/completion/postfix/test_all.dart b/pkg/analysis_server/test/services/completion/postfix/test_all.dart
index a2a43c5..4f4c9cb 100644
--- a/pkg/analysis_server/test/services/completion/postfix/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/postfix/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
index 3fb9792..6d789ad 100644
--- a/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/services/completion/statement/test_all.dart b/pkg/analysis_server/test/services/completion/statement/test_all.dart
index f88ea5a..fb89619 100644
--- a/pkg/analysis_server/test/services/completion/statement/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/statement/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/services/completion/test_all.dart b/pkg/analysis_server/test/services/completion/test_all.dart
index e89a4e8..11542d1 100644
--- a/pkg/analysis_server/test/services/completion/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/change_test.dart b/pkg/analysis_server/test/services/correction/change_test.dart
index d11aabd..1a74aa1 100644
--- a/pkg/analysis_server/test/services/correction/change_test.dart
+++ b/pkg/analysis_server/test/services/correction/change_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/levenshtein_test.dart b/pkg/analysis_server/test/services/correction/levenshtein_test.dart
index c344a4c..d8a77e6 100644
--- a/pkg/analysis_server/test/services/correction/levenshtein_test.dart
+++ b/pkg/analysis_server/test/services/correction/levenshtein_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/name_suggestion_test.dart b/pkg/analysis_server/test/services/correction/name_suggestion_test.dart
index d0ac381..f0703ad 100644
--- a/pkg/analysis_server/test/services/correction/name_suggestion_test.dart
+++ b/pkg/analysis_server/test/services/correction/name_suggestion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index ff56f55..8c53f7a 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index 81001fa..faaac42 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index eb27ec2..74b85d5 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/strings_test.dart b/pkg/analysis_server/test/services/correction/strings_test.dart
index a7a68e7..c55cb7b 100644
--- a/pkg/analysis_server/test/services/correction/strings_test.dart
+++ b/pkg/analysis_server/test/services/correction/strings_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/correction/util_test.dart b/pkg/analysis_server/test/services/correction/util_test.dart
index 53eaa7c..b21db87 100644
--- a/pkg/analysis_server/test/services/correction/util_test.dart
+++ b/pkg/analysis_server/test/services/correction/util_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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 'dart:async';
diff --git a/pkg/analysis_server/test/services/linter/test_all.dart b/pkg/analysis_server/test/services/linter/test_all.dart
index 270b1a4..feb89d6 100644
--- a/pkg/analysis_server/test/services/linter/test_all.dart
+++ b/pkg/analysis_server/test/services/linter/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
index 213972f..bf429de 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
index fec6d34..80308ef 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_rename.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
index abac0c8..b06f849 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_getter_to_method_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
index 129cf15..d8fe817 100644
--- a/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/convert_method_to_getter_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
index fd048d2..157d574 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_local_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
index c4d46de..580a076 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/refactoring/inline_local_test.dart b/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
index 41e32b8..0ca2a60 100644
--- a/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/inline_local_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
index 077035c..061ba99 100644
--- a/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/inline_method_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index dd52924..fa60f61 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/refactoring/naming_conventions_test.dart b/pkg/analysis_server/test/services/refactoring/naming_conventions_test.dart
index 6973932..d714f0d 100644
--- a/pkg/analysis_server/test/services/refactoring/naming_conventions_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/naming_conventions_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
index 90957df..bd297d4 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_class_member_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
index 2f0f4a3..884c04a 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_constructor_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
index ed29086..ef76288 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_label_test.dart b/pkg/analysis_server/test/services/refactoring/rename_label_test.dart
index 076ec77..b8d8564 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_label_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_label_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_library_test.dart b/pkg/analysis_server/test/services/refactoring/rename_library_test.dart
index dc1df38..b8f8ac2 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_library_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_library_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
index 25359cd..042fdcc 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart b/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
index 1f23392..baa28a5 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_unit_member_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/refactoring/test_all.dart b/pkg/analysis_server/test/services/refactoring/test_all.dart
index 5dc96b6..a63865d 100644
--- a/pkg/analysis_server/test/services/refactoring/test_all.dart
+++ b/pkg/analysis_server/test/services/refactoring/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/search/element_visitors_test.dart b/pkg/analysis_server/test/services/search/element_visitors_test.dart
index ef2c208..5739ea8 100644
--- a/pkg/analysis_server/test/services/search/element_visitors_test.dart
+++ b/pkg/analysis_server/test/services/search/element_visitors_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/services/search/hierarchy_test.dart b/pkg/analysis_server/test/services/search/hierarchy_test.dart
index cec129e4..785345a 100644
--- a/pkg/analysis_server/test/services/search/hierarchy_test.dart
+++ b/pkg/analysis_server/test/services/search/hierarchy_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/search/test_all.dart b/pkg/analysis_server/test/services/search/test_all.dart
index eed01b8..63d9465 100644
--- a/pkg/analysis_server/test/services/search/test_all.dart
+++ b/pkg/analysis_server/test/services/search/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/services/test_all.dart b/pkg/analysis_server/test/services/test_all.dart
index 2d77c25..76edf82 100644
--- a/pkg/analysis_server/test/services/test_all.dart
+++ b/pkg/analysis_server/test/services/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index 5a8dfcb..7242529 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart b/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart
index f748909..9e6b5d2 100644
--- a/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/closingLabels_computer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
index 8fcde2d..3f2d2ae 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
index 731ca5f..fde32c7 100644
--- a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
index 8a5dad4..8e123ae 100644
--- a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index eb45aad..643d144c 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/computer/test_all.dart b/pkg/analysis_server/test/src/computer/test_all.dart
index 8159db8..c99b3c5 100644
--- a/pkg/analysis_server/test/src/computer/test_all.dart
+++ b/pkg/analysis_server/test/src/computer/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/domain_abstract_test.dart b/pkg/analysis_server/test/src/domain_abstract_test.dart
index dde70ce..41ba49d 100644
--- a/pkg/analysis_server/test/src/domain_abstract_test.dart
+++ b/pkg/analysis_server/test/src/domain_abstract_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/domains/execution/completion_test.dart b/pkg/analysis_server/test/src/domains/execution/completion_test.dart
index 41529c6..37ff7fa 100644
--- a/pkg/analysis_server/test/src/domains/execution/completion_test.dart
+++ b/pkg/analysis_server/test/src/domains/execution/completion_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/domains/execution/test_all.dart b/pkg/analysis_server/test/src/domains/execution/test_all.dart
index 20e6141..cde2384 100644
--- a/pkg/analysis_server/test/src/domains/execution/test_all.dart
+++ b/pkg/analysis_server/test/src/domains/execution/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/domains/test_all.dart b/pkg/analysis_server/test/src/domains/test_all.dart
index 81a4c82..ea67387 100644
--- a/pkg/analysis_server/test/src/domains/test_all.dart
+++ b/pkg/analysis_server/test/src/domains/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart b/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
index 1d7ba263..1039fe9 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index 947fb79..18df136 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
index 84f8f04..0636227 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_notification_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/flutter/test_all.dart b/pkg/analysis_server/test/src/flutter/test_all.dart
index d209fd5..09ef471 100644
--- a/pkg/analysis_server/test/src/flutter/test_all.dart
+++ b/pkg/analysis_server/test/src/flutter/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
index caba741..3a557bb 100644
--- a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
+++ b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/src/plugin/notification_manager_test.dart b/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
index ae42433..124dfd5 100644
--- a/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/notification_manager_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
index 6bfaf1d..c21b06d 100644
--- a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
+++ b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/plugin/request_converter_test.dart b/pkg/analysis_server/test/src/plugin/request_converter_test.dart
index 527623b..c0a3d1c 100644
--- a/pkg/analysis_server/test/src/plugin/request_converter_test.dart
+++ b/pkg/analysis_server/test/src/plugin/request_converter_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/plugin/result_collector_test.dart b/pkg/analysis_server/test/src/plugin/result_collector_test.dart
index e6372c6..d628c63 100644
--- a/pkg/analysis_server/test/src/plugin/result_collector_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_collector_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/plugin/result_converter_test.dart b/pkg/analysis_server/test/src/plugin/result_converter_test.dart
index ffe30cd..5c947aa 100644
--- a/pkg/analysis_server/test/src/plugin/result_converter_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_converter_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/plugin/result_merger_test.dart b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
index 75f11fa..0b051e6 100644
--- a/pkg/analysis_server/test/src/plugin/result_merger_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/plugin/test_all.dart b/pkg/analysis_server/test/src/plugin/test_all.dart
index a1f7564..48883d7 100644
--- a/pkg/analysis_server/test/src/plugin/test_all.dart
+++ b/pkg/analysis_server/test/src/plugin/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
index d5e8dd5..c847a3d 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_constructor_test.dart
@@ -34,9 +34,51 @@
@reflectiveTest
class CreateConstructorTest extends FixProcessorTest {
+ static final _text200 = 'x' * 200;
+
@override
FixKind get kind => DartFixKind.CREATE_CONSTRUCTOR;
+ test_inLibrary_insteadOfSyntheticDefault() async {
+ var a = newFile('/home/test/lib/a.dart', content: '''
+/// $_text200
+class A {}
+''').path;
+ await resolveTestUnit('''
+import 'a.dart';
+
+main() {
+ new A.named(1, 2.0);
+}
+''');
+ await assertHasFix('''
+/// $_text200
+class A {
+ A.named(int i, double d);
+}
+''', target: a);
+ }
+
+ test_inLibrary_named() async {
+ var a = newFile('/home/test/lib/a.dart', content: '''
+/// $_text200
+class A {}
+''').path;
+ await resolveTestUnit('''
+import 'a.dart';
+
+main() {
+ new A(1, 2.0);
+}
+''');
+ await assertHasFix('''
+/// $_text200
+class A {
+ A(int i, double d);
+}
+''', target: a);
+ }
+
test_insteadOfSyntheticDefault() async {
await resolveTestUnit('''
class A {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
index 68d5820..78de092 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -362,6 +362,53 @@
''');
}
+ test_withFunction_functionTopLevelVariable() async {
+ addSource('/home/test/lib/lib.dart', 'var myFunction = () {};');
+ await resolveTestUnit('''
+main() {
+ myFunction();
+}
+''');
+ await assertHasFix('''
+import 'package:test/lib.dart';
+
+main() {
+ myFunction();
+}
+''');
+ }
+
+ test_withFunction_preferFunctionOverTopLevelVariable() async {
+ _configureMyPkg({
+ 'b.dart': 'var myFunction = () {};',
+ 'a.dart': 'myFunction() {}',
+ });
+ await resolveTestUnit('''
+main() {
+ myFunction();
+}
+''');
+ await assertHasFix('''
+import 'package:my_pkg/a.dart';
+
+main() {
+ myFunction();
+}
+''');
+ }
+
+ @failingTest
+ test_withFunction_nonFunctionType() async {
+ // TODO Remove preferFunctionOverTopLevelVariable test once this is passing
+ addSource('/home/test/lib/lib.dart', 'int zero = 0;');
+ await resolveTestUnit('''
+main() {
+ zero();
+}
+''');
+ await assertNoFix();
+ }
+
test_withTopLevelVariable() async {
addSource('/home/test/lib/lib.dart', '''
library lib;
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index c148ef0..20193cb 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/utilities/profiling_test.dart b/pkg/analysis_server/test/src/utilities/profiling_test.dart
index 4906c4b..ccc4c22 100644
--- a/pkg/analysis_server/test/src/utilities/profiling_test.dart
+++ b/pkg/analysis_server/test/src/utilities/profiling_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/src/utilities/test_all.dart b/pkg/analysis_server/test/src/utilities/test_all.dart
index cf5d6fc..580e29b 100644
--- a/pkg/analysis_server/test/src/utilities/test_all.dart
+++ b/pkg/analysis_server/test/src/utilities/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/stress/replay/operation.dart b/pkg/analysis_server/test/stress/replay/operation.dart
index dbacce9..fc6334e 100644
--- a/pkg/analysis_server/test/stress/replay/operation.dart
+++ b/pkg/analysis_server/test/stress/replay/operation.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index d713f0a..60397de 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/stress/utilities/git.dart b/pkg/analysis_server/test/stress/utilities/git.dart
index 1be2307..0b16361 100644
--- a/pkg/analysis_server/test/stress/utilities/git.dart
+++ b/pkg/analysis_server/test/stress/utilities/git.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/stress/utilities/logger.dart b/pkg/analysis_server/test/stress/utilities/logger.dart
index acf7a74..bbdd406 100644
--- a/pkg/analysis_server/test/stress/utilities/logger.dart
+++ b/pkg/analysis_server/test/stress/utilities/logger.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 5afc1e7..e26c43d 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/timing/completion/completion_simple.dart b/pkg/analysis_server/test/timing/completion/completion_simple.dart
index 50cbaa2..2e8164a 100644
--- a/pkg/analysis_server/test/timing/completion/completion_simple.dart
+++ b/pkg/analysis_server/test/timing/completion/completion_simple.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/timing/timing_framework.dart b/pkg/analysis_server/test/timing/timing_framework.dart
index 9c4be1f..d02e6f0 100644
--- a/pkg/analysis_server/test/timing/timing_framework.dart
+++ b/pkg/analysis_server/test/timing/timing_framework.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart b/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
index bcffd7a..fbf2615 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
index b352d18..df7a3c8 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// 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.
@@ -89,6 +89,42 @@
.replaceAll(new RegExp('[ \n]'), '');
expect(output, equals(expected));
});
+
+ test('ResponseMessage does not include an error with a result', () {
+ final id = new Either2<num, String>.t1(1);
+ final result = 'my result';
+ final resp = new ResponseMessage(id, result, null, jsonRpcVersion);
+ final jsonMap = resp.toJson();
+ expect(jsonMap, contains('result'));
+ expect(jsonMap, isNot(contains('error')));
+ });
+
+ test('ResponseMessage can include a null result', () {
+ final id = new Either2<num, String>.t1(1);
+ final resp = new ResponseMessage(id, null, null, jsonRpcVersion);
+ final jsonMap = resp.toJson();
+ expect(jsonMap, contains('result'));
+ expect(jsonMap, isNot(contains('error')));
+ });
+
+ test('ResponseMessage does not include a result for an error', () {
+ final id = new Either2<num, String>.t1(1);
+ final error =
+ new ResponseError<String>(ErrorCodes.ParseError, 'Error', null);
+ final resp = new ResponseMessage(id, null, error, jsonRpcVersion);
+ final jsonMap = resp.toJson();
+ expect(jsonMap, contains('error'));
+ expect(jsonMap, isNot(contains('result')));
+ });
+
+ test('ResponseMessage throws if both result and error are non-null', () {
+ final id = new Either2<num, String>.t1(1);
+ final result = 'my result';
+ final error =
+ new ResponseError<String>(ErrorCodes.ParseError, 'Error', null);
+ final resp = new ResponseMessage(id, result, error, jsonRpcVersion);
+ expect(resp.toJson, throwsA(new TypeMatcher<String>()));
+ });
});
group('fromJson', () {
@@ -121,6 +157,18 @@
final message = NotificationMessage.fromJson(jsonDecode(input));
expect(message.params, isNull);
});
+
+ test('deserialises subtypes into the correct class', () {
+ // Create some JSON that includes a VersionedTextDocumentIdenfitier but
+ // where the class definition only references a TextDocumentIdemntifier.
+ final input = jsonEncode(new TextDocumentPositionParams(
+ new VersionedTextDocumentIdentifier(111, 'file:///foo/bar.dart'),
+ new Position(1, 1),
+ ).toJson());
+ final params = TextDocumentPositionParams.fromJson(jsonDecode(input));
+ expect(params.textDocument,
+ const TypeMatcher<VersionedTextDocumentIdentifier>());
+ });
});
test('objects with lists can round-trip through to json and back', () {
diff --git a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
index 103392d..abf1791 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
@@ -21,7 +21,7 @@
options?: OptionKind[];
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Interface>());
final Interface interface = output[0];
@@ -46,7 +46,7 @@
};
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
// Length is two because we'll fabricate the type of textDoc.
expect(output, hasLength(2));
@@ -87,7 +87,7 @@
options1: any;
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Interface>());
final Interface interface = output[0];
@@ -106,7 +106,7 @@
data?: D;
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Interface>());
final Interface interface = output[0];
@@ -128,7 +128,7 @@
params?: Array<any> | object;
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Interface>());
final Interface interface = output[0];
@@ -152,7 +152,7 @@
changes: { [uri: string]: TextEdit[]; };
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Interface>());
final Interface interface = output[0];
@@ -173,7 +173,7 @@
canBeUndefined?: string;
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
final Interface interface = output[0];
expect(interface.members, hasLength(4));
interface.members.forEach((m) => expect(m, const TypeMatcher<Field>()));
@@ -213,7 +213,7 @@
a: a;
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
final Interface interface = output[0];
expect(interface.commentText, equals('''
Describes the what this class in lots of words that wrap onto multiple lines that will need re-wrapping to format nicely when converted into Dart.
@@ -234,7 +234,7 @@
final String input = '''
export type DocumentSelector = DocumentFilter[];
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<TypeAlias>());
final TypeAlias typeAlias = output[0];
@@ -261,7 +261,7 @@
export const Rename: ResourceOperationKind = 'rename';
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Namespace>());
final Namespace namespace = output[0];
@@ -290,7 +290,7 @@
label: string | [number, number];
}
''';
- final List<AstNode> output = parseFile(input);
+ final List<AstNode> output = parseString(input);
expect(output, hasLength(1));
expect(output[0], const TypeMatcher<Interface>());
final Interface interface = output[0];
diff --git a/pkg/analysis_server/tool/instrumentation/log/log.dart b/pkg/analysis_server/tool/instrumentation/log/log.dart
index 10dfd90..f575765 100644
--- a/pkg/analysis_server/tool/instrumentation/log/log.dart
+++ b/pkg/analysis_server/tool/instrumentation/log/log.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/instrumentation/log_viewer.dart b/pkg/analysis_server/tool/instrumentation/log_viewer.dart
index 62d5722..6edb34b 100644
--- a/pkg/analysis_server/tool/instrumentation/log_viewer.dart
+++ b/pkg/analysis_server/tool/instrumentation/log_viewer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/instrumentation/page/log_page.dart b/pkg/analysis_server/tool/instrumentation/page/log_page.dart
index b537580..bb9b9c9 100644
--- a/pkg/analysis_server/tool/instrumentation/page/log_page.dart
+++ b/pkg/analysis_server/tool/instrumentation/page/log_page.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/instrumentation/page/page_writer.dart b/pkg/analysis_server/tool/instrumentation/page/page_writer.dart
index dca5673..3d1d68a 100644
--- a/pkg/analysis_server/tool/instrumentation/page/page_writer.dart
+++ b/pkg/analysis_server/tool/instrumentation/page/page_writer.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/instrumentation/page/stats_page.dart b/pkg/analysis_server/tool/instrumentation/page/stats_page.dart
index a8932a1..907f16c 100644
--- a/pkg/analysis_server/tool/instrumentation/page/stats_page.dart
+++ b/pkg/analysis_server/tool/instrumentation/page/stats_page.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/instrumentation/page/task_page.dart b/pkg/analysis_server/tool/instrumentation/page/task_page.dart
index f5cd312..e553eab 100644
--- a/pkg/analysis_server/tool/instrumentation/page/task_page.dart
+++ b/pkg/analysis_server/tool/instrumentation/page/task_page.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/instrumentation/server.dart b/pkg/analysis_server/tool/instrumentation/server.dart
index bfeb7cc..4fd50e1 100644
--- a/pkg/analysis_server/tool/instrumentation/server.dart
+++ b/pkg/analysis_server/tool/instrumentation/server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// 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.
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index a8ad68e..fe5bf80 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -38,6 +38,7 @@
| client/registerCapability | | | | | unused, but should be used for DocumentSelector at least
| client/unregisterCapability | | | | |
| workspace/didChangeWatchedFiles | | | | | unused, server does own watching |
+| workspace/didChangeWorkspaceFolders | ✅ | ✅ | ✅ | ✅ |
| workspace/symbol | | | | |
| workspace/executeCommand | ✅ | ✅ | ✅ | ✅ |
| workspace/applyEdit | ✅ | ✅ | ✅ | ✅ |
@@ -55,13 +56,13 @@
| textDocument/typeDefinition | | | | |
| textDocument/implementation | | | | |
| textDocument/references | ✅ | ✅ | ✅ | ✅ |
-| textDocument/documentHighlight | | | | |
+| textDocument/documentHighlight | ✅ | ✅ | ✅ | ✅ |
| textDocument/documentSymbol | ✅ | ✅ | ✅ | ✅ |
| textDocument/codeAction (sortMembers) | ✅ | ✅ | ✅ | ✅ |
| textDocument/codeAction (organiseImports) | ✅ | ✅ | ✅ | ✅ |
| textDocument/codeAction (refactors) | | | | |
-| textDocument/codeAction (assists) | ✅ | ✅ | ✅ | |
-| textDocument/codeAction (fixes) | ✅ | ✅ | ✅ | |
+| textDocument/codeAction (assists) | ✅ | ✅ | ✅ | ✅ |
+| textDocument/codeAction (fixes) | ✅ | ✅ | ✅ | ✅ |
| textDocument/codeLens | | | | |
| codeLens/resolve | | | | |
| textDocument/documentLink | | | | |
@@ -69,7 +70,7 @@
| textDocument/formatting | ✅ | ✅ | ✅ | ✅ |
| textDocument/rangeFormatting | | | | | requires support from dart_style?
| textDocument/onTypeFormatting | ✅ | ✅ | ✅ | ✅ |
-| textDocument/rename | | | | |
+| textDocument/rename | ✅ | ✅ | Incomplete! | |
| textDocument/prepareRename | | | | |
| textDocument/foldingRange | | | | |
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 6b90396..6c87b90 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -9,6 +9,7 @@
final formatter = new DartFormatter();
Map<String, Interface> _interfaces = {};
+Map<String, List<String>> _subtypes = {};
// TODO(dantup): Rename namespaces -> enums since they're always that now.
Map<String, Namespace> _namespaces = {};
Map<String, TypeAlias> _typeAliases = {};
@@ -31,9 +32,15 @@
types
.whereType<TypeAlias>()
.forEach((alias) => _typeAliases[alias.name] = alias);
- types
- .whereType<Interface>()
- .forEach((interface) => _interfaces[interface.name] = interface);
+ types.whereType<Interface>().forEach((interface) {
+ _interfaces[interface.name] = interface;
+ // Keep track of our base classes so they can look up their super classes
+ // later in their fromJson() to deserialise into the most specific type.
+ interface.baseTypes.forEach((base) {
+ final subTypes = _subtypes[base.dartType] ??= new List<String>();
+ subTypes.add(interface.name);
+ });
+ });
types
.whereType<Namespace>()
.forEach((namespace) => _namespaces[namespace.name] = namespace);
@@ -403,6 +410,16 @@
..writeIndentedln('static ${interface.nameWithTypeArgs} '
'fromJson${interface.typeArgsString}(Map<String, dynamic> json) {')
..indent();
+ // First check whether any of our subclasses can deserialise this.
+ for (final subclassName in _subtypes[interface.name] ?? const <String>[]) {
+ final subclass = _interfaces[subclassName];
+ buffer
+ ..writeIndentedln('if (${subclass.nameWithTypeArgs}.canParse(json)) {')
+ ..indent()
+ ..writeln('return ${subclass.nameWithTypeArgs}.fromJson(json);')
+ ..outdent()
+ ..writeIndentedln('}');
+ }
for (final field in allFields) {
buffer.writeIndented('final ${field.name} = ');
_writeFromJsonCode(buffer, field.type, "json['${field.name}']",
@@ -471,9 +488,9 @@
void _writeJsonMapAssignment(
IndentableStringBuffer buffer, Field field, String mapName) {
- // If we are allowed to be undefined (which essentially means required to be
- // undefined and never explicitly null), we'll only add the value if set.
- if (field.allowsUndefined) {
+ // If we are allowed to be undefined, we'll only add the value if set.
+ final shouldBeOmittedIfNoValue = field.allowsUndefined;
+ if (shouldBeOmittedIfNoValue) {
buffer
..writeIndentedln('if (${field.name} != null) {')
..indent();
@@ -483,7 +500,7 @@
buffer.write(''' ?? (throw '${field.name} is required but was not set')''');
}
buffer.writeln(';');
- if (field.allowsUndefined) {
+ if (shouldBeOmittedIfNoValue) {
buffer
..outdent()
..writeIndentedln('}');
@@ -511,8 +528,15 @@
..writeIndentedln('Map<String, dynamic> toJson() {')
..indent()
..writeIndentedln('Map<String, dynamic> __result = {};');
- for (var field in _getAllFields(interface)) {
- _writeJsonMapAssignment(buffer, field, '__result');
+ // ResponseMessage must confirm to JSON-RPC which says only one of
+ // result/error can be included. Since this isn't encoded in the types we
+ // need to special-case it's toJson generation.
+ if (interface.name == "ResponseMessage") {
+ _writeToJsonFieldsForResponseMessage(buffer, interface);
+ } else {
+ for (var field in _getAllFields(interface)) {
+ _writeJsonMapAssignment(buffer, field, '__result');
+ }
}
buffer
..writeIndentedln('return __result;')
@@ -520,6 +544,35 @@
..writeIndentedln('}');
}
+void _writeToJsonFieldsForResponseMessage(
+ IndentableStringBuffer buffer, Interface interface) {
+ const mapName = '__result';
+
+ final allFields = _getAllFields(interface);
+ final standardFields =
+ allFields.where((f) => f.name != 'error' && f.name != 'result');
+
+ for (var field in standardFields) {
+ _writeJsonMapAssignment(buffer, field, mapName);
+ }
+
+ // Write special code for result/error so that only one is populated.
+ buffer
+ ..writeIndentedln('if (error != null && result != null) {')
+ ..indent()
+ ..writeIndentedln('''throw 'result and error cannot both be set';''')
+ ..outdent()
+ ..writeIndentedln('} else if (error != null) {')
+ ..indent()
+ ..writeIndentedln('''$mapName['error'] = error;''')
+ ..outdent()
+ ..writeIndentedln('} else {')
+ ..indent()
+ ..writeIndentedln('''$mapName['result'] = result;''')
+ ..outdent()
+ ..writeIndentedln('}');
+}
+
void _writeToString(IndentableStringBuffer buffer, Interface interface) {
buffer
..writeIndentedln('@override')
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 8e93a31..909a06b 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:io';
+import 'package:analysis_server/src/services/correction/strings.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
@@ -23,7 +24,7 @@
final String spec = await fetchSpec();
final List<AstNode> types = extractTypeScriptBlocks(spec)
.where(shouldIncludeScriptBlock)
- .map(parseFile)
+ .map(parseString)
.expand((f) => f)
.where(includeTypeDefinitionInOutput)
.toList();
@@ -31,6 +32,10 @@
// Generate an enum for all of the request methods to avoid strings.
types.add(extractMethodsEnum(spec));
+ // Extract additional inline types that are specificed online in the `results`
+ // section of the doc.
+ types.addAll(extractResultsInlineTypes(spec));
+
final String output = generateDartForTypes(types);
new File(path.join(outFolder, 'protocol_generated.dart'))
@@ -89,6 +94,42 @@
final Uri specUri = Uri.parse(
'https://raw.githubusercontent.com/Microsoft/language-server-protocol/gh-pages/specification.md');
+/// Pattern to extract inline types from the `result: {xx, yy }` notes in the spec.
+/// Doesn't parse past full stops as some of these have english sentences tagged on
+/// the end that we don't want to parse.
+final _resultsInlineTypesPattern = new RegExp(r'''\* result:[^\.]*({.*})''');
+
+/// Extract inline types found directly in the `results:` sections of the spec
+/// that are not declared with their own names elsewhere.
+List<AstNode> extractResultsInlineTypes(String spec) {
+ InlineInterface toInterface(String typeDef) {
+ // The definition passed here will be a bare inline type, such as:
+ //
+ // { range: Range, placeholder: string }
+ //
+ // In order to parse this, we'll just format it as a type alias and then
+ // run it through the standard parsing code.
+ final typeAlias = 'type temp = ${typeDef.replaceAll(',', ';')};';
+
+ final parsed = parseString(typeAlias);
+
+ // Extract the InlineInterface that was created.
+ InlineInterface interface = parsed.firstWhere((t) => t is InlineInterface);
+
+ // Create a new name based on the fields.
+ var newName = interface.members.map((m) => capitalize(m.name)).join('And');
+
+ return new InlineInterface(newName, interface.members);
+ }
+
+ return _resultsInlineTypesPattern
+ .allMatches(spec)
+ .map((m) => m.group(1).trim())
+ .toList()
+ .map(toInterface)
+ .toList();
+}
+
Future<String> fetchSpec() async {
final resp = await http.get(specUri);
return resp.body;
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 6f70d2b..6ff12a9 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -32,9 +32,15 @@
return comment.trim();
}
-/// Fixes up some enum types that are not as specific as they could be in the
-/// spec. For example, Diagnostic.severity is typed "number" but can be mapped
-/// to the DiagnosticSeverity enum class.
+/// Improves types in generated code, including:
+///
+/// - Fixes up some enum types that are not as specific as they could be in the
+/// spec. For example, Diagnostic.severity is typed "number" but can be mapped
+/// to the DiagnosticSeverity enum class.
+///
+/// - Narrows unions to single types where they're only generated on the server
+/// and we know we always use a specific type. This avoids wrapping a lot
+/// of code in `EitherX<Y,Z>.tX()` and simplifies the testing of them.
String getImprovedType(String interfaceName, String fieldName) {
const Map<String, Map<String, String>> _improvedTypeMappings = {
"Diagnostic": {
@@ -72,6 +78,9 @@
},
"ParameterInformation": {
"label": "String",
+ },
+ "ServerCapabilities": {
+ "changeNotifications": "bool",
}
};
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index a7c8e4d..bd303e1 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -12,6 +12,8 @@
final _validIdentifierCharacters = RegExp('[a-zA-Z0-9_]');
+bool isAnyType(TypeBase t) => t is Type && t.name == 'any';
+
bool isNullType(TypeBase t) => t is Type && t.name == 'null';
bool isUndefinedType(TypeBase t) => t is Type && t.name == 'undefined';
@@ -20,7 +22,7 @@
/// of type names for inline types.
const fieldNameForIndexer = 'indexer';
-List<AstNode> parseFile(String input) {
+List<AstNode> parseString(String input) {
final scanner = new Scanner(input);
final tokens = scanner.scan();
final parser = new Parser(tokens);
@@ -298,7 +300,6 @@
_eatUnwantedKeywords();
final name = _consume(TokenType.IDENTIFIER, 'Expected identifier');
var canBeUndefined = _match([TokenType.QUESTION]);
- var canBeNull = false;
_consume(TokenType.COLON, 'Expected :');
TypeBase type;
Token value;
@@ -327,16 +328,17 @@
// Special handling for fields that have fixed values.
if (value != null) {
return new FixedValueField(
- leadingComment, name, value, type, canBeNull, canBeUndefined);
+ leadingComment, name, value, type, false, canBeUndefined);
}
+ var canBeNull = false;
if (type is UnionType) {
UnionType union = type;
// Since undefined and null can appear in the union type list but we want to
// handle it specially in the code generation, we promote them to fields on
// the Field.
canBeUndefined |= union.types.any(isUndefinedType);
- canBeNull = union.types.any(isNullType);
+ canBeNull = union.types.any((t) => isNullType(t) || isAnyType(t));
// Finally, we need to remove them from the union.
final remainingTypes = union.types
.where((t) => !isNullType(t) && !isUndefinedType(t))
@@ -349,6 +351,11 @@
type = remainingTypes.length > 1
? new UnionType(remainingTypes)
: remainingTypes.single;
+ } else if (isAnyType(type)) {
+ // There are values in the spec marked as `any` that allow nulls (for
+ // example, the result field on ResponseMessage can be null for a
+ // successful response that has no return value, eg. shutdown).
+ canBeNull = true;
}
return Field(leadingComment, name, type, canBeNull, canBeUndefined);
}
diff --git a/pkg/analysis_server/tool/spec/api.dart b/pkg/analysis_server/tool/spec/api.dart
index 1fd0c67..6e98267 100644
--- a/pkg/analysis_server/tool/spec/api.dart
+++ b/pkg/analysis_server/tool/spec/api.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/check_all_test.dart b/pkg/analysis_server/tool/spec/check_all_test.dart
index cd313ee..3aefa25 100644
--- a/pkg/analysis_server/tool/spec/check_all_test.dart
+++ b/pkg/analysis_server/tool/spec/check_all_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_analysis_server.dart b/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
index b713e60..75fc69c 100644
--- a/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
+++ b/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_dart.dart b/pkg/analysis_server/tool/spec/codegen_dart.dart
index 8b736bb..f6d1533 100644
--- a/pkg/analysis_server/tool/spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/spec/codegen_dart.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
index f34ea9c..adb57f7 100644
--- a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
+++ b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart b/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
index 88870a7a..8fec4fa 100644
--- a/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
+++ b/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_java.dart b/pkg/analysis_server/tool/spec/codegen_java.dart
index d1e02b4..9956fe1 100644
--- a/pkg/analysis_server/tool/spec/codegen_java.dart
+++ b/pkg/analysis_server/tool/spec/codegen_java.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_java_types.dart b/pkg/analysis_server/tool/spec/codegen_java_types.dart
index dd963d0..2006405 100644
--- a/pkg/analysis_server/tool/spec/codegen_java_types.dart
+++ b/pkg/analysis_server/tool/spec/codegen_java_types.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_matchers.dart b/pkg/analysis_server/tool/spec/codegen_matchers.dart
index 480e46f..226c707 100644
--- a/pkg/analysis_server/tool/spec/codegen_matchers.dart
+++ b/pkg/analysis_server/tool/spec/codegen_matchers.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
index 658f2c7..7530d39 100644
--- a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
+++ b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2017, 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.
diff --git a/pkg/analysis_server/tool/spec/from_html.dart b/pkg/analysis_server/tool/spec/from_html.dart
index 79f5882..be77a02 100644
--- a/pkg/analysis_server/tool/spec/from_html.dart
+++ b/pkg/analysis_server/tool/spec/from_html.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/generate_all.dart b/pkg/analysis_server/tool/spec/generate_all.dart
index a29593d..c5afd22 100644
--- a/pkg/analysis_server/tool/spec/generate_all.dart
+++ b/pkg/analysis_server/tool/spec/generate_all.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
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 073d802..83f2643 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -60,6 +60,12 @@
private final String displayText;
/**
+ * The URI of the element corresponding to this suggestion. It will be set whenever analysis server
+ * is able to compute it.
+ */
+ private final String elementUri;
+
+ /**
* The offset, relative to the beginning of the completion, of where the selection should be placed
* after insertion.
*/
@@ -169,11 +175,12 @@
/**
* Constructor for {@link CompletionSuggestion}.
*/
- 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) {
+ public CompletionSuggestion(String kind, int relevance, String completion, String displayText, String elementUri, 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.elementUri = elementUri;
this.selectionOffset = selectionOffset;
this.selectionLength = selectionLength;
this.isDeprecated = isDeprecated;
@@ -203,6 +210,7 @@
other.relevance == relevance &&
ObjectUtilities.equals(other.completion, completion) &&
ObjectUtilities.equals(other.displayText, displayText) &&
+ ObjectUtilities.equals(other.elementUri, elementUri) &&
other.selectionOffset == selectionOffset &&
other.selectionLength == selectionLength &&
other.isDeprecated == isDeprecated &&
@@ -230,6 +238,7 @@
int relevance = jsonObject.get("relevance").getAsInt();
String completion = jsonObject.get("completion").getAsString();
String displayText = jsonObject.get("displayText") == null ? null : jsonObject.get("displayText").getAsString();
+ String elementUri = jsonObject.get("elementUri") == null ? null : jsonObject.get("elementUri").getAsString();
int selectionOffset = jsonObject.get("selectionOffset").getAsInt();
int selectionLength = jsonObject.get("selectionLength").getAsInt();
boolean isDeprecated = jsonObject.get("isDeprecated").getAsBoolean();
@@ -248,7 +257,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, displayText, 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, elementUri, 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) {
@@ -330,6 +339,14 @@
}
/**
+ * The URI of the element corresponding to this suggestion. It will be set whenever analysis server
+ * is able to compute it.
+ */
+ public String getElementUri() {
+ return elementUri;
+ }
+
+ /**
* True if the function or method being suggested has at least one named parameter. This field is
* omitted if the parameterNames field is omitted.
*/
@@ -444,6 +461,7 @@
builder.append(relevance);
builder.append(completion);
builder.append(displayText);
+ builder.append(elementUri);
builder.append(selectionOffset);
builder.append(selectionLength);
builder.append(isDeprecated);
@@ -473,6 +491,9 @@
if (displayText != null) {
jsonObject.addProperty("displayText", displayText);
}
+ if (elementUri != null) {
+ jsonObject.addProperty("elementUri", elementUri);
+ }
jsonObject.addProperty("selectionOffset", selectionOffset);
jsonObject.addProperty("selectionLength", selectionLength);
jsonObject.addProperty("isDeprecated", isDeprecated);
@@ -546,6 +567,8 @@
builder.append(completion + ", ");
builder.append("displayText=");
builder.append(displayText + ", ");
+ builder.append("elementUri=");
+ builder.append(elementUri + ", ");
builder.append("selectionOffset=");
builder.append(selectionOffset + ", ");
builder.append("selectionLength=");
diff --git a/pkg/analysis_server/tool/spec/implied_types.dart b/pkg/analysis_server/tool/spec/implied_types.dart
index 49531b7..856b2a4 100644
--- a/pkg/analysis_server/tool/spec/implied_types.dart
+++ b/pkg/analysis_server/tool/spec/implied_types.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 0266e7c..2418991 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- <version>1.21.1</version>
+ <version>1.22.1</version>
</h1>
<p>
This document contains a specification of the API provided by the
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart
index a2c1b37..1683331 100644
--- a/pkg/analysis_server/tool/spec/to_html.dart
+++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2014, 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.
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 15c626a..fd21adb 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.21.1';
+const String PROTOCOL_VERSION = '1.22.1';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 547cb82..0260c07 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -534,6 +534,9 @@
/// Return `true` if this element has an annotation of the form `@JS(..)`.
bool get hasJS;
+ /// Return `true` if this element has an annotation of the form '@literal'.
+ bool get hasLiteral;
+
/// Return `true` if this element has an annotation of the form `@override`.
bool get hasOverride;
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index dc89edf..f2ddef8 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -75,6 +75,12 @@
bool get isDartCoreFunction;
/**
+ * Return `true` if this type represents the type 'int' defined in the
+ * dart:core library.
+ */
+ bool get isDartCoreInt;
+
+ /**
* Return `true` if this type represents the type 'Null' defined in the
* dart:core library.
*/
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 7ffa3f6..fdaed1b 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -277,9 +277,10 @@
HintCode.DEAD_CODE,
HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH,
HintCode.DEAD_CODE_ON_CATCH_SUBTYPE,
- HintCode.DEPRECATED_MEMBER_USE,
- HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION,
HintCode.DEPRECATED_EXTENDS_FUNCTION,
+ HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION,
+ HintCode.DEPRECATED_MEMBER_USE,
+ HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE,
HintCode.DEPRECATED_MIXIN_FUNCTION,
HintCode.DIVISION_OPTIMIZATION,
HintCode.DUPLICATE_IMPORT,
@@ -288,7 +289,6 @@
HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE,
HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE,
HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION,
- HintCode.INVALID_ASSIGNMENT,
HintCode.INVALID_FACTORY_ANNOTATION,
HintCode.INVALID_FACTORY_METHOD_DECL,
HintCode.INVALID_FACTORY_METHOD_IMPL,
@@ -310,6 +310,8 @@
HintCode.MIXIN_ON_SEALED_CLASS,
HintCode.MUST_BE_IMMUTABLE,
HintCode.MUST_CALL_SUPER,
+ HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR,
+ HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW,
HintCode.NULL_AWARE_BEFORE_OPERATOR,
HintCode.NULL_AWARE_IN_CONDITION,
HintCode.NULL_AWARE_IN_LOGICAL_OPERATOR,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 5e2a359..960c862 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -40,6 +40,7 @@
import 'package:analyzer/src/workspace/bazel.dart';
import 'package:analyzer/src/workspace/gn.dart';
import 'package:analyzer/src/workspace/package_build.dart';
+import 'package:analyzer/src/workspace/pub.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:args/args.dart';
import 'package:package_config/packages.dart';
@@ -672,16 +673,19 @@
static Workspace createWorkspace(ResourceProvider resourceProvider,
String rootPath, ContextBuilder contextBuilder) {
if (_hasPackageFileInPath(resourceProvider, rootPath)) {
- // Bazel workspaces that include package files are treated like normal
- // (non-Bazel) directories. But may still use package:build.
+ // A Bazel or Gn workspace that includes a '.packages' file is treated
+ // like a normal (non-Bazel/Gn) directory. But may still use
+ // package:build or Pub.
return PackageBuildWorkspace.find(
resourceProvider, rootPath, contextBuilder) ??
+ PubWorkspace.find(resourceProvider, rootPath, contextBuilder) ??
BasicWorkspace.find(resourceProvider, rootPath, contextBuilder);
}
Workspace workspace = BazelWorkspace.find(resourceProvider, rootPath);
workspace ??= GnWorkspace.find(resourceProvider, rootPath);
workspace ??=
PackageBuildWorkspace.find(resourceProvider, rootPath, contextBuilder);
+ workspace ??= PubWorkspace.find(resourceProvider, rootPath, contextBuilder);
return workspace ??
BasicWorkspace.find(resourceProvider, rootPath, contextBuilder);
}
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index f26ad7d..eebc966 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -262,61 +262,9 @@
@override
void set analysisOptions(AnalysisOptions options) {
- bool needsRecompute = this._options.analyzeFunctionBodiesPredicate !=
- options.analyzeFunctionBodiesPredicate ||
- this._options.generateImplicitErrors !=
- options.generateImplicitErrors ||
- this._options.generateSdkErrors != options.generateSdkErrors ||
- this._options.dart2jsHint != options.dart2jsHint ||
- _notEqual(
- this._options.enabledPluginNames, options.enabledPluginNames) ||
- _notEqual(this._options.errorProcessors, options.errorProcessors) ||
- _notEqual(this._options.excludePatterns, options.excludePatterns) ||
- (this._options.hint && !options.hint) ||
- (this._options.lint && !options.lint) ||
- _notEqual(this._options.lintRules, options.lintRules) ||
- this._options.preserveComments != options.preserveComments ||
- this._options.useFastaParser != options.useFastaParser ||
- this._options.enableLazyAssignmentOperators !=
- options.enableLazyAssignmentOperators ||
- ((options is AnalysisOptionsImpl)
- ? this._options.strongModeHints != options.strongModeHints
- : false) ||
- ((options is AnalysisOptionsImpl)
- ? this._options.implicitCasts != options.implicitCasts
- : false) ||
- ((options is AnalysisOptionsImpl)
- ? this._options.implicitDynamic != options.implicitDynamic
- : false) ||
- !_samePatchPaths(this._options.patchPaths, options.patchPaths);
- this._options.analyzeFunctionBodiesPredicate =
- options.analyzeFunctionBodiesPredicate;
- this._options.generateImplicitErrors = options.generateImplicitErrors;
- this._options.generateSdkErrors = options.generateSdkErrors;
- this._options.dart2jsHint = options.dart2jsHint;
- this._options.enableLazyAssignmentOperators =
- options.enableLazyAssignmentOperators;
- this._options.enableTiming = options.enableTiming;
- this._options.enabledPluginNames = options.enabledPluginNames;
- this._options.errorProcessors = options.errorProcessors;
- this._options.excludePatterns = options.excludePatterns;
- this._options.hint = options.hint;
- this._options.lint = options.lint;
- this._options.lintRules = options.lintRules;
- this._options.preserveComments = options.preserveComments;
- this._options.useFastaParser = options.useFastaParser;
- this._options.trackCacheDependencies = options.trackCacheDependencies;
- this._options.disableCacheFlushing = options.disableCacheFlushing;
- this._options.patchPaths = options.patchPaths;
- if (options is AnalysisOptionsImpl) {
- this._options.strongModeHints = options.strongModeHints;
- this._options.implicitCasts = options.implicitCasts;
- this._options.implicitDynamic = options.implicitDynamic;
- }
- if (needsRecompute) {
- for (WorkManager workManager in workManagers) {
- workManager.onAnalysisOptionsChanged();
- }
+ this._options = options;
+ for (WorkManager workManager in workManagers) {
+ workManager.onAnalysisOptionsChanged();
}
}
@@ -1650,19 +1598,6 @@
AnalysisEngine.instance.logger.logInformation(message);
}
- bool _notEqual<T>(List<T> first, List<T> second) {
- int length = first.length;
- if (length != second.length) {
- return true;
- }
- for (int i = 0; i < length; i++) {
- if (first[i] != second[i]) {
- return true;
- }
- }
- return false;
- }
-
/**
* Notify all of the analysis listeners that the errors associated with the
* given [source] has been updated to the given [errors].
@@ -1803,21 +1738,6 @@
_removeFromCache(source);
_removeFromPriorityOrder(source);
}
-
- static bool _samePatchPaths(
- Map<String, List<String>> a, Map<String, List<String>> b) {
- if (a.length != b.length) return false;
- for (var key in a.keys) {
- if (!b.containsKey(key)) return false;
- var aValue = a[key];
- var bValue = b[key];
- if (aValue.length != bValue.length) return false;
- for (var i = 0; i < aValue.length; i++) {
- if (aValue[i] != bValue[i]) return false;
- }
- }
- return true;
- }
}
/**
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 9369ec0..e8c9902 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -550,7 +550,13 @@
}
if (AnalysisEngine.isDartFileName(path)) {
_fileTracker.addFile(path);
- _changeFile(path);
+ // If the file is known, it has already been read, even if it did not
+ // exist. Now we are notified that the file exists, so we need to
+ // re-read it and make sure that we invalidate signature of the files
+ // that reference it.
+ if (_fsState.knownFilePaths.contains(path)) {
+ _changeFile(path);
+ }
}
}
@@ -1330,15 +1336,9 @@
* Implementation for [changeFile].
*/
void _changeFile(String path) {
- // If the file is known, it has already been read, even if it din't exist.
- // Now we are notified that the file changed (just changed or added), so we
- // need to re-read it and make sure that we invalidate signature of the
- // files that reference it.
- if (_fsState.knownFilePaths.contains(path)) {
- _fileTracker.changeFile(path);
- _libraryContext = null;
- _priorityResults.clear();
- }
+ _fileTracker.changeFile(path);
+ _libraryContext = null;
+ _priorityResults.clear();
}
/**
@@ -1807,7 +1807,7 @@
}
try {
List<AnalysisDriverExceptionFileBuilder> contextFiles = libraryFile
- .libraryFiles
+ .transitiveFiles
.map((file) => new AnalysisDriverExceptionFileBuilder(
path: file.path, content: file.content))
.toList();
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index 8dad745..4a016fa 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -40,12 +40,18 @@
/// String to enable the experiment "constant-update"
static const String constant_update_2018 = 'constant-update-2018';
+ /// String to enable the experiment "control-flow-collections"
+ static const String control_flow_collections = 'control-flow-collections';
+
/// String to enable the experiment "non-nullable"
static const String non_nullable = 'non-nullable';
/// String to enable the experiment "set-literals"
static const String set_literals = 'set-literals';
+ /// String to enable the experiment "spread-collections"
+ static const String spread_collections = 'spread-collections';
+
/// String to enable the experiment "bogus-disabled"
static const String bogus_disabled = 'bogus-disabled';
@@ -76,6 +82,18 @@
IsEnabledByDefault.non_nullable,
IsExpired.non_nullable,
'Non Nullable'),
+ EnableString.control_flow_collections: const ExperimentalFeature(
+ 3,
+ EnableString.control_flow_collections,
+ IsEnabledByDefault.control_flow_collections,
+ IsExpired.control_flow_collections,
+ 'Control Flow Collections'),
+ EnableString.spread_collections: const ExperimentalFeature(
+ 4,
+ EnableString.spread_collections,
+ IsEnabledByDefault.spread_collections,
+ IsExpired.spread_collections,
+ 'Spread Collections'),
EnableString.bogus_disabled: const ExperimentalFeature(
null,
EnableString.bogus_disabled,
@@ -143,12 +161,18 @@
/// Default state of the experiment "constant-update"
static const bool constant_update_2018 = false;
+ /// Default state of the experiment "control-flow-collections"
+ static const bool control_flow_collections = false;
+
/// Default state of the experiment "non-nullable"
static const bool non_nullable = false;
/// Default state of the experiment "set-literals"
static const bool set_literals = false;
+ /// Default state of the experiment "spread-collections"
+ static const bool spread_collections = false;
+
/// Default state of the experiment "bogus-disabled"
static const bool bogus_disabled = false;
@@ -163,12 +187,18 @@
/// Expiration status of the experiment "constant-update"
static const bool constant_update_2018 = false;
+ /// Expiration status of the experiment "control-flow-collections"
+ static const bool control_flow_collections = false;
+
/// Expiration status of the experiment "non-nullable"
static const bool non_nullable = false;
/// Expiration status of the experiment "set-literals"
static const bool set_literals = false;
+ /// Expiration status of the experiment "spread-collections"
+ static const bool spread_collections = false;
+
/// Expiration status of the experiment "bogus-disabled"
static const bool bogus_disabled = true;
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 35f1df0..eb87535 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -361,6 +361,23 @@
}
/**
+ * Return the set of transitive files - the file itself and all of the
+ * directly or indirectly referenced files.
+ */
+ Set<FileState> get transitiveFiles {
+ var transitiveFiles = new Set<FileState>();
+
+ void appendReferenced(FileState file) {
+ if (transitiveFiles.add(file)) {
+ file._directReferencedFiles?.forEach(appendReferenced);
+ }
+ }
+
+ appendReferenced(this);
+ return transitiveFiles;
+ }
+
+ /**
* Return the signature of the file, based on API signatures of the
* transitive closure of imported / exported files.
*/
@@ -670,9 +687,8 @@
return _createEmptyCompilationUnit();
}
- AnalysisOptions analysisOptions = _fsState._analysisOptions;
- ExperimentStatus experimentStatus =
- new ExperimentStatus.fromStrings(analysisOptions.enabledExperiments);
+ AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
+ ExperimentStatus experimentStatus = analysisOptions.experimentStatus;
CharSequenceReader reader = new CharSequenceReader(content);
Scanner scanner = new Scanner(source, reader, errorListener);
scanner.enableGtGtGt = experimentStatus.constant_update_2018;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index a3813f6..8624f12 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -56,6 +55,7 @@
final TypeProvider _typeProvider;
final TypeSystem _typeSystem;
+ bool isNonNullableMigrated = false;
LibraryElement _libraryElement;
LibraryScope _libraryScope;
@@ -102,6 +102,8 @@
for (FileState file in _library.libraryFiles) {
units[file] = _parse(file);
}
+ isNonNullableMigrated = (units.values.first as CompilationUnitImpl)
+ .hasPragmaAnalyzerNonNullable;
// Resolve URIs in directives to corresponding sources.
units.forEach((file, unit) {
@@ -182,13 +184,8 @@
* Compute [_constants] in all units.
*/
void _computeConstants() {
- computeConstants(
- _typeProvider,
- _context.typeSystem,
- _declaredVariables,
- _constants.toList(),
- ExperimentStatus.fromStrings(
- _context.analysisOptions.enabledExperiments));
+ computeConstants(_typeProvider, _context.typeSystem, _declaredVariables,
+ _constants.toList(), _analysisOptions.experimentStatus);
}
void _computeHints(FileState file, CompilationUnit unit) {
@@ -603,11 +600,13 @@
// TODO(scheglov) remove EnumMemberBuilder class
new TypeParameterBoundsResolver(
- _context.typeSystem, _libraryElement, source, errorListener)
+ _context.typeSystem, _libraryElement, source, errorListener,
+ isNonNullableMigrated: isNonNullableMigrated)
.resolveTypeBounds(unit);
unit.accept(new TypeResolverVisitor(
- _libraryElement, source, _typeProvider, errorListener));
+ _libraryElement, source, _typeProvider, errorListener,
+ isNonNullableMigrated: isNonNullableMigrated));
unit.accept(new VariableResolverVisitor(
_libraryElement, source, _typeProvider, errorListener,
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 30e9486..453c439 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -12,12 +12,12 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
/// Instances of the class `ConstantVerifier` traverse an AST structure looking
@@ -70,8 +70,9 @@
_typeProvider, declaredVariables,
forAnalysisDriver: forAnalysisDriver,
typeSystem: _typeSystem,
- experimentStatus: ExperimentStatus.fromStrings(
- currentLibrary.context.analysisOptions.enabledExperiments));
+ experimentStatus:
+ (currentLibrary.context.analysisOptions as AnalysisOptionsImpl)
+ .experimentStatus);
}
@override
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f23c65a..f764d36 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -12,7 +12,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/compute.dart';
import 'package:analyzer/src/dart/constant/value.dart';
@@ -20,7 +19,7 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
import 'package:analyzer/src/generated/engine.dart'
- show AnalysisContext, AnalysisEngine;
+ show AnalysisContext, AnalysisEngine, AnalysisOptionsImpl;
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
@@ -2336,13 +2335,9 @@
/// of this variable could not be computed because of errors.
DartObject computeConstantValue() {
if (evaluationResult == null) {
- computeConstants(
- context.typeProvider,
- context.typeSystem,
- context.declaredVariables,
- [this],
- ExperimentStatus.fromStrings(
- context.analysisOptions.enabledExperiments));
+ AnalysisOptionsImpl analysisOptions = context.analysisOptions;
+ computeConstants(context.typeProvider, context.typeSystem,
+ context.declaredVariables, [this], analysisOptions.experimentStatus);
}
return evaluationResult?.value;
}
@@ -2556,12 +2551,6 @@
element.library?.name == _META_LIB_NAME;
@override
- bool get isLiteral =>
- element is PropertyAccessorElement &&
- element.name == _LITERAL_VARIABLE_NAME &&
- element.library?.name == _META_LIB_NAME;
-
- @override
bool get isIsTest =>
element is PropertyAccessorElement &&
element.name == _IS_TEST_VARIABLE_NAME &&
@@ -2580,6 +2569,12 @@
element.library?.name == _JS_LIB_NAME;
@override
+ bool get isLiteral =>
+ element is PropertyAccessorElement &&
+ element.name == _LITERAL_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
bool get isMustCallSuper =>
element is PropertyAccessorElement &&
element.name == _MUST_CALL_SUPER_VARIABLE_NAME &&
@@ -2639,13 +2634,9 @@
@override
DartObject computeConstantValue() {
if (evaluationResult == null) {
- computeConstants(
- context.typeProvider,
- context.typeSystem,
- context.declaredVariables,
- [this],
- ExperimentStatus.fromStrings(
- context.analysisOptions.enabledExperiments));
+ AnalysisOptionsImpl analysisOptions = context.analysisOptions;
+ computeConstants(context.typeProvider, context.typeSystem,
+ context.declaredVariables, [this], analysisOptions.experimentStatus);
}
return constantValue;
}
@@ -2836,6 +2827,18 @@
}
@override
+ bool get hasLiteral {
+ var metadata = this.metadata;
+ for (var i = 0; i < metadata.length; i++) {
+ var annotation = metadata[i];
+ if (annotation.isLiteral) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
bool get hasOverride {
var metadata = this.metadata;
for (var i = 0; i < metadata.length; i++) {
@@ -4203,7 +4206,10 @@
@override
DartType get type {
- if (unlinkedParam != null && unlinkedParam.type == null && field != null) {
+ if (unlinkedParam != null &&
+ unlinkedParam.type == null &&
+ !unlinkedParam.isFunctionTyped &&
+ field != null) {
_type ??= field?.type ?? DynamicTypeImpl.instance;
}
return super.type;
@@ -6400,6 +6406,9 @@
bool get hasJS => false;
@override
+ bool get hasLiteral => false;
+
+ @override
bool get hasOverride => false;
@override
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 97f978f..67f47f7 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -46,6 +46,9 @@
bool get hasJS => actualElement.hasJS;
@override
+ bool get hasLiteral => actualElement.hasLiteral;
+
+ @override
bool get hasNonFinalField => actualElement.hasNonFinalField;
@override
@@ -389,6 +392,9 @@
bool get hasJS => actualElement.hasJS;
@override
+ bool get hasLiteral => actualElement.hasLiteral;
+
+ @override
bool get hasOverride => actualElement.hasOverride;
@override
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index bc18d7b7..484458a 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -422,6 +422,9 @@
bool get hasJS => _baseElement.hasJS;
@override
+ bool get hasLiteral => _baseElement.hasLiteral;
+
+ @override
bool get hasOverride => _baseElement.hasOverride;
@override
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 40d664e..6b7d311 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -56,14 +56,35 @@
*/
class BottomTypeImpl extends TypeImpl {
/**
- * The unique instance of this class.
+ * The unique instance of this class, with indeterminate nullability.
*/
- static final BottomTypeImpl instance = new BottomTypeImpl._();
+ static final BottomTypeImpl instance = instanceIndeterminate;
+
+ /**
+ * The unique instance of this class, nullable.
+ */
+ static final BottomTypeImpl instanceNullable =
+ new BottomTypeImpl._(Nullability.nullable);
+
+ /**
+ * The unique instance of this class, with indeterminate nullability.
+ */
+ static final BottomTypeImpl instanceIndeterminate =
+ new BottomTypeImpl._(Nullability.indeterminate);
+
+ /**
+ * The unique instance of this class, non-nullable.
+ */
+ static final BottomTypeImpl instanceNonNullable =
+ new BottomTypeImpl._(Nullability.nonNullable);
+
+ @override
+ final Nullability nullability;
/**
* Prevent the creation of instances of this class.
*/
- BottomTypeImpl._() : super(null, "<bottom>");
+ BottomTypeImpl._(this.nullability) : super(null, "<bottom>");
@override
int get hashCode => 0;
@@ -111,6 +132,19 @@
List<DartType> argumentTypes, List<DartType> parameterTypes,
[List<FunctionTypeAliasElement> prune]) =>
this;
+
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ switch (nullability) {
+ case Nullability.nullable:
+ return instanceNullable;
+ case Nullability.indeterminate:
+ return instanceIndeterminate;
+ case Nullability.nonNullable:
+ return instanceNonNullable;
+ }
+ throw StateError('Unexpected nullability: $nullability');
+ }
}
/**
@@ -119,7 +153,7 @@
*/
class CircularFunctionTypeImpl extends DynamicTypeImpl
implements _FunctionTypeImplLazy {
- CircularFunctionTypeImpl() : super._circular();
+ CircularFunctionTypeImpl() : super._circular(Nullability.indeterminate);
@override
List<ParameterElement> get baseParameters => const <ParameterElement>[];
@@ -206,7 +240,8 @@
bool operator ==(Object object) => object is CircularFunctionTypeImpl;
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
+ void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
+ {bool withNullability = false}) {
buffer.write('...');
}
@@ -227,6 +262,9 @@
FunctionTypeImpl substitute3(List<DartType> argumentTypes) => this;
@override
+ TypeImpl withNullability(Nullability nullability) => this;
+
+ @override
void _forEachParameterType(
ParameterKind kind, callback(String name, DartType type)) {
// There are no parameters.
@@ -256,13 +294,14 @@
* `...`.
*/
class CircularTypeImpl extends DynamicTypeImpl {
- CircularTypeImpl() : super._circular();
+ CircularTypeImpl() : super._circular(Nullability.indeterminate);
@override
bool operator ==(Object object) => object is CircularTypeImpl;
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
+ void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
+ {bool withNullability = false}) {
buffer.write('...');
}
@@ -292,8 +331,10 @@
FunctionTypedElement _computedElement;
DeferredFunctionTypeImpl(this._computeElement, String name,
- List<DartType> typeArguments, bool isInstantiated)
- : super._(null, name, null, typeArguments, null, null, isInstantiated);
+ List<DartType> typeArguments, bool isInstantiated,
+ {Nullability nullability = Nullability.indeterminate})
+ : super._(null, name, null, typeArguments, null, null, isInstantiated,
+ nullability: nullability);
@override
FunctionTypedElement get element {
@@ -303,6 +344,14 @@
}
return _computedElement;
}
+
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ if (this.nullability == nullability) return this;
+ return DeferredFunctionTypeImpl(
+ _computeElement, name, typeArguments, isInstantiated,
+ nullability: nullability);
+ }
}
/**
@@ -310,14 +359,35 @@
*/
class DynamicTypeImpl extends TypeImpl {
/**
- * The unique instance of this class.
+ * The unique instance of this class, with indeterminate nullability.
*/
- static final DynamicTypeImpl instance = new DynamicTypeImpl._();
+ static final DynamicTypeImpl instance = instanceIndeterminate;
+
+ /**
+ * The unique instance of this class, nullable.
+ */
+ static final DynamicTypeImpl instanceNullable =
+ new DynamicTypeImpl._(Nullability.nullable);
+
+ /**
+ * The unique instance of this class, with indeterminate nullability.
+ */
+ static final DynamicTypeImpl instanceIndeterminate =
+ new DynamicTypeImpl._(Nullability.indeterminate);
+
+ /**
+ * The unique instance of this class, non-nullable.
+ */
+ static final DynamicTypeImpl instanceNonNullable =
+ new DynamicTypeImpl._(Nullability.nonNullable);
+
+ @override
+ final Nullability nullability;
/**
* Prevent the creation of instances of this class.
*/
- DynamicTypeImpl._()
+ DynamicTypeImpl._(this.nullability)
: super(new DynamicElementImpl(), Keyword.DYNAMIC.lexeme) {
(element as DynamicElementImpl).type = this;
}
@@ -325,7 +395,8 @@
/**
* Constructor used by [CircularTypeImpl].
*/
- DynamicTypeImpl._circular() : super(instance.element, Keyword.DYNAMIC.lexeme);
+ DynamicTypeImpl._circular(this.nullability)
+ : super(instance.element, Keyword.DYNAMIC.lexeme);
@override
int get hashCode => 1;
@@ -378,23 +449,41 @@
}
return this;
}
+
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ switch (nullability) {
+ case Nullability.nullable:
+ return instanceNullable;
+ case Nullability.indeterminate:
+ return instanceIndeterminate;
+ case Nullability.nonNullable:
+ return instanceNonNullable;
+ }
+ throw StateError('Unexpected nullability: $nullability');
+ }
}
/**
* The type of a function, method, constructor, getter, or setter.
*/
abstract class FunctionTypeImpl extends TypeImpl implements FunctionType {
+ @override
+ final Nullability nullability;
+
/**
* Initialize a newly created function type to be declared by the given
* [element], and also initialize [typeArguments] to match the
* [typeParameters], which permits later substitution.
*/
- factory FunctionTypeImpl(FunctionTypedElement element) {
+ factory FunctionTypeImpl(FunctionTypedElement element,
+ {Nullability nullability = Nullability.indeterminate}) {
if (element is FunctionTypeAliasElement) {
throw new StateError('Use FunctionTypeImpl.forTypedef for typedefs');
}
return new _FunctionTypeImplLazy._(
- element, null, null, null, null, null, false);
+ element, null, null, null, null, null, false,
+ nullability: nullability);
}
/**
@@ -404,9 +493,11 @@
* Note: this constructor mishandles generics.
* See https://github.com/dart-lang/sdk/issues/34657.
*/
- factory FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element) {
+ factory FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
+ {Nullability nullability = Nullability.indeterminate}) {
return new _FunctionTypeImplLazy._(
- element, element?.name, null, null, null, null, false);
+ element, element?.name, null, null, null, null, false,
+ nullability: nullability);
}
/**
@@ -417,7 +508,9 @@
* If type formals is empty, this returns the original unless [force] is set
* to [true].
*/
- factory FunctionTypeImpl.fresh(FunctionType original, {bool force = false}) {
+ factory FunctionTypeImpl.fresh(FunctionType original,
+ {bool force = false,
+ Nullability nullability = Nullability.indeterminate}) {
// We build up a substitution for the type parameters,
// {variablesFresh/variables} then apply it.
@@ -465,19 +558,21 @@
function.returnType = newType.returnType;
function.typeParameters = freshVarElements;
function.shareParameters(newType.parameters);
- return function.type = new FunctionTypeImpl(function);
+ return function.type =
+ new FunctionTypeImpl(function, nullability: nullability);
}
/// Creates a function type that's not associated with any element in the
/// element tree.
- factory FunctionTypeImpl.synthetic(
- DartType returnType,
- List<TypeParameterElement> typeFormals,
- List<ParameterElement> parameters) {
- return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters);
+ factory FunctionTypeImpl.synthetic(DartType returnType,
+ List<TypeParameterElement> typeFormals, List<ParameterElement> parameters,
+ {Nullability nullability = Nullability.indeterminate}) {
+ return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters,
+ nullability: nullability);
}
- FunctionTypeImpl._(Element element, String name) : super(element, name);
+ FunctionTypeImpl._(Element element, String name, this.nullability)
+ : super(element, name);
@deprecated
@override
@@ -626,7 +721,8 @@
}
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
+ void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
+ {bool withNullability = false}) {
if (visitedTypes.add(this)) {
if (typeFormals.isNotEmpty) {
// To print a type with type variables, first make sure we have unique
@@ -661,7 +757,7 @@
}
TypeParameterTypeImpl t =
new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1));
- t.appendTo(buffer, visitedTypes);
+ t.appendTo(buffer, visitedTypes, withNullability: withNullability);
instantiateTypeArgs.add(t);
variables.add(e.type);
if (e.bound != null) {
@@ -675,7 +771,9 @@
// Instantiate it and print the resulting type. After instantiation, it
// will no longer have typeFormals, so we will continue below.
- this.instantiate(instantiateTypeArgs).appendTo(buffer, visitedTypes);
+ this
+ .instantiate(instantiateTypeArgs)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
return;
}
@@ -704,7 +802,8 @@
if (normalParameterTypes.isNotEmpty) {
for (DartType type in normalParameterTypes) {
writeSeparator();
- (type as TypeImpl).appendTo(buffer, visitedTypes);
+ (type as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
}
}
if (optionalParameterTypes.isNotEmpty) {
@@ -712,7 +811,8 @@
buffer.write("[");
for (DartType type in optionalParameterTypes) {
writeSeparator();
- (type as TypeImpl).appendTo(buffer, visitedTypes);
+ (type as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
}
buffer.write("]");
needsComma = true;
@@ -724,7 +824,8 @@
writeSeparator();
buffer.write(name);
buffer.write(": ");
- (type as TypeImpl).appendTo(buffer, visitedTypes);
+ (type as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
});
buffer.write("}");
needsComma = true;
@@ -734,7 +835,11 @@
if (returnType == null) {
buffer.write("null");
} else {
- (returnType as TypeImpl).appendTo(buffer, visitedTypes);
+ (returnType as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ }
+ if (withNullability) {
+ _appendNullability(buffer);
}
visitedTypes.remove(this);
} else {
@@ -823,9 +928,9 @@
if (identical(returnType, this.returnType) &&
identical(parameters, this.parameters)) {
return this;
- } else {
- return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters);
}
+ return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters,
+ nullability: nullability);
}
@override
@@ -1191,6 +1296,9 @@
* A concrete implementation of an [InterfaceType].
*/
class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
+ @override
+ final Nullability nullability;
+
/**
* A list containing the actual types of the type arguments.
*/
@@ -1231,7 +1339,8 @@
/**
* Initialize a newly created type to be declared by the given [element].
*/
- InterfaceTypeImpl(ClassElement element, [this.prunedTypedefs])
+ InterfaceTypeImpl(ClassElement element,
+ [this.prunedTypedefs, this.nullability = Nullability.indeterminate])
: super(element, element.displayName);
/**
@@ -1239,26 +1348,42 @@
* with the given [name] and [typeArguments].
*/
InterfaceTypeImpl.elementWithNameAndArgs(
- ClassElement element, String name, this._typeArgumentsComputer)
+ ClassElement element, String name, this._typeArgumentsComputer,
+ {this.nullability = Nullability.indeterminate})
: prunedTypedefs = null,
super(element, name) {
_typeArguments = null;
}
+ InterfaceTypeImpl.explicit(ClassElement element, List<DartType> typeArguments,
+ {this.nullability = Nullability.indeterminate})
+ : prunedTypedefs = null,
+ _typeArguments = typeArguments,
+ super(element, element.displayName);
+
/**
* Initialize a newly created type to have the given [name]. This constructor
* should only be used in cases where there is no declaration of the type.
*/
- InterfaceTypeImpl.named(String name)
+ InterfaceTypeImpl.named(String name,
+ {this.nullability = Nullability.indeterminate})
: prunedTypedefs = null,
super(null, name);
/**
* Private constructor.
*/
- InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs)
+ InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs,
+ {this.nullability = Nullability.indeterminate})
: super(element, name);
+ InterfaceTypeImpl._withNullability(InterfaceTypeImpl original,
+ {this.nullability = Nullability.indeterminate})
+ : _typeArguments = original._typeArguments,
+ _typeArgumentsComputer = original._typeArgumentsComputer,
+ prunedTypedefs = original.prunedTypedefs,
+ super(original.element, original.name);
+
@override
List<PropertyAccessorElement> get accessors {
_flushCachedMembersIfStale();
@@ -1380,6 +1505,15 @@
}
@override
+ bool get isDartCoreInt {
+ ClassElement element = this.element;
+ if (element == null) {
+ return false;
+ }
+ return element.name == "int" && element.library.isDartCore;
+ }
+
+ @override
bool get isDartCoreNull {
ClassElement element = this.element;
if (element == null) {
@@ -1471,7 +1605,8 @@
}
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
+ void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
+ {bool withNullability = false}) {
if (visitedTypes.add(this)) {
buffer.write(name);
int argumentCount = typeArguments.length;
@@ -1481,10 +1616,14 @@
if (i > 0) {
buffer.write(", ");
}
- (typeArguments[i] as TypeImpl).appendTo(buffer, visitedTypes);
+ (typeArguments[i] as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
}
buffer.write(">");
}
+ if (withNullability) {
+ _appendNullability(buffer);
+ }
visitedTypes.remove(this);
} else {
buffer.write('<recursive>');
@@ -2042,7 +2181,8 @@
// alias, and function type aliases are always expanded by starting with
// base types.
assert(this.prunedTypedefs == null);
- InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune);
+ InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune,
+ nullability: nullability);
result.typeArguments = typeArguments
.map((DartType t) => (t as TypeImpl).pruned(prune))
.toList();
@@ -2070,7 +2210,8 @@
if (identical(typeArguments, this.typeArguments)) {
return this;
} else {
- return new InterfaceTypeImpl._(element, name, prunedTypedefs)
+ return new InterfaceTypeImpl._(element, name, prunedTypedefs,
+ nullability: nullability)
..typeArguments = typeArguments;
}
}
@@ -2093,7 +2234,8 @@
return this;
}
- InterfaceTypeImpl newType = new InterfaceTypeImpl(element, prune);
+ InterfaceTypeImpl newType =
+ new InterfaceTypeImpl(element, prune, nullability);
newType.typeArguments = newTypeArguments;
return newType;
}
@@ -2103,6 +2245,12 @@
InterfaceTypeImpl substitute4(List<DartType> argumentTypes) =>
instantiate(argumentTypes);
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ if (this.nullability == nullability) return this;
+ return InterfaceTypeImpl._withNullability(this, nullability: nullability);
+ }
+
/**
* Flush cache members if the version of [element] for which members are
* cached and the current version of the [element].
@@ -2449,7 +2597,21 @@
lubArguments[i] = DynamicTypeImpl.instance;
}
}
- InterfaceTypeImpl lub = new InterfaceTypeImpl(firstElement);
+
+ Nullability computeNullability() {
+ Nullability first = (firstType as InterfaceTypeImpl).nullability;
+ Nullability second = (secondType as InterfaceTypeImpl).nullability;
+ if (first == Nullability.nullable || second == Nullability.nullable) {
+ return Nullability.nullable;
+ } else if (first == Nullability.indeterminate ||
+ second == Nullability.indeterminate) {
+ return Nullability.indeterminate;
+ }
+ return Nullability.nonNullable;
+ }
+
+ InterfaceTypeImpl lub =
+ new InterfaceTypeImpl(firstElement, null, computeNullability());
lub.typeArguments = lubArguments;
return lub;
}
@@ -2515,6 +2677,27 @@
}
/**
+ * The nullability of a type.
+ */
+enum Nullability {
+ /**
+ * An indication that the type includes the value `null`.
+ */
+ nullable,
+
+ /**
+ * An indication that the type is a legacy type which may be interpreted as
+ * either nullable or non-nullable as appropriate.
+ */
+ indeterminate,
+
+ /**
+ * An indication that the type does not include the value `null`.
+ */
+ nonNullable
+}
+
+/**
* The abstract class `TypeImpl` implements the behavior common to objects
* representing the declared type of elements in the element model.
*/
@@ -2555,6 +2738,9 @@
bool get isDartCoreFunction => false;
@override
+ bool get isDartCoreInt => false;
+
+ @override
bool get isDartCoreNull => false;
@override
@@ -2570,10 +2756,16 @@
bool get isVoid => false;
/**
+ * Return the nullability of this type.
+ */
+ Nullability get nullability;
+
+ /**
* Append a textual representation of this type to the given [buffer]. The set
* of [visitedTypes] is used to prevent infinite recursion.
*/
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
+ void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
+ {bool withNullability = false}) {
if (visitedTypes.add(this)) {
if (name == null) {
buffer.write("<unnamed type>");
@@ -2584,6 +2776,9 @@
} else {
buffer.write('<recursive>');
}
+ if (withNullability) {
+ _appendNullability(buffer);
+ }
}
@override
@@ -2687,13 +2882,32 @@
[List<FunctionTypeAliasElement> prune]);
@override
- String toString() {
+ String toString({bool withNullability = false}) {
StringBuffer buffer = new StringBuffer();
- appendTo(buffer, new Set.identity());
+ appendTo(buffer, new Set.identity(), withNullability: withNullability);
return buffer.toString();
}
/**
+ * Return the same type, but with the given [nullability].
+ */
+ TypeImpl withNullability(Nullability nullability);
+
+ void _appendNullability(StringBuffer buffer) {
+ switch (nullability) {
+ case Nullability.nullable:
+ buffer.write('?');
+ break;
+ case Nullability.indeterminate:
+ buffer.write('*');
+ break;
+ case Nullability.nonNullable:
+ buffer.write('!');
+ break;
+ }
+ }
+
+ /**
* Return `true` if corresponding elements of the [first] and [second] lists
* of type arguments are all equal.
*/
@@ -2775,11 +2989,15 @@
static bool _appendingBounds = false;
+ @override
+ final Nullability nullability;
+
/**
* Initialize a newly created type parameter type to be declared by the given
* [element] and to have the given name.
*/
- TypeParameterTypeImpl(TypeParameterElement element)
+ TypeParameterTypeImpl(TypeParameterElement element,
+ {this.nullability = Nullability.indeterminate})
: super(element, element.name);
@override
@@ -2816,8 +3034,9 @@
* Append a textual representation of this type to the given [buffer]. The set
* of [visitedTypes] is used to prevent infinite recursion.
*/
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
- super.appendTo(buffer, visitedTypes);
+ void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
+ {bool withNullability = false}) {
+ super.appendTo(buffer, visitedTypes, withNullability: withNullability);
TypeParameterElement e = element;
if (e is TypeParameterMember &&
e.bound != e.baseElement.bound &&
@@ -2826,7 +3045,8 @@
// If we're appending bounds already, we don't want to do it recursively.
_appendingBounds = true;
try {
- (e.bound as TypeImpl).appendTo(buffer, visitedTypes);
+ (e.bound as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
} finally {
_appendingBounds = false;
}
@@ -2933,12 +3153,38 @@
int length = parameterTypes.length;
for (int i = 0; i < length; i++) {
if (parameterTypes[i] == this) {
- return argumentTypes[i];
+ TypeImpl argumentType = argumentTypes[i];
+
+ // TODO(scheglov) It should not happen, but sometimes arguments are null.
+ if (argumentType == null) {
+ return argumentType;
+ }
+
+ // TODO(scheglov) Proposed substitution rules for nullability.
+ Nullability resultNullability;
+ Nullability argumentNullability = argumentType.nullability;
+ if (argumentNullability == Nullability.nullable ||
+ nullability == Nullability.nullable) {
+ resultNullability = Nullability.nullable;
+ } else if (argumentNullability == Nullability.indeterminate ||
+ nullability == Nullability.indeterminate) {
+ resultNullability = Nullability.indeterminate;
+ } else {
+ resultNullability = Nullability.nonNullable;
+ }
+
+ return argumentType.withNullability(resultNullability);
}
}
return this;
}
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ if (this.nullability == nullability) return this;
+ return TypeParameterTypeImpl(element, nullability: nullability);
+ }
+
/**
* Return a list containing the type parameter types defined by the given
* array of type parameter elements ([typeParameters]).
@@ -2986,6 +3232,9 @@
bool get isUndefined => true;
@override
+ Nullability get nullability => Nullability.indeterminate;
+
+ @override
bool operator ==(Object object) => identical(object, this);
@override
@@ -3030,6 +3279,9 @@
}
return this;
}
+
+ @override
+ TypeImpl withNullability(Nullability nullability) => this;
}
/**
@@ -3046,14 +3298,35 @@
*/
class VoidTypeImpl extends TypeImpl implements VoidType {
/**
- * The unique instance of this class.
+ * The unique instance of this class, with indeterminate nullability.
*/
- static final VoidTypeImpl instance = new VoidTypeImpl._();
+ static final VoidTypeImpl instance = instanceIndeterminate;
+
+ /**
+ * The unique instance of this class, nullable.
+ */
+ static final VoidTypeImpl instanceNullable =
+ new VoidTypeImpl._(Nullability.nullable);
+
+ /**
+ * The unique instance of this class, with indeterminate nullability.
+ */
+ static final VoidTypeImpl instanceIndeterminate =
+ new VoidTypeImpl._(Nullability.indeterminate);
+
+ /**
+ * The unique instance of this class, non-nullable.
+ */
+ static final VoidTypeImpl instanceNonNullable =
+ new VoidTypeImpl._(Nullability.nonNullable);
+
+ @override
+ final Nullability nullability;
/**
* Prevent the creation of instances of this class.
*/
- VoidTypeImpl._() : super(null, Keyword.VOID.lexeme);
+ VoidTypeImpl._(this.nullability) : super(null, Keyword.VOID.lexeme);
@override
int get hashCode => 2;
@@ -3096,6 +3369,19 @@
List<DartType> argumentTypes, List<DartType> parameterTypes,
[List<FunctionTypeAliasElement> prune]) =>
this;
+
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ switch (nullability) {
+ case Nullability.nullable:
+ return instanceNullable;
+ case Nullability.indeterminate:
+ return instanceIndeterminate;
+ case Nullability.nonNullable:
+ return instanceNonNullable;
+ }
+ throw StateError('Unexpected nullability: $nullability');
+ }
}
/**
@@ -3146,9 +3432,10 @@
this._typeArguments,
this._returnType,
this._parameters,
- this._isInstantiated)
+ this._isInstantiated,
+ {Nullability nullability = Nullability.indeterminate})
: _typeParameters = null,
- super._(element, name);
+ super._(element, name, nullability);
/**
* Return the base parameter elements of this function element.
@@ -3354,7 +3641,8 @@
newTypeArgs.addAll(argumentTypes);
return new _FunctionTypeImplLazy._(element, name, prunedTypedefs,
- newTypeArgs, _returnType, _parameters, true);
+ newTypeArgs, _returnType, _parameters, true,
+ nullability: nullability);
}
@override
@@ -3375,7 +3663,8 @@
.map((DartType t) => (t as TypeImpl).pruned(prune))
.toList(growable: false);
return new _FunctionTypeImplLazy._(element, name, prune, typeArgs,
- _returnType, _parameters, _isInstantiated);
+ _returnType, _parameters, _isInstantiated,
+ nullability: nullability);
}
}
@@ -3403,7 +3692,16 @@
List<DartType> typeArgs =
TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
return new _FunctionTypeImplLazy._(element, name, prune, typeArgs,
- _returnType, _parameters, _isInstantiated);
+ _returnType, _parameters, _isInstantiated,
+ nullability: nullability);
+ }
+
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ if (this.nullability == nullability) return this;
+ return _FunctionTypeImplLazy._(element, name, prunedTypedefs,
+ _typeArguments, _returnType, _parameters, _isInstantiated,
+ nullability: nullability);
}
@override
@@ -3450,8 +3748,9 @@
@override
final List<ParameterElement> parameters;
- _FunctionTypeImplStrict._(this.returnType, this.typeFormals, this.parameters)
- : super._(null, null);
+ _FunctionTypeImplStrict._(this.returnType, this.typeFormals, this.parameters,
+ {Nullability nullability = Nullability.indeterminate})
+ : super._(null, null, nullability);
@override
List<TypeParameterElement> get boundTypeParameters => typeFormals;
@@ -3506,7 +3805,8 @@
return new _FunctionTypeImplStrict._(
returnType.substitute2(argumentTypes, parameterTypes),
const [],
- _transformOrShare(parameters, transformParameter));
+ _transformOrShare(parameters, transformParameter),
+ nullability: nullability);
}
@override
@@ -3565,7 +3865,15 @@
return this;
}
return new _FunctionTypeImplStrict._(
- newReturnType, newTypeFormals, newParameters);
+ newReturnType, newTypeFormals, newParameters,
+ nullability: nullability);
+ }
+
+ @override
+ TypeImpl withNullability(Nullability nullability) {
+ if (this.nullability == nullability) return this;
+ return _FunctionTypeImplStrict._(returnType, typeFormals, parameters,
+ nullability: nullability);
}
@override
diff --git a/pkg/analyzer/lib/src/dart/element/wrapped.dart b/pkg/analyzer/lib/src/dart/element/wrapped.dart
index 3dfc8d6..3c6f7f1 100644
--- a/pkg/analyzer/lib/src/dart/element/wrapped.dart
+++ b/pkg/analyzer/lib/src/dart/element/wrapped.dart
@@ -65,6 +65,9 @@
bool get hasJS => wrappedUnit.hasJS;
@override
+ bool get hasLiteral => wrappedUnit.hasLiteral;
+
+ @override
bool get hasLoadLibraryFunction => wrappedUnit.hasLoadLibraryFunction;
@override
@@ -255,6 +258,9 @@
bool get hasJS => wrappedImport.hasJS;
@override
+ bool get hasLiteral => wrappedImport.hasLiteral;
+
+ @override
bool get hasOverride => wrappedImport.hasOverride;
@override
@@ -454,6 +460,9 @@
bool get hasJS => wrappedLib.hasJS;
@override
+ bool get hasLiteral => wrappedLib.hasLiteral;
+
+ @override
bool get hasLoadLibraryFunction => wrappedLib.hasLoadLibraryFunction;
@override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 07700ec..62c6a8a 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -68,6 +68,23 @@
"Try replacing the use of the deprecated member with the replacement.");
/**
+ * Deprecated members should not be invoked or used from within the package
+ * where they are declared.
+ *
+ * Intentionally separate from DEPRECATED_MEMBER_USE, so that package owners
+ * can ignore same-package deprecate member use Hints if they like, and
+ * continue to see cross-package deprecated member use Hints.
+ *
+ * Parameters:
+ * 0: the name of the member
+ */
+ static const HintCode DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE = const HintCode(
+ 'DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE',
+ "'{0}' is deprecated and shouldn't be used.",
+ correction:
+ "Try replacing the use of the deprecated member with the replacement.");
+
+ /**
* Users should not create a class named `Function` anymore.
*/
static const HintCode DEPRECATED_FUNCTION_CLASS_DECLARATION = const HintCode(
@@ -161,23 +178,6 @@
"rename the function in the imported library.");
/**
- * This hint is generated anywhere where the
- * [StaticTypeWarningCode.INVALID_ASSIGNMENT] would have been generated, if we
- * used propagated information for the warnings.
- *
- * Parameters:
- * 0: the name of the right hand side type
- * 1: the name of the left hand side type
- */
- // TODO(brianwilkerson) This hint code should be removed, as should the code
- // that appears to generate it.
- static const HintCode INVALID_ASSIGNMENT = const HintCode(
- 'INVALID_ASSIGNMENT',
- "A value of type '{0}' can't be assigned to a variable of type '{1}'.",
- correction: "Try changing the type of the variable, or "
- "casting the right-hand type to '{1}'.");
-
- /**
* This hint is generated anywhere a @factory annotation is associated with
* anything other than a method.
*/
@@ -399,6 +399,27 @@
"but does not invoke the overridden method.");
/**
+ * Generate a hint for non-const instance creation using a constructor
+ * annotated with `@literal`.
+ */
+ static const HintCode NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR = const HintCode(
+ 'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR',
+ "This instance creation must be 'const', because the {0} constructor is "
+ "marked as '@literal'.",
+ correction: "Try adding a 'const' keyword.");
+
+ /**
+ * Generate a hint for non-const instance creation (with the `new` keyword)
+ * using a constructor annotated with `@literal`.
+ */
+ static const HintCode NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW =
+ const HintCode(
+ 'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW',
+ "This instance creation must be 'const', because the {0} constructor is "
+ "marked as '@literal'.",
+ correction: "Try replacing the 'new' keyword with 'const'.");
+
+ /**
* When the left operand of a binary expression uses '?.' operator, it can be
* `null`.
*/
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 10894cd..527f2ed 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -17,6 +17,7 @@
import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/java_engine.dart';
@@ -1422,8 +1423,12 @@
@override
bool dart2jsHint = false;
- @override
- List<String> enabledExperiments = const <String>[];
+ List<String> _enabledExperiments = const <String>[];
+
+ /**
+ * Parsed [enabledExperiments].
+ */
+ ExperimentStatus _experimentStatus = ExperimentStatus();
@override
List<String> enabledPluginNames = const <String>[];
@@ -1602,6 +1607,14 @@
void set enableConditionalDirectives(_) {}
@override
+ List<String> get enabledExperiments => _enabledExperiments;
+
+ set enabledExperiments(List<String> enabledExperiments) {
+ _enabledExperiments = enabledExperiments;
+ _experimentStatus = ExperimentStatus.fromStrings(enabledExperiments);
+ }
+
+ @override
@deprecated
bool get enableGenericMethods => true;
@@ -1655,6 +1668,11 @@
}
/**
+ * The set of enabled experiments.
+ */
+ ExperimentStatus get experimentStatus => _experimentStatus;
+
+ /**
* Return `true` to enable mixin declarations.
* https://github.com/dart-lang/language/issues/12
*/
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 7992ecf..5283d92 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2220,7 +2220,7 @@
if (expressionType == null) {
return;
}
- if (_expressionIsAssignableAtType(expression, expressionType, type)) {
+ if (_typeSystem.isAssignableTo(expressionType, type)) {
return;
}
_errorReporter.reportErrorForNode(errorCode, expression, arguments);
@@ -2239,8 +2239,7 @@
DartType actualStaticType,
DartType expectedStaticType,
ErrorCode errorCode) {
- if (!_expressionIsAssignableAtType(
- expression, actualStaticType, expectedStaticType)) {
+ if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
_errorReporter.reportTypeErrorForNode(
errorCode, expression, [actualStaticType, expectedStaticType]);
return false;
@@ -3093,7 +3092,7 @@
if (staticType == null) {
return;
}
- if (_expressionIsAssignableAtType(expression, staticType, fieldType)) {
+ if (_typeSystem.isAssignableTo(staticType, fieldType)) {
return;
}
// report problem
@@ -4972,8 +4971,7 @@
var checkWithType = (!_inAsync)
? fromType
: _typeProvider.futureType.instantiate(<DartType>[fromType]);
- if (_expressionIsAssignableAtType(
- returnExpression, checkWithType, expectedType)) {
+ if (_typeSystem.isAssignableTo(checkWithType, expectedType)) {
return;
}
}
@@ -5075,7 +5073,7 @@
DartType caseType = getStaticType(caseExpression);
// check types
- if (!_expressionIsAssignableAtType(expression, expressionType, caseType)) {
+ if (!_typeSystem.isAssignableTo(expressionType, caseType)) {
_errorReporter.reportErrorForNode(
StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
expression,
@@ -5719,11 +5717,6 @@
}
}
- bool _expressionIsAssignableAtType(Expression expression,
- DartType actualStaticType, DartType expectedStaticType) {
- return _typeSystem.isAssignableTo(actualStaticType, expectedStaticType);
- }
-
InterfaceType _findInterfaceTypeForMixin(TypeName mixin,
InterfaceType supertypeConstraint, List<InterfaceType> interfaceTypes) {
var element = supertypeConstraint.element;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 3696609..9dc3ff1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -29,11 +29,11 @@
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error_verifier.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/static_type_analyzer.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:path/path.dart' as path;
@@ -286,6 +286,9 @@
/// The [WorkspacePackage] in which [_currentLibrary] is declared.
WorkspacePackage _workspacePackage;
+ /// The [LinterContext] used for possible const calculations.
+ LinterContext _linterContext;
+
/// Create a new instance of the [BestPracticesVerifier].
///
/// @param errorReporter the error reporter
@@ -295,6 +298,7 @@
this._currentLibrary, {
TypeSystem typeSystem,
ResourceProvider resourceProvider,
+ DeclaredVariables declaredVariables,
}) : _nullType = typeProvider.nullType,
_futureNullType = typeProvider.futureNullType,
_typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
@@ -305,6 +309,8 @@
Workspace workspace = ContextBuilder.createWorkspace(
resourceProvider, libraryPath, null /* ContextBuilder */);
_workspacePackage = workspace.findPackageFor(libraryPath);
+ _linterContext = LinterContextImpl(null /* allUnits */,
+ null /* currentUnit */, declaredVariables, typeProvider, _typeSystem);
}
@override
@@ -359,9 +365,7 @@
@override
void visitAssignmentExpression(AssignmentExpression node) {
TokenType operatorType = node.operator.type;
- if (operatorType == TokenType.EQ) {
- _checkForInvalidAssignment(node.leftHandSide, node.rightHandSide);
- } else {
+ if (operatorType != TokenType.EQ) {
_checkForDeprecatedMemberUse(node.staticElement, node);
}
super.visitAssignmentExpression(node);
@@ -480,6 +484,7 @@
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
_checkForDeprecatedMemberUse(node.staticElement, node);
+ _checkForLiteralConstructorUse(node);
super.visitInstanceCreationExpression(node);
}
@@ -592,12 +597,6 @@
}
}
- @override
- void visitVariableDeclaration(VariableDeclaration node) {
- _checkForInvalidAssignment(node.name, node.initializer);
- super.visitVariableDeclaration(node);
- }
-
/// Check for the passed is expression for the unnecessary type check hint
/// codes as well as null checks expressed using an is expression.
///
@@ -717,11 +716,16 @@
} else if (displayName == FunctionElement.CALL_METHOD_NAME &&
node is MethodInvocation &&
node.staticInvokeType is InterfaceType) {
- displayName =
- "${resolutionMap.staticInvokeTypeForInvocationExpression(node).displayName}.${element.displayName}";
+ DartType staticInvokeType =
+ resolutionMap.staticInvokeTypeForInvocationExpression(node);
+ displayName = "${staticInvokeType.displayName}.${element.displayName}";
}
- _errorReporter.reportErrorForNode(
- HintCode.DEPRECATED_MEMBER_USE, node, [displayName]);
+ LibraryElement library =
+ element is LibraryElement ? element : element.library;
+ HintCode hintCode = _workspacePackage.contains(library.source.fullName)
+ ? HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
+ : HintCode.DEPRECATED_MEMBER_USE;
+ _errorReporter.reportErrorForNode(hintCode, node, [displayName]);
}
}
@@ -874,41 +878,6 @@
}
}
- /// This verifies that the passed left hand side and right hand side represent
- /// a valid assignment.
- ///
- /// This method corresponds to ErrorVerifier.checkForInvalidAssignment.
- ///
- /// @param lhs the left hand side expression
- /// @param rhs the right hand side expression
- /// @return `true` if and only if an error code is generated on the passed
- /// node
- /// See [HintCode.INVALID_ASSIGNMENT].
- bool _checkForInvalidAssignment(Expression lhs, Expression rhs) {
- if (lhs == null || rhs == null) {
- return false;
- }
- VariableElement leftVariableElement = ErrorVerifier.getVariableElement(lhs);
- DartType leftType = (leftVariableElement == null)
- ? ErrorVerifier.getStaticType(lhs)
- : leftVariableElement.type;
- DartType staticRightType = ErrorVerifier.getStaticType(rhs);
- if (!_typeSystem.isAssignableTo(staticRightType, leftType)) {
- // The warning was generated on this rhs
- return false;
- }
- // Test for, and then generate the hint
- DartType bestRightType = rhs.staticType;
- if (leftType != null && bestRightType != null) {
- if (!_typeSystem.isAssignableTo(bestRightType, leftType)) {
- _errorReporter.reportTypeErrorForNode(
- HintCode.INVALID_ASSIGNMENT, rhs, [bestRightType, leftType]);
- return true;
- }
- }
- return false;
- }
-
void _checkForInvalidFactory(MethodDeclaration decl) {
// Check declaration.
// Note that null return types are expected to be flagged by other analyses.
@@ -979,6 +948,32 @@
}
}
+ /// Check that the instance creation node is const if the constructor is
+ /// marked with [literal].
+ _checkForLiteralConstructorUse(InstanceCreationExpression node) {
+ ConstructorName constructorName = node.constructorName;
+ ConstructorElement constructor = constructorName.staticElement;
+ if (constructor == null) {
+ return;
+ }
+ if (!node.isConst &&
+ constructor.hasLiteral &&
+ _linterContext.canBeConst(node)) {
+ // Echoing jwren's TODO from _checkForDeprecatedMemberUse:
+ // TODO(jwren) We should modify ConstructorElement.getDisplayName(), or
+ // have the logic centralized elsewhere, instead of doing this logic
+ // here.
+ String fullConstructorName = constructorName.type.name.name;
+ if (constructorName.name != null) {
+ fullConstructorName = '$fullConstructorName.${constructorName.name}';
+ }
+ HintCode hint = node.keyword?.keyword == Keyword.NEW
+ ? HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW
+ : HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR;
+ _errorReporter.reportErrorForNode(hint, node, [fullConstructorName]);
+ }
+ }
+
/// Check that the imported library does not define a loadLibrary function.
/// The import has already been determined to be deferred when this is called.
///
@@ -1254,17 +1249,17 @@
// }
// return false;
// }
-
- /// Return `true` if the given [type] represents `Future<void>`.
- bool _isFutureVoid(DartType type) {
- if (type.isDartAsyncFuture) {
- List<DartType> typeArgs = (type as InterfaceType).typeArguments;
- if (typeArgs.length == 1 && typeArgs[0].isVoid) {
- return true;
- }
- }
- return false;
- }
+//
+// /// Return `true` if the given [type] represents `Future<void>`.
+// bool _isFutureVoid(DartType type) {
+// if (type.isDartAsyncFuture) {
+// List<DartType> typeArgs = (type as InterfaceType).typeArguments;
+// if (typeArgs.length == 1 && typeArgs[0].isVoid) {
+// return true;
+// }
+// }
+// return false;
+// }
static bool _hasDeprecatedAnnotation(List<Annotation> annotations) {
for (var i = 0; i < annotations.length; i++) {
@@ -5220,8 +5215,8 @@
if (mapT != null &&
node.typeArguments == null &&
node.entries.isEmpty &&
- typeSystem.isAssignableTo(typeProvider.setNullType, mapT) &&
- !typeSystem.isAssignableTo(typeProvider.mapNullNullType, mapT)) {
+ typeSystem.isAssignableTo(typeProvider.iterableObjectType, mapT) &&
+ !typeSystem.isAssignableTo(typeProvider.mapObjectObjectType, mapT)) {
// The node is really an empty set literal with no type arguments, so
// don't try to visit the replaced map literal.
return;
@@ -6872,6 +6867,8 @@
final TypeSystem typeSystem;
final DartType dynamicType;
final DartType undefinedType;
+ final bool isNonNullableMigrated;
+ final AnalysisOptionsImpl analysisOptions;
final LibraryElement definingLibrary;
final Source source;
final AnalysisErrorListener errorListener;
@@ -6885,11 +6882,17 @@
Scope nameScope;
- TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
- this.definingLibrary, this.source, this.errorListener,
+ TypeNameResolver(
+ this.typeSystem,
+ TypeProvider typeProvider,
+ this.isNonNullableMigrated,
+ this.definingLibrary,
+ this.source,
+ this.errorListener,
{this.shouldUseWithClauseInferredTypes: true})
: dynamicType = typeProvider.dynamicType,
- undefinedType = typeProvider.undefinedType;
+ undefinedType = typeProvider.undefinedType,
+ analysisOptions = definingLibrary.context.analysisOptions;
/// Report an error with the given error code and arguments.
///
@@ -7112,22 +7115,25 @@
node.type = undefinedType;
return;
}
- DartType type = null;
+
if (element is ClassElement) {
- _setElement(typeName, element);
- type = element.type;
- } else if (element == DynamicElementImpl.instance) {
+ _resolveClassElement(node, typeName, argumentList, element);
+ return;
+ }
+
+ TypeImpl type = null;
+ if (element == DynamicElementImpl.instance) {
_setElement(typeName, element);
type = DynamicTypeImpl.instance;
} else if (element is FunctionTypeAliasElement) {
_setElement(typeName, element);
- type = element.type;
+ type = element.type as TypeImpl;
} else if (element is TypeParameterElement) {
_setElement(typeName, element);
- type = element.type;
+ type = element.type as TypeImpl;
} else if (element is MultiplyDefinedElement) {
List<Element> elements = element.conflictingElements;
- type = _getTypeWhenMultiplyDefined(elements);
+ type = _getTypeWhenMultiplyDefined(elements) as TypeImpl;
} else {
// The name does not represent a type.
RedirectingConstructorKind redirectingConstructorKind;
@@ -7207,37 +7213,15 @@
element, typeArguments) ??
dynamicType;
} else {
- DartType redirectedType =
- _inferTypeArgumentsForRedirectedConstructor(node, type);
- if (redirectedType != null) {
- type = redirectedType;
- } else {
- type = typeSystem.instantiateToBounds(type);
- }
+ type = typeSystem.instantiateToBounds(type);
}
}
- DartType refinedType;
- if (shouldUseWithClauseInferredTypes) {
- var parent = node.parent;
- if (parent is WithClause &&
- type is InterfaceType &&
- type.element.typeParameters.isNotEmpty) {
- // Get the (possibly inferred) mixin type from the element model.
- var grandParent = parent.parent;
- if (grandParent is ClassDeclaration) {
- refinedType =
- _getInferredMixinType(grandParent.declaredElement, type.element);
- } else if (grandParent is ClassTypeAlias) {
- refinedType =
- _getInferredMixinType(grandParent.declaredElement, type.element);
- } else {
- assert(false, 'Unexpected context for "with" clause');
- }
- }
- }
- refinedType ??= type;
- typeName.staticType = refinedType;
- node.type = refinedType;
+
+ var nullability = _getNullability(node.question != null);
+ type = type.withNullability(nullability);
+
+ typeName.staticType = type;
+ node.type = type;
}
DartType _getInferredMixinType(
@@ -7266,6 +7250,22 @@
return StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
}
+ Nullability _getNullability(bool hasQuestion) {
+ Nullability nullability;
+ if (analysisOptions.experimentStatus.non_nullable) {
+ if (hasQuestion) {
+ nullability = Nullability.nullable;
+ } else if (isNonNullableMigrated) {
+ nullability = Nullability.nonNullable;
+ } else {
+ nullability = Nullability.indeterminate;
+ }
+ } else {
+ nullability = Nullability.indeterminate;
+ }
+ return nullability;
+ }
+
/// Checks if the given [typeName] is the target in a redirected constructor.
RedirectingConstructorKind _getRedirectingConstructorKind(TypeName typeName) {
AstNode parent = typeName.parent;
@@ -7339,7 +7339,7 @@
/// If the [node] is the type name in a redirected factory constructor,
/// infer type arguments using the enclosing class declaration. Return `null`
/// otherwise.
- DartType _inferTypeArgumentsForRedirectedConstructor(
+ InterfaceTypeImpl _inferTypeArgumentsForRedirectedConstructor(
TypeName node, DartType type) {
AstNode constructorName = node.parent;
AstNode enclosingConstructor = constructorName?.parent;
@@ -7405,6 +7405,77 @@
bool _isTypeNameInTypeArgumentList(TypeName typeName) =>
typeName.parent is TypeArgumentList;
+ void _resolveClassElement(TypeName node, Identifier typeName,
+ TypeArgumentList argumentList, ClassElement element) {
+ _setElement(typeName, element);
+
+ var typeParameters = element.typeParameters;
+ var parameterCount = typeParameters.length;
+
+ List<DartType> typeArguments;
+ if (argumentList != null) {
+ var argumentNodes = argumentList.arguments;
+ var argumentCount = argumentNodes.length;
+
+ typeArguments = new List<DartType>(parameterCount);
+ if (argumentCount == parameterCount) {
+ for (int i = 0; i < parameterCount; i++) {
+ typeArguments[i] = _getType(argumentNodes[i]);
+ }
+ } else {
+ reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node,
+ [typeName.name, parameterCount, argumentCount]);
+ for (int i = 0; i < parameterCount; i++) {
+ typeArguments[i] = dynamicType;
+ }
+ }
+ } else if (parameterCount == 0) {
+ typeArguments = const <DartType>[];
+ } else {
+ var redirectedType =
+ _inferTypeArgumentsForRedirectedConstructor(node, element.type);
+ if (redirectedType != null) {
+ typeArguments = redirectedType.typeArguments;
+ } else {
+ var typeFormals = typeParameters;
+ typeArguments = typeSystem.instantiateTypeFormalsToBounds(typeFormals);
+ }
+ }
+
+ var parent = node.parent;
+
+ Nullability nullability;
+ if (parent is ClassTypeAlias ||
+ parent is ExtendsClause ||
+ parent is ImplementsClause ||
+ parent is OnClause ||
+ parent is WithClause) {
+ nullability = Nullability.nonNullable;
+ } else {
+ nullability = _getNullability(node.question != null);
+ }
+
+ var type = InterfaceTypeImpl.explicit(element, typeArguments,
+ nullability: nullability);
+
+ if (shouldUseWithClauseInferredTypes) {
+ if (parent is WithClause && parameterCount != 0) {
+ // Get the (possibly inferred) mixin type from the element model.
+ var grandParent = parent.parent;
+ if (grandParent is ClassDeclaration) {
+ type = _getInferredMixinType(grandParent.declaredElement, element);
+ } else if (grandParent is ClassTypeAlias) {
+ type = _getInferredMixinType(grandParent.declaredElement, element);
+ } else {
+ assert(false, 'Unexpected context for "with" clause');
+ }
+ }
+ }
+
+ typeName.staticType = type;
+ node.type = type;
+ }
+
/// Records the new Element for a TypeName's Identifier.
///
/// A null may be passed in to indicate that the element can't be resolved.
@@ -7638,10 +7709,16 @@
TypeNameResolver typeNameResolver = null;
TypeParameterBoundsResolver(
- this.typeSystem, this.library, this.source, this.errorListener)
+ this.typeSystem, this.library, this.source, this.errorListener,
+ {bool isNonNullableMigrated = false})
: libraryScope = new LibraryScope(library),
- typeNameResolver = new TypeNameResolver(typeSystem,
- typeSystem.typeProvider, library, source, errorListener);
+ typeNameResolver = new TypeNameResolver(
+ typeSystem,
+ typeSystem.typeProvider,
+ isNonNullableMigrated,
+ library,
+ source,
+ errorListener);
/// Resolve bounds of type parameters of classes, class and function type
/// aliases.
@@ -7875,14 +7952,17 @@
/// Return the type representing the type 'Iterable<dynamic>'.
InterfaceType get iterableDynamicType;
+ /// Return the type representing the type 'Iterable<Object>'.
+ InterfaceType get iterableObjectType;
+
/// Return the type representing the built-in type 'Iterable'.
InterfaceType get iterableType;
/// Return the type representing the built-in type 'List'.
InterfaceType get listType;
- /// Return the type representing 'Map<Null, Null>'.
- InterfaceType get mapNullNullType;
+ /// Return the type representing 'Map<Object, Object>'.
+ InterfaceType get mapObjectObjectType;
/// Return the type representing the built-in type 'Map'.
InterfaceType get mapType;
@@ -7903,9 +7983,6 @@
/// Return the type representing the built-in type 'Object'.
InterfaceType get objectType;
- /// Return the type representing 'Set<Null>'.
- InterfaceType get setNullType;
-
/// Return the type representing the built-in type 'Set'.
InterfaceType get setType;
@@ -8017,6 +8094,9 @@
/// The type representing 'Iterable<dynamic>'.
InterfaceType _iterableDynamicType;
+ /// The type representing 'Iterable<Object>'.
+ InterfaceType _iterableObjectType;
+
/// The type representing the built-in type 'Iterable'.
InterfaceType _iterableType;
@@ -8026,8 +8106,8 @@
/// The type representing the built-in type 'Map'.
InterfaceType _mapType;
- /// The type representing the built-in type 'Map<Null, Null>'.
- InterfaceType _mapNullNullType;
+ /// The type representing the built-in type 'Map<Object, Object>'.
+ InterfaceType _mapObjectObjectType;
/// An shared object representing the value 'null'.
DartObjectImpl _nullObject;
@@ -8035,9 +8115,6 @@
/// The type representing the type 'Set'.
InterfaceType _setType;
- /// The type representing the type 'Set<Null>'.
- InterfaceType _setNullType;
-
/// The type representing the type 'Null'.
InterfaceType _nullType;
@@ -8125,13 +8202,16 @@
InterfaceType get iterableDynamicType => _iterableDynamicType;
@override
+ InterfaceType get iterableObjectType => _iterableObjectType;
+
+ @override
InterfaceType get iterableType => _iterableType;
@override
InterfaceType get listType => _listType;
@override
- InterfaceType get mapNullNullType => _mapNullNullType;
+ InterfaceType get mapObjectObjectType => _mapObjectObjectType;
@override
InterfaceType get mapType => _mapType;
@@ -8154,9 +8234,6 @@
InterfaceType get objectType => _objectType;
@override
- InterfaceType get setNullType => _setNullType;
-
- @override
InterfaceType get setType => _setType;
@override
@@ -8224,8 +8301,9 @@
_futureDynamicType = _futureType.instantiate(<DartType>[_dynamicType]);
_futureNullType = _futureType.instantiate(<DartType>[_nullType]);
_iterableDynamicType = _iterableType.instantiate(<DartType>[_dynamicType]);
- _mapNullNullType = _mapType.instantiate(<DartType>[_nullType, _nullType]);
- _setNullType = _setType.instantiate(<DartType>[_nullType]);
+ _iterableObjectType = _iterableType.instantiate(<DartType>[_objectType]);
+ _mapObjectObjectType =
+ _mapType.instantiate(<DartType>[_objectType, _objectType]);
_streamDynamicType = _streamType.instantiate(<DartType>[_dynamicType]);
// FutureOr<T> is still fairly new, so if we're analyzing an SDK that
// doesn't have it yet, create an element for it.
@@ -8284,6 +8362,9 @@
/// Type type system in use for this resolver pass.
TypeSystem _typeSystem;
+ /// Whether the library migrated to non-nullable.
+ final bool isNonNullableMigrated;
+
/// The helper to resolve types.
TypeNameResolver _typeNameResolver;
@@ -8319,6 +8400,7 @@
TypeResolverVisitor(LibraryElement definingLibrary, Source source,
TypeProvider typeProvider, AnalysisErrorListener errorListener,
{Scope nameScope,
+ this.isNonNullableMigrated: false,
this.mode: TypeResolverMode.everything,
bool shouldUseWithClauseInferredTypes: true,
this.shouldSetElementSupertypes: false})
@@ -8327,8 +8409,8 @@
_dynamicType = typeProvider.dynamicType;
_undefinedType = typeProvider.undefinedType;
_typeSystem = TypeSystem.create(definingLibrary.context);
- _typeNameResolver = new TypeNameResolver(
- _typeSystem, typeProvider, definingLibrary, source, errorListener,
+ _typeNameResolver = new TypeNameResolver(_typeSystem, typeProvider,
+ isNonNullableMigrated, definingLibrary, source, errorListener,
shouldUseWithClauseInferredTypes: shouldUseWithClauseInferredTypes);
}
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 89dbcb5..88f8f3b 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -10,12 +10,15 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/task/strong/checker.dart'
@@ -52,6 +55,11 @@
DartType _dynamicType;
/**
+ * The status of the active experiments of the current context.
+ */
+ ExperimentStatus _experimentStatus;
+
+ /**
* The type representing the class containing the nodes being analyzed,
* or `null` if the nodes are not within a class.
*/
@@ -72,6 +80,9 @@
_typeSystem = _resolver.typeSystem;
_dynamicType = _typeProvider.dynamicType;
_promoteManager = _resolver.promoteManager;
+ _experimentStatus = (_resolver.definingLibrary.context.analysisOptions
+ as AnalysisOptionsImpl)
+ .experimentStatus;
}
/**
@@ -173,21 +184,33 @@
ParameterizedType inferMapType(MapLiteral node, {bool downwards: false}) {
DartType contextType = InferenceContext.getContext(node);
- if (contextType != null &&
- node.typeArguments == null &&
- node.entries.isEmpty &&
- _typeSystem.isAssignableTo(_typeProvider.setNullType, contextType) &&
- !_typeSystem.isAssignableTo(
- _typeProvider.mapNullNullType, contextType)) {
- // The node is really an empty set literal with no type arguments. Rewrite
- // the AST and infer the type of the set as appropriate.
- SetLiteral setLiteral = new AstFactoryImpl().setLiteral(
- node.constKeyword, null, node.leftBracket, null, node.rightBracket);
- InferenceContext.setType(setLiteral, contextType);
- NodeReplacer.replace(node, setLiteral);
- DartType type = inferSetType(setLiteral, downwards: downwards);
- setLiteral.staticType = type;
- return type;
+ if (contextType != null && _experimentStatus.set_literals) {
+ DartType unwrap(DartType type) {
+ if (type is InterfaceType &&
+ type.isDartAsyncFutureOr &&
+ type.typeArguments.length == 1) {
+ return unwrap(type.typeArguments[0]);
+ }
+ return type;
+ }
+
+ DartType unwrappedContextType = unwrap(contextType);
+ if (node.typeArguments == null &&
+ node.entries.isEmpty &&
+ _typeSystem.isAssignableTo(
+ _typeProvider.iterableObjectType, unwrappedContextType) &&
+ !_typeSystem.isAssignableTo(
+ _typeProvider.mapObjectObjectType, unwrappedContextType)) {
+ // The node is really an empty set literal with no type arguments.
+ // Rewrite the AST and infer the type of the set as appropriate.
+ SetLiteral setLiteral = new AstFactoryImpl().setLiteral(
+ node.constKeyword, null, node.leftBracket, null, node.rightBracket);
+ InferenceContext.setType(setLiteral, contextType);
+ NodeReplacer.replace(node, setLiteral);
+ DartType type = inferSetType(setLiteral, downwards: downwards);
+ setLiteral.staticType = type;
+ return type;
+ }
}
List<DartType> elementTypes;
List<ParameterElement> parameters;
@@ -830,13 +853,14 @@
void visitPostfixExpression(PostfixExpression node) {
Expression operand = node.operand;
DartType staticType = _getStaticType(operand, read: true);
- TokenType operator = node.operator.type;
- if (operator == TokenType.MINUS_MINUS || operator == TokenType.PLUS_PLUS) {
- DartType intType = _typeProvider.intType;
- if (identical(staticType, intType)) {
- staticType = intType;
- }
+
+ // No need to check for `intVar++`, the result is `int`.
+ if (!staticType.isDartCoreInt) {
+ var operatorElement = node.staticElement;
+ var operatorReturnType = _computeStaticReturnType(operatorElement);
+ _checkForInvalidAssignmentIncDec(node, operand, operatorReturnType);
}
+
_recordStaticType(node, staticType);
}
@@ -894,9 +918,12 @@
DartType staticType = _computeStaticReturnType(staticMethodElement);
if (operator == TokenType.MINUS_MINUS ||
operator == TokenType.PLUS_PLUS) {
- DartType intType = _typeProvider.intType;
- if (identical(_getStaticType(node.operand, read: true), intType)) {
- staticType = intType;
+ Expression operand = node.operand;
+ var operandReadType = _getStaticType(operand, read: true);
+ if (operandReadType.isDartCoreInt) {
+ staticType = _typeProvider.intType;
+ } else {
+ _checkForInvalidAssignmentIncDec(node, operand, staticType);
}
}
_recordStaticType(node, staticType);
@@ -1189,6 +1216,20 @@
_recordStaticType(node, staticType);
}
+ /// Check that the result [type] of a prefix or postfix `++` or `--`
+ /// expression is assignable to the write type of the [operand].
+ void _checkForInvalidAssignmentIncDec(
+ AstNode node, Expression operand, DartType type) {
+ var operandWriteType = _getStaticType(operand);
+ if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
+ _resolver.errorReporter.reportTypeErrorForNode(
+ StaticTypeWarningCode.INVALID_ASSIGNMENT,
+ node,
+ [type, operandWriteType],
+ );
+ }
+ }
+
/**
* Record that the static type of the given node is the type of the second argument to the method
* represented by the given element.
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 1f4cc10..30b176b 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -89,6 +89,11 @@
InterfaceType _iterableDynamicType;
/**
+ * The type representing 'Iterable<Object>'
+ */
+ InterfaceType _iterableObjectType;
+
+ /**
* The type representing the built-in type 'Iterable'.
*/
InterfaceType _iterableType;
@@ -109,9 +114,9 @@
InterfaceType _mapType;
/**
- * The type representing the built-in type 'Map'.
+ * The type representing the built-in type 'Map<Object, Object>'.
*/
- InterfaceType _mapNullNullType;
+ InterfaceType _mapObjectObjectType;
/**
* An shared object representing the value 'null'.
@@ -139,11 +144,6 @@
InterfaceType _setType;
/**
- * The type representing the built-in type 'Set'.
- */
- InterfaceType _setNullType;
-
- /**
* The type representing the built-in type 'StackTrace'.
*/
InterfaceType _stackTraceType;
@@ -334,6 +334,14 @@
}
@override
+ InterfaceType get iterableObjectType {
+ if (_iterableObjectType == null) {
+ _iterableObjectType = iterableType.instantiate(<DartType>[objectType]);
+ }
+ return _iterableObjectType;
+ }
+
+ @override
InterfaceType get iterableType {
if (_iterableType == null) {
ClassElementImpl iterableElement =
@@ -399,11 +407,12 @@
}
@override
- InterfaceType get mapNullNullType {
- if (_mapNullNullType == null) {
- _mapNullNullType = mapType.instantiate(<DartType>[nullType, nullType]);
+ InterfaceType get mapObjectObjectType {
+ if (_mapObjectObjectType == null) {
+ _mapObjectObjectType =
+ mapType.instantiate(<DartType>[objectType, objectType]);
}
- return _mapNullNullType;
+ return _mapObjectObjectType;
}
@override
@@ -494,14 +503,6 @@
}
@override
- InterfaceType get setNullType {
- if (_setNullType == null) {
- _setNullType = setType.instantiate(<DartType>[nullType]);
- }
- return _setNullType;
- }
-
- @override
InterfaceType get setType {
if (_setType == null) {
ClassElementImpl setElement = ElementFactory.classElement2("Set", ["E"]);
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 2a2bebe..6a4ffba 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -885,7 +885,7 @@
DartType _substituteForUnknownType(DartType type, {bool lowerBound: false}) {
if (identical(type, UnknownInferredType.instance)) {
if (lowerBound) {
- // TODO(jmesserly): this should be the bottom type, once i can be
+ // TODO(jmesserly): this should be the bottom type, once it can be
// reified.
return typeProvider.nullType;
}
@@ -896,7 +896,8 @@
var newTypeArgs = _transformList(type.typeArguments,
(t) => _substituteForUnknownType(t, lowerBound: lowerBound));
if (identical(type.typeArguments, newTypeArgs)) return type;
- return new InterfaceTypeImpl(type.element, type.prunedTypedefs)
+ return new InterfaceTypeImpl(
+ type.element, type.prunedTypedefs, type.nullability)
..typeArguments = newTypeArgs;
}
if (type is FunctionType) {
@@ -922,7 +923,8 @@
}
return new FunctionTypeImpl.synthetic(
- newReturnType, type.typeFormals, newParameters);
+ newReturnType, type.typeFormals, newParameters,
+ nullability: (type as TypeImpl).nullability);
}
return type;
}
@@ -2171,10 +2173,14 @@
bool get isDynamic => true;
@override
+ Nullability get nullability => Nullability.indeterminate;
+
+ @override
bool operator ==(Object object) => identical(object, this);
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> types) {
+ void appendTo(StringBuffer buffer, Set<TypeImpl> types,
+ {bool withNullability = false}) {
buffer.write('?');
}
@@ -2228,6 +2234,9 @@
return this;
}
+ @override
+ TypeImpl withNullability(Nullability nullability) => this;
+
/// Given a [type] T, return true if it does not have an unknown type `?`.
static bool isKnown(DartType type) => !isUnknown(type);
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index b9b065e..f0a1a4a 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -62,6 +62,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/builder.dart';
@@ -434,6 +435,9 @@
bool get strongModeHints => false;
@override
+ ExperimentStatus get experimentStatus => new ExperimentStatus();
+
+ @override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
@@ -1008,15 +1012,15 @@
List<InterfaceType> get interfaces => const [];
@override
+ bool get isAbstract => false;
+
+ @override
bool get isEnum => true;
@override
bool get isMixin => false;
@override
- bool get isAbstract => false;
-
- @override
bool get isObject => false;
@override
@@ -5318,15 +5322,15 @@
InterfaceType _futureType;
InterfaceType _intType;
InterfaceType _iterableDynamicType;
+ InterfaceType _iterableObjectType;
InterfaceType _iterableType;
InterfaceType _listType;
InterfaceType _mapType;
- InterfaceType _mapNullNullType;
+ InterfaceType _mapObjectObjectType;
InterfaceType _nullType;
InterfaceType _numType;
InterfaceType _objectType;
InterfaceType _setType;
- InterfaceType _setNullType;
InterfaceType _stackTraceType;
InterfaceType _streamDynamicType;
InterfaceType _streamType;
@@ -5387,6 +5391,10 @@
iterableType.instantiate(<DartType>[dynamicType]);
@override
+ InterfaceType get iterableObjectType =>
+ _iterableObjectType ??= iterableType.instantiate(<DartType>[objectType]);
+
+ @override
InterfaceType get iterableType =>
_iterableType ??= _buildInterfaceType(_linker.coreLibrary, 'Iterable');
@@ -5395,8 +5403,8 @@
_listType ??= _buildInterfaceType(_linker.coreLibrary, 'List');
@override
- InterfaceType get mapNullNullType =>
- _mapNullNullType ??= mapType.instantiate(<DartType>[nullType, nullType]);
+ InterfaceType get mapObjectObjectType => _mapObjectObjectType ??=
+ mapType.instantiate(<DartType>[objectType, objectType]);
@override
InterfaceType get mapType =>
@@ -5421,10 +5429,6 @@
_objectType ??= _buildInterfaceType(_linker.coreLibrary, 'Object');
@override
- InterfaceType get setNullType =>
- _setNullType ??= setType.instantiate(<DartType>[nullType]);
-
- @override
InterfaceType get setType =>
_setType ??= _buildInterfaceType(_linker.coreLibrary, 'Set');
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index ae35bf7..3c6b194 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1458,6 +1458,19 @@
@override
_ReferenceInfo getReferenceInfo(int index) {
+ // We don't know how to reproduce this.
+ // https://github.com/dart-lang/sdk/issues/35551
+ // https://github.com/dart-lang/sdk/issues/34534
+ // So, adding logging to gather more information.
+ if (index >= referenceInfos.length) {
+ var buffer = StringBuffer();
+ buffer.writeln('librarySource: ${unit.librarySource}');
+ buffer.writeln('unitSource: ${unit.source}');
+ buffer.writeln('unlinkedUnit: ${unlinkedUnit.toJson()}');
+ buffer.writeln('linkedUnit: ${linkedUnit.toJson()}');
+ throw StateError(buffer.toString());
+ }
+
_ReferenceInfo result = referenceInfos[index];
if (result == null) {
LinkedReference linkedReference = linkedUnit.references[index];
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index b60e627..b3389a0 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -128,16 +128,16 @@
InterfaceType _futureType;
InterfaceType _intType;
InterfaceType _iterableDynamicType;
+ InterfaceType _iterableObjectType;
InterfaceType _iterableType;
InterfaceType _listType;
InterfaceType _mapType;
- InterfaceType _mapNullNullType;
+ InterfaceType _mapObjectObjectType;
DartObjectImpl _nullObject;
InterfaceType _nullType;
InterfaceType _numType;
InterfaceType _objectType;
InterfaceType _setType;
- InterfaceType _setNullType;
InterfaceType _stackTraceType;
InterfaceType _streamDynamicType;
InterfaceType _streamType;
@@ -236,6 +236,13 @@
}
@override
+ InterfaceType get iterableObjectType {
+ assert(_coreLibrary != null);
+ _iterableObjectType ??= iterableType.instantiate(<DartType>[objectType]);
+ return _iterableObjectType;
+ }
+
+ @override
InterfaceType get iterableType {
assert(_coreLibrary != null);
_iterableType ??= _getType(_coreLibrary, "Iterable");
@@ -250,10 +257,10 @@
}
@override
- InterfaceType get mapNullNullType {
+ InterfaceType get mapObjectObjectType {
assert(_coreLibrary != null);
- return _mapNullNullType ??=
- mapType.instantiate(<DartType>[nullType, nullType]);
+ return _mapObjectObjectType ??=
+ mapType.instantiate(<DartType>[objectType, objectType]);
}
@override
@@ -293,12 +300,6 @@
}
@override
- InterfaceType get setNullType {
- assert(_coreLibrary != null);
- return _setNullType ??= setType.instantiate(<DartType>[nullType]);
- }
-
- @override
InterfaceType get setType {
assert(_coreLibrary != null);
return _setType ??= _getType(_coreLibrary, "Set");
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index b48d3c49..b68d13e 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -106,6 +106,8 @@
abstract class HashMap<K, V> implements Map<K, V> {}
abstract class LinkedHashMap<K, V> implements Map<K, V> {}
+abstract class HashSet<E> implements Set<E> {}
+abstract class LinkedHashSet<E> implements Set<E> {}
''');
const _MockSdkLibrary _LIB_CONVERT = const _MockSdkLibrary(
@@ -152,6 +154,12 @@
const Deprecated(this.expires);
}
+class pragma {
+ final String name;
+ final Object options;
+ const pragma(this.name, [this.options]);
+}
+
abstract class double extends num {
static const double NAN = 0.0 / 0.0;
static const double INFINITY = 1.0 / 0.0;
diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart
index bfeb81b9..89b270f 100644
--- a/pkg/analyzer/lib/src/workspace/basic.dart
+++ b/pkg/analyzer/lib/src/workspace/basic.dart
@@ -8,29 +8,16 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/workspace/simple.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:package_config/packages.dart';
/**
* Information about a default Dart workspace.
+ *
+ * A BasicWorkspace should only be used when no other workspace type is valid.
*/
-class BasicWorkspace extends Workspace {
- /**
- * The [ResourceProvider] by which paths are converted into [Resource]s.
- */
- final ResourceProvider provider;
-
- /**
- * The absolute workspace root path.
- */
- final String root;
-
- final ContextBuilder _builder;
-
- Map<String, List<Folder>> _packageMap;
-
- Packages _packages;
-
+class BasicWorkspace extends SimpleWorkspace {
/**
* The singular package in this workspace.
*
@@ -38,37 +25,9 @@
*/
BasicWorkspacePackage _theOnlyPackage;
- BasicWorkspace._(this.provider, this.root, this._builder);
-
- @override
- Map<String, List<Folder>> get packageMap {
- _packageMap ??= _builder.convertPackagesToMap(packages);
- return _packageMap;
- }
-
- Packages get packages {
- _packages ??= _builder.createPackageMap(root);
- return _packages;
- }
-
- @override
- UriResolver get packageUriResolver =>
- new PackageMapUriResolver(provider, packageMap);
-
- @override
- SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData) {
- if (summaryData != null) {
- throw new UnsupportedError(
- 'Summary files are not supported in a basic workspace.');
- }
- List<UriResolver> resolvers = <UriResolver>[];
- if (sdk != null) {
- resolvers.add(new DartUriResolver(sdk));
- }
- resolvers.add(packageUriResolver);
- resolvers.add(new ResourceUriResolver(provider));
- return new SourceFactory(resolvers, packages, provider);
- }
+ BasicWorkspace._(
+ ResourceProvider provider, String root, ContextBuilder builder)
+ : super(provider, root, builder);
@override
WorkspacePackage findPackageFor(String filePath) {
@@ -83,6 +42,10 @@
/**
* Find the basic workspace that contains the given [path].
+ *
+ * As a [BasicWorkspace] is not defined by any marker files or build
+ * artifacts, this simply creates a BasicWorkspace with [path] as the [root]
+ * (or [path]'s parent if [path] points to a file).
*/
static BasicWorkspace find(
ResourceProvider provider, String path, ContextBuilder builder) {
@@ -95,11 +58,11 @@
}
/**
- * Information about a package defined in a _BasicWorkspace.
+ * Information about a package defined in a [BasicWorkspace].
*
* Separate from [Packages] or package maps, this class is designed to simply
* understand whether arbitrary file paths represent libraries declared within
- * a given package in a _BasicWorkspace.
+ * a given package in a [BasicWorkspace].
*/
class BasicWorkspacePackage extends WorkspacePackage {
final String root;
@@ -110,9 +73,9 @@
@override
bool contains(String path) {
- // There is a 1-1 relationship between _BasicWorkspaces and
- // _BasicWorkspacePackages. If a file is in a package's workspace,
- // then it is in the package as well.
+ // There is a 1-1 relationship between [BasicWorkspace]s and
+ // [BasicWorkspacePackage]s. If a file is in a package's workspace, then it
+ // is in the package as well.
return workspace.provider.pathContext.isWithin(root, path);
}
}
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index d4a83b9c..5e90c71 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -287,11 +287,12 @@
/**
* Find the Bazel workspace that contains the given [filePath].
*
- * Return `null` if a workspace markers, such as the `WORKSPACE` file, or
+ * Return `null` if a workspace marker, such as the `WORKSPACE` file, or
* the sibling `READONLY` folder cannot be found.
*
* Return `null` if the workspace does not have `bazel-genfiles` or
- * `blaze-genfiles` folders, so we don't know where to search generated files.
+ * `blaze-genfiles` folders, since we don't know where to search generated
+ * files.
*
* Return `null` if there is a folder 'foo' with the sibling `READONLY`
* folder, but there is corresponding folder 'foo' in `READONLY`, i.e. the
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index 77ef5e8..191c421 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -198,6 +198,10 @@
* file must be found in [filePath]'s output directory.
*/
static GnWorkspace find(ResourceProvider provider, String filePath) {
+ Resource resource = provider.getResource(filePath);
+ if (resource is File) {
+ filePath = resource.parent.path;
+ }
Folder folder = provider.getFolder(filePath);
while (true) {
Folder parent = folder.parent;
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
new file mode 100644
index 0000000..f89937c
--- /dev/null
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2019, 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:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/workspace/simple.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
+import 'package:package_config/packages.dart';
+
+/// Information about a Pub workspace.
+class PubWorkspace extends SimpleWorkspace {
+ /// The name of the file that identifies the root of the workspace.
+ static const String _pubspecName = 'pubspec.yaml';
+
+ /// The singular package in this workspace.
+ ///
+ /// Each Pub workspace is itself one package.
+ PubWorkspacePackage _theOnlyPackage;
+
+ PubWorkspace._(ResourceProvider provider, String root, ContextBuilder builder)
+ : super(provider, root, builder);
+
+ @override
+ WorkspacePackage findPackageFor(String filePath) {
+ final Folder folder = provider.getFolder(filePath);
+ if (provider.pathContext.isWithin(root, folder.path)) {
+ _theOnlyPackage ??= new PubWorkspacePackage(root, this);
+ return _theOnlyPackage;
+ } else {
+ return null;
+ }
+ }
+
+ /// Find the pub workspace that contains the given [path].
+ static PubWorkspace find(
+ ResourceProvider provider, String filePath, ContextBuilder builder) {
+ Resource resource = provider.getResource(filePath);
+ if (resource is File) {
+ filePath = resource.parent.path;
+ }
+ Folder folder = provider.getFolder(filePath);
+ while (true) {
+ Folder parent = folder.parent;
+ if (parent == null) {
+ return null;
+ }
+
+ if (folder.getChildAssumingFile(_pubspecName).exists) {
+ // Found the pubspec.yaml file; this is our root.
+ String root = folder.path;
+ return new PubWorkspace._(provider, root, builder);
+ }
+
+ // Go up a folder.
+ folder = parent;
+ }
+ }
+}
+
+/// Information about a package defined in a [PubWorkspace].
+///
+/// Separate from [Packages] or package maps, this class is designed to simply
+/// understand whether arbitrary file paths represent libraries declared within
+/// a given package in a [PubWorkspace].
+class PubWorkspacePackage extends WorkspacePackage {
+ final String root;
+
+ final PubWorkspace workspace;
+
+ PubWorkspacePackage(this.root, this.workspace);
+
+ @override
+ bool contains(String path) {
+ // There is a 1-1 relationship between [PubWorkspace]s and
+ // [PubWorkspacePackage]s. If a file is in a package's workspace, then it
+ // is in the package as well.
+ return workspace.provider.pathContext.isWithin(root, path);
+ }
+}
diff --git a/pkg/analyzer/lib/src/workspace/simple.dart b/pkg/analyzer/lib/src/workspace/simple.dart
new file mode 100644
index 0000000..c2d0d8e
--- /dev/null
+++ b/pkg/analyzer/lib/src/workspace/simple.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2019, 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:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
+import 'package:package_config/packages.dart';
+
+/// An abstract class for simple workspaces which do not feature any build
+/// artifacts or generated files.
+///
+/// The [packageMap] and [packageUrlResolver] are simple derivations from the
+/// [ContextBuilder] and [ResourceProvider] required for the class.
+abstract class SimpleWorkspace extends Workspace {
+ /// The [ResourceProvider] by which paths are converted into [Resource]s.
+ final ResourceProvider provider;
+
+ /// The absolute workspace root path.
+ final String root;
+
+ final ContextBuilder _builder;
+
+ Map<String, List<Folder>> _packageMap;
+
+ Packages _packages;
+
+ SimpleWorkspace(this.provider, this.root, this._builder);
+
+ @override
+ Map<String, List<Folder>> get packageMap {
+ _packageMap ??= _builder.convertPackagesToMap(packages);
+ return _packageMap;
+ }
+
+ Packages get packages {
+ _packages ??= _builder.createPackageMap(root);
+ return _packages;
+ }
+
+ @override
+ UriResolver get packageUriResolver =>
+ new PackageMapUriResolver(provider, packageMap);
+
+ @override
+ SourceFactory createSourceFactory(DartSdk sdk, SummaryDataStore summaryData) {
+ if (summaryData != null) {
+ throw new UnsupportedError(
+ 'Summary files are not supported in a Pub workspace.');
+ }
+ List<UriResolver> resolvers = <UriResolver>[];
+ if (sdk != null) {
+ resolvers.add(new DartUriResolver(sdk));
+ }
+ resolvers.add(packageUriResolver);
+ resolvers.add(new ResourceUriResolver(provider));
+ return new SourceFactory(resolvers, packages, provider);
+ }
+}
diff --git a/pkg/analyzer/test/dart/ast/visitor_test.dart b/pkg/analyzer/test/dart/ast/visitor_test.dart
index 0a8e8dd..31b3c35a 100644
--- a/pkg/analyzer/test/dart/ast/visitor_test.dart
+++ b/pkg/analyzer/test/dart/ast/visitor_test.dart
@@ -4,11 +4,11 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/test_utilities/ast_type_matchers.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/parser_test.dart' show ParserTestCase;
+import '../../util/ast_type_matchers.dart';
main() {
defineReflectiveSuite(() {
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index 1b05603..0c87fa9 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -31,13 +31,13 @@
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/test_utilities/element_type_matchers.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/source_span.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/element_type_matchers.dart';
import 'parser_test.dart';
import 'resolver_test_case.dart';
import 'test_support.dart';
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 0a7da26..e33ea7d 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -15,6 +15,13 @@
import '../src/util/yaml_test.dart';
import 'resolver_test_case.dart';
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(CrossPackageHintCodeTest);
+ defineReflectiveTests(HintCodeTest);
+ });
+}
+
final metaLibraryStub = r'''
library meta;
@@ -59,20 +66,10 @@
}
''';
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(CrossPackageHintCodeTest);
- defineReflectiveTests(HintCodeTest);
- });
-}
-
@reflectiveTest
class CrossPackageHintCodeTest extends ResolverTestCase {
- /// Write a pubspec file at [root], so that BestPracticesVerifier can see that
- /// [root] is the root of a BasicWorkspace, and a BasicWorkspacePackage.
- void newBasicPackage(String root) {
- newFile('$root/pubspec.yaml');
- }
+ @override
+ bool get enableNewAnalysisDriver => true;
test_subtypeOfSealedClass_extending() async {
super.resetWith(packages: [
@@ -86,7 +83,7 @@
]
]);
- newBasicPackage('/pkg1');
+ _newPubPackageRoot('/pkg1');
Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
import 'package:foo/foo.dart';
class Bar extends Foo {}
@@ -108,7 +105,7 @@
]
]);
- newBasicPackage('/pkg1');
+ _newPubPackageRoot('/pkg1');
Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
import 'package:foo/foo.dart';
class Bar implements Foo {}
@@ -118,94 +115,6 @@
verify([source]);
}
- test_subtypeOfSealedClass_with() async {
- super.resetWith(packages: [
- ['meta', metaLibraryStub],
- [
- 'foo',
- r'''
-import 'package:meta/meta.dart';
-@sealed class Foo {}
-'''
- ]
- ]);
-
- newBasicPackage('/pkg1');
- Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
- import 'package:foo/foo.dart';
- class Bar extends Object with Foo {}
- ''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
- verify([source]);
- }
-
- test_subtypeOfSealedMixin_with() async {
- super.resetWith(packages: [
- ['meta', metaLibraryStub],
- [
- 'foo',
- r'''
-import 'package:meta/meta.dart';
-@sealed mixin Foo {}
-'''
- ]
- ]);
-
- newBasicPackage('/pkg1');
- Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
- import 'package:foo/foo.dart';
- class Bar extends Object with Foo {}
- ''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
- verify([source]);
- }
-
- test_subtypeOfSealedClass_mixinOn() async {
- super.resetWith(packages: [
- ['meta', metaLibraryStub],
- [
- 'foo',
- r'''
-import 'package:meta/meta.dart';
-@sealed class Foo {}
-'''
- ]
- ]);
-
- newBasicPackage('/pkg1');
- Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
- import 'package:foo/foo.dart';
- mixin Bar on Foo {}
- ''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MIXIN_ON_SEALED_CLASS]);
- verify([source]);
- }
-
- test_subtypeOfSealedClass_mixinImplements() async {
- super.resetWith(packages: [
- ['meta', metaLibraryStub],
- [
- 'foo',
- r'''
-import 'package:meta/meta.dart';
-@sealed class Foo {}
-'''
- ]
- ]);
-
- newBasicPackage('/pkg1');
- Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
- import 'package:foo/foo.dart';
- mixin Bar implements Foo {}
- ''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
- verify([source]);
- }
-
test_subtypeOfSealedClass_mixinApplication() async {
super.resetWith(packages: [
['meta', metaLibraryStub],
@@ -218,7 +127,7 @@
]
]);
- newBasicPackage('/pkg1');
+ _newPubPackageRoot('/pkg1');
Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
import 'package:foo/foo.dart';
class Bar1 {}
@@ -229,23 +138,66 @@
verify([source]);
}
- test_subtypeOfSealedMixin_mixinApplication() async {
+ test_subtypeOfSealedClass_mixinImplements() async {
super.resetWith(packages: [
['meta', metaLibraryStub],
[
'foo',
r'''
import 'package:meta/meta.dart';
-@sealed mixin Foo {}
+@sealed class Foo {}
'''
]
]);
- newBasicPackage('/pkg1');
+ _newPubPackageRoot('/pkg1');
Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
import 'package:foo/foo.dart';
- class Bar1 {}
- class Bar2 = Bar1 with Foo;
+ mixin Bar implements Foo {}
+ ''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
+ verify([source]);
+ }
+
+ test_subtypeOfSealedClass_mixinOn() async {
+ super.resetWith(packages: [
+ ['meta', metaLibraryStub],
+ [
+ 'foo',
+ r'''
+import 'package:meta/meta.dart';
+@sealed class Foo {}
+'''
+ ]
+ ]);
+
+ _newPubPackageRoot('/pkg1');
+ Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
+ import 'package:foo/foo.dart';
+ mixin Bar on Foo {}
+ ''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.MIXIN_ON_SEALED_CLASS]);
+ verify([source]);
+ }
+
+ test_subtypeOfSealedClass_with() async {
+ super.resetWith(packages: [
+ ['meta', metaLibraryStub],
+ [
+ 'foo',
+ r'''
+import 'package:meta/meta.dart';
+@sealed class Foo {}
+'''
+ ]
+ ]);
+
+ _newPubPackageRoot('/pkg1');
+ Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
+ import 'package:foo/foo.dart';
+ class Bar extends Object with Foo {}
''');
await computeAnalysisResult(source);
assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
@@ -257,7 +209,7 @@
['meta', metaLibraryStub],
]);
- newBasicPackage('/pkg1');
+ _newPubPackageRoot('/pkg1');
Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
import 'package:meta/meta.dart';
@sealed class Foo {}
@@ -273,12 +225,64 @@
verify([source]);
}
+ test_subtypeOfSealedClass_withinPackageLibDirectory_OK() async {
+ super.resetWith(packages: [
+ ['meta', metaLibraryStub],
+ ]);
+
+ _newPubPackageRoot('/pkg1');
+ Source source1 = addNamedSource('/pkg1/lib/lib1.dart', r'''
+ import 'package:meta/meta.dart';
+ @sealed class Foo {}
+ ''');
+ Source source2 = addNamedSource('/pkg1/lib/src/lib2.dart', r'''
+ import '../lib1.dart';
+ class Bar1 extends Foo {}
+ class Bar2 implements Foo {}
+ class Bar4 = Bar1 with Foo;
+ mixin Bar5 on Foo {}
+ mixin Bar6 implements Foo {}
+ ''');
+ await computeAnalysisResult(source1);
+ await computeAnalysisResult(source2);
+ assertNoErrors(source1);
+ assertNoErrors(source2);
+ verify([source1, source2]);
+ }
+
+ test_subtypeOfSealedClass_withinPackageTestDirectory_OK() async {
+ super.resetWith(packages: [
+ ['meta', metaLibraryStub],
+ ]);
+
+ newFolder('/pkg1');
+ _newPubPackageRoot('/pkg1');
+
+ Source source1 = addNamedSource('/pkg1/lib/lib1.dart', r'''
+ import 'package:meta/meta.dart';
+ @sealed class Foo {}
+ ''');
+ Source source2 = addNamedSource('/pkg1/test/test.dart', r'''
+ import '../lib/lib1.dart';
+ class Bar1 extends Foo {}
+ class Bar2 implements Foo {}
+ class Bar4 = Bar1 with Foo;
+ mixin Bar5 on Foo {}
+ mixin Bar6 implements Foo {}
+ ''');
+ await computeAnalysisResult(source1);
+ await computeAnalysisResult(source2);
+ assertNoErrors(source1);
+ assertNoErrors(source2);
+ verify([source1, source2]);
+ }
+
test_subtypeOfSealedClass_withinPart_OK() async {
super.resetWith(packages: [
['meta', metaLibraryStub],
]);
- newBasicPackage('/pkg1');
+ _newPubPackageRoot('/pkg1');
Source source1 = addNamedSource('/pkg1/lib/lib1.dart', r'''
import 'package:meta/meta.dart';
part 'part1.dart';
@@ -297,48 +301,55 @@
verify([source1]);
}
- test_subtypeOfSealedClass_withinPackageLibDirectory_OK() async {
+ test_subtypeOfSealedMixin_mixinApplication() async {
super.resetWith(packages: [
['meta', metaLibraryStub],
+ [
+ 'foo',
+ r'''
+import 'package:meta/meta.dart';
+@sealed mixin Foo {}
+'''
+ ]
]);
- newBasicPackage('/pkg1');
- Source source1 = addNamedSource('/pkg1/lib/lib1.dart', r'''
- import 'package:meta/meta.dart';
- @sealed class Foo {}
- ''');
- addNamedSource('/pkg1/lib/src/lib2.dart', r'''
- class Bar1 extends Foo {}
- class Bar2 implements Foo {}
- class Bar4 = Bar1 with Foo;
- mixin Bar5 on Foo {}
- mixin Bar6 implements Foo {}
- ''');
- await computeAnalysisResult(source1);
- assertNoErrors(source1);
- verify([source1]);
+ _newPubPackageRoot('/pkg1');
+ Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
+ import 'package:foo/foo.dart';
+ class Bar1 {}
+ class Bar2 = Bar1 with Foo;
+ ''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
+ verify([source]);
}
- test_subtypeOfSealedClass_withinPackageTestDirectory_OK() async {
+ test_subtypeOfSealedMixin_with() async {
super.resetWith(packages: [
['meta', metaLibraryStub],
+ [
+ 'foo',
+ r'''
+import 'package:meta/meta.dart';
+@sealed mixin Foo {}
+'''
+ ]
]);
- newBasicPackage('/pkg1');
- Source source1 = addNamedSource('/pkg1/lib/lib1.dart', r'''
- import 'package:meta/meta.dart';
- @sealed class Foo {}
- ''');
- addNamedSource('/pkg1/test/test.dart', r'''
- class Bar1 extends Foo {}
- class Bar2 implements Foo {}
- class Bar4 = Bar1 with Foo;
- mixin Bar5 on Foo {}
- mixin Bar6 implements Foo {}
- ''');
- await computeAnalysisResult(source1);
- assertNoErrors(source1);
- verify([source1]);
+ _newPubPackageRoot('/pkg1');
+ Source source = addNamedSource('/pkg1/lib/lib1.dart', r'''
+ import 'package:foo/foo.dart';
+ class Bar extends Object with Foo {}
+ ''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.SUBTYPE_OF_SEALED_CLASS]);
+ verify([source]);
+ }
+
+ /// Write a pubspec file at [root], so that BestPracticesVerifier can see
+ /// that [root] is the root of a PubWorkspace, and a PubWorkspacePackage.
+ void _newPubPackageRoot(String root) {
+ newFile('$root/pubspec.yaml');
}
}
@@ -1227,76 +1238,6 @@
]);
}
- test_invalidAssignment_instanceVariable() async {
- Source source = addSource(r'''
-class A {
- int x;
-}
-f(var y) {
- A a;
- if(y is String) {
- a.x = y;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
- verify([source]);
- }
-
- test_invalidAssignment_localVariable() async {
- Source source = addSource(r'''
-f(var y) {
- if(y is String) {
- int x = y;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
- verify([source]);
- }
-
- test_invalidAssignment_message() async {
- // The implementation of HintCode.INVALID_ASSIGNMENT assumes that
- // StaticTypeWarningCode.INVALID_ASSIGNMENT has the same message.
- expect(StaticTypeWarningCode.INVALID_ASSIGNMENT.message,
- HintCode.INVALID_ASSIGNMENT.message);
- }
-
- test_invalidAssignment_staticVariable() async {
- Source source = addSource(r'''
-class A {
- static int x;
-}
-f(var y) {
- if(y is String) {
- A.x = y;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
- verify([source]);
- }
-
- test_invalidAssignment_variableDeclaration() async {
- // 17971
- Source source = addSource(r'''
-class Point {
- final num x, y;
- Point(this.x, this.y);
- Point operator +(Point other) {
- return new Point(x+other.x, y+other.y);
- }
-}
-main() {
- var p1 = new Point(0, 0);
- var p2 = new Point(10, 10);
- int n = p1 + p2;
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
- verify([source]);
- }
-
test_invalidImmutableAnnotation_method() async {
Source source = addSource(r'''
import 'package:meta/meta.dart';
@@ -1323,6 +1264,55 @@
verify([source]);
}
+ test_nonConstCallToLiteralConstructor_nonConstContext() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ @literal
+ const A();
+}
+void main() {
+ var a = A();
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR]);
+ verify([source]);
+ }
+
+ test_nonConstCallToLiteralConstructor_usingNew() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ @literal
+ const A();
+}
+void main() {
+ var a = new A();
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(
+ source, [HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW]);
+ verify([source]);
+ }
+
+ test_nonConstCallToLiteralConstructor_namedConstructor() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ @literal
+ const A.named();
+}
+void main() {
+ var a = A.named();
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR]);
+ verify([source]);
+ }
+
test_invalidLiteralAnnotation_nonConstructor() async {
Source source = addSource(r'''
import 'package:meta/meta.dart';
@@ -1347,6 +1337,17 @@
verify([source]);
}
+ test_invalidSealedAnnotation_onMixin() async {
+ Source source = addNamedSource('/lib1.dart', r'''
+import 'package:meta/meta.dart';
+
+@sealed mixin M {}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.INVALID_SEALED_ANNOTATION]);
+ verify([source]);
+ }
+
test_invalidSealedAnnotation_onMixinApplication() async {
Source source = addNamedSource('/lib1.dart', r'''
import 'package:meta/meta.dart';
@@ -1362,17 +1363,6 @@
verify([source]);
}
- test_invalidSealedAnnotation_onMixin() async {
- Source source = addNamedSource('/lib1.dart', r'''
-import 'package:meta/meta.dart';
-
-@sealed mixin M {}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.INVALID_SEALED_ANNOTATION]);
- verify([source]);
- }
-
test_invalidSealedAnnotation_onNonClass() async {
Source source = addNamedSource('/lib1.dart', r'''
import 'package:meta/meta.dart';
@@ -2415,21 +2405,6 @@
verify([source]);
}
- test_mustBeImmutable_mixinApplicationBase() async {
- Source source = addSource(r'''
-import 'package:meta/meta.dart';
-class A {
- int x;
-}
-class B {}
-@immutable
-class C = A with B;
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.MUST_BE_IMMUTABLE]);
- verify([source]);
- }
-
test_mustBeImmutable_fromMixin() async {
Source source = addSource(r'''
import 'package:meta/meta.dart';
@@ -2473,6 +2448,21 @@
verify([source]);
}
+ test_mustBeImmutable_mixinApplicationBase() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ int x;
+}
+class B {}
+@immutable
+class C = A with B;
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.MUST_BE_IMMUTABLE]);
+ verify([source]);
+ }
+
test_mustCallSuper() async {
Source source = addSource(r'''
import 'package:meta/meta.dart';
@@ -3900,26 +3890,6 @@
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
}
- test_unnecessaryCast_type_supertype() async {
- Source source = addSource(r'''
-m(int i) {
- var b = i as Object;
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNNECESSARY_CAST]);
- verify([source]);
- }
-
- test_unnecessaryCast_type_type() async {
- Source source = addSource(r'''
-m(num i) {
- var b = i as num;
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNNECESSARY_CAST]);
- verify([source]);
- }
-
test_unnecessaryNoSuchMethod_blockBody() async {
Source source = addSource(r'''
class A {
@@ -4746,346 +4716,6 @@
verify([source]);
}
- test_unusedField_isUsed_argument() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f = 0;
- main() {
- print(++_f);
- }
-}
-print(x) {}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_isUsed_reference_implicitThis() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- main() {
- print(_f);
- }
-}
-print(x) {}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_isUsed_reference_implicitThis_expressionFunctionBody() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- m() => _f;
-}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_isUsed_reference_implicitThis_subclass() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- main() {
- print(_f);
- }
-}
-class B extends A {
- int _f;
-}
-print(x) {}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_isUsed_reference_qualified_propagatedElement() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
-}
-main() {
- var a = new A();
- print(a._f);
-}
-print(x) {}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_isUsed_reference_qualified_staticElement() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
-}
-main() {
- A a = new A();
- print(a._f);
-}
-print(x) {}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_isUsed_reference_qualified_unresolved() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
-}
-main(a) {
- print(a._f);
-}
-print(x) {}''');
- await computeAnalysisResult(source);
- assertErrors(source);
- verify([source]);
- }
-
- test_unusedField_notUsed_compoundAssign() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- main() {
- _f += 2;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedField_notUsed_constructorFieldInitializers() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- A() : _f = 0;
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedField_notUsed_fieldFormalParameter() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- A(this._f);
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedField_notUsed_noReference() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
-}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedField_notUsed_nullAssign() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- var _f;
- m() {
- _f ??= doSomething();
- }
-}
-doSomething() => 0;
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedField_notUsed_postfixExpr() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f = 0;
- main() {
- _f++;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedField_notUsed_prefixExpr() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f = 0;
- main() {
- ++_f;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedField_notUsed_simpleAssignment() async {
- enableUnusedElement = true;
- Source source = addSource(r'''
-class A {
- int _f;
- m() {
- _f = 1;
- }
-}
-main(A a) {
- a._f = 2;
-}
-''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_FIELD]);
- verify([source]);
- }
-
- test_unusedImport() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart';''');
- Source source2 = addNamedSource("/lib1.dart", "library lib1;");
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_IMPORT]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- test_unusedImport_as() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart';
-import 'lib1.dart' as one;
-one.A a;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_IMPORT]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- @failingTest
- test_unusedImport_as_equalPrefixes() async {
- // See todo at ImportsVerifier.prefixElementMap.
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' as one;
-import 'lib2.dart' as one;
-one.A a;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}''');
- Source source3 = addNamedSource("/lib2.dart", r'''
-library lib2;
-class B {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- await computeAnalysisResult(source3);
- assertErrors(source, [HintCode.UNUSED_IMPORT]);
- assertNoErrors(source2);
- assertNoErrors(source3);
- verify([source, source2, source3]);
- }
-
- test_unusedImport_hide() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart';
-import 'lib1.dart' hide A;
-A a;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_IMPORT]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- test_unusedImport_inComment_libraryDirective() async {
- Source source = addSource(r'''
-/// Use [Future] class.
-library L;
-import 'dart:async';
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- }
-
- test_unusedImport_show() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' show A;
-import 'lib1.dart' show B;
-A a;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}
-class B {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_IMPORT]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- test_unusedLabel_inSwitch() async {
- Source source = addSource(r'''
-f(x) {
- switch (x) {
- label: case 0:
- break;
- default:
- break;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_LABEL]);
- verify([source]);
- }
-
- test_unusedLabel_onWhile() async {
- Source source = addSource(r'''
-f(condition()) {
- label: while (condition()) {
- break;
- }
-}''');
- await computeAnalysisResult(source);
- assertErrors(source, [HintCode.UNUSED_LABEL]);
- verify([source]);
- }
-
test_unusedLocalVariable_inCatch_exception() async {
enableUnusedLocalVariable = true;
Source source = addSource(r'''
@@ -5287,78 +4917,4 @@
assertErrors(source);
verify([source]);
}
-
- test_unusedShownName() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' show A, B;
-A a;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}
-class B {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- test_unusedShownName_as() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' as p show A, B;
-p.A a;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}
-class B {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- test_unusedShownName_duplicates() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' show A, B;
-import 'lib1.dart' show C, D;
-A a;
-C c;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}
-class B {}
-class C {}
-class D {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(
- source, [HintCode.UNUSED_SHOWN_NAME, HintCode.UNUSED_SHOWN_NAME]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
-
- test_unusedShownName_topLevelVariable() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' show var1, var2;
-import 'lib1.dart' show var3, var4;
-int a = var1;
-int b = var2;
-int c = var3;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-const int var1 = 1;
-const int var2 = 2;
-const int var3 = 3;
-const int var4 = 4;''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
- assertNoErrors(source2);
- verify([source, source2]);
- }
}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 7eb938a..12a26e8 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2846,6 +2846,74 @@
verify([source]);
}
+ test_invalidAssignment_postfixExpression_localVariable() async {
+ Source source = addSource(r'''
+class A {
+ A operator+(_) => this;
+}
+
+f(A a) {
+ a++;
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_invalidAssignment_postfixExpression_property() async {
+ Source source = addSource(r'''
+class A {
+ A operator+(_) => this;
+}
+
+class C {
+ A a;
+}
+
+f(C c) {
+ c.a++;
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_invalidAssignment_prefixExpression_localVariable() async {
+ Source source = addSource(r'''
+class A {
+ A operator+(_) => this;
+}
+
+f(A a) {
+ ++a;
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_invalidAssignment_prefixExpression_property() async {
+ Source source = addSource(r'''
+class A {
+ A operator+(_) => this;
+}
+
+class C {
+ A a;
+}
+
+f(C c) {
+ ++c.a;
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_invalidAssignment_toDynamic() async {
Source source = addSource(r'''
f() {
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index f1af9c5..bf270f1 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -483,6 +483,57 @@
verify([source]);
}
+ test_nonConstCallToLiteralConstructor_constCreation() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ @literal
+ const A();
+}
+
+void main() {
+ const a = const A();
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_nonConstCallToLiteralConstructor_constContextCreation() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ @literal
+ const A();
+}
+
+void main() {
+ const a = A();
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_nonConstCallToLiteralConstructor_unconstableCreation() async {
+ Source source = addSource(r'''
+import 'package:meta/meta.dart';
+class A {
+ @literal
+ const A(List list);
+}
+
+void main() {
+ var a = A(new List());
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_overrideOnNonOverridingField_inInterface() async {
Source source = addSource(r'''
class A {
@@ -910,102 +961,6 @@
assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
}
- test_unnecessaryCast_13855_parameter_A() async {
- // dartbug.com/13855, dartbug.com/13732
- Source source = addSource(r'''
-class A{
- a() {}
-}
-class B<E> {
- E e;
- m() {
- (e as A).a();
- }
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unnecessaryCast_conditionalExpression() async {
- Source source = addSource(r'''
-abstract class I {}
-class A implements I {}
-class B implements I {}
-I m(A a, B b) {
- return a == null ? b as I : a as I;
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unnecessaryCast_dynamic_type() async {
- Source source = addSource(r'''
-m(v) {
- var b = v as Object;
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unnecessaryCast_function() async {
- Source source = addSource(r'''
-void main() {
- Function(Null) f = (String x) => x;
- (f as Function(int))(3);
-}
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unnecessaryCast_function2() async {
- Source source = addSource(r'''
-class A {}
-
-class B<T extends A> {
- void foo() {
- T Function(T) f;
- A Function(A) g;
- g = f as A Function(A);
- }
-}
-''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unnecessaryCast_generics() async {
- // dartbug.com/18953
- Source source = addSource(r'''
-import 'dart:async';
-Future<int> f() => new Future.value(0);
-void g(bool c) {
- (c ? f(): new Future.value(0) as Future<int>).then((int value) {});
-}''');
- await computeAnalysisResult(source);
- if (enableNewAnalysisDriver) {
- assertErrors(source, [HintCode.UNNECESSARY_CAST]);
- } else {
- assertNoErrors(source);
- }
- verify([source]);
- }
-
- test_unnecessaryCast_type_dynamic() async {
- Source source = addSource(r'''
-m(v) {
- var b = Object as dynamic;
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
test_unnecessaryNoSuchMethod_blockBody_notReturnStatement() async {
Source source = addSource(r'''
class A {
@@ -1066,224 +1021,6 @@
assertNoErrors(source);
verify([source]);
}
-
- test_unusedImport_annotationOnDirective() async {
- Source source = addSource(r'''
-library L;
-@A()
-import 'lib1.dart';''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {
- const A() {}
-}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- assertErrors(source);
- verify([source, source2]);
- }
-
- test_unusedImport_as_equalPrefixes() async {
- // 18818
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' as one;
-import 'lib2.dart' as one;
-one.A a;
-one.B b;''');
- Source source2 = addNamedSource("/lib1.dart", r'''
-library lib1;
-class A {}''');
- Source source3 = addNamedSource("/lib2.dart", r'''
-library lib2;
-class B {}''');
- await computeAnalysisResult(source);
- await computeAnalysisResult(source2);
- await computeAnalysisResult(source3);
- assertErrors(source);
- assertNoErrors(source2);
- assertNoErrors(source3);
- verify([source, source2, source3]);
- }
-
- test_unusedImport_core_library() async {
- Source source = addSource(r'''
-library L;
-import 'dart:core';''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedImport_export() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart';
-Two two;''');
- addNamedSource("/lib1.dart", r'''
-library lib1;
-export 'lib2.dart';
-class One {}''');
- addNamedSource("/lib2.dart", r'''
-library lib2;
-class Two {}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedImport_export2() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart';
-Three three;''');
- addNamedSource("/lib1.dart", r'''
-library lib1;
-export 'lib2.dart';
-class One {}''');
- addNamedSource("/lib2.dart", r'''
-library lib2;
-export 'lib3.dart';
-class Two {}''');
- addNamedSource("/lib3.dart", r'''
-library lib3;
-class Three {}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedImport_export_infiniteLoop() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart';
-Two two;''');
- addNamedSource("/lib1.dart", r'''
-library lib1;
-export 'lib2.dart';
-class One {}''');
- addNamedSource("/lib2.dart", r'''
-library lib2;
-export 'lib3.dart';
-class Two {}''');
- addNamedSource("/lib3.dart", r'''
-library lib3;
-export 'lib2.dart';
-class Three {}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedImport_metadata() async {
- Source source = addSource(r'''
-library L;
-@A(x)
-import 'lib1.dart';
-class A {
- final int value;
- const A(this.value);
-}''');
- addNamedSource("/lib1.dart", r'''
-library lib1;
-const x = 0;''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedImport_prefix_topLevelFunction() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' hide topLevelFunction;
-import 'lib1.dart' as one show topLevelFunction;
-class A {
- static void x() {
- One o;
- one.topLevelFunction();
- }
-}''');
- addNamedSource("/lib1.dart", r'''
-library lib1;
-class One {}
-topLevelFunction() {}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedImport_prefix_topLevelFunction2() async {
- Source source = addSource(r'''
-library L;
-import 'lib1.dart' hide topLevelFunction;
-import 'lib1.dart' as one show topLevelFunction;
-import 'lib1.dart' as two show topLevelFunction;
-class A {
- static void x() {
- One o;
- one.topLevelFunction();
- two.topLevelFunction();
- }
-}''');
- addNamedSource("/lib1.dart", r'''
-library lib1;
-class One {}
-topLevelFunction() {}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedLabel_inSwitch() async {
- Source source = addSource(r'''
-f(x) {
- switch (x) {
- label: case 0:
- break;
- default:
- continue label;
- }
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_unusedLabel_onWhile() async {
- Source source = addSource(r'''
-f(condition()) {
- label: while (condition()) {
- break label;
- }
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_useOfVoidResult_implicitReturnValue() async {
- Source source = addSource(r'''
-f() {}
-class A {
- n() {
- var a = f();
- }
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
-
- test_useOfVoidResult_nonVoidReturnValue() async {
- Source source = addSource(r'''
-int f() => 1;
-g() {
- var a = f();
-}''');
- await computeAnalysisResult(source);
- assertNoErrors(source);
- verify([source]);
- }
}
class PubSuggestionCodeTest extends ResolverTestCase {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 1f618d1..b022212 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -15,7 +15,6 @@
import 'package:analyzer/src/generated/parser.dart' as analyzer;
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/string_source.dart';
-import 'package:analyzer/src/test_utilities/ast_type_matchers.dart';
import 'package:front_end/src/fasta/parser/forwarding_listener.dart' as fasta;
import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
import 'package:front_end/src/fasta/scanner.dart'
@@ -26,6 +25,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../util/ast_type_matchers.dart';
import 'parser_fasta_listener.dart';
import 'parser_test.dart';
import 'test_support.dart';
@@ -113,8 +113,9 @@
void test_conditionalExpression_precedence_nullableType_as2() {
ExpressionStatement statement = parseStatement('x as bool? ? (x + y) : z;');
ConditionalExpression expression = statement.expression;
- Expression condition = expression.condition;
- expect(condition, isAsExpression);
+ AsExpression asExpression = expression.condition;
+ TypeName type = asExpression.type;
+ expect(type.question.lexeme, '?');
Expression thenExpression = expression.thenExpression;
expect(thenExpression, isParenthesizedExpression);
Expression elseExpression = expression.elseExpression;
@@ -127,9 +128,10 @@
ExpressionStatement statement =
parseStatement('(x as bool?) ? (x + y) : z;');
ConditionalExpression expression = statement.expression;
- Expression condition = expression.condition;
- expect(condition, isParenthesizedExpression);
- expect((condition as ParenthesizedExpression).expression, isAsExpression);
+ ParenthesizedExpression condition = expression.condition;
+ AsExpression asExpression = condition.expression;
+ TypeName type = asExpression.type;
+ expect(type.question.lexeme, '?');
Expression thenExpression = expression.thenExpression;
expect(thenExpression, isParenthesizedExpression);
Expression elseExpression = expression.elseExpression;
@@ -142,8 +144,9 @@
ExpressionStatement statement =
parseStatement('x is String? ? (x + y) : z;');
ConditionalExpression expression = statement.expression;
- Expression condition = expression.condition;
- expect(condition, isIsExpression);
+ IsExpression isExpression = expression.condition;
+ TypeName type = isExpression.type;
+ expect(type.question.lexeme, '?');
Expression thenExpression = expression.thenExpression;
expect(thenExpression, isParenthesizedExpression);
Expression elseExpression = expression.elseExpression;
@@ -156,9 +159,10 @@
ExpressionStatement statement =
parseStatement('(x is String?) ? (x + y) : z;');
ConditionalExpression expression = statement.expression;
- Expression condition = expression.condition;
- expect(condition, isParenthesizedExpression);
- expect((condition as ParenthesizedExpression).expression, isIsExpression);
+ ParenthesizedExpression condition = expression.condition;
+ IsExpression isExpression = condition.expression;
+ TypeName type = isExpression.type;
+ expect(type.question.lexeme, '?');
Expression thenExpression = expression.thenExpression;
expect(thenExpression, isParenthesizedExpression);
Expression elseExpression = expression.elseExpression;
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index bab974d..e6fbf65 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -24,7 +24,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:analyzer/src/test_utilities/ast_type_matchers.dart';
+import '../util/ast_type_matchers.dart';
import 'test_support.dart';
main() {
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 0558400..69dc68b 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -1732,13 +1732,13 @@
null, "A", null, extendsClause, withClause, implementsClause);
declaration.name.staticElement = elementA;
_resolveNode(declaration, [elementA, elementB, elementC, elementD]);
- expect(elementA.supertype, same(elementB.type));
+ expect(elementA.supertype, elementB.type);
List<InterfaceType> mixins = elementA.mixins;
expect(mixins, hasLength(1));
- expect(mixins[0], same(elementC.type));
+ expect(mixins[0], elementC.type);
List<InterfaceType> interfaces = elementA.interfaces;
expect(interfaces, hasLength(1));
- expect(interfaces[0], same(elementD.type));
+ expect(interfaces[0], elementD.type);
_listener.assertNoErrors();
}
@@ -1759,7 +1759,7 @@
null, "B", null, extendsClause, null, null);
declaration.name.staticElement = elementB;
_resolveNode(declaration, [elementA, elementB]);
- expect(elementB.supertype, same(elementA.type));
+ expect(elementB.supertype, elementA.type);
_listener.assertNoErrors();
}
@@ -1785,7 +1785,7 @@
pElement.type = pType;
_resolveFormalParameter(pNode, [intType.element]);
- expect(pType.returnType, same(intType));
+ expect(pType.returnType, intType);
expect(pType.parameters, hasLength(1));
_listener.assertNoErrors();
}
@@ -1808,7 +1808,7 @@
AstTestFactory.fieldFormalParameter(null, intTypeName, parameterName);
node.identifier.staticElement =
ElementFactory.requiredParameter(parameterName);
- expect(_resolveFormalParameter(node, [intType.element]), same(intType));
+ expect(_resolveFormalParameter(node, [intType.element]), intType);
_listener.assertNoErrors();
}
@@ -2017,7 +2017,7 @@
SimpleIdentifier identifier = node.identifier;
ParameterElementImpl element = new ParameterElementImpl.forNode(identifier);
node.declaredElement = identifier.staticElement = element;
- expect(_resolveFormalParameter(node, [intElement]), same(intType));
+ expect(_resolveFormalParameter(node, [intElement]), intType);
_listener.assertNoErrors();
}
@@ -2026,7 +2026,7 @@
TypeName typeName = AstTestFactory.typeName(classA);
typeName.type = null;
_resolveNode(typeName, [classA]);
- expect(typeName.type, same(classA.type));
+ expect(typeName.type, classA.type);
_listener.assertNoErrors();
}
@@ -2051,7 +2051,7 @@
expect(resultType.element, same(classA));
List<DartType> resultArguments = resultType.typeArguments;
expect(resultArguments, hasLength(1));
- expect(resultArguments[0], same(classB.type));
+ expect(resultArguments[0], classB.type);
_listener.assertNoErrors();
}
@@ -2107,11 +2107,11 @@
_resolveNode(node, definedElements);
SimpleIdentifier exceptionParameter = node.exceptionParameter;
if (exceptionParameter != null) {
- expect(exceptionParameter.staticType, same(exceptionType));
+ expect(exceptionParameter.staticType, exceptionType);
}
SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
if (stackTraceParameter != null) {
- expect(stackTraceParameter.staticType, same(stackTraceType));
+ expect(stackTraceParameter.staticType, stackTraceType);
}
}
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 485d871..a682c9d 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -35,6 +35,8 @@
import 'analysis_context_factory.dart';
import 'test_support.dart';
+const String _defaultSourceName = "/test.dart";
+
/**
* An AST visitor used to verify that all of the nodes in an AST structure that
* should have been resolved were resolved.
@@ -407,7 +409,8 @@
* file will have the given [contents] set in the content provider. Return the
* source representing the added file.
*/
- Source addSource(String contents) => addNamedSource("/test.dart", contents);
+ Source addSource(String contents) =>
+ addNamedSource(_defaultSourceName, contents);
/**
* The [code] that assigns the value to the variable "v", no matter how. We
@@ -457,8 +460,8 @@
*/
// TODO(rnystrom): Use this in more tests that have the same structure.
Future<void> assertErrorsInCode(String code, List<ErrorCode> errors,
- {bool verify: true}) async {
- Source source = addSource(code);
+ {bool verify: true, String sourceName: _defaultSourceName}) async {
+ Source source = addNamedSource(sourceName, code);
await computeAnalysisResult(source);
assertErrors(source, errors);
if (verify) {
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index 634605f..91bb80a 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -1698,9 +1698,8 @@
DartType staticType = node.staticType;
expect(staticType is FunctionType, isTrue);
FunctionType functionType = staticType;
- expect(
- functionType.parameters[0].type, same(test.typeProvider.intType));
- expect(functionType.returnType, same(test.typeProvider.stringType));
+ expect(functionType.parameters[0].type, test.typeProvider.intType);
+ expect(functionType.returnType, test.typeProvider.stringType);
} on AnalysisException catch (e, stackTrace) {
thrownException[0] = new CaughtException(e, stackTrace);
}
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index eae9fe1..fe9cb89 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -32,6 +33,7 @@
main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(SetLiteralsTest);
defineReflectiveTests(StaticTypeAnalyzerTest);
defineReflectiveTests(StaticTypeAnalyzer2Test);
defineReflectiveTests(StaticTypeAnalyzer3Test);
@@ -48,6 +50,27 @@
fail(message);
}
+@reflectiveTest
+class SetLiteralsTest extends StaticTypeAnalyzer2TestShared {
+ @override
+ List<String> get enabledExperiments => [EnableString.set_literals];
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ test_emptySetLiteral_parameter_typed() async {
+ String code = r'''
+main() {
+ useSet({});
+}
+void useSet(Set<int> s) {
+}
+''';
+ await resolveTestUnit(code);
+ expectExpressionType('{}', 'Set<int>');
+ }
+}
+
/**
* Like [StaticTypeAnalyzerTest], but as end-to-end tests.
*/
@@ -210,18 +233,6 @@
await resolveTestUnit(code);
expectExpressionType('{}', 'Map<int, int>');
}
-
- test_emptySetLiteral_parameter_typed() async {
- String code = r'''
-main() {
- useSet({});
-}
-void useSet(Set<int> s) {
-}
-''';
- await resolveTestUnit(code);
- expectExpressionType('{}', 'Set<int>');
- }
}
@reflectiveTest
@@ -1660,6 +1671,16 @@
bool get enableNewAnalysisDriver => true;
+ test_emptySetLiteral_inferredFromLinkedHashSet() async {
+ String code = r'''
+import 'dart:collection';
+LinkedHashSet<int> test4() => {};
+''';
+ await resolveTestUnit(code, noErrors: false);
+ expectExpressionType('{}', 'Set<?>');
+ await assertErrorsInCode(code, [StrongModeCode.INVALID_CAST_LITERAL_SET]);
+ }
+
test_emptySetLiteral_initializer_typed_nested() async {
String code = r'''
Set<Set<int>> ints = {{}};
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 283d077..5c1f94b 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -193,6 +193,13 @@
]);
}
+ test_defaultSetLiteralNotEnabled() async {
+ await assertErrorsInCode(r'''
+void main() {
+ Set _ = {};
+}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
test_expectedOneListTypeArgument() async {
await assertErrorsInCode(r'''
main() {
@@ -549,6 +556,70 @@
}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
}
+ test_invalidAssignment_postfixExpression_localVariable() async {
+ await assertErrorsInCode(r'''
+class A {
+ B operator+(_) => new B();
+}
+
+class B {}
+
+f(A a) {
+ a++;
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ test_invalidAssignment_postfixExpression_property() async {
+ await assertErrorsInCode(r'''
+class A {
+ B operator+(_) => new B();
+}
+
+class B {}
+
+class C {
+ A a;
+}
+
+f(C c) {
+ c.a++;
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ test_invalidAssignment_prefixExpression_localVariable() async {
+ await assertErrorsInCode(r'''
+class A {
+ B operator+(_) => new B();
+}
+
+class B {}
+
+f(A a) {
+ ++a;
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ test_invalidAssignment_prefixExpression_property() async {
+ await assertErrorsInCode(r'''
+class A {
+ B operator+(_) => new B();
+}
+
+class B {}
+
+class C {
+ A a;
+}
+
+f(C c) {
+ ++c.a;
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
test_invalidAssignment_regressionInIssue18468Fix() async {
// https://code.google.com/p/dart/issues/detail?id=18628
await assertErrorsInCode(r'''
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index 5ceb965..247d10f 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -18,8 +18,8 @@
import '../src/util/yaml_test.dart';
main() {
- AnalysisError invalid_assignment =
- new AnalysisError(new TestSource(), 0, 1, HintCode.INVALID_ASSIGNMENT, [
+ AnalysisError invalid_assignment = new AnalysisError(
+ new TestSource(), 0, 1, StaticTypeWarningCode.INVALID_ASSIGNMENT, [
['x'],
['y']
]);
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 3594512..23e564e 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -17,7 +17,12 @@
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/workspace/basic.dart';
import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/gn.dart';
+import 'package:analyzer/src/workspace/package_build.dart';
+import 'package:analyzer/src/workspace/pub.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
import 'package:args/args.dart';
import 'package:package_config/packages.dart';
import 'package:package_config/src/packages_impl.dart';
@@ -872,6 +877,68 @@
expect(result.path, filePath);
}
+ void test_createWorkspace_hasPackagesFile_hasDartToolAndPubspec() {
+ newFile('/workspace/.packages');
+ newFolder('/workspace/.dart_tool/build/generated/project/lib');
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<PackageBuildWorkspace>());
+ }
+
+ void test_createWorkspace_hasPackagesFile_hasPubspec() {
+ newFile('/workspace/.packages');
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<PubWorkspace>());
+ }
+
+ void test_createWorkspace_hasPackagesFile_noMarkerFiles() {
+ newFile('/workspace/.packages');
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<BasicWorkspace>());
+ }
+
+ void test_createWorkspace_noPackagesFile_hasDartToolAndPubspec() {
+ newFolder('/workspace/.dart_tool/build/generated/project/lib');
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<PackageBuildWorkspace>());
+ }
+
+ void test_createWorkspace_noPackagesFile_hasPubspec() {
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<PubWorkspace>());
+ }
+
+ void test_createWorkspace_noPackagesFile_noMarkerFiles() {
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<BasicWorkspace>());
+ }
+
+ void test_createWorkspace_noPackagesFile_hasGnMarkerFiles() {
+ newFolder('/workspace/.jiri_root');
+ newFile(
+ '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib.packages');
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<GnWorkspace>());
+ }
+
+ void test_createWorkspace_noPackagesFile_hasBazelMarkerFiles() {
+ newFile('/workspace/WORKSPACE');
+ newFolder('/workspace/bazel-genfiles');
+ Workspace workspace = ContextBuilder.createWorkspace(
+ resourceProvider, '/workspace/project/lib/lib.dart', builder);
+ expect(workspace, TypeMatcher<BazelWorkspace>());
+ }
+
_defineMockLintRules() {
_mockLintRule = new _MockLintRule('mock_lint_rule');
Registry.ruleRegistry.registerDefault(_mockLintRule);
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index df8a221..5822d82 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -26,7 +26,6 @@
import 'package:analyzer/src/task/api/model.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/task/html.dart';
-import 'package:analyzer/src/test_utilities/element_type_matchers.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:html/dom.dart' show Document;
import 'package:test/test.dart';
@@ -34,6 +33,7 @@
import '../../generated/engine_test.dart';
import '../../generated/test_support.dart';
+import '../../util/element_type_matchers.dart';
import 'abstract_context.dart';
main() {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b5c6ad8..e52ece7 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -4081,12 +4081,12 @@
VariableDeclarationStatement vStatement = mainStatements[1];
VariableDeclaration vDeclaration = vStatement.variables.variables[0];
- expect(vDeclaration.declaredElement.type, same(doubleType));
+ expect(vDeclaration.declaredElement.type, doubleType);
MethodInvocation fInvocation = vDeclaration.initializer;
expect(fInvocation.methodName.staticElement, same(fElement));
expect(fInvocation.methodName.staticType.toString(), fTypeString);
- expect(fInvocation.staticType, same(doubleType));
+ expect(fInvocation.staticType, doubleType);
expect(fInvocation.staticInvokeType.toString(), fTypeString);
}
@@ -4407,12 +4407,12 @@
{
VariableDeclarationStatement statement = mainStatements[1];
VariableDeclaration declaration = statement.variables.variables[0];
- expect(declaration.declaredElement.type, same(doubleType));
+ expect(declaration.declaredElement.type, doubleType);
MethodInvocation invocation = declaration.initializer;
expect(invocation.methodName.staticElement, same(fElement));
expect(invocation.methodName.staticType.toString(), fTypeString);
- expect(invocation.staticType, same(doubleType));
+ expect(invocation.staticType, doubleType);
expect(invocation.staticInvokeType.toString(), fTypeString);
List<Expression> arguments = invocation.argumentList.arguments;
@@ -5773,7 +5773,7 @@
expect(invocation.methodName.staticElement, same(fElement));
expect(invocation.methodName.staticType.toString(), fTypeString);
- expect(invocation.staticType, same(doubleType));
+ expect(invocation.staticType, doubleType);
expect(invocation.staticInvokeType.toString(), fTypeString);
_assertArgumentToParameter(arguments[0], fElement.parameters[0]);
@@ -6868,21 +6868,20 @@
SimpleIdentifier identifier = statement.expression;
expect(identifier.staticElement, same(getterElement));
- expect(identifier.staticType, same(typeProvider.intType));
+ expect(identifier.staticType, typeProvider.intType);
}
// super.getter;
{
ExpressionStatement statement = testStatements[3];
PropertyAccess propertyAccess = statement.expression;
- expect(propertyAccess.staticType, same(typeProvider.intType));
+ expect(propertyAccess.staticType, typeProvider.intType);
SuperExpression target = propertyAccess.target;
expect(target.staticType, bNode.declaredElement.type); // raw
expect(propertyAccess.propertyName.staticElement, same(getterElement));
- expect(
- propertyAccess.propertyName.staticType, same(typeProvider.intType));
+ expect(propertyAccess.propertyName.staticType, typeProvider.intType);
}
// setter = 3;
@@ -6892,7 +6891,7 @@
SimpleIdentifier identifier = assignment.leftHandSide;
expect(identifier.staticElement, same(setterElement));
- expect(identifier.staticType, same(typeProvider.intType));
+ expect(identifier.staticType, typeProvider.intType);
}
// this.setter = 4;
@@ -6906,8 +6905,7 @@
expect(target.staticType, bNode.declaredElement.type); // raw
expect(propertyAccess.propertyName.staticElement, same(setterElement));
- expect(
- propertyAccess.propertyName.staticType, same(typeProvider.intType));
+ expect(propertyAccess.propertyName.staticType, typeProvider.intType);
}
// super + 5;
@@ -7511,7 +7509,7 @@
TypeName typeName = bDeclaration.fields.type;
SimpleIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, same(tElement));
- expect(typeIdentifier.staticType, same(tElement.type));
+ expect(typeIdentifier.staticType, tElement.type);
VariableDeclaration bNode = bDeclaration.fields.variables[0];
expect(bNode.declaredElement, same(bElement));
@@ -8816,7 +8814,7 @@
TypeName typeName = node.type;
if (typeName != null) {
- expect(typeName.type, same(type));
+ expect(typeName.type, type);
expect(typeName.name.staticElement, same(type.element));
}
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 12505a4..aef3c08 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -2337,19 +2337,11 @@
}
test_hasFilesToAnalyze() async {
- var a = convertPath('/test/lib/a.dart');
- var b = convertPath('/test/lib/b.dart');
- var c = convertPath('/test/lib/c.dart');
-
// No files yet, nothing to analyze.
expect(driver.hasFilesToAnalyze, isFalse);
// Add a new file, it should be analyzed.
- newFile(a, content: r'''
-import 'b.dart';
-main() {}
-''');
- driver.addFile(a);
+ addTestFile('main() {}', priority: false);
expect(driver.hasFilesToAnalyze, isTrue);
// Wait for idle, nothing to do.
@@ -2357,25 +2349,19 @@
expect(driver.hasFilesToAnalyze, isFalse);
// Ask to analyze the file, so there is a file to analyze.
- Future<ResolvedUnitResult> future = driver.getResult(a);
+ Future<ResolvedUnitResult> future = driver.getResult(testFile);
expect(driver.hasFilesToAnalyze, isTrue);
// Once analysis is done, there is nothing to analyze.
await future;
expect(driver.hasFilesToAnalyze, isFalse);
- // Change a file that is not added, but referenced, so known.
- driver.changeFile(b);
+ // Change a file, even if not added, it still might affect analysis.
+ driver.changeFile(convertPath('/not/added.dart'));
expect(driver.hasFilesToAnalyze, isTrue);
await waitForIdleWithoutExceptions();
expect(driver.hasFilesToAnalyze, isFalse);
- // Change a file that is not known - neither added, nor referenced.
- driver.changeFile(c);
- expect(driver.hasFilesToAnalyze, isFalse);
- await waitForIdleWithoutExceptions();
- expect(driver.hasFilesToAnalyze, isFalse);
-
// Request of referenced names is not analysis of a file.
driver.getFilesReferencingName('X');
expect(driver.hasFilesToAnalyze, isFalse);
@@ -3376,6 +3362,28 @@
expect(result.errors, hasLength(0));
}
+ test_results_removeFile_changeFile() async {
+ var a = convertPath('/test/lib/a.dart');
+ var b = convertPath('/test/lib/b.dart');
+
+ newFile(a, content: r'''
+var v = 0;
+''');
+ driver.addFile(a);
+
+ await waitForIdleWithoutExceptions();
+ expect(allResults.singleWhere((r) => r.path == a).errors, hasLength(0));
+ allResults.clear();
+
+ newFile(a, content: r'''
+var v = 0
+''');
+ driver.removeFile(b);
+ driver.changeFile(a);
+ await waitForIdleWithoutExceptions();
+ expect(allResults.singleWhere((r) => r.path == a).errors, hasLength(1));
+ }
+
test_results_skipNotAffected() async {
var a = convertPath('/test/lib/a.dart');
var b = convertPath('/test/lib/b.dart');
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index f19f1bd..c6d4eab 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -14,12 +14,12 @@
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
-import 'package:analyzer/src/test_utilities/ast_type_matchers.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/parser_test.dart' show ParserTestCase;
import '../../../generated/test_support.dart';
+import '../../../util/ast_type_matchers.dart';
main() {
defineReflectiveSuite(() {
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index b144d20..94176f6 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -817,9 +817,7 @@
DartObjectImpl result = expression.accept(new ConstantVisitor(
new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
- experimentStatus:
- ExperimentStatus.fromStrings(options.enabledExperiments),
- typeSystem: typeSystem),
+ experimentStatus: options.experimentStatus, typeSystem: typeSystem),
errorReporter,
lexicalEnvironment: lexicalEnvironment));
if (errorCodes == null) {
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 1d4d442..0616164 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -4,7 +4,6 @@
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'driver_resolution.dart';
@@ -17,31 +16,205 @@
@reflectiveTest
class NonNullableTest extends DriverResolutionTest {
+ static const _migrated = "@pragma('analyzer:non-nullable') library test;";
+
@override
AnalysisOptionsImpl get analysisOptions =>
AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
- test_interfaceType() async {
- addTestFile(r'''
-int v = 0;
+ @override
+ bool get typeToStringWithNullability => true;
+
+ test_class_hierarchy() async {
+ addTestFile('''
+class A {}
+
+class X1 extends A {} // 1
+class X2 implements A {} // 2
+class X3 with A {} // 3
''');
await resolveTestFile();
assertNoTestErrors();
- var typeName = findNode.typeName('int v');
- expect(typeName.name.name, 'int');
- expect(typeName.question, isNull);
+ assertType(findNode.typeName('A {} // 1'), 'A!');
+ assertType(findNode.typeName('A {} // 2'), 'A!');
+ assertType(findNode.typeName('A {} // 3'), 'A!');
}
- test_interfaceType_nullable() async {
- addTestFile(r'''
-int? v = 0;
+ test_classTypeAlias_hierarchy() async {
+ addTestFile('''
+class A {}
+class B {}
+class C {}
+
+class X = A with B implements C;
''');
await resolveTestFile();
assertNoTestErrors();
- var typeName = findNode.typeName('int? v');
- expect(typeName.name.name, 'int');
- expect(typeName.question, isNotNull);
+ assertType(findNode.typeName('A with'), 'A!');
+ assertType(findNode.typeName('B implements'), 'B!');
+ assertType(findNode.typeName('C;'), 'C!');
+ }
+
+ test_local_parameter_interfaceType() async {
+ addTestFile('''
+$_migrated
+main() {
+ f(int? a, int b) {}
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('int? a'), 'int?');
+ assertType(findNode.typeName('int b'), 'int!');
+ }
+
+ test_local_returnType_interfaceType() async {
+ addTestFile('''
+$_migrated
+main() {
+ int? f() => 0;
+ int g() => 0;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('int? f'), 'int?');
+ assertType(findNode.typeName('int g'), 'int!');
+ }
+
+ @failingTest
+ test_local_variable_genericFunctionType() async {
+ addTestFile('''
+$_migrated
+main() {
+ int? Function(bool, String?)? a;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(
+ findNode.genericFunctionType('Function('),
+ '(bool!, String?) → int??',
+ );
+ }
+
+ test_local_variable_interfaceType() async {
+ addTestFile('''
+$_migrated
+main() {
+ int? a = 0;
+ int b = 0;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('int? a'), 'int?');
+ assertType(findNode.typeName('int b'), 'int!');
+ }
+
+ test_local_variable_interfaceType_generic() async {
+ addTestFile('''
+$_migrated
+main() {
+ List<int?>? a = [];
+ List<int>? b = [];
+ List<int?> c = [];
+ List<int> d = [];
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('List<int?>? a'), 'List<int?>?');
+ assertType(findNode.typeName('List<int>? b'), 'List<int!>?');
+ assertType(findNode.typeName('List<int?> c'), 'List<int?>!');
+ assertType(findNode.typeName('List<int> d'), 'List<int!>!');
+ }
+
+ test_local_variable_interfaceType_notMigrated() async {
+ addTestFile('''
+main() {
+ int? a = 0;
+ int b = 0;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('int? a'), 'int?');
+ assertType(findNode.typeName('int b'), 'int*');
+ }
+
+ test_local_variable_typeParameter() async {
+ addTestFile('''
+$_migrated
+
+class A<T> {
+ main(T a) {
+ T? b;
+ }
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('T a'), 'T!');
+ assertType(findNode.typeName('T? b'), 'T?');
+ }
+
+ test_mixin_hierarchy() async {
+ addTestFile('''
+class A {}
+
+mixin X1 on A {} // 1
+mixin X2 implements A {} // 2
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('A {} // 1'), 'A!');
+ assertType(findNode.typeName('A {} // 2'), 'A!');
+ }
+
+ test_typedef_classic() async {
+ addTestFile('''
+$_migrated
+
+typedef int? F(bool a, String? b);
+
+main() {
+ F? a;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(findNode.typeName('F? a'), '(bool!, String?) → int??');
+ }
+
+ @failingTest
+ test_typedef_function() async {
+ addTestFile('''
+$_migrated
+
+typedef F<T> = int? Function(bool, T, T?);
+
+main() {
+ F<String>? a;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+
+ assertType(
+ findNode.typeName('F<String>'),
+ '(bool!, String!, String?) → int??',
+ );
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 7e7c6b3..efd7d8e 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -58,6 +58,9 @@
TypeProvider get typeProvider =>
result.unit.declaredElement.context.typeProvider;
+ /// Whether `DartType.toString()` with nullability should be asked.
+ bool get typeToStringWithNullability => false;
+
void addTestFile(String content) {
newFile('/test/lib/test.dart', content: content);
}
@@ -127,7 +130,9 @@
}
void assertElementTypeString(DartType type, String expected) {
- expect(type.toString(), expected);
+ TypeImpl typeImpl = type;
+ expect(typeImpl.toString(withNullability: typeToStringWithNullability),
+ expected);
}
void assertElementTypeStrings(List<DartType> types, List<String> expected) {
@@ -320,7 +325,7 @@
}
void assertType(AstNode node, String expected) {
- DartType actual;
+ TypeImpl actual;
if (node is Expression) {
actual = node.staticType;
} else if (node is GenericFunctionType) {
@@ -330,7 +335,8 @@
} else {
fail('Unsupported node: (${node.runtimeType}) $node');
}
- expect(actual?.toString(), expected);
+ expect(actual?.toString(withNullability: typeToStringWithNullability),
+ expected);
}
void assertTypeDynamic(Expression expression) {
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index bd6d96e..73966e0 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -17,7 +17,7 @@
@reflectiveTest
class ArgumentTypeNotAssignableTest extends ResolverTestCase {
test_functionType() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m() {
var a = new A();
a.n(() => 0);
@@ -29,7 +29,7 @@
}
test_interfaceType() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m() {
var i = '';
n(i);
diff --git a/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart b/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart
index 61f3441..94f9c00 100644
--- a/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart
@@ -17,7 +17,7 @@
@reflectiveTest
class CanBeNullAfterNullAwareTest extends ResolverTestCase {
test_afterCascade() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
x..a?.b.c;
}
@@ -25,7 +25,7 @@
}
test_beforeCascade() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
x?.a..m();
}
@@ -33,7 +33,7 @@
}
test_cascadeWithParenthesis() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
(x?.a)..m();
}
@@ -41,7 +41,7 @@
}
test_definedForNull() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
m(x) {
x?.a.hashCode;
x?.a.runtimeType;
@@ -54,7 +54,7 @@
}
test_guarded_methodInvocation() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
m(x) {
x?.a()?.b();
}
@@ -62,7 +62,7 @@
}
test_guarded_propertyAccess() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
m(x) {
x?.a?.b;
}
@@ -70,7 +70,7 @@
}
test_methodInvocation() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
x?.a.b();
}
@@ -78,7 +78,7 @@
}
test_multipleInvocations() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
x?.a
..m()
@@ -88,7 +88,7 @@
}
test_parenthesized() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
(x?.a).b;
}
@@ -96,7 +96,7 @@
}
test_propertyAccess() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
m(x) {
x?.a.b;
}
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
index 2102064..c864b70 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
@@ -16,7 +16,6 @@
});
}
-@reflectiveTest
mixin ConstConstructorWithMixinWithFieldMixin implements ResolutionTest {
test_class_instance() async {
addTestFile(r'''
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index 7519905..1dcc23e 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -3,12 +3,15 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/resolver_test_case.dart';
main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(DeprecatedMemberUseFromSamePackageTest);
+ defineReflectiveTests(DeprecatedMemberUseFromSamePackageTest_Driver);
defineReflectiveTests(DeprecatedMemberUseTest);
defineReflectiveTests(DeprecatedMemberUseTest_Driver);
});
@@ -16,18 +19,96 @@
@reflectiveTest
class DeprecatedMemberUseTest extends ResolverTestCase {
- test__methodInvocation_contructor() async {
+ /// Write a pubspec file at [root], so that BestPracticesVerifier can see that
+ /// [root] is the root of a BasicWorkspace, and a BasicWorkspacePackage.
+ void newBasicPackage(String root) {
+ newFile('$root/pubspec.yaml');
+ }
+
+ test_methodInvocation_contructor() async {
+ resetWithFooLibrary(r'''
+class A {
+ @Deprecated('0.9')
+ m() {}
+}
+''');
+
+ newBasicPackage('/pkg1');
+ assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() => A().m();
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+ }
+
+ test_methodInvocation_constant() async {
+ resetWithFooLibrary(r'''
+class A {
+ @deprecated
+ m() {}
+}
+''');
+
+ newBasicPackage('/pkg1');
+ assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() => A().m();
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+ }
+
+ void resetWithFooLibrary(String source) {
+ super.resetWith(packages: [
+ ['foo', source]
+ ]);
+ }
+
+ test_export() async {
+ resetWithFooLibrary(r'''
+@deprecated
+library deprecated_library;
+class A {}
+''');
+
+ newBasicPackage('/pkg1');
+ assertErrorsInCode('''
+export 'package:foo/foo.dart';
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+ }
+
+ test_import() async {
+ resetWithFooLibrary(r'''
+@deprecated
+library deprecated_library;
+class A {}
+''');
+
+ newBasicPackage('/pkg1');
+ assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+f(A a) {}
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+ }
+}
+
+@reflectiveTest
+class DeprecatedMemberUseTest_Driver extends DeprecatedMemberUseTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
+
+@reflectiveTest
+class DeprecatedMemberUseFromSamePackageTest extends ResolverTestCase {
+ test_methodInvocation_contructor() async {
assertErrorsInCode(r'''
class A {
@Deprecated('0.9')
m() {}
n() {m();}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_call() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
call() {}
@@ -36,11 +117,11 @@
a();
}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_compoundAssignment() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
A operator+(A a) { return a; }
@@ -49,7 +130,7 @@
A b;
a += b;
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_export() async {
@@ -58,13 +139,13 @@
library deprecated_library;
class A {}
''');
- assertErrorsInCode('''
+ await assertErrorsInCode('''
export 'deprecated_library.dart';
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_field() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
int x = 1;
@@ -72,11 +153,11 @@
f(A a) {
return a.x;
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_getter() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
get m => 1;
@@ -84,7 +165,7 @@
f(A a) {
return a.m;
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_import() async {
@@ -93,14 +174,14 @@
library deprecated_library;
class A {}
''');
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
import 'deprecated_library.dart';
f(A a) {}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_inDeprecatedClass() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
f() {}
@@ -114,7 +195,7 @@
}
test_inDeprecatedField() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
class C {}
@@ -126,7 +207,7 @@
}
test_inDeprecatedFunction() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
f() {}
@@ -138,7 +219,7 @@
}
test_inDeprecatedLibrary() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
library lib;
@@ -154,7 +235,7 @@
}
test_inDeprecatedMethod() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
f() {}
@@ -168,7 +249,7 @@
}
test_inDeprecatedMethod_inDeprecatedClass() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
f() {}
@@ -183,7 +264,7 @@
}
test_inDeprecatedMixin() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
f() {}
@@ -197,7 +278,7 @@
}
test_inDeprecatedTopLevelVariable() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
@deprecated
class C {}
@@ -207,7 +288,7 @@
}
test_indexExpression() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
operator[](int i) {}
@@ -215,11 +296,11 @@
f(A a) {
return a[1];
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_instanceCreation_defaultConstructor() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
A(int i) {}
@@ -227,11 +308,11 @@
f() {
A a = new A(1);
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_instanceCreation_namedConstructor() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
A.named(int i) {}
@@ -239,21 +320,21 @@
f() {
A a = new A.named(1);
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_methodInvocation_constant() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
m() {}
n() {m();}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_operator() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
operator+(A a) {}
@@ -262,26 +343,26 @@
A b;
return a + b;
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_parameter_named() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
m({@deprecated int x}) {}
n() {m(x: 1);}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_parameter_named_inDefiningFunction() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
f({@deprecated int x}) => x;
''');
}
test_parameter_named_inDefiningLocalFunction() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
class C {
m() {
f({@deprecated int x}) {
@@ -294,7 +375,7 @@
}
test_parameter_named_inDefiningMethod() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
class C {
m({@deprecated int x}) {
return x;
@@ -304,7 +385,7 @@
}
test_parameter_named_inNestedLocalFunction() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
class C {
m({@deprecated int x}) {
f() {
@@ -317,16 +398,16 @@
}
test_parameter_positional() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
m([@deprecated int x]) {}
n() {m(1);}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_setter() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
set s(v) {}
@@ -334,11 +415,11 @@
f(A a) {
return a.s = 1;
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_superConstructor_defaultConstructor() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
A() {}
@@ -346,11 +427,11 @@
class B extends A {
B() : super() {}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
test_superConstructor_namedConstructor() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
class A {
@deprecated
A.named() {}
@@ -358,12 +439,13 @@
class B extends A {
B() : super.named() {}
}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
}
}
@reflectiveTest
-class DeprecatedMemberUseTest_Driver extends DeprecatedMemberUseTest {
+class DeprecatedMemberUseFromSamePackageTest_Driver
+ extends DeprecatedMemberUseFromSamePackageTest {
@override
bool get enableNewAnalysisDriver => true;
}
diff --git a/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart b/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
index 539cdf1..6adfcf2 100644
--- a/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
@@ -17,7 +17,7 @@
@reflectiveTest
class DivisionOptimizationTest extends ResolverTestCase {
test_divisionOptimization() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
f(int x, int y) {
var v = x / y.toInt();
}
@@ -25,7 +25,7 @@
}
test_double() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
f(double x, double y) {
var v = (x / y).toInt();
}
@@ -33,7 +33,7 @@
}
test_dynamic() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
f(x, y) {
var v = (x / y).toInt();
}
@@ -41,7 +41,7 @@
}
test_int() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
f(int x, int y) {
var v = (x / y).toInt();
}
@@ -49,7 +49,7 @@
}
test_nonNumeric() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
class A {
num operator /(x) { return x; }
}
@@ -60,7 +60,7 @@
}
test_wrappedInParentheses() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
f(int x, int y) {
var v = (((x / y))).toInt();
}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
new file mode 100644
index 0000000..0630617
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(InvalidAssignmentTest);
+ defineReflectiveTests(InvalidAssignmentTest_Driver);
+ });
+}
+
+@reflectiveTest
+class InvalidAssignmentTest extends ResolverTestCase {
+ test_instanceVariable() async {
+ await assertErrorsInCode(r'''
+class A {
+ int x;
+}
+f(var y) {
+ A a;
+ if (y is String) {
+ a.x = y;
+ }
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ test_localVariable() async {
+ await assertErrorsInCode(r'''
+f(var y) {
+ if (y is String) {
+ int x = y;
+ }
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ test_staticVariable() async {
+ await assertErrorsInCode(r'''
+class A {
+ static int x;
+}
+f(var y) {
+ if (y is String) {
+ A.x = y;
+ }
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+
+ test_variableDeclaration() async {
+ // 17971
+ await assertErrorsInCode(r'''
+class Point {
+ final num x, y;
+ Point(this.x, this.y);
+ Point operator +(Point other) {
+ return new Point(x+other.x, y+other.y);
+ }
+}
+main() {
+ var p1 = new Point(0, 0);
+ var p2 = new Point(10, 10);
+ int n = p1 + p2;
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+ }
+}
+
+@reflectiveTest
+class InvalidAssignmentTest_Driver extends InvalidAssignmentTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
index 70c22e5..e10b266 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
@@ -25,7 +25,7 @@
}
test_namedParameter_withDefault() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
m({@required a = 1}) => null;
@@ -33,7 +33,7 @@
}
test_positionalParameter_withDefault() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
m([@required a = 1]) => null;
@@ -41,7 +41,7 @@
}
test_ppositionalParameter_noDefault() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
m([@required a]) => null;
@@ -49,7 +49,7 @@
}
test_requiredParameter() async {
- assertErrorsInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
m(@required a) => null;
@@ -57,7 +57,7 @@
}
test_valid() async {
- assertNoErrorsInCode(r'''
+ await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
m1() => null;
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index a0b3585..0be860c 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -8,7 +8,14 @@
import 'can_be_null_after_null_aware_test.dart' as can_be_null_after_null_aware;
import 'deprecated_member_use_test.dart' as deprecated_member_use;
import 'division_optimization_test.dart' as division_optimization;
+import 'invalid_assignment_test.dart' as invalid_assignment;
import 'invalid_required_param_test.dart' as invalid_required_param;
+import 'unnecessary_cast_test.dart' as unnecessary_cast;
+import 'unused_field_test.dart' as unused_field;
+import 'unused_import_test.dart' as unused_import;
+import 'unused_label_test.dart' as unused_label;
+import 'unused_shown_name_test.dart' as unused_shown_name;
+import 'use_of_void_result_test.dart' as use_of_void_result;
main() {
defineReflectiveSuite(() {
@@ -16,6 +23,13 @@
can_be_null_after_null_aware.main();
deprecated_member_use.main();
division_optimization.main();
+ invalid_assignment.main();
invalid_required_param.main();
+ unnecessary_cast.main();
+ unused_field.main();
+ unused_import.main();
+ unused_label.main();
+ unused_shown_name.main();
+ use_of_void_result.main();
}, name: 'diagnostics');
}
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
new file mode 100644
index 0000000..507e656
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnnecessaryCastTest);
+ defineReflectiveTests(UnnecessaryCastTest_Driver);
+ });
+}
+
+@reflectiveTest
+class UnnecessaryCastTest extends ResolverTestCase {
+ test_conditionalExpression() async {
+ await assertNoErrorsInCode(r'''
+abstract class I {}
+class A implements I {}
+class B implements I {}
+I m(A a, B b) {
+ return a == null ? b as I : a as I;
+}
+''');
+ }
+
+ test_dynamic_type() async {
+ await assertNoErrorsInCode(r'''
+m(v) {
+ var b = v as Object;
+}
+''');
+ }
+
+ test_function() async {
+ await assertNoErrorsInCode(r'''
+void main() {
+ Function(Null) f = (String x) => x;
+ (f as Function(int))(3);
+}
+''');
+ }
+
+ test_function2() async {
+ await assertNoErrorsInCode(r'''
+class A {}
+
+class B<T extends A> {
+ void foo() {
+ T Function(T) f;
+ A Function(A) g;
+ g = f as A Function(A);
+ }
+}
+''');
+ }
+
+ test_generics() async {
+ // dartbug.com/18953
+ await assertNoErrorsInCode(r'''
+import 'dart:async';
+Future<int> f() => new Future.value(0);
+void g(bool c) {
+ (c ? f(): new Future.value(0) as Future<int>).then((int value) {});
+}
+''');
+ }
+
+ test_parameter_A() async {
+ // dartbug.com/13855, dartbug.com/13732
+ await assertNoErrorsInCode(r'''
+class A{
+ a() {}
+}
+class B<E> {
+ E e;
+ m() {
+ (e as A).a();
+ }
+}
+''');
+ }
+
+ test_type_dynamic() async {
+ await assertNoErrorsInCode(r'''
+m(v) {
+ var b = Object as dynamic;
+}
+''');
+ }
+
+ test_type_supertype() async {
+ await assertErrorsInCode(r'''
+m(int i) {
+ var b = i as Object;
+}
+''', [HintCode.UNNECESSARY_CAST]);
+ }
+
+ test_type_type() async {
+ await assertErrorsInCode(r'''
+m(num i) {
+ var b = i as num;
+}
+''', [HintCode.UNNECESSARY_CAST]);
+ }
+}
+
+@reflectiveTest
+class UnnecessaryCastTest_Driver extends UnnecessaryCastTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ @override
+ test_generics() async {
+ // dartbug.com/18953
+ assertErrorsInCode(r'''
+import 'dart:async';
+Future<int> f() => new Future.value(0);
+void g(bool c) {
+ (c ? f(): new Future.value(0) as Future<int>).then((int value) {});
+}
+''', [HintCode.UNNECESSARY_CAST]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
new file mode 100644
index 0000000..6a60a1b
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
@@ -0,0 +1,198 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnusedFieldTest);
+ defineReflectiveTests(UnusedFieldTest_Driver);
+ });
+}
+
+@reflectiveTest
+class UnusedFieldTest extends ResolverTestCase {
+ @override
+ bool get enableUnusedElement => true;
+
+ test_unusedField_isUsed_argument() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f = 0;
+ main() {
+ print(++_f);
+ }
+}
+print(x) {}
+''');
+ }
+
+ test_unusedField_isUsed_reference_implicitThis() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f;
+ main() {
+ print(_f);
+ }
+}
+print(x) {}
+''');
+ }
+
+ test_unusedField_isUsed_reference_implicitThis_expressionFunctionBody() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f;
+ m() => _f;
+}
+''');
+ }
+
+ test_unusedField_isUsed_reference_implicitThis_subclass() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f;
+ main() {
+ print(_f);
+ }
+}
+class B extends A {
+ int _f;
+}
+print(x) {}
+''');
+ }
+
+ test_unusedField_isUsed_reference_qualified_propagatedElement() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f;
+}
+main() {
+ var a = new A();
+ print(a._f);
+}
+print(x) {}
+''');
+ }
+
+ test_unusedField_isUsed_reference_qualified_staticElement() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f;
+}
+main() {
+ A a = new A();
+ print(a._f);
+}
+print(x) {}
+''');
+ }
+
+ test_unusedField_isUsed_reference_qualified_unresolved() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _f;
+}
+main(a) {
+ print(a._f);
+}
+print(x) {}
+''');
+ }
+
+ test_unusedField_notUsed_compoundAssign() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f;
+ main() {
+ _f += 2;
+ }
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+
+ test_unusedField_notUsed_constructorFieldInitializers() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f;
+ A() : _f = 0;
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+
+ test_unusedField_notUsed_fieldFormalParameter() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f;
+ A(this._f);
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+
+ test_unusedField_notUsed_noReference() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f;
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+
+ test_unusedField_notUsed_nullAssign() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ var _f;
+ m() {
+ _f ??= doSomething();
+ }
+}
+doSomething() => 0;
+''');
+ }
+
+ test_unusedField_notUsed_postfixExpr() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f = 0;
+ main() {
+ _f++;
+ }
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+
+ test_unusedField_notUsed_prefixExpr() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f = 0;
+ main() {
+ ++_f;
+ }
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+
+ test_unusedField_notUsed_simpleAssignment() async {
+ await assertErrorsInCode(r'''
+class A {
+ int _f;
+ m() {
+ _f = 1;
+ }
+}
+main(A a) {
+ a._f = 2;
+}
+''', [HintCode.UNUSED_FIELD]);
+ }
+}
+
+@reflectiveTest
+class UnusedFieldTest_Driver extends UnusedFieldTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_import_test.dart b/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
new file mode 100644
index 0000000..e930e3e
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
@@ -0,0 +1,321 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnusedImportTest);
+ defineReflectiveTests(UnusedImportTest_Driver);
+ });
+}
+
+@reflectiveTest
+class UnusedImportTest extends ResolverTestCase {
+ test_annotationOnDirective() async {
+ Source source = addSource(r'''
+library L;
+@A()
+import 'lib1.dart';
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {
+ const A() {}
+}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source);
+ verify([source, source2]);
+ }
+
+ test_as() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart';
+import 'lib1.dart' as one;
+one.A a;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_IMPORT]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+
+ test_as_equalPrefixes_referenced() async {
+ // 18818
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' as one;
+import 'lib2.dart' as one;
+one.A a;
+one.B b;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+''');
+ Source source3 = addNamedSource("/lib2.dart", r'''
+library lib2;
+class B {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ await computeAnalysisResult(source3);
+ assertErrors(source);
+ assertNoErrors(source2);
+ assertNoErrors(source3);
+ verify([source, source2, source3]);
+ }
+
+ @failingTest
+ test_as_equalPrefixes_unreferenced() async {
+ // See todo at ImportsVerifier.prefixElementMap.
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' as one;
+import 'lib2.dart' as one;
+one.A a;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+''');
+ Source source3 = addNamedSource("/lib2.dart", r'''
+library lib2;
+class B {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ await computeAnalysisResult(source3);
+ assertErrors(source, [HintCode.UNUSED_IMPORT]);
+ assertNoErrors(source2);
+ assertNoErrors(source3);
+ verify([source, source2, source3]);
+ }
+
+ test_core_library() async {
+ Source source = addSource(r'''
+library L;
+import 'dart:core';
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_export() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart';
+Two two;
+''');
+ addNamedSource("/lib1.dart", r'''
+library lib1;
+export 'lib2.dart';
+class One {}
+''');
+ addNamedSource("/lib2.dart", r'''
+library lib2;
+class Two {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_export2() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart';
+Three three;
+''');
+ addNamedSource("/lib1.dart", r'''
+library lib1;
+export 'lib2.dart';
+class One {}
+''');
+ addNamedSource("/lib2.dart", r'''
+library lib2;
+export 'lib3.dart';
+class Two {}
+''');
+ addNamedSource("/lib3.dart", r'''
+library lib3;
+class Three {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_export_infiniteLoop() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart';
+Two two;
+''');
+ addNamedSource("/lib1.dart", r'''
+library lib1;
+export 'lib2.dart';
+class One {}
+''');
+ addNamedSource("/lib2.dart", r'''
+library lib2;
+export 'lib3.dart';
+class Two {}
+''');
+ addNamedSource("/lib3.dart", r'''
+library lib3;
+export 'lib2.dart';
+class Three {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_hide() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart';
+import 'lib1.dart' hide A;
+A a;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_IMPORT]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+
+ test_inComment_libraryDirective() async {
+ Source source = addSource(r'''
+/// Use [Future] class.
+library L;
+import 'dart:async';
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ }
+
+ test_metadata() async {
+ Source source = addSource(r'''
+library L;
+@A(x)
+import 'lib1.dart';
+class A {
+ final int value;
+ const A(this.value);
+}
+''');
+ addNamedSource("/lib1.dart", r'''
+library lib1;
+const x = 0;
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_prefix_topLevelFunction() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' hide topLevelFunction;
+import 'lib1.dart' as one show topLevelFunction;
+class A {
+ static void x() {
+ One o;
+ one.topLevelFunction();
+ }
+}
+''');
+ addNamedSource("/lib1.dart", r'''
+library lib1;
+class One {}
+topLevelFunction() {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_prefix_topLevelFunction2() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' hide topLevelFunction;
+import 'lib1.dart' as one show topLevelFunction;
+import 'lib1.dart' as two show topLevelFunction;
+class A {
+ static void x() {
+ One o;
+ one.topLevelFunction();
+ two.topLevelFunction();
+ }
+}
+''');
+ addNamedSource("/lib1.dart", r'''
+library lib1;
+class One {}
+topLevelFunction() {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_show() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' show A;
+import 'lib1.dart' show B;
+A a;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+class B {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_IMPORT]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+
+ test_unusedImport() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart';
+''');
+ Source source2 = addNamedSource("/lib1.dart", '''
+library lib1;
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_IMPORT]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+}
+
+@reflectiveTest
+class UnusedImportTest_Driver extends UnusedImportTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_label_test.dart b/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
new file mode 100644
index 0000000..7609554
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnusedLabelTest);
+ defineReflectiveTests(UnusedLabelTest_Driver);
+ });
+}
+
+@reflectiveTest
+class UnusedLabelTest extends ResolverTestCase {
+ test_unused_inSwitch() async {
+ await assertErrorsInCode(r'''
+f(x) {
+ switch (x) {
+ label: case 0:
+ break;
+ default:
+ break;
+ }
+}
+''', [HintCode.UNUSED_LABEL]);
+ }
+
+ test_unused_onWhile() async {
+ await assertErrorsInCode(r'''
+f(condition()) {
+ label: while (condition()) {
+ break;
+ }
+}
+''', [HintCode.UNUSED_LABEL]);
+ }
+
+ test_used_inSwitch() async {
+ await assertNoErrorsInCode(r'''
+f(x) {
+ switch (x) {
+ label: case 0:
+ break;
+ default:
+ continue label;
+ }
+}
+''');
+ }
+
+ test_used_onWhile() async {
+ await assertNoErrorsInCode(r'''
+f(condition()) {
+ label: while (condition()) {
+ break label;
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class UnusedLabelTest_Driver extends UnusedLabelTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart b/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
new file mode 100644
index 0000000..8fba003
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2019, 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:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UnusedShownNameTest);
+ defineReflectiveTests(UnusedShownNameTest_Driver);
+ });
+}
+
+@reflectiveTest
+class UnusedShownNameTest extends ResolverTestCase {
+ test_unreferenced() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' show A, B;
+A a;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+class B {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+
+ test_unusedShownName_as() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' as p show A, B;
+p.A a;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+class B {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+
+ test_unusedShownName_duplicates() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' show A, B;
+import 'lib1.dart' show C, D;
+A a;
+C c;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+class A {}
+class B {}
+class C {}
+class D {}
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(
+ source, [HintCode.UNUSED_SHOWN_NAME, HintCode.UNUSED_SHOWN_NAME]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+
+ test_unusedShownName_topLevelVariable() async {
+ Source source = addSource(r'''
+library L;
+import 'lib1.dart' show var1, var2;
+import 'lib1.dart' show var3, var4;
+int a = var1;
+int b = var2;
+int c = var3;
+''');
+ Source source2 = addNamedSource("/lib1.dart", r'''
+library lib1;
+const int var1 = 1;
+const int var2 = 2;
+const int var3 = 3;
+const int var4 = 4;
+''');
+ await computeAnalysisResult(source);
+ await computeAnalysisResult(source2);
+ assertErrors(source, [HintCode.UNUSED_SHOWN_NAME]);
+ assertNoErrors(source2);
+ verify([source, source2]);
+ }
+}
+
+@reflectiveTest
+class UnusedShownNameTest_Driver extends UnusedShownNameTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
new file mode 100644
index 0000000..f44a502
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, 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:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(UseOfVoidResultTest);
+ defineReflectiveTests(UseOfVoidResultTest_Driver);
+ });
+}
+
+@reflectiveTest
+class UseOfVoidResultTest extends ResolverTestCase {
+ test_implicitReturnValue() async {
+ await assertNoErrorsInCode(r'''
+f() {}
+class A {
+ n() {
+ var a = f();
+ }
+}
+''');
+ }
+
+ test_nonVoidReturnValue() async {
+ await assertNoErrorsInCode(r'''
+int f() => 1;
+g() {
+ var a = f();
+}
+''');
+ }
+}
+
+@reflectiveTest
+class UseOfVoidResultTest_Driver extends UseOfVoidResultTest {
+ @override
+ bool get enableNewAnalysisDriver => true;
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 9267132..69d2215 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -451,6 +451,36 @@
''');
}
+ test_class_constructor_field_formal_functionTyped_noReturnType() async {
+ var library = await checkLibrary(r'''
+class C {
+ var x;
+ C(this.x(double b));
+}
+''');
+ checkElementText(library, r'''
+class C {
+ dynamic x;
+ C((double) → dynamic this.x);
+}
+''');
+ }
+
+ test_class_constructor_field_formal_functionTyped_withReturnType() async {
+ var library = await checkLibrary(r'''
+class C {
+ var x;
+ C(int this.x(double b));
+}
+''');
+ checkElementText(library, r'''
+class C {
+ dynamic x;
+ C((double) → int this.x);
+}
+''');
+ }
+
test_class_constructor_field_formal_multiple_matching_fields() async {
// This is a compile-time error but it should still analyze consistently.
var library = await checkLibrary('class C { C(this.x); int x; String x; }',
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 5554649..71fd7cd 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -100,15 +100,14 @@
List<String> strings: const <String>[],
List<_EntityRefValidator> referenceValidators:
const <_EntityRefValidator>[],
- bool forTypeInferenceOnly: false,
- bool enableSetLiterals: IsEnabledByDefault.set_literals}) {
+ bool forTypeInferenceOnly: false}) {
if (forTypeInferenceOnly && !containsNonConstExprs) {
expect(constExpr, isNull);
return;
}
expect(constExpr, isNotNull);
expect(constExpr.sourceRepresentation,
- _normalizeTokenString(sourceRepresentation, enableSetLiterals));
+ _normalizeTokenString(sourceRepresentation));
expect(constExpr.isValidConst, isValidConst);
expect(constExpr.operations, operators);
expect(constExpr.ints, ints);
@@ -121,29 +120,6 @@
}
}
- String _normalizeTokenString(String tokenString, bool enableSetLiterals) {
- // Note: to normalize the token string it's not sufficient to tokenize it
- // and then pass the tokens to `tokensToString`; we also need to parse it
- // because parsing modifies the token stream (splitting up `[]`, `>>`, and
- // `>>>` tokens when circumstances warrant).
- //
- // We wrap the expression in "f() async => ...;" to ensure that the await
- // keyword is properly parsed.
- var sourceText = 'f() async => $tokenString;';
- var errorListener = AnalysisErrorListener.NULL_LISTENER;
- var reader = new CharSequenceReader(sourceText);
- var stringSource = new StringSource(sourceText, null);
- var scanner = new Scanner(stringSource, reader, errorListener);
- var startToken = scanner.tokenize();
- var parser = new Parser(stringSource, errorListener)
- ..enableSetLiterals = enableSetLiterals;
- var compilationUnit = parser.parseCompilationUnit(startToken);
- var f = compilationUnit.declarations[0] as FunctionDeclaration;
- var body = f.functionExpression.body as ExpressionFunctionBody;
- var expression = body.expression;
- return tokensToString(expression.beginToken, expression.endToken);
- }
-
/**
* Check that [annotations] contains a single entry which is a reference to
* a top level variable called `a` in the current library.
@@ -824,11 +800,8 @@
* with the given [variableName].
*/
UnlinkedVariable serializeVariableText(String text,
- {String variableName: 'v',
- bool allowErrors: false,
- bool enableSetLiterals: IsEnabledByDefault.set_literals}) {
- serializeLibraryText(text,
- allowErrors: allowErrors, enableSetLiterals: enableSetLiterals);
+ {String variableName: 'v', bool allowErrors: false}) {
+ serializeLibraryText(text, allowErrors: allowErrors);
return findVariable(variableName, failIfAbsent: true);
}
@@ -2968,46 +2941,48 @@
}
test_constExpr_makeTypedSet() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = const <int>{11, 22, 33};',
- enableSetLiterals: true);
+ experimentStatus = ExperimentStatus(set_literals: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = const <int>{11, 22, 33};');
assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <int>{11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [11, 22, 33, 3],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
- expectedKind: ReferenceKind.classOrEnum)
- ],
- enableSetLiterals: true);
+ variable.initializer.bodyExpr,
+ 'const <int>{11, 22, 33}',
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeTypedSet
+ ],
+ ints: [11, 22, 33, 3],
+ referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
+ expectedKind: ReferenceKind.classOrEnum)
+ ],
+ );
}
test_constExpr_makeTypedSet_dynamic() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = const <dynamic>{11, 22, 33};',
- enableSetLiterals: true);
+ experimentStatus = ExperimentStatus(set_literals: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = const <dynamic>{11, 22, 33};');
assertUnlinkedConst(
- variable.initializer.bodyExpr, 'const <dynamic>{11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeTypedSet
- ],
- ints: [11, 22, 33, 3],
- referenceValidators: [(EntityRef r) => checkDynamicTypeRef(r)],
- enableSetLiterals: true);
+ variable.initializer.bodyExpr,
+ 'const <dynamic>{11, 22, 33}',
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeTypedSet
+ ],
+ ints: [11, 22, 33, 3],
+ referenceValidators: [(EntityRef r) => checkDynamicTypeRef(r)],
+ );
}
test_constExpr_makeTypedSet_functionType() {
- UnlinkedVariable variable = serializeVariableText(
- 'final v = <void Function(int)>{};',
- enableSetLiterals: true);
+ experimentStatus = ExperimentStatus(set_literals: true);
+ UnlinkedVariable variable =
+ serializeVariableText('final v = <void Function(int)>{};');
assertUnlinkedConst(variable.initializer.bodyExpr, '<void Function(int)>{}',
operators: [UnlinkedExprOperation.makeTypedSet],
ints: [
@@ -3034,9 +3009,9 @@
}
test_constExpr_makeTypedSet_functionType_withTypeParameters() {
+ experimentStatus = ExperimentStatus(set_literals: true);
UnlinkedVariable variable = serializeVariableText(
- 'final v = <void Function<T>(Function<Q>(T, Q))>{};',
- enableSetLiterals: true);
+ 'final v = <void Function<T>(Function<Q>(T, Q))>{};');
assertUnlinkedConst(variable.initializer.bodyExpr,
'<void Function<T>(Function<Q>(T, Q))>{}',
operators: [UnlinkedExprOperation.makeTypedSet],
@@ -3123,18 +3098,20 @@
}
test_constExpr_makeUntypedSet() {
- UnlinkedVariable variable = serializeVariableText(
- 'const v = const {11, 22, 33};',
- enableSetLiterals: true);
- assertUnlinkedConst(variable.initializer.bodyExpr, 'const {11, 22, 33}',
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.makeUntypedSet
- ],
- ints: [11, 22, 33, 3],
- enableSetLiterals: true);
+ experimentStatus = ExperimentStatus(set_literals: true);
+ UnlinkedVariable variable =
+ serializeVariableText('const v = const {11, 22, 33};');
+ assertUnlinkedConst(
+ variable.initializer.bodyExpr,
+ 'const {11, 22, 33}',
+ operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeUntypedSet
+ ],
+ ints: [11, 22, 33, 3],
+ );
}
test_constExpr_parenthesized() {
@@ -7418,9 +7395,9 @@
}
test_expr_makeTypedSet() {
- UnlinkedVariable variable = serializeVariableText(
- 'var v = <int>{11, 22, 33};',
- enableSetLiterals: true);
+ experimentStatus = ExperimentStatus(set_literals: true);
+ UnlinkedVariable variable =
+ serializeVariableText('var v = <int>{11, 22, 33};');
assertUnlinkedConst(variable.initializer.bodyExpr, '<int>{11, 22, 33}',
operators: [UnlinkedExprOperation.makeTypedSet],
ints: [0],
@@ -7428,8 +7405,7 @@
(EntityRef r) => checkTypeRef(r, 'dart:core', 'int',
expectedKind: ReferenceKind.classOrEnum)
],
- forTypeInferenceOnly: true,
- enableSetLiterals: true);
+ forTypeInferenceOnly: true);
}
test_expr_makeUntypedList() {
@@ -7465,8 +7441,8 @@
}
test_expr_makeUntypedSet() {
- UnlinkedVariable variable =
- serializeVariableText('var v = {11, 22, 33};', enableSetLiterals: true);
+ experimentStatus = ExperimentStatus(set_literals: true);
+ UnlinkedVariable variable = serializeVariableText('var v = {11, 22, 33};');
assertUnlinkedConst(variable.initializer.bodyExpr, '{11, 22, 33}',
operators: [
UnlinkedExprOperation.pushInt,
@@ -7475,8 +7451,7 @@
UnlinkedExprOperation.makeUntypedSet
],
ints: [11, 22, 33, 3],
- forTypeInferenceOnly: true,
- enableSetLiterals: true);
+ forTypeInferenceOnly: true);
}
test_expr_super() {
@@ -10784,6 +10759,30 @@
],
forTypeInferenceOnly: true);
}
+
+ String _normalizeTokenString(String tokenString) {
+ // Note: to normalize the token string it's not sufficient to tokenize it
+ // and then pass the tokens to `tokensToString`; we also need to parse it
+ // because parsing modifies the token stream (splitting up `[]`, `>>`, and
+ // `>>>` tokens when circumstances warrant).
+ //
+ // We wrap the expression in "f() async => ...;" to ensure that the await
+ // keyword is properly parsed.
+ var sourceText = 'f() async => $tokenString;';
+ var errorListener = AnalysisErrorListener.NULL_LISTENER;
+ var reader = new CharSequenceReader(sourceText);
+ var stringSource = new StringSource(sourceText, null);
+ var scanner = new Scanner(stringSource, reader, errorListener);
+ var startToken = scanner.tokenize();
+ var parser = new Parser(stringSource, errorListener)
+ ..enableSetLiterals = experimentStatus.set_literals
+ ..enableNonNullable = experimentStatus.non_nullable;
+ var compilationUnit = parser.parseCompilationUnit(startToken);
+ var f = compilationUnit.declarations[0] as FunctionDeclaration;
+ var body = f.functionExpression.body as ExpressionFunctionBody;
+ var expression = body.expression;
+ return tokensToString(expression.beginToken, expression.endToken);
+ }
}
/**
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index 5cab182..fe525e0 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -22,7 +22,6 @@
import 'package:analyzer/src/summary/prelink.dart';
import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
-import 'package:analyzer/src/task/api/dart.dart';
import 'package:analyzer/src/task/api/general.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:path/path.dart' show posix;
@@ -36,15 +35,19 @@
return posix.toUri(absolutePath).toString();
}
-CompilationUnit _parseText(String text,
- {bool enableSetLiterals: IsEnabledByDefault.set_literals}) {
+CompilationUnit _parseText(
+ String text, {
+ ExperimentStatus experimentStatus,
+}) {
+ experimentStatus ??= ExperimentStatus();
CharSequenceReader reader = new CharSequenceReader(text);
Scanner scanner =
new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER);
Token token = scanner.tokenize();
Parser parser =
new Parser(NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
- ..enableSetLiterals = enableSetLiterals;
+ ..enableSetLiterals = experimentStatus.set_literals
+ ..enableNonNullable = experimentStatus.non_nullable;
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = new LineInfo(scanner.lineStarts);
return unit;
@@ -91,8 +94,8 @@
/// The tests themselves can then be provided via mixin, allowing summaries to
/// be tested in a variety of ways.
abstract class ResynthesizeTestStrategy {
- //Future<LibraryElementImpl> checkLibrary(String text,
- // {bool allowErrors: false, bool dumpSummaries: false});
+ /// The set of [ExperimentStatus] enabled in this test.
+ ExperimentStatus experimentStatus;
void set allowMissingFiles(bool value);
@@ -124,6 +127,9 @@
/// generation using the old two-phase API.
class ResynthesizeTestStrategyTwoPhase extends AbstractResynthesizeTest
implements ResynthesizeTestStrategy {
+ @override
+ ExperimentStatus experimentStatus = ExperimentStatus();
+
final Set<Source> serializedSources = new Set<Source>();
final Map<String, UnlinkedUnitBuilder> uriToUnit =
@@ -206,7 +212,10 @@
}
return null;
}
- CompilationUnit unit = context.computeResult(source, PARSED_UNIT);
+
+ String contents = context.getContents(source).data;
+ CompilationUnit unit = _parseText(contents);
+
UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
return unlinkedUnit;
@@ -285,6 +294,9 @@
/// The tests themselves can then be provided via mixin, allowing summaries to
/// be tested in a variety of ways.
abstract class SummaryBaseTestStrategy {
+ /// The set of [ExperimentStatus] enabled in this test.
+ ExperimentStatus experimentStatus;
+
/// Add the given package bundle as a dependency so that it may be referenced
/// by the files under test.
void addBundle(String path, PackageBundle bundle);
@@ -332,9 +344,7 @@
/// Serialize the given library [text], then deserialize it and store its
/// summary in [lib].
- void serializeLibraryText(String text,
- {bool allowErrors: false,
- bool enableSetLiterals: IsEnabledByDefault.set_literals});
+ void serializeLibraryText(String text, {bool allowErrors: false});
}
/// Implementation of [SummaryBlackBoxTestStrategy] that drives summary
@@ -346,11 +356,8 @@
bool get skipFullyLinkedData => true;
@override
- void serializeLibraryText(String text,
- {bool allowErrors: false,
- bool enableSetLiterals: IsEnabledByDefault.set_literals}) {
- super.serializeLibraryText(text,
- allowErrors: allowErrors, enableSetLiterals: enableSetLiterals);
+ void serializeLibraryText(String text, {bool allowErrors: false}) {
+ super.serializeLibraryText(text, allowErrors: allowErrors);
UnlinkedUnit getPart(String absoluteUri) {
return _linkerInputs.getUnit(absoluteUri);
@@ -507,6 +514,9 @@
_FilesToLink<UnlinkedUnitBuilder> _filesToLink =
new _FilesToLink<UnlinkedUnitBuilder>();
+ @override
+ ExperimentStatus experimentStatus = ExperimentStatus();
+
_LinkerInputs _linkerInputs;
bool get _allowMissingFiles;
@@ -541,20 +551,16 @@
return assembler.assemble();
}
- UnlinkedUnitBuilder createUnlinkedSummary(Uri uri, String text,
- {bool enableSetLiterals: IsEnabledByDefault.set_literals}) =>
+ UnlinkedUnitBuilder createUnlinkedSummary(Uri uri, String text) =>
serializeAstUnlinked(
- _parseText(text, enableSetLiterals: enableSetLiterals));
+ _parseText(text, experimentStatus: experimentStatus));
_LinkerInputs _createLinkerInputs(String text,
- {String path: '/test.dart',
- String uri,
- bool enableSetLiterals: IsEnabledByDefault.set_literals}) {
+ {String path: '/test.dart', String uri}) {
uri ??= absUri(path);
Uri testDartUri = Uri.parse(uri);
- UnlinkedUnitBuilder unlinkedDefiningUnit = createUnlinkedSummary(
- testDartUri, text,
- enableSetLiterals: enableSetLiterals);
+ UnlinkedUnitBuilder unlinkedDefiningUnit =
+ createUnlinkedSummary(testDartUri, text);
_filesToLink.uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit;
_LinkerInputs linkerInputs = new _LinkerInputs(
_allowMissingFiles,
@@ -573,7 +579,7 @@
/// generation using the old two-phase API.
///
/// Not intended to be used directly; instead use a derived class that either
-/// exercises the full summary algorithmm or just pre-linking.
+/// exercises the full summary algorithm or just pre-linking.
abstract class _SummaryBlackBoxTestStrategyTwoPhase
extends _SummaryBaseTestStrategyTwoPhase
implements SummaryBlackBoxTestStrategy {
@@ -595,12 +601,9 @@
bool get containsNonConstExprs => true;
@override
- void serializeLibraryText(String text,
- {bool allowErrors: false,
- bool enableSetLiterals: IsEnabledByDefault.set_literals}) {
+ void serializeLibraryText(String text, {bool allowErrors: false}) {
Map<String, UnlinkedUnitBuilder> uriToUnit = this._filesToLink.uriToUnit;
- _linkerInputs =
- _createLinkerInputs(text, enableSetLiterals: enableSetLiterals);
+ _linkerInputs = _createLinkerInputs(text);
linked = link(
_linkerInputs.linkedLibraries,
_linkerInputs.getDependency,
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 645c950..cd1e370 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -69,8 +69,8 @@
new TestSource(), 0, 1, HintCode.UNUSED_LOCAL_VARIABLE, [
['x']
]);
- var invalid_assignment =
- new AnalysisError(new TestSource(), 0, 1, HintCode.INVALID_ASSIGNMENT, [
+ var invalid_assignment = new AnalysisError(
+ new TestSource(), 0, 1, StaticTypeWarningCode.INVALID_ASSIGNMENT, [
['x'],
['y']
]);
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 2991634..51c6016 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,9 +18,75 @@
defineReflectiveSuite(() {
defineReflectiveTests(InferredTypeTest);
defineReflectiveTests(InferredTypeTest_Driver);
+ defineReflectiveTests(InferredTypeTest_SetLiterals);
});
}
+@reflectiveTest
+class InferredTypeTest extends AbstractStrongTest with InferredTypeMixin {
+ @override
+ bool get mayCheckTypesOfLocals => true;
+
+ @override
+ Future<CompilationUnitElement> checkFileElement(String content) async {
+ CompilationUnit unit = await checkFile(content);
+ return unit.declaredElement;
+ }
+
+ @override
+ @failingTest
+ test_circularReference_viaClosures() {
+ return super.test_circularReference_viaClosures();
+ }
+
+ @override
+ @failingTest
+ test_circularReference_viaClosures_initializerTypes() {
+ return super.test_circularReference_viaClosures_initializerTypes();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_typeName_error1() {
+ // Test doesn't work with the old task model
+ return super.test_instantiateToBounds_typeName_error1();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_typeName_error2() {
+ // Test doesn't work with the old task model
+ return super.test_instantiateToBounds_typeName_error2();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_typeName_error3() {
+ // Test doesn't work with the old task model
+ return super.test_instantiateToBounds_typeName_error3();
+ }
+
+ @override
+ @failingTest
+ test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
+ return super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
+ }
+
+ @override
+ @failingTest
+ test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
+ return super
+ .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
+ }
+
+ @failingTest
+ @override
+ test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
+ return super
+ .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
+ }
+}
+
mixin InferredTypeMixin {
/// Extra top-level errors if needed due to being analyze multiple times.
bool get hasExtraTaskModelPass => true;
@@ -1504,7 +1571,7 @@
Iterable<Map<int, int>> bar() sync* {
yield /*info:INFERRED_TYPE_LITERAL*/{};
yield /*error:YIELD_OF_INVALID_TYPE*/new List();
- yield* {};
+ yield* /*error:YIELD_OF_INVALID_TYPE*/{};
yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
}
''');
@@ -2229,8 +2296,8 @@
test_infer_assignToProperty_custom() async {
await checkFileElement(r'''
class A {
- int operator +(other) => 1;
- double operator -(other) => 2.0;
+ A operator +(other) => this;
+ A operator -(other) => this;
}
class B {
A a;
@@ -4391,71 +4458,6 @@
}
@reflectiveTest
-class InferredTypeTest extends AbstractStrongTest with InferredTypeMixin {
- @override
- bool get mayCheckTypesOfLocals => true;
-
- @override
- Future<CompilationUnitElement> checkFileElement(String content) async {
- CompilationUnit unit = await checkFile(content);
- return unit.declaredElement;
- }
-
- @override
- @failingTest
- test_circularReference_viaClosures() {
- return super.test_circularReference_viaClosures();
- }
-
- @override
- @failingTest
- test_circularReference_viaClosures_initializerTypes() {
- return super.test_circularReference_viaClosures_initializerTypes();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_error1() {
- // Test doesn't work with the old task model
- return super.test_instantiateToBounds_typeName_error1();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_error2() {
- // Test doesn't work with the old task model
- return super.test_instantiateToBounds_typeName_error2();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_error3() {
- // Test doesn't work with the old task model
- return super.test_instantiateToBounds_typeName_error3();
- }
-
- @override
- @failingTest
- test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
- return super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
- }
-
- @override
- @failingTest
- test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
- return super
- .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
- }
-
- @failingTest
- @override
- test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
- return super
- .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
- }
-}
-
-@reflectiveTest
class InferredTypeTest_Driver extends AbstractStrongTest
with InferredTypeMixin {
@override
@@ -4487,3 +4489,66 @@
.test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
}
}
+
+@reflectiveTest
+class InferredTypeTest_SetLiterals extends AbstractStrongTest
+ with InferredTypeMixin {
+ @override
+ List<String> get enabledExperiments => [EnableString.set_literals];
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ @override
+ bool get hasExtraTaskModelPass => false;
+
+ @override
+ bool get mayCheckTypesOfLocals => true;
+
+ @override
+ Future<CompilationUnitElement> checkFileElement(String content) async {
+ CompilationUnit unit = await checkFile(content);
+ return unit.declaredElement;
+ }
+
+ @override
+ test_downwardsInferenceYieldYieldStar() async {
+ // The fifth to last case is inferred differently with set_literals enabled,
+ // and no longer an error compared to the base implementation.
+ await checkFileElement('''
+import 'dart:async';
+
+abstract class MyStream<T> extends Stream<T> {
+ factory MyStream() => null;
+}
+
+Stream<List<int>> foo() async* {
+ yield /*info:INFERRED_TYPE_LITERAL*/[];
+ yield /*error:YIELD_OF_INVALID_TYPE*/new MyStream();
+ yield* /*error:YIELD_OF_INVALID_TYPE*/[];
+ yield* /*info:INFERRED_TYPE_ALLOCATION*/new MyStream();
+}
+
+Iterable<Map<int, int>> bar() sync* {
+ yield /*info:INFERRED_TYPE_LITERAL*/{};
+ yield /*error:YIELD_OF_INVALID_TYPE*/new List();
+ yield* {};
+ yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
+}
+''');
+ }
+
+ @failingTest
+ @override
+ test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
+ return super
+ .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
+ }
+
+ @failingTest
+ @override
+ test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
+ return super
+ .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
+ }
+}
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index c9c3fcf..521f759 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -245,6 +245,8 @@
bool get enableNewAnalysisDriver => false;
+ List<String> get enabledExperiments => [];
+
/// Adds a file to check. The file should contain:
///
/// * all expected failures are listed in the source code using comments
@@ -286,6 +288,7 @@
analysisOptions.strongModeHints = true;
analysisOptions.implicitCasts = implicitCasts;
analysisOptions.implicitDynamic = implicitDynamic;
+ analysisOptions.enabledExperiments = enabledExperiments;
var mockSdk = new MockSdk(resourceProvider: resourceProvider);
mockSdk.context.analysisOptions = analysisOptions;
diff --git a/pkg/analyzer/test/src/workspace/basic_test.dart b/pkg/analyzer/test/src/workspace/basic_test.dart
index 1abdbc9..6df62db 100644
--- a/pkg/analyzer/test/src/workspace/basic_test.dart
+++ b/pkg/analyzer/test/src/workspace/basic_test.dart
@@ -30,13 +30,40 @@
main() {
defineReflectiveSuite(() {
- // TODO(srawlins): Write a BasicWorkspaceTest akin to
- // PackageBuildWorkspaceTest.
+ defineReflectiveTests(BasicWorkspaceTest);
defineReflectiveTests(BasicWorkspacePackageTest);
});
}
@reflectiveTest
+class BasicWorkspaceTest with ResourceProviderMixin {
+ setUp() {
+ newFolder('/workspace');
+ }
+
+ void test_find_fail_notAbsolute() {
+ expect(
+ () => BasicWorkspace.find(resourceProvider, convertPath('not_absolute'),
+ new MockContextBuilder()),
+ throwsA(TypeMatcher<ArgumentError>()));
+ }
+
+ void test_find_directory() {
+ BasicWorkspace workspace = BasicWorkspace.find(
+ resourceProvider, convertPath('/workspace'), new MockContextBuilder());
+ expect(workspace.root, convertPath('/workspace'));
+ }
+
+ void test_find_file() {
+ BasicWorkspace workspace = BasicWorkspace.find(
+ resourceProvider,
+ convertPath('/workspace/project/lib/lib1.dart'),
+ new MockContextBuilder());
+ expect(workspace.root, convertPath('/workspace/project/lib'));
+ }
+}
+
+@reflectiveTest
class BasicWorkspacePackageTest with ResourceProviderMixin {
BasicWorkspace workspace;
@@ -47,7 +74,7 @@
contextBuilder.packagesMapMap[convertPath('/workspace')] = packages;
contextBuilder.packagesToMapMap[packages] = packageMap;
- newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ newFolder('/workspace');
workspace = BasicWorkspace.find(
resourceProvider, convertPath('/workspace'), contextBuilder);
}
diff --git a/pkg/analyzer/test/src/workspace/gn_test.dart b/pkg/analyzer/test/src/workspace/gn_test.dart
index bc75f28..8cd0a5b 100644
--- a/pkg/analyzer/test/src/workspace/gn_test.dart
+++ b/pkg/analyzer/test/src/workspace/gn_test.dart
@@ -182,6 +182,7 @@
newFile('/ws/.config',
content: 'FOO=foo\n' + 'FUCHSIA_BUILD_DIR="$buildDir"\n' + 'BAR=bar\n');
newFile('/ws/out/debug-x87_128/dartlang/gen/some/code/foo.packages');
+ newFolder('/ws/some/code');
return GnWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
}
diff --git a/pkg/analyzer/test/src/workspace/pub_test.dart b/pkg/analyzer/test/src/workspace/pub_test.dart
new file mode 100644
index 0000000..48d88d6
--- /dev/null
+++ b/pkg/analyzer/test/src/workspace/pub_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2019, 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:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/workspace/pub.dart';
+import 'package:package_config/packages.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(PubWorkspacePackageTest);
+ defineReflectiveTests(PubWorkspaceTest);
+ });
+}
+
+class MockContextBuilder implements ContextBuilder {
+ Map<String, Packages> packagesMapMap = <String, Packages>{};
+ Map<Packages, Map<String, List<Folder>>> packagesToMapMap =
+ <Packages, Map<String, List<Folder>>>{};
+
+ Map<String, List<Folder>> convertPackagesToMap(Packages packages) =>
+ packagesToMapMap[packages];
+
+ Packages createPackageMap(String rootDirectoryPath) =>
+ packagesMapMap[rootDirectoryPath];
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockPackages implements Packages {
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+@reflectiveTest
+class PubWorkspacePackageTest with ResourceProviderMixin {
+ PubWorkspace workspace;
+
+ setUp() {
+ final contextBuilder = new MockContextBuilder();
+ final packages = new MockPackages();
+ final packageMap = <String, List<Folder>>{'project': []};
+ contextBuilder.packagesMapMap[convertPath('/workspace')] = packages;
+ contextBuilder.packagesToMapMap[packages] = packageMap;
+
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ workspace = PubWorkspace.find(
+ resourceProvider, convertPath('/workspace'), contextBuilder);
+ }
+
+ void test_findPackageFor_unrelatedFile() {
+ newFile('/workspace/project/lib/file.dart');
+
+ var package = workspace
+ .findPackageFor(convertPath('/workspace2/project/lib/file.dart'));
+ expect(package, isNull);
+ }
+
+ void test_findPackageFor_includedFile() {
+ newFile('/workspace/project/lib/file.dart');
+
+ var package = workspace
+ .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
+ expect(package, isNotNull);
+ expect(package.root, convertPath('/workspace'));
+ expect(package.workspace, equals(workspace));
+ }
+
+ void test_contains_differentWorkspace() {
+ newFile('/workspace2/project/lib/file.dart');
+
+ var package = workspace
+ .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+ expect(package.contains('/workspace2/project/lib/file.dart'), isFalse);
+ }
+
+ void test_contains_sameWorkspace() {
+ newFile('/workspace/project/lib/file2.dart');
+
+ var package = workspace
+ .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+ expect(package.contains('/workspace/project/lib/file2.dart'), isTrue);
+ expect(package.contains('/workspace/project/bin/bin.dart'), isTrue);
+ expect(package.contains('/workspace/project/test/test.dart'), isTrue);
+ }
+}
+
+@reflectiveTest
+class PubWorkspaceTest with ResourceProviderMixin {
+ void test_find_fail_notAbsolute() {
+ expect(
+ () => PubWorkspace.find(resourceProvider, convertPath('not_absolute'),
+ new MockContextBuilder()),
+ throwsA(TypeMatcher<ArgumentError>()));
+ }
+
+ void test_find_missingPubspec() {
+ PubWorkspace workspace = PubWorkspace.find(resourceProvider,
+ convertPath('/workspace/lib/lib1.dart'), new MockContextBuilder());
+ expect(workspace, isNull);
+ }
+
+ void test_find_directory() {
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ PubWorkspace workspace = PubWorkspace.find(
+ resourceProvider, convertPath('/workspace'), new MockContextBuilder());
+ expect(workspace.root, convertPath('/workspace'));
+ }
+
+ void test_find_file() {
+ newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
+ PubWorkspace workspace = PubWorkspace.find(resourceProvider,
+ convertPath('/workspace/lib/lib1.dart'), new MockContextBuilder());
+ expect(workspace.root, convertPath('/workspace'));
+ }
+}
diff --git a/pkg/analyzer/test/src/workspace/test_all.dart b/pkg/analyzer/test/src/workspace/test_all.dart
index 351175b..c2e0512 100644
--- a/pkg/analyzer/test/src/workspace/test_all.dart
+++ b/pkg/analyzer/test/src/workspace/test_all.dart
@@ -4,12 +4,14 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'basic_test.dart' as basic_test;
import 'bazel_test.dart' as bazel_test;
import 'gn_test.dart' as gn_test;
import 'package_build_test.dart' as package_build_test;
main() {
defineReflectiveSuite(() {
+ basic_test.main();
bazel_test.main();
gn_test.main();
package_build_test.main();
diff --git a/pkg/analyzer/lib/src/test_utilities/ast_type_matchers.dart b/pkg/analyzer/test/util/ast_type_matchers.dart
similarity index 100%
rename from pkg/analyzer/lib/src/test_utilities/ast_type_matchers.dart
rename to pkg/analyzer/test/util/ast_type_matchers.dart
diff --git a/pkg/analyzer/lib/src/test_utilities/element_type_matchers.dart b/pkg/analyzer/test/util/element_type_matchers.dart
similarity index 100%
rename from pkg/analyzer/lib/src/test_utilities/element_type_matchers.dart
rename to pkg/analyzer/test/util/element_type_matchers.dart
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 6ab809c..0d84b98 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1004,6 +1004,12 @@
is only defined if the displayed text should be different than the
completion. Otherwise it is omitted.
</p>
+ </dd><dt class="field"><b>elementUri: String<span style="color:#999999"> (optional)</span></b></dt><dd>
+
+ <p>
+ The URI of the element corresponding to this suggestion. It will be
+ set whenever analysis server is able to compute it.
+ </p>
</dd><dt class="field"><b>selectionOffset: int</b></dt><dd>
<p>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 596aa9e..b7718d7 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -598,6 +598,7 @@
* "relevance": int
* "completion": String
* "displayText": optional String
+ * "elementUri": optional String
* "selectionOffset": int
* "selectionLength": int
* "isDeprecated": bool
@@ -629,6 +630,8 @@
String _displayText;
+ String _elementUri;
+
int _selectionOffset;
int _selectionLength;
@@ -729,6 +732,20 @@
}
/**
+ * The URI of the element corresponding to this suggestion. It will be set
+ * whenever analysis server is able to compute it.
+ */
+ String get elementUri => _elementUri;
+
+ /**
+ * The URI of the element corresponding to this suggestion. It will be set
+ * whenever analysis server is able to compute it.
+ */
+ void set elementUri(String value) {
+ this._elementUri = value;
+ }
+
+ /**
* The offset, relative to the beginning of the completion, of where the
* selection should be placed after insertion.
*/
@@ -1003,6 +1020,7 @@
bool isDeprecated,
bool isPotential,
{String displayText,
+ String elementUri,
String docSummary,
String docComplete,
String declaringType,
@@ -1021,6 +1039,7 @@
this.relevance = relevance;
this.completion = completion;
this.displayText = displayText;
+ this.elementUri = elementUri;
this.selectionOffset = selectionOffset;
this.selectionLength = selectionLength;
this.isDeprecated = isDeprecated;
@@ -1073,6 +1092,11 @@
displayText = jsonDecoder.decodeString(
jsonPath + ".displayText", json["displayText"]);
}
+ String elementUri;
+ if (json.containsKey("elementUri")) {
+ elementUri = jsonDecoder.decodeString(
+ jsonPath + ".elementUri", json["elementUri"]);
+ }
int selectionOffset;
if (json.containsKey("selectionOffset")) {
selectionOffset = jsonDecoder.decodeInt(
@@ -1178,6 +1202,7 @@
return new CompletionSuggestion(kind, relevance, completion,
selectionOffset, selectionLength, isDeprecated, isPotential,
displayText: displayText,
+ elementUri: elementUri,
docSummary: docSummary,
docComplete: docComplete,
declaringType: declaringType,
@@ -1206,6 +1231,9 @@
if (displayText != null) {
result["displayText"] = displayText;
}
+ if (elementUri != null) {
+ result["elementUri"] = elementUri;
+ }
result["selectionOffset"] = selectionOffset;
result["selectionLength"] = selectionLength;
result["isDeprecated"] = isDeprecated;
@@ -1265,6 +1293,7 @@
relevance == other.relevance &&
completion == other.completion &&
displayText == other.displayText &&
+ elementUri == other.elementUri &&
selectionOffset == other.selectionOffset &&
selectionLength == other.selectionLength &&
isDeprecated == other.isDeprecated &&
@@ -1297,6 +1326,7 @@
hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
hash = JenkinsSmiHash.combine(hash, completion.hashCode);
hash = JenkinsSmiHash.combine(hash, displayText.hashCode);
+ hash = JenkinsSmiHash.combine(hash, elementUri.hashCode);
hash = JenkinsSmiHash.combine(hash, selectionOffset.hashCode);
hash = JenkinsSmiHash.combine(hash, selectionLength.hashCode);
hash = JenkinsSmiHash.combine(hash, isDeprecated.hashCode);
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 820f31e..d95c14d 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -134,6 +134,7 @@
* "relevance": int
* "completion": String
* "displayText": optional String
+ * "elementUri": optional String
* "selectionOffset": int
* "selectionLength": int
* "isDeprecated": bool
@@ -165,6 +166,7 @@
"isPotential": isBool
}, optionalFields: {
"displayText": isString,
+ "elementUri": isString,
"docSummary": isString,
"docComplete": isString,
"declaringType": isString,
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index ed8daca..d12b351 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -206,6 +206,13 @@
completion. Otherwise it is omitted.
</p>
</field>
+ <field name="elementUri" optional="true">
+ <ref>String</ref>
+ <p>
+ The URI of the element corresponding to this suggestion. It will be
+ set whenever analysis server is able to compute it.
+ </p>
+ </field>
<field name="selectionOffset">
<ref>int</ref>
<p>
diff --git a/pkg/compiler/analysis_options.yaml b/pkg/compiler/analysis_options.yaml
index 3400954..af22f6b 100644
--- a/pkg/compiler/analysis_options.yaml
+++ b/pkg/compiler/analysis_options.yaml
@@ -5,4 +5,8 @@
analyzer:
errors:
todo: ignore
+ # Allow cross-package deprecated calls
+ # TODO(srawlins): clean these up and remove this "ignore."
deprecated_member_use: ignore
+ # Allow deprecated calls from within the same package
+ deprecated_member_use_from_same_package: ignore
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 0c79da0..11816ed 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -13,57 +13,51 @@
// Unless explicitly allowed, passing [:null:] for any argument to the
// methods of library will result in an Error being thrown.
-/**
- * Returns a future that completes to the source corresponding to [uri].
- * If an exception occurs, the future completes with this exception.
- *
- * The source can be represented either as a [:List<int>:] of UTF-8 bytes or as
- * a [String].
- *
- * The following text is non-normative:
- *
- * It is recommended to return a UTF-8 encoded list of bytes because the scanner
- * is more efficient in this case. In either case, the data structure is
- * expected to hold a zero element at the last position. If this is not the
- * case, the entire data structure is copied before scanning.
- */
+/// Returns a future that completes to the source corresponding to [uri].
+/// If an exception occurs, the future completes with this exception.
+///
+/// The source can be represented either as a [:List<int>:] of UTF-8 bytes or as
+/// a [String].
+///
+/// The following text is non-normative:
+///
+/// It is recommended to return a UTF-8 encoded list of bytes because the
+/// scanner is more efficient in this case. In either case, the data structure
+/// is expected to hold a zero element at the last position. If this is not the
+/// case, the entire data structure is copied before scanning.
typedef Future /* <String | List<int>> */ CompilerInputProvider(Uri uri);
/// Deprecated, please use [CompilerInputProvider] instead.
typedef Future<String> ReadStringFromUri(Uri uri);
-/**
- * Returns an [EventSink] that will serve as compiler output for the given
- * component.
- *
- * Components are identified by [name] and [extension]. By convention,
- * the empty string [:"":] will represent the main script
- * (corresponding to the script parameter of [compile]) even if the
- * main script is a library. For libraries that are compiled
- * separately, the library name is used.
- *
- * At least the following extensions can be expected:
- *
- * * "js" for JavaScript output.
- * * "js.map" for source maps.
- * * "dart" for Dart output.
- * * "dart.map" for source maps.
- *
- * As more features are added to the compiler, new names and
- * extensions may be introduced.
- */
+/// Returns an [EventSink] that will serve as compiler output for the given
+/// component.
+///
+/// Components are identified by [name] and [extension]. By convention,
+/// the empty string [:"":] will represent the main script
+/// (corresponding to the script parameter of [compile]) even if the
+/// main script is a library. For libraries that are compiled
+/// separately, the library name is used.
+///
+/// At least the following extensions can be expected:
+///
+/// * "js" for JavaScript output.
+/// * "js.map" for source maps.
+/// * "dart" for Dart output.
+/// * "dart.map" for source maps.
+///
+/// As more features are added to the compiler, new names and
+/// extensions may be introduced.
typedef EventSink<String> CompilerOutputProvider(String name, String extension);
-/**
- * Invoked by the compiler to report diagnostics. If [uri] is
- * [:null:], so are [begin] and [end]. No other arguments may be
- * [:null:]. If [uri] is not [:null:], neither are [begin] and
- * [end]. [uri] indicates the compilation unit from where the
- * diagnostic originates. [begin] and [end] are zero-based character
- * offsets from the beginning of the compilation unit. [message] is the
- * diagnostic message, and [kind] indicates indicates what kind of
- * diagnostic it is.
- */
+/// Invoked by the compiler to report diagnostics. If [uri] is
+/// [:null:], so are [begin] and [end]. No other arguments may be
+/// [:null:]. If [uri] is not [:null:], neither are [begin] and
+/// [end]. [uri] indicates the compilation unit from where the
+/// diagnostic originates. [begin] and [end] are zero-based character
+/// offsets from the beginning of the compilation unit. [message] is the
+/// diagnostic message, and [kind] indicates indicates what kind of
+/// diagnostic it is.
typedef void DiagnosticHandler(
Uri uri, int begin, int end, String message, Diagnostic kind);
@@ -82,21 +76,19 @@
CompilationResult(this.compiler, {this.isSuccess: true});
}
-/**
- * Returns a future that completes to a non-null String when [script]
- * has been successfully compiled.
- *
- * The compiler output is obtained by providing an [outputProvider].
- *
- * If the compilation fails, the future's value will be [:null:] and
- * [handler] will have been invoked at least once with [:kind ==
- * Diagnostic.ERROR:] or [:kind == Diagnostic.CRASH:].
- *
- * Deprecated: if no [outputProvider] is given, the future completes
- * to the compiled script. This behavior will be removed in the future
- * as the compiler may create multiple files to support lazy loading
- * of libraries.
- */
+/// Returns a future that completes to a non-null String when [script]
+/// has been successfully compiled.
+///
+/// The compiler output is obtained by providing an [outputProvider].
+///
+/// If the compilation fails, the future's value will be [:null:] and
+/// [handler] will have been invoked at least once with [:kind ==
+/// Diagnostic.ERROR:] or [:kind == Diagnostic.CRASH:].
+///
+/// Deprecated: if no [outputProvider] is given, the future completes
+/// to the compiled script. This behavior will be removed in the future
+/// as the compiler may create multiple files to support lazy loading
+/// of libraries.
Future<CompilationResult> compile(
Uri script,
Uri librariesSpecificationUri,
@@ -128,74 +120,54 @@
});
}
-/**
- * Kind of diagnostics that the compiler can report.
- */
+/// Kind of diagnostics that the compiler can report.
class Diagnostic {
- /**
- * An error as identified by the "Dart Programming Language
- * Specification" [http://www.dartlang.org/docs/spec/].
- *
- * Note: the compiler may still produce an executable result after
- * reporting a compilation error. The specification says:
- *
- * "A compile-time error must be reported by a Dart compiler before
- * the erroneous code is executed." and "If a compile-time error
- * occurs within the code of a running isolate A, A is immediately
- * suspended."
- *
- * This means that the compiler can generate code that when executed
- * terminates execution.
- */
+ /// An error as identified by the "Dart Programming Language
+ /// Specification" [http://www.dartlang.org/docs/spec/].
+ ///
+ /// Note: the compiler may still produce an executable result after
+ /// reporting a compilation error. The specification says:
+ ///
+ /// "A compile-time error must be reported by a Dart compiler before
+ /// the erroneous code is executed." and "If a compile-time error
+ /// occurs within the code of a running isolate A, A is immediately
+ /// suspended."
+ ///
+ /// This means that the compiler can generate code that when executed
+ /// terminates execution.
static const Diagnostic ERROR = const Diagnostic(1, 'error');
- /**
- * A warning as identified by the "Dart Programming Language
- * Specification" [http://www.dartlang.org/docs/spec/].
- */
+ /// A warning as identified by the "Dart Programming Language
+ /// Specification" [http://www.dartlang.org/docs/spec/].
static const Diagnostic WARNING = const Diagnostic(2, 'warning');
- /**
- * Any other warning that is not covered by [WARNING].
- */
+ /// Any other warning that is not covered by [WARNING].
static const Diagnostic HINT = const Diagnostic(4, 'hint');
- /**
- * Additional information about the preceding non-info diagnostic from the
- * compiler.
- *
- * For example, consider a duplicated definition. The compiler first emits a
- * message about the duplicated definition, then emits an info message about
- * the location of the existing definition.
- */
+ /// Additional information about the preceding non-info diagnostic from the
+ /// compiler.
+ ///
+ /// For example, consider a duplicated definition. The compiler first emits a
+ /// message about the duplicated definition, then emits an info message about
+ /// the location of the existing definition.
static const Diagnostic INFO = const Diagnostic(8, 'info');
- /**
- * Informational messages that shouldn't be printed unless
- * explicitly requested by the user of a compiler.
- */
+ /// Informational messages that shouldn't be printed unless
+ /// explicitly requested by the user of a compiler.
static const Diagnostic VERBOSE_INFO = const Diagnostic(16, 'verbose info');
- /**
- * An internal error in the compiler.
- */
+ /// An internal error in the compiler.
static const Diagnostic CRASH = const Diagnostic(32, 'crash');
- /**
- * An [int] representation of this kind. The ordinals are designed
- * to be used as bitsets.
- */
+ /// An [int] representation of this kind. The ordinals are designed
+ /// to be used as bitsets.
final int ordinal;
- /**
- * The name of this kind.
- */
+ /// The name of this kind.
final String name;
- /**
- * This constructor is not private to support user-defined
- * diagnostic kinds.
- */
+ /// This constructor is not private to support user-defined
+ /// diagnostic kinds.
const Diagnostic(this.ordinal, this.name);
String toString() => name;
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 1ead006..991fb58 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -43,6 +43,8 @@
static const String experimentCallInstrumentation =
'--experiment-call-instrumentation';
+ static const String enableLanguageExperiments = '--enable-experiment';
+
static const String fastStartup = '--fast-startup';
static const String fatalWarnings = '--fatal-warnings';
static const String generateCodeWithCompileTimeErrors =
@@ -59,6 +61,8 @@
static const String minify = '--minify';
static const String noFrequencyBasedMinification =
'--no-frequency-based-minification';
+ // Disables minification even if enabled by other options, e.g. '-O2'.
+ static const String noMinify = '--no-minify';
static const String noSourceMaps = '--no-source-maps';
static const String preserveUris = '--preserve-uris';
static const String showPackageWarnings = '--show-package-warnings';
@@ -127,6 +131,10 @@
static const String showPackageWarnings =
'${Flags.showPackageWarnings}|${Flags.showPackageWarnings}=.*';
+ static const String enableLanguageExperiments =
+ '${Flags.enableLanguageExperiments}|'
+ '${Flags.enableLanguageExperiments}=.*';
+
// Experimental options.
static const String resolutionInput = '--resolution-input=.+';
static const String bazelPaths = '--bazel-paths=.+';
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 188f52e..9913a66 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -1905,16 +1905,6 @@
/// Returns the function type variables defined on [function].
List<TypeVariableType> getFunctionTypeVariables(FunctionEntity function);
- /// Returns the 'element' type of a function with an async, async* or sync*
- /// marker. The return type of the method is inspected to determine the type
- /// parameter of the Future, Stream or Iterable.
- DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function);
-
- /// Returns the 'element' type of a function with the async, async* or sync*
- /// marker [marker]. [returnType] is the return type marked function.
- DartType getAsyncOrSyncStarElementType(
- AsyncMarker marker, DartType returnType);
-
/// Returns the type of the [local] function.
FunctionType getLocalFunctionType(Local local);
@@ -1996,4 +1986,14 @@
/// This is the type used as the default type argument when no explicit type
/// argument is passed.
DartType getTypeVariableDefaultType(TypeVariableEntity typeVariable);
+
+ /// Returns the 'element' type of a function with the async, async* or sync*
+ /// marker [marker]. [returnType] is the return type marked function.
+ DartType getAsyncOrSyncStarElementType(
+ AsyncMarker marker, DartType returnType);
+
+ /// Returns the 'element' type of a function with an async, async* or sync*
+ /// marker. The return type of the method is inspected to determine the type
+ /// parameter of the Future, Stream or Iterable.
+ DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function);
}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 96ac042..b35401a 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -195,7 +195,6 @@
JavaScriptBackend createBackend() {
return new JavaScriptBackend(this,
generateSourceMap: options.generateSourceMap,
- useStartupEmitter: options.useStartupEmitter,
useMultiSourceInfo: options.useMultiSourceInfo,
useNewSourceInfo: options.useNewSourceInfo);
}
@@ -444,9 +443,7 @@
return jClosedWorld;
}
- /**
- * Empty the [enqueuer] queue.
- */
+ /// Empty the [enqueuer] queue.
void emptyQueue(Enqueuer enqueuer, {void onProgress(Enqueuer enqueuer)}) {
selfTask.measureSubtask("emptyQueue", () {
enqueuer.forEach((WorkItem work) {
@@ -775,11 +772,9 @@
@override
bool get hasReportedError => compiler.compilationFailed;
- /**
- * Perform an operation, [f], returning the return value from [f]. If an
- * error occurs then report it as having occurred during compilation of
- * [element]. Can be nested.
- */
+ /// Perform an operation, [f], returning the return value from [f]. If an
+ /// error occurs then report it as having occurred during compilation of
+ /// [element]. Can be nested.
withCurrentElement(Entity element, f()) {
Entity old = currentElement;
_currentElement = element;
diff --git a/pkg/compiler/lib/src/constant_system_dart.dart b/pkg/compiler/lib/src/constant_system_dart.dart
index 8d9fab5..1fc88a5 100644
--- a/pkg/compiler/lib/src/constant_system_dart.dart
+++ b/pkg/compiler/lib/src/constant_system_dart.dart
@@ -51,9 +51,7 @@
}
}
-/**
- * Operations that only work if both arguments are integers.
- */
+/// Operations that only work if both arguments are integers.
abstract class BinaryBitOperation implements BinaryOperation {
const BinaryBitOperation();
ConstantValue fold(ConstantValue left, ConstantValue right) {
@@ -412,12 +410,10 @@
}
}
-/**
- * A constant system implementing the Dart semantics. This system relies on
- * the underlying runtime-system. That is, if dart2js is run in an environment
- * that doesn't correctly implement Dart's semantics this constant system will
- * not return the correct values.
- */
+/// A constant system implementing the Dart semantics. This system relies on
+/// the underlying runtime-system. That is, if dart2js is run in an environment
+/// that doesn't correctly implement Dart's semantics this constant system will
+/// not return the correct values.
class DartConstantSystem extends ConstantSystem {
final add = const AddOperation();
final bitAnd = const BitAndOperation();
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index c543720..91d89f2 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -14,19 +14,17 @@
}
abstract class UnaryOperation extends Operation {
- /** Returns [:null:] if it was unable to fold the operation. */
+ /// Returns [:null:] if it was unable to fold the operation.
ConstantValue fold(ConstantValue constant);
}
abstract class BinaryOperation extends Operation {
- /** Returns [:null:] if it was unable to fold the operation. */
+ /// Returns [:null:] if it was unable to fold the operation.
ConstantValue fold(ConstantValue left, ConstantValue right);
apply(left, right);
}
-/**
- * A [ConstantSystem] is responsible for creating constants and folding them.
- */
+/// A [ConstantSystem] is responsible for creating constants and folding them.
abstract class ConstantSystem {
BinaryOperation get add;
BinaryOperation get bitAnd;
@@ -75,15 +73,19 @@
// system because an int is a double at runtime.
bool isSubtype(DartTypes types, DartType s, DartType t);
- /** Returns true if the [constant] is an integer at runtime. */
+ /// Returns true if the [constant] is an integer at runtime.
bool isInt(ConstantValue constant);
- /** Returns true if the [constant] is a double at runtime. */
+
+ /// Returns true if the [constant] is a double at runtime.
bool isDouble(ConstantValue constant);
- /** Returns true if the [constant] is a string at runtime. */
+
+ /// Returns true if the [constant] is a string at runtime.
bool isString(ConstantValue constant);
- /** Returns true if the [constant] is a boolean at runtime. */
+
+ /// Returns true if the [constant] is a boolean at runtime.
bool isBool(ConstantValue constant);
- /** Returns true if the [constant] is null at runtime. */
+
+ /// Returns true if the [constant] is null at runtime.
bool isNull(ConstantValue constant);
UnaryOperation lookupUnary(UnaryOperator operator) {
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index aae0175..3d30d3b 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -71,9 +71,11 @@
bool get isMap => false;
bool get isConstructedObject => false;
bool get isFunction => false;
- /** Returns true if the constant is null, a bool, a number or a string. */
+
+ /// Returns true if the constant is null, a bool, a number or a string.
bool get isPrimitive => false;
- /** Returns true if the constant is a list, a map or a constructed object. */
+
+ /// Returns true if the constant is a list, a map or a constructed object.
bool get isObject => false;
bool get isType => false;
bool get isInterceptor => false;
@@ -170,7 +172,7 @@
}
class NullConstantValue extends PrimitiveConstantValue {
- /** The value a Dart null is compiled to in JavaScript. */
+ /// The value a Dart null is compiled to in JavaScript.
static const String JsNull = "null";
const factory NullConstantValue() = NullConstantValue._internal;
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 74818db..dbfe890 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -23,21 +23,17 @@
const String _defaultSpecificationUri = '../../../../sdk/lib/libraries.json';
const String OUTPUT_LANGUAGE_DART = 'Dart';
-/**
- * A string to identify the revision or build.
- *
- * This ID is displayed if the compiler crashes and in verbose mode, and is
- * an aid in reproducing bug reports.
- *
- * The actual string is rewritten by a wrapper script when included in the sdk.
- */
+/// A string to identify the revision or build.
+///
+/// This ID is displayed if the compiler crashes and in verbose mode, and is
+/// an aid in reproducing bug reports.
+///
+/// The actual string is rewritten by a wrapper script when included in the sdk.
String BUILD_ID = null;
-/**
- * The data passed to the [HandleOption] callback is either a single
- * string argument, or the arguments iterator for multiple arguments
- * handlers.
- */
+/// The data passed to the [HandleOption] callback is either a single
+/// string argument, or the arguments iterator for multiple arguments
+/// handlers.
typedef void HandleOption(Null data);
class OptionHandler {
@@ -52,12 +48,10 @@
OptionHandler(this.pattern, this._handle, {this.multipleArguments: false});
}
-/**
- * Extract the parameter of an option.
- *
- * For example, in ['--out=fisk.js'] and ['-ohest.js'], the parameters
- * are ['fisk.js'] and ['hest.js'], respectively.
- */
+/// Extract the parameter of an option.
+///
+/// For example, in ['--out=fisk.js'] and ['-ohest.js'], the parameters
+/// are ['fisk.js'] and ['hest.js'], respectively.
String extractParameter(String argument, {bool isOptionalArgument: false}) {
// m[0] is the entire match (which will be equal to argument). m[1]
// is something like "-o" or "--out=", and m[2] is the parameter.
@@ -340,10 +334,11 @@
new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
new OptionHandler('-O.*', setOptimizationLevel),
new OptionHandler(Flags.allowMockCompilation, ignoreOption),
- new OptionHandler(Flags.fastStartup, passThrough),
+ new OptionHandler(Flags.fastStartup, ignoreOption),
new OptionHandler(Flags.genericMethodSyntax, ignoreOption),
new OptionHandler(Flags.initializingFormalAccess, ignoreOption),
new OptionHandler(Flags.minify, passThrough),
+ new OptionHandler(Flags.noMinify, passThrough),
new OptionHandler(Flags.preserveUris, ignoreOption),
new OptionHandler('--force-strip=.*', setStrip),
new OptionHandler(Flags.disableDiagnosticColors, (_) {
@@ -380,6 +375,7 @@
new OptionHandler(Flags.dumpInfo, passThrough),
new OptionHandler('--disallow-unsafe-eval', ignoreOption),
new OptionHandler(Option.showPackageWarnings, passThrough),
+ new OptionHandler(Option.enableLanguageExperiments, passThrough),
new OptionHandler(Flags.useContentSecurityPolicy, passThrough),
new OptionHandler(Flags.enableExperimentalMirrors, passThrough),
new OptionHandler(Flags.enableAssertMessage, passThrough),
@@ -765,10 +761,6 @@
--no-source-maps
Do not generate a source map file.
- --fast-startup
- Produce JavaScript that can be parsed more quickly by VMs. This option
- usually results in larger JavaScript files with faster startup.
-
-O<0,1,2,3,4>
Controls optimizations that can help reduce code-size and improve
performance of the generated code for deployment.
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 31c1687..ddbd195 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -133,14 +133,12 @@
/// Should describe how to fix the problem. Elided when using --terse option.
final String howToFix;
- /**
- * Examples will be checked by
- * tests/compiler/dart2js/message_kind_test.dart.
- *
- * An example is either a String containing the example source code or a Map
- * from filenames to source code. In the latter case, the filename for the
- * main library code must be 'main.dart'.
- */
+ /// Examples will be checked by
+ /// tests/compiler/dart2js/message_kind_test.dart.
+ ///
+ /// An example is either a String containing the example source code or a Map
+ /// from filenames to source code. In the latter case, the filename for the
+ /// main library code must be 'main.dart'.
final List examples;
/// Additional options needed for the examples to work.
diff --git a/pkg/compiler/lib/src/diagnostics/spannable.dart b/pkg/compiler/lib/src/diagnostics/spannable.dart
index 3c8b6d1..cdba684 100644
--- a/pkg/compiler/lib/src/diagnostics/spannable.dart
+++ b/pkg/compiler/lib/src/diagnostics/spannable.dart
@@ -4,9 +4,7 @@
library dart2js.diagnostics.spannable;
-/**
- * Tagging interface for classes from which source spans can be generated.
- */
+/// Tagging interface for classes from which source spans can be generated.
// TODO(johnniwinther): Find a better name.
// TODO(ahe): How about "Bolt"?
abstract class Spannable {}
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index e2722a0..d3f9c4d 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -32,6 +32,7 @@
final Compiler compiler;
final JClosedWorld closedWorld;
final GlobalTypeInferenceResults _globalInferenceResults;
+ final DumpInfoTask dumpInfoTask;
JElementEnvironment get environment => closedWorld.elementEnvironment;
CodegenWorldBuilder get codegenWorldBuilder => compiler.codegenWorldBuilder;
@@ -41,13 +42,13 @@
final Map<ConstantValue, Info> _constantToInfo = <ConstantValue, Info>{};
final Map<OutputUnit, OutputUnitInfo> _outputToInfo = {};
- ElementInfoCollector(
- this.compiler, this.closedWorld, this._globalInferenceResults);
+ ElementInfoCollector(this.compiler, this.dumpInfoTask, this.closedWorld,
+ this._globalInferenceResults);
void run() {
- compiler.dumpInfoTask._constantToNode.forEach((constant, node) {
+ dumpInfoTask._constantToNode.forEach((constant, node) {
// TODO(sigmund): add dependencies on other constants
- var size = compiler.dumpInfoTask._nodeToSize[node];
+ var size = dumpInfoTask._nodeData[node].length;
var code = jsAst.prettyPrint(node,
enableMinification: compiler.options.enableMinification);
var info = new ConstantInfo(
@@ -64,8 +65,8 @@
/// output size. Either because it is a function being emitted or inlined,
/// or because it is an entity that holds dependencies to other entities.
bool shouldKeep(Entity entity) {
- return compiler.dumpInfoTask.impacts.containsKey(entity) ||
- compiler.dumpInfoTask.inlineCount.containsKey(entity);
+ return dumpInfoTask.impacts.containsKey(entity) ||
+ dumpInfoTask.inlineCount.containsKey(entity);
}
LibraryInfo visitLibrary(LibraryEntity lib) {
@@ -73,7 +74,7 @@
if (libname.isEmpty) {
libname = '<unnamed>';
}
- int size = compiler.dumpInfoTask.sizeOf(lib);
+ int size = dumpInfoTask.sizeOf(lib);
LibraryInfo info = new LibraryInfo(libname, lib.canonicalUri, null, size);
_entityToInfo[lib] = info;
@@ -122,8 +123,8 @@
return null;
}
- int size = compiler.dumpInfoTask.sizeOf(field);
- String code = compiler.dumpInfoTask.codeOf(field);
+ int size = dumpInfoTask.sizeOf(field);
+ String code = dumpInfoTask.codeOf(field);
// TODO(het): Why doesn't `size` account for the code size already?
if (code != null) size += code.length;
@@ -162,7 +163,7 @@
outputUnit: _unitInfoForClass(clazz));
_entityToInfo[clazz] = classInfo;
- int size = compiler.dumpInfoTask.sizeOf(clazz);
+ int size = dumpInfoTask.sizeOf(clazz);
environment.forEachLocalClassMember(clazz, (member) {
if (member.isFunction || member.isGetter || member.isSetter) {
FunctionInfo functionInfo = visitFunction(member);
@@ -213,7 +214,7 @@
ClosureInfo closureInfo = new ClosureInfo(
name: element.name,
outputUnit: _unitInfoForClass(element),
- size: compiler.dumpInfoTask.sizeOf(element));
+ size: dumpInfoTask.sizeOf(element));
_entityToInfo[element] = closureInfo;
FunctionEntity callMethod = closedWorld.elementEnvironment
@@ -229,7 +230,7 @@
}
FunctionInfo visitFunction(FunctionEntity function) {
- int size = compiler.dumpInfoTask.sizeOf(function);
+ int size = dumpInfoTask.sizeOf(function);
// TODO(sigmund): consider adding a small info to represent unreachable
// code here.
if (size == 0 && !shouldKeep(function)) return null;
@@ -260,7 +261,7 @@
: false,
isExternal: function.isExternal,
);
- String code = compiler.dumpInfoTask.codeOf(function);
+ String code = dumpInfoTask.codeOf(function);
List<ParameterInfo> parameters = <ParameterInfo>[];
List<String> inferredParameterTypes = <String>[];
@@ -280,7 +281,7 @@
String sideEffects =
'${_globalInferenceResults.inferredData.getSideEffectsOfElement(function)}';
- int inlinedCount = compiler.dumpInfoTask.inlineCount[function];
+ int inlinedCount = dumpInfoTask.inlineCount[function];
if (inlinedCount == null) inlinedCount = 0;
FunctionInfo info = new FunctionInfo(
@@ -400,10 +401,10 @@
/// The size of the generated output.
int _programSize;
- // A set of javascript AST nodes that we care about the size of.
- // This set is automatically populated when registerEntityAst()
- // is called.
- final Set<jsAst.Node> _tracking = new Set<jsAst.Node>();
+ /// Data associated with javascript AST nodes. The map only contains keys for
+ /// nodes that we care about. Keys are automatically added when
+ /// [registerEntityAst] is called.
+ final Map<jsAst.Node, _CodeData> _nodeData = <jsAst.Node, _CodeData>{};
// A mapping from Dart Entities to Javascript AST Nodes.
final Map<Entity, List<jsAst.Node>> _entityToNodes =
@@ -411,10 +412,6 @@
final Map<ConstantValue, jsAst.Node> _constantToNode =
<ConstantValue, jsAst.Node>{};
- // A mapping from Javascript AST Nodes to the size of their
- // pretty-printed contents.
- final Map<jsAst.Node, int> _nodeToSize = <jsAst.Node, int>{};
-
final Map<Entity, int> inlineCount = <Entity, int>{};
// A mapping from an entity to a list of entities that are
@@ -470,24 +467,15 @@
return selections;
}
- // Returns true if we care about tracking the size of
- // this node.
- bool isTracking(jsAst.Node code) {
- if (compiler.options.dumpInfo) {
- return _tracking.contains(code);
- } else {
- return false;
- }
- }
-
/// Registers that a javascript AST node [code] was produced by the dart
/// Entity [entity].
- void registerEntityAst(Entity entity, jsAst.Node code) {
+ void registerEntityAst(Entity entity, jsAst.Node code,
+ {LibraryEntity library}) {
if (compiler.options.dumpInfo) {
_entityToNodes
.putIfAbsent(entity, () => new List<jsAst.Node>())
.add(code);
- _tracking.add(code);
+ _nodeData[code] ??= _CodeData();
}
}
@@ -496,19 +484,36 @@
assert(_constantToNode[constant] == null ||
_constantToNode[constant] == code);
_constantToNode[constant] = code;
- _tracking.add(code);
+ _nodeData[code] ??= _CodeData();
}
}
- /// Records the size of a dart AST node after it has been pretty-printed into
- /// the output buffer.
- void recordAstSize(jsAst.Node node, int size) {
- if (isTracking(node)) {
- //TODO: should I be incrementing here instead?
- _nodeToSize[node] = size;
+ // TODO(sigmund): delete the stack once we stop emitting the source text.
+ List<_CodeData> _stack = [];
+ void enterNode(jsAst.Node node, int start) {
+ var data = _nodeData[node];
+ if (data != null) {
+ _stack.add(data);
+ data.start = start;
}
}
+ void emit(String string) {
+ // Note: historically we emitted the full body of classes and methods, so
+ // instance methods ended up emitted twice. Once we use a different
+ // encoding of dump info, we also plan to remove this duplication.
+ _stack.forEach((f) => f.text.write(string));
+ }
+
+ void exitNode(jsAst.Node node, int start, int end, int closing) {
+ var data = _nodeData[node];
+ if (data == null) return;
+ var last = _stack.removeLast();
+ assert(data == last);
+ assert(data.start == start);
+ data.end = end;
+ }
+
/// Returns the size of the source code that was generated for an entity.
/// If no source code was produced, return 0.
int sizeOf(Entity entity) {
@@ -519,7 +524,7 @@
}
}
- int sizeOfNode(jsAst.Node node) => _nodeToSize[node] ?? 0;
+ int sizeOfNode(jsAst.Node node) => _nodeData[node].length ?? 0;
String codeOf(Entity entity) {
List<jsAst.Node> code = _entityToNodes[entity];
@@ -527,8 +532,7 @@
// Concatenate rendered ASTs.
StringBuffer sb = new StringBuffer();
for (jsAst.Node ast in code) {
- sb.writeln(jsAst.prettyPrint(ast,
- enableMinification: compiler.options.enableMinification));
+ sb.writeln(_nodeData[ast].text);
}
return sb.toString();
}
@@ -537,7 +541,7 @@
GlobalTypeInferenceResults globalInferenceResults) {
measure(() {
infoCollector = new ElementInfoCollector(
- compiler, closedWorld, globalInferenceResults)
+ compiler, this, closedWorld, globalInferenceResults)
..run();
StringBuffer jsonBuffer = new StringBuffer();
dumpInfoJson(jsonBuffer, closedWorld);
@@ -634,3 +638,15 @@
});
}
}
+
+/// Helper class to store what dump-info will show for a piece of code.
+///
+/// Currently we print out the actual text, in the future, we will only emit
+/// start and end offsets.
+class _CodeData {
+ int start;
+ int end;
+ StringBuffer text = new StringBuffer();
+
+ int get length => end - start;
+}
diff --git a/pkg/compiler/lib/src/elements/entity_utils.dart b/pkg/compiler/lib/src/elements/entity_utils.dart
index 6096e4a..0a26700 100644
--- a/pkg/compiler/lib/src/elements/entity_utils.dart
+++ b/pkg/compiler/lib/src/elements/entity_utils.dart
@@ -101,15 +101,13 @@
}
}
-/**
- * Map an operator-name to a valid JavaScript identifier.
- *
- * For non-operator names, this method just returns its input.
- *
- * The results returned from this method are guaranteed to be valid
- * JavaScript identifiers, except it may include reserved words for
- * non-operator names.
- */
+/// Map an operator-name to a valid JavaScript identifier.
+///
+/// For non-operator names, this method just returns its input.
+///
+/// The results returned from this method are guaranteed to be valid
+/// JavaScript identifiers, except it may include reserved words for
+/// non-operator names.
String operatorNameToIdentifier(String name) {
if (name == null) {
return name;
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index bc4d20e..d42f31a 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -103,7 +103,8 @@
bool _containsFreeTypeVariables(List<FunctionTypeVariable> bindings) => false;
}
-/// Pairs of [FunctionTypeVariable]s that are currently assumed to be equivalent.
+/// Pairs of [FunctionTypeVariable]s that are currently assumed to be
+/// equivalent.
///
/// This is used to compute the equivalence relation on types coinductively.
class _Assumptions {
diff --git a/pkg/compiler/lib/src/helpers/expensive_map.dart b/pkg/compiler/lib/src/helpers/expensive_map.dart
index 5f5cb44..ed95b22 100644
--- a/pkg/compiler/lib/src/helpers/expensive_map.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_map.dart
@@ -4,11 +4,9 @@
import "dart:collection";
-/**
- * The expensive map is a data structure useful for tracking down
- * excessive memory usage due to large maps. It acts as an ordinary
- * hash map, but it uses 10 times more memory (by default).
- */
+/// The expensive map is a data structure useful for tracking down
+/// excessive memory usage due to large maps. It acts as an ordinary
+/// hash map, but it uses 10 times more memory (by default).
class ExpensiveMap<K, V> extends MapBase<K, V> {
final List _maps;
diff --git a/pkg/compiler/lib/src/helpers/expensive_set.dart b/pkg/compiler/lib/src/helpers/expensive_set.dart
index 76f8cd7..f4c2f4f 100644
--- a/pkg/compiler/lib/src/helpers/expensive_set.dart
+++ b/pkg/compiler/lib/src/helpers/expensive_set.dart
@@ -4,11 +4,9 @@
import 'dart:collection';
-/**
- * The expensive set is a data structure useful for tracking down
- * excessive memory usage due to large sets. It acts as an ordinary
- * hash set, but it uses 10 times more memory (by default).
- */
+/// The expensive set is a data structure useful for tracking down
+/// excessive memory usage due to large sets. It acts as an ordinary
+/// hash set, but it uses 10 times more memory (by default).
class ExpensiveSet<E> extends SetBase<E> {
final List _sets;
diff --git a/pkg/compiler/lib/src/helpers/trace.dart b/pkg/compiler/lib/src/helpers/trace.dart
index 2c92824..104c227 100644
--- a/pkg/compiler/lib/src/helpers/trace.dart
+++ b/pkg/compiler/lib/src/helpers/trace.dart
@@ -9,23 +9,21 @@
typedef void Trace(String message,
{bool condition(String stackTrace), int limit, bool throwOnPrint});
-/**
- * Helper method for printing stack traces for debugging.
- *
- * [message] is printed as the header of the stack trace.
- *
- * If [condition] is provided, the stack trace is only printed if [condition]
- * returns [:true:] on the stack trace text. This can be used to filter the
- * printed stack traces based on their content. For instance only print stack
- * traces that contain specific paths.
- *
- * If [limit] is provided, the stack trace is limited to [limit] entries.
- *
- * If [throwOnPrint] is `true`, [message] will be thrown after the stack trace
- * has been printed. Together with [condition] this can be used to discover
- * unknown call-sites in tests by filtering known call-sites and throwning
- * otherwise.
- */
+/// Helper method for printing stack traces for debugging.
+///
+/// [message] is printed as the header of the stack trace.
+///
+/// If [condition] is provided, the stack trace is only printed if [condition]
+/// returns [:true:] on the stack trace text. This can be used to filter the
+/// printed stack traces based on their content. For instance only print stack
+/// traces that contain specific paths.
+///
+/// If [limit] is provided, the stack trace is limited to [limit] entries.
+///
+/// If [throwOnPrint] is `true`, [message] will be thrown after the stack trace
+/// has been printed. Together with [condition] this can be used to discover
+/// unknown call-sites in tests by filtering known call-sites and throwning
+/// otherwise.
Trace get trace {
enableDebugMode();
return _trace;
@@ -293,22 +291,20 @@
}
// TODO(johnniwinther): Use this format for --throw-on-error.
-/**
- * Converts the normal VM stack trace into a more compact and readable format.
- *
- * The output format is [: <file> . . . <lineNo>:<columnNo> <method> :] where
- * [: <file> :] is file name, [: <lineNo> :] is the line number,
- * [: <columnNo> :] is the column number, and [: <method> :] is the method name.
- *
- * If [rangeStart] and/or [rangeEnd] are provided, only the lines within the
- * range are included.
- * If [showColumnNo] is [:false:], the [: :<columnNo> :] part is omitted.
- * If [showDots] is [:true:], the space between [: <file> :] and [: <lineNo> :]
- * is padded with dots on every other line.
- * If [filePrefix] is provided, then for every file name thats starts with
- * [filePrefix] only the remainder is printed.
- * If [lambda] is non-null, anonymous closures are printed as [lambda].
- */
+/// Converts the normal VM stack trace into a more compact and readable format.
+///
+/// The output format is `<file> . . . <lineNo>:<columnNo> <method>` where
+/// `<file>` is file name, `<lineNo>` is the line number, `<columnNo>` is the
+/// column number, and `<method>` is the method name.
+///
+/// If [rangeStart] and/or [rangeEnd] are provided, only the lines within the
+/// range are included.
+/// If [showColumnNo] is `false`, the `:<columnNo>` part is omitted.
+/// If [showDots] is `true`, the space between `<file>` and `<lineNo>` is padded
+/// with dots on every other line.
+/// If [filePrefix] is provided, then for every file name thats starts with
+/// [filePrefix] only the remainder is printed.
+/// If [lambda] is non-null, anonymous closures are printed as [lambda].
String prettifyStackTrace(StackTrace stackTrace,
{int rangeStart,
int rangeEnd,
@@ -324,12 +320,10 @@
.prettify(showColumnNo: showColumnNo, showDots: showDots);
}
-/**
- * Pads (or truncates) [text] to the [intendedLength].
- *
- * If [padLeft] is [:true:] the text is padding inserted to the left of [text].
- * A repetition of the [dots] text is used for padding.
- */
+/// Pads (or truncates) [text] to the [intendedLength].
+///
+/// If [padLeft] is [:true:] the text is padding inserted to the left of [text].
+/// A repetition of the [dots] text is used for padding.
String pad(String text, int intendedLength,
{bool padLeft: false, String dots: ' '}) {
if (text.length == intendedLength) return text;
diff --git a/pkg/compiler/lib/src/helpers/track_map.dart b/pkg/compiler/lib/src/helpers/track_map.dart
index 7c2eb86..6cb7121 100644
--- a/pkg/compiler/lib/src/helpers/track_map.dart
+++ b/pkg/compiler/lib/src/helpers/track_map.dart
@@ -2,17 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-/**
- * The track map is a simple wrapper around a map that keeps track
- * of the 'final' size of maps grouped by description. It allows
- * determining the distribution of sizes for a specific allocation
- * site and it can be used like this:
- *
- * Map<String, int> map = new TrackMap<String, int>("my-map");
- *
- * After finishing the compilaton, the histogram of track map sizes
- * is printed but only when running in verbose mode.
- */
+/// The track map is a simple wrapper around a map that keeps track
+/// of the 'final' size of maps grouped by description. It allows
+/// determining the distribution of sizes for a specific allocation
+/// site and it can be used like this:
+///
+/// Map<String, int> map = new TrackMap<String, int>("my-map");
+///
+/// After finishing the compilaton, the histogram of track map sizes
+/// is printed but only when running in verbose mode.
class TrackMap<K, V> implements Map<K, V> {
final Map<K, V> _map;
final List _counts;
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index e029d4f..60ea7a3 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -310,10 +310,8 @@
GlobalTypeInferenceElementData dataOfMember(MemberEntity element) =>
_memberData[element] ??= new KernelGlobalTypeInferenceElementData();
- /**
- * Update [sideEffects] with the side effects of [callee] being
- * called with [selector].
- */
+ /// Update [sideEffects] with the side effects of [callee] being
+ /// called with [selector].
void updateSideEffects(SideEffectsBuilder sideEffectsBuilder,
Selector selector, MemberEntity callee) {
if (callee.isField) {
diff --git a/pkg/compiler/lib/src/inferrer/list_tracer.dart b/pkg/compiler/lib/src/inferrer/list_tracer.dart
index 7043105..dfe10a0 100644
--- a/pkg/compiler/lib/src/inferrer/list_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/list_tracer.dart
@@ -11,11 +11,9 @@
import 'node_tracer.dart';
import 'type_graph_nodes.dart';
-/**
- * A set of selector names that [List] implements, that we know do not
- * change the element type of the list, or let the list escape to code
- * that might change the element type.
- */
+/// A set of selector names that [List] implements, that we know do not
+/// change the element type of the list, or let the list escape to code
+/// that might change the element type.
Set<String> okListSelectorsSet = new Set<String>.from(const <String>[
// From Object.
'==',
@@ -137,11 +135,9 @@
ListTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
- /**
- * Returns [true] if the analysis completed successfully, [false] if it
- * bailed out. In the former case, [assignments] holds a list of
- * [TypeInformation] nodes that flow into the element type of this list.
- */
+ /// Returns [true] if the analysis completed successfully, [false] if it
+ /// bailed out. In the former case, [assignments] holds a list of
+ /// [TypeInformation] nodes that flow into the element type of this list.
bool run() {
analyze();
ListTypeInformation list = tracedType;
diff --git a/pkg/compiler/lib/src/inferrer/locals_handler.dart b/pkg/compiler/lib/src/inferrer/locals_handler.dart
index cfe7f1c..aff2896 100644
--- a/pkg/compiler/lib/src/inferrer/locals_handler.dart
+++ b/pkg/compiler/lib/src/inferrer/locals_handler.dart
@@ -13,13 +13,11 @@
import 'inferrer_engine.dart';
import 'type_graph_nodes.dart';
-/**
- * A variable scope holds types for variables. It has a link to a
- * parent scope, but never changes the types in that parent. Instead,
- * updates to locals of a parent scope are put in the current scope.
- * The inferrer makes sure updates get merged into the parent scope,
- * once the control flow block has been visited.
- */
+/// A variable scope holds types for variables. It has a link to a
+/// parent scope, but never changes the types in that parent. Instead,
+/// updates to locals of a parent scope are put in the current scope.
+/// The inferrer makes sure updates get merged into the parent scope,
+/// once the control flow block has been visited.
class VariableScope {
/// The number of parent scopes of this scope.
///
@@ -241,9 +239,7 @@
}
}
-/**
- * Placeholder for inferred arguments types on sends.
- */
+/// Placeholder for inferred arguments types on sends.
class ArgumentsTypes extends IterableMixin<TypeInformation> {
final List<TypeInformation> positional;
final Map<String, TypeInformation> named;
@@ -317,9 +313,7 @@
}
}
-/**
- * Placeholder for inferred types of local variables.
- */
+/// Placeholder for inferred types of local variables.
class LocalsHandler {
final VariableScope _locals;
@@ -439,36 +433,34 @@
return this;
}
- /**
- * Merge all [LocalsHandler] in [handlers] into [:this:].
- *
- * If [keepOwnLocals] is true, the types of locals in this
- * [LocalsHandler] are being used in the merge. [keepOwnLocals]
- * should be true if this [LocalsHandler], the dominator of
- * all [handlers], also directly flows into the join point,
- * that is the code after all [handlers]. For example, consider:
- *
- * [: switch (...) {
- * case 1: ...; break;
- * }
- * :]
- *
- * The [LocalsHandler] at entry of the switch also flows into the
- * exit of the switch, because there is no default case. So the
- * types of locals at entry of the switch have to take part to the
- * merge.
- *
- * The above situation is also true for labeled statements like
- *
- * [: L: {
- * if (...) break;
- * ...
- * }
- * :]
- *
- * where [:this:] is the [LocalsHandler] for the paths through the
- * labeled statement that do not break out.
- */
+ /// Merge all [LocalsHandler] in [handlers] into [:this:].
+ ///
+ /// If [keepOwnLocals] is true, the types of locals in this
+ /// [LocalsHandler] are being used in the merge. [keepOwnLocals]
+ /// should be true if this [LocalsHandler], the dominator of
+ /// all [handlers], also directly flows into the join point,
+ /// that is the code after all [handlers]. For example, consider:
+ ///
+ /// [: switch (...) {
+ /// case 1: ...; break;
+ /// }
+ /// :]
+ ///
+ /// The [LocalsHandler] at entry of the switch also flows into the
+ /// exit of the switch, because there is no default case. So the
+ /// types of locals at entry of the switch have to take part to the
+ /// merge.
+ ///
+ /// The above situation is also true for labeled statements like
+ ///
+ /// [: L: {
+ /// if (...) break;
+ /// ...
+ /// }
+ /// :]
+ ///
+ /// where [:this:] is the [LocalsHandler] for the paths through the
+ /// labeled statement that do not break out.
LocalsHandler mergeAfterBreaks(
InferrerEngine inferrer, Iterable<LocalsHandler> handlers,
{bool keepOwnLocals: true}) {
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index 83ad71c..e9da06a 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -43,12 +43,10 @@
MapTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
- /**
- * Returns [true] if the analysis completed successfully, [false]
- * if it bailed out. In the former case, [keyAssignments] and
- * [valueAssignments] hold a list of [TypeInformation] nodes that
- * flow into the key and value types of this map.
- */
+ /// Returns [true] if the analysis completed successfully, [false]
+ /// if it bailed out. In the former case, [keyAssignments] and
+ /// [valueAssignments] hold a list of [TypeInformation] nodes that
+ /// flow into the key and value types of this map.
bool run() {
analyze();
MapTypeInformation map = tracedType;
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index e88535a..e0abccf 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -249,11 +249,9 @@
}
}
- /**
- * Checks whether this is a call to a list adding method. The definition of
- * what list adding means has to stay in sync with
- * [isParameterOfListAddingMethod].
- */
+ /// Checks whether this is a call to a list adding method. The definition of
+ /// what list adding means has to stay in sync with
+ /// [isParameterOfListAddingMethod].
bool mightAddToContainer(DynamicCallSiteTypeInformation info) {
if (info.arguments == null) return false;
if (info.arguments.named.isNotEmpty) return false;
@@ -275,20 +273,16 @@
return currentUser == arguments[index];
}
- /**
- * Checks whether the call site flows the currentUser to the key argument of
- * an indexing setter. This must be kept in sync with
- * [isParameterOfMapAddingMethod].
- */
+ /// Checks whether the call site flows the currentUser to the key argument of
+ /// an indexing setter. This must be kept in sync with
+ /// [isParameterOfMapAddingMethod].
bool isIndexSetKey(DynamicCallSiteTypeInformation info) {
return isIndexSetArgument(info, 0);
}
- /**
- * Checks whether the call site flows the currentUser to the value argument of
- * an indexing setter. This must be kept in sync with
- * [isParameterOfListAddingMethod] and [isParameterOfMapAddingMethod].
- */
+ /// Checks whether the call site flows the currentUser to the value argument
+ /// of an indexing setter. This must be kept in sync with
+ /// [isParameterOfListAddingMethod] and [isParameterOfMapAddingMethod].
bool isIndexSetValue(DynamicCallSiteTypeInformation info) {
return isIndexSetArgument(info, 1);
}
@@ -398,11 +392,9 @@
}
}
- /**
- * Check whether element is the parameter of a list adding method.
- * The definition of what a list adding method is has to stay in sync with
- * [mightAddToContainer].
- */
+ /// Check whether element is the parameter of a list adding method.
+ /// The definition of what a list adding method is has to stay in sync with
+ /// [mightAddToContainer].
bool isParameterOfListAddingMethod(ParameterTypeInformation parameterInfo) {
if (!parameterInfo.isRegularParameter) return false;
if (parameterInfo.method.enclosingClass !=
@@ -413,11 +405,9 @@
return (name == '[]=') || (name == 'add') || (name == 'insert');
}
- /**
- * Check whether element is the parameter of a list adding method.
- * The definition of what a list adding method is has to stay in sync with
- * [isIndexSetKey] and [isIndexSetValue].
- */
+ /// Check whether element is the parameter of a list adding method.
+ /// The definition of what a list adding method is has to stay in sync with
+ /// [isIndexSetKey] and [isIndexSetValue].
bool isParameterOfMapAddingMethod(ParameterTypeInformation parameterInfo) {
if (!parameterInfo.isRegularParameter) return false;
if (parameterInfo.method.enclosingClass !=
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 67f830a..d9f69ca 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -18,12 +18,10 @@
import 'type_graph_nodes.dart';
import 'types.dart';
-/**
- * A work queue for the inferrer. It filters out nodes that are tagged as
- * [TypeInformation.doNotEnqueue], as well as ensures through
- * [TypeInformation.inQueue] that a node is in the queue only once at
- * a time.
- */
+/// A work queue for the inferrer. It filters out nodes that are tagged as
+/// [TypeInformation.doNotEnqueue], as well as ensures through
+/// [TypeInformation.inQueue] that a node is in the queue only once at
+/// a time.
class WorkQueue {
final Queue<TypeInformation> queue = new Queue<TypeInformation>();
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index f614109..794e62d 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -21,22 +21,20 @@
import 'inferrer_engine.dart';
import 'type_system.dart';
-/**
- * Common class for all nodes in the graph. The current nodes are:
- *
- * - Concrete types
- * - Elements
- * - Call sites
- * - Narrowing instructions
- * - Phi instructions
- * - Containers (for lists)
- * - Type of the element in a container
- *
- * A node has a set of assignments and users. Assignments are used to
- * compute the type of the node ([TypeInformation.computeType]). Users are
- * added to the inferrer's work queue when the type of the node
- * changes.
- */
+/// Common class for all nodes in the graph. The current nodes are:
+///
+/// - Concrete types
+/// - Elements
+/// - Call sites
+/// - Narrowing instructions
+/// - Phi instructions
+/// - Containers (for lists)
+/// - Type of the element in a container
+///
+/// A node has a set of assignments and users. Assignments are used to
+/// compute the type of the node ([TypeInformation.computeType]). Users are
+/// added to the inferrer's work queue when the type of the node
+/// changes.
abstract class TypeInformation {
Set<TypeInformation> users;
var /* List|ParameterAssignments */ _assignments;
@@ -149,16 +147,12 @@
return abandonInferencing ? safeType(inferrer) : computeType(inferrer);
}
- /**
- * Computes a new type for this [TypeInformation] node depending on its
- * potentially updated inputs.
- */
+ /// Computes a new type for this [TypeInformation] node depending on its
+ /// potentially updated inputs.
AbstractValue computeType(InferrerEngine inferrer);
- /**
- * Returns an approximation for this [TypeInformation] node that is always
- * safe to use. Used when abandoning inference on a node.
- */
+ /// Returns an approximation for this [TypeInformation] node that is always
+ /// safe to use. Used when abandoning inference on a node.
AbstractValue safeType(InferrerEngine inferrer) {
return inferrer.types.dynamicType.type;
}
@@ -243,14 +237,12 @@
bool mightBePassedToFunctionApply = false;
}
-/**
- * Marker node used only during tree construction but not during actual type
- * refinement.
- *
- * Currently, this is used to give a type to an optional parameter even before
- * the corresponding default expression has been analyzed. See
- * [getDefaultTypeOfParameter] and [setDefaultTypeOfParameter] for details.
- */
+/// Marker node used only during tree construction but not during actual type
+/// refinement.
+///
+/// Currently, this is used to give a type to an optional parameter even before
+/// the corresponding default expression has been analyzed. See
+/// [getDefaultTypeOfParameter] and [setDefaultTypeOfParameter] for details.
class PlaceholderTypeInformation extends TypeInformation {
PlaceholderTypeInformation(
AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
@@ -267,13 +259,11 @@
toString() => "Placeholder [$hashCode]";
}
-/**
- * Parameters of instance functions behave differently than other
- * elements because the inferrer may remove assignments. This happens
- * when the receiver of a dynamic call site can be refined
- * to a type where we know more about which instance method is being
- * called.
- */
+/// Parameters of instance functions behave differently than other
+/// elements because the inferrer may remove assignments. This happens
+/// when the receiver of a dynamic call site can be refined
+/// to a type where we know more about which instance method is being
+/// called.
class ParameterAssignments extends IterableBase<TypeInformation> {
final Map<TypeInformation, int> assignments = new Map<TypeInformation, int>();
@@ -314,33 +304,31 @@
String toString() => assignments.keys.toList().toString();
}
-/**
- * A node representing a resolved element of the component. The kind of
- * elements that need an [ElementTypeInformation] are:
- *
- * - Functions (including getters and setters)
- * - Constructors (factory or generative)
- * - Fields
- * - Parameters
- * - Local variables mutated in closures
- *
- * The [ElementTypeInformation] of a function and a constructor is its
- * return type.
- *
- * Note that a few elements of these kinds must be treated specially,
- * and they are dealt in [ElementTypeInformation.handleSpecialCases]:
- *
- * - Parameters of closures, `noSuchMethod` and `call` instance
- * methods: we currently do not infer types for those.
- *
- * - Fields and parameters being assigned by synthesized calls done by
- * the backend: we do not know what types the backend will use.
- *
- * - Native functions and fields: because native methods contain no Dart
- * code, and native fields do not have Dart assignments, we just
- * trust their type annotation.
- *
- */
+/// A node representing a resolved element of the component. The kind of
+/// elements that need an [ElementTypeInformation] are:
+///
+/// - Functions (including getters and setters)
+/// - Constructors (factory or generative)
+/// - Fields
+/// - Parameters
+/// - Local variables mutated in closures
+///
+/// The [ElementTypeInformation] of a function and a constructor is its
+/// return type.
+///
+/// Note that a few elements of these kinds must be treated specially,
+/// and they are dealt in [ElementTypeInformation.handleSpecialCases]:
+///
+/// - Parameters of closures, `noSuchMethod` and `call` instance
+/// methods: we currently do not infer types for those.
+///
+/// - Fields and parameters being assigned by synthesized calls done by
+/// the backend: we do not know what types the backend will use.
+///
+/// - Native functions and fields: because native methods contain no Dart
+/// code, and native fields do not have Dart assignments, we just
+/// trust their type annotation.
+///
abstract class ElementTypeInformation extends TypeInformation {
/// Marker to disable inference for closures in [handleSpecialCases].
bool disableInferenceForClosures = true;
@@ -360,42 +348,36 @@
String get debugName;
}
-/**
- * A node representing members in the broadest sense:
- *
- * - Functions
- * - Constructors
- * - Fields (also synthetic ones due to closures)
- * - Local functions (closures)
- *
- * These should never be created directly but instead are constructed by
- * the [ElementTypeInformation] factory.
- */
+/// A node representing members in the broadest sense:
+///
+/// - Functions
+/// - Constructors
+/// - Fields (also synthetic ones due to closures)
+/// - Local functions (closures)
+///
+/// These should never be created directly but instead are constructed by
+/// the [ElementTypeInformation] factory.
abstract class MemberTypeInformation extends ElementTypeInformation
with ApplyableTypeInformation {
final MemberEntity _member;
- /**
- * If [element] is a function, [closurizedCount] is the number of
- * times it is closurized. The value gets updated while inferring.
- */
+ /// If [element] is a function, [closurizedCount] is the number of
+ /// times it is closurized. The value gets updated while inferring.
int closurizedCount = 0;
// Strict `bool` value is computed in cleanup(). Also used as a flag to see if
// cleanup has been called.
bool _isCalledOnce = null;
- /**
- * This map contains the callers of [element]. It stores all unique call sites
- * to enable counting the global number of call sites of [element].
- *
- * A call site is either an AST [ast.Node], an [Element] (see uses of
- * [synthesizeForwardingCall] in [SimpleTypeInferrerVisitor]) or an IR
- * [ir.Node].
- *
- * The global information is summarized in [cleanup], after which [_callers]
- * is set to `null`.
- */
+ /// This map contains the callers of [element]. It stores all unique call
+ /// sites to enable counting the global number of call sites of [element].
+ ///
+ /// A call site is either an AST [ast.Node], an [Element] (see uses of
+ /// [synthesizeForwardingCall] in [SimpleTypeInferrerVisitor]) or an IR
+ /// [ir.Node].
+ ///
+ /// The global information is summarized in [cleanup], after which [_callers]
+ /// is set to `null`.
Map<MemberEntity, Setlet<Object>> _callers;
MemberTypeInformation._internal(
@@ -673,15 +655,13 @@
}
}
-/**
- * A node representing parameters:
- *
- * - Parameters
- * - Initializing formals
- *
- * These should never be created directly but instead are constructed by
- * the [ElementTypeInformation] factory.
- */
+/// A node representing parameters:
+///
+/// - Parameters
+/// - Initializing formals
+///
+/// These should never be created directly but instead are constructed by
+/// the [ElementTypeInformation] factory.
class ParameterTypeInformation extends ElementTypeInformation {
final Local _parameter;
final DartType _type;
@@ -872,16 +852,14 @@
throw new StateError('Unexpected call type $callType.');
}
-/**
- * A [CallSiteTypeInformation] is a call found in the AST, or a
- * synthesized call for implicit calls in Dart (such as forwarding
- * factories). The [_call] field is a [ast.Node] for the former, and an
- * [Element] for the latter.
- *
- * In the inferrer graph, [CallSiteTypeInformation] nodes do not have
- * any assignment. They rely on the [caller] field for static calls,
- * and [selector] and [receiver] fields for dynamic calls.
- */
+/// A [CallSiteTypeInformation] is a call found in the AST, or a
+/// synthesized call for implicit calls in Dart (such as forwarding
+/// factories). The [_call] field is a [ast.Node] for the former, and an
+/// [Element] for the latter.
+///
+/// In the inferrer graph, [CallSiteTypeInformation] nodes do not have
+/// any assignment. They rely on the [caller] field for static calls,
+/// and [selector] and [receiver] fields for dynamic calls.
abstract class CallSiteTypeInformation extends TypeInformation
with ApplyableTypeInformation {
final Object _call;
@@ -1069,15 +1047,13 @@
});
}
- /**
- * We optimize certain operations on the [int] class because we know more
- * about their return type than the actual Dart code. For example, we know int
- * + int returns an int. The Dart library code for [int.operator+] only says
- * it returns a [num].
- *
- * Returns the more precise TypeInformation, or `null` to defer to the library
- * code.
- */
+ /// We optimize certain operations on the [int] class because we know more
+ /// about their return type than the actual Dart code. For example, we know
+ /// int + int returns an int. The Dart library code for [int.operator+] only
+ /// says it returns a [num].
+ ///
+ /// Returns the more precise TypeInformation, or `null` to defer to the
+ /// library code.
TypeInformation handleIntrisifiedSelector(
Selector selector, AbstractValue mask, InferrerEngine inferrer) {
JClosedWorld closedWorld = inferrer.closedWorld;
@@ -1240,8 +1216,8 @@
return abstractValueDomain.getDictionaryValueForKey(
typeMask, key);
} else {
- // The typeMap is precise, so if we do not find the key, the lookup
- // will be [null] at runtime.
+ // The typeMap is precise, so if we do not find the key, the
+ // lookup will be [null] at runtime.
if (debug.VERBOSE) {
print("Dictionary lookup for $key yields [null].");
}
@@ -1364,16 +1340,14 @@
}
}
-/**
- * A [ConcreteTypeInformation] represents a type that needed
- * to be materialized during the creation of the graph. For example,
- * literals, [:this:] or [:super:] need a [ConcreteTypeInformation].
- *
- * [ConcreteTypeInformation] nodes have no assignment. Also, to save
- * on memory, we do not add users to [ConcreteTypeInformation] nodes,
- * because we know such node will never be refined to a different
- * type.
- */
+/// A [ConcreteTypeInformation] represents a type that needed
+/// to be materialized during the creation of the graph. For example,
+/// literals, [:this:] or [:super:] need a [ConcreteTypeInformation].
+///
+/// [ConcreteTypeInformation] nodes have no assignment. Also, to save
+/// on memory, we do not add users to [ConcreteTypeInformation] nodes,
+/// because we know such node will never be refined to a different
+/// type.
class ConcreteTypeInformation extends TypeInformation {
ConcreteTypeInformation(AbstractValue type) : super.untracked(type) {
this.isStable = true;
@@ -1447,25 +1421,23 @@
}
}
-/**
- * A [NarrowTypeInformation] narrows a [TypeInformation] to a type,
- * represented in [typeAnnotation].
- *
- * A [NarrowTypeInformation] node has only one assignment: the
- * [TypeInformation] it narrows.
- *
- * [NarrowTypeInformation] nodes are created for:
- *
- * - Code after `is` and `as` checks, where we have more information
- * on the type of the right hand side of the expression.
- *
- * - Code after a dynamic call, where we have more information on the
- * type of the receiver: it can only be of a class that holds a
- * potential target of this dynamic call.
- *
- * - In checked mode, after a type annotation, we have more
- * information on the type of a local.
- */
+/// A [NarrowTypeInformation] narrows a [TypeInformation] to a type,
+/// represented in [typeAnnotation].
+///
+/// A [NarrowTypeInformation] node has only one assignment: the
+/// [TypeInformation] it narrows.
+///
+/// [NarrowTypeInformation] nodes are created for:
+///
+/// - Code after `is` and `as` checks, where we have more information
+/// on the type of the right hand side of the expression.
+///
+/// - Code after a dynamic call, where we have more information on the
+/// type of the receiver: it can only be of a class that holds a
+/// potential target of this dynamic call.
+///
+/// - In checked mode, after a type annotation, we have more
+/// information on the type of a local.
class NarrowTypeInformation extends TypeInformation {
final AbstractValue typeAnnotation;
@@ -1506,14 +1478,12 @@
}
}
-/**
- * An [InferredTypeInformation] is a [TypeInformation] that
- * defaults to the dynamic type until it is marked as being
- * inferred, at which point it computes its type based on
- * its assignments.
- */
+/// An [InferredTypeInformation] is a [TypeInformation] that
+/// defaults to the dynamic type until it is marked as being
+/// inferred, at which point it computes its type based on
+/// its assignments.
abstract class InferredTypeInformation extends TypeInformation {
- /** Whether the element type in that container has been inferred. */
+ /// Whether the element type in that container has been inferred.
bool inferred = false;
InferredTypeInformation(AbstractValueDomain abstractValueDomain,
@@ -1532,26 +1502,22 @@
}
}
-/**
- * A [ListTypeInformation] is a [TypeInformation] created
- * for each `List` instantiations.
- */
+/// A [ListTypeInformation] is a [TypeInformation] created
+/// for each `List` instantiations.
class ListTypeInformation extends TypeInformation with TracedTypeInformation {
final ElementInContainerTypeInformation elementType;
- /** The container type before it is inferred. */
+ /// The container type before it is inferred.
final AbstractValue originalType;
- /** The length at the allocation site. */
+ /// The length at the allocation site.
final int originalLength;
- /** The length after the container has been traced. */
+ /// The length after the container has been traced.
int inferredLength;
- /**
- * Whether this list goes through a growable check.
- * We conservatively assume it does.
- */
+ /// Whether this list goes through a growable check.
+ /// We conservatively assume it does.
bool checksGrowable = true;
ListTypeInformation(
@@ -1600,10 +1566,8 @@
}
}
-/**
- * An [ElementInContainerTypeInformation] holds the common type of the
- * elements in a [ListTypeInformation].
- */
+/// An [ElementInContainerTypeInformation] holds the common type of the
+/// elements in a [ListTypeInformation].
class ElementInContainerTypeInformation extends InferredTypeInformation {
ElementInContainerTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation context, elementType)
@@ -1616,10 +1580,8 @@
}
}
-/**
- * A [MapTypeInformation] is a [TypeInformation] created
- * for maps.
- */
+/// A [MapTypeInformation] is a [TypeInformation] created
+/// for maps.
class MapTypeInformation extends TypeInformation with TracedTypeInformation {
// When in Dictionary mode, this map tracks the type of the values that
// have been assigned to a specific [String] key.
@@ -1777,10 +1739,8 @@
}
}
-/**
- * A [KeyInMapTypeInformation] holds the common type
- * for the keys in a [MapTypeInformation]
- */
+/// A [KeyInMapTypeInformation] holds the common type
+/// for the keys in a [MapTypeInformation]
class KeyInMapTypeInformation extends InferredTypeInformation {
KeyInMapTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation context, TypeInformation keyType)
@@ -1793,10 +1753,8 @@
String toString() => 'Key in Map $type';
}
-/**
- * A [ValueInMapTypeInformation] holds the common type
- * for the values in a [MapTypeInformation]
- */
+/// A [ValueInMapTypeInformation] holds the common type
+/// for the values in a [MapTypeInformation]
class ValueInMapTypeInformation extends InferredTypeInformation {
// [nonNull] is set to true if this value is known to be part of the map.
// Note that only values assigned to a specific key value in dictionary
@@ -1821,10 +1779,8 @@
String toString() => 'Value in Map $type';
}
-/**
- * A [PhiElementTypeInformation] is an union of
- * [ElementTypeInformation], that is local to a method.
- */
+/// A [PhiElementTypeInformation] is an union of
+/// [ElementTypeInformation], that is local to a method.
class PhiElementTypeInformation extends TypeInformation {
final ir.Node branchNode;
final Local variable;
@@ -1893,9 +1849,7 @@
}
}
-/**
- * Mixin for [TypeInformation] nodes that can bail out during tracing.
- */
+/// Mixin for [TypeInformation] nodes that can bail out during tracing.
abstract class TracedTypeInformation implements TypeInformation {
/// Set to false once analysis has succeeded.
bool bailedOut = true;
@@ -1905,19 +1859,16 @@
Set<TypeInformation> _flowsInto;
- /**
- * The set of [TypeInformation] nodes where values from the traced node could
- * flow in.
- */
+ /// The set of [TypeInformation] nodes where values from the traced node could
+ /// flow in.
Set<TypeInformation> get flowsInto {
return (_flowsInto == null)
? const ImmutableEmptySet<TypeInformation>()
: _flowsInto;
}
- /**
- * Adds [nodes] to the sets of values this [TracedTypeInformation] flows into.
- */
+ /// Adds [nodes] to the sets of values this [TracedTypeInformation] flows
+ /// into.
void addFlowsIntoTargets(Iterable<TypeInformation> nodes) {
if (_flowsInto == null) {
_flowsInto = nodes.toSet();
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index cff86a1..21c5316 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -43,9 +43,7 @@
bool checkClassEntity(ClassEntity cls);
}
-/**
- * The class [SimpleInferrerVisitor] will use when working on types.
- */
+/// The class [SimpleInferrerVisitor] will use when working on types.
class TypeSystem {
final JClosedWorld _closedWorld;
final TypeSystemStrategy strategy;
@@ -274,10 +272,8 @@
_abstractValueDomain, value, _abstractValueDomain.boolType);
}
- /**
- * Returns the least upper bound between [firstType] and
- * [secondType].
- */
+ /// Returns the least upper bound between [firstType] and
+ /// [secondType].
TypeInformation computeLUB(
TypeInformation firstType, TypeInformation secondType) {
if (firstType == null) return secondType;
@@ -291,22 +287,18 @@
_abstractValueDomain.union(firstType.type, secondType.type));
}
- /**
- * Returns `true` if `selector` should be updated to reflect the new
- * `receiverType`.
- */
+ /// Returns `true` if `selector` should be updated to reflect the new
+ /// `receiverType`.
bool selectorNeedsUpdate(TypeInformation info, AbstractValue mask) {
return info.type != mask;
}
- /**
- * Returns a new receiver type for this [selector] applied to
- * [receiverType].
- *
- * The option [isConditional] is true when [selector] was seen in a
- * conditional send (e.g. `a?.selector`), in which case the returned type may
- * be null.
- */
+ /// Returns a new receiver type for this [selector] applied to
+ /// [receiverType].
+ ///
+ /// The option [isConditional] is true when [selector] was seen in a
+ /// conditional send (e.g. `a?.selector`), in which case the returned type
+ /// may be null.
TypeInformation refineReceiver(
Selector selector, AbstractValue mask, TypeInformation receiver,
{bool isConditional}) {
@@ -333,11 +325,9 @@
return newType;
}
- /**
- * Returns the intersection between [type] and [annotation].
- * [isNullable] indicates whether the annotation implies a null
- * type.
- */
+ /// Returns the intersection between [type] and [annotation].
+ /// [isNullable] indicates whether the annotation implies a null
+ /// type.
TypeInformation narrowType(TypeInformation type, DartType annotation,
{bool isNullable: true}) {
if (annotation.treatAsDynamic) return type;
@@ -377,9 +367,7 @@
}
}
- /**
- * Returns the non-nullable type of [type].
- */
+ /// Returns the non-nullable type of [type].
TypeInformation narrowNotNull(TypeInformation type) {
if (_abstractValueDomain.isExact(type.type).isDefinitelyTrue) {
return type;
@@ -423,9 +411,7 @@
return typeInformation;
}
- /**
- * Returns the internal inferrer representation for [mask].
- */
+ /// Returns the internal inferrer representation for [mask].
ConcreteTypeInformation getConcreteTypeFor(AbstractValue mask) {
assert(mask != null);
return concreteTypes.putIfAbsent(mask, () {
@@ -558,9 +544,7 @@
return info.isConcrete ? info.type : mask;
}
- /**
- * Returns a new type that unions [firstInput] and [secondInput].
- */
+ /// Returns a new type that unions [firstInput] and [secondInput].
TypeInformation allocateDiamondPhi(
TypeInformation firstInput, TypeInformation secondInput) {
PhiElementTypeInformation result = new PhiElementTypeInformation(
@@ -582,10 +566,8 @@
return result;
}
- /**
- * Returns a new type for holding the potential types of [element].
- * [inputType] is the first incoming type of the phi.
- */
+ /// Returns a new type for holding the potential types of [element].
+ /// [inputType] is the first incoming type of the phi.
PhiElementTypeInformation allocatePhi(
ir.Node node, Local variable, TypeInformation inputType,
{bool isTry}) {
@@ -601,13 +583,11 @@
return _addPhi(node, variable, inputType, isTry);
}
- /**
- * Returns a new type for holding the potential types of [element].
- * [inputType] is the first incoming type of the phi. [allocateLoopPhi]
- * only differs from [allocatePhi] in that it allows the underlying
- * implementation of [TypeSystem] to differentiate Phi nodes due to loops
- * from other merging uses.
- */
+ /// Returns a new type for holding the potential types of [element].
+ /// [inputType] is the first incoming type of the phi. [allocateLoopPhi]
+ /// only differs from [allocatePhi] in that it allows the underlying
+ /// implementation of [TypeSystem] to differentiate Phi nodes due to loops
+ /// from other merging uses.
PhiElementTypeInformation allocateLoopPhi(
ir.Node node, Local variable, TypeInformation inputType,
{bool isTry}) {
@@ -615,12 +595,10 @@
return _addPhi(node, variable, inputType, isTry);
}
- /**
- * Simplies the phi representing [element] and of the type
- * [phiType]. For example, if this phi has one incoming input, an
- * implementation of this method could just return that incoming
- * input type.
- */
+ /// Simplies the phi representing [element] and of the type
+ /// [phiType]. For example, if this phi has one incoming input, an
+ /// implementation of this method could just return that incoming
+ /// input type.
TypeInformation simplifyPhi(
ir.Node node, Local variable, PhiElementTypeInformation phiType) {
assert(phiType.branchNode == node);
@@ -628,9 +606,7 @@
return phiType;
}
- /**
- * Adds [newType] as an input of [phiType].
- */
+ /// Adds [newType] as an input of [phiType].
PhiElementTypeInformation addPhiInput(Local variable,
PhiElementTypeInformation phiType, TypeInformation newType) {
phiType.addAssignment(newType);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
index 8b67ca6..8463350 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
@@ -4,14 +4,12 @@
part of masks;
-/**
- * A [DictionaryTypeMask] is a [TypeMask] for a specific allocation
- * site of a map (currently only internal Map class) that is used as
- * a dictionary, i.e. a mapping from a set of statically known strings
- * to values. These typemasks only come into existence after the
- * [TypeGraphInferrer] has successfully identified such a usage. Otherwise,
- * the more general [MapTypeMask] is used.
- */
+/// A [DictionaryTypeMask] is a [TypeMask] for a specific allocation
+/// site of a map (currently only internal Map class) that is used as
+/// a dictionary, i.e. a mapping from a set of statically known strings
+/// to values. These typemasks only come into existence after the
+/// [TypeGraphInferrer] has successfully identified such a usage. Otherwise,
+/// the more general [MapTypeMask] is used.
class DictionaryTypeMask extends MapTypeMask {
/// Tag used for identifying serialized [DictionaryTypeMask] objects in a
/// debugging data stream.
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
index 2dfe38a..41db5e8 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/flat_type_mask.dart
@@ -4,10 +4,8 @@
part of masks;
-/**
- * A flat type mask is a type mask that has been flattened to contain a
- * base type.
- */
+/// A flat type mask is a type mask that has been flattened to contain a
+/// base type.
class FlatTypeMask implements TypeMask {
/// Tag used for identifying serialized [FlatTypeMask] objects in a
/// debugging data stream.
@@ -45,10 +43,8 @@
FlatTypeMask.internal(this.base, this.flags);
- /**
- * Ensures that the generated mask is normalized, i.e., a call to
- * [TypeMask.assertIsNormalized] with the factory's result returns `true`.
- */
+ /// Ensures that the generated mask is normalized, i.e., a call to
+ /// [TypeMask.assertIsNormalized] with the factory's result returns `true`.
factory FlatTypeMask.normalized(
ClassEntity base, int flags, JClosedWorld world) {
if ((flags >> 1) == EMPTY || ((flags >> 1) == EXACT)) {
@@ -260,9 +256,7 @@
}
}
- /**
- * Returns whether or not this type mask contains all types.
- */
+ /// Returns whether or not this type mask contains all types.
bool containsAll(JClosedWorld closedWorld) {
if (isEmptyOrNull || isExact) return false;
return identical(base, closedWorld.commonElements.objectClass);
@@ -519,11 +513,9 @@
: new TypeMask.nonNullEmpty();
}
- /**
- * Returns whether [element] is a potential target when being
- * invoked on this type mask. [selector] is used to ensure library
- * privacy is taken into account.
- */
+ /// Returns whether [element] is a potential target when being
+ /// invoked on this type mask. [selector] is used to ensure library
+ /// privacy is taken into account.
bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld) {
CommonElements commonElements = closedWorld.commonElements;
assert(element.name == name.text);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
index 781a51e..7b8e73a 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
@@ -4,10 +4,8 @@
part of masks;
-/**
- * A type mask that wraps an other one, and delegate all its
- * implementation methods to it.
- */
+/// A type mask that wraps an other one, and delegate all its
+/// implementation methods to it.
abstract class ForwardingTypeMask implements TypeMask {
TypeMask get forwardTo;
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
index 4a59fcd..2486256 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
@@ -4,11 +4,9 @@
part of masks;
-/**
- * A [MapTypeMask] is a [TypeMask] for a specific allocation
- * site of a map (currently only internal Map class) that will get specialized
- * once the [TypeGraphInferrer] phase finds a key and/or value type for it.
- */
+/// A [MapTypeMask] is a [TypeMask] for a specific allocation
+/// site of a map (currently only internal Map class) that will get specialized
+/// once the [TypeGraphInferrer] phase finds a key and/or value type for it.
class MapTypeMask extends AllocationTypeMask {
/// Tag used for identifying serialized [MapTypeMask] objects in a
/// debugging data stream.
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
index eb06347..d54859d 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/type_mask.dart
@@ -103,11 +103,9 @@
value,
}
-/**
- * A type mask represents a set of contained classes, but the
- * operations on it are not guaranteed to be precise and they may
- * yield conservative answers that contain too many classes.
- */
+/// A type mask represents a set of contained classes, but the
+/// operations on it are not guaranteed to be precise and they may
+/// yield conservative answers that contain too many classes.
abstract class TypeMask implements AbstractValue {
factory TypeMask(
ClassEntity base, int kind, bool isNullable, JClosedWorld closedWorld) {
@@ -245,10 +243,8 @@
/// Serializes this [TypeMask] to [sink].
void writeToDataSink(DataSink sink);
- /**
- * If [mask] is forwarding, returns the first non-forwarding [TypeMask] in
- * [mask]'s forwarding chain.
- */
+ /// If [mask] is forwarding, returns the first non-forwarding [TypeMask] in
+ /// [mask]'s forwarding chain.
static TypeMask nonForwardingMask(mask) {
while (mask.isForwarding) {
mask = mask.forwardTo;
@@ -256,13 +252,11 @@
return mask;
}
- /**
- * Asserts that this mask uses the smallest possible representation for
- * its types. Currently, we normalize subtype and subclass to exact if no
- * subtypes or subclasses are present and subtype to subclass if only
- * subclasses exist. We also normalize exact to empty if the corresponding
- * baseclass was never instantiated.
- */
+ /// Asserts that this mask uses the smallest possible representation for
+ /// its types. Currently, we normalize subtype and subclass to exact if no
+ /// subtypes or subclasses are present and subtype to subclass if only
+ /// subclasses exist. We also normalize exact to empty if the corresponding
+ /// baseclass was never instantiated.
static bool assertIsNormalized(TypeMask mask, JClosedWorld closedWorld) {
String reason = getNotNormalizedReason(mask, closedWorld);
assert(reason == null,
@@ -307,14 +301,10 @@
return 'Unknown type mask $mask.';
}
- /**
- * Returns a nullable variant of [this] type mask.
- */
+ /// Returns a nullable variant of [this] type mask.
TypeMask nullable();
- /**
- * Returns a non-nullable variant of [this] type mask.
- */
+ /// Returns a non-nullable variant of [this] type mask.
TypeMask nonNullable();
/// Whether nothing matches this mask, not even null.
@@ -361,38 +351,28 @@
bool containsOnlyString(JClosedWorld closedWorld);
bool containsOnly(ClassEntity cls);
- /**
- * Compares two [TypeMask] objects for structural equality.
- *
- * Note: This may differ from semantic equality in the set containment sense.
- * Use [containsMask] and [isInMask] for that, instead.
- */
+ /// Compares two [TypeMask] objects for structural equality.
+ ///
+ /// Note: This may differ from semantic equality in the set containment sense.
+ /// Use [containsMask] and [isInMask] for that, instead.
bool operator ==(other);
- /**
- * If this returns `true`, [other] is guaranteed to be a supertype of this
- * mask, i.e., this mask is in [other]. However, the inverse does not hold.
- * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
- * false negatives.
- */
+ /// If this returns `true`, [other] is guaranteed to be a supertype of this
+ /// mask, i.e., this mask is in [other]. However, the inverse does not hold.
+ /// Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
+ /// false negatives.
bool isInMask(TypeMask other, JClosedWorld closedWorld);
- /**
- * If this returns `true`, [other] is guaranteed to be a subtype of this mask,
- * i.e., this mask contains [other]. However, the inverse does not hold.
- * Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
- * false negatives.
- */
+ /// If this returns `true`, [other] is guaranteed to be a subtype of this
+ /// mask, i.e. this mask contains [other]. However, the inverse does not hold.
+ /// Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
+ /// false negatives.
bool containsMask(TypeMask other, JClosedWorld closedWorld);
- /**
- * Returns whether this type mask is an instance of [cls].
- */
+ /// Returns whether this type mask is an instance of [cls].
bool satisfies(ClassEntity cls, JClosedWorld closedWorld);
- /**
- * Returns whether or not this type mask contains the given class [cls].
- */
+ /// Returns whether or not this type mask contains the given class [cls].
bool contains(ClassEntity cls, JClosedWorld closedWorld);
/// Returns whether or not this type mask contains all types.
@@ -402,17 +382,13 @@
/// otherwise returns `null`. This method is conservative.
ClassEntity singleClass(JClosedWorld closedWorld);
- /**
- * Returns a type mask representing the union of [this] and [other].
- */
+ /// Returns a type mask representing the union of [this] and [other].
TypeMask union(TypeMask other, JClosedWorld closedWorld);
/// Returns whether the intersection of this and [other] is empty.
bool isDisjoint(TypeMask other, JClosedWorld closedWorld);
- /**
- * Returns a type mask representing the intersection of [this] and [other].
- */
+ /// Returns a type mask representing the intersection of [this] and [other].
TypeMask intersection(TypeMask other, JClosedWorld closedWorld);
/// Returns whether [element] is a potential target when being invoked on this
@@ -423,9 +399,7 @@
/// [noSuchMethod].
bool needsNoSuchMethodHandling(Selector selector, JClosedWorld world);
- /**
- * Returns the [element] that is known to always be hit at runtime
- * on this mask. Returns null if there is none.
- */
+ /// Returns the [element] that is known to always be hit at runtime
+ /// on this mask. Returns null if there is none.
MemberEntity locateSingleMember(Selector selector, JClosedWorld closedWorld);
}
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
index 0d252f0..2f1f9de 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/union_type_mask.dart
@@ -232,14 +232,12 @@
bool get isForwarding => false;
bool get isValue => false;
- /**
- * Checks whether [other] is contained in this union.
- *
- * Invariants:
- * - [other] may not be a [UnionTypeMask] itself
- * - the cheap test matching against individual members of [disjointMasks]
- * must have failed.
- */
+ /// Checks whether [other] is contained in this union.
+ ///
+ /// Invariants:
+ /// - [other] may not be a [UnionTypeMask] itself
+ /// - the cheap test matching against individual members of [disjointMasks]
+ /// must have failed.
bool slowContainsCheck(TypeMask other, JClosedWorld closedWorld) {
// Unions should never make it here.
assert(!other.isUnion);
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 4fb641a..0d3b387 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -549,6 +549,7 @@
CallPosition.getSemanticPositionForCall(node);
registerPosition(callPosition.sourcePositionKind);
break;
+ case StepKind.ACCESS:
case StepKind.NEW:
case StepKind.RETURN:
case StepKind.BREAK:
@@ -771,6 +772,7 @@
FUN_EXIT,
CALL,
NEW,
+ ACCESS,
RETURN,
BREAK,
CONTINUE,
@@ -1010,6 +1012,18 @@
@override
visitAccess(js.PropertyAccess node) {
visit(node.receiver);
+ notifyStep(
+ node,
+ // Technically we'd like to use the offset of the `.` in the property
+ // access, but the js_ast doesn't expose it. Since this is only used to
+ // search backwards for inlined frames, we use the receiver's END offset
+ // instead as an approximation. Note that the END offset points one
+ // character after the end of the node, so it is likely always the
+ // offset we want.
+ getOffsetForNode(
+ node, getSyntaxOffset(node.receiver, kind: CodePositionKind.END)),
+ StepKind.ACCESS);
+ steps.add(node);
visit(node.selector);
}
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index 19ff07f..5daea39 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -14,8 +14,10 @@
/// and a precomputed cache for complex expression type.
class CachedStaticType extends StaticTypeBase implements StaticTypeProvider {
final Map<ir.Expression, ir.DartType> _cache;
+ final ThisInterfaceType thisType;
- CachedStaticType(ir.TypeEnvironment typeEnvironment, this._cache)
+ CachedStaticType(
+ ir.TypeEnvironment typeEnvironment, this._cache, this.thisType)
: super(typeEnvironment);
@override
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
new file mode 100644
index 0000000..570fa82
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -0,0 +1,534 @@
+// 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:front_end/src/api_unstable/dart2js.dart'
+ show operatorFromString;
+
+import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
+
+import '../common.dart';
+import 'scope.dart';
+import 'static_type.dart';
+import 'static_type_base.dart';
+import 'util.dart';
+
+abstract class ImpactBuilder extends StaticTypeVisitor {
+ final VariableScopeModel variableScopeModel;
+
+ ImpactBuilder(ir.TypeEnvironment typeEnvironment,
+ ir.ClassHierarchy classHierarchy, this.variableScopeModel)
+ : super(typeEnvironment, classHierarchy);
+
+ ClassRelation _computeClassRelationFromType(ir.DartType type) {
+ if (type is ThisInterfaceType) {
+ return ClassRelation.thisExpression;
+ } else if (type is ExactInterfaceType) {
+ return ClassRelation.exact;
+ } else {
+ return ClassRelation.subtype;
+ }
+ }
+
+ void registerIntLiteral(int value);
+
+ @override
+ void handleIntLiteral(ir.IntLiteral node) {
+ registerIntLiteral(node.value);
+ }
+
+ void registerDoubleLiteral(double value);
+
+ @override
+ void handleDoubleLiteral(ir.DoubleLiteral node) {
+ registerDoubleLiteral(node.value);
+ }
+
+ void registerBoolLiteral(bool value);
+
+ @override
+ void handleBoolLiteral(ir.BoolLiteral node) {
+ registerBoolLiteral(node.value);
+ }
+
+ void registerStringLiteral(String value);
+
+ @override
+ void handleStringLiteral(ir.StringLiteral node) {
+ registerStringLiteral(node.value);
+ }
+
+ void registerSymbolLiteral(String value);
+
+ @override
+ void handleSymbolLiteral(ir.SymbolLiteral node) {
+ registerSymbolLiteral(node.value);
+ }
+
+ void registerNullLiteral();
+
+ @override
+ void handleNullLiteral(ir.NullLiteral node) {
+ registerNullLiteral();
+ }
+
+ void registerListLiteral(ir.DartType elementType,
+ {bool isConstant, bool isEmpty});
+
+ @override
+ void handleListLiteral(ir.ListLiteral node) {
+ registerListLiteral(node.typeArgument,
+ isConstant: node.isConst, isEmpty: node.expressions.isEmpty);
+ }
+
+ void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
+ {bool isConstant, bool isEmpty});
+
+ @override
+ void handleMapLiteral(ir.MapLiteral node) {
+ registerMapLiteral(node.keyType, node.valueType,
+ isConstant: node.isConst, isEmpty: node.entries.isEmpty);
+ }
+
+ void registerStaticTearOff(
+ ir.Procedure procedure, ir.LibraryDependency import);
+
+ void registerStaticGet(ir.Member member, ir.LibraryDependency import);
+
+ @override
+ void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {
+ ir.Member target = node.target;
+ if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) {
+ registerStaticTearOff(target, getDeferredImport(node));
+ } else {
+ registerStaticGet(target, getDeferredImport(node));
+ }
+ }
+
+ void registerStaticSet(ir.Member member, ir.LibraryDependency import);
+
+ @override
+ void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
+ registerStaticSet(node.target, getDeferredImport(node));
+ }
+
+ void registerAssert({bool withMessage});
+
+ @override
+ void handleAssertStatement(ir.AssertStatement node) {
+ registerAssert(withMessage: node.message != null);
+ }
+
+ void registerGenericInstantiation(
+ ir.FunctionType expressionType, List<ir.DartType> typeArguments);
+
+ @override
+ void handleInstantiation(ir.Instantiation node,
+ ir.FunctionType expressionType, ir.DartType resultType) {
+ registerGenericInstantiation(expressionType, node.typeArguments);
+ }
+
+ void registerSyncStar(ir.DartType elementType);
+
+ void registerAsync(ir.DartType elementType);
+
+ void registerAsyncStar(ir.DartType elementType);
+
+ void handleAsyncMarker(ir.FunctionNode function) {
+ ir.AsyncMarker asyncMarker = function.asyncMarker;
+ ir.DartType returnType = function.returnType;
+
+ switch (asyncMarker) {
+ case ir.AsyncMarker.Sync:
+ break;
+ case ir.AsyncMarker.SyncStar:
+ ir.DartType elementType = const ir.DynamicType();
+ if (returnType is ir.InterfaceType) {
+ if (returnType.classNode == typeEnvironment.coreTypes.iterableClass) {
+ elementType = returnType.typeArguments.first;
+ }
+ }
+ registerSyncStar(elementType);
+ break;
+
+ case ir.AsyncMarker.Async:
+ ir.DartType elementType = const ir.DynamicType();
+ if (returnType is ir.InterfaceType) {
+ if (returnType.classNode == typeEnvironment.coreTypes.futureOrClass) {
+ elementType = returnType.typeArguments.first;
+ } else if (returnType.classNode ==
+ typeEnvironment.coreTypes.futureClass) {
+ elementType = returnType.typeArguments.first;
+ }
+ }
+ registerAsync(elementType);
+ break;
+
+ case ir.AsyncMarker.AsyncStar:
+ ir.DartType elementType = const ir.DynamicType();
+ if (returnType is ir.InterfaceType) {
+ if (returnType.classNode == typeEnvironment.coreTypes.streamClass) {
+ elementType = returnType.typeArguments.first;
+ }
+ }
+ registerAsyncStar(elementType);
+ break;
+
+ case ir.AsyncMarker.SyncYielding:
+ failedAt(CURRENT_ELEMENT_SPANNABLE,
+ "Unexpected async marker: ${asyncMarker}");
+ }
+ }
+
+ void registerStringConcatenation();
+
+ @override
+ void handleStringConcatenation(ir.StringConcatenation node) {
+ registerStringConcatenation();
+ }
+
+ void registerLocalFunction(ir.TreeNode node);
+
+ @override
+ Null handleFunctionDeclaration(ir.FunctionDeclaration node) {
+ registerLocalFunction(node);
+ handleAsyncMarker(node.function);
+ }
+
+ @override
+ void handleFunctionExpression(ir.FunctionExpression node) {
+ registerLocalFunction(node);
+ handleAsyncMarker(node.function);
+ }
+
+ void registerLocalWithoutInitializer();
+
+ @override
+ void handleVariableDeclaration(ir.VariableDeclaration node) {
+ if (node.initializer == null) {
+ registerLocalWithoutInitializer();
+ }
+ }
+
+ void registerIsCheck(ir.DartType type);
+
+ @override
+ void handleIsExpression(ir.IsExpression node) {
+ registerIsCheck(node.type);
+ }
+
+ void registerImplicitCast(ir.DartType type);
+
+ void registerAsCast(ir.DartType type);
+
+ @override
+ void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {
+ if (typeEnvironment.isSubtypeOf(operandType, node.type)) {
+ // Skip unneeded casts.
+ return;
+ }
+ if (node.isTypeError) {
+ registerImplicitCast(node.type);
+ } else {
+ registerAsCast(node.type);
+ }
+ }
+
+ void registerThrow();
+
+ @override
+ void handleThrow(ir.Throw node) {
+ registerThrow();
+ }
+
+ void registerSyncForIn(ir.DartType iterableType);
+
+ void registerAsyncForIn(ir.DartType iterableType);
+
+ @override
+ void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {
+ if (node.isAsync) {
+ registerAsyncForIn(iterableType);
+ } else {
+ registerSyncForIn(iterableType);
+ }
+ }
+
+ void registerCatch();
+
+ void registerStackTrace();
+
+ void registerCatchType(ir.DartType type);
+
+ @override
+ void handleCatch(ir.Catch node) {
+ registerCatch();
+ if (node.stackTrace != null) {
+ registerStackTrace();
+ }
+ if (node.guard is! ir.DynamicType) {
+ registerCatchType(node.guard);
+ }
+ }
+
+ void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import);
+
+ @override
+ void handleTypeLiteral(ir.TypeLiteral node) {
+ registerTypeLiteral(node.type, getDeferredImport(node));
+ }
+
+ void registerFieldInitializer(ir.Field node);
+
+ @override
+ void handleFieldInitializer(ir.FieldInitializer node) {
+ registerFieldInitializer(node.field);
+ }
+
+ void registerLoadLibrary();
+
+ @override
+ void handleLoadLibrary(ir.LoadLibrary node) {
+ registerLoadLibrary();
+ }
+
+ void registerRedirectingInitializer(
+ ir.Constructor constructor, ir.Arguments arguments);
+
+ void handleRedirectingInitializer(
+ ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
+ registerRedirectingInitializer(node.target, node.arguments);
+ }
+
+ void registerParameterCheck(ir.DartType type);
+
+ @override
+ void handleParameter(ir.VariableDeclaration parameter) {
+ registerParameterCheck(parameter.type);
+ }
+
+ @override
+ void handleSignature(ir.FunctionNode node) {
+ for (ir.TypeParameter parameter in node.typeParameters) {
+ registerParameterCheck(parameter.bound);
+ }
+ }
+
+ void registerLazyField();
+
+ @override
+ void handleField(ir.Field field) {
+ registerParameterCheck(field.type);
+ if (field.initializer != null) {
+ if (!field.isInstanceMember &&
+ !field.isConst &&
+ field.initializer is! ir.NullLiteral) {
+ registerLazyField();
+ }
+ } else {
+ registerNullLiteral();
+ }
+ }
+
+ @override
+ void handleProcedure(ir.Procedure procedure) {
+ handleAsyncMarker(procedure.function);
+ }
+
+ void registerNew(ir.Member constructor, ir.InterfaceType type,
+ ir.Arguments arguments, ir.LibraryDependency import,
+ {bool isConst});
+
+ @override
+ void handleConstructorInvocation(ir.ConstructorInvocation node,
+ ArgumentTypes argumentTypes, ir.DartType resultType) {
+ registerNew(node.target, node.constructedType, node.arguments,
+ getDeferredImport(node),
+ isConst: node.isConst);
+ }
+
+ void registerStaticInvocation(
+ ir.Procedure target, ir.Arguments arguments, ir.LibraryDependency import);
+
+ @override
+ void handleStaticInvocation(ir.StaticInvocation node,
+ ArgumentTypes argumentTypes, ir.DartType returnType) {
+ if (node.target.kind == ir.ProcedureKind.Factory) {
+ // TODO(johnniwinther): We should not mark the type as instantiated but
+ // rather follow the type arguments directly.
+ //
+ // Consider this:
+ //
+ // abstract class A<T> {
+ // factory A.regular() => new B<T>();
+ // factory A.redirect() = B<T>;
+ // }
+ //
+ // class B<T> implements A<T> {}
+ //
+ // main() {
+ // print(new A<int>.regular() is B<int>);
+ // print(new A<String>.redirect() is B<String>);
+ // }
+ //
+ // To track that B is actually instantiated as B<int> and B<String> we
+ // need to follow the type arguments passed to A.regular and A.redirect
+ // to B. Currently, we only do this soundly if we register A<int> and
+ // A<String> as instantiated. We should instead register that A.T is
+ // instantiated as int and String.
+ registerNew(
+ node.target,
+ new ir.InterfaceType(
+ node.target.enclosingClass, node.arguments.types),
+ node.arguments,
+ getDeferredImport(node),
+ isConst: node.isConst);
+ } else {
+ registerStaticInvocation(
+ node.target, node.arguments, getDeferredImport(node));
+ }
+ }
+
+ void registerLocalFunctionInvocation(
+ ir.FunctionDeclaration localFunction, ir.Arguments arguments);
+
+ void registerDynamicInvocation(ir.DartType receiverType,
+ ClassRelation relation, ir.Name name, ir.Arguments arguments);
+
+ void registerInstanceInvocation(ir.DartType receiverType,
+ ClassRelation relation, ir.Member target, ir.Arguments arguments);
+
+ void registerFunctionInvocation(
+ ir.DartType receiverType, ir.Arguments arguments);
+
+ @override
+ void handleMethodInvocation(
+ ir.MethodInvocation node,
+ ir.DartType receiverType,
+ ArgumentTypes argumentTypes,
+ ir.DartType returnType) {
+ ir.Expression receiver = node.receiver;
+ if (receiver is ir.VariableGet &&
+ receiver.variable.isFinal &&
+ receiver.variable.parent is ir.FunctionDeclaration) {
+ registerLocalFunctionInvocation(receiver.variable.parent, node.arguments);
+ } else {
+ ClassRelation relation = _computeClassRelationFromType(receiverType);
+
+ ir.Member interfaceTarget = node.interfaceTarget;
+ if (interfaceTarget == null) {
+ registerDynamicInvocation(
+ receiverType, relation, node.name, node.arguments);
+ // TODO(johnniwinther): Avoid treating a known function call as a
+ // dynamic call when CFE provides a way to distinguish the two.
+ if (operatorFromString(node.name.name) == null &&
+ receiverType is ir.DynamicType) {
+ // We might implicitly call a getter that returns a function.
+ registerFunctionInvocation(const ir.DynamicType(), node.arguments);
+ }
+ } else {
+ if (interfaceTarget is ir.Field ||
+ interfaceTarget is ir.Procedure &&
+ interfaceTarget.kind == ir.ProcedureKind.Getter) {
+ registerInstanceInvocation(
+ receiverType, relation, interfaceTarget, node.arguments);
+ registerFunctionInvocation(
+ interfaceTarget.getterType, node.arguments);
+ } else {
+ registerInstanceInvocation(
+ receiverType, relation, interfaceTarget, node.arguments);
+ }
+ }
+ }
+ }
+
+ @override
+ void handleDirectMethodInvocation(
+ ir.DirectMethodInvocation node,
+ ir.DartType receiverType,
+ ArgumentTypes argumentTypes,
+ ir.DartType returnType) {
+ registerInstanceInvocation(
+ receiverType, ClassRelation.exact, node.target, node.arguments);
+ }
+
+ void registerDynamicGet(
+ ir.DartType receiverType, ClassRelation relation, ir.Name name);
+
+ void registerInstanceGet(
+ ir.DartType receiverType, ClassRelation relation, ir.Member target);
+
+ @override
+ void handlePropertyGet(
+ ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
+ ClassRelation relation = _computeClassRelationFromType(receiverType);
+ if (node.interfaceTarget != null) {
+ registerInstanceGet(receiverType, relation, node.interfaceTarget);
+ } else {
+ registerDynamicGet(receiverType, relation, node.name);
+ }
+ }
+
+ @override
+ void handleDirectPropertyGet(ir.DirectPropertyGet node,
+ ir.DartType receiverType, ir.DartType resultType) {
+ registerInstanceGet(receiverType, ClassRelation.exact, node.target);
+ }
+
+ void registerDynamicSet(
+ ir.DartType receiverType, ClassRelation relation, ir.Name name);
+
+ void registerInstanceSet(
+ ir.DartType receiverType, ClassRelation relation, ir.Member target);
+
+ @override
+ void handlePropertySet(
+ ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
+ ClassRelation relation = _computeClassRelationFromType(receiverType);
+ if (node.interfaceTarget != null) {
+ registerInstanceSet(receiverType, relation, node.interfaceTarget);
+ } else {
+ registerDynamicSet(receiverType, relation, node.name);
+ }
+ }
+
+ @override
+ void handleDirectPropertySet(ir.DirectPropertySet node,
+ ir.DartType receiverType, ir.DartType valueType) {
+ registerInstanceSet(receiverType, ClassRelation.exact, node.target);
+ }
+
+ void registerSuperInvocation(ir.Name name, ir.Arguments arguments);
+
+ @override
+ void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
+ ArgumentTypes argumentTypes, ir.DartType returnType) {
+ registerSuperInvocation(node.name, node.arguments);
+ }
+
+ void registerSuperGet(ir.Name name);
+
+ @override
+ void handleSuperPropertyGet(
+ ir.SuperPropertyGet node, ir.DartType resultType) {
+ registerSuperGet(node.name);
+ }
+
+ void registerSuperSet(ir.Name name);
+
+ @override
+ void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
+ registerSuperSet(node.name);
+ }
+
+ void registerSuperInitializer(
+ ir.Constructor source, ir.Constructor target, ir.Arguments arguments);
+
+ @override
+ void handleSuperInitializer(
+ ir.SuperInitializer node, ArgumentTypes argumentTypes) {
+ registerSuperInitializer(node.parent, node.target, node.arguments);
+ }
+}
diff --git a/pkg/compiler/lib/src/kernel/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
similarity index 72%
rename from pkg/compiler/lib/src/kernel/runtime_type_analysis.dart
rename to pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index b5da035..cde8217 100644
--- a/pkg/compiler/lib/src/kernel/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -1,18 +1,86 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2019, 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:kernel/ast.dart' as ir;
import '../common/names.dart';
-import '../elements/types.dart';
-import '../ir/util.dart';
-import '../universe/feature.dart';
-import 'element_map.dart';
+import 'util.dart';
-/// Computes the [RuntimeTypeUse] corresponding to the `e.runtimeType` [node].
-RuntimeTypeUse computeRuntimeTypeUse(
- KernelToElementMap elementMap, ir.PropertyGet node) {
+/// Enum for recognized use kinds of `Object.runtimeType`.
+enum RuntimeTypeUseKind {
+ /// Unknown use of `Object.runtimeType`. This is the fallback value if the
+ /// usage didn't match any of the recognized patterns.
+ unknown,
+
+ /// `Object.runtimeType` used in a pattern like
+ /// `a.runtimeType == b.runtimeType`.
+ equals,
+
+ /// `Object.runtimeType` used in a pattern like `'${e.runtimeType}'` or
+ /// `e.runtimeType.toString()`.
+ string,
+}
+
+/// Data object use for computing static type information on uses of
+/// `Object.runtimeType`.
+class RuntimeTypeUseData {
+ /// The use kind of `Object.runtimeType`.
+ final RuntimeTypeUseKind kind;
+
+ /// The property get for the left (or single) occurrence of `.runtimeType`.
+ final ir.PropertyGet leftRuntimeTypeExpression;
+
+ /// The receiver expression.
+ final ir.Expression receiver;
+
+ /// The static type of the receiver expression. This is set in the static type
+ /// visitor.
+ ir.DartType receiverType;
+
+ /// The property get for the right occurrence of `.runtimeType` when [kind]
+ /// is `RuntimeTypeUseKind.equals`.
+ final ir.PropertyGet rightRuntimeTypeExpression;
+
+ /// The argument expression if [kind] is `RuntimeTypeUseKind.equals`.
+ final ir.Expression argument;
+
+ /// The static type of the argument expression. This is set in the static type
+ /// visitor.
+ ir.DartType argumentType;
+
+ RuntimeTypeUseData(this.kind, this.leftRuntimeTypeExpression, this.receiver,
+ this.rightRuntimeTypeExpression, this.argument);
+
+ bool get isComplete {
+ switch (kind) {
+ case RuntimeTypeUseKind.unknown:
+ case RuntimeTypeUseKind.string:
+ return receiverType != null;
+ case RuntimeTypeUseKind.equals:
+ return receiverType != null && argumentType != null;
+ }
+ throw new UnsupportedError("Unexpected RuntimeTypeUseKind $kind.");
+ }
+
+ String toString() {
+ return "RuntimeTypeUseData(kind=$kind,"
+ "receiverGet=$leftRuntimeTypeExpression,receiver=$receiver,"
+ "receiverType=$receiverType,argumentGet=$rightRuntimeTypeExpression,"
+ "argument=$argument,argumentType=$argumentType)";
+ }
+}
+
+/// Computes the [RuntimeTypeUseData] corresponding to the `e.runtimeType`
+/// [node].
+///
+/// [cache] is used to ensure that only one [RuntimeTypeUseData] object is
+/// created per case, even for the `==` case.
+RuntimeTypeUseData computeRuntimeTypeUse(
+ Map<ir.PropertyGet, RuntimeTypeUseData> cache, ir.PropertyGet node) {
+ RuntimeTypeUseData receiverData = cache[node];
+ if (receiverData != null) return receiverData;
+
/// Returns `true` if [node] is of the form `e.runtimeType`.
bool isGetRuntimeType(ir.TreeNode node) {
return node is ir.PropertyGet && node.name.name == Identifiers.runtimeType_;
@@ -32,7 +100,9 @@
assert(isGetRuntimeType(node));
// TODO(johnniwinther): Special-case `this.runtimeType`.
+ ir.PropertyGet receiverGet;
ir.Expression receiver;
+ ir.PropertyGet argumentGet;
ir.Expression argument;
RuntimeTypeUseKind kind;
@@ -65,6 +135,7 @@
//
kind = RuntimeTypeUseKind.string;
receiver = nullAware.receiver;
+ receiverGet = node;
}
} else if (nullAware.parent is ir.MethodInvocation) {
ir.MethodInvocation methodInvocation = nullAware.parent;
@@ -87,7 +158,9 @@
// .==(e1.runtimeType)
kind = RuntimeTypeUseKind.equals;
receiver = nullAware.receiver;
+ receiverGet = node;
argument = otherGetRuntimeType.receiver;
+ argumentGet = methodInvocation.arguments.positional.first;
}
NullAwareExpression otherNullAware = getNullAwareExpression(
@@ -106,7 +179,9 @@
//
kind = RuntimeTypeUseKind.equals;
receiver = nullAware.receiver;
+ receiverGet = node;
argument = otherNullAware.receiver;
+ argumentGet = otherNullAware.expression;
}
} else if (isInvokeToString(nullAware.parent)) {
// Detected
@@ -121,6 +196,7 @@
//
kind = RuntimeTypeUseKind.string;
receiver = nullAware.receiver;
+ receiverGet = node;
}
} else if (nullAware.parent is ir.Arguments &&
nullAware.parent.parent is ir.MethodInvocation) {
@@ -146,7 +222,9 @@
// ^
kind = RuntimeTypeUseKind.equals;
receiver = otherGetRuntimeType.receiver;
+ receiverGet = otherGetRuntimeType;
argument = nullAware.receiver;
+ argumentGet = node;
}
if (otherNullAware != null &&
@@ -162,7 +240,9 @@
// ^
kind = RuntimeTypeUseKind.equals;
receiver = otherNullAware.receiver;
+ receiverGet = otherNullAware.expression;
argument = nullAware.receiver;
+ argumentGet = node;
}
}
} else if (nullAware.parent is ir.StringConcatenation) {
@@ -176,6 +256,7 @@
// ^
kind = RuntimeTypeUseKind.string;
receiver = nullAware.receiver;
+ receiverGet = node;
} else {
// Default to unknown
//
@@ -187,6 +268,7 @@
// ^
kind = RuntimeTypeUseKind.unknown;
receiver = nullAware.receiver;
+ receiverGet = node;
}
}
} else if (node.parent is ir.VariableDeclaration &&
@@ -203,6 +285,7 @@
// ^
kind = RuntimeTypeUseKind.string;
receiver = node.receiver;
+ receiverGet = node;
}
} else if (node.parent is ir.MethodInvocation) {
ir.MethodInvocation methodInvocation = node.parent;
@@ -225,7 +308,9 @@
// ^
kind = RuntimeTypeUseKind.equals;
receiver = node.receiver;
+ receiverGet = node;
argument = otherGetRuntimeType.receiver;
+ argumentGet = otherGetRuntimeType;
} else if (nullAware != null && isGetRuntimeType(nullAware.expression)) {
// Detected
//
@@ -238,7 +323,9 @@
// let #t1 = e1 in #t1 == null ? null : #t1.runtimeType)
kind = RuntimeTypeUseKind.equals;
receiver = node.receiver;
+ receiverGet = node;
argument = nullAware.receiver;
+ argumentGet = nullAware.expression;
}
} else if (isInvokeToString(node.parent)) {
// Detected
@@ -247,6 +334,7 @@
// ^
kind = RuntimeTypeUseKind.string;
receiver = node.receiver;
+ receiverGet = node;
}
} else if (node.parent is ir.Arguments &&
node.parent.parent is ir.MethodInvocation) {
@@ -270,7 +358,9 @@
// ^
kind = RuntimeTypeUseKind.equals;
receiver = otherGetRuntimeType.receiver;
+ receiverGet = otherGetRuntimeType;
argument = node.receiver;
+ argumentGet = node;
} else if (nullAware != null && isGetRuntimeType(nullAware.expression)) {
// Detected
//
@@ -283,7 +373,9 @@
// ^
kind = RuntimeTypeUseKind.equals;
receiver = nullAware.receiver;
+ receiverGet = nullAware.expression;
argument = node.receiver;
+ argumentGet = node;
}
}
} else if (node.parent is ir.StringConcatenation) {
@@ -293,6 +385,7 @@
// ^
kind = RuntimeTypeUseKind.string;
receiver = node.receiver;
+ receiverGet = node;
}
if (kind == null) {
@@ -302,10 +395,20 @@
// ^
kind = RuntimeTypeUseKind.unknown;
receiver = node.receiver;
+ receiverGet = node;
}
- DartType receiverType = elementMap.getStaticType(receiver);
- DartType argumentType =
- argument == null ? null : elementMap.getStaticType(argument);
- return new RuntimeTypeUse(kind, receiverType, argumentType);
+ RuntimeTypeUseData data = new RuntimeTypeUseData(
+ kind, receiverGet, receiver, argumentGet, argument);
+ cache[receiverGet] = data;
+ if (argumentGet != null) {
+ cache[argumentGet] = data;
+ }
+
+ assert(receiverGet != null, "Missing receiverGet in $data for $node.");
+ assert(!(argument != null && argumentGet == null),
+ "Missing argumentGet in $data for $node.");
+ assert(
+ receiverGet != argumentGet, "Duplicate property get in $data for $node.");
+ return data;
}
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 47129b6..9ddc390 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -7,9 +7,11 @@
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/type_algebra.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
+import '../common/names.dart';
+import '../util/util.dart';
+import 'runtime_type_analysis.dart';
import 'scope.dart';
import 'static_type_base.dart';
-import '../util/util.dart';
/// Enum values for how the target of a static type should be interpreted.
enum ClassRelation {
@@ -35,8 +37,13 @@
abstract class StaticTypeVisitor extends StaticTypeBase {
Map<ir.Expression, ir.DartType> _cache = {};
Map<ir.Expression, TypeMap> typeMapsForTesting;
+ Map<ir.PropertyGet, RuntimeTypeUseData> _pendingRuntimeTypeUseData = {};
- StaticTypeVisitor(ir.TypeEnvironment typeEnvironment)
+ final ir.ClassHierarchy hierarchy;
+
+ ThisInterfaceType _thisType;
+
+ StaticTypeVisitor(ir.TypeEnvironment typeEnvironment, this.hierarchy)
: super(typeEnvironment);
Map<ir.Expression, ir.DartType> get cachedStaticTypes => _cache;
@@ -51,7 +58,17 @@
VariableScopeModel get variableScopeModel;
- bool completes(ir.DartType type) => type != const ir.BottomType();
+ ThisInterfaceType get thisType {
+ assert(_thisType != null);
+ return _thisType;
+ }
+
+ void set thisType(ThisInterfaceType value) {
+ assert(value == null || _thisType == null);
+ _thisType = value;
+ }
+
+ bool completes(ir.DartType type) => type != const DoesNotCompleteType();
Set<ir.VariableDeclaration> _currentVariables;
Set<ir.VariableDeclaration> _invalidatedVariables =
@@ -148,7 +165,7 @@
}
if (type is ir.InterfaceType) {
ir.InterfaceType upcastType =
- typeEnvironment.hierarchy.getTypeAsInstanceOf(type, superclass);
+ typeEnvironment.getTypeAsInstanceOf(type, superclass);
if (upcastType != null) return upcastType;
} else if (type is ir.BottomType) {
return superclass.bottomType;
@@ -165,8 +182,8 @@
ir.PropertyGet node, ir.DartType receiverType) {
ir.Member interfaceTarget = node.interfaceTarget;
if (interfaceTarget == null && receiverType is ir.InterfaceType) {
- interfaceTarget = node.interfaceTarget = typeEnvironment.hierarchy
- .getInterfaceMember(receiverType.classNode, node.name);
+ interfaceTarget = node.interfaceTarget =
+ hierarchy.getInterfaceMember(receiverType.classNode, node.name);
}
if (interfaceTarget != null) {
ir.Class superclass = interfaceTarget.enclosingClass;
@@ -187,6 +204,9 @@
void handlePropertyGet(
ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {}
+ void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
+ ir.DartType receiverType, ir.DartType argumentType) {}
+
@override
ir.DartType visitPropertyGet(ir.PropertyGet node) {
ir.DartType receiverType = visitNode(node.receiver);
@@ -194,6 +214,31 @@
_cache[node] = _computePropertyGetType(node, receiverType);
receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
handlePropertyGet(node, receiverType, resultType);
+ if (node.name.name == Identifiers.runtimeType_) {
+ RuntimeTypeUseData data =
+ computeRuntimeTypeUse(_pendingRuntimeTypeUseData, node);
+ if (data.leftRuntimeTypeExpression == node) {
+ // [node] is the left (or single) occurrence of `.runtimeType` so we
+ // can set the static type of the receiver expression.
+ data.receiverType = receiverType;
+ } else {
+ // [node] is the right occurrence of `.runtimeType` so we
+ // can set the static type of the argument expression.
+ assert(data.rightRuntimeTypeExpression == node,
+ "Unexpected RuntimeTypeUseData for $node: $data");
+ data.argumentType = receiverType;
+ }
+ if (data.isComplete) {
+ /// We now have all need static types so we can remove the data from
+ /// the cache and handle the runtime type use.
+ _pendingRuntimeTypeUseData.remove(data.leftRuntimeTypeExpression);
+ if (data.rightRuntimeTypeExpression != null) {
+ _pendingRuntimeTypeUseData.remove(data.rightRuntimeTypeExpression);
+ }
+ handleRuntimeTypeUse(
+ node, data.kind, data.receiverType, data.argumentType);
+ }
+ }
return resultType;
}
@@ -205,7 +250,7 @@
ir.DartType receiverType = visitNode(node.receiver);
ir.DartType valueType = super.visitPropertySet(node);
if (node.interfaceTarget == null && receiverType is ir.InterfaceType) {
- node.interfaceTarget = typeEnvironment.hierarchy
+ node.interfaceTarget = hierarchy
.getInterfaceMember(receiverType.classNode, node.name, setter: true);
}
receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
@@ -388,8 +433,8 @@
interfaceTarget = node.interfaceTarget = objectEquals;
}
if (interfaceTarget == null && receiverType is ir.InterfaceType) {
- ir.Member member = typeEnvironment.hierarchy
- .getInterfaceMember(receiverType.classNode, node.name);
+ ir.Member member =
+ hierarchy.getInterfaceMember(receiverType.classNode, node.name);
if (_isApplicable(node.arguments, member)) {
interfaceTarget = node.interfaceTarget = member;
}
@@ -428,7 +473,7 @@
if (node.name.name == 'call') {
if (receiverType is ir.FunctionType) {
if (receiverType.typeParameters.length != node.arguments.types.length) {
- return const ir.BottomType();
+ return const DoesNotCompleteType();
}
return ir.Substitution.fromPairs(
receiverType.typeParameters, node.arguments.types)
@@ -582,8 +627,8 @@
ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) {
ArgumentTypes argumentTypes = _visitArguments(node.arguments);
ir.DartType resultType = node.arguments.types.isEmpty
- ? node.target.enclosingClass.rawType
- : new ir.InterfaceType(
+ ? new ExactInterfaceType.from(node.target.enclosingClass.rawType)
+ : new ExactInterfaceType(
node.target.enclosingClass, node.arguments.types);
_cache[node] = resultType;
handleConstructorInvocation(node, argumentTypes, resultType);
@@ -604,8 +649,8 @@
if (declaringClass.typeParameters.isEmpty) {
resultType = node.interfaceTarget.getterType;
} else {
- ir.DartType receiver = typeEnvironment.hierarchy
- .getTypeAsInstanceOf(typeEnvironment.thisType, declaringClass);
+ ir.DartType receiver =
+ typeEnvironment.getTypeAsInstanceOf(thisType, declaringClass);
resultType = ir.Substitution.fromInterfaceType(receiver)
.substituteType(node.interfaceTarget.getterType);
}
@@ -637,8 +682,8 @@
returnType = const ir.DynamicType();
} else {
ir.Class superclass = node.interfaceTarget.enclosingClass;
- ir.InterfaceType receiverType = typeEnvironment.hierarchy
- .getTypeAsInstanceOf(typeEnvironment.thisType, superclass);
+ ir.InterfaceType receiverType =
+ typeEnvironment.getTypeAsInstanceOf(thisType, superclass);
returnType = ir.Substitution.fromInterfaceType(receiverType)
.substituteType(node.interfaceTarget.function.returnType);
returnType = ir.Substitution.fromPairs(
@@ -709,14 +754,14 @@
return null;
} else {
typeMap = afterThen.join(afterOtherwise);
- return const ir.BottomType();
+ return const DoesNotCompleteType();
}
}
@override
ir.DartType visitConditionalExpression(ir.ConditionalExpression node) {
- // TODO(johnniwinther): Should we return `const ir.BottomType()` if both
- // branches are failing?
+ // TODO(johnniwinther): Should we return `const DoesNotCompleteType()` if
+ // both branches are failing?
_handleConditional(node.condition, node.then, node.otherwise);
return super.visitConditionalExpression(node);
}
@@ -766,12 +811,15 @@
@override
ir.DartType visitBlock(ir.Block node) {
+ assert(_pendingRuntimeTypeUseData.isEmpty);
ir.DartType type;
for (ir.Statement statement in node.statements) {
if (!completes(visitNode(statement))) {
- type = const ir.BottomType();
+ type = const DoesNotCompleteType();
}
}
+ assert(_pendingRuntimeTypeUseData.isEmpty,
+ "Incomplete RuntimeTypeUseData: $_pendingRuntimeTypeUseData");
return type;
}
@@ -902,7 +950,7 @@
@override
ir.DartType visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
- return const ir.BottomType();
+ return const DoesNotCompleteType();
}
@override
@@ -912,7 +960,7 @@
@override
ir.DartType visitBreakStatement(ir.BreakStatement node) {
- return const ir.BottomType();
+ return const DoesNotCompleteType();
}
@override
@@ -1028,7 +1076,7 @@
@override
ir.DartType visitReturnStatement(ir.ReturnStatement node) {
visitNode(node.expression);
- return const ir.BottomType();
+ return const DoesNotCompleteType();
}
@override
@@ -1122,22 +1170,21 @@
@override
Null visitProcedure(ir.Procedure node) {
- typeEnvironment.thisType =
- node.enclosingClass != null ? node.enclosingClass.thisType : null;
+ thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
_currentVariables = new Set<ir.VariableDeclaration>();
visitSignature(node.function);
visitNode(node.function.body);
handleProcedure(node);
_invalidatedVariables.removeAll(_currentVariables);
_currentVariables = null;
- typeEnvironment.thisType = null;
+ thisType = null;
}
void handleConstructor(ir.Constructor node) {}
@override
Null visitConstructor(ir.Constructor node) {
- typeEnvironment.thisType = node.enclosingClass.thisType;
+ thisType = new ThisInterfaceType.from(node.enclosingClass.thisType);
_currentVariables = new Set<ir.VariableDeclaration>();
visitSignature(node.function);
visitNodes(node.initializers);
@@ -1145,18 +1192,17 @@
handleConstructor(node);
_invalidatedVariables.removeAll(_currentVariables);
_currentVariables = null;
- typeEnvironment.thisType = null;
+ thisType = null;
}
void handleField(ir.Field node) {}
@override
Null visitField(ir.Field node) {
- typeEnvironment.thisType =
- node.enclosingClass != null ? node.enclosingClass.thisType : null;
+ thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
visitNode(node.initializer);
handleField(node);
- typeEnvironment.thisType = null;
+ thisType = null;
}
void handleVariableDeclaration(ir.VariableDeclaration node) {}
@@ -1227,7 +1273,8 @@
// We cannot promote. No single type is most specific.
// TODO(johnniwinther): Compute implied types? For instance when the
// declared type is `Iterable<String>` and tested type is
- // `List<dynamic>` we could promote to the implied type `List<String>`.
+ // `List<dynamic>` we could promote to the implied type
+ // `List<String>`.
return null;
}
}
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 508c4d0..20cf00c 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -8,6 +8,41 @@
import 'package:kernel/type_algebra.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
+/// Special bottom type used to signal that an expression or statement does
+/// not complete normally. This is the case for instance of throw expressions
+/// and return statements.
+class DoesNotCompleteType extends ir.BottomType {
+ const DoesNotCompleteType();
+
+ String toString() => 'DoesNotCompleteType()';
+}
+
+/// Special interface type used to signal that the static type of an expression
+/// has precision of a this-expression.
+class ThisInterfaceType extends ir.InterfaceType {
+ ThisInterfaceType(ir.Class classNode, [List<ir.DartType> typeArguments])
+ : super(classNode, typeArguments);
+
+ factory ThisInterfaceType.from(ir.InterfaceType type) => type != null
+ ? new ThisInterfaceType(type.classNode, type.typeArguments)
+ : null;
+
+ String toString() => 'this:${super.toString()}';
+}
+
+/// Special interface type used to signal that the static type of an expression
+/// is exact, i.e. the runtime type is not a subtype or subclass of the type.
+class ExactInterfaceType extends ir.InterfaceType {
+ ExactInterfaceType(ir.Class classNode, [List<ir.DartType> typeArguments])
+ : super(classNode, typeArguments);
+
+ factory ExactInterfaceType.from(ir.InterfaceType type) => type != null
+ ? new ExactInterfaceType(type.classNode, type.typeArguments)
+ : null;
+
+ String toString() => 'exact:${super.toString()}';
+}
+
/// Base class for computing static types.
///
/// This class uses the visitor pattern to compute the static type that are
@@ -18,7 +53,7 @@
/// expression kind. For instance method invocations whose static type depend
/// on the static types of the receiver and type arguments and the signature
/// of the targeted procedure.
-class StaticTypeBase extends ir.Visitor<ir.DartType> {
+abstract class StaticTypeBase extends ir.Visitor<ir.DartType> {
final ir.TypeEnvironment _typeEnvironment;
StaticTypeBase(this._typeEnvironment);
@@ -27,6 +62,8 @@
ir.TypeEnvironment get typeEnvironment => _typeEnvironment;
+ ThisInterfaceType get thisType;
+
@override
ir.DartType defaultNode(ir.Node node) {
return null;
@@ -73,7 +110,7 @@
}
@override
- ir.DartType visitNullLiteral(ir.NullLiteral node) => const ir.BottomType();
+ ir.DartType visitNullLiteral(ir.NullLiteral node) => typeEnvironment.nullType;
@override
ir.DartType visitIntLiteral(ir.IntLiteral node) => typeEnvironment.intType;
@@ -112,8 +149,7 @@
}
@override
- ir.DartType visitThisExpression(ir.ThisExpression node) =>
- typeEnvironment.thisType;
+ ThisInterfaceType visitThisExpression(ir.ThisExpression node) => thisType;
@override
ir.DartType visitStaticGet(ir.StaticGet node) => node.target.getterType;
@@ -129,10 +165,10 @@
}
@override
- ir.DartType visitThrow(ir.Throw node) => const ir.BottomType();
+ ir.DartType visitThrow(ir.Throw node) => const DoesNotCompleteType();
@override
- ir.DartType visitRethrow(ir.Rethrow node) => const ir.BottomType();
+ ir.DartType visitRethrow(ir.Rethrow node) => const DoesNotCompleteType();
@override
ir.DartType visitLogicalExpression(ir.LogicalExpression node) =>
@@ -168,7 +204,7 @@
@override
ir.DartType visitInvalidExpression(ir.InvalidExpression node) =>
- const ir.BottomType();
+ const DoesNotCompleteType();
@override
ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index 9893f5b..523cd66 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -69,20 +69,20 @@
@override
void emit(String string) {
+ monitor?.emit(string);
outBuffer.add(string);
}
@override
void enterNode(Node node, int startPosition) {
+ monitor?.enterNode(node, startPosition);
codePositionListener.onStartPosition(node, startPosition);
}
@override
void exitNode(
Node node, int startPosition, int endPosition, int closingPosition) {
- if (monitor != null) {
- monitor.recordAstSize(node, endPosition - startPosition);
- }
+ monitor?.exitNode(node, startPosition, endPosition, closingPosition);
codePositionListener.onPositions(
node, startPosition, endPosition, closingPosition);
}
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index f58853e..d191491 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -52,9 +52,7 @@
openAndCloseNode(node, '${node.runtimeType}', {'value': node.value});
}
- /**
- * Pretty-prints given node tree into string.
- */
+ /// Pretty-prints given node tree into string.
static String prettyPrint(Node node) {
var p = new DebugPrinter();
node.accept(p);
diff --git a/pkg/compiler/lib/src/js_backend/allocator_analysis.dart b/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
index 9312d15..787e64c 100644
--- a/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
@@ -31,12 +31,11 @@
// this.x = this.z = null;
//
class KAllocatorAnalysis implements AllocatorAnalysis {
- final CompilerOptions _options;
final KernelToElementMap _elementMap;
final Map<KField, ConstantValue> _fixedInitializers = {};
- KAllocatorAnalysis(this._options, KernelFrontEndStrategy kernelStrategy)
+ KAllocatorAnalysis(KernelFrontEndStrategy kernelStrategy)
: _elementMap = kernelStrategy.elementMap;
// Register class during resolution. Use simple syntactic analysis to find
@@ -53,19 +52,13 @@
if (initializer == null || initializer is ir.NullLiteral) {
inits[field] = const NullConstantValue();
} else if (initializer is ir.IntLiteral) {
- if (_options.useStartupEmitter) {
- BigInt intValue = BigInt.from(initializer.value).toUnsigned(64);
- inits[field] = IntConstantValue(intValue);
- }
+ BigInt intValue = BigInt.from(initializer.value).toUnsigned(64);
+ inits[field] = IntConstantValue(intValue);
} else if (initializer is ir.BoolLiteral) {
- if (_options.useStartupEmitter) {
- inits[field] = BoolConstantValue(initializer.value);
- }
+ inits[field] = BoolConstantValue(initializer.value);
} else if (initializer is ir.StringLiteral) {
- if (_options.useStartupEmitter) {
- if (initializer.value.length <= 20) {
- inits[field] = StringConstantValue(initializer.value);
- }
+ if (initializer.value.length <= 20) {
+ inits[field] = StringConstantValue(initializer.value);
}
}
}
@@ -92,16 +85,15 @@
static const String tag = 'allocator-analysis';
// --csp and --fast-startup have different constraints to the generated code.
- final CompilerOptions _options;
final Map<JField, ConstantValue> _fixedInitializers = {};
- JAllocatorAnalysis._(this._options);
+ JAllocatorAnalysis._();
/// Deserializes a [JAllocatorAnalysis] object from [source].
factory JAllocatorAnalysis.readFromDataSource(
DataSource source, CompilerOptions options) {
source.begin(tag);
- JAllocatorAnalysis analysis = new JAllocatorAnalysis._(options);
+ JAllocatorAnalysis analysis = new JAllocatorAnalysis._();
int fieldCount = source.readInt();
for (int i = 0; i < fieldCount; i++) {
JField field = source.readMember();
@@ -125,7 +117,7 @@
static JAllocatorAnalysis from(KAllocatorAnalysis kAnalysis,
JsToFrontendMap map, CompilerOptions options) {
- var result = new JAllocatorAnalysis._(options);
+ var result = JAllocatorAnalysis._();
kAnalysis._fixedInitializers.forEach((KField kField, ConstantValue value) {
// TODO(sra): Translate constant, but Null and these primitives do not
@@ -142,11 +134,6 @@
}
bool get _isEnabled {
- if (_options.useContentSecurityPolicy && !_options.useStartupEmitter) {
- // TODO(sra): Refactor csp 'precompiled' constructor generation to allow
- // in-allocator initialization.
- return false;
- }
return true;
}
// TODO(sra): Add way to let injected fields be initialized to a constant in
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 81ea82f..be118eb 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -9,7 +9,8 @@
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/names.dart' show Uris;
import '../common/tasks.dart' show CompilerTask;
-import '../common_elements.dart' show CommonElements, ElementEnvironment;
+import '../common_elements.dart'
+ show CommonElements, ElementEnvironment, JElementEnvironment;
import '../compiler.dart' show Compiler;
import '../constants/constant_system.dart';
import '../deferred_load.dart' show DeferredLoadTask;
@@ -312,9 +313,7 @@
CodeEmitterTask emitter;
- /**
- * The generated code as a js AST for compiled methods.
- */
+ /// The generated code as a js AST for compiled methods.
final Map<MemberEntity, jsAst.Expression> generatedCode =
<MemberEntity, jsAst.Expression>{};
@@ -326,9 +325,7 @@
return _namer;
}
- /**
- * Set of classes whose `operator ==` methods handle `null` themselves.
- */
+ /// Set of classes whose `operator ==` methods handle `null` themselves.
final Set<ClassEntity> specialOperatorEqClasses = new Set<ClassEntity>();
List<CompilerTask> get tasks {
@@ -387,7 +384,6 @@
JavaScriptBackend(this.compiler,
{bool generateSourceMap: true,
- bool useStartupEmitter: false,
bool useMultiSourceInfo: false,
bool useNewSourceInfo: false})
: this.sourceInformationStrategy =
@@ -397,9 +393,7 @@
_backendUsageBuilder =
new BackendUsageBuilderImpl(compiler.frontendStrategy);
_checkedModeHelpers = new CheckedModeHelpers();
- emitter =
- new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
-
+ emitter = new CodeEmitterTask(compiler, generateSourceMap);
noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
commonElements, compiler.frontendStrategy.createNoSuchMethodResolver());
functionCompiler = new SsaFunctionCompiler(
@@ -555,7 +549,7 @@
nativeBasicData,
_backendUsageBuilder);
_allocatorResolutionAnalysis =
- new KAllocatorAnalysis(compiler.options, compiler.frontendStrategy);
+ new KAllocatorAnalysis(compiler.frontendStrategy);
ClassQueries classQueries = compiler.frontendStrategy.createClassQueries();
ClassHierarchyBuilder classHierarchyBuilder =
new ClassHierarchyBuilder(commonElements, classQueries);
@@ -702,11 +696,9 @@
NativeEnqueuer get nativeCodegenEnqueuer => _nativeCodegenEnqueuer;
- /**
- * Unit test hook that returns code of an element as a String.
- *
- * Invariant: [element] must be a declaration element.
- */
+ /// Unit test hook that returns code of an element as a String.
+ ///
+ /// Invariant: [element] must be a declaration element.
String getGeneratedCode(MemberEntity element) {
return jsAst.prettyPrint(generatedCode[element],
enableMinification: compiler.options.enableMinification);
@@ -719,10 +711,8 @@
return programSize;
}
- /**
- * Returns [:true:] if the checking of [type] is performed directly on the
- * object and not on an interceptor.
- */
+ /// Returns [:true:] if the checking of [type] is performed directly on the
+ /// object and not on an interceptor.
bool hasDirectCheckFor(CommonElements commonElements, DartType type) {
if (!type.isInterfaceType) return false;
InterfaceType interfaceType = type;
@@ -810,7 +800,7 @@
jsAst.Expression rewriteAsync(
CommonElements commonElements,
- ElementEnvironment elementEnvironment,
+ JElementEnvironment elementEnvironment,
CodegenRegistry registry,
FunctionEntity element,
jsAst.Expression code,
@@ -886,7 +876,7 @@
AsyncRewriter _makeAsyncRewriter(
CommonElements commonElements,
- ElementEnvironment elementEnvironment,
+ JElementEnvironment elementEnvironment,
CodegenRegistry registry,
FunctionEntity element,
jsAst.Expression code,
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index efe00d9..39612fd 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -7,6 +7,7 @@
import '../elements/entities.dart';
import '../elements/types.dart';
import '../frontend_strategy.dart';
+import '../ir/runtime_type_analysis.dart';
import '../serialization/serialization.dart';
import '../universe/feature.dart';
import '../util/util.dart' show Setlet;
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index ed231cc..71bb262 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -154,12 +154,10 @@
new Map<String, CheckedModeHelper>.fromIterable(helpers,
key: (helper) => helper.name);
- /**
- * Returns the checked mode helper that will be needed to do a type check/type
- * cast on [type] at runtime. Note that this method is being called both by
- * the resolver with interface types (int, String, ...), and by the SSA
- * backend with implementation types (JSInt, JSString, ...).
- */
+ /// Returns the checked mode helper that will be needed to do a type
+ /// check/type cast on [type] at runtime. Note that this method is being
+ /// called both by the resolver with interface types (int, String, ...), and
+ /// by the SSA backend with implementation types (JSInt, JSString, ...).
CheckedModeHelper getCheckedModeHelper(
DartType type, CommonElements commonElements,
{bool typeCast}) {
@@ -167,11 +165,9 @@
typeCast: typeCast, nativeCheckOnly: false);
}
- /**
- * Returns the native checked mode helper that will be needed to do a type
- * check/type cast on [type] at runtime. If no native helper exists for
- * [type], [:null:] is returned.
- */
+ /// Returns the native checked mode helper that will be needed to do a type
+ /// check/type cast on [type] at runtime. If no native helper exists for
+ /// [type], [:null:] is returned.
CheckedModeHelper getNativeCheckedModeHelper(
DartType type, CommonElements commonElements,
{bool typeCast}) {
@@ -179,10 +175,9 @@
typeCast: typeCast, nativeCheckOnly: true);
}
- /**
- * Returns the checked mode helper for the type check/type cast for [type]. If
- * [nativeCheckOnly] is [:true:], only names for native helpers are returned.
- */
+ /// Returns the checked mode helper for the type check/type cast for
+ /// [type]. If [nativeCheckOnly] is [:true:], only names for native helpers
+ /// are returned.
CheckedModeHelper getCheckedModeHelperInternal(
DartType type, CommonElements commonElements,
{bool typeCast, bool nativeCheckOnly}) {
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 7afba73..3fb4475 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -22,13 +22,11 @@
typedef jsAst.Expression _ConstantListGenerator(jsAst.Expression array);
-/**
- * Generates the JavaScript expressions for constants.
- *
- * It uses a given [constantReferenceGenerator] to reference nested constants
- * (if there are some). It is hence up to that function to decide which
- * constants should be inlined or not.
- */
+/// Generates the JavaScript expressions for constants.
+///
+/// It uses a given [constantReferenceGenerator] to reference nested constants
+/// (if there are some). It is hence up to that function to decide which
+/// constants should be inlined or not.
class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
// Matches blank lines, comment lines and trailing comments that can't be part
// of a string.
@@ -45,11 +43,9 @@
final _ConstantReferenceGenerator constantReferenceGenerator;
final _ConstantListGenerator makeConstantList;
- /**
- * The given [constantReferenceGenerator] function must, when invoked with a
- * constant, either return a reference or return its literal expression if it
- * can be inlined.
- */
+ /// The given [constantReferenceGenerator] function must, when invoked with a
+ /// constant, either return a reference or return its literal expression if it
+ /// can be inlined.
ConstantEmitter(
this._options,
this._commonElements,
@@ -63,11 +59,9 @@
Emitter get _emitter => _task.emitter;
- /**
- * Constructs a literal expression that evaluates to the constant. Uses a
- * canonical name unless the constant can be emitted multiple times (as for
- * numbers and strings).
- */
+ /// Constructs a literal expression that evaluates to the constant. Uses a
+ /// canonical name unless the constant can be emitted multiple times (as for
+ /// numbers and strings).
jsAst.Expression generate(ConstantValue constant) {
return _visit(constant);
}
@@ -171,11 +165,9 @@
}
}
- /**
- * Write the contents of the quoted string to a [CodeBuffer] in
- * a form that is valid as JavaScript string literal content.
- * The string is assumed quoted by double quote characters.
- */
+ /// Write the contents of the quoted string to a [CodeBuffer] in
+ /// a form that is valid as JavaScript string literal content.
+ /// The string is assumed quoted by double quote characters.
@override
jsAst.Expression visitString(StringConstantValue constant, [_]) {
return js.escapedString(constant.stringValue, ascii: true);
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index d454cf3..6b9de6a 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -31,14 +31,12 @@
ConstantSystem get constantSystem => dartConstantSystem;
}
-/**
- * The [JavaScriptConstantCompiler] is used to keep track of compile-time
- * constants, initializations of global and static fields, and default values of
- * optional parameters for the JavaScript interpretation of constants.
- */
+/// The [JavaScriptConstantCompiler] is used to keep track of compile-time
+/// constants, initializations of global and static fields, and default values
+/// of optional parameters for the JavaScript interpretation of constants.
class JavaScriptConstantCompiler implements BackendConstantEnvironment {
// TODO(johnniwinther): Move this to the backend constant handler.
- /** Caches the statics where the initial value cannot be eagerly compiled. */
+ /// Caches the statics where the initial value cannot be eagerly compiled.
final Set<FieldEntity> lazyStatics = new Set<FieldEntity>();
JavaScriptConstantCompiler();
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 8b0d237..21eabbf 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -28,10 +28,8 @@
}
}
-/**
- * In JavaScript we truncate the result to an unsigned 32 bit integer. Also, -0
- * is treated as if it was the integer 0.
- */
+/// In JavaScript we truncate the result to an unsigned 32 bit integer. Also, -0
+/// is treated as if it was the integer 0.
class JavaScriptBinaryBitOperation implements BinaryOperation {
final BinaryBitOperation dartBitOperation;
@@ -223,10 +221,8 @@
}
}
-/**
- * Constant system following the semantics for Dart code that has been
- * compiled to JavaScript.
- */
+/// Constant system following the semantics for Dart code that has been
+/// compiled to JavaScript.
class JavaScriptConstantSystem extends ConstantSystem {
final BITS32 = new BigInt.from(0xFFFFFFFF);
@@ -269,10 +265,8 @@
JavaScriptConstantSystem._internal();
- /**
- * Returns true if [value] will turn into NaN or infinity
- * at runtime.
- */
+ /// Returns true if [value] will turn into NaN or infinity
+ /// at runtime.
bool integerBecomesNanOrInfinity(BigInt value) {
double doubleValue = value.toDouble();
return doubleValue.isNaN || doubleValue.isInfinite;
@@ -411,13 +405,11 @@
}
class JavaScriptMapConstant extends MapConstantValue {
- /**
- * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript
- * object. It would change the prototype chain.
- */
+ /// The [PROTO_PROPERTY] must not be used as normal property in any JavaScript
+ /// object. It would change the prototype chain.
static const String PROTO_PROPERTY = "__proto__";
- /** The dart class implementing constant map literals. */
+ /// The dart class implementing constant map literals.
static const String DART_CLASS = "ConstantMap";
static const String DART_STRING_CLASS = "ConstantStringMap";
static const String DART_PROTO_CLASS = "ConstantProtoMap";
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index 4b27e24..79a4453 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -14,43 +14,41 @@
import 'backend_usage.dart' show BackendUsageBuilder;
import 'native_data.dart';
-/**
- * Support for Custom Elements.
- *
- * The support for custom elements the compiler builds a table that maps the
- * custom element class's [Type] to the interceptor for the class and the
- * constructor(s) for the class.
- *
- * We want the table to contain only the custom element classes used, and we
- * want to avoid resolving and compiling constructors that are not used since
- * that may bring in unused code. This class controls the resolution and code
- * generation to restrict the impact.
- *
- * The following line of code requires the generation of the generative
- * constructor factory function(s) for FancyButton, and their insertion into the
- * table:
- *
- * document.register(FancyButton, 'x-fancy-button');
- *
- * We detect this by 'joining' the classes that are referenced as type literals
- * with the classes that are custom elements, enabled by detecting the presence
- * of the table access code used by document.register.
- *
- * We have to be more conservative when the type is unknown, e.g.
- *
- * document.register(classMirror.reflectedType, tagFromMetadata);
- *
- * and
- *
- * class Component<T> {
- * final tag;
- * Component(this.tag);
- * void register() => document.register(T, tag);
- * }
- * const Component<FancyButton>('x-fancy-button').register();
- *
- * In these cases we conservatively generate all viable entries in the table.
- */
+/// Support for Custom Elements.
+///
+/// The support for custom elements the compiler builds a table that maps the
+/// custom element class's [Type] to the interceptor for the class and the
+/// constructor(s) for the class.
+///
+/// We want the table to contain only the custom element classes used, and we
+/// want to avoid resolving and compiling constructors that are not used since
+/// that may bring in unused code. This class controls the resolution and code
+/// generation to restrict the impact.
+///
+/// The following line of code requires the generation of the generative
+/// constructor factory function(s) for FancyButton, and their insertion into
+/// the table:
+///
+/// document.register(FancyButton, 'x-fancy-button');
+///
+/// We detect this by 'joining' the classes that are referenced as type literals
+/// with the classes that are custom elements, enabled by detecting the presence
+/// of the table access code used by document.register.
+///
+/// We have to be more conservative when the type is unknown, e.g.
+///
+/// document.register(classMirror.reflectedType, tagFromMetadata);
+///
+/// and
+///
+/// class Component<T> {
+/// final tag;
+/// Component(this.tag);
+/// void register() => document.register(T, tag);
+/// }
+/// const Component<FancyButton>('x-fancy-button').register();
+///
+/// In these cases we conservatively generate all viable entries in the table.
abstract class CustomElementsAnalysisBase {
final NativeBasicData _nativeData;
final ElementEnvironment _elementEnvironment;
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index f7e8984..828dd25 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -33,13 +33,11 @@
}
}
-/**
- * Encapsulates the global state of field naming.
- *
- * The field naming registry allocates names to be used along a path in the
- * inheritance hierarchy of fields, starting with the object class. The actual
- * hierarchy is encoded using instances of [_FieldNamingScope].
- */
+/// Encapsulates the global state of field naming.
+///
+/// The field naming registry allocates names to be used along a path in the
+/// inheritance hierarchy of fields, starting with the object class. The actual
+/// hierarchy is encoded using instances of [_FieldNamingScope].
class _FieldNamingRegistry {
final Namer namer;
@@ -82,18 +80,16 @@
}
}
-/**
- * A [_FieldNamingScope] encodes a node in the inheritance tree of the current
- * class hierarchy. The root node typically is the node corresponding to the
- * `Object` class. It is used to assign a unique name to each field of a class.
- * Unique here means unique wrt. all fields along the path back to the root.
- * This is achieved at construction time via the [_fieldNameCounter] field that
- * counts the number of fields on the path to the root node that have been
- * encountered so far.
- *
- * Obviously, this only works if no fields are added to a parent node after its
- * children have added their first field.
- */
+/// A [_FieldNamingScope] encodes a node in the inheritance tree of the current
+/// class hierarchy. The root node typically is the node corresponding to the
+/// `Object` class. It is used to assign a unique name to each field of a class.
+/// Unique here means unique wrt. all fields along the path back to the root.
+/// This is achieved at construction time via the [_fieldNameCounter] field that
+/// counts the number of fields on the path to the root node that have been
+/// encountered so far.
+///
+/// Obviously, this only works if no fields are added to a parent node after its
+/// children have added their first field.
class _FieldNamingScope {
final _FieldNamingScope superScope;
final Entity container;
@@ -160,9 +156,7 @@
_fieldNameCounter = superScope.inheritanceBasedFieldNameCounter;
}
- /**
- * Checks whether [name] is already used in the current scope chain.
- */
+ /// Checks whether [name] is already used in the current scope chain.
_isNameUnused(jsAst.Name name) {
return !names.values.contains(name) &&
((superScope == null) || superScope._isNameUnused(name));
@@ -187,15 +181,13 @@
bool containsField(Entity field) => names.containsKey(field);
}
-/**
- * Field names for mixins have two constraints: They need to be unique in the
- * hierarchy of each application of a mixin and they need to be the same for
- * all applications of a mixin. To achieve this, we use global naming for
- * mixins from the same name pool as fields and add a `$` at the end to ensure
- * they do not collide with normal field names. The `$` sign is typically used
- * as a separator between method names and argument counts and does not appear
- * in generated names themselves.
- */
+/// Field names for mixins have two constraints: They need to be unique in the
+/// hierarchy of each application of a mixin and they need to be the same for
+/// all applications of a mixin. To achieve this, we use global naming for
+/// mixins from the same name pool as fields and add a `$` at the end to ensure
+/// they do not collide with normal field names. The `$` sign is typically used
+/// as a separator between method names and argument counts and does not appear
+/// in generated names themselves.
class _MixinFieldNamingScope extends _FieldNamingScope {
int get _localFieldNameCounter => registry.globalCount;
void set _localFieldNameCounter(int val) {
@@ -218,12 +210,10 @@
}
}
-/**
- * [BoxFieldElement] fields work differently in that they do not belong to an
- * actual class but an anonymous box associated to a [Local]. As there is no
- * inheritance chain, we do not need to compute fields a priori but can assign
- * names on the fly.
- */
+/// [BoxFieldElement] fields work differently in that they do not belong to an
+/// actual class but an anonymous box associated to a [Local]. As there is no
+/// inheritance chain, we do not need to compute fields a priori but can assign
+/// names on the fly.
class _BoxFieldNamingScope extends _FieldNamingScope {
_BoxFieldNamingScope(Local box, _FieldNamingRegistry registry)
: super.rootScope(box, registry);
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 3739932..2d772ff 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -4,9 +4,7 @@
part of js_backend.namer;
-/**
- * Assigns JavaScript identifiers to Dart variables, class-names and members.
- */
+/// Assigns JavaScript identifiers to Dart variables, class-names and members.
class MinifyNamer extends Namer
with
_MinifiedFieldNamer,
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 0fe5bd1..9e7a95b 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -40,103 +40,101 @@
part 'minify_namer.dart';
part 'namer_names.dart';
-/**
- * Assigns JavaScript identifiers to Dart variables, class-names and members.
- *
- * Names are generated through three stages:
- *
- * 1. Original names and proposed names
- * 2. Disambiguated names (also known as "mangled names")
- * 3. Annotated names
- *
- * Original names are names taken directly from the input.
- *
- * Proposed names are either original names or synthesized names for input
- * elements that do not have original names.
- *
- * Disambiguated names are derived from the above, but are mangled to ensure
- * uniqueness within some namespace (e.g. as fields on the same JS object).
- * In [MinifyNamer], disambiguated names are also minified.
- *
- * Annotated names are names generated from a disambiguated name. Annotated
- * names must be computable at runtime by prefixing/suffixing constant strings
- * onto the disambiguated name.
- *
- * For example, some entity called `x` might be associated with these names:
- *
- * Original name: `x`
- *
- * Disambiguated name: `x1` (if something else was called `x`)
- *
- * Annotated names: `x1` (field name)
- * `get$x1` (getter name)
- * `set$x1` (setter name)
- *
- * The [Namer] can choose the disambiguated names, and to some degree the
- * prefix/suffix constants used to construct annotated names. It cannot choose
- * annotated names with total freedom, for example, it cannot choose that the
- * getter for `x1` should be called `getX` -- the annotated names are always
- * built by concatenation.
- *
- * Disambiguated names must be chosen such that none of the annotated names can
- * clash with each other. This may happen even if the disambiguated names are
- * distinct, for example, suppose a field `x` and `get$x` exists in the input:
- *
- * Original names: `x` and `get$x`
- *
- * Disambiguated names: `x` and `get$x` (the two names a different)
- *
- * Annotated names: `x` (field for `x`)
- * `get$x` (getter for `x`)
- * `get$x` (field for `get$x`)
- * `get$get$x` (getter for `get$x`)
- *
- * The getter for `x` clashes with the field name for `get$x`, so the
- * disambiguated names are invalid.
- *
- * Additionally, disambiguated names must be chosen such that all annotated
- * names are valid JavaScript identifiers and do not coincide with a native
- * JavaScript property such as `__proto__`.
- *
- * The following annotated names are generated for instance members, where
- * <NAME> denotes the disambiguated name.
- *
- * 0. The disambiguated name can itself be seen as an annotated name.
- *
- * 1. Multiple annotated names exist for the `call` method, encoding arity and
- * named parameters with the pattern:
- *
- * call$<N>$namedParam1...$namedParam<M>
- *
- * where <N> is the number of parameters (required and optional) and <M> is
- * the number of named parameters, and namedParam<n> are the names of the
- * named parameters in alphabetical order.
- *
- * Note that the same convention is used for the *proposed name* of other
- * methods. Thus, for ordinary methods, the suffix becomes embedded in the
- * disambiguated name (and can be minified), whereas for the 'call' method,
- * the suffix is an annotation that must be computable at runtime
- * (and thus cannot be minified).
- *
- * Note that the ordering of named parameters is not encapsulated in the
- * [Namer], and is hardcoded into other components, such as [Element] and
- * [Selector].
- *
- * 2. The getter/setter for a field:
- *
- * get$<NAME>
- * set$<NAME>
- *
- * (The [getterPrefix] and [setterPrefix] are different in [MinifyNamer]).
- *
- * 3. The `is` and operator uses the following names:
- *
- * $is<NAME>
- * $as<NAME>
- *
- * For local variables, the [Namer] only provides *proposed names*. These names
- * must be disambiguated elsewhere.
- */
+/// Assigns JavaScript identifiers to Dart variables, class-names and members.
+///
+/// Names are generated through three stages:
+///
+/// 1. Original names and proposed names
+/// 2. Disambiguated names (also known as "mangled names")
+/// 3. Annotated names
+///
+/// Original names are names taken directly from the input.
+///
+/// Proposed names are either original names or synthesized names for input
+/// elements that do not have original names.
+///
+/// Disambiguated names are derived from the above, but are mangled to ensure
+/// uniqueness within some namespace (e.g. as fields on the same JS object).
+/// In [MinifyNamer], disambiguated names are also minified.
+///
+/// Annotated names are names generated from a disambiguated name. Annotated
+/// names must be computable at runtime by prefixing/suffixing constant strings
+/// onto the disambiguated name.
+///
+/// For example, some entity called `x` might be associated with these names:
+///
+/// Original name: `x`
+///
+/// Disambiguated name: `x1` (if something else was called `x`)
+///
+/// Annotated names: `x1` (field name)
+/// `get$x1` (getter name)
+/// `set$x1` (setter name)
+///
+/// The [Namer] can choose the disambiguated names, and to some degree the
+/// prefix/suffix constants used to construct annotated names. It cannot choose
+/// annotated names with total freedom, for example, it cannot choose that the
+/// getter for `x1` should be called `getX` -- the annotated names are always
+/// built by concatenation.
+///
+/// Disambiguated names must be chosen such that none of the annotated names can
+/// clash with each other. This may happen even if the disambiguated names are
+/// distinct, for example, suppose a field `x` and `get$x` exists in the input:
+///
+/// Original names: `x` and `get$x`
+///
+/// Disambiguated names: `x` and `get$x` (the two names a different)
+///
+/// Annotated names: `x` (field for `x`)
+/// `get$x` (getter for `x`)
+/// `get$x` (field for `get$x`)
+/// `get$get$x` (getter for `get$x`)
+///
+/// The getter for `x` clashes with the field name for `get$x`, so the
+/// disambiguated names are invalid.
+///
+/// Additionally, disambiguated names must be chosen such that all annotated
+/// names are valid JavaScript identifiers and do not coincide with a native
+/// JavaScript property such as `__proto__`.
+///
+/// The following annotated names are generated for instance members, where
+/// <NAME> denotes the disambiguated name.
+///
+/// 0. The disambiguated name can itself be seen as an annotated name.
+///
+/// 1. Multiple annotated names exist for the `call` method, encoding arity and
+/// named parameters with the pattern:
+///
+/// call$<N>$namedParam1...$namedParam<M>
+///
+/// where <N> is the number of parameters (required and optional) and <M> is
+/// the number of named parameters, and namedParam<n> are the names of the
+/// named parameters in alphabetical order.
+///
+/// Note that the same convention is used for the *proposed name* of other
+/// methods. Thus, for ordinary methods, the suffix becomes embedded in the
+/// disambiguated name (and can be minified), whereas for the 'call' method,
+/// the suffix is an annotation that must be computable at runtime
+/// (and thus cannot be minified).
+///
+/// Note that the ordering of named parameters is not encapsulated in the
+/// [Namer], and is hardcoded into other components, such as [Element] and
+/// [Selector].
+///
+/// 2. The getter/setter for a field:
+///
+/// get$<NAME>
+/// set$<NAME>
+///
+/// (The [getterPrefix] and [setterPrefix] are different in [MinifyNamer]).
+///
+/// 3. The `is` and operator uses the following names:
+///
+/// $is<NAME>
+/// $as<NAME>
+///
+/// For local variables, the [Namer] only provides *proposed names*. These names
+/// must be disambiguated elsewhere.
class Namer {
static const List<String> javaScriptKeywords = const <String>[
// ES5 7.6.1.1 Keywords.
@@ -616,10 +614,8 @@
String get isolatePropertiesName => r'$isolateProperties';
jsAst.Name get noSuchMethodName => invocationName(Selectors.noSuchMethod_);
- /**
- * Some closures must contain their name. The name is stored in
- * [STATIC_CLOSURE_NAME_NAME].
- */
+ /// Some closures must contain their name. The name is stored in
+ /// [STATIC_CLOSURE_NAME_NAME].
String get STATIC_CLOSURE_NAME_NAME => r'$name';
String get closureInvocationSelectorName => Identifiers.call;
bool get shouldMinify => false;
@@ -763,17 +759,15 @@
return 'c\$${target.nestingLevel}';
}
- /**
- * If the [originalName] is not private returns [originalName]. Otherwise
- * mangles the [originalName] so that each library has its own distinguished
- * version of the name.
- *
- * Although the name is not guaranteed to be unique within any namespace,
- * clashes are very unlikely in practice. Therefore, it can be used in cases
- * where uniqueness is nice but not a strict requirement.
- *
- * The resulting name is a *proposed name* and is never minified.
- */
+ /// If the [originalName] is not private returns [originalName]. Otherwise
+ /// mangles the [originalName] so that each library has its own distinguished
+ /// version of the name.
+ ///
+ /// Although the name is not guaranteed to be unique within any namespace,
+ /// clashes are very unlikely in practice. Therefore, it can be used in cases
+ /// where uniqueness is nice but not a strict requirement.
+ ///
+ /// The resulting name is a *proposed name* and is never minified.
String privateName(Name originalName) {
String text = originalName.text;
@@ -933,26 +927,20 @@
CURRENT_ELEMENT_SPANNABLE, 'Unexpected special selector: $selector');
}
- /**
- * Returns the internal name used for an invocation mirror of this selector.
- */
+ /// Returns the internal name used for an invocation mirror of this selector.
jsAst.Name invocationMirrorInternalName(Selector selector) =>
invocationName(selector);
- /**
- * Returns the disambiguated name for the given field, used for constructing
- * the getter and setter names.
- */
+ /// Returns the disambiguated name for the given field, used for constructing
+ /// the getter and setter names.
jsAst.Name fieldAccessorName(FieldEntity element) {
return element.isInstanceMember
? _disambiguateMember(element.memberName)
: _disambiguateGlobalMember(element);
}
- /**
- * Returns name of the JavaScript property used to store a static or instance
- * field.
- */
+ /// Returns name of the JavaScript property used to store a static or instance
+ /// field.
jsAst.Name fieldPropertyName(FieldEntity element) {
return element.isInstanceMember
? instanceFieldPropertyName(element)
@@ -983,9 +971,7 @@
jsAst.Name globalPropertyNameForType(Entity element) =>
_disambiguateGlobalType(element);
- /**
- * Returns the JavaScript property name used to store an instance field.
- */
+ /// Returns the JavaScript property name used to store an instance field.
jsAst.Name instanceFieldPropertyName(FieldEntity element) {
ClassEntity enclosingClass = element.enclosingClass;
@@ -1410,10 +1396,8 @@
}
}
- /**
- * Returns a proposed name for the given [LibraryElement].
- * The returned id is guaranteed to be a valid JavaScript identifier.
- */
+ /// Returns a proposed name for the given [LibraryElement].
+ /// The returned id is guaranteed to be a valid JavaScript identifier.
// TODO(sra): Pre-process libraries to assign [libraryLongNames] in a way that
// is independent of the order of calls to namer.
String _proposeNameForLibrary(LibraryEntity library) {
@@ -1837,21 +1821,19 @@
}
}
-/**
- * Generator of names for [ConstantValue] values.
- *
- * The names are stable under perturbations of the source. The name is either a
- * short sequence of words, if this can be found from the constant, or a type
- * followed by a hash tag.
- *
- * List_imX // A List, with hash tag.
- * C_Sentinel // const Sentinel(), "C_" added to avoid clash
- * // with class name.
- * JSInt_methods // an interceptor.
- * Duration_16000 // const Duration(milliseconds: 16)
- * EventKeyProvider_keyup // const EventKeyProvider('keyup')
- *
- */
+/// Generator of names for [ConstantValue] values.
+///
+/// The names are stable under perturbations of the source. The name is either
+/// a short sequence of words, if this can be found from the constant, or a type
+/// followed by a hash tag.
+///
+/// List_imX // A List, with hash tag.
+/// C_Sentinel // const Sentinel(), "C_" added to avoid clash
+/// // with class name.
+/// JSInt_methods // an interceptor.
+/// Duration_16000 // const Duration(milliseconds: 16)
+/// EventKeyProvider_keyup // const EventKeyProvider('keyup')
+///
class ConstantNamingVisitor implements ConstantValueVisitor {
static final RegExp IDENTIFIER = new RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
static const MAX_FRAGMENTS = 5;
@@ -2083,14 +2065,12 @@
}
}
-/**
- * Generates canonical hash values for [ConstantValue]s.
- *
- * Unfortunately, [Constant.hashCode] is not stable under minor perturbations,
- * so it can't be used for generating names. This hasher keeps consistency
- * between runs by basing hash values of the names of elements, rather than
- * their hashCodes.
- */
+/// Generates canonical hash values for [ConstantValue]s.
+///
+/// Unfortunately, [Constant.hashCode] is not stable under minor perturbations,
+/// so it can't be used for generating names. This hasher keeps consistency
+/// between runs by basing hash values of the names of elements, rather than
+/// their hashCodes.
class ConstantCanonicalHasher implements ConstantValueVisitor<int, Null> {
static const _MASK = 0x1fffffff;
static const _UINT32_LIMIT = 4 * 1024 * 1024 * 1024;
@@ -2260,12 +2240,10 @@
}
}
- /**
- * [_combine] and [_finish] are parts of the [Jenkins hash function][1],
- * modified by using masking to keep values in SMI range.
- *
- * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
- */
+ /// [_combine] and [_finish] are parts of the [Jenkins hash function][1],
+ /// modified by using masking to keep values in SMI range.
+ ///
+ /// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
static int _combine(int hash, int value) {
hash = _MASK & (hash + value);
hash = _MASK & (hash + (((_MASK >> 10) & hash) << 10));
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 937a205..ec375e0 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -15,6 +15,7 @@
import '../elements/entities.dart';
import '../elements/names.dart';
import '../elements/types.dart';
+import '../ir/runtime_type_analysis.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_emitter/js_emitter.dart' show Emitter;
@@ -703,15 +704,13 @@
_RuntimeTypesBase(this._types);
- /**
- * Compute type arguments of classes that use one of their type variables in
- * is-checks and add the is-checks that they imply.
- *
- * This function must be called after all is-checks have been registered.
- *
- * TODO(karlklose): move these computations into a function producing an
- * immutable datastructure.
- */
+ /// Compute type arguments of classes that use one of their type variables in
+ /// is-checks and add the is-checks that they imply.
+ ///
+ /// This function must be called after all is-checks have been registered.
+ ///
+ /// TODO(karlklose): move these computations into a function producing an
+ /// immutable datastructure.
void registerImplicitChecks(
Set<InterfaceType> instantiatedTypes,
Iterable<ClassEntity> classesUsingChecks,
@@ -2276,20 +2275,18 @@
}
}
- /**
- * Compute a JavaScript expression that describes the necessary substitution
- * for type arguments in a subtype test.
- *
- * The result can be:
- * 1) `null`, if no substituted check is necessary, because the
- * type variables are the same or there are no type variables in the class
- * that is checked for.
- * 2) A list expression describing the type arguments to be used in the
- * subtype check, if the type arguments to be used in the check do not
- * depend on the type arguments of the object.
- * 3) A function mapping the type variables of the object to be checked to
- * a list expression.
- */
+ /// Compute a JavaScript expression that describes the necessary substitution
+ /// for type arguments in a subtype test.
+ ///
+ /// The result can be:
+ /// 1) `null`, if no substituted check is necessary, because the type
+ /// variables are the same or there are no type variables in the class
+ /// that is checked for.
+ /// 2) A list expression describing the type arguments to be used in the
+ /// subtype check, if the type arguments to be used in the check do not
+ /// depend on the type arguments of the object.
+ /// 3) A function mapping the type variables of the object to be checked to
+ /// a list expression.
@override
jsAst.Expression getSubstitutionCode(
Emitter emitter, Substitution substitution) {
@@ -2381,10 +2378,8 @@
TypeRepresentationGenerator(this.namer, this._nativeData);
- /**
- * Creates a type representation for [type]. [onVariable] is called to provide
- * the type representation for type variables.
- */
+ /// Creates a type representation for [type]. [onVariable] is called to
+ /// provide the type representation for type variables.
jsAst.Expression getTypeRepresentation(
Emitter emitter,
DartType type,
@@ -2787,10 +2782,8 @@
'parameters=$parameters,length=$length)';
}
-/**
- * A pair of a class that we need a check against and the type argument
- * substitution for this check.
- */
+/// A pair of a class that we need a check against and the type argument
+/// substitution for this check.
class TypeCheck {
final ClassEntity cls;
final bool needsIs;
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 73a5d1c..fb31e92 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -85,11 +85,9 @@
'function(#, v) { return #.# = v; }', [args, receiver, fieldName]);
}
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [member] must be a declaration element.
- */
+ /// Documentation wanted -- johnniwinther
+ ///
+ /// Invariant: [member] must be a declaration element.
Map<jsAst.Name, jsAst.Expression> generateCallStubsForGetter(
MemberEntity member, Map<Selector, SelectorConstraints> selectors) {
// If the method is intercepted, the stub gets the
@@ -245,12 +243,13 @@
///
/// `tearOff` takes the following arguments:
/// * `funcs`: a list of functions. These are the functions representing the
-/// member that is torn off. There can be more than one, since a member
-/// can have several stubs.
-/// Each function must have the `$callName` property set.
-/// * `applyTrampolineIndex` is the index of the stub to be used for Function.apply
+/// member that is torn off. There can be more than one, since a member
+/// can have several stubs.
+/// Each function must have the `$callName` property set.
+/// * `applyTrampolineIndex` is the index of the stub to be used for
+/// Function.apply
/// * `reflectionInfo`: contains reflective information, and the function
-/// type. TODO(floitsch): point to where this is specified.
+/// type. TODO(floitsch): point to where this is specified.
/// * `isStatic`.
/// * `name`.
/// * `isIntercepted.
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 36f8a9f..7fac11d 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -17,7 +17,6 @@
import '../js_backend/inferred_data.dart';
import '../universe/codegen_world_builder.dart';
import '../world.dart' show JClosedWorld;
-import 'full_emitter/emitter.dart' as full_js_emitter;
import 'program_builder/program_builder.dart';
import 'startup_emitter/emitter.dart' as startup_js_emitter;
@@ -27,12 +26,10 @@
import 'type_test_registry.dart' show TypeTestRegistry;
import 'sorter.dart';
-/**
- * Generates the code for all used classes in the program. Static fields (even
- * in classes) are ignored, since they can be treated as non-class elements.
- *
- * The code for the containing (used) methods must exist in the `universe`.
- */
+/// Generates the code for all used classes in the program. Static fields (even
+/// in classes) are ignored, since they can be treated as non-class elements.
+///
+/// The code for the containing (used) methods must exist in the `universe`.
class CodeEmitterTask extends CompilerTask {
TypeTestRegistry typeTestRegistry;
NativeEmitter _nativeEmitter;
@@ -50,14 +47,10 @@
/// Contains a list of all classes that are emitted.
Set<ClassEntity> neededClasses;
- CodeEmitterTask(
- Compiler compiler, bool generateSourceMap, bool useStartupEmitter)
+ CodeEmitterTask(Compiler compiler, bool generateSourceMap)
: compiler = compiler,
- _emitterFactory = useStartupEmitter
- ? new startup_js_emitter.EmitterFactory(
- generateSourceMap: generateSourceMap)
- : new full_js_emitter.EmitterFactory(
- generateSourceMap: generateSourceMap),
+ _emitterFactory = startup_js_emitter.EmitterFactory(
+ generateSourceMap: generateSourceMap),
super(compiler.measurer);
NativeEmitter get nativeEmitter {
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
deleted file mode 100644
index 7f55142..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_builder.dart
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.full_emitter.class_builder;
-
-import '../../elements/entities.dart';
-import '../../js/js.dart' as jsAst;
-import '../../js/js.dart' show js;
-import '../../js_backend/js_backend.dart' show Namer;
-
-/**
- * A data structure for collecting fragments of a class definition.
- */
-class ClassBuilder {
- final List<jsAst.Property> properties = <jsAst.Property>[];
- final List<jsAst.Literal> fields = <jsAst.Literal>[];
-
- jsAst.Name superName;
- jsAst.Node functionType;
- List<jsAst.Expression> fieldMetadata;
-
- final Entity element;
- final Namer namer;
- final bool isForActualClass;
-
- ClassBuilder.forLibrary(LibraryEntity library, this.namer)
- : isForActualClass = false,
- element = library;
-
- ClassBuilder.forClass(ClassEntity cls, this.namer)
- : isForActualClass = true,
- element = cls;
-
- ClassBuilder.forStatics(this.element, this.namer) : isForActualClass = false;
-
- jsAst.Property addProperty(jsAst.Literal name, jsAst.Expression value) {
- jsAst.Property property = new jsAst.Property(js.quoteName(name), value);
- properties.add(property);
- return property;
- }
-
- jsAst.Property addPropertyByName(String name, jsAst.Expression value) {
- jsAst.Property property = new jsAst.Property(js.string(name), value);
- properties.add(property);
- return property;
- }
-
- void addField(jsAst.Literal field) {
- fields.add(field);
- }
-
- static String functionTypeEncodingDescription =
- 'For simple function types the function type is stored in the metadata '
- 'and the index is encoded into the superclass field.';
-
- static String fieldEncodingDescription =
- 'Fields are encoded as a comma separated list. If there is a superclass '
- '(and possibly a function type encoding) the fields are separated from '
- 'the superclass by a semicolon.';
-
- jsAst.ObjectInitializer toObjectInitializer(
- {bool emitClassDescriptor: true}) {
- List<jsAst.Literal> parts = <jsAst.Literal>[];
- if (isForActualClass) {
- if (superName != null) {
- parts.add(superName);
- if (functionType != null) {
- // See [functionTypeEncodingDescription] above.
- parts.add(js.stringPart(':'));
- parts.add(functionType);
- }
- }
- parts.add(js.stringPart(';'));
- }
- // See [fieldEncodingDescription] above.
- parts.addAll(js.joinLiterals(fields, js.stringPart(',')));
- dynamic classData = js.concatenateStrings(parts, addQuotes: true);
- if (fieldMetadata != null) {
- // If we need to store fieldMetadata, classData is turned into an array,
- // and the field metadata is appended. So if classData is just a string,
- // there is no field metadata.
- classData =
- new jsAst.ArrayInitializer([classData]..addAll(fieldMetadata));
- }
- List<jsAst.Property> fieldsAndProperties;
- if (emitClassDescriptor) {
- fieldsAndProperties = <jsAst.Property>[];
- fieldsAndProperties.add(new jsAst.Property(
- js.string(namer.classDescriptorProperty), classData));
- fieldsAndProperties.addAll(properties);
- } else {
- fieldsAndProperties = properties;
- }
- return new jsAst.ObjectInitializer(fieldsAndProperties, isOneLiner: false);
- }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
deleted file mode 100644
index be7634c..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ /dev/null
@@ -1,343 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.full_emitter.class_emitter;
-
-import '../../common.dart';
-import '../../common/names.dart' show Names;
-import '../../common_elements.dart';
-import '../../deferred_load.dart' show OutputUnit;
-import '../../elements/entities.dart';
-import '../../js/js.dart' as jsAst;
-import '../../js/js.dart' show js;
-import '../../js_backend/js_backend.dart' show CompoundName, Namer;
-import '../../world.dart' show JClosedWorld;
-import '../js_emitter.dart' hide Emitter, EmitterFactory;
-import '../model.dart';
-import 'emitter.dart';
-
-class ClassEmitter extends CodeEmitterHelper {
- final JClosedWorld closedWorld;
-
- ClassEmitter(this.closedWorld);
-
- ClassStubGenerator get _stubGenerator => new ClassStubGenerator(task.emitter,
- closedWorld.commonElements, namer, codegenWorldBuilder, closedWorld,
- enableMinification: compiler.options.enableMinification);
-
- ElementEnvironment get _elementEnvironment => closedWorld.elementEnvironment;
-
- /**
- * Documentation wanted -- johnniwinther
- */
- void emitClass(Class cls, ClassBuilder enclosingBuilder, Fragment fragment) {
- ClassEntity classElement = cls.element;
-
- emitter.needsClassSupport = true;
-
- ClassEntity superclass = _elementEnvironment.getSuperClass(classElement);
- jsAst.Name superName;
- if (superclass != null) {
- superName = namer.className(superclass);
- }
-
- if (cls.mixinClass != null) {
- jsAst.Name mixinName = cls.mixinClass.name;
- superName = new CompoundName([superName, Namer.literalPlus, mixinName]);
- emitter.needsMixinSupport = true;
- }
-
- ClassBuilder builder = new ClassBuilder.forClass(classElement, namer);
- builder.superName = superName;
- emitConstructorsForCSP(cls);
- emitFields(cls, builder);
- if (cls.hasRtiField) {
- builder.addField(namer.rtiFieldJsName);
- }
- emitCheckedClassSetters(cls, builder);
- emitClassGettersSettersForCSP(cls, builder);
- emitInstanceMembers(cls, builder);
- emitStubs(cls.callStubs, builder);
- emitRuntimeTypeInformation(cls, builder);
- emitNativeInfo(cls, builder);
-
- if (classElement == closedWorld.commonElements.closureClass) {
- // We add a special getter here to allow for tearing off a closure from
- // itself.
- jsAst.Fun function = js('function() { return this; }');
- jsAst.Name name = namer.getterForMember(Names.call);
- builder.addProperty(name, function);
- }
-
- emitClassBuilderWithReflectionData(
- cls, builder, enclosingBuilder, fragment);
- }
-
- /**
- * Emits the precompiled constructor when in CSP mode.
- */
- void emitConstructorsForCSP(Class cls) {
- if (!compiler.options.useContentSecurityPolicy) return;
-
- List<jsAst.Name> fieldNames = <jsAst.Name>[];
- if (!cls.onlyForRti && !cls.isNative) {
- fieldNames = cls.fields.map((Field field) => field.name).toList();
- }
-
- ClassEntity classElement = cls.element;
-
- jsAst.Expression constructorAst = _stubGenerator.generateClassConstructor(
- classElement, fieldNames, cls.hasRtiField);
-
- jsAst.Name constructorName = namer.className(classElement);
- OutputUnit outputUnit =
- closedWorld.outputUnitData.outputUnitForClass(classElement);
- emitter.assemblePrecompiledConstructor(
- outputUnit, constructorName, constructorAst, fieldNames);
- }
-
- /// Returns `true` if fields added.
- bool emitFields(FieldContainer container, ClassBuilder builder,
- {bool classIsNative: false, bool emitStatics: false}) {
- Iterable<Field> fields;
- if (container is Class) {
- if (emitStatics) {
- fields = container.staticFieldsForReflection;
- } else if (container.onlyForRti) {
- return false;
- } else {
- fields = container.fields;
- }
- } else {
- assert(container is Library);
- assert(emitStatics);
- fields = container.staticFieldsForReflection;
- }
-
- bool fieldsAdded = false;
-
- for (Field field in fields) {
- FieldEntity fieldElement = field.element;
- jsAst.Name name = field.name;
- jsAst.Name accessorName = field.accessorName;
- bool needsGetter = field.needsGetter;
- bool needsSetter = field.needsUncheckedSetter;
-
- // Ignore needsCheckedSetter - that is handled below.
- bool needsAccessor = (needsGetter || needsSetter);
- // We need to output the fields for non-native classes so we can auto-
- // generate the constructor. For native classes there are no
- // constructors, so we don't need the fields unless we are generating
- // accessors at runtime.
- bool needsFieldsForConstructor = !emitStatics && !classIsNative;
- if (needsFieldsForConstructor || needsAccessor) {
- List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[];
- if (field.initializerInAllocator != null) {
- assert(field.initializerInAllocator.isNull);
- fieldNameParts.add(js.stringPart('0'));
- }
- if (!needsAccessor) {
- // Emit field for constructor generation.
- assert(!classIsNative);
- fieldNameParts.add(name);
- } else {
- // Emit (possibly renaming) field name so we can add accessors at
- // runtime.
- if (name != accessorName) {
- fieldNameParts.add(accessorName);
- fieldNameParts.add(js.stringPart(':'));
- }
- fieldNameParts.add(name);
- if (field.needsInterceptedGetter) {
- emitter.interceptorEmitter.interceptorInvocationNames
- .add(namer.getterForElement(fieldElement));
- }
- // TODO(16168): The setter creator only looks at the getter-name.
- // Even though the setter could avoid the interceptor convention we
- // currently still need to add the additional argument.
- if (field.needsInterceptedGetter || field.needsInterceptedSetter) {
- emitter.interceptorEmitter.interceptorInvocationNames
- .add(namer.setterForMember(fieldElement));
- }
-
- int code = field.getterFlags + (field.setterFlags << 2);
- if (code == 0) {
- reporter.internalError(
- fieldElement, 'Field code is 0 ($fieldElement).');
- }
- fieldNameParts.add(
- js.stringPart(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]));
- }
- jsAst.Literal fieldNameAst = js.concatenateStrings(fieldNameParts);
- builder.addField(fieldNameAst);
- // Add 1 because adding a field to the class also requires a comma
- compiler.dumpInfoTask.registerEntityAst(fieldElement, fieldNameAst);
- fieldsAdded = true;
- }
- }
-
- return fieldsAdded;
- }
-
- /// Emits checked setters for fields.
- void emitCheckedClassSetters(Class cls, ClassBuilder builder) {
- if (cls.onlyForRti) return;
-
- for (StubMethod method in cls.checkedSetters) {
- MemberEntity member = method.element;
- assert(member != null);
- jsAst.Expression code = method.code;
- jsAst.Name setterName = method.name;
- compiler.dumpInfoTask
- .registerEntityAst(member, builder.addProperty(setterName, code));
- }
- }
-
- /// Emits getters/setters for fields if compiling in CSP mode.
- void emitClassGettersSettersForCSP(Class cls, ClassBuilder builder) {
- if (!compiler.options.useContentSecurityPolicy || cls.onlyForRti) return;
-
- for (Field field in cls.fields) {
- FieldEntity member = field.element;
- reporter.withCurrentElement(member, () {
- if (field.needsGetter) {
- emitGetterForCSP(member, field.name, field.accessorName, builder);
- }
- if (field.needsUncheckedSetter) {
- emitSetterForCSP(member, field.name, field.accessorName, builder);
- }
- });
- }
- }
-
- void emitStubs(Iterable<StubMethod> stubs, ClassBuilder builder) {
- for (Method method in stubs) {
- jsAst.Property property = builder.addProperty(method.name, method.code);
- compiler.dumpInfoTask.registerEntityAst(method.element, property);
- }
- }
-
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [classElement] must be a declaration element.
- */
- void emitInstanceMembers(Class cls, ClassBuilder builder) {
- ClassEntity classElement = cls.element;
-
- if (cls.onlyForRti || cls.isSimpleMixinApplication) return;
-
- // TODO(herhut): This is a no-op. Should it be removed?
- for (Field field in cls.fields) {
- emitter.containerBuilder.addMemberField(field, builder);
- }
-
- for (Method method in cls.methods) {
- assert(method.element.isInstanceMember, failedAt(classElement));
- emitter.containerBuilder.addMemberMethod(method, builder);
- }
-
- if (classElement == closedWorld.commonElements.objectClass &&
- closedWorld.backendUsage.isNoSuchMethodUsed) {
- // Emit the noSuchMethod handlers on the Object prototype now,
- // so that the code in the dynamicFunction helper can find
- // them. Note that this helper is invoked before analyzing the
- // full JS script.
- emitter.nsmEmitter.emitNoSuchMethodHandlers(builder.addProperty);
- }
- }
-
- /// Emits the members from the model.
- void emitRuntimeTypeInformation(Class cls, ClassBuilder builder) {
- assert(builder.functionType == null);
- if (cls.functionTypeIndex != null) {
- builder.functionType = cls.functionTypeIndex;
- }
-
- for (Method method in cls.isChecks) {
- builder.addProperty(method.name, method.code);
- }
- }
-
- void emitNativeInfo(Class cls, ClassBuilder builder) {
- jsAst.Expression nativeInfo = NativeGenerator.encodeNativeInfo(cls);
- if (nativeInfo != null) {
- builder.addPropertyByName(namer.nativeSpecProperty, nativeInfo);
- }
- }
-
- void emitClassBuilderWithReflectionData(Class cls, ClassBuilder classBuilder,
- ClassBuilder enclosingBuilder, Fragment fragment) {
- ClassEntity classEntity = cls.element;
- jsAst.Name className = cls.name;
-
- List<jsAst.Property> statics = new List<jsAst.Property>();
- ClassBuilder staticsBuilder =
- new ClassBuilder.forStatics(classEntity, namer);
- if (emitFields(cls, staticsBuilder, emitStatics: true)) {
- jsAst.ObjectInitializer initializer =
- staticsBuilder.toObjectInitializer();
- compiler.dumpInfoTask.registerEntityAst(classEntity, initializer);
- jsAst.Node property = initializer.properties.single;
- compiler.dumpInfoTask.registerEntityAst(classEntity, property);
- statics.add(property);
- }
-
- // TODO(herhut): Do not grab statics out of the properties.
- ClassBuilder classProperties =
- emitter.classDescriptors[fragment]?.remove(classEntity);
- if (classProperties != null) {
- statics.addAll(classProperties.properties);
- }
-
- if (!statics.isEmpty) {
- classBuilder.addProperty(
- namer.staticsPropertyName, // 'static' or its minified name.
- new jsAst.ObjectInitializer(statics, isOneLiner: false));
- }
-
- // TODO(ahe): This method (generateClass) should return a jsAst.Expression.
- jsAst.ObjectInitializer propertyValue = classBuilder.toObjectInitializer();
- compiler.dumpInfoTask
- .registerEntityAst(classBuilder.element, propertyValue);
- enclosingBuilder.addProperty(className, propertyValue);
-
- String reflectionName =
- emitter.getReflectionClassName(classEntity, className);
- if (reflectionName != null) {
- // TODO(herhut): Fix use of reflection name here.
- enclosingBuilder.addPropertyByName("+$reflectionName", js.number(0));
- }
- }
-
- void emitGetterForCSP(FieldEntity member, jsAst.Name fieldName,
- jsAst.Name accessorName, ClassBuilder builder) {
- jsAst.Expression function =
- _stubGenerator.generateGetter(member, fieldName);
-
- jsAst.Name getterName = namer.deriveGetterName(accessorName);
- ClassEntity cls = member.enclosingClass;
- jsAst.Name className = namer.className(cls);
- OutputUnit outputUnit =
- closedWorld.outputUnitData.outputUnitForMember(member);
- emitter
- .cspPrecompiledFunctionFor(outputUnit)
- .add(js('#.prototype.# = #', [className, getterName, function]));
- }
-
- void emitSetterForCSP(FieldEntity member, jsAst.Name fieldName,
- jsAst.Name accessorName, ClassBuilder builder) {
- jsAst.Expression function =
- _stubGenerator.generateSetter(member, fieldName);
-
- jsAst.Name setterName = namer.deriveSetterName(accessorName);
- ClassEntity cls = member.enclosingClass;
- jsAst.Name className = namer.className(cls);
- OutputUnit outputUnit =
- closedWorld.outputUnitData.outputUnitForMember(member);
- emitter
- .cspPrecompiledFunctionFor(outputUnit)
- .add(js('#.prototype.# = #', [className, setterName, function]));
- }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart
deleted file mode 100644
index 36932fb..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/code_emitter_helper.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart2js.js_emitter.full_emitter;
-
-class CodeEmitterHelper {
- Emitter emitter;
-
- Namer get namer => emitter.namer;
-
- JavaScriptBackend get backend => emitter.backend;
-
- CodeEmitterTask get task => emitter.task;
-
- Compiler get compiler => emitter.compiler;
-
- DiagnosticReporter get reporter => compiler.reporter;
-
- CodegenWorldBuilder get codegenWorldBuilder => compiler.codegenWorldBuilder;
-
- String get n => emitter.n;
-
- String get _ => emitter._;
-
- String get N => emitter.N;
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
deleted file mode 100644
index 0836206..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/container_builder.dart
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.full_emitter.container_builder;
-
-import '../../deferred_load.dart' show OutputUnit;
-import '../../elements/entities.dart';
-import '../../elements/names.dart';
-import '../../js/js.dart' as jsAst;
-import '../../js/js.dart' show js;
-import '../../world.dart';
-import '../js_emitter.dart' hide Emitter, EmitterFactory;
-import '../model.dart';
-import 'emitter.dart';
-
-/// This class should morph into something that makes it easy to build
-/// JavaScript representations of libraries, class-sides, and instance-sides.
-/// Initially, it is just a placeholder for code that is moved from
-/// [CodeEmitterTask].
-class ContainerBuilder extends CodeEmitterHelper {
- JClosedWorld _closedWorld;
-
- ContainerBuilder(this._closedWorld);
-
- void addMemberMethod(DartMethod method, ClassBuilder builder) {
- FunctionEntity member = method.element;
- OutputUnit outputUnit =
- _closedWorld.outputUnitData.outputUnitForMember(member);
- jsAst.Name name = method.name;
- ParameterStructure parameters = member.parameterStructure;
- jsAst.Expression code = method.code;
- bool needsStubs = method.parameterStubs.isNotEmpty;
- bool canBeApplied = method.canBeApplied;
- bool canTearOff = method.needsTearOff;
- jsAst.Name tearOffName = method.tearOffName;
- bool isClosure = method is InstanceMethod && method.isClosureCallMethod;
- jsAst.Name superAlias = method is InstanceMethod ? method.aliasName : null;
- bool hasSuperAlias = superAlias != null;
- jsAst.Expression memberTypeExpression = method.functionType;
- bool needStructuredInfo = canTearOff || canBeApplied || hasSuperAlias;
-
- bool isIntercepted = false;
- if (method is InstanceMethod) {
- isIntercepted = method.isIntercepted;
- }
-
- emitter.interceptorEmitter.recordMangledNameOfMemberMethod(member, name);
-
- if (!needStructuredInfo) {
- compiler.dumpInfoTask
- .registerEntityAst(member, builder.addProperty(name, code));
-
- for (ParameterStubMethod stub in method.parameterStubs) {
- assert(stub.callName == null);
- jsAst.Property property = builder.addProperty(stub.name, stub.code);
- compiler.dumpInfoTask.registerEntityAst(member, property);
- emitter.interceptorEmitter
- .recordMangledNameOfMemberMethod(member, stub.name);
- }
- return;
- }
- emitter.needsStructuredMemberInfo = true;
-
- // This element is needed for reflection or needs additional stubs or has a
- // super alias. So we need to retain additional information.
-
- // The information is stored in an array with this format:
- //
- // 1. The alias name for this function (optional).
- // 2. Index into the functions and stubs of the apply stub (optional).
- // 3. The JS function for this member.
- // 4. First stub.
- // 5. Name of first stub.
- // ...
- // M. Call name of this member.
- // M+1. Call name of first stub.
- // ...
- // N. Getter name for tearOff.
- // N+1. (Required parameter count << 2) + (member.isAccessor ? 2 : 0) +
- // (isIntercepted ? 1 : 0)
- // N+2. (Optional parameter count << 1) +
- // (parameters.optionalParametersAreNamed ? 1 : 0).
- // N+3. Index to function type in constant pool.
- // N+4. First default argument.
- // ...
- // O. First parameter name (if needed for reflection or Function.apply).
- // ...
- // P. Unmangled name (if reflectable).
- // P+1. First metadata (if reflectable).
- // ...
- // TODO(ahe): Consider one of the parameter counts can be replaced by the
- // length property of the JavaScript function object.
-
- List<jsAst.Expression> expressions = <jsAst.Expression>[];
-
- // Create the optional aliasing entry if this method is called via super.
- if (hasSuperAlias) {
- expressions.add(js.quoteName(superAlias));
- }
-
- if (canBeApplied && parameters.typeParameters > 0) {
- // The first stub is the one that has all the value parameters parameters
- // but no type parameters. This is the entry point for Function.apply.
- expressions.add(js.number(1));
- }
-
- expressions.add(code);
-
- bool onlyNeedsSuperAlias = !(canTearOff || canBeApplied || needsStubs);
-
- if (onlyNeedsSuperAlias) {
- jsAst.ArrayInitializer arrayInit =
- new jsAst.ArrayInitializer(expressions);
- compiler.dumpInfoTask
- .registerEntityAst(member, builder.addProperty(name, arrayInit));
- return;
- }
-
- jsAst.Literal callSelectorString;
- if (method.callName == null) {
- callSelectorString = new jsAst.LiteralNull();
- } else {
- callSelectorString = js.quoteName(method.callName);
- }
-
- // On [requiredParameterCount], the lower bit is set if this method can be
- // called reflectively.
- int requiredParameterCount = parameters.requiredParameters << 2;
- if (member.isGetter || member.isSetter) requiredParameterCount += 2;
- if (isIntercepted) requiredParameterCount += 1;
-
- int optionalParameterCount = parameters.optionalParameters << 1;
- if (parameters.namedParameters.isNotEmpty) optionalParameterCount++;
-
- var tearOffInfo = <jsAst.Expression>[callSelectorString];
-
- for (ParameterStubMethod stub in method.parameterStubs) {
- jsAst.Name invocationName = stub.name;
- emitter.interceptorEmitter
- .recordMangledNameOfMemberMethod(member, invocationName);
-
- expressions.add(stub.code);
- if (member.isInstanceMember) {
- expressions.add(js.quoteName(invocationName));
- }
- jsAst.Name callName = stub.callName;
- jsAst.Literal callSelectorString =
- (callName == null) ? new jsAst.LiteralNull() : js.quoteName(callName);
- tearOffInfo.add(callSelectorString);
- }
-
- expressions
- ..addAll(tearOffInfo)
- ..add((tearOffName == null || member.isGetter || member.isSetter)
- ? js("null")
- : js.quoteName(tearOffName))
- ..add(js.number(requiredParameterCount))
- ..add(js.number(optionalParameterCount))
- ..add(memberTypeExpression == null ? js("null") : memberTypeExpression);
-
- if (canBeApplied) {
- expressions.addAll(
- task.metadataCollector.reifyDefaultArguments(member, outputUnit));
-
- codegenWorldBuilder.forEachParameter(member, (_, String name, _2) {
- expressions.add(task.metadataCollector.reifyName(name, outputUnit));
- });
- }
- Name memberName = member.memberName;
- if (isClosure && canBeApplied) {
- expressions.add(js.string(namer.privateName(memberName)));
- }
-
- jsAst.ArrayInitializer arrayInit =
- new jsAst.ArrayInitializer(expressions.toList());
- compiler.dumpInfoTask
- .registerEntityAst(member, builder.addProperty(name, arrayInit));
- }
-
- void addMemberField(Field field, ClassBuilder builder) {
- // For now, do nothing.
- }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart
deleted file mode 100644
index ac14c66..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/declarations.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart2js.js_emitter.full_emitter;
-
-/// Enables debugging of fast/slow objects using V8-specific primitives.
-const DEBUG_FAST_OBJECTS = false;
-
-/**
- * Call-back for adding property with [name] and [value].
- */
-typedef jsAst.Property AddPropertyFunction(
- jsAst.Name name, jsAst.Expression value);
-
-// Compact field specifications. The format of the field specification is
-// <accessorName>:<fieldName><suffix> where the suffix and accessor name
-// prefix are optional. The suffix directs the generation of getter and
-// setter methods. Each of the getter and setter has two bits to determine
-// the calling convention. Setter listed below, getter is similar.
-//
-// 00: no setter
-// 01: function(value) { this.field = value; }
-// 10: function(receiver, value) { receiver.field = value; }
-// 11: function(receiver, value) { this.field = value; }
-//
-// The suffix encodes 4 bits using three ASCII ranges of non-identifier
-// characters.
-const FIELD_CODE_CHARACTERS = r"<=>?@{|}~%&'()*";
-const NO_FIELD_CODE = 0;
-const FIRST_FIELD_CODE = 1;
-const RANGE1_FIRST = 0x3c; // <=>?@ encodes 1..5
-const RANGE1_LAST = 0x40;
-const RANGE2_FIRST = 0x7b; // {|}~ encodes 6..9
-const RANGE2_LAST = 0x7e;
-const RANGE3_FIRST = 0x25; // %&'()*+ encodes 10..16
-const RANGE3_LAST = 0x2b;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/deferred_output_unit_hash.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/deferred_output_unit_hash.dart
deleted file mode 100644
index 8c79a8b..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/deferred_output_unit_hash.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart2js.js_emitter.full_emitter;
-
-class _DeferredOutputUnitHash extends jsAst.DeferredString {
- String _hash;
- final OutputUnit _outputUnit;
-
- _DeferredOutputUnitHash(this._outputUnit);
-
- void setHash(String hash) {
- assert(_hash == null);
- _hash = hash;
- }
-
- String get value {
- assert(_hash != null);
- return '"$_hash"';
- }
-
- String toString() => "HashCode for ${_outputUnit} [$_hash]";
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
deleted file mode 100644
index 9da5325..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ /dev/null
@@ -1,1725 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.full_emitter;
-
-import 'dart:convert';
-
-import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
-import 'package:js_runtime/shared/embedded_names.dart'
- show JsBuiltin, JsGetName;
-
-import '../../../compiler_new.dart';
-import '../../common.dart';
-import '../../common_elements.dart' show CommonElements, ElementEnvironment;
-import '../../compiler.dart' show Compiler;
-import '../../constants/values.dart';
-import '../../deferred_load.dart'
- show deferredPartFileName, OutputUnit, OutputUnitData;
-import '../../elements/entities.dart';
-import '../../hash/sha1.dart' show Hasher;
-import '../../io/code_output.dart';
-import '../../io/location_provider.dart' show LocationCollector;
-import '../../io/source_map_builder.dart' show SourceMapBuilder;
-import '../../js/js.dart' as jsAst;
-import '../../js/js.dart' show js;
-import '../../js_backend/js_backend.dart'
- show ConstantEmitter, JavaScriptBackend, Namer;
-import '../../js_backend/native_data.dart';
-import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
-import '../../universe/call_structure.dart' show CallStructure;
-import '../../universe/codegen_world_builder.dart';
-import '../../util/uri_extras.dart' show relativize;
-import '../../world.dart' show JClosedWorld;
-import '../constant_ordering.dart' show ConstantOrdering;
-import '../headers.dart';
-import '../js_emitter.dart' hide Emitter, EmitterFactory;
-import '../js_emitter.dart' as js_emitter show EmitterBase, EmitterFactory;
-import '../model.dart';
-import '../program_builder/program_builder.dart';
-import '../sorter.dart';
-
-import 'class_builder.dart';
-import 'class_emitter.dart';
-import 'container_builder.dart';
-import 'interceptor_emitter.dart';
-import 'nsm_emitter.dart';
-
-export 'class_builder.dart';
-export 'class_emitter.dart';
-export 'container_builder.dart';
-export 'interceptor_emitter.dart';
-export 'nsm_emitter.dart';
-
-part 'code_emitter_helper.dart';
-part 'declarations.dart';
-part 'deferred_output_unit_hash.dart';
-part 'setup_program_builder.dart';
-
-class EmitterFactory implements js_emitter.EmitterFactory {
- final bool generateSourceMap;
-
- EmitterFactory({this.generateSourceMap});
-
- @override
- bool get supportsReflection => true;
-
- @override
- Emitter createEmitter(CodeEmitterTask task, Namer namer,
- JClosedWorld closedWorld, Sorter sorter) {
- return new Emitter(
- task.compiler, namer, closedWorld, generateSourceMap, task, sorter);
- }
-}
-
-class Emitter extends js_emitter.EmitterBase {
- final Compiler compiler;
- final CodeEmitterTask task;
- final JClosedWorld _closedWorld;
-
- // The following fields will be set to copies of the program-builder's
- // collector.
- Map<OutputUnit, List<FieldEntity>> outputStaticNonFinalFieldLists;
- Map<OutputUnit, Set<LibraryEntity>> outputLibraryLists;
-
- final ContainerBuilder containerBuilder;
- final ClassEmitter classEmitter;
- final NsmEmitter nsmEmitter;
- final InterceptorEmitter interceptorEmitter;
- final Sorter _sorter;
- final ConstantOrdering _constantOrdering;
-
- // TODO(johnniwinther): Wrap these fields in a caching strategy.
- final List<jsAst.Statement> cachedEmittedConstantsAst = <jsAst.Statement>[];
-
- bool needsClassSupport = false;
- bool needsMixinSupport = false;
- bool needsLazyInitializer = false;
-
- /// True if [ContainerBuilder.addMemberMethodFromInfo] used "structured info",
- /// that is, some function was needed for reflection, had stubs, or had a
- /// super alias.
- bool needsStructuredMemberInfo = false;
-
- final Namer namer;
- ConstantEmitter constantEmitter;
- NativeEmitter get nativeEmitter => task.nativeEmitter;
- TypeTestRegistry get typeTestRegistry => task.typeTestRegistry;
- CommonElements get commonElements => _closedWorld.commonElements;
- ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
- CodegenWorldBuilder get _worldBuilder => compiler.codegenWorldBuilder;
- OutputUnitData get _outputUnitData => _closedWorld.outputUnitData;
-
- // The full code that is written to each hunk part-file.
- Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>();
-
- String classesCollector;
-
- JavaScriptBackend get backend => compiler.backend;
-
- String get _ => space;
- String get space => compiler.options.enableMinification ? "" : " ";
- String get n => compiler.options.enableMinification ? "" : "\n";
- String get N => compiler.options.enableMinification ? "\n" : ";\n";
-
- /**
- * List of expressions and statements that will be included in the
- * precompiled function.
- *
- * To save space, dart2js normally generates constructors and accessors
- * dynamically. This doesn't work in CSP mode, so dart2js emits them directly
- * when in CSP mode.
- */
- Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions =
- new Map<OutputUnit, List<jsAst.Node>>();
-
- Map<OutputUnit, List<jsAst.Expression>> _cspPrecompiledConstructorNames =
- new Map<OutputUnit, List<jsAst.Expression>>();
-
- /**
- * Accumulate properties for classes and libraries, describing their
- * static/top-level members.
- * Later, these members are emitted when the class or library is emitted.
- *
- * See [getElementDescriptor].
- */
- // TODO(ahe): Generate statics with their class, and store only libraries in
- // this map.
- final Map<Fragment, Map<LibraryEntity, ClassBuilder>> libraryDescriptors =
- new Map<Fragment, Map<LibraryEntity, ClassBuilder>>();
-
- final Map<Fragment, Map<ClassEntity, ClassBuilder>> classDescriptors =
- new Map<Fragment, Map<ClassEntity, ClassBuilder>>();
-
- final bool generateSourceMap;
-
- Emitter(this.compiler, this.namer, this._closedWorld, this.generateSourceMap,
- this.task, Sorter sorter)
- : classEmitter = new ClassEmitter(_closedWorld),
- interceptorEmitter = new InterceptorEmitter(_closedWorld),
- nsmEmitter = new NsmEmitter(_closedWorld),
- _sorter = sorter,
- containerBuilder = new ContainerBuilder(_closedWorld),
- _constantOrdering = new ConstantOrdering(sorter) {
- constantEmitter = new ConstantEmitter(
- compiler.options,
- _closedWorld.commonElements,
- compiler.codegenWorldBuilder,
- _closedWorld.rtiNeed,
- compiler.backend.rtiEncoder,
- _closedWorld.allocatorAnalysis,
- task,
- this.constantReference,
- constantListGenerator);
- containerBuilder.emitter = this;
- classEmitter.emitter = this;
- nsmEmitter.emitter = this;
- interceptorEmitter.emitter = this;
- }
-
- DiagnosticReporter get reporter => compiler.reporter;
-
- NativeData get _nativeData => _closedWorld.nativeData;
-
- List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) {
- return _cspPrecompiledFunctions.putIfAbsent(
- outputUnit, () => new List<jsAst.Node>());
- }
-
- List<jsAst.Expression> cspPrecompiledConstructorNamesFor(
- OutputUnit outputUnit) {
- return _cspPrecompiledConstructorNames.putIfAbsent(
- outputUnit, () => new List<jsAst.Expression>());
- }
-
- @override
- bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
- if (constant.isFunction) return true; // Already emitted.
- if (constant.isPrimitive) return true; // Inlined.
- if (constant.isDummy) return true; // Inlined.
- // The name is null when the constant is already a JS constant.
- // TODO(floitsch): every constant should be registered, so that we can
- // share the ones that take up too much space (like some strings).
- if (namer.constantName(constant) == null) return true;
- return false;
- }
-
- @override
- int compareConstants(ConstantValue a, ConstantValue b) {
- // Inlined constants don't affect the order and sometimes don't even have
- // names.
- int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1;
- int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1;
- if (cmp1 + cmp2 < 2) return cmp1 - cmp2;
-
- // Emit constant interceptors first. Constant interceptors for primitives
- // might be used by code that builds other constants. See Issue 18173.
- if (a.isInterceptor != b.isInterceptor) {
- return a.isInterceptor ? -1 : 1;
- }
-
- // Sorting by the long name clusters constants with the same constructor
- // which compresses a tiny bit better.
- int r = namer.constantLongName(a).compareTo(namer.constantLongName(b));
- if (r != 0) return r;
-
- // Resolve collisions in the long name by using a structural order.
- return _constantOrdering.compare(a, b);
- }
-
- @override
- jsAst.Expression constantReference(ConstantValue value) {
- if (value.isFunction) {
- FunctionConstantValue functionConstant = value;
- return isolateStaticClosureAccess(functionConstant.element);
- }
-
- // We are only interested in the "isInlined" part, but it does not hurt to
- // test for the other predicates.
- if (isConstantInlinedOrAlreadyEmitted(value)) {
- return constantEmitter.generate(value);
- }
- return js('#.#',
- [namer.globalObjectForConstant(value), namer.constantName(value)]);
- }
-
- jsAst.Expression constantInitializerExpression(ConstantValue value) {
- return constantEmitter.generate(value);
- }
-
- String get name => 'CodeEmitter';
-
- String get finishIsolateConstructorName =>
- '${namer.isolateName}.\$finishIsolateConstructor';
- String get isolatePropertiesName =>
- '${namer.isolateName}.${namer.isolatePropertiesName}';
- String get lazyInitializerProperty => r'$lazy';
- String get lazyInitializerName =>
- '${namer.isolateName}.${lazyInitializerProperty}';
- String get initName => 'init';
-
- jsAst.Name get makeConstListProperty =>
- namer.internalGlobal('makeConstantList');
-
- /// For deferred loading we communicate the initializers via this global var.
- final String deferredInitializers = r"$dart_deferred_initializers$";
-
- /// Contains the global state that is needed to initialize and load a
- /// deferred library.
- String get globalsHolder => r"$globals$";
-
- @override
- jsAst.Expression generateEmbeddedGlobalAccess(String global) {
- return js(generateEmbeddedGlobalAccessString(global));
- }
-
- String generateEmbeddedGlobalAccessString(String global) {
- // TODO(floitsch): don't use 'init' as global embedder storage.
- return '$initName.$global';
- }
-
- @override
- jsAst.Expression isolateLazyInitializerAccess(FieldEntity element) {
- return jsAst.js('#.#', [
- namer.globalObjectForMember(element),
- namer.lazyInitializerName(element)
- ]);
- }
-
- @override
- jsAst.Expression isolateStaticClosureAccess(FunctionEntity element) {
- return jsAst.js('#.#()', [
- namer.globalObjectForMember(element),
- namer.staticClosureName(element)
- ]);
- }
-
- @override
- jsAst.PropertyAccess prototypeAccess(
- ClassEntity element, bool hasBeenInstantiated) {
- return jsAst.js('#.prototype', constructorAccess(element));
- }
-
- @override
- jsAst.Template templateForBuiltin(JsBuiltin builtin) {
- switch (builtin) {
- case JsBuiltin.dartObjectConstructor:
- return jsAst.js
- .expressionTemplateYielding(typeAccess(commonElements.objectClass));
-
- case JsBuiltin.isCheckPropertyToJsConstructorName:
- int isPrefixLength = namer.operatorIsPrefix.length;
- return jsAst.js.expressionTemplateFor('#.substring($isPrefixLength)');
-
- case JsBuiltin.isFunctionType:
- return backend.rtiEncoder.templateForIsFunctionType;
-
- case JsBuiltin.isFutureOrType:
- return backend.rtiEncoder.templateForIsFutureOrType;
-
- case JsBuiltin.isVoidType:
- return backend.rtiEncoder.templateForIsVoidType;
-
- case JsBuiltin.isDynamicType:
- return backend.rtiEncoder.templateForIsDynamicType;
-
- case JsBuiltin.isJsInteropTypeArgument:
- return backend.rtiEncoder.templateForIsJsInteropTypeArgument;
-
- case JsBuiltin.rawRtiToJsConstructorName:
- return jsAst.js.expressionTemplateFor("#.$typeNameProperty");
-
- case JsBuiltin.rawRuntimeType:
- return jsAst.js.expressionTemplateFor("#.constructor");
-
- case JsBuiltin.isSubtype:
- // TODO(floitsch): move this closer to where is-check properties are
- // built.
- String isPrefix = namer.operatorIsPrefix;
- return jsAst.js
- .expressionTemplateFor("('$isPrefix' + #) in #.prototype");
-
- case JsBuiltin.isGivenTypeRti:
- return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #');
-
- case JsBuiltin.getMetadata:
- String metadataAccess =
- generateEmbeddedGlobalAccessString(embeddedNames.METADATA);
- return jsAst.js.expressionTemplateFor("$metadataAccess[#]");
-
- case JsBuiltin.getType:
- String typesAccess =
- generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
- return jsAst.js.expressionTemplateFor("$typesAccess[#]");
-
- default:
- reporter.internalError(
- NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
- return null;
- }
- }
-
- @override
- int generatedSize(OutputUnit unit) {
- return outputBuffers[unit].length;
- }
-
- List<jsAst.Statement> buildTrivialNsmHandlers() {
- return nsmEmitter.buildTrivialNsmHandlers();
- }
-
- jsAst.Statement buildNativeInfoHandler(
- jsAst.Expression infoAccess,
- jsAst.Expression constructorAccess,
- jsAst.Expression subclassReadGenerator(jsAst.Expression subclass),
- jsAst.Expression interceptorsByTagAccess,
- jsAst.Expression leafTagsAccess) {
- return NativeGenerator.buildNativeInfoHandler(infoAccess, constructorAccess,
- subclassReadGenerator, interceptorsByTagAccess, leafTagsAccess);
- }
-
- /// In minified mode we want to keep the name for the most common core types.
- bool _isNativeTypeNeedingReflectionName(ClassEntity element) {
- return (element == commonElements.intClass ||
- element == commonElements.doubleClass ||
- element == commonElements.numClass ||
- element == commonElements.stringClass ||
- element == commonElements.boolClass ||
- element == commonElements.nullClass ||
- element == commonElements.listClass);
- }
-
- /// Returns the "reflection name" of a [ClassEntity], if needed.
- ///
- /// The reflection name of class 'C' is 'C'.
- /// An anonymous mixin application has no reflection name.
- ///
- /// This is used by js_mirrors.dart.
- // TODO(johnniwinther): Do we still need this when js_mirrors is deleted?
- String getReflectionClassName(ClassEntity cls, jsAst.Name mangledName) {
- // Make sure to retain names of common native types.
- if (_isNativeTypeNeedingReflectionName(cls)) {
- assert(!cls.isClosure);
- assert(!_elementEnvironment.isUnnamedMixinApplication(cls));
- return cls.name;
- }
- return null;
- }
-
- String namedParametersAsReflectionNames(CallStructure structure) {
- if (structure.isUnnamed) return '';
- String names = structure.getOrderedNamedArguments().join(':');
- return ':$names';
- }
-
- jsAst.Statement buildCspPrecompiledFunctionFor(OutputUnit outputUnit) {
- if (compiler.options.useContentSecurityPolicy) {
- // TODO(ahe): Compute a hash code.
- // TODO(sigurdm): Avoid this precompiled function. Generated
- // constructor-functions and getter/setter functions can be stored in the
- // library-description table. Setting properties on these can be moved to
- // finishClasses.
- return js.statement(r"""
- #precompiled = function ($collectedClasses$) {
- #norename;
- var $desc;
- #functions;
- return #result;
- };""", {
- 'norename': new jsAst.Comment("// ::norenaming:: "),
- 'precompiled': generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED),
- 'functions': cspPrecompiledFunctionFor(outputUnit),
- 'result': new jsAst.ArrayInitializer(
- cspPrecompiledConstructorNamesFor(outputUnit))
- });
- } else {
- return js.comment("Constructors are generated at runtime.");
- }
- }
-
- void assembleClass(
- Class cls, ClassBuilder enclosingBuilder, Fragment fragment) {
- ClassEntity classElement = cls.element;
- reporter.withCurrentElement(classElement, () {
- classEmitter.emitClass(cls, enclosingBuilder, fragment);
- });
- }
-
- void assembleStaticFunctions(
- Iterable<Method> staticFunctions, Fragment fragment) {
- if (staticFunctions == null) return;
-
- for (Method method in staticFunctions) {
- FunctionEntity element = method.element;
- // We need to filter out null-elements for the interceptors.
- // TODO(floitsch): use the precomputed interceptors here.
- if (element == null) continue;
- ClassBuilder builder = new ClassBuilder.forStatics(element, namer);
- containerBuilder.addMemberMethod(method, builder);
- getStaticMethodDescriptor(element, fragment)
- .properties
- .addAll(builder.properties);
- }
- }
-
- jsAst.Statement buildStaticNonFinalFieldInitializations(
- OutputUnit outputUnit) {
- jsAst.Statement buildInitialization(
- FieldEntity element, jsAst.Expression initialValue) {
- return js.statement('${namer.staticStateHolder}.# = #',
- [namer.globalPropertyNameForMember(element), initialValue]);
- }
-
- bool inMainUnit = (outputUnit == _outputUnitData.mainOutputUnit);
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- Iterable<FieldEntity> fields = outputStaticNonFinalFieldLists[outputUnit];
- // If the outputUnit does not contain any static non-final fields, then
- // [fields] is `null`.
- if (fields != null) {
- for (FieldEntity element in fields) {
- reporter.withCurrentElement(element, () {
- ConstantValue constant =
- _worldBuilder.getConstantFieldInitializer(element);
- parts.add(buildInitialization(element, constantReference(constant)));
- });
- }
- }
-
- if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) {
- // In the main output-unit we output a stub initializer for deferred
- // variables, so that `isolateProperties` stays a fast object.
- outputStaticNonFinalFieldLists
- .forEach((OutputUnit fieldsOutputUnit, Iterable<FieldEntity> fields) {
- if (fieldsOutputUnit == outputUnit) return; // Skip the main unit.
- for (FieldEntity element in fields) {
- reporter.withCurrentElement(element, () {
- parts.add(buildInitialization(element, jsAst.number(0)));
- });
- }
- });
- }
-
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildLazilyInitializedStaticFields(
- Iterable<StaticField> lazyFields,
- {bool isMainFragment: true}) {
- if (lazyFields.isNotEmpty) {
- needsLazyInitializer = true;
- List<jsAst.Expression> laziesInfo =
- buildLaziesInfo(lazyFields, isMainFragment);
- return js.statement('''
- (function(lazies) {
- for (var i = 0; i < lazies.length; ) {
- var fieldName = lazies[i++];
- var getterName = lazies[i++];
- var lazyValue = lazies[i++];
- if (#notMinified) {
- var staticName = lazies[i++];
- }
- if (#isDeferredFragment) {
- var fieldHolder = lazies[i++];
- }
- // We build the lazy-check here:
- // lazyInitializer(fieldName, getterName, lazyValue, staticName);
- // 'staticName' is used for error reporting in non-minified mode.
- // 'lazyValue' must be a closure that constructs the initial value.
- if (#isMainFragment) {
- if (#notMinified) {
- #lazy(fieldName, getterName, lazyValue, staticName);
- } else {
- #lazy(fieldName, getterName, lazyValue);
- }
- } else {
- if (#notMinified) {
- #lazy(fieldName, getterName, lazyValue, staticName, fieldHolder);
- } else {
- #lazy(fieldName, getterName, lazyValue, null, fieldHolder);
- }
- }
- }
- })(#laziesInfo)
- ''', {
- 'notMinified': !compiler.options.enableMinification,
- 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo),
- 'lazy': js(lazyInitializerName),
- 'isMainFragment': isMainFragment,
- 'isDeferredFragment': !isMainFragment
- });
- } else {
- return js.comment("No lazy statics.");
- }
- }
-
- List<jsAst.Expression> buildLaziesInfo(
- Iterable<StaticField> lazies, bool isMainFragment) {
- List<jsAst.Expression> laziesInfo = <jsAst.Expression>[];
- for (StaticField field in lazies) {
- laziesInfo.add(js.quoteName(field.name));
- laziesInfo.add(js.quoteName(field.getterName));
- laziesInfo.add(field.code);
- if (!compiler.options.enableMinification) {
- laziesInfo.add(js.quoteName(field.name));
- }
- if (!isMainFragment) {
- laziesInfo.add(js('#', field.holder.name));
- }
- }
- return laziesInfo;
- }
-
- jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- jsAst.Expression metadata = program.metadataForOutputUnit(outputUnit);
- jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit);
-
- if (outputUnit == _outputUnitData.mainOutputUnit) {
- jsAst.Expression metadataAccess =
- generateEmbeddedGlobalAccess(embeddedNames.METADATA);
- jsAst.Expression typesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.TYPES);
-
- parts
- ..add(js.statement('# = #;', [metadataAccess, metadata]))
- ..add(js.statement('# = #;', [typesAccess, types]));
- } else if (types != null) {
- parts.add(
- js.statement('var ${namer.deferredMetadataName} = #;', metadata));
- parts.add(js.statement('var ${namer.deferredTypesName} = #;', types));
- }
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildCompileTimeConstants(List<Constant> constants,
- {bool isMainFragment}) {
- assert(isMainFragment != null);
-
- if (constants.isEmpty) return js.comment("No constants in program.");
- List<jsAst.Statement> parts = <jsAst.Statement>[];
- for (Constant constant in constants) {
- ConstantValue constantValue = constant.value;
- parts.add(buildConstantInitializer(constantValue));
- }
-
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildConstantInitializer(ConstantValue constant) {
- jsAst.Name name = namer.constantName(constant);
- jsAst.Statement initializer = js.statement('#.# = #', [
- namer.globalObjectForConstant(constant),
- name,
- constantInitializerExpression(constant)
- ]);
- compiler.dumpInfoTask.registerConstantAst(constant, initializer);
- return initializer;
- }
-
- jsAst.Expression constantListGenerator(jsAst.Expression array) {
- // TODO(floitsch): there is no harm in caching the template.
- return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]);
- }
-
- jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) {
- if (outputContainsConstantList) {
- return js.statement(r'''
- // Functions are stored in the hidden class and not as properties in
- // the object. We never actually look at the value, but only want
- // to know if the property exists.
- #.# = function (list) {
- list.immutable$list = Array;
- list.fixed$length = Array;
- return list;
- }''', [namer.isolateName, makeConstListProperty]);
- } else {
- return js.comment("Output contains no constant list.");
- }
- }
-
- jsAst.Statement buildFunctionThatReturnsNull() {
- return js.statement('#.# = function() {}',
- [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]);
- }
-
- jsAst.Expression generateFunctionThatReturnsNull() {
- return js("#.#",
- [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]);
- }
-
- buildMain(jsAst.Statement invokeMain) {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- if (NativeGenerator.needsIsolateAffinityTagInitialization(
- _closedWorld.backendUsage)) {
- parts.add(NativeGenerator.generateIsolateAffinityTagInitialization(
- _closedWorld.backendUsage, generateEmbeddedGlobalAccess, js("""
- // On V8, the 'intern' function converts a string to a symbol, which
- // makes property access much faster.
- function (s) {
- var o = {};
- o[s] = 1;
- return Object.keys(convertToFastObject(o))[0];
- }""", [])));
- }
-
- parts
- ..add(js.comment('BEGIN invoke [main].'))
- ..add(invokeMain)
- ..add(js.comment('END invoke [main].'));
-
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildInitFunction(bool outputContainsConstantList) {
- jsAst.Expression allClassesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
- jsAst.Expression getTypeFromNameAccess =
- generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME);
- jsAst.Expression interceptorsByTagAccess =
- generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
- jsAst.Expression leafTagsAccess =
- generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
- jsAst.Expression finishedClassesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
- jsAst.Expression cyclicThrow =
- staticFunctionAccess(commonElements.cyclicThrowHelper);
- jsAst.Expression laziesAccess =
- generateEmbeddedGlobalAccess(embeddedNames.LAZIES);
-
- return js.statement("""
- function init() {
- $isolatePropertiesName = Object.create(null);
- #allClasses = map();
- #getTypeFromName = function(name) {return #allClasses[name];};
- #interceptorsByTag = map();
- #leafTags = map();
- #finishedClasses = map();
-
- if (#needsLazyInitializer) {
- // [staticName] is only provided in non-minified mode. If missing, we
- // fall back to [fieldName]. Likewise, [prototype] is optional and
- // defaults to the isolateProperties object.
- $lazyInitializerName = function (fieldName, getterName, lazyValue,
- staticName, prototype) {
- if (!#lazies) #lazies = Object.create(null);
- #lazies[fieldName] = getterName;
-
- // 'prototype' will be undefined except if we are doing an update
- // during incremental compilation. In this case we put the lazy
- // field directly on the isolate instead of the isolateProperties.
- prototype = prototype || $isolatePropertiesName;
- var sentinelUndefined = {};
- var sentinelInProgress = {};
- prototype[fieldName] = sentinelUndefined;
-
- prototype[getterName] = function () {
- var result = this[fieldName];
- if (result == sentinelInProgress) {
- // In minified mode, static name is not provided, so fall back
- // to the minified fieldName.
- #cyclicThrow(staticName || fieldName);
- }
- try {
- if (result === sentinelUndefined) {
- this[fieldName] = sentinelInProgress;
- try {
- result = this[fieldName] = lazyValue();
- } finally {
- // Use try-finally, not try-catch/throw as it destroys the
- // stack trace.
- if (result === sentinelUndefined)
- this[fieldName] = null;
- }
- }
- return result;
- } finally {
- this[getterName] = function() { return this[fieldName]; };
- }
- }
- }
- }
-
- // We replace the old Isolate function with a new one that initializes
- // all its fields with the initial (and often final) value of all
- // globals.
- //
- // We also copy over old values like the prototype, and the
- // isolateProperties themselves.
- $finishIsolateConstructorName = function (oldIsolate) {
- var isolateProperties = oldIsolate.#isolatePropertiesName;
- function Isolate() {
-
- var staticNames = Object.keys(isolateProperties);
- for (var i = 0; i < staticNames.length; i++) {
- var staticName = staticNames[i];
- this[staticName] = isolateProperties[staticName];
- }
-
- // Reset lazy initializers to null.
- // When forcing the object to fast mode (below) v8 will consider
- // functions as part the object's map. Since we will change them
- // (after the first call to the getter), we would have a map
- // transition.
- var lazies = init.lazies;
- var lazyInitializers = lazies ? Object.keys(lazies) : [];
- for (var i = 0; i < lazyInitializers.length; i++) {
- this[lazies[lazyInitializers[i]]] = null;
- }
-
- // Use the newly created object as prototype. In Chrome,
- // this creates a hidden class for the object and makes
- // sure it is fast to access.
- function ForceEfficientMap() {}
- ForceEfficientMap.prototype = this;
- new ForceEfficientMap();
-
- // Now, after being a fast map we can set the lazies again.
- for (var i = 0; i < lazyInitializers.length; i++) {
- var lazyInitName = lazies[lazyInitializers[i]];
- this[lazyInitName] = isolateProperties[lazyInitName];
- }
- }
- Isolate.prototype = oldIsolate.prototype;
- Isolate.prototype.constructor = Isolate;
- Isolate.#isolatePropertiesName = isolateProperties;
- if (#outputContainsConstantList) {
- Isolate.#makeConstListProperty = oldIsolate.#makeConstListProperty;
- }
- Isolate.#functionThatReturnsNullProperty =
- oldIsolate.#functionThatReturnsNullProperty;
- return Isolate;
- }
-
- }""", {
- 'allClasses': allClassesAccess,
- 'getTypeFromName': getTypeFromNameAccess,
- 'interceptorsByTag': interceptorsByTagAccess,
- 'leafTags': leafTagsAccess,
- 'finishedClasses': finishedClassesAccess,
- 'needsLazyInitializer': needsLazyInitializer,
- 'lazies': laziesAccess,
- 'cyclicThrow': cyclicThrow,
- 'isolatePropertiesName': namer.isolatePropertiesName,
- 'outputContainsConstantList': outputContainsConstantList,
- 'makeConstListProperty': makeConstListProperty,
- 'functionThatReturnsNullProperty':
- backend.rtiEncoder.getFunctionThatReturnsNullName,
- });
- }
-
- jsAst.Statement buildConvertToFastObjectFunction() {
- List<jsAst.Statement> debugCode = <jsAst.Statement>[];
- if (DEBUG_FAST_OBJECTS) {
- debugCode.add(js.statement(r'''
- // The following only works on V8 when run with option
- // "--allow-natives-syntax". We use'new Function' because the
- // miniparser does not understand V8 native syntax.
- if (typeof print === "function") {
- var HasFastProperties =
- new Function("a", "return %HasFastProperties(a)");
- print("Size of global object: "
- + String(Object.getOwnPropertyNames(properties).length)
- + ", fast properties " + HasFastProperties(properties));
- }'''));
- }
-
- return js.statement(r'''
- function convertToFastObject(properties) {
- // Create an instance that uses 'properties' as prototype. This should
- // make 'properties' a fast object.
- function MyClass() {};
- MyClass.prototype = properties;
- new MyClass();
- #;
- return properties;
- }''', [debugCode]);
- }
-
- jsAst.Statement buildConvertToSlowObjectFunction() {
- return js.statement(r'''
- function convertToSlowObject(properties) {
- // Add and remove a property to make the object transition into hashmap
- // mode.
- properties.__MAGIC_SLOW_PROPERTY = 1;
- delete properties.__MAGIC_SLOW_PROPERTY;
- return properties;
- }''');
- }
-
- jsAst.Statement buildSupportsDirectProtoAccess() {
- jsAst.Statement supportsDirectProtoAccess;
-
- supportsDirectProtoAccess = js.statement(r'''
- var supportsDirectProtoAccess = (function () {
- var cls = function () {};
- cls.prototype = {'p': {}};
- var object = new cls();
- if (!(object.__proto__ && object.__proto__.p === cls.prototype.p))
- return false;
-
- try {
- // Are we running on a platform where the performance is good?
- // (i.e. Chrome or d8).
-
- // Chrome userAgent?
- if (typeof navigator != "undefined" &&
- typeof navigator.userAgent == "string" &&
- navigator.userAgent.indexOf("Chrome/") >= 0) return true;
-
- // d8 version() looks like "N.N.N.N", jsshell version() like "N".
- if (typeof version == "function" &&
- version.length == 0) {
- var v = version();
- if (/^\d+\.\d+\.\d+\.\d+$/.test(v)) return true;
- }
- } catch(_) {}
-
- return false;
- })();
- ''');
-
- return supportsDirectProtoAccess;
- }
-
- jsAst.Expression generateLibraryDescriptor(
- LibraryEntity library, Fragment fragment) {
- dynamic uri = "";
- if (!compiler.options.enableMinification) {
- uri = library.canonicalUri;
- if (uri.scheme == 'file' && compiler.options.outputUri != null) {
- uri =
- relativize(compiler.options.outputUri, library.canonicalUri, false);
- }
- }
-
- String libraryName = !compiler.options.enableMinification
- ? _elementEnvironment.getLibraryName(library)
- : "";
-
- jsAst.Fun metadata = null;
-
- ClassBuilder descriptor = libraryDescriptors[fragment][library];
-
- jsAst.ObjectInitializer initializer;
- if (descriptor == null) {
- // Nothing of the library was emitted.
- // TODO(floitsch): this should not happen. We currently have an example
- // with language/prefix6_negative_test.dart where we have an instance
- // method without its corresponding class.
- initializer = new jsAst.ObjectInitializer([]);
- } else {
- initializer = descriptor.toObjectInitializer();
- }
-
- compiler.dumpInfoTask.registerEntityAst(library, metadata);
- compiler.dumpInfoTask.registerEntityAst(library, initializer);
-
- List<jsAst.Expression> parts = <jsAst.Expression>[];
- parts
- ..add(js.string(libraryName))
- ..add(js.string(uri.toString()))
- ..add(metadata == null ? new jsAst.ArrayHole() : metadata)
- ..add(js('#', namer.globalObjectForLibrary(library)))
- ..add(initializer);
- if (library == _closedWorld.elementEnvironment.mainLibrary) {
- parts.add(js.number(1));
- }
-
- return new jsAst.ArrayInitializer(parts);
- }
-
- void assemblePrecompiledConstructor(
- OutputUnit outputUnit,
- jsAst.Name constructorName,
- jsAst.Expression constructorAst,
- List<jsAst.Name> fields) {
- cspPrecompiledFunctionFor(outputUnit)
- .add(new jsAst.FunctionDeclaration(constructorName, constructorAst));
-
- cspPrecompiledFunctionFor(outputUnit).add(js.statement(r'''
- {
- #constructorName.#typeNameProperty = #constructorNameString;
- // IE does not have a name property.
- if (!("name" in #constructorName))
- #constructorName.name = #constructorNameString;
- $desc = $collectedClasses$.#constructorName[1];
- #constructorName.prototype = $desc;
- }''', {
- "constructorName": constructorName,
- "typeNameProperty": typeNameProperty,
- "constructorNameString": js.quoteName(constructorName),
- }));
-
- cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName));
- }
-
- jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- parts.add(js.comment("""
- // The global objects start as so-called "slow objects". For V8, this
- // means that it won't try to make map transitions as we add properties
- // to these objects. Later on, we attempt to turn these objects into
- // fast objects by calling "convertToFastObject" (see
- // [emitConvertToFastObjectFunction]).
- """));
-
- for (String globalObject in Namer.reservedGlobalObjectNames) {
- if (isProgramSplit) {
- String template =
- "var #globalObject = #globalsHolder.#globalObject = map();";
- parts.add(js.statement(template,
- {"globalObject": globalObject, "globalsHolder": globalsHolder}));
- } else {
- parts.add(js.statement(
- "var #globalObject = map();", {"globalObject": globalObject}));
- }
- }
-
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildConvertGlobalObjectToFastObjects() {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- for (String globalObject in Namer.reservedGlobalObjectNames) {
- parts.add(js.statement(
- '#globalObject = convertToFastObject(#globalObject);',
- {"globalObject": globalObject}));
- }
-
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildDebugFastObjectCode() {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- if (DEBUG_FAST_OBJECTS) {
- parts.add(js.statement(r'''
- // The following only works on V8 when run with option
- // "--allow-natives-syntax". We use'new Function' because the
- // miniparser does not understand V8 native syntax.
- if (typeof print === "function") {
- var HasFastProperties =
- new Function("a", "return %HasFastProperties(a)");
- print("Size of global helper object: "
- + String(Object.getOwnPropertyNames(H).length)
- + ", fast properties " + HasFastProperties(H));
- print("Size of global platform object: "
- + String(Object.getOwnPropertyNames(P).length)
- + ", fast properties " + HasFastProperties(P));
- print("Size of global dart:html object: "
- + String(Object.getOwnPropertyNames(W).length)
- + ", fast properties " + HasFastProperties(W));
- print("Size of isolate properties object: "
- + String(Object.getOwnPropertyNames($).length)
- + ", fast properties " + HasFastProperties($));
- print("Size of constant object: "
- + String(Object.getOwnPropertyNames(C).length)
- + ", fast properties " + HasFastProperties(C));
- var names = Object.getOwnPropertyNames($);
- for (var i = 0; i < names.length; i++) {
- print("$." + names[i]);
- }
- }
- '''));
-
- for (String object in Namer.userGlobalObjects) {
- parts.add(js.statement('''
- if (typeof print === "function") {
- print("Size of " + #objectString + ": "
- + String(Object.getOwnPropertyNames(#object).length)
- + ", fast properties " + HasFastProperties(#object));
- }
- ''', {"object": object, "objectString": js.string(object)}));
- }
- }
-
- return new jsAst.Block(parts);
- }
-
- void checkEverythingEmitted(
- Map<ClassEntity, ClassBuilder> pendingClassBuilders) {
- if (pendingClassBuilders == null) return;
- List<ClassEntity> pendingClasses =
- _sorter.sortClasses(pendingClassBuilders.keys);
-
- pendingClasses.forEach((ClassEntity element) => reporter.reportInfo(
- element, MessageKind.GENERIC, {'text': 'Pending statics.'}));
-
- if (pendingClasses != null && !pendingClasses.isEmpty) {
- reporter.internalError(
- pendingClasses.first, 'Pending statics (see above).');
- }
- }
-
- void assembleLibrary(Library library, Fragment fragment) {
- LibraryEntity libraryElement = library.element;
-
- assembleStaticFunctions(library.statics, fragment);
-
- ClassBuilder libraryBuilder =
- getLibraryDescriptor(libraryElement, fragment);
- for (Class cls in library.classes) {
- assembleClass(cls, libraryBuilder, fragment);
- }
-
- classEmitter.emitFields(library, libraryBuilder, emitStatics: true);
- }
-
- void assembleProgram(Program program) {
- for (Fragment fragment in program.fragments) {
- for (Library library in fragment.libraries) {
- assembleLibrary(library, fragment);
- }
- }
- }
-
- jsAst.Statement buildDeferredHeader() {
- /// For deferred loading we communicate the initializers via this global
- /// variable. The deferred hunks will add their initialization to this.
- /// The semicolon is important in minified mode, without it the
- /// following parenthesis looks like a call to the object literal.
- return js.statement(
- 'self.#deferredInitializers = '
- 'self.#deferredInitializers || Object.create(null);',
- {'deferredInitializers': deferredInitializers});
- }
-
- jsAst.Program buildOutputAstForMain(Program program,
- Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
- MainFragment mainFragment = program.mainFragment;
- OutputUnit mainOutputUnit = mainFragment.outputUnit;
- bool isProgramSplit = program.isSplit;
-
- List<jsAst.Statement> statements = <jsAst.Statement>[];
-
- statements..add(buildGeneratedBy())..add(js.comment(HOOKS_API_USAGE));
-
- if (isProgramSplit) {
- statements.add(buildDeferredHeader());
- }
-
- // Collect the AST for the descriptors.
- Map<LibraryEntity, ClassBuilder> descriptors =
- libraryDescriptors[mainFragment] ?? const {};
-
- checkEverythingEmitted(classDescriptors[mainFragment]);
-
- Iterable<LibraryEntity> libraries = outputLibraryLists[mainOutputUnit];
- if (libraries == null) libraries = <LibraryEntity>[];
-
- List<jsAst.Expression> parts = <jsAst.Expression>[];
- for (LibraryEntity library in _sorter.sortLibraries(libraries)) {
- parts.add(generateLibraryDescriptor(library, mainFragment));
- descriptors.remove(library);
- }
-
- if (descriptors.isNotEmpty) {
- List<LibraryEntity> remainingLibraries = descriptors.keys.toList();
-
- // The remaining descriptors are only accessible through reflection.
- // The program builder does not collect libraries that only
- // contain typedefs that are used for reflection.
- for (LibraryEntity element in remainingLibraries) {
- parts.add(generateLibraryDescriptor(element, mainFragment));
- descriptors.remove(element);
- }
- }
- jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts);
-
- // Using a named function here produces easier to read stack traces in
- // Chrome/V8.
- statements.add(js.statement("""
- (function() {
- // No renaming in the top-level function to save the locals for the
- // nested context where they will be used more. We have to put the
- // comment into a hole as the parser strips out comments right away.
- #disableVariableRenaming;
- #supportsDirectProtoAccess;
-
- if (#isProgramSplit) {
- /// We collect all the global state, so it can be passed to the
- /// initializer of deferred files.
- var #globalsHolder = Object.create(null)
- }
-
- // [map] returns an object that V8 shouldn't try to optimize with a
- // hidden class. This prevents a potential performance problem where V8
- // tries to build a hidden class for an object used as a hashMap.
- // It requires fewer characters to declare a variable as a parameter than
- // with `var`.
- function map(x) {
- x = Object.create(null);
- x.x = 0;
- delete x.x;
- return x;
- }
-
- #globalObjectSetup;
-
- function #isolateName() {}
-
- if (#isProgramSplit) {
- #globalsHolder.#isolateName = #isolateName;
- #globalsHolder.#initName = #initName;
- #globalsHolder.#setupProgramName = #setupProgramName;
- }
-
- init();
-
- #cspPrecompiledFunctions;
-
- #setupProgram;
-
- #functionThatReturnsNull;
-
- // The argument to reflectionDataParser is assigned to a temporary 'dart'
- // so that 'dart.' will appear as the prefix to dart methods in stack
- // traces and profile entries.
- var dart = #descriptors;
-
- #setupProgramName(dart, 0, 0);
-
- #getInterceptorMethods;
- #oneShotInterceptors;
-
- #makeConstantList;
-
- // We abuse the short name used for the isolate here to store
- // the isolate properties. This is safe as long as the real isolate
- // object does not exist yet.
- var ${namer.staticStateHolder} = #isolatePropertiesName;
-
- // Constants in checked mode call into RTI code to set type information
- // which may need getInterceptor (and one-shot interceptor) methods, so
- // we have to make sure that [emitGetInterceptorMethods] and
- // [emitOneShotInterceptors] have been called.
- #compileTimeConstants;
-
- // Static field initializations require the classes and compile-time
- // constants to be set up.
- #staticNonFinalInitializers;
-
- ${namer.staticStateHolder} = null;
-
- #deferredBoilerPlate;
-
- #typeToInterceptorMap;
-
- #lazyStaticFields;
-
- #isolateName = $finishIsolateConstructorName(#isolateName);
-
- ${namer.staticStateHolder} = new #isolateName();
-
- #metadata;
-
- #convertToFastObject;
- #convertToSlowObject;
-
- #convertGlobalObjectsToFastObjects;
- #debugFastObjects;
-
- #init;
-
- #main;
- })();
- """, {
- "disableVariableRenaming": js.comment("/* ::norenaming:: */"),
- "isProgramSplit": isProgramSplit,
- "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(),
- "globalsHolder": globalsHolder,
- "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit),
- "isolateName": namer.isolateName,
- "isolatePropertiesName": js(isolatePropertiesName),
- "initName": initName,
- "functionThatReturnsNull": buildFunctionThatReturnsNull(),
- "setupProgram": buildSetupProgram(
- program, compiler, backend, namer, this, _closedWorld),
- "setupProgramName": setupProgramName,
- "descriptors": descriptorsAst,
- "cspPrecompiledFunctions": buildCspPrecompiledFunctionFor(mainOutputUnit),
- "getInterceptorMethods": interceptorEmitter.buildGetInterceptorMethods(),
- "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(),
- "makeConstantList":
- buildMakeConstantList(program.outputContainsConstantList),
- "compileTimeConstants": buildCompileTimeConstants(mainFragment.constants,
- isMainFragment: true),
- "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes),
- "staticNonFinalInitializers":
- buildStaticNonFinalFieldInitializations(mainOutputUnit),
- "typeToInterceptorMap":
- interceptorEmitter.buildTypeToInterceptorMap(program),
- "lazyStaticFields": buildLazilyInitializedStaticFields(
- mainFragment.staticLazilyInitializedFields),
- "metadata": buildMetadata(program, mainOutputUnit),
- "convertToFastObject": buildConvertToFastObjectFunction(),
- "convertToSlowObject": buildConvertToSlowObjectFunction(),
- "convertGlobalObjectsToFastObjects":
- buildConvertGlobalObjectToFastObjects(),
- "debugFastObjects": buildDebugFastObjectCode(),
- "init": buildInitFunction(program.outputContainsConstantList),
- "main": buildMain(mainFragment.invokeMain)
- }));
-
- return new jsAst.Program(statements);
- }
-
- void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) {
- LocationCollector locationCollector;
- List<CodeOutputListener> codeOutputListeners;
- if (generateSourceMap) {
- locationCollector = new LocationCollector();
- codeOutputListeners = <CodeOutputListener>[locationCollector];
- }
-
- CodeOutput mainOutput = new StreamCodeOutput(
- compiler.outputProvider.createOutputSink('', 'js', OutputType.js),
- codeOutputListeners);
- outputBuffers[mainOutputUnit] = mainOutput;
-
- mainOutput.addBuffer(jsAst.createCodeBuffer(
- program, compiler.options, backend.sourceInformationStrategy,
- monitor: compiler.dumpInfoTask));
-
- if (compiler.options.deferredMapUri != null) {
- outputDeferredMap();
- }
-
- if (generateSourceMap) {
- mainOutput.add(SourceMapBuilder.generateSourceMapTag(
- compiler.options.sourceMapUri, compiler.options.outputUri));
- }
-
- mainOutput.close();
-
- if (generateSourceMap) {
- SourceMapBuilder.outputSourceMap(
- mainOutput,
- locationCollector,
- namer.createMinifiedGlobalNameMap(),
- namer.createMinifiedInstanceNameMap(),
- '',
- compiler.options.sourceMapUri,
- compiler.options.outputUri,
- compiler.outputProvider);
- }
- }
-
- Map<OutputUnit, jsAst.Expression> buildDescriptorsForOutputUnits(
- Program program) {
- Map<OutputUnit, jsAst.Expression> outputs =
- new Map<OutputUnit, jsAst.Expression>();
-
- for (Fragment fragment in program.deferredFragments) {
- OutputUnit outputUnit = fragment.outputUnit;
-
- Map<LibraryEntity, ClassBuilder> descriptors =
- libraryDescriptors[fragment];
-
- if (descriptors != null && descriptors.isNotEmpty) {
- Iterable<LibraryEntity> libraries = outputLibraryLists[outputUnit];
- if (libraries == null) libraries = <LibraryEntity>[];
-
- // TODO(johnniwinther): Avoid creating [CodeBuffer]s.
- List<jsAst.Expression> parts = <jsAst.Expression>[];
- for (LibraryEntity library in _sorter.sortLibraries(libraries)) {
- parts.add(generateLibraryDescriptor(library, fragment));
- descriptors.remove(library);
- }
-
- outputs[outputUnit] = new jsAst.ArrayInitializer(parts);
- }
- }
-
- return outputs;
- }
-
- void finalizeTokensInAst(
- jsAst.Program main, Iterable<jsAst.Program> deferredParts) {
- jsAst.TokenCounter counter = new jsAst.TokenCounter();
- counter.countTokens(main);
- deferredParts.forEach(counter.countTokens);
- task.metadataCollector.finalizeTokens();
- if (backend.namer is jsAst.TokenFinalizer) {
- dynamic finalizer = backend.namer;
- finalizer.finalizeTokens();
- }
- }
-
- int emitProgram(ProgramBuilder programBuilder) {
- Program program =
- programBuilder.buildProgram(storeFunctionTypesInMetadata: true);
- if (retainDataForTesting) {
- programForTesting = program;
- }
-
- outputStaticNonFinalFieldLists =
- programBuilder.collector.outputStaticNonFinalFieldLists;
- outputLibraryLists = programBuilder.collector.outputLibraryLists;
-
- assembleProgram(program);
-
- // Construct the ASTs for all deferred output units.
- Map<OutputUnit, jsAst.Program> deferredParts =
- buildOutputAstForDeferredCode(program);
-
- Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens =
- new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables(
- deferredParts.keys, deferredParts.keys.map((OutputUnit unit) {
- return new _DeferredOutputUnitHash(unit);
- }));
-
- jsAst.Program mainOutput =
- buildOutputAstForMain(program, deferredHashTokens);
-
- finalizeTokensInAst(mainOutput, deferredParts.values);
-
- // Emit deferred units first, so we have their hashes.
- // Map from OutputUnit to a hash of its content. The hash uniquely
- // identifies the code of the output-unit. It does not include
- // boilerplate JS code, like the sourcemap directives or the hash
- // itself.
- Map<OutputUnit, String> deferredLoadHashes =
- emitDeferredOutputUnits(deferredParts);
-
- deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) {
- token.setHash(deferredLoadHashes[key]);
- });
- emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput);
-
- if (_closedWorld.backendUsage.requiresPreamble &&
- !backend.htmlLibraryIsLoaded) {
- reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
- }
- // Return the total program size.
- return outputBuffers.values.fold(0, (a, b) => a + b.length);
- }
-
- ClassBuilder getStaticMethodDescriptor(
- FunctionEntity element, Fragment fragment) {
- if (!_nativeData.isNativeMember(element)) {
- // For static (not top level) elements, record their code in a buffer
- // specific to the class. For now, not supported for native classes and
- // native elements.
- ClassEntity cls = element.enclosingClass;
- if (compiler.codegenWorldBuilder.directlyInstantiatedClasses
- .contains(cls) &&
- !_nativeData.isNativeClass(cls) &&
- _outputUnitData.outputUnitForMember(element) ==
- _outputUnitData.outputUnitForClass(cls)) {
- return classDescriptors
- .putIfAbsent(fragment, () => new Map<ClassEntity, ClassBuilder>())
- .putIfAbsent(cls, () {
- return new ClassBuilder.forClass(cls, namer);
- });
- }
- }
- return _getLibraryDescriptor(element, element.library, fragment);
- }
-
- ClassBuilder getLibraryDescriptor(LibraryEntity element, Fragment fragment) {
- return _getLibraryDescriptor(element, element, fragment);
- }
-
- ClassBuilder _getLibraryDescriptor(
- Entity element, LibraryEntity owner, Fragment fragment) {
- if (owner == null) {
- reporter.internalError(element, 'Owner is null.');
- }
- return libraryDescriptors
- .putIfAbsent(fragment, () => new Map<LibraryEntity, ClassBuilder>())
- .putIfAbsent(owner, () {
- return new ClassBuilder.forLibrary(owner, namer);
- });
- }
-
- /// Emits support-code for deferred loading into [output].
- jsAst.Statement buildDeferredBoilerPlate(
- Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- parts.add(js.statement('''
- {
- // Function for checking if a hunk is loaded given its hash.
- #isHunkLoaded = function(hunkHash) {
- return !!$deferredInitializers[hunkHash];
- };
- #deferredInitialized = new Object(null);
- // Function for checking if a hunk is initialized given its hash.
- #isHunkInitialized = function(hunkHash) {
- return #deferredInitialized[hunkHash];
- };
- // Function for initializing a loaded hunk, given its hash.
- #initializeLoadedHunk = function(hunkHash) {
- var hunk = $deferredInitializers[hunkHash];
- if (hunk == null) {
- throw "DeferredLoading state error: code with hash '" +
- hunkHash + "' was not loaded";
- }
- hunk(#globalsHolder, ${namer.staticStateHolder});
- #deferredInitialized[hunkHash] = true;
- };
- }
- ''', {
- "globalsHolder": globalsHolder,
- "isHunkLoaded":
- generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED),
- "isHunkInitialized":
- generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_INITIALIZED),
- "initializeLoadedHunk":
- generateEmbeddedGlobalAccess(embeddedNames.INITIALIZE_LOADED_HUNK),
- "deferredInitialized":
- generateEmbeddedGlobalAccess(embeddedNames.DEFERRED_INITIALIZED)
- }));
-
- void store(
- jsAst.Expression map, jsAst.Expression uris, jsAst.Expression hashes) {
- void assign(String name, jsAst.Expression value) {
- parts.add(
- js.statement('# = #', [generateEmbeddedGlobalAccess(name), value]));
- }
-
- assign(embeddedNames.DEFERRED_LIBRARY_PARTS, map);
- assign(embeddedNames.DEFERRED_PART_URIS, uris);
- assign(embeddedNames.DEFERRED_PART_HASHES, hashes);
- }
-
- createDeferredLoadingData(
- _closedWorld.outputUnitData.hunksToLoad, deferredLoadHashes, store);
-
- return new jsAst.Block(parts);
- }
-
- // Create data used for loading and initializing the hunks for a deferred
- // import. There are three parts: a map from loadId to list of parts, where
- // parts are represented as an index; an array of uris indexed by part; and an
- // array of hashes indexed by part.
- void createDeferredLoadingData(
- Map<String, List<OutputUnit>> loadMap,
- Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes,
- void finish(jsAst.Expression map, jsAst.Expression uris,
- jsAst.Expression hashes)) {
- Map<OutputUnit, int> fragmentIndexes = <OutputUnit, int>{};
- var uris = <jsAst.Expression>[];
- var hashes = <jsAst.Expression>[];
-
- List<jsAst.Property> libraryPartsMapEntries = <jsAst.Property>[];
-
- loadMap.forEach((String loadId, List<OutputUnit> fragmentList) {
- List<jsAst.Expression> indexes = <jsAst.Expression>[];
- for (OutputUnit fragment in fragmentList) {
- int index = fragmentIndexes[fragment];
- if (index == null) {
- index = fragmentIndexes[fragment] = fragmentIndexes.length;
- uris.add(js.escapedString(
- deferredPartFileName(compiler.options, fragment.name)));
- _DeferredOutputUnitHash hash = deferredLoadHashes[fragment];
- assert(hash != null, "No hash for $fragment in $deferredLoadHashes.");
- hashes.add(hash);
- }
- indexes.add(js.number(index));
- }
- libraryPartsMapEntries.add(new jsAst.Property(
- js.string(loadId), new jsAst.ArrayInitializer(indexes)));
- });
-
- finish(new jsAst.ObjectInitializer(libraryPartsMapEntries),
- new jsAst.ArrayInitializer(uris), new jsAst.ArrayInitializer(hashes));
- }
-
- Map<OutputUnit, jsAst.Program> buildOutputAstForDeferredCode(
- Program program) {
- if (!program.isSplit) return const <OutputUnit, jsAst.Program>{};
-
- Map<OutputUnit, jsAst.Program> result =
- new Map<OutputUnit, jsAst.Program>();
-
- Map<OutputUnit, jsAst.Expression> deferredAsts =
- buildDescriptorsForOutputUnits(program);
-
- for (Fragment fragment in program.deferredFragments) {
- OutputUnit outputUnit = fragment.outputUnit;
- jsAst.Expression libraryDescriptor = deferredAsts[outputUnit];
- List<jsAst.Statement> body = <jsAst.Statement>[];
-
- // No renaming in the top-level function to save the locals for the
- // nested context where they will be used more.
- body.add(js.comment("/* ::norenaming:: "));
-
- for (String globalObject in Namer.reservedGlobalObjectNames) {
- body.add(js.statement('var #object = #globalsHolder.#object;',
- {'globalsHolder': globalsHolder, 'object': globalObject}));
- }
- body
- ..add(js.statement('var init = #globalsHolder.init;',
- {'globalsHolder': globalsHolder}))
- ..add(js.statement(
- 'var $setupProgramName = '
- '#globalsHolder.$setupProgramName;',
- {'globalsHolder': globalsHolder}))
- ..add(js.statement(
- 'var ${namer.isolateName} = '
- '#globalsHolder.${namer.isolateName};',
- {'globalsHolder': globalsHolder}));
- String metadataAccess =
- generateEmbeddedGlobalAccessString(embeddedNames.METADATA);
- String typesAccess =
- generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
- if (libraryDescriptor != null) {
- // The argument to reflectionDataParser is assigned to a temporary
- // 'dart' so that 'dart.' will appear as the prefix to dart methods
- // in stack traces and profile entries.
- body.add(js.statement('var dart = #', libraryDescriptor));
-
- if (compiler.options.useContentSecurityPolicy) {
- body.add(buildCspPrecompiledFunctionFor(outputUnit));
- }
- body.add(js.statement('$setupProgramName('
- 'dart, ${metadataAccess}.length, ${typesAccess}.length);'));
- }
-
- body
- ..add(buildMetadata(program, outputUnit))
- ..add(js.statement('${metadataAccess}.push.apply(${metadataAccess}, '
- '${namer.deferredMetadataName});'))
- ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
- '${namer.deferredTypesName});'));
-
- body.add(
- buildCompileTimeConstants(fragment.constants, isMainFragment: false));
- body.add(buildStaticNonFinalFieldInitializations(outputUnit));
- body.add(buildLazilyInitializedStaticFields(
- fragment.staticLazilyInitializedFields,
- isMainFragment: false));
-
- List<jsAst.Statement> statements = <jsAst.Statement>[];
-
- statements
- ..add(buildGeneratedBy())
- ..add(buildDeferredHeader())
- ..add(js.statement(
- '${deferredInitializers}.current = '
- """function (#, ${namer.staticStateHolder}) {
- #
- }
- """,
- [globalsHolder, body]));
-
- result[outputUnit] = new jsAst.Program(statements);
- }
-
- return result;
- }
-
- /// Returns a map from OutputUnit to a hash of its content. The hash uniquely
- /// identifies the code of the output-unit. It does not include
- /// boilerplate JS code, like the sourcemap directives or the hash
- /// itself.
- Map<OutputUnit, String> emitDeferredOutputUnits(
- Map<OutputUnit, jsAst.Program> outputAsts) {
- Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>();
-
- for (OutputUnit outputUnit in outputAsts.keys) {
- List<CodeOutputListener> outputListeners = <CodeOutputListener>[];
- Hasher hasher = new Hasher();
- outputListeners.add(hasher);
-
- LocationCollector locationCollector;
- if (generateSourceMap) {
- locationCollector = new LocationCollector();
- outputListeners.add(locationCollector);
- }
-
- String partPrefix = deferredPartFileName(
- compiler.options, outputUnit.name,
- addExtension: false);
- CodeOutput output = new StreamCodeOutput(
- compiler.outputProvider
- .createOutputSink(partPrefix, 'part.js', OutputType.jsPart),
- outputListeners);
-
- outputBuffers[outputUnit] = output;
-
- output.addBuffer(jsAst.createCodeBuffer(outputAsts[outputUnit],
- compiler.options, backend.sourceInformationStrategy,
- monitor: compiler.dumpInfoTask));
-
- // Make a unique hash of the code (before the sourcemaps are added)
- // This will be used to retrieve the initializing function from the global
- // variable.
- String hash = hasher.getHash();
-
- output.add('$N${deferredInitializers}["$hash"]$_=$_'
- '${deferredInitializers}.current$N');
-
- if (generateSourceMap) {
- Uri mapUri, partUri;
- Uri sourceMapUri = compiler.options.sourceMapUri;
- Uri outputUri = compiler.options.outputUri;
-
- String partName = "$partPrefix.part";
-
- if (sourceMapUri != null) {
- String mapFileName = partName + ".js.map";
- List<String> mapSegments = sourceMapUri.pathSegments.toList();
- mapSegments[mapSegments.length - 1] = mapFileName;
- mapUri =
- compiler.options.sourceMapUri.replace(pathSegments: mapSegments);
- }
-
- if (outputUri != null) {
- String partFileName = partName + ".js";
- List<String> partSegments = outputUri.pathSegments.toList();
- partSegments[partSegments.length - 1] = partFileName;
- partUri =
- compiler.options.outputUri.replace(pathSegments: partSegments);
- }
-
- output.add(SourceMapBuilder.generateSourceMapTag(mapUri, partUri));
- output.close();
- SourceMapBuilder.outputSourceMap(output, locationCollector, {}, {},
- partName, mapUri, partUri, compiler.outputProvider);
- } else {
- output.close();
- }
-
- hunkHashes[outputUnit] = hash;
- }
- return hunkHashes;
- }
-
- jsAst.Comment buildGeneratedBy() {
- StringBuffer flavor = new StringBuffer();
- flavor.write('full emitter');
- // TODO(johnniwinther): Remove this flavor.
- flavor.write(', strong');
- if (compiler.options.trustPrimitives) flavor.write(', trust primitives');
- if (compiler.options.omitImplicitChecks) flavor.write(', omit checks');
- if (compiler.options.laxRuntimeTypeToString) {
- flavor.write(', lax runtime type');
- }
- if (compiler.options.useContentSecurityPolicy) flavor.write(', CSP');
- if (_closedWorld.backendUsage.isMirrorsUsed) flavor.write(', mirrors');
- return new jsAst.Comment(generatedBy(compiler, flavor: '$flavor'));
- }
-
- void outputDeferredMap() {
- Map<String, dynamic> mapping = new Map<String, dynamic>();
- // Json does not support comments, so we embed the explanation in the
- // data.
- mapping["_comment"] = "This mapping shows which compiled `.js` files are "
- "needed for a given deferred library import.";
- mapping.addAll(_closedWorld.outputUnitData
- .computeDeferredMap(compiler.options, _elementEnvironment));
- compiler.outputProvider.createOutputSink(
- compiler.options.deferredMapUri.path, '', OutputType.deferredMap)
- ..add(const JsonEncoder.withIndent(" ").convert(mapping))
- ..close();
- }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
deleted file mode 100644
index e7afba7..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/interceptor_emitter.dart
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.full_emitter.interceptor_emitter;
-
-import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
-import '../../elements/entities.dart';
-import '../../js/js.dart' as jsAst;
-import '../../js/js.dart' show js;
-import '../../world.dart' show JClosedWorld;
-import '../js_emitter.dart' hide Emitter, EmitterFactory;
-import '../model.dart';
-import 'emitter.dart';
-
-class InterceptorEmitter extends CodeEmitterHelper {
- final JClosedWorld closedWorld;
- final Set<jsAst.Name> interceptorInvocationNames = new Set<jsAst.Name>();
-
- InterceptorEmitter(this.closedWorld);
-
- void recordMangledNameOfMemberMethod(MemberEntity member, jsAst.Name name) {
- if (closedWorld.interceptorData.isInterceptedMethod(member)) {
- interceptorInvocationNames.add(name);
- }
- }
-
- jsAst.Expression buildGetInterceptorMethod(
- jsAst.Name key, Set<ClassEntity> classes) {
- InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
- compiler.options,
- closedWorld.commonElements,
- backend.emitter,
- backend.nativeCodegenEnqueuer,
- namer,
- backend.oneShotInterceptorData,
- backend.customElementsCodegenAnalysis,
- compiler.codegenWorldBuilder,
- closedWorld);
- jsAst.Expression function =
- stubGenerator.generateGetInterceptorMethod(classes);
-
- return function;
- }
-
- /**
- * Emit all versions of the [:getInterceptor:] method.
- */
- jsAst.Statement buildGetInterceptorMethods() {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
-
- parts.add(js.comment('getInterceptor methods'));
-
- Iterable<jsAst.Name> names =
- backend.oneShotInterceptorData.specializedGetInterceptorNames;
- for (jsAst.Name name in names) {
- Set<ClassEntity> classes =
- backend.oneShotInterceptorData.getSpecializedGetInterceptorsFor(name);
- parts.add(js.statement('#.# = #', [
- namer.globalObjectForLibrary(
- closedWorld.commonElements.interceptorsLibrary),
- name,
- buildGetInterceptorMethod(name, classes)
- ]));
- }
-
- return new jsAst.Block(parts);
- }
-
- jsAst.Statement buildOneShotInterceptors() {
- List<jsAst.Statement> parts = <jsAst.Statement>[];
- Iterable<jsAst.Name> names =
- backend.oneShotInterceptorData.oneShotInterceptorNames;
-
- InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
- compiler.options,
- closedWorld.commonElements,
- backend.emitter,
- backend.nativeCodegenEnqueuer,
- namer,
- backend.oneShotInterceptorData,
- backend.customElementsCodegenAnalysis,
- compiler.codegenWorldBuilder,
- closedWorld);
- String globalObject = namer
- .globalObjectForLibrary(closedWorld.commonElements.interceptorsLibrary);
- for (jsAst.Name name in names) {
- jsAst.Expression function =
- stubGenerator.generateOneShotInterceptor(name);
- parts.add(js.statement('${globalObject}.# = #', [name, function]));
- }
-
- return new jsAst.Block(parts);
- }
-
- /**
- * Emit initializer for `typeToInterceptorMap` data structure used by
- * `findInterceptorForType`. See declaration of `typeToInterceptor` in
- * `interceptors.dart`.
- */
- jsAst.Statement buildTypeToInterceptorMap(Program program) {
- jsAst.Expression array = program.typeToInterceptorMap;
- if (array == null) return js.comment("Empty type-to-interceptor map.");
-
- jsAst.Expression typeToInterceptorMap = emitter
- .generateEmbeddedGlobalAccess(embeddedNames.TYPE_TO_INTERCEPTOR_MAP);
- return js.statement('# = #', [typeToInterceptorMap, array]);
- }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
deleted file mode 100644
index b136d73..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ /dev/null
@@ -1,398 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.js_emitter.full_emitter.nsm_emitter;
-
-import '../../elements/entities.dart';
-import '../../js/js.dart' as jsAst;
-import '../../js/js.dart' show js;
-import '../../js_backend/js_backend.dart' show GetterName, SetterName;
-import '../../universe/selector.dart' show Selector;
-import 'package:front_end/src/api_unstable/dart2js.dart'
- show $$, $A, $HASH, $Z, $a, $z;
-import '../../world.dart' show JClosedWorld;
-import '../js_emitter.dart' hide Emitter, EmitterFactory;
-import '../model.dart';
-import 'emitter.dart';
-
-class NsmEmitter extends CodeEmitterHelper {
- final JClosedWorld closedWorld;
- final List<Selector> trivialNsmHandlers = <Selector>[];
-
- NsmEmitter(this.closedWorld);
-
- /// If this is true then we can generate the noSuchMethod handlers at startup
- /// time, instead of them being emitted as part of the Object class.
- bool get generateTrivialNsmHandlers => true;
-
- // If we need fewer than this many noSuchMethod handlers we can save space by
- // just emitting them in JS, rather than emitting the JS needed to generate
- // them at run time.
- static const VERY_FEW_NO_SUCH_METHOD_HANDLERS = 10;
-
- static const MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING = 4;
-
- void emitNoSuchMethodHandlers(AddPropertyFunction addProperty) {
- ClassStubGenerator generator = new ClassStubGenerator(task.emitter,
- closedWorld.commonElements, namer, codegenWorldBuilder, closedWorld,
- enableMinification: compiler.options.enableMinification);
-
- // Keep track of the JavaScript names we've already added so we
- // do not introduce duplicates (bad for code size).
- Map<jsAst.Name, Selector> addedJsNames =
- generator.computeSelectorsForNsmHandlers();
-
- // Set flag used by generateMethod helper below. If we have very few
- // handlers we use addProperty for them all, rather than try to generate
- // them at runtime.
- bool haveVeryFewNoSuchMemberHandlers =
- (addedJsNames.length < VERY_FEW_NO_SUCH_METHOD_HANDLERS);
- List<jsAst.Name> names = addedJsNames.keys.toList()..sort();
- for (jsAst.Name jsName in names) {
- Selector selector = addedJsNames[jsName];
- List<jsAst.Expression> argNames = selector.callStructure
- .getOrderedNamedArguments()
- .map((String name) => js.string(name))
- .toList();
- int type = selector.invocationMirrorKind;
- if (!haveVeryFewNoSuchMemberHandlers &&
- isTrivialNsmHandler(type, argNames, selector, jsName)) {
- trivialNsmHandlers.add(selector);
- } else {
- StubMethod method =
- generator.generateStubForNoSuchMethod(jsName, selector);
- addProperty(method.name, method.code);
- }
- }
- }
-
- // Identify the noSuchMethod handlers that are so simple that we can
- // generate them programatically.
- bool isTrivialNsmHandler(
- int type, List argNames, Selector selector, jsAst.Name internalName) {
- if (!generateTrivialNsmHandlers) return false;
- // Check for named arguments.
- if (argNames.isNotEmpty) return false;
- if (selector.typeArgumentCount > 0) return false;
- // Check for unexpected name (this doesn't really happen).
- if (internalName is GetterName) return type == 1;
- if (internalName is SetterName) return type == 2;
- return type == 0;
- }
-
- /**
- * Adds (at runtime) the handlers to the Object class which catch calls to
- * methods that the object does not have. The handlers create an invocation
- * mirror object.
- *
- * The current version only gives you the minified name when minifying (when
- * not minifying this method is not called).
- *
- * In order to generate the noSuchMethod handlers we only need the minified
- * name of the method. We test the first character of the minified name to
- * determine if it is a getter or a setter, and we use the arguments array at
- * runtime to get the number of arguments and their values. If the method
- * involves named arguments etc. then we don't handle it here, but emit the
- * handler method directly on the Object class.
- *
- * The minified names are mostly 1-4 character names, which we emit in sorted
- * order (primary key is length, secondary ordering is lexicographic). This
- * gives an order like ... dD dI dX da ...
- *
- * Gzip is good with repeated text, but it can't diff-encode, so we do that
- * for it. We encode the minified names in a comma-separated string, but all
- * the 1-4 character names are encoded before the first comma as a series of
- * base 26 numbers. The last digit of each number is lower case, the others
- * are upper case, so 1 is "b" and 26 is "Ba".
- *
- * We think of the minified names as base 88 numbers using the ASCII
- * characters from # to z. The base 26 numbers each encode the delta from
- * the previous minified name to the next. So if there is a minified name
- * called Df and the next is Dh, then they are 2971 and 2973 when thought of
- * as base 88 numbers. The difference is 2, which is "c" in lower-case-
- * terminated base 26.
- *
- * The reason we don't encode long minified names with this method is that
- * decoding the base 88 numbers would overflow JavaScript's puny integers.
- *
- * There are some selectors that have a special calling convention (because
- * they are called with the receiver as the first argument). They need a
- * slightly different noSuchMethod handler, so we handle these first.
- */
- List<jsAst.Statement> buildTrivialNsmHandlers() {
- List<jsAst.Statement> statements = <jsAst.Statement>[];
- if (trivialNsmHandlers.length == 0) return statements;
-
- bool minify = compiler.options.enableMinification;
- bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;
-
- // Find out how many selectors there are with the special calling
- // convention.
- Iterable<Selector> interceptedSelectors = trivialNsmHandlers.where(
- (Selector s) => closedWorld.interceptorData.isInterceptedName(s.name));
- Iterable<Selector> ordinarySelectors = trivialNsmHandlers.where(
- (Selector s) => !closedWorld.interceptorData.isInterceptedName(s.name));
-
- // Get the short names (JS names, perhaps minified).
- Iterable<jsAst.Name> interceptedShorts =
- interceptedSelectors.map(namer.invocationMirrorInternalName);
- Iterable<jsAst.Name> ordinaryShorts =
- ordinarySelectors.map(namer.invocationMirrorInternalName);
-
- jsAst.Expression sortedShorts;
- Iterable<String> sortedLongs;
- if (useDiffEncoding) {
- assert(minify);
- sortedShorts =
- new _DiffEncodedListOfNames([interceptedShorts, ordinaryShorts]);
- } else {
- Iterable<Selector> sorted =
- [interceptedSelectors, ordinarySelectors].expand((e) => (e));
- sortedShorts = js.concatenateStrings(
- js.joinLiterals(sorted.map(namer.invocationMirrorInternalName),
- js.stringPart(",")),
- addQuotes: true);
-
- if (!minify) {
- sortedLongs =
- sorted.map((selector) => selector.invocationMirrorMemberName);
- }
- }
- // Startup code that loops over the method names and puts handlers on the
- // Object class to catch noSuchMethod invocations.
- ClassEntity objectClass = closedWorld.commonElements.objectClass;
- jsAst.Expression createInvocationMirror = backend.emitter
- .staticFunctionAccess(
- closedWorld.commonElements.createInvocationMirror);
- if (useDiffEncoding) {
- statements.add(js.statement('''{
- var objectClassObject = processedClasses.collected[#objectClass],
- nameSequences = #diffEncoding.split("."),
- shortNames = [];
- if (objectClassObject instanceof Array)
- objectClassObject = objectClassObject[1];
- for (var j = 0; j < nameSequences.length; ++j) {
- var sequence = nameSequences[j].split(","),
- nameNumber = 0;
- // If we are loading a deferred library the object class will not be
- // in the collectedClasses so objectClassObject is undefined, and we
- // skip setting up the names.
- if (!objectClassObject) break;
- // Likewise, if the current sequence is empty, we don't process it.
- if (sequence.length == 0) continue;
- var diffEncodedString = sequence[0];
- for (var i = 0; i < diffEncodedString.length; i++) {
- var codes = [],
- diff = 0,
- digit = diffEncodedString.charCodeAt(i);
- for (; digit <= ${$Z};) {
- diff *= 26;
- diff += (digit - ${$A});
- digit = diffEncodedString.charCodeAt(++i);
- }
- diff *= 26;
- diff += (digit - ${$a});
- nameNumber += diff;
- for (var remaining = nameNumber;
- remaining > 0;
- remaining = (remaining / 88) | 0) {
- codes.unshift(${$HASH} + remaining % 88);
- }
- shortNames.push(
- String.fromCharCode.apply(String, codes));
- }
- if (sequence.length > 1) {
- Array.prototype.push.apply(shortNames, sequence.shift());
- }
- }
- }''', {
- 'objectClass': js.quoteName(namer.className(objectClass)),
- 'diffEncoding': sortedShorts
- }));
- } else {
- // No useDiffEncoding version.
- statements.add(js.statement(
- 'var objectClassObject = processedClasses.collected[#objectClass],'
- ' shortNames = #diffEncoding.split(",")',
- {
- 'objectClass': js.quoteName(namer.className(objectClass)),
- 'diffEncoding': sortedShorts
- }));
- if (!minify) {
- statements.add(js.statement('var longNames = #longs.split(",")',
- {'longs': js.string(sortedLongs.join(','))}));
- }
- statements.add(js.statement('if (objectClassObject instanceof Array)'
- ' objectClassObject = objectClassObject[1];'));
- }
-
- dynamic isIntercepted = // jsAst.Expression or bool.
- interceptedSelectors.isEmpty
- ? false
- : ordinarySelectors.isEmpty
- ? true
- : js('j < #', js.number(interceptedSelectors.length));
-
- statements.add(js.statement('''
- // If we are loading a deferred library the object class will not be in
- // the collectedClasses so objectClassObject is undefined, and we skip
- // setting up the names.
- if (objectClassObject) {
- for (var j = 0; j < shortNames.length; j++) {
- var type = 0;
- var shortName = shortNames[j];
- if (shortName.indexOf("${namer.getterPrefix}") == 0) type = 1;
- if (shortName.indexOf("${namer.setterPrefix}") == 0) type = 2;
- // Generate call to:
- //
- // createInvocationMirror(String name, internalName, type,
- // arguments, argumentNames, typeArgumentCount)
- //
-
- // This 'if' is either a static choice or dynamic choice depending on
- // [isIntercepted].
- if (#isIntercepted) {
- objectClassObject[shortName] =
- (function(name, shortName, type) {
- return function(receiver) {
- return this.#noSuchMethodName(
- receiver,
- #createInvocationMirror(name, shortName, type,
- // Create proper Array with all arguments except first
- // (receiver).
- Array.prototype.slice.call(arguments, 1),
- [],
- 0));
- }
- })(#names[j], shortName, type);
- } else {
- objectClassObject[shortName] =
- (function(name, shortName, type) {
- return function() {
- return this.#noSuchMethodName(
- // Object.noSuchMethodName ignores the explicit receiver
- // argument. We could pass anything in place of [this].
- this,
- #createInvocationMirror(name, shortName, type,
- // Create proper Array with all arguments.
- Array.prototype.slice.call(arguments, 0),
- [],
- 0));
- }
- })(#names[j], shortName, type);
- }
- }
- }''', {
- 'noSuchMethodName': namer.noSuchMethodName,
- 'createInvocationMirror': createInvocationMirror,
- 'names': minify ? 'shortNames' : 'longNames',
- 'isIntercepted': isIntercepted
- }));
-
- return statements;
- }
-}
-
-/// When pretty printed, this node computes a diff-encoded string for the list
-/// of given names.
-///
-/// See [buildTrivialNsmHandlers].
-class _DiffEncodedListOfNames extends jsAst.DeferredString
- implements jsAst.AstContainer {
- String _cachedValue;
- List<jsAst.ArrayInitializer> ast;
-
- Iterable<jsAst.Node> get containedNodes => ast;
-
- _DiffEncodedListOfNames(Iterable<Iterable<jsAst.Name>> names) {
- // Store the names in ArrayInitializer nodes to make them discoverable
- // by traversals of the ast.
- ast = names
- .map((Iterable i) => new jsAst.ArrayInitializer(i.toList()))
- .toList();
- }
-
- void _computeDiffEncodingForList(
- Iterable<jsAst.Name> names, StringBuffer diffEncoding) {
- // Treat string as a number in base 88 with digits in ASCII order from # to
- // z. The short name sorting is based on length, and uses ASCII order for
- // equal length strings so this means that names are ascending. The hash
- // character, #, is never given as input, but we need it because it's the
- // implicit leading zero (otherwise we could not code names with leading
- // dollar signs).
- int fromBase88(String x) {
- int answer = 0;
- for (int i = 0; i < x.length; i++) {
- int c = x.codeUnitAt(i);
- // No support for Unicode minified identifiers in JS.
- assert(c >= $$ && c <= $z);
- answer *= 88;
- answer += c - $HASH;
- }
- return answer;
- }
-
- // Big endian encoding, A = 0, B = 1...
- // A lower case letter terminates the number.
- String toBase26(int x) {
- int c = x;
- var encodingChars = <int>[];
- encodingChars.add($a + (c % 26));
- while (true) {
- c ~/= 26;
- if (c == 0) break;
- encodingChars.add($A + (c % 26));
- }
- return new String.fromCharCodes(encodingChars.reversed.toList());
- }
-
- // Sort by length, then lexicographic.
- int compare(String a, String b) {
- if (a.length != b.length) return a.length - b.length;
- return a.compareTo(b);
- }
-
- List<String> shorts = names.map((jsAst.Name name) => name.name).toList()
- ..sort(compare);
-
- int previous = 0;
- for (String short in shorts) {
- if (short.length <= NsmEmitter.MAX_MINIFIED_LENGTH_FOR_DIFF_ENCODING) {
- int base63 = fromBase88(short);
- int diff = base63 - previous;
- previous = base63;
- String base26Diff = toBase26(diff);
- diffEncoding.write(base26Diff);
- } else {
- if (diffEncoding.length != 0) {
- diffEncoding.write(',');
- }
- diffEncoding.write(short);
- }
- }
- }
-
- String _computeDiffEncoding() {
- StringBuffer buffer = new StringBuffer();
- for (jsAst.ArrayInitializer list in ast) {
- if (buffer.isNotEmpty) {
- // Emit period that resets the diff base to zero when we switch to
- // normal calling convention (this avoids the need to code negative
- // diffs).
- buffer.write(".");
- }
- List<jsAst.Name> names = list.elements;
- _computeDiffEncodingForList(names, buffer);
- }
- return '"${buffer.toString()}"';
- }
-
- String get value {
- if (_cachedValue == null) {
- _cachedValue = _computeDiffEncoding();
- }
-
- return _cachedValue;
- }
-}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
deleted file mode 100644
index 0c1fda6..0000000
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ /dev/null
@@ -1,818 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart2js.js_emitter.full_emitter;
-
-// TODO(ahe): Share these with js_helper.dart.
-const FUNCTION_INDEX = 0;
-const NAME_INDEX = 1;
-const CALL_NAME_INDEX = 2;
-const REQUIRED_PARAMETER_INDEX = 3;
-const OPTIONAL_PARAMETER_INDEX = 4;
-const DEFAULT_ARGUMENTS_INDEX = 5;
-
-const bool VALIDATE_DATA = false;
-
-const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1;
-const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1;
-const RANGE1_ADJUST = -(FIRST_FIELD_CODE - RANGE1_FIRST);
-const RANGE2_ADJUST = -(FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST);
-const RANGE3_ADJUST =
- -(FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST);
-
-const String setupProgramName = 'setupProgram';
-// TODO(floitsch): make sure this property can't clash with anything. It's
-// unlikely since it lives on types, but still.
-const String typeNameProperty = r'builtin$cls';
-
-jsAst.Statement buildSetupProgram(
- Program program,
- Compiler compiler,
- JavaScriptBackend backend,
- Namer namer,
- Emitter emitter,
- JClosedWorld closedWorld) {
- jsAst.Expression typeInformationAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION);
- jsAst.Expression staticsAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.STATICS);
- jsAst.Expression mangledGlobalNamesAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
- jsAst.Expression mangledNamesAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
- jsAst.Expression librariesAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.LIBRARIES);
- jsAst.Expression typesAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPES);
- jsAst.Expression allClassesAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
- jsAst.Expression precompiledAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED);
- jsAst.Expression finishedClassesAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
- jsAst.Expression interceptorsByTagAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
- jsAst.Expression leafTagsAccess =
- emitter.generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
-
- String reflectableField = namer.reflectableField;
- String reflectionInfoField = namer.reflectionInfoField;
- String reflectionNameField = namer.reflectionNameField;
- String metadataIndexField = namer.metadataIndexField;
- String defaultValuesField = namer.defaultValuesField;
- String methodsWithOptionalArgumentsField =
- namer.methodsWithOptionalArgumentsField;
- String unmangledNameIndex =
- ' 2 * optionalParameterCount + requiredParameterCount + 3';
- String receiverParamName =
- compiler.options.enableMinification ? "r" : "receiver";
- String valueParamName = compiler.options.enableMinification ? "v" : "value";
- String space = compiler.options.enableMinification ? "" : " ";
- String _ = space;
-
- String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
- jsAst.Expression nativeInfoAccess = js('prototype[$specProperty]', []);
- jsAst.Expression constructorAccess = js('constructor', []);
- Function subclassReadGenerator =
- (jsAst.Expression subclass) => js('allClasses[#]', subclass);
- jsAst.Statement nativeInfoHandler = emitter.buildNativeInfoHandler(
- nativeInfoAccess,
- constructorAccess,
- subclassReadGenerator,
- interceptorsByTagAccess,
- leafTagsAccess);
-
- Map<String, dynamic> holes = {
- 'needsClassSupport': emitter.needsClassSupport,
- 'libraries': librariesAccess,
- 'mangledNames': mangledNamesAccess,
- 'mangledGlobalNames': mangledGlobalNamesAccess,
- 'statics': staticsAccess,
- 'staticsPropertyName': namer.staticsPropertyName,
- 'staticsPropertyNameString': js.quoteName(namer.staticsPropertyName),
- 'typeInformation': typeInformationAccess,
- 'notInCspMode': !compiler.options.useContentSecurityPolicy,
- 'inCspMode': compiler.options.useContentSecurityPolicy,
- 'deferredAction': namer.deferredAction,
- 'allClasses': allClassesAccess,
- 'debugFastObjects': DEBUG_FAST_OBJECTS,
- 'precompiled': precompiledAccess,
- 'finishedClassesAccess': finishedClassesAccess,
- 'needsMixinSupport': emitter.needsMixinSupport,
- 'needsNativeSupport': program.needsNativeSupport,
- 'enabledJsInterop': closedWorld.nativeData.isJsInteropUsed,
- 'jsInteropBoostrap': jsInteropAnalysis.buildJsInteropBootstrap(
- compiler.codegenWorldBuilder, closedWorld.nativeData, namer),
- 'isInterceptorClass':
- namer.operatorIs(closedWorld.commonElements.jsInterceptorClass),
- 'isObject': namer.operatorIs(closedWorld.commonElements.objectClass),
- 'specProperty': js.string(namer.nativeSpecProperty),
- 'trivialNsmHandlers': emitter.buildTrivialNsmHandlers(),
- 'types': typesAccess,
- 'objectClassName': js.quoteName(
- namer.runtimeTypeName(closedWorld.commonElements.objectClass)),
- 'needsStructuredMemberInfo': emitter.needsStructuredMemberInfo,
- 'usesMangledNames': closedWorld.backendUsage.isMirrorsUsed ||
- closedWorld.backendUsage.isFunctionApplyUsed,
- 'tearOffCode': buildTearOffCode(
- compiler.options, emitter, namer, closedWorld.commonElements),
- 'nativeInfoHandler': nativeInfoHandler,
- 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
- 'deferredActionString': js.string(namer.deferredAction),
- 'callCatchAll':
- js.quoteName(namer.getNameForJsGetName(null, JsGetName.CALL_CATCH_ALL)),
- };
- String skeleton = '''
-function $setupProgramName(programData, metadataOffset, typesOffset) {
- "use strict";
- if (#needsClassSupport) {
-
- function generateAccessor(fieldDescriptor, accessors, cls) {
- var fieldInformation = fieldDescriptor.split("-");
- var field = fieldInformation[0];
- var len = field.length;
- var code = field.charCodeAt(len - 1);
- var reflectable;
- if (fieldInformation.length > 1) reflectable = true;
- else reflectable = false;
- code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))
- ? code - $RANGE1_ADJUST
- : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))
- ? code - $RANGE2_ADJUST
- : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))
- ? code - $RANGE3_ADJUST
- : $NO_FIELD_CODE;
-
- if (code) { // needsAccessor
- var getterCode = code & 3;
- var setterCode = code >> 2;
- var accessorName = field = field.substring(0, len - 1);
-
- var divider = field.indexOf(":");
- if (divider > 0) { // Colon never in first position.
- accessorName = field.substring(0, divider);
- field = field.substring(divider + 1);
- }
-
- if (getterCode) { // needsGetter
- var args = (getterCode & 2) ? "$receiverParamName" : "";
- var receiver = (getterCode & 1) ? "this" : "$receiverParamName";
- var body = "return " + receiver + "." + field;
- var property =
- cls + ".prototype.${namer.getterPrefix}" + accessorName + "=";
- var fn = "function(" + args + "){" + body + "}";
- if (reflectable)
- accessors.push(property + "\$reflectable(" + fn + ");\\n");
- else
- accessors.push(property + fn + ";\\n");
- }
-
- if (setterCode) { // needsSetter
- var args = (setterCode & 2)
- ? "$receiverParamName,${_}$valueParamName"
- : "$valueParamName";
- var receiver = (setterCode & 1) ? "this" : "$receiverParamName";
- var body = receiver + "." + field + "$_=$_$valueParamName";
- var property =
- cls + ".prototype.${namer.setterPrefix}" + accessorName + "=";
- var fn = "function(" + args + "){" + body + "}";
- if (reflectable)
- accessors.push(property + "\$reflectable(" + fn + ");\\n");
- else
- accessors.push(property + fn + ";\\n");
- }
- }
-
- return field;
- }
-
- // First the class name, then the field names in an array and the members
- // (inside an Object literal).
- // The caller can also pass in the constructor as a function if needed.
- //
- // Example:
- // defineClass("A", ["x", "y"], {
- // foo\$1: function(y) {
- // print(this.x + y);
- // },
- // bar\$2: function(t, v) {
- // this.x = t - v;
- // },
- // });
- function defineClass(name, fields) {
- var accessors = [];
-
- var str = "function " + name + "(";
- var comma = "", body = "";
-
- for (var i = 0; i < fields.length; i++) {
- var fieldDescriptor = fields[i];
- if (fieldDescriptor.charCodeAt(0) == 48) {
- // null-initialized field.
- fieldDescriptor = fieldDescriptor.substring(1);
- var field = generateAccessor(fieldDescriptor, accessors, name);
- body += ("this." + field + " = null;\\n");
- } else {
- var field = generateAccessor(fieldDescriptor, accessors, name);
- var parameter = "p_" + field;
- str += comma;
- comma = ", ";
- str += parameter;
- body += ("this." + field + " = " + parameter + ";\\n");
- }
- }
- if (supportsDirectProtoAccess) {
- body += "this." + #deferredActionString + "();";
- }
- str += ") {\\n" + body + "}\\n";
- str += name + ".$typeNameProperty=\\"" + name + "\\";\\n";
- str += "\$desc=\$collectedClasses." + name + "[1];\\n";
- str += name + ".prototype = \$desc;\\n";
- if (typeof defineClass.name != "string") {
- str += name + ".name=\\"" + name + "\\";\\n";
- }
- str += accessors.join("");
-
- return str;
- }
-
- // If the browser supports changing the prototype via __proto__, we make
- // use of that feature. Otherwise, we copy the properties into a new
- // constructor.
- var inheritFrom = supportsDirectProtoAccess ?
- function(constructor, superConstructor) {
- var prototype = constructor.prototype;
- prototype.__proto__ = superConstructor.prototype;
- // Use a function for `true` here, as functions are stored in the
- // hidden class and not as properties in the object.
- prototype.constructor = constructor;
- prototype[#operatorIsPrefix + constructor.name] = constructor;
- return convertToFastObject(prototype);
- } :
- function() {
- function tmp() {}
- return function (constructor, superConstructor) {
- tmp.prototype = superConstructor.prototype;
- var object = new tmp();
- convertToSlowObject(object);
- var properties = constructor.prototype;
- var members = Object.keys(properties);
- for (var i = 0; i < members.length; i++) {
- var member = members[i];
- object[member] = properties[member];
- }
- // Use a function for `true` here, as functions are stored in the
- // hidden class and not as properties in the object.
- object[#operatorIsPrefix + constructor.name] = constructor;
- object.constructor = constructor;
- constructor.prototype = object;
- return object;
- };
- }();
-
- // Class descriptions are collected in a JS object.
- // 'finishClasses' takes all collected descriptions and sets up
- // the prototype.
- // Once set up, the constructors prototype field satisfy:
- // - it contains all (local) members.
- // - its internal prototype (__proto__) points to the superclass'
- // prototype field.
- // - the prototype's constructor field points to the JavaScript
- // constructor.
- // For engines where we have access to the '__proto__' we can manipulate
- // the object literal directly. For other engines we have to create a new
- // object and copy over the members.
- function finishClasses(processedClasses) {
- if (#debugFastObjects)
- print("Number of classes: " +
- Object.getOwnPropertyNames(processedClasses.collected).length);
-
- var allClasses = #allClasses;
-
- if (#inCspMode) {
- var constructors = #precompiled(processedClasses.collected);
- }
-
- if (#notInCspMode) {
- processedClasses.combinedConstructorFunction +=
- "return [\\n" + processedClasses.constructorsList.join(",\\n ") +
- "\\n]";
- var constructors =
- new Function("\$collectedClasses",
- processedClasses.combinedConstructorFunction)
- (processedClasses.collected);
- processedClasses.combinedConstructorFunction = null;
- }
-
- for (var i = 0; i < constructors.length; i++) {
- var constructor = constructors[i];
- var cls = constructor.name;
- var desc = processedClasses.collected[cls];
- var globalObject = desc[0];
- desc = desc[1];
- allClasses[cls] = constructor;
- globalObject[cls] = constructor;
- }
- constructors = null;
-
- var finishedClasses = #finishedClassesAccess;
-
- function finishClass(cls) {
-
- if (finishedClasses[cls]) return;
- finishedClasses[cls] = true;
-
- var superclass = processedClasses.pending[cls];
-
- if (#needsMixinSupport) {
- if (superclass && superclass.indexOf("+") > 0) {
- var s = superclass.split("+");
- superclass = s[0];
- var mixinClass = s[1];
- finishClass(mixinClass);
- var mixin = allClasses[mixinClass];
- var mixinPrototype = mixin.prototype;
- var clsPrototype = allClasses[cls].prototype;
-
- var properties = Object.keys(mixinPrototype);
- for (var i = 0; i < properties.length; i++) {
- var d = properties[i];
- if (!hasOwnProperty.call(clsPrototype, d))
- clsPrototype[d] = mixinPrototype[d];
- }
- }
- }
-
- // The superclass is only false (empty string) for the Dart Object
- // class. The minifier together with noSuchMethod can put methods on
- // the Object.prototype object, and they show through here, so we check
- // that we have a string.
- if (!superclass || typeof superclass != "string") {
- // Inlined special case of InheritFrom here for performance reasons.
- // Fix up the Dart Object class' prototype.
- var constructor = allClasses[cls];
- var prototype = constructor.prototype;
- prototype.constructor = constructor;
- prototype.#isObject = constructor;
- prototype.#deferredAction = function() {};
- return;
- }
- finishClass(superclass);
- var superConstructor = allClasses[superclass];
-
- if (!superConstructor) {
- superConstructor = existingIsolateProperties[superclass];
- }
-
- var constructor = allClasses[cls];
- var prototype = inheritFrom(constructor, superConstructor);
-
- if (#needsMixinSupport) {
- if (mixinPrototype) {
- prototype.#deferredAction
- = mixinDeferredActionHelper(mixinPrototype, prototype);
- }
- }
-
- if (#needsNativeSupport) {
- if (Object.prototype.hasOwnProperty.call(prototype, #specProperty)) {
- #nativeInfoHandler;
- // As native classes can come into existence without a constructor
- // call, we have to ensure that the class has been fully
- // initialized.
- prototype.#deferredAction();
- }
- }
- // Interceptors (or rather their prototypes) are also used without
- // first instantiating them first.
- if (prototype.#isInterceptorClass) {
- prototype.#deferredAction();
- }
- }
-
- #trivialNsmHandlers;
-
- var properties = Object.keys(processedClasses.pending);
- for (var i = 0; i < properties.length; i++) finishClass(properties[i]);
- }
-
- // Generic handler for deferred class setup. The handler updates the
- // prototype that it is installed on (it traverses the prototype chain
- // of [this] to find itself) and then removes itself. It recurses by
- // calling deferred handling again, which terminates on Object due to
- // the final handler.
- function finishAddStubsHelper() {
- var prototype = this;
- // Find the actual prototype that this handler is installed on.
- while (!prototype.hasOwnProperty(#deferredActionString)) {
- prototype = prototype.__proto__;
- }
- delete prototype.#deferredAction; // Intended to make it slow, too.
- var properties = Object.keys(prototype);
- for (var index = 0; index < properties.length; index++) {
- var property = properties[index];
- var firstChar = property.charCodeAt(0);
- var elem;
- // We have to filter out some special properties that are used for
- // metadata in descriptors. Currently, we filter everything that
- // starts with + or *. This has to stay in sync with the special
- // properties that are used by processClassData below.
- if (property !== "${namer.classDescriptorProperty}" &&
- property !== "$reflectableField" &&
- firstChar !== 43 && // 43 is aka "+".
- firstChar !== 42 && // 42 is aka "*"
- (elem = prototype[property]) != null &&
- elem.constructor === Array &&
- property !== "<>") {
- addStubs(prototype, elem, property, false, []);
- }
- }
- convertToFastObject(prototype);
- prototype = prototype.__proto__;
- // Call other handlers.
- prototype.#deferredAction();
- }
-
- if (#needsMixinSupport) {
- // Returns a deferred class setup handler that first invokes the
- // handler on [mixinPrototype] and then resumes handling on
- // [targetPrototype]. If [targetPrototype] already has a handler
- // installed, the handler is preserved in the generated closure and
- // thus can be safely overwritten.
- function mixinDeferredActionHelper(mixinPrototype, targetPrototype) {
- var chain;
- if (targetPrototype.hasOwnProperty(#deferredActionString)) {
- chain = targetPrototype.#deferredAction;
- }
- return function foo() {
- if (!supportsDirectProtoAccess) return;
- var prototype = this;
- // Find the actual prototype that this handler is installed on.
- while (!prototype.hasOwnProperty(#deferredActionString)) {
- prototype = prototype.__proto__;
- }
- if (chain) {
- prototype.#deferredAction = chain;
- } else {
- delete prototype.#deferredAction;
- convertToFastObject(prototype);
- }
- mixinPrototype.#deferredAction();
- prototype.#deferredAction();
- }
- }
- }
-
- function processClassData(cls, descriptor, processedClasses) {
- descriptor = convertToSlowObject(descriptor); // Use a slow object.
- var previousProperty;
- var properties = Object.keys(descriptor);
- var hasDeferredWork = false;
- var shouldDeferWork =
- supportsDirectProtoAccess && cls != #objectClassName;
- for (var i = 0; i < properties.length; i++) {
- var property = properties[i];
- var firstChar = property.charCodeAt(0);
- if (property === #staticsPropertyNameString) {
- processStatics(#statics[cls] = descriptor.#staticsPropertyName,
- processedClasses);
- delete descriptor.#staticsPropertyName;
- } else if (firstChar === 43) { // 43 is "+".
- mangledNames[previousProperty] = property.substring(1);
- var flag = descriptor[property];
- if (flag > 0)
- descriptor[previousProperty].$reflectableField = flag;
- } else if (firstChar === 42) { // 42 is "*"
- descriptor[previousProperty].$defaultValuesField =
- descriptor[property];
- var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
- if (!optionalMethods) {
- descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {}
- }
- optionalMethods[property] = previousProperty;
- } else {
- var elem = descriptor[property];
- if (property !== "${namer.classDescriptorProperty}" &&
- elem != null &&
- elem.constructor === Array &&
- property !== "<>") {
- if (shouldDeferWork) {
- hasDeferredWork = true;
- } else {
- addStubs(descriptor, elem, property, false, []);
- }
- } else {
- previousProperty = property;
- }
- }
- }
-
- if (hasDeferredWork)
- descriptor.#deferredAction = finishAddStubsHelper;
-
- /* The 'fields' are either a constructor function or a
- * string encoding fields, constructor and superclass. Gets the
- * superclass and fields in the format
- * 'Super;field1,field2'
- * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor.
- */
- var classData = descriptor["${namer.classDescriptorProperty}"],
- split, supr, fields = classData;
-
- // ${ClassBuilder.fieldEncodingDescription}.
- var s = fields.split(";");
- fields = s[1] ? s[1].split(",") : [];
- supr = s[0];
- // ${ClassBuilder.functionTypeEncodingDescription}.
- split = supr.split(":");
- if (split.length == 2) {
- supr = split[0];
- var functionSignature = split[1];
- if (functionSignature)
- descriptor.${namer.operatorSignature} = function(s) {
- return function() {
- return #types[s];
- };
- }(functionSignature);
- }
-
- if (supr) processedClasses.pending[cls] = supr;
- if (#notInCspMode) {
- processedClasses.combinedConstructorFunction +=
- defineClass(cls, fields);
- processedClasses.constructorsList.push(cls);
- }
- processedClasses.collected[cls] = [globalObject, descriptor];
- classes.push(cls);
- }
- }
-
- function processStatics(descriptor, processedClasses) {
- var properties = Object.keys(descriptor);
- for (var i = 0; i < properties.length; i++) {
- var property = properties[i];
- if (property === "${namer.classDescriptorProperty}") continue;
- var element = descriptor[property];
- var firstChar = property.charCodeAt(0);
- var previousProperty;
- if (firstChar === 43) { // 43 is "+".
- mangledGlobalNames[previousProperty] = property.substring(1);
- var flag = descriptor[property];
- if (flag > 0)
- descriptor[previousProperty].$reflectableField = flag;
- if (element && element.length)
- #typeInformation[previousProperty] = element;
- } else if (firstChar === 42) { // 42 is "*"
- globalObject[previousProperty].$defaultValuesField = element;
- var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
- if (!optionalMethods) {
- descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {}
- }
- optionalMethods[property] = previousProperty;
- } else if (typeof element === "function") {
- globalObject[previousProperty = property] = element;
- functions.push(property);
- } else if (element.constructor === Array) {
- if (#needsStructuredMemberInfo) {
- addStubs(globalObject, element, property, true, functions);
- }
- } else {
- // We will not enter this case if no classes are defined.
- if (#needsClassSupport) {
- previousProperty = property;
- processClassData(property, element, processedClasses);
- }
- }
- }
- }
-
- if (#needsStructuredMemberInfo) {
-
- // See [dart2js.js_emitter.ContainerBuilder.addMemberMethod] for format of
- // [array].
-
- // Processes the stub declaration given by [array] and stores the results
- // in the corresponding [prototype]. [name] is the property name in
- // [prototype] that the stub declaration belongs to.
- // If [isStatic] is true, the property being processed belongs to a static
- // function and thus is stored as a global. In that case we also add all
- // generated functions to the [functions] array, which is used by the
- // mirrors system to enumerate all static functions of a library. For
- // non-static functions we might still add some functions to [functions] but
- // the information is thrown away at the call site. This is to avoid
- // conditionals.
- function addStubs(prototype, array, name, isStatic, functions) {
- var index = $FUNCTION_INDEX, applyTrampolineIndex = index, alias = array[index], f;
- if (typeof alias == "string") {
- f = array[++index];
- } else {
- f = alias;
- alias = name;
- }
- if (typeof f == "number") {
- applyTrampolineIndex = f;
- f = array[++index];
- }
- prototype[name] = prototype[alias] = f;
- var funcs = [f];
- f.\$stubName = name;
- functions.push(name);
- for (index++; index < array.length; index++) {
- f = array[index];
- if (typeof f != "function") break;
- if (!isStatic) {
- f.\$stubName = ${readString("array", "++index")};
- }
- funcs.push(f);
- if (f.\$stubName) {
- prototype[f.\$stubName] = f;
- functions.push(f.\$stubName);
- }
- }
-
- for (var i = 0; i < funcs.length; index++, i++) {
- funcs[i].\$callName = ${readString("array", "index")};
- }
- var getterStubName = ${readString("array", "index")};
- array = array.slice(++index);
- var requiredParameterInfo = ${readInt("array", "0")};
- var isIntercepted = (requiredParameterInfo & 1) === 1;
- requiredParameterInfo = requiredParameterInfo >> 1;
- var requiredParameterCount = requiredParameterInfo >> 1;
- var isAccessor = (requiredParameterInfo & 1) === 1;
- var isSetter = requiredParameterInfo === 3;
- var isGetter = requiredParameterInfo === 1;
- var optionalParameterInfo = ${readInt("array", "1")};
- var optionalParameterCount = optionalParameterInfo >> 1;
- var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;
- var totalParameterCount = requiredParameterCount + optionalParameterCount;
- var functionTypeIndex = ${readFunctionType("array", "2")};
- if (typeof functionTypeIndex == "number")
- ${readFunctionType("array", "2")} = functionTypeIndex + typesOffset;
- if (metadataOffset > 0) {
- var position = 3;
- // Update index that refers to the parameter default value.
- for (var i = 0; i < optionalParameterCount; i++) {
- if (typeof ${readInt("array", "position")} == "number")
- ${readInt("array", "position")} =
- ${readInt("array", "position")} + metadataOffset;
- position++;
- }
- for (var i = 0; i < totalParameterCount; i++) {
- // Update index that refers to the parameter name.
- ${readInt("array", "position")} =
- ${readInt("array", "position")} + metadataOffset;
- position++;
- }
- }
- var unmangledNameIndex = $unmangledNameIndex;
-
- if (getterStubName) {
- f = tearOff(funcs, applyTrampolineIndex, array, isStatic, name, isIntercepted);
- prototype[name].\$getter = f;
- f.\$getterStub = true;
- if (isStatic) {
- functions.push(getterStubName);
- }
- prototype[getterStubName] = f;
- funcs.push(f);
- f.\$stubName = getterStubName;
- f.\$callName = null;
- }
-
- if (#usesMangledNames) {
- var isReflectable = array.length > unmangledNameIndex;
- if (isReflectable) {
- funcs[0].$reflectableField = 1;
- funcs[0].$reflectionInfoField = array;
- for (var i = 1; i < funcs.length; i++) {
- funcs[i].$reflectableField = 2;
- funcs[i].$reflectionInfoField = array;
- }
- var mangledNames = isStatic ? #mangledGlobalNames : #mangledNames;
- var unmangledName = ${readString("array", "unmangledNameIndex")};
- // The function is either a getter, a setter, or a method.
- // If it is a method, it might also have a tear-off closure.
- // The unmangledName is the same as the getter-name.
- var reflectionName = unmangledName;
- if (getterStubName) mangledNames[getterStubName] = reflectionName;
- if (isSetter) {
- reflectionName += "=";
- } else if (!isGetter) {
- reflectionName += ":" +
- (requiredParameterCount + optionalParameterCount);
- }
- mangledNames[name] = reflectionName;
- funcs[0].$reflectionNameField = reflectionName;
- for (var i = unmangledNameIndex + 1; i < array.length; i++) {
- ${readInt("array", "i")} =
- ${readInt("array", "i")} + metadataOffset;
- }
- funcs[0].$metadataIndexField = unmangledNameIndex + 1;
- // The following line installs the [${JsGetName.CALL_CATCH_ALL}]
- // property for closures.
- if (optionalParameterCount) prototype[#callCatchAll] = funcs[applyTrampolineIndex];
- }
- }
- }
-
- if (#enabledJsInterop) {
- #jsInteropBoostrap
- }
- #tearOffCode;
- }
-
- var functionCounter = 0;
- if (!#libraries) #libraries = [];
- if (!#mangledNames) #mangledNames = map();
- if (!#mangledGlobalNames) #mangledGlobalNames = map();
- if (!#statics) #statics = map();
- if (!#typeInformation) #typeInformation = map();
- var libraries = #libraries;
- var mangledNames = #mangledNames;
- var mangledGlobalNames = #mangledGlobalNames;
- var hasOwnProperty = Object.prototype.hasOwnProperty;
- var length = programData.length;
- var processedClasses = map();
- processedClasses.collected = map();
- processedClasses.pending = map();
- if (#notInCspMode) {
- processedClasses.constructorsList = [];
- // For every class processed [processedClasses.combinedConstructorFunction]
- // will be updated with the corresponding constructor function.
- processedClasses.combinedConstructorFunction =
- "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+
- "var \$desc;\\n";
- }
- for (var i = 0; i < length; i++) {
- var data = programData[i];
-
-// [data] contains these elements:
-// 0. The library name (not unique).
-// 1. The library URI (unique).
-// 2. A function returning the metadata associated with this library.
-// 3. The global object to use for this library.
-// 4. An object literal listing the members of the library.
-// 5. This element is optional and if present it is true and signals that this
-// library is the root library (see dart:mirrors IsolateMirror.rootLibrary).
-//
-// The entries of [data] are built in [assembleProgram] above.
-
- var name = data[0];
- var uri = data[1];
- var metadata = data[2];
- var globalObject = data[3];
- var descriptor = data[4];
- var isRoot = !!data[5];
- var fields = descriptor && descriptor["${namer.classDescriptorProperty}"];
- if (fields instanceof Array) fields = fields[0];
- var classes = [];
- var functions = [];
- processStatics(descriptor, processedClasses);
- libraries.push([name, uri, classes, functions, metadata, fields, isRoot,
- globalObject]);
- }
- if (#needsClassSupport) finishClasses(processedClasses);
-}''';
-
- // TODO(zarah): Remove empty else branches in output when if(#hole) is false.
- return js.statement(skeleton, holes);
-}
-
-String readString(String array, String index) {
- return readChecked(
- array, index, 'result != null && typeof result != "string"', 'string');
-}
-
-String readInt(String array, String index) {
- return readChecked(
- array,
- index,
- 'result != null && (typeof result != "number" || (result|0) !== result)',
- 'int');
-}
-
-String readFunctionType(String array, String index) {
- return readChecked(
- array,
- index,
- 'result != null && '
- '(typeof result != "number" || (result|0) !== result) && '
- 'typeof result != "function"',
- 'function or int');
-}
-
-String readChecked(String array, String index, String check, String type) {
- if (!VALIDATE_DATA) return '$array[$index]';
- return '''
-(function() {
- var result = $array[$index];
- if ($check) {
- throw new Error(
- name + ": expected value of type \'$type\' at index " + ($index) +
- " but got " + (typeof result));
- }
- return result;
-})()''';
-}
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index d91972f..3bbdcfa0 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -58,10 +58,8 @@
return _emitterTask.interceptorPrototypeAccess(cls);
}
- /**
- * Build a JavaScript AST node for doing a type check on
- * [cls]. [cls] must be a non-native interceptor class.
- */
+ /// Build a JavaScript AST node for doing a type check on
+ /// [cls]. [cls] must be a non-native interceptor class.
jsAst.Statement buildInterceptorCheck(ClassEntity cls) {
jsAst.Expression condition;
assert(_interceptorData.isInterceptedClass(cls));
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 933f41c..7829d79 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -72,10 +72,8 @@
Fragment get mainFragment => fragments.first;
}
-/**
- * This class represents a JavaScript object that contains static state, like
- * classes or functions.
- */
+/// This class represents a JavaScript object that contains static state, like
+/// classes or functions.
class Holder {
final String name;
final int index;
@@ -90,12 +88,10 @@
}
}
-/**
- * This class represents one output file.
- *
- * If no library is deferred, there is only one [Fragment] of type
- * [MainFragment].
- */
+/// This class represents one output file.
+///
+/// If no library is deferred, there is only one [Fragment] of type
+/// [MainFragment].
abstract class Fragment {
/// The outputUnit should only be used during the transition to the new model.
/// Uses indicate missing information in the model.
@@ -122,12 +118,10 @@
bool get isMainFragment;
}
-/**
- * The main output file.
- *
- * This code emitted from this [Fragment] must be loaded first. It can then load
- * other [DeferredFragment]s.
- */
+/// The main output file.
+///
+/// This code emitted from this [Fragment] must be loaded first. It can then load
+/// other [DeferredFragment]s.
class MainFragment extends Fragment {
final js.Statement invokeMain;
@@ -149,9 +143,7 @@
}
}
-/**
- * An output (file) for deferred code.
- */
+/// An output (file) for deferred code.
class DeferredFragment extends Fragment {
final String name;
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 85230aa..2e0dca3 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -46,36 +46,35 @@
NativeData get _nativeData => _closedWorld.nativeData;
InterceptorData get _interceptorData => _closedWorld.interceptorData;
- /**
- * Prepares native classes for emission. Returns the unneeded classes.
- *
- * Removes trivial classes (that can be represented by a super type) and
- * generates properties that have to be added to classes (native or not).
- *
- * Updates the `nativeLeafTags`, `nativeNonLeafTags` and `nativeExtensions`
- * fields of the given classes. This data must be emitted with the
- * corresponding classes.
- *
- * The interceptors are filtered to avoid emitting trivial interceptors. For
- * example, if the program contains no code that can distinguish between the
- * numerous subclasses of `Element` then we can pretend that `Element` is a
- * leaf class, and all instances of subclasses of `Element` are instances of
- * `Element`.
- *
- * There is also a performance benefit (in addition to the obvious code size
- * benefit), due to how [getNativeInterceptor] works. Finding the interceptor
- * of a leaf class in the hierarchy is more efficient that a non-leaf, so it
- * improves performance when more classes can be treated as leaves.
- *
- * [classes] contains native classes, mixin applications, and user subclasses
- * of native classes.
- *
- * [interceptorClassesNeededByConstants] contains the interceptors that are
- * referenced by constants.
- *
- * [classesModifiedByEmitRTISupport] contains the list of classes that must
- * exist, because runtime-type support adds information to the class.
- */
+ /// Prepares native classes for emission. Returns the unneeded classes.
+ ///
+ /// Removes trivial classes (that can be represented by a super type) and
+ /// generates properties that have to be added to classes (native or not).
+ ///
+ /// Updates the `nativeLeafTags`, `nativeNonLeafTags` and `nativeExtensions`
+ /// fields of the given classes. This data must be emitted with the
+ /// corresponding classes.
+ ///
+ /// The interceptors are filtered to avoid emitting trivial interceptors. For
+ /// example, if the program contains no code that can distinguish between the
+ /// numerous subclasses of `Element` then we can pretend that `Element` is a
+ /// leaf class, and all instances of subclasses of `Element` are instances of
+ /// `Element`.
+ ///
+ /// There is also a performance benefit (in addition to the obvious code size
+ /// benefit), due to how [getNativeInterceptor] works. Finding the
+ /// interceptor of a leaf class in the hierarchy is more efficient that a
+ /// non-leaf, so it improves performance when more classes can be treated as
+ /// leaves.
+ ///
+ /// [classes] contains native classes, mixin applications, and user subclasses
+ /// of native classes.
+ ///
+ /// [interceptorClassesNeededByConstants] contains the interceptors that are
+ /// referenced by constants.
+ ///
+ /// [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,
@@ -219,11 +218,9 @@
.toSet();
}
- /**
- * Computes the native classes that are extended (subclassed) by non-native
- * classes and the set non-mative classes that extend them. (A List is used
- * instead of a Set for out stability).
- */
+ /// Computes the native classes that are extended (subclassed) by non-native
+ /// classes and the set non-mative classes that extend them. (A List is used
+ /// instead of a Set for out stability).
Map<Class, List<Class>> computeExtensionPoints(List<Class> classes) {
Class nativeSuperclassOf(Class cls) {
if (cls == null) return null;
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 6592f68..e57a3ab 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -4,12 +4,10 @@
part of dart2js.js_emitter.program_builder;
-/**
- * Generates the code for all used classes in the program. Static fields (even
- * in classes) are ignored, since they can be treated as non-class elements.
- *
- * The code for the containing (used) methods must exist in the `universe`.
- */
+/// Generates the code for all used classes in the program. Static fields (even
+/// in classes) are ignored, since they can be treated as non-class elements.
+///
+/// The code for the containing (used) methods must exist in the `universe`.
class Collector {
final CompilerOptions _options;
final JCommonElements _commonElements;
@@ -78,10 +76,8 @@
return classes;
}
- /**
- * Return a function that returns true if its argument is a class
- * that needs to be emitted.
- */
+ /// Return a function that returns true if its argument is a class
+ /// that needs to be emitted.
Function computeClassFilter(Iterable<ClassEntity> backendTypeHelpers) {
Set<ClassEntity> unneededClasses = new Set<ClassEntity>();
// The [Bool] class is not marked as abstract, but has a factory
@@ -129,9 +125,7 @@
];
}
- /**
- * Compute all the constants that must be emitted.
- */
+ /// Compute all the constants that must be emitted.
void computeNeededConstants() {
List<ConstantValue> constants =
_worldBuilder.getConstantsForEmission(_emitter.compareConstants);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index e1b0d46..493afa9 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -4,24 +4,22 @@
part of dart2js.js_emitter.program_builder;
-/**
- * [member] is a field (instance, static, or top level).
- *
- * [name] is the field name that the [Namer] has picked for this field's
- * storage, that is, the JavaScript property name.
- *
- * [accessorName] is the name of the accessor. For instance fields this is
- * mostly the same as [name] except when [member] is shadowing a field in its
- * superclass. For other fields, they are rarely the same.
- *
- * [needsGetter] and [needsSetter] represent if a getter or a setter
- * respectively is needed. There are many factors in this, for example, if the
- * accessor can be inlined.
- *
- * [needsCheckedSetter] indicates that a checked getter is needed, and in this
- * case, [needsSetter] is always false. [needsCheckedSetter] is only true when
- * type assertions are enabled (checked mode).
- */
+/// [member] is a field (instance, static, or top level).
+///
+/// [name] is the field name that the [Namer] has picked for this field's
+/// storage, that is, the JavaScript property name.
+///
+/// [accessorName] is the name of the accessor. For instance fields this is
+/// mostly the same as [name] except when [member] is shadowing a field in its
+/// superclass. For other fields, they are rarely the same.
+///
+/// [needsGetter] and [needsSetter] represent if a getter or a setter
+/// respectively is needed. There are many factors in this, for example, if the
+/// accessor can be inlined.
+///
+/// [needsCheckedSetter] indicates that a checked getter is needed, and in this
+/// case, [needsSetter] is always false. [needsCheckedSetter] is only true when
+/// type assertions are enabled (checked mode).
typedef void AcceptField(FieldEntity member, js.Name name, js.Name accessorName,
bool needsGetter, bool needsSetter, bool needsCheckedSetter);
@@ -43,22 +41,20 @@
this._namer,
this._closedWorld);
- /**
- * Invokes [f] for each of the fields of [element].
- *
- * [element] must be a [ClassEntity] or a [LibraryEntity].
- *
- * If [element] is a [ClassEntity], the static fields of the class are
- * visited if [visitStatics] is true and the instance fields are visited if
- * [visitStatics] is false.
- *
- * If [element] is a [LibraryEntity], [visitStatics] must be true.
- *
- * When visiting the instance fields of a class, the fields of its superclass
- * are also visited if the class is instantiated.
- *
- * Invariant: [element] must be a declaration element.
- */
+ /// Invokes [f] for each of the fields of [element].
+ ///
+ /// [element] must be a [ClassEntity] or a [LibraryEntity].
+ ///
+ /// If [element] is a [ClassEntity], the static fields of the class are
+ /// visited if [visitStatics] is true and the instance fields are visited if
+ /// [visitStatics] is false.
+ ///
+ /// If [element] is a [LibraryEntity], [visitStatics] must be true.
+ ///
+ /// When visiting the instance fields of a class, the fields of its superclass
+ /// are also visited if the class is instantiated.
+ ///
+ /// Invariant: [element] must be a declaration element.
void visitFields(AcceptField f,
{bool visitStatics: false, LibraryEntity library, ClassEntity cls}) {
bool isNativeClass = false;
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 7d974f3..02cdf45 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -102,13 +102,11 @@
: _outputUnitVisitor = new _TypeContainedInOutputUnitVisitor(
_commonElements, _outputUnitData);
- /**
- * Generate "is tests" for [cls] itself, and the "is tests" for the
- * classes it implements and type argument substitution functions for these
- * tests. We don't need to add the "is tests" of the super class because
- * they will be inherited at runtime, but we may need to generate the
- * substitutions, because they may have changed.
- */
+ /// Generate "is tests" for [cls] itself, and the "is tests" for the
+ /// classes it implements and type argument substitution functions for these
+ /// tests. We don't need to add the "is tests" of the super class because
+ /// they will be inherited at runtime, but we may need to generate the
+ /// substitutions, because they may have changed.
/// Generates all properties necessary for is-checks on the [classElement].
///
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 5ef3622..8e5224c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -560,14 +560,12 @@
#inheritance;
}''';
-/**
- * This class builds a JavaScript tree for a given fragment.
- *
- * A fragment is generally written into a separate file so that it can be
- * loaded dynamically when a deferred library is loaded.
- *
- * This class is stateless and can be reused for different fragments.
- */
+/// This class builds a JavaScript tree for a given fragment.
+///
+/// A fragment is generally written into a separate file so that it can be
+/// loaded dynamically when a deferred library is loaded.
+///
+/// This class is stateless and can be reused for different fragments.
class FragmentEmitter {
final Compiler compiler;
final Namer namer;
@@ -597,6 +595,13 @@
return js.js('#.#', [cls.holder.name, cls.name]);
}
+ void registerEntityAst(Entity entity, js.Node code, {LibraryEntity library}) {
+ compiler.dumpInfoTask.registerEntityAst(entity, code);
+ // TODO(sigmund): stop recoding associations twice, dump-info already
+ // has library to element dependencies to recover this data.
+ if (library != null) compiler.dumpInfoTask.registerEntityAst(library, code);
+ }
+
js.Statement emitMainFragment(
Program program, DeferredLoadingState deferredLoadingState) {
MainFragment fragment = program.fragments.first;
@@ -792,30 +797,28 @@
.where((Holder holder) => !holder.isStaticStateHolder)
.toList(growable: false);
- Map<Holder, Map<js.Name, js.Expression>> holderCode = {};
+ Map<Holder, List<js.Property>> holderCode = {};
for (Holder holder in holders) {
- holderCode[holder] = <js.Name, js.Expression>{};
+ holderCode[holder] = <js.Property>[];
}
for (Library library in fragment.libraries) {
for (StaticMethod method in library.statics) {
assert(!method.holder.isStaticStateHolder);
var staticMethod = emitStaticMethod(method);
- if (compiler.options.dumpInfo) {
- for (var code in staticMethod.values) {
- compiler.dumpInfoTask.registerEntityAst(method.element, code);
- compiler.dumpInfoTask.registerEntityAst(library.element, code);
- }
- }
- holderCode[method.holder].addAll(staticMethod);
+ staticMethod.forEach((key, value) {
+ var property = new js.Property(js.quoteName(key), value);
+ holderCode[method.holder].add(property);
+ registerEntityAst(method.element, property, library: library.element);
+ });
}
for (Class cls in library.classes) {
assert(!cls.holder.isStaticStateHolder);
var constructor = emitConstructor(cls);
- compiler.dumpInfoTask.registerEntityAst(cls.element, constructor);
- compiler.dumpInfoTask.registerEntityAst(library.element, constructor);
- holderCode[cls.holder][cls.name] = constructor;
+ var property = new js.Property(js.quoteName(cls.name), constructor);
+ registerEntityAst(cls.element, property, library: library.element);
+ holderCode[cls.holder].add(property);
}
}
@@ -823,10 +826,7 @@
List<Holder> activeHolders = [];
for (Holder holder in holders) {
- List<js.Property> properties = [];
- holderCode[holder].forEach((js.Name key, js.Expression value) {
- properties.add(new js.Property(js.quoteName(key), value));
- });
+ List<js.Property> properties = holderCode[holder];
if (properties.isEmpty) {
holderInitializations.add(new js.VariableInitialization(
new js.VariableDeclaration(holder.name, allowRename: false),
@@ -1006,8 +1006,7 @@
var proto = js.js.statement(
'#.prototype = #;', [classReference(cls), emitPrototype(cls)]);
ClassEntity element = cls.element;
- compiler.dumpInfoTask.registerEntityAst(element, proto);
- compiler.dumpInfoTask.registerEntityAst(element.library, proto);
+ registerEntityAst(element, proto, library: element.library);
return proto;
}).toList(growable: false);
@@ -1050,7 +1049,7 @@
emitInstanceMethod(method)
.forEach((js.Expression name, js.Expression code) {
var prop = js.Property(name, code);
- compiler.dumpInfoTask.registerEntityAst(method.element, prop);
+ registerEntityAst(method.element, prop);
properties.add(prop);
});
});
@@ -1216,11 +1215,13 @@
if (cls.isSoftDeferred != softDeferred) continue;
collect(cls);
if (cls.mixinClass != null) {
- mixinCalls.add(js.js.statement('#(#, #)', [
+ js.Statement statement = js.js.statement('#(#, #)', [
locals.find('_mixin', 'hunkHelpers.mixin'),
classReference(cls),
classReference(cls.mixinClass),
- ]));
+ ]);
+ registerEntityAst(cls.element, statement, library: library.element);
+ mixinCalls.add(statement);
}
}
}
@@ -1231,13 +1232,27 @@
? new js.LiteralNull()
: classReference(superclass);
if (list.length == 1) {
- inheritCalls.add(js.js.statement('#(#, #)', [
+ Class cls = list.single;
+ var statement = js.js.statement('#(#, #)', [
locals.find('_inherit', 'hunkHelpers.inherit'),
- classReference(list.single),
+ classReference(cls),
superclassReference
- ]));
+ ]);
+ registerEntityAst(cls.element, statement, library: cls.element.library);
+ inheritCalls.add(statement);
} else {
- var listElements = list.map(classReference).toList();
+ List<js.Expression> listElements = [];
+ // Since inheritMany shares the superclass reference, we attribute it
+ // only to the first subclass.
+ ClassEntity firstClass = list.first.element;
+ registerEntityAst(firstClass, superclassReference,
+ library: firstClass.library);
+ for (Class cls in list) {
+ js.Expression reference = classReference(cls);
+ registerEntityAst(cls.element, reference,
+ library: cls.element.library);
+ listElements.add(reference);
+ }
inheritCalls.add(js.js.statement('#(#, #)', [
locals.find('_inheritMany', 'hunkHelpers.inheritMany'),
superclassReference,
@@ -1271,14 +1286,18 @@
if (method.aliasName != null) {
if (firstAlias) {
firstAlias = false;
- assignments.add(js.js.statement(
+ js.Statement statement = js.js.statement(
assignments.isEmpty
? 'var _ = #.prototype;'
: '_ = #.prototype',
- classReference(cls)));
+ classReference(cls));
+ registerEntityAst(method.element, statement);
+ assignments.add(statement);
}
- assignments.add(js.js.statement('_.# = _.#',
- [js.quoteName(method.aliasName), js.quoteName(method.name)]));
+ js.Statement statement = js.js.statement('_.# = _.#',
+ [js.quoteName(method.aliasName), js.quoteName(method.name)]);
+ registerEntityAst(method.element, statement);
+ assignments.add(statement);
}
}
}
@@ -1489,8 +1508,11 @@
if (method is StaticDartMethod) {
if (method.needsTearOff) {
Holder holder = method.holder;
- inits.add(
- emitInstallTearOff(new js.VariableUse(holder.name), method));
+ js.Statement statement =
+ emitInstallTearOff(new js.VariableUse(holder.name), method);
+ registerEntityAst(method.element, statement,
+ library: library.element);
+ inits.add(statement);
}
}
}
@@ -1508,7 +1530,9 @@
reference = js.js('# = #', [temp, container]);
}
for (InstanceMethod method in methods) {
- inits.add(emitInstallTearOff(reference, method));
+ js.Statement statement = emitInstallTearOff(reference, method);
+ registerEntityAst(method.element, statement);
+ inits.add(statement);
reference = temp; // Second and subsequent calls use temp.
}
}
@@ -1558,8 +1582,11 @@
//
Iterable<js.Statement> statements = fields.map((StaticField field) {
assert(field.holder.isStaticStateHolder);
- return js.js
+ js.Statement statement = js.js
.statement("#.# = #;", [field.holder.name, field.name, field.code]);
+ registerEntityAst(field.element, statement,
+ library: field.element.library);
+ return statement;
});
return wrapPhase('staticFields', statements.toList());
}
@@ -1574,13 +1601,17 @@
LocalAliases locals = LocalAliases();
for (StaticField field in fields) {
assert(field.holder.isStaticStateHolder);
- statements.add(js.js.statement("#(#, #, #, #);", [
+ js.Statement statement = js.js.statement("#(#, #, #, #);", [
locals.find('_lazy', 'hunkHelpers.lazy'),
field.holder.name,
js.quoteName(field.name),
js.quoteName(field.getterName),
field.code
- ]));
+ ]);
+
+ registerEntityAst(field.element, statement,
+ library: field.element.library);
+ statements.add(statement);
}
if (locals.isNotEmpty) {
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index b9461da..f0b0efd 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -119,10 +119,6 @@
/// Returns the definition information for [cls].
ClassDefinition getClassDefinition(covariant ClassEntity cls);
- /// Returns the static type of [node].
- // TODO(johnniwinther): This should be provided directly from kernel.
- DartType getStaticType(ir.Expression node);
-
/// [ElementEnvironment] for library, class and member lookup.
JElementEnvironment get elementEnvironment;
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 68618f8..47433bc 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -33,6 +33,7 @@
import '../ir/element_map.dart';
import '../ir/types.dart';
import '../ir/visitors.dart';
+import '../ir/static_type_base.dart';
import '../ir/static_type_provider.dart';
import '../ir/util.dart';
import '../js/js.dart' as js;
@@ -99,6 +100,7 @@
JsConstantEnvironment _constantEnvironment;
KernelDartTypes _types;
ir.TypeEnvironment _typeEnvironment;
+ ir.ClassHierarchy _classHierarchy;
/// Library environment. Used for fast lookup.
JProgramEnv programEnv;
@@ -1057,12 +1059,18 @@
ir.TypeEnvironment get typeEnvironment {
if (_typeEnvironment == null) {
_typeEnvironment ??= new ir.TypeEnvironment(
- new ir.CoreTypes(programEnv.mainComponent),
- new ir.ClassHierarchy(programEnv.mainComponent));
+ new ir.CoreTypes(programEnv.mainComponent), classHierarchy);
}
return _typeEnvironment;
}
+ ir.ClassHierarchy get classHierarchy {
+ if (_classHierarchy == null) {
+ _classHierarchy ??= new ir.ClassHierarchy(programEnv.mainComponent);
+ }
+ return _classHierarchy;
+ }
+
StaticTypeProvider getStaticTypeProvider(MemberEntity member) {
MemberDefinition memberDefinition = members.getData(member).definition;
Map<ir.Expression, ir.DartType> cachedStaticTypes;
@@ -1095,29 +1103,8 @@
}
assert(cachedStaticTypes != null, "No static types cached for $member.");
- return new CachedStaticType(
- // We need a copy of the type environment since the `thisType` field
- // is holds state, making the environment contextually bound.
- new ir.TypeEnvironment(
- typeEnvironment.coreTypes, typeEnvironment.hierarchy)
- ..thisType = thisType,
- cachedStaticTypes);
- }
-
- DartType getStaticType(ir.Expression node) {
- ir.TreeNode enclosingClass = node;
- while (enclosingClass != null && enclosingClass is! ir.Class) {
- enclosingClass = enclosingClass.parent;
- }
- try {
- typeEnvironment.thisType =
- enclosingClass is ir.Class ? enclosingClass.thisType : null;
- return getDartType(node.getStaticType(typeEnvironment));
- } catch (e) {
- // The static type computation crashes on type errors. Use `dynamic`
- // as static type.
- return commonElements.dynamicType;
- }
+ return new CachedStaticType(typeEnvironment, cachedStaticTypes,
+ new ThisInterfaceType.from(thisType));
}
Name getName(ir.Name name) {
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index 9533b15..b6fe609 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../constants/values.dart';
@@ -29,8 +30,12 @@
/// Access to the [DartTypes] object.
DartTypes get types;
+ /// Returns the type environment for the underlying kernel model.
ir.TypeEnvironment get typeEnvironment;
+ /// Returns the class hierarchy for the underlying kernel model.
+ ir.ClassHierarchy get classHierarchy;
+
/// Returns the [DartType] corresponding to [type].
DartType getDartType(ir.DartType type);
@@ -55,6 +60,10 @@
/// access of [node].
Selector getSelector(ir.Expression node);
+ /// Returns the [Selector] corresponding to the invocation of [name] with
+ /// [arguments].
+ Selector getInvocationSelector(ir.Name name, ir.Arguments arguments);
+
/// Returns the [MemberEntity] corresponding to the member [node].
MemberEntity getMember(ir.Member node);
@@ -113,10 +122,6 @@
/// Returns the defining node for [cls].
ir.Class getClassNode(covariant ClassEntity cls);
- /// Returns the static type of [node].
- // TODO(johnniwinther): This should be provided directly from kernel.
- DartType getStaticType(ir.Expression node);
-
/// Adds libraries in [component] to the set of libraries.
///
/// The main method of the first component is used as the main method for the
@@ -176,9 +181,6 @@
/// Returns the defining node for [member].
ir.Member getMemberNode(covariant MemberEntity member);
-
- /// Returns the element type of a async/sync*/async* function.
- DartType getFunctionAsyncOrSyncStarElementType(ir.FunctionNode functionNode);
}
/// Kinds of foreign functions.
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 6c0a91c..9a8c1d1 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -71,6 +71,7 @@
KernelConstantEnvironment _constantEnvironment;
KernelDartTypes _types;
ir.TypeEnvironment _typeEnvironment;
+ ir.ClassHierarchy _classHierarchy;
/// Library environment. Used for fast lookup.
KProgramEnv env = new KProgramEnv();
@@ -413,6 +414,9 @@
if (superClass == targetClass) {
return target;
}
+
+ /// This path is needed for synthetically injected superclasses like
+ /// `Interceptor` and `JavaScriptObject`.
KClassEnv env = classes.getEnv(superClass);
ConstructorEntity constructor = env.lookupConstructor(this, target.name);
if (constructor != null) {
@@ -718,26 +722,16 @@
ir.TypeEnvironment get typeEnvironment {
if (_typeEnvironment == null) {
_typeEnvironment ??= new ir.TypeEnvironment(
- new ir.CoreTypes(env.mainComponent),
- new ir.ClassHierarchy(env.mainComponent));
+ new ir.CoreTypes(env.mainComponent), classHierarchy);
}
return _typeEnvironment;
}
- DartType getStaticType(ir.Expression node) {
- ir.TreeNode enclosingClass = node;
- while (enclosingClass != null && enclosingClass is! ir.Class) {
- enclosingClass = enclosingClass.parent;
+ ir.ClassHierarchy get classHierarchy {
+ if (_classHierarchy == null) {
+ _classHierarchy ??= new ir.ClassHierarchy(env.mainComponent);
}
- try {
- typeEnvironment.thisType =
- enclosingClass is ir.Class ? enclosingClass.thisType : null;
- return getDartType(node.getStaticType(typeEnvironment));
- } catch (e) {
- // The static type computation crashes on type errors. Use `dynamic`
- // as static type.
- return commonElements.dynamicType;
- }
+ return _classHierarchy;
}
Name getName(ir.Name name) {
@@ -783,7 +777,7 @@
return getSetterSelector(node.name);
}
if (node is ir.InvocationExpression) {
- return getInvocationSelector(node);
+ return getInvocationSelector(node.name, node.arguments);
}
throw failedAt(
CURRENT_ELEMENT_SPANNABLE,
@@ -791,8 +785,8 @@
"${node}");
}
- Selector getInvocationSelector(ir.InvocationExpression invocation) {
- Name name = getName(invocation.name);
+ Selector getInvocationSelector(ir.Name irName, ir.Arguments arguments) {
+ Name name = getName(irName);
SelectorKind kind;
if (Selector.isOperatorName(name.text)) {
if (name == Names.INDEX_NAME || name == Names.INDEX_SET_NAME) {
@@ -804,7 +798,7 @@
kind = SelectorKind.CALL;
}
- CallStructure callStructure = getCallStructure(invocation.arguments);
+ CallStructure callStructure = getCallStructure(arguments);
return new Selector(kind, name, callStructure);
}
@@ -1454,27 +1448,6 @@
return _getTypedefNode(typedef);
}
- /// Returns the element type of a async/sync*/async* function.
- @override
- DartType getFunctionAsyncOrSyncStarElementType(ir.FunctionNode functionNode) {
- DartType returnType = getDartType(functionNode.returnType);
- switch (functionNode.asyncMarker) {
- case ir.AsyncMarker.SyncStar:
- return elementEnvironment.getAsyncOrSyncStarElementType(
- AsyncMarker.SYNC_STAR, returnType);
- case ir.AsyncMarker.Async:
- return elementEnvironment.getAsyncOrSyncStarElementType(
- AsyncMarker.ASYNC, returnType);
- case ir.AsyncMarker.AsyncStar:
- return elementEnvironment.getAsyncOrSyncStarElementType(
- AsyncMarker.ASYNC_STAR, returnType);
- default:
- failedAt(CURRENT_ELEMENT_SPANNABLE,
- "Unexpected ir.AsyncMarker: ${functionNode.asyncMarker}");
- }
- return null;
- }
-
/// Returns `true` is [node] has a `@Native(...)` annotation.
// TODO(johnniwinther): Cache this for later use.
bool isNativeClass(ir.Class node) {
@@ -1698,46 +1671,6 @@
}
@override
- DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
- // TODO(sra): Should be getting the DartType from the node.
- DartType returnType = getFunctionType(function).returnType;
- return getAsyncOrSyncStarElementType(function.asyncMarker, returnType);
- }
-
- @override
- DartType getAsyncOrSyncStarElementType(
- AsyncMarker asyncMarker, DartType returnType) {
- switch (asyncMarker) {
- case AsyncMarker.SYNC:
- return returnType;
- case AsyncMarker.SYNC_STAR:
- if (returnType is InterfaceType) {
- if (returnType.element == elementMap.commonElements.iterableClass) {
- return returnType.typeArguments.first;
- }
- }
- return dynamicType;
- case AsyncMarker.ASYNC:
- if (returnType is FutureOrType) return returnType.typeArgument;
- if (returnType is InterfaceType) {
- if (returnType.element == elementMap.commonElements.futureClass) {
- return returnType.typeArguments.first;
- }
- }
- return dynamicType;
- case AsyncMarker.ASYNC_STAR:
- if (returnType is InterfaceType) {
- if (returnType.element == elementMap.commonElements.streamClass) {
- return returnType.typeArguments.first;
- }
- }
- return dynamicType;
- }
- assert(false, 'Unexpected marker ${asyncMarker}');
- return null;
- }
-
- @override
DartType getFieldType(FieldEntity field) {
return elementMap._getFieldType(field);
}
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index a93e7e7..c3b4306 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -2,9 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:front_end/src/api_unstable/dart2js.dart'
- show operatorFromString;
-
import 'package:kernel/ast.dart' as ir;
import '../common.dart';
@@ -14,8 +11,10 @@
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
+import '../ir/runtime_type_analysis.dart';
import '../ir/scope.dart';
import '../ir/static_type.dart';
+import '../ir/impact.dart';
import '../ir/util.dart';
import '../js_backend/annotations.dart';
import '../js_backend/native_data.dart';
@@ -27,22 +26,21 @@
import '../universe/use.dart';
import '../universe/world_builder.dart';
import 'element_map.dart';
-import 'runtime_type_analysis.dart';
-class KernelImpactBuilder extends StaticTypeVisitor {
+class KernelImpactBuilder extends ImpactBuilder {
final ResolutionWorldImpactBuilder impactBuilder;
final KernelToElementMap elementMap;
final DiagnosticReporter reporter;
final CompilerOptions _options;
final MemberEntity currentMember;
- final VariableScopeModel variableScopeModel;
final Set<PragmaAnnotation> _annotations;
KernelImpactBuilder(this.elementMap, this.currentMember, this.reporter,
- this._options, this.variableScopeModel, this._annotations)
+ this._options, VariableScopeModel variableScopeModel, this._annotations)
: this.impactBuilder =
new ResolutionWorldImpactBuilder('${currentMember}'),
- super(elementMap.typeEnvironment);
+ super(elementMap.typeEnvironment, elementMap.classHierarchy,
+ variableScopeModel);
CommonElements get commonElements => elementMap.commonElements;
@@ -53,22 +51,25 @@
bool get inferEffectivelyFinalVariableTypes =>
!_annotations.contains(PragmaAnnotation.disableFinal);
- /// Add a checked-mode type use of [type] if it is not `dynamic`.
- DartType checkType(ir.DartType irType, TypeUseKind kind) {
- DartType type = elementMap.getDartType(irType);
- if (kind != null && !type.isDynamic) {
- switch (kind) {
- case TypeUseKind.PARAMETER_CHECK:
- impactBuilder.registerTypeUse(new TypeUse.parameterCheck(type));
- break;
- case TypeUseKind.IMPLICIT_CAST:
- impactBuilder.registerTypeUse(new TypeUse.implicitCast(type));
- break;
- default:
- throw new UnsupportedError("Unexpected type check kind: $kind");
+ Object _computeReceiverConstraint(
+ ir.DartType receiverType, ClassRelation relation) {
+ if (receiverType is ir.InterfaceType) {
+ if (receiverType.classNode == typeEnvironment.futureOrClass) {
+ // CFE encodes FutureOr as an interface type!
+ return null;
}
+ return new StrongModeConstraint(commonElements, _nativeBasicData,
+ elementMap.getClass(receiverType.classNode), relation);
}
- return type;
+ return null;
+ }
+
+ @override
+ void registerParameterCheck(ir.DartType irType) {
+ DartType type = elementMap.getDartType(irType);
+ if (!type.isDynamic) {
+ impactBuilder.registerTypeUse(new TypeUse.parameterCheck(type));
+ }
}
List<DartType> _getTypeArguments(ir.Arguments arguments) {
@@ -76,34 +77,14 @@
return arguments.types.map(elementMap.getDartType).toList();
}
- /// Add checked-mode type use for the parameter type and constant for the
- /// default value of [parameter].
@override
- void handleParameter(ir.VariableDeclaration parameter) {
- checkType(parameter.type, TypeUseKind.PARAMETER_CHECK);
- }
-
- /// Add checked-mode type use for parameter and return types, and add
- /// constants for default values.
- @override
- void handleSignature(ir.FunctionNode node) {
- for (ir.TypeParameter parameter in node.typeParameters) {
- checkType(parameter.bound, TypeUseKind.PARAMETER_CHECK);
- }
+ void registerLazyField() {
+ impactBuilder.registerFeature(Feature.LAZY_FIELD);
}
@override
void handleField(ir.Field field) {
- checkType(field.type, TypeUseKind.PARAMETER_CHECK);
- if (field.initializer != null) {
- if (!field.isInstanceMember &&
- !field.isConst &&
- field.initializer is! ir.NullLiteral) {
- impactBuilder.registerFeature(Feature.LAZY_FIELD);
- }
- } else {
- impactBuilder.registerConstantLiteral(new NullConstantExpression());
- }
+ super.handleField(field);
if (field.isInstanceMember &&
elementMap.isNativeClass(field.enclosingClass)) {
@@ -126,49 +107,37 @@
}
}
- void handleAsyncMarker(ir.FunctionNode function) {
- ir.AsyncMarker asyncMarker = function.asyncMarker;
- if (asyncMarker == ir.AsyncMarker.Sync) return;
+ @override
+ void registerSyncStar(ir.DartType elementType) {
+ impactBuilder.registerFeature(Feature.SYNC_STAR);
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
+ commonElements.syncStarIterableFactory,
+ const CallStructure.unnamed(1, 1),
+ <DartType>[elementMap.getDartType(elementType)]));
+ }
- DartType elementType =
- elementMap.getFunctionAsyncOrSyncStarElementType(function);
+ @override
+ void registerAsync(ir.DartType elementType) {
+ impactBuilder.registerFeature(Feature.ASYNC);
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
+ commonElements.asyncAwaitCompleterFactory,
+ const CallStructure.unnamed(0, 1),
+ <DartType>[elementMap.getDartType(elementType)]));
+ }
- switch (asyncMarker) {
- case ir.AsyncMarker.SyncStar:
- impactBuilder.registerFeature(Feature.SYNC_STAR);
- impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
- commonElements.syncStarIterableFactory,
- const CallStructure.unnamed(1, 1),
- <DartType>[elementType]));
- break;
-
- case ir.AsyncMarker.Async:
- impactBuilder.registerFeature(Feature.ASYNC);
- var completerFactory = commonElements.asyncAwaitCompleterFactory;
- impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
- completerFactory,
- const CallStructure.unnamed(0, 1),
- <DartType>[elementType]));
- break;
-
- case ir.AsyncMarker.AsyncStar:
- impactBuilder.registerFeature(Feature.ASYNC_STAR);
- impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
- commonElements.asyncStarStreamControllerFactory,
- const CallStructure.unnamed(1, 1),
- <DartType>[elementType]));
- break;
-
- case ir.AsyncMarker.Sync:
- case ir.AsyncMarker.SyncYielding:
- failedAt(CURRENT_ELEMENT_SPANNABLE,
- "Unexpected async marker: ${asyncMarker}");
- }
+ @override
+ void registerAsyncStar(ir.DartType elementType) {
+ impactBuilder.registerFeature(Feature.ASYNC_STAR);
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
+ commonElements.asyncStarStreamControllerFactory,
+ const CallStructure.unnamed(1, 1),
+ <DartType>[elementMap.getDartType(elementType)]));
}
@override
void handleProcedure(ir.Procedure procedure) {
- handleAsyncMarker(procedure.function);
+ super.handleProcedure(procedure);
+
MemberEntity member = elementMap.getMember(procedure);
if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
@@ -178,68 +147,71 @@
}
@override
- void handleIntLiteral(ir.IntLiteral node) {
+ void registerIntLiteral(int value) {
impactBuilder.registerConstantLiteral(
- new IntConstantExpression(new BigInt.from(node.value).toUnsigned(64)));
+ new IntConstantExpression(new BigInt.from(value).toUnsigned(64)));
}
@override
- void handleDoubleLiteral(ir.DoubleLiteral node) {
- impactBuilder
- .registerConstantLiteral(new DoubleConstantExpression(node.value));
+ void registerDoubleLiteral(double value) {
+ impactBuilder.registerConstantLiteral(new DoubleConstantExpression(value));
}
@override
- void handleBoolLiteral(ir.BoolLiteral node) {
- impactBuilder
- .registerConstantLiteral(new BoolConstantExpression(node.value));
+ void registerBoolLiteral(bool value) {
+ impactBuilder.registerConstantLiteral(new BoolConstantExpression(value));
}
@override
- void handleStringLiteral(ir.StringLiteral node) {
- impactBuilder
- .registerConstantLiteral(new StringConstantExpression(node.value));
+ void registerStringLiteral(String value) {
+ impactBuilder.registerConstantLiteral(new StringConstantExpression(value));
}
@override
- void handleSymbolLiteral(ir.SymbolLiteral node) {
- impactBuilder.registerConstSymbolName(node.value);
+ void registerSymbolLiteral(String value) {
+ impactBuilder.registerConstSymbolName(value);
}
@override
- void handleNullLiteral(ir.NullLiteral node) {
+ void registerNullLiteral() {
impactBuilder.registerConstantLiteral(new NullConstantExpression());
}
@override
- void handleListLiteral(ir.ListLiteral node) {
- DartType elementType = elementMap.getDartType(node.typeArgument);
-
+ void registerListLiteral(ir.DartType elementType,
+ {bool isConstant, bool isEmpty}) {
impactBuilder.registerListLiteral(new ListLiteralUse(
- commonElements.listType(elementType),
- isConstant: node.isConst,
- isEmpty: node.expressions.isEmpty));
+ commonElements.listType(elementMap.getDartType(elementType)),
+ isConstant: isConstant,
+ isEmpty: isEmpty));
}
@override
- void handleMapLiteral(ir.MapLiteral node) {
- DartType keyType = elementMap.getDartType(node.keyType);
- DartType valueType = elementMap.getDartType(node.valueType);
+ void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
+ {bool isConstant, bool isEmpty}) {
impactBuilder.registerMapLiteral(new MapLiteralUse(
- commonElements.mapType(keyType, valueType),
- isConstant: node.isConst,
- isEmpty: node.entries.isEmpty));
+ commonElements.mapType(
+ elementMap.getDartType(keyType), elementMap.getDartType(valueType)),
+ isConstant: isConstant,
+ isEmpty: isEmpty));
}
@override
- void handleConstructorInvocation(ir.ConstructorInvocation node,
- ArgumentTypes argumentTypes, ir.DartType resultType) {
- handleNew(node, node.target, isConst: node.isConst);
- }
-
- void handleNew(ir.InvocationExpression node, ir.Member target,
- {bool isConst: false}) {
+ void registerNew(ir.Member target, ir.InterfaceType type,
+ ir.Arguments arguments, ir.LibraryDependency import,
+ {bool isConst}) {
ConstructorEntity constructor = elementMap.getConstructor(target);
+ CallStructure callStructure = elementMap.getCallStructure(arguments);
+ ImportEntity deferredImport = elementMap.getImport(import);
+ impactBuilder.registerStaticUse(isConst
+ ? new StaticUse.constConstructorInvoke(constructor, callStructure,
+ elementMap.getDartType(type), deferredImport)
+ : new StaticUse.typedConstructorInvoke(constructor, callStructure,
+ elementMap.getDartType(type), deferredImport));
+ if (type.typeArguments.any((ir.DartType type) => type is! ir.DynamicType)) {
+ impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK);
+ }
+
if (commonElements.isSymbolConstructor(constructor)) {
impactBuilder.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
}
@@ -252,21 +224,9 @@
// return here.
}
- InterfaceType type = elementMap.createInterfaceType(
- target.enclosingClass, node.arguments.types);
- CallStructure callStructure = elementMap.getCallStructure(node.arguments);
- ImportEntity deferredImport = elementMap.getImport(getDeferredImport(node));
- impactBuilder.registerStaticUse(isConst
- ? new StaticUse.constConstructorInvoke(
- constructor, callStructure, type, deferredImport)
- : new StaticUse.typedConstructorInvoke(
- constructor, callStructure, type, deferredImport));
- if (type.typeArguments.any((DartType type) => !type.isDynamic)) {
- impactBuilder.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK);
- }
if (isConst && commonElements.isSymbolConstructor(constructor)) {
ConstantValue value =
- elementMap.getConstantValue(node.arguments.positional.first);
+ elementMap.getConstantValue(arguments.positional.first);
if (!value.isString) {
// TODO(het): Get the actual span for the Symbol constructor argument
reporter.reportErrorMessage(
@@ -281,59 +241,38 @@
}
@override
- Null handleSuperInitializer(
- ir.SuperInitializer node, ArgumentTypes argumentTypes) {
+ void registerSuperInitializer(
+ ir.Constructor source, ir.Constructor target, ir.Arguments arguments) {
// TODO(johnniwinther): Maybe rewrite `node.target` to point to a
// synthesized unnamed mixin constructor when needed. This would require us
// to consider impact building a required pre-step for inference and
// ssa-building.
- ConstructorEntity target =
- elementMap.getSuperConstructor(node.parent, node.target);
+ ConstructorEntity constructor =
+ elementMap.getSuperConstructor(source, target);
impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
- target, elementMap.getCallStructure(node.arguments)));
+ constructor, elementMap.getCallStructure(arguments)));
+ }
+
+ @override
+ void registerStaticInvocation(ir.Procedure procedure, ir.Arguments arguments,
+ ir.LibraryDependency import) {
+ FunctionEntity target = elementMap.getMethod(procedure);
+ CallStructure callStructure = elementMap.getCallStructure(arguments);
+ List<DartType> typeArguments = _getTypeArguments(arguments);
+ if (commonElements.isExtractTypeArguments(target)) {
+ _handleExtractTypeArguments(target, typeArguments, callStructure);
+ return;
+ } else {
+ ImportEntity deferredImport = elementMap.getImport(import);
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
+ target, callStructure, typeArguments, deferredImport));
+ }
}
void handleStaticInvocation(ir.StaticInvocation node,
ArgumentTypes argumentTypes, ir.DartType returnType) {
- if (node.target.kind == ir.ProcedureKind.Factory) {
- // TODO(johnniwinther): We should not mark the type as instantiated but
- // rather follow the type arguments directly.
- //
- // Consider this:
- //
- // abstract class A<T> {
- // factory A.regular() => new B<T>();
- // factory A.redirect() = B<T>;
- // }
- //
- // class B<T> implements A<T> {}
- //
- // main() {
- // print(new A<int>.regular() is B<int>);
- // print(new A<String>.redirect() is B<String>);
- // }
- //
- // To track that B is actually instantiated as B<int> and B<String> we
- // need to follow the type arguments passed to A.regular and A.redirect
- // to B. Currently, we only do this soundly if we register A<int> and
- // A<String> as instantiated. We should instead register that A.T is
- // instantiated as int and String.
- handleNew(node, node.target, isConst: node.isConst);
- } else {
- FunctionEntity target = elementMap.getMethod(node.target);
- List<DartType> typeArguments = _getTypeArguments(node.arguments);
- if (commonElements.isExtractTypeArguments(target)) {
- _handleExtractTypeArguments(node, target, typeArguments);
- return;
- }
- ImportEntity deferredImport =
- elementMap.getImport(getDeferredImport(node));
- impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
- target,
- elementMap.getCallStructure(node.arguments),
- typeArguments,
- deferredImport));
- }
+ super.handleStaticInvocation(node, argumentTypes, returnType);
+
switch (elementMap.getForeignKind(node)) {
case ForeignKind.JS:
impactBuilder
@@ -359,8 +298,8 @@
}
}
- void _handleExtractTypeArguments(ir.StaticInvocation node,
- FunctionEntity target, List<DartType> typeArguments) {
+ void _handleExtractTypeArguments(FunctionEntity target,
+ List<DartType> typeArguments, CallStructure callStructure) {
// extractTypeArguments<Map>(obj, fn) has additional impacts:
//
// 1. All classes implementing Map need to carry type arguments (similar
@@ -368,8 +307,8 @@
//
// 2. There is an invocation of fn with some number of type arguments.
//
- impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
- target, elementMap.getCallStructure(node.arguments), typeArguments));
+ impactBuilder.registerStaticUse(
+ new StaticUse.staticInvoke(target, callStructure, typeArguments));
if (typeArguments.length != 1) return;
DartType matchedType = typeArguments.first;
@@ -388,27 +327,26 @@
}
@override
- void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {
- ir.Member target = node.target;
- if (target is ir.Procedure && target.kind == ir.ProcedureKind.Method) {
- FunctionEntity method = elementMap.getMethod(target);
- impactBuilder.registerStaticUse(new StaticUse.staticTearOff(
- method, elementMap.getImport(getDeferredImport(node))));
- } else {
- MemberEntity member = elementMap.getMember(target);
- impactBuilder.registerStaticUse(new StaticUse.staticGet(
- member, elementMap.getImport(getDeferredImport(node))));
- }
+ void registerStaticTearOff(
+ ir.Procedure procedure, ir.LibraryDependency import) {
+ impactBuilder.registerStaticUse(new StaticUse.staticTearOff(
+ elementMap.getMethod(procedure), elementMap.getImport(import)));
}
@override
- void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
- MemberEntity member = elementMap.getMember(node.target);
- impactBuilder.registerStaticUse(new StaticUse.staticSet(
- member, elementMap.getImport(getDeferredImport(node))));
+ void registerStaticGet(ir.Member member, ir.LibraryDependency import) {
+ impactBuilder.registerStaticUse(new StaticUse.staticGet(
+ elementMap.getMember(member), elementMap.getImport(import)));
}
- void handleSuperInvocation(ir.Name name, ir.Node arguments) {
+ @override
+ void registerStaticSet(ir.Member member, ir.LibraryDependency import) {
+ impactBuilder.registerStaticUse(new StaticUse.staticSet(
+ elementMap.getMember(member), elementMap.getImport(import)));
+ }
+
+ @override
+ void registerSuperInvocation(ir.Name name, ir.Arguments arguments) {
FunctionEntity method =
elementMap.getSuperMember(currentMember, name, setter: false);
List<DartType> typeArguments = _getTypeArguments(arguments);
@@ -424,34 +362,7 @@
}
@override
- void handleDirectMethodInvocation(
- ir.DirectMethodInvocation node,
- ir.DartType receiverType,
- ArgumentTypes argumentTypes,
- ir.DartType returnType) {
- List<DartType> typeArguments = _getTypeArguments(node.arguments);
- MemberEntity member = elementMap.getMember(node.target);
- // TODO(johnniwinther): Restrict the dynamic use to only match the known
- // target.
- // TODO(johnniwinther): Restrict this to subclasses?
- Object constraint = new StrongModeConstraint(
- commonElements, _nativeBasicData, member.enclosingClass);
- impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
- new Selector.call(
- member.memberName, elementMap.getCallStructure(node.arguments)),
- constraint,
- typeArguments));
- }
-
- @override
- void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
- ArgumentTypes argumentTypes, ir.DartType returnType) {
- // TODO(johnniwinther): Should we support this or always use the
- // [MixinFullResolution] transformer?
- handleSuperInvocation(node.name, node.arguments);
- }
-
- void handleSuperGet(ir.Name name, ir.Member target) {
+ void registerSuperGet(ir.Name name) {
MemberEntity member =
elementMap.getSuperMember(currentMember, name, setter: false);
if (member != null) {
@@ -469,21 +380,7 @@
}
@override
- void handleDirectPropertyGet(ir.DirectPropertyGet node,
- ir.DartType receiverType, ir.DartType resultType) {
- // TODO(johnniwinther): Restrict the dynamic use to only match the known
- // target.
- impactBuilder.registerDynamicUse(new DynamicUse(
- new Selector.getter(elementMap.getMember(node.target).memberName)));
- }
-
- @override
- void handleSuperPropertyGet(
- ir.SuperPropertyGet node, ir.DartType resultType) {
- handleSuperGet(node.name, node.interfaceTarget);
- }
-
- void handleSuperSet(ir.Name name, ir.Node target, ir.Node value) {
+ void registerSuperSet(ir.Name name) {
MemberEntity member =
elementMap.getSuperMember(currentMember, name, setter: true);
if (member != null) {
@@ -501,275 +398,235 @@
}
@override
- void handleDirectPropertySet(ir.DirectPropertySet node,
- ir.DartType receiverType, ir.DartType valueType) {
- // TODO(johnniwinther): Restrict the dynamic use to only match the known
- // target.
- impactBuilder.registerDynamicUse(new DynamicUse(
- new Selector.setter(elementMap.getMember(node.target).memberName)));
+ void registerLocalFunctionInvocation(
+ ir.FunctionDeclaration localFunction, ir.Arguments arguments) {
+ CallStructure callStructure = elementMap.getCallStructure(arguments);
+ List<DartType> typeArguments = _getTypeArguments(arguments);
+ // Invocation of a local function. No need for dynamic use, but
+ // we need to track the type arguments.
+ impactBuilder.registerStaticUse(new StaticUse.closureCall(
+ elementMap.getLocalFunction(localFunction),
+ callStructure,
+ typeArguments));
+ // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove
+ // this when kernel adds an `isFunctionCall` flag to
+ // [ir.MethodInvocation].
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ callStructure.callSelector, null, typeArguments));
}
@override
- void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
- handleSuperSet(node.name, node.interfaceTarget, node.value);
+ void registerDynamicInvocation(ir.DartType receiverType,
+ ClassRelation relation, ir.Name name, ir.Arguments arguments) {
+ Selector selector = elementMap.getInvocationSelector(name, arguments);
+ List<DartType> typeArguments = _getTypeArguments(arguments);
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(selector,
+ _computeReceiverConstraint(receiverType, relation), typeArguments));
}
@override
- void handleMethodInvocation(
- ir.MethodInvocation node,
- ir.DartType receiverType,
- ArgumentTypes argumentTypes,
- ir.DartType returnType) {
- Selector selector = elementMap.getSelector(node);
- List<DartType> typeArguments = _getTypeArguments(node.arguments);
- ir.Expression receiver = node.receiver;
- if (receiver is ir.VariableGet &&
- receiver.variable.isFinal &&
- receiver.variable.parent is ir.FunctionDeclaration) {
- Local localFunction =
- elementMap.getLocalFunction(receiver.variable.parent);
- // Invocation of a local function. No need for dynamic use, but
- // we need to track the type arguments.
- impactBuilder.registerStaticUse(new StaticUse.closureCall(
- localFunction, selector.callStructure, typeArguments));
- // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove
- // this when kernel adds an `isFunctionCall` flag to
- // [ir.MethodInvocation].
- impactBuilder.registerDynamicUse(
- new ConstrainedDynamicUse(selector, null, typeArguments));
- } else {
- ClassRelation relation = receiver is ir.ThisExpression
- ? ClassRelation.thisExpression
- : ClassRelation.subtype;
- DartType receiverDartType = elementMap.getDartType(receiverType);
- Object constraint;
- if (receiverDartType is InterfaceType) {
- constraint = new StrongModeConstraint(commonElements, _nativeBasicData,
- receiverDartType.element, relation);
- }
- ir.Member interfaceTarget = node.interfaceTarget;
- if (interfaceTarget == null) {
- // TODO(johnniwinther): Avoid treating a known function call as a
- // dynamic call when CFE provides a way to distinguish the two.
- impactBuilder.registerDynamicUse(
- new ConstrainedDynamicUse(selector, constraint, typeArguments));
- if (operatorFromString(node.name.name) == null &&
- receiverDartType.isDynamic) {
- // We might implicitly call a getter that returns a function.
- impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
- selector.toCallSelector(), null, typeArguments));
- }
- } else {
- if (interfaceTarget is ir.Field ||
- interfaceTarget is ir.Procedure &&
- interfaceTarget.kind == ir.ProcedureKind.Getter) {
- impactBuilder.registerDynamicUse(
- new ConstrainedDynamicUse(selector, constraint, typeArguments));
- // An `o.foo()` invocation is (potentially) an `o.foo.call()`
- // invocation.
- Object getterConstraint;
- if (interfaceTarget != null) {
- DartType receiverType =
- elementMap.getDartType(interfaceTarget.getterType);
- if (receiverType is InterfaceType) {
- getterConstraint = new StrongModeConstraint(
- commonElements, _nativeBasicData, receiverType.element);
+ void registerFunctionInvocation(
+ ir.DartType receiverType, ir.Arguments arguments) {
+ CallStructure callStructure = elementMap.getCallStructure(arguments);
+ List<DartType> typeArguments = _getTypeArguments(arguments);
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ callStructure.callSelector,
+ _computeReceiverConstraint(receiverType, ClassRelation.subtype),
+ typeArguments));
+ }
+
+ @override
+ void registerInstanceInvocation(ir.DartType receiverType,
+ ClassRelation relation, ir.Member target, ir.Arguments arguments) {
+ List<DartType> typeArguments = _getTypeArguments(arguments);
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ elementMap.getInvocationSelector(target.name, arguments),
+ _computeReceiverConstraint(receiverType, relation),
+ typeArguments));
+ }
+
+ @override
+ void registerDynamicGet(
+ ir.DartType receiverType, ClassRelation relation, ir.Name name) {
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ new Selector.getter(elementMap.getName(name)),
+ _computeReceiverConstraint(receiverType, relation),
+ const <DartType>[]));
+ }
+
+ @override
+ void registerInstanceGet(
+ ir.DartType receiverType, ClassRelation relation, ir.Member target) {
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ new Selector.getter(elementMap.getName(target.name)),
+ _computeReceiverConstraint(receiverType, relation),
+ const <DartType>[]));
+ }
+
+ @override
+ void registerDynamicSet(
+ ir.DartType receiverType, ClassRelation relation, ir.Name name) {
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ new Selector.setter(elementMap.getName(name)),
+ _computeReceiverConstraint(receiverType, relation),
+ const <DartType>[]));
+ }
+
+ @override
+ void registerInstanceSet(
+ ir.DartType receiverType, ClassRelation relation, ir.Member target) {
+ impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+ new Selector.setter(elementMap.getName(target.name)),
+ _computeReceiverConstraint(receiverType, relation),
+ const <DartType>[]));
+ }
+
+ void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
+ ir.DartType receiverType, ir.DartType argumentType) {
+ DartType receiverDartType = elementMap.getDartType(receiverType);
+ DartType argumentDartType =
+ argumentType == null ? null : elementMap.getDartType(argumentType);
+
+ if (_options.omitImplicitChecks) {
+ switch (kind) {
+ case RuntimeTypeUseKind.string:
+ if (!_options.laxRuntimeTypeToString) {
+ if (receiverDartType == commonElements.objectType) {
+ reporter.reportHintMessage(computeSourceSpanFromTreeNode(node),
+ MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT);
+ } else {
+ reporter.reportHintMessage(
+ computeSourceSpanFromTreeNode(node),
+ MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
+ {'receiverType': '${receiverDartType}.'});
}
}
-
- impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
- selector.toCallSelector(), getterConstraint, typeArguments));
- } else {
- impactBuilder.registerDynamicUse(
- new ConstrainedDynamicUse(selector, constraint, typeArguments));
- }
+ break;
+ case RuntimeTypeUseKind.equals:
+ case RuntimeTypeUseKind.unknown:
+ break;
}
}
+ impactBuilder.registerRuntimeTypeUse(
+ new RuntimeTypeUse(kind, receiverDartType, argumentDartType));
}
@override
- void handlePropertyGet(
- ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
- Object constraint;
- DartType receiverDartType = elementMap.getDartType(receiverType);
- if (receiverDartType is InterfaceType) {
- ClassRelation relation = node.receiver is ir.ThisExpression
- ? ClassRelation.thisExpression
- : ClassRelation.subtype;
- constraint = new StrongModeConstraint(
- commonElements, _nativeBasicData, receiverDartType.element, relation);
- }
- impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
- new Selector.getter(elementMap.getName(node.name)),
- constraint, const <DartType>[]));
-
- if (node.name.name == Identifiers.runtimeType_) {
- RuntimeTypeUse runtimeTypeUse = computeRuntimeTypeUse(elementMap, node);
- if (_options.omitImplicitChecks) {
- switch (runtimeTypeUse.kind) {
- case RuntimeTypeUseKind.string:
- if (!_options.laxRuntimeTypeToString) {
- if (runtimeTypeUse.receiverType == commonElements.objectType) {
- reporter.reportHintMessage(computeSourceSpanFromTreeNode(node),
- MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT);
- } else {
- reporter.reportHintMessage(
- computeSourceSpanFromTreeNode(node),
- MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
- {'receiverType': '${runtimeTypeUse.receiverType}.'});
- }
- }
- break;
- case RuntimeTypeUseKind.equals:
- case RuntimeTypeUseKind.unknown:
- break;
- }
- }
- impactBuilder.registerRuntimeTypeUse(runtimeTypeUse);
- }
- }
-
- @override
- void handlePropertySet(
- ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
- Object constraint;
- DartType receiverDartType = elementMap.getDartType(receiverType);
- if (receiverDartType is InterfaceType) {
- ClassRelation relation = node.receiver is ir.ThisExpression
- ? ClassRelation.thisExpression
- : ClassRelation.subtype;
- constraint = new StrongModeConstraint(
- commonElements, _nativeBasicData, receiverDartType.element, relation);
- }
- impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
- new Selector.setter(elementMap.getName(node.name)),
- constraint, const <DartType>[]));
- }
-
- @override
- void handleAssertStatement(ir.AssertStatement node) {
+ void registerAssert({bool withMessage}) {
impactBuilder.registerFeature(
- node.message != null ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
+ withMessage ? Feature.ASSERT_WITH_MESSAGE : Feature.ASSERT);
}
@override
- void handleInstantiation(ir.Instantiation node,
- ir.FunctionType expressionType, ir.DartType resultType) {
+ void registerGenericInstantiation(
+ ir.FunctionType expressionType, List<ir.DartType> typeArguments) {
// TODO(johnniwinther): Track which arities are used in instantiation.
impactBuilder.registerInstantiation(new GenericInstantiation(
elementMap.getDartType(expressionType),
- node.typeArguments.map(elementMap.getDartType).toList()));
+ typeArguments.map(elementMap.getDartType).toList()));
}
@override
- void handleStringConcatenation(ir.StringConcatenation node) {
+ void registerStringConcatenation() {
impactBuilder.registerFeature(Feature.STRING_INTERPOLATION);
impactBuilder.registerFeature(Feature.STRING_JUXTAPOSITION);
}
@override
- Null handleFunctionDeclaration(ir.FunctionDeclaration node) {
+ void registerLocalFunction(ir.TreeNode node) {
Local function = elementMap.getLocalFunction(node);
impactBuilder.registerStaticUse(new StaticUse.closure(function));
- handleAsyncMarker(node.function);
}
@override
- void handleFunctionExpression(ir.FunctionExpression node) {
- Local function = elementMap.getLocalFunction(node);
- impactBuilder.registerStaticUse(new StaticUse.closure(function));
- handleAsyncMarker(node.function);
+ void registerLocalWithoutInitializer() {
+ impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
}
@override
- void handleVariableDeclaration(ir.VariableDeclaration node) {
- if (node.initializer == null) {
- impactBuilder.registerFeature(Feature.LOCAL_WITHOUT_INITIALIZER);
- }
+ void registerIsCheck(ir.DartType type) {
+ impactBuilder
+ .registerTypeUse(new TypeUse.isCheck(elementMap.getDartType(type)));
}
@override
- void handleIsExpression(ir.IsExpression node) {
+ void registerImplicitCast(ir.DartType type) {
impactBuilder.registerTypeUse(
- new TypeUse.isCheck(elementMap.getDartType(node.type)));
+ new TypeUse.implicitCast(elementMap.getDartType(type)));
}
@override
- void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {
- if (elementMap.typeEnvironment.isSubtypeOf(operandType, node.type)) {
- // Skip unneeded casts.
- return;
- }
- DartType type = elementMap.getDartType(node.type);
- if (node.isTypeError) {
- impactBuilder.registerTypeUse(new TypeUse.implicitCast(type));
- } else {
- impactBuilder.registerTypeUse(new TypeUse.asCast(type));
- }
+ void registerAsCast(ir.DartType type) {
+ impactBuilder
+ .registerTypeUse(new TypeUse.asCast(elementMap.getDartType(type)));
}
@override
- void handleThrow(ir.Throw node) {
+ @override
+ void registerThrow() {
impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
}
- @override
- void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {
+ void registerSyncForIn(ir.DartType iterableType) {
// TODO(johnniwinther): Use receiver constraints for the dynamic uses in
// strong mode.
- if (node.isAsync) {
- impactBuilder.registerFeature(Feature.ASYNC_FOR_IN);
- impactBuilder.registerDynamicUse(new DynamicUse(Selectors.cancel));
- } else {
- impactBuilder.registerFeature(Feature.SYNC_FOR_IN);
- impactBuilder.registerDynamicUse(new DynamicUse(Selectors.iterator));
- }
+ impactBuilder.registerFeature(Feature.SYNC_FOR_IN);
+ impactBuilder.registerDynamicUse(new DynamicUse(Selectors.iterator));
impactBuilder.registerDynamicUse(new DynamicUse(Selectors.current));
impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
}
- @override
- void handleCatch(ir.Catch node) {
+ void registerAsyncForIn(ir.DartType iterableType) {
+ // TODO(johnniwinther): Use receiver constraints for the dynamic uses in
+ // strong mode.
+ impactBuilder.registerFeature(Feature.ASYNC_FOR_IN);
+ impactBuilder.registerDynamicUse(new DynamicUse(Selectors.cancel));
+ impactBuilder.registerDynamicUse(new DynamicUse(Selectors.current));
+ impactBuilder.registerDynamicUse(new DynamicUse(Selectors.moveNext));
+ }
+
+ void registerCatch() {
impactBuilder.registerFeature(Feature.CATCH_STATEMENT);
- if (node.stackTrace != null) {
- impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
- }
- if (node.guard is! ir.DynamicType) {
- impactBuilder.registerTypeUse(
- new TypeUse.catchType(elementMap.getDartType(node.guard)));
- }
+ }
+
+ void registerStackTrace() {
+ impactBuilder.registerFeature(Feature.STACK_TRACE_IN_CATCH);
+ }
+
+ void registerCatchType(ir.DartType type) {
+ impactBuilder
+ .registerTypeUse(new TypeUse.catchType(elementMap.getDartType(type)));
}
@override
- void handleTypeLiteral(ir.TypeLiteral node) {
- ImportEntity deferredImport = elementMap.getImport(getDeferredImport(node));
- impactBuilder.registerTypeUse(new TypeUse.typeLiteral(
- elementMap.getDartType(node.type), deferredImport));
- if (node.type is ir.FunctionType) {
- ir.FunctionType functionType = node.type;
- assert(functionType.typedef != null);
+ void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import) {
+ ImportEntity deferredImport = elementMap.getImport(import);
+ impactBuilder.registerTypeUse(
+ new TypeUse.typeLiteral(elementMap.getDartType(type), deferredImport));
+ if (type is ir.FunctionType) {
+ assert(type.typedef != null);
// TODO(johnniwinther): Can we avoid the typedef type altogether?
// We need to ensure that the typedef is live.
- elementMap.getTypedefType(functionType.typedef);
+ elementMap.getTypedefType(type.typedef);
}
}
@override
- void handleFieldInitializer(ir.FieldInitializer node) {
- impactBuilder.registerStaticUse(
- new StaticUse.fieldInit(elementMap.getField(node.field)));
+ void registerFieldInitializer(ir.Field node) {
+ impactBuilder
+ .registerStaticUse(new StaticUse.fieldInit(elementMap.getField(node)));
}
@override
- void handleRedirectingInitializer(
- ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
- ConstructorEntity target = elementMap.getConstructor(node.target);
+ void registerRedirectingInitializer(
+ ir.Constructor constructor, ir.Arguments arguments) {
+ ConstructorEntity target = elementMap.getConstructor(constructor);
impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
- target, elementMap.getCallStructure(node.arguments)));
+ target, elementMap.getCallStructure(arguments)));
}
@override
- void handleLoadLibrary(ir.LoadLibrary node) {
+ void registerLoadLibrary() {
impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
commonElements.loadDeferredLibrary, CallStructure.ONE_ARG));
impactBuilder.registerFeature(Feature.LOAD_LIBRARY);
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index 4d14f55..19891b3 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -72,7 +72,8 @@
new Dart2jsTarget(targetName, new TargetFlags()),
_options.librariesSpecificationUri,
_options.platformBinaries.resolve(platform),
- _options.packageConfig);
+ _options.packageConfig,
+ experimentalFlags: _options.languageExperiments);
component = await fe.compile(
initializedCompilerState,
false,
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index a437151..61900e4 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -94,36 +94,34 @@
int get index => values.indexOf(this);
}
-/**
- * A summary of the behavior of a native element.
- *
- * Native code can return values of one type and cause native subtypes of
- * another type to be instantiated. By default, we compute both from the
- * declared type.
- *
- * A field might yield any native type that 'is' the field type.
- *
- * A method might create and return instances of native subclasses of its
- * declared return type, and a callback argument may be called with instances of
- * the callback parameter type (e.g. Event).
- *
- * If there is one or more `@Creates` annotations, the union of the named types
- * replaces the inferred instantiated type, and the return type is ignored for
- * the purpose of inferring instantiated types.
- *
- * @Creates('IDBCursor') // Created asynchronously.
- * @Creates('IDBRequest') // Created synchronously (for return value).
- * IDBRequest openCursor();
- *
- * If there is one or more `@Returns` annotations, the union of the named types
- * replaces the declared return type.
- *
- * @Returns('IDBRequest')
- * IDBRequest openCursor();
- *
- * Types in annotations are non-nullable, so include `@Returns('Null')` if
- * `null` may be returned.
- */
+/// A summary of the behavior of a native element.
+///
+/// Native code can return values of one type and cause native subtypes of
+/// another type to be instantiated. By default, we compute both from the
+/// declared type.
+///
+/// A field might yield any native type that 'is' the field type.
+///
+/// A method might create and return instances of native subclasses of its
+/// declared return type, and a callback argument may be called with instances
+/// of the callback parameter type (e.g. Event).
+///
+/// If there is one or more `@Creates` annotations, the union of the named types
+/// replaces the inferred instantiated type, and the return type is ignored for
+/// the purpose of inferring instantiated types.
+///
+/// @Creates('IDBCursor') // Created asynchronously.
+/// @Creates('IDBRequest') // Created synchronously (for return value).
+/// IDBRequest openCursor();
+///
+/// If there is one or more `@Returns` annotations, the union of the named types
+/// replaces the declared return type.
+///
+/// @Returns('IDBRequest')
+/// IDBRequest openCursor();
+///
+/// Types in annotations are non-nullable, so include `@Returns('Null')` if
+/// `null` may be returned.
class NativeBehavior {
/// Tag used for identifying serialized [NativeBehavior] objects in a
/// debugging data stream.
@@ -742,11 +740,9 @@
}
}
- /**
- * Returns a list of type constraints from the annotations of
- * [annotationClass].
- * Returns `null` if no constraints.
- */
+ /// Returns a list of type constraints from the annotations of
+ /// [annotationClass].
+ /// Returns `null` if no constraints.
List _collect(Iterable<ConstantValue> metadata, ClassEntity annotationClass,
TypeLookup lookupType) {
var types = null;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index a3a1dd2..dfd4b8f 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -14,9 +14,8 @@
import 'behavior.dart';
import 'resolver.dart' show NativeClassFinder;
-/**
- * This could be an abstract class but we use it as a stub for the dart_backend.
- */
+/// This could be an abstract class but we use it as a stub for the
+/// dart_backend.
class NativeEnqueuer {
/// Called when a [type] has been instantiated natively.
void onInstantiatedType(InterfaceType type) {}
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 41c32cc..89e4c55 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -70,6 +70,9 @@
/// flags.
Map<String, String> environment = const <String, String>{};
+ /// Flags enabling language experiments.
+ Map<fe.ExperimentalFlag, bool> languageExperiments = {};
+
/// A possibly null state object for kernel compilation.
fe.InitializedCompilerState kernelInitializedCompilerState;
@@ -170,6 +173,11 @@
// TODO(sigmund): rename to minify
bool enableMinification = false;
+ /// Flag to turn off minification even if enabled elsewhere, e.g. via
+ /// -O2. Both [enableMinification] and [_disableMinification] can be true, in
+ /// which case [_disableMinification] wins.
+ bool _disableMinification = false;
+
/// Whether to model which native classes are live based on annotations on the
/// core libraries. If false, all native classes will be included by default.
bool enableNativeLiveTypeAnalysis = true;
@@ -244,10 +252,6 @@
/// (experimental)
bool useNewSourceInfo = false;
- /// Whether the user requested to use the fast startup emitter. The full
- /// emitter might still be used if the program uses dart:mirrors.
- bool useStartupEmitter = false;
-
/// Enable verbose printing during compilation. Includes a time-breakdown
/// between phases at the end.
bool verbose = false;
@@ -312,6 +316,7 @@
..suppressHints = _hasOption(options, Flags.suppressHints)
..shownPackageWarnings =
_extractOptionalCsvOption(options, Flags.showPackageWarnings)
+ ..languageExperiments = _extractExperiments(options)
..disableInlining = _hasOption(options, Flags.disableInlining)
..disableProgramSplit = _hasOption(options, Flags.disableProgramSplit)
..disableTypeInference = _hasOption(options, Flags.disableTypeInference)
@@ -323,6 +328,7 @@
..enableExperimentalMirrors =
_hasOption(options, Flags.enableExperimentalMirrors)
..enableMinification = _hasOption(options, Flags.minify)
+ .._disableMinification = _hasOption(options, Flags.noMinify)
..enableNativeLiveTypeAnalysis =
!_hasOption(options, Flags.disableNativeLiveTypeAnalysis)
..enableUserAssertions = _hasOption(options, Flags.enableCheckedMode) ||
@@ -358,7 +364,6 @@
!_hasOption(options, Flags.noFrequencyBasedMinification)
..useMultiSourceInfo = _hasOption(options, Flags.useMultiSourceInfo)
..useNewSourceInfo = _hasOption(options, Flags.useNewSourceInfo)
- ..useStartupEmitter = _hasOption(options, Flags.fastStartup)
..verbose = _hasOption(options, Flags.verbose)
..showInternalProgress = _hasOption(options, Flags.progress)
..readDataUri = _extractUriOption(options, '${Flags.readData}=')
@@ -391,7 +396,6 @@
void deriveOptions() {
if (benchmarkingProduction) {
- useStartupEmitter = true;
trustPrimitives = true;
omitImplicitChecks = true;
}
@@ -427,6 +431,10 @@
parameterCheckPolicy = CheckPolicy.checked;
implicitDowncastCheckPolicy = CheckPolicy.checked;
}
+
+ if (_disableMinification) {
+ enableMinification = false;
+ }
}
/// Returns `true` if warnings and hints are shown for all packages.
@@ -505,4 +513,11 @@
return null;
}
+Map<fe.ExperimentalFlag, bool> _extractExperiments(List<String> options) {
+ List<String> experiments =
+ _extractOptionalCsvOption(options, Flags.enableLanguageExperiments);
+ return fe.parseExperimentalFlags(
+ experiments, (String error) => throw new ArgumentError(error));
+}
+
const String _UNDETERMINED_BUILD_ID = "build number could not be determined";
diff --git a/pkg/compiler/lib/src/ordered_typeset.dart b/pkg/compiler/lib/src/ordered_typeset.dart
index 57ed4cb..e3b4f3e 100644
--- a/pkg/compiler/lib/src/ordered_typeset.dart
+++ b/pkg/compiler/lib/src/ordered_typeset.dart
@@ -13,23 +13,21 @@
import 'elements/types.dart';
import 'serialization/serialization.dart';
-/**
- * An ordered set of the supertypes of a class. The supertypes of a class are
- * ordered by decreasing hierarchy depth and by the order they are extended,
- * mixed in, or implemented.
- *
- * For these classes
- *
- * class A {} // Depth = 1.
- * class B {} // Depth = 1.
- * class C extends B implements A {} // Depth 2.
- *
- * the ordered supertypes are
- *
- * A: [A, Object]
- * B: [B, Object]
- * C: [C, B, A, Object]
- */
+/// An ordered set of the supertypes of a class. The supertypes of a class are
+/// ordered by decreasing hierarchy depth and by the order they are extended,
+/// mixed in, or implemented.
+///
+/// For these classes
+///
+/// class A {} // Depth = 1.
+/// class B {} // Depth = 1.
+/// class C extends B implements A {} // Depth 2.
+///
+/// the ordered supertypes are
+///
+/// A: [A, Object]
+/// B: [B, Object]
+/// C: [C, B, A, Object]
class OrderedTypeSet {
/// Tag used for identifying serialized [OrderedTypeSet] objects in a
/// debugging data stream.
@@ -198,23 +196,21 @@
String toString() => types.toString();
}
-/**
- * Builder for creation an ordered set of the supertypes of a class. The
- * supertypes are ordered by decreasing hierarchy depth and by the order they
- * are extended, mixed in, or implemented.
- *
- * For these classes
- *
- * class A {} // Depth = 1.
- * class B {} // Depth = 1.
- * class C extends B implements A {} // Depth 2.
- *
- * the ordered supertypes are
- *
- * A: [A, Object]
- * B: [B, Object]
- * C: [C, B, A, Object]
- */
+/// Builder for creation an ordered set of the supertypes of a class. The
+/// supertypes are ordered by decreasing hierarchy depth and by the order they
+/// are extended, mixed in, or implemented.
+///
+/// For these classes
+///
+/// class A {} // Depth = 1.
+/// class B {} // Depth = 1.
+/// class C extends B implements A {} // Depth 2.
+///
+/// the ordered supertypes are
+///
+/// A: [A, Object]
+/// B: [B, Object]
+/// C: [C, B, A, Object]
abstract class OrderedTypeSetBuilder {
OrderedTypeSet createOrderedTypeSet(
InterfaceType supertype, Link<DartType> interfaces);
@@ -257,10 +253,8 @@
return toTypeSet();
}
- /**
- * Adds [type] and all supertypes of [type] to [allSupertypes] while
- * substituting type variables.
- */
+ /// Adds [type] and all supertypes of [type] to [allSupertypes] while
+ /// substituting type variables.
void _addAllSupertypes(InterfaceType type) {
ClassEntity classElement = type.element;
Link<InterfaceType> supertypes = getOrderedTypeSet(classElement).supertypes;
diff --git a/pkg/compiler/lib/src/script.dart b/pkg/compiler/lib/src/script.dart
index 403776b..5adbdae 100644
--- a/pkg/compiler/lib/src/script.dart
+++ b/pkg/compiler/lib/src/script.dart
@@ -9,18 +9,14 @@
class Script {
final SourceFile file;
- /**
- * The readable URI from which this script was loaded.
- *
- * See [LibraryLoader] for terminology on URIs.
- */
+ /// The readable URI from which this script was loaded.
+ ///
+ /// See [LibraryLoader] for terminology on URIs.
final Uri readableUri;
- /**
- * The resource URI from which this script was loaded.
- *
- * See [LibraryLoader] for terminology on URIs.
- */
+ /// The resource URI from which this script was loaded.
+ ///
+ /// See [LibraryLoader] for terminology on URIs.
final Uri resourceUri;
/// This script was synthesized.
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index 28da0ca..28fdf8a 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -219,6 +219,8 @@
return const ir.InvalidType();
case DartTypeNodeKind.bottomType:
return const ir.BottomType();
+ case DartTypeNodeKind.doesNotComplete:
+ return const DoesNotCompleteType();
case DartTypeNodeKind.typeParameterType:
ir.TypeParameter typeParameter = readTypeParameterNode();
ir.DartType promotedBound = _readDartTypeNode(functionTypeVariables);
@@ -270,6 +272,16 @@
List<ir.DartType> typeArguments =
_readDartTypeNodes(functionTypeVariables);
return new ir.InterfaceType(cls, typeArguments);
+ case DartTypeNodeKind.thisInterfaceType:
+ ir.Class cls = readClassNode();
+ List<ir.DartType> typeArguments =
+ _readDartTypeNodes(functionTypeVariables);
+ return new ThisInterfaceType(cls, typeArguments);
+ case DartTypeNodeKind.exactInterfaceType:
+ ir.Class cls = readClassNode();
+ List<ir.DartType> typeArguments =
+ _readDartTypeNodes(functionTypeVariables);
+ return new ExactInterfaceType(cls, typeArguments);
case DartTypeNodeKind.typedef:
ir.Typedef typedef = readTypedefNode();
List<ir.DartType> typeArguments =
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 589c6eef..a75b7e3 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -90,7 +90,7 @@
interfaceType,
typedef,
dynamicType,
- futureOr
+ futureOr,
}
/// Visitor that serializes [DartType] object together with [AbstractDataSink].
@@ -194,6 +194,9 @@
dynamicType,
bottomType,
invalidType,
+ thisInterfaceType,
+ exactInterfaceType,
+ doesNotComplete,
}
const String functionTypeNodeTag = 'function-type-node';
@@ -235,12 +238,22 @@
void visitBottomType(
ir.BottomType node, List<ir.TypeParameter> functionTypeVariables) {
- _sink.writeEnum(DartTypeNodeKind.bottomType);
+ if (node == const DoesNotCompleteType()) {
+ _sink.writeEnum(DartTypeNodeKind.doesNotComplete);
+ } else {
+ _sink.writeEnum(DartTypeNodeKind.bottomType);
+ }
}
void visitInterfaceType(
ir.InterfaceType node, List<ir.TypeParameter> functionTypeVariables) {
- _sink.writeEnum(DartTypeNodeKind.interfaceType);
+ if (node is ThisInterfaceType) {
+ _sink.writeEnum(DartTypeNodeKind.thisInterfaceType);
+ } else if (node is ExactInterfaceType) {
+ _sink.writeEnum(DartTypeNodeKind.exactInterfaceType);
+ } else {
+ _sink.writeEnum(DartTypeNodeKind.interfaceType);
+ }
_sink.writeClassNode(node.classNode);
visitTypes(node.typeArguments, functionTypeVariables);
}
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 2d2fd9b..3348edd 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -14,6 +14,7 @@
import '../elements/entities.dart';
import '../elements/indexed.dart';
import '../elements/types.dart';
+import '../ir/static_type_base.dart';
import '../js_model/closure.dart';
import '../js_model/locals.dart';
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 1c14b38..1674df2 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -4933,10 +4933,8 @@
..cleanUp();
}
- /**
- * Try to inline [element] within the correct context of the builder. The
- * insertion point is the state of the builder.
- */
+ /// Try to inline [element] within the correct context of the builder. The
+ /// insertion point is the state of the builder.
bool _tryInlineMethod(
FunctionEntity function,
Selector selector,
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 9a23841..dc941f4 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -134,26 +134,22 @@
}
class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
- /**
- * Returned by [expressionType] to tell how code can be generated for
- * a subgraph.
- * - [TYPE_STATEMENT] means that the graph must be generated as a statement,
- * which is always possible.
- * - [TYPE_EXPRESSION] means that the graph can be generated as an expression,
- * or possibly several comma-separated expressions.
- * - [TYPE_DECLARATION] means that the graph can be generated as an
- * expression, and that it only generates expressions of the form
- * variable = expression
- * which are also valid as parts of a "var" declaration.
- */
+ /// Returned by [expressionType] to tell how code can be generated for
+ /// a subgraph.
+ /// - [TYPE_STATEMENT] means that the graph must be generated as a statement,
+ /// which is always possible.
+ /// - [TYPE_EXPRESSION] means that the graph can be generated as an expression,
+ /// or possibly several comma-separated expressions.
+ /// - [TYPE_DECLARATION] means that the graph can be generated as an
+ /// expression, and that it only generates expressions of the form
+ /// variable = expression
+ /// which are also valid as parts of a "var" declaration.
static const int TYPE_STATEMENT = 0;
static const int TYPE_EXPRESSION = 1;
static const int TYPE_DECLARATION = 2;
- /**
- * Whether we are currently generating expressions instead of statements.
- * This includes declarations, which are generated as expressions.
- */
+ /// Whether we are currently generating expressions instead of statements.
+ /// This includes declarations, which are generated as expressions.
bool isGeneratingExpression = false;
final CompilerOptions _options;
@@ -180,10 +176,8 @@
List<js.Expression> expressionStack;
List<js.Block> oldContainerStack;
- /**
- * Contains the names of the instructions, as well as the parallel
- * copies to perform on block transitioning.
- */
+ /// Contains the names of the instructions, as well as the parallel
+ /// copies to perform on block transitioning.
VariableNames variableNames;
/// `true` when we need to generate a `var` declaration at function entry,
@@ -191,17 +185,13 @@
/// middle of the function.
bool shouldGroupVarDeclarations = false;
- /**
- * While generating expressions, we can't insert variable declarations.
- * Instead we declare them at the start of the function. When minifying
- * we do this most of the time, because it reduces the size unless there
- * is only one variable.
- */
+ /// While generating expressions, we can't insert variable declarations.
+ /// Instead we declare them at the start of the function. When minifying
+ /// we do this most of the time, because it reduces the size unless there
+ /// is only one variable.
final Set<String> collectedVariableDeclarations;
- /**
- * Set of variables and parameters that have already been declared.
- */
+ /// Set of variables and parameters that have already been declared.
final Set<String> declaredLocals;
HGraph currentGraph;
@@ -332,10 +322,8 @@
return hasNonBitOpUser(instruction, new Set<HPhi>());
}
- /**
- * If the [instruction] is not `null` it will be used to attach the position
- * to the [statement].
- */
+ /// If the [instruction] is not `null` it will be used to attach the position
+ /// to the [statement].
void pushStatement(js.Statement statement) {
assert(expressionStack.isEmpty);
currentContainer.statements.add(statement);
@@ -345,20 +333,16 @@
currentContainer.statements.insert(0, statement);
}
- /**
- * If the [instruction] is not `null` it will be used to attach the position
- * to the [expression].
- */
+ /// If the [instruction] is not `null` it will be used to attach the position
+ /// to the [expression].
pushExpressionAsStatement(
js.Expression expression, SourceInformation sourceInformation) {
pushStatement(new js.ExpressionStatement(expression)
.withSourceInformation(sourceInformation));
}
- /**
- * If the [instruction] is not `null` it will be used to attach the position
- * to the [expression].
- */
+ /// If the [instruction] is not `null` it will be used to attach the position
+ /// to the [expression].
push(js.Expression expression) {
expressionStack.add(expression);
}
@@ -507,15 +491,13 @@
subGraph = oldSubGraph;
}
- /**
- * Check whether a sub-graph can be generated as an expression, or even
- * as a declaration, or if it has to fall back to being generated as
- * a statement.
- * Expressions are anything that doesn't generate control flow constructs.
- * Declarations must only generate assignments on the form "id = expression",
- * and not, e.g., expressions where the value isn't assigned, or where it's
- * assigned to something that's not a simple variable.
- */
+ /// Check whether a sub-graph can be generated as an expression, or even
+ /// as a declaration, or if it has to fall back to being generated as
+ /// a statement.
+ /// Expressions are anything that doesn't generate control flow constructs.
+ /// Declarations must only generate assignments on the form "id = expression",
+ /// and not, e.g., expressions where the value isn't assigned, or where it's
+ /// assigned to something that's not a simple variable.
int expressionType(HExpressionInformation info) {
// The only HExpressionInformation used as part of a HBlockInformation is
// current HSubExpressionBlockInformation, so it's the only one reaching
@@ -580,12 +562,10 @@
(limits.end.last is HConditionalBranch);
}
- /**
- * Generate statements from block information.
- * If the block information contains expressions, generate only
- * assignments, and if it ends in a conditional branch, don't generate
- * the condition.
- */
+ /// Generate statements from block information.
+ /// If the block information contains expressions, generate only
+ /// assignments, and if it ends in a conditional branch, don't generate
+ /// the condition.
void generateStatements(HBlockInformation block) {
if (block is HStatementInformation) {
block.accept(this);
@@ -604,12 +584,10 @@
return result;
}
- /**
- * If the [block] only contains one statement returns that statement. If the
- * that statement itself is a block, recursively calls this method.
- *
- * If the block is empty, returns a new instance of [js.NOP].
- */
+ /// If the [block] only contains one statement returns that statement. If the
+ /// that statement itself is a block, recursively calls this method.
+ ///
+ /// If the block is empty, returns a new instance of [js.NOP].
js.Statement unwrapStatement(js.Block block) {
int len = block.statements.length;
if (len == 0) return new js.EmptyStatement();
@@ -621,9 +599,7 @@
return block;
}
- /**
- * Generate expressions from block information.
- */
+ /// Generate expressions from block information.
js.Expression generateExpression(HExpressionInformation expression) {
// Currently we only handle sub-expression graphs.
assert(expression is HSubExpressionBlockInformation);
@@ -651,9 +627,7 @@
}
}
- /**
- * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET].
- */
+ /// Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET].
List<js.Expression> visitArguments(List<HInstruction> inputs,
{int start: HInvoke.ARGUMENTS_OFFSET}) {
assert(inputs.length >= start);
@@ -1331,10 +1305,8 @@
assignVariable(destination, new js.VariableUse(source), sourceInformation);
}
- /**
- * Sequentialize a list of conceptually parallel copies. Parallel
- * copies may contain cycles, that this method breaks.
- */
+ /// Sequentialize a list of conceptually parallel copies. Parallel
+ /// copies may contain cycles, that this method breaks.
void sequentializeCopies(
Iterable<Copy<HInstruction>> instructionCopies,
String tempName,
@@ -2194,7 +2166,10 @@
use(node.receiver);
js.Expression receiver = pop();
use(node.value);
- push(new js.Assignment(new js.PropertyAccess(receiver, name), pop())
+ push(new js.Assignment(
+ new js.PropertyAccess(receiver, name)
+ .withSourceInformation(node.sourceInformation),
+ pop())
.withSourceInformation(node.sourceInformation));
}
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 2fc43bb..78ddc04 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -12,10 +12,8 @@
import '../world.dart' show JClosedWorld;
import 'nodes.dart';
-/**
- * Replaces some instructions with specialized versions to make codegen easier.
- * Caches codegen information on nodes.
- */
+/// Replaces some instructions with specialized versions to make codegen easier.
+/// Caches codegen information on nodes.
class SsaInstructionSelection extends HBaseVisitor {
final JClosedWorld _closedWorld;
final InterceptorData _interceptorData;
@@ -341,10 +339,8 @@
}
}
-/**
- * Remove [HTypeKnown] instructions from the graph, to make codegen
- * analysis easier.
- */
+/// Remove [HTypeKnown] instructions from the graph, to make codegen
+/// analysis easier.
class SsaTypeKnownRemover extends HBaseVisitor {
void visitGraph(HGraph graph) {
visitDominatorTree(graph);
@@ -370,10 +366,8 @@
}
}
-/**
- * Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
- * mode.
- */
+/// Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
+/// mode.
class SsaTrustedCheckRemover extends HBaseVisitor {
final CompilerOptions _options;
@@ -401,29 +395,25 @@
}
}
-/**
- * Instead of emitting each SSA instruction with a temporary variable
- * mark instructions that can be emitted at their use-site.
- * For example, in:
- * t0 = 4;
- * t1 = 3;
- * t2 = add(t0, t1);
- * t0 and t1 would be marked and the resulting code would then be:
- * t2 = add(4, 3);
- */
+/// Instead of emitting each SSA instruction with a temporary variable
+/// mark instructions that can be emitted at their use-site.
+/// For example, in:
+/// t0 = 4;
+/// t1 = 3;
+/// t2 = add(t0, t1);
+/// t0 and t1 would be marked and the resulting code would then be:
+/// t2 = add(4, 3);
class SsaInstructionMerger extends HBaseVisitor {
final AbstractValueDomain _abstractValueDomain;
final SuperMemberData _superMemberData;
- /**
- * List of [HInstruction] that the instruction merger expects in
- * order when visiting the inputs of an instruction.
- */
+
+ /// List of [HInstruction] that the instruction merger expects in
+ /// order when visiting the inputs of an instruction.
List<HInstruction> expectedInputs;
- /**
- * Set of pure [HInstruction] that the instruction merger expects to
- * find. The order of pure instructions do not matter, as they will
- * not be affected by side effects.
- */
+
+ /// Set of pure [HInstruction] that the instruction merger expects to
+ /// find. The order of pure instructions do not matter, as they will
+ /// not be affected by side effects.
Set<HInstruction> pureInputs;
Set<HInstruction> generateAtUseSite;
@@ -710,11 +700,9 @@
}
}
-/**
- * Detect control flow arising from short-circuit logical and
- * conditional operators, and prepare the program to be generated
- * using these operators instead of nested ifs and boolean variables.
- */
+/// Detect control flow arising from short-circuit logical and
+/// conditional operators, and prepare the program to be generated
+/// using these operators instead of nested ifs and boolean variables.
class SsaConditionMerger extends HGraphVisitor {
Set<HInstruction> generateAtUseSite;
Set<HInstruction> controlFlowOperators;
@@ -730,10 +718,8 @@
visitPostDominatorTree(graph);
}
- /**
- * Check if a block has at least one statement other than
- * [instruction].
- */
+ /// Check if a block has at least one statement other than
+ /// [instruction].
bool hasAnyStatement(HBasicBlock block, HInstruction instruction) {
// If [instruction] is not in [block], then if the block is not
// empty, we know there will be a statement to emit.
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 938d1dd..7b78b8c 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -281,8 +281,6 @@
/// concrete SSA builder reports an error.
bool getFlagValue(String flagName) {
switch (flagName) {
- case 'IS_FULL_EMITTER':
- return !options.useStartupEmitter;
case 'MINIFIED':
return options.enableMinification;
case 'MUST_RETAIN_METADATA':
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index 0ea8717..3f5d89b 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -12,26 +12,24 @@
import 'nodes.dart';
import 'optimize.dart';
-/**
- * This phase simplifies interceptors in multiple ways:
- *
- * 1) If the interceptor is for an object whose type is known, it
- * tries to use a constant interceptor instead.
- *
- * 2) Interceptors are specialized based on the selector it is used with.
- *
- * 3) If we know the object is not intercepted, we just use the object
- * instead.
- *
- * 4) Single use interceptors at dynamic invoke sites are replaced with 'one
- * shot interceptors' which are synthesized static helper functions that fetch
- * the interceptor and then call the method. This saves code size and makes the
- * receiver of an intercepted call a candidate for being generated at use site.
- *
- * 5) Some HIs operations on an interceptor are replaced with a HIs version that
- * uses 'instanceof' rather than testing a type flag.
- *
- */
+/// This phase simplifies interceptors in multiple ways:
+///
+/// 1) If the interceptor is for an object whose type is known, it
+/// tries to use a constant interceptor instead.
+///
+/// 2) Interceptors are specialized based on the selector it is used with.
+///
+/// 3) If we know the object is not intercepted, we just use the object
+/// instead.
+///
+/// 4) Single use interceptors at dynamic invoke sites are replaced with 'one
+/// shot interceptors' which are synthesized static helper functions that fetch
+/// the interceptor and then call the method. This saves code size and makes the
+/// receiver of an intercepted call a candidate for being generated at use site.
+///
+/// 5) Some HIs operations on an interceptor are replaced with a HIs version that
+/// uses 'instanceof' rather than testing a type flag.
+///
class SsaSimplifyInterceptors extends HBaseVisitor
implements OptimizationPhase {
final String name = "SsaSimplifyInterceptors";
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 847ad4e..18f2ce2 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -16,12 +16,10 @@
import 'nodes.dart';
import 'types.dart';
-/**
- * [InvokeDynamicSpecializer] and its subclasses are helpers to
- * optimize intercepted dynamic calls. It knows what input types
- * would be beneficial for performance, and how to change a invoke
- * dynamic to a builtin instruction (e.g. HIndex, HBitNot).
- */
+/// [InvokeDynamicSpecializer] and its subclasses are helpers to
+/// optimize intercepted dynamic calls. It knows what input types
+/// would be beneficial for performance, and how to change a invoke
+/// dynamic to a builtin instruction (e.g. HIndex, HBitNot).
class InvokeDynamicSpecializer {
const InvokeDynamicSpecializer();
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 568ae0b..dc693ef 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -510,7 +510,7 @@
class SubExpression extends SubGraph {
const SubExpression(HBasicBlock start, HBasicBlock end) : super(start, end);
- /** Find the condition expression if this sub-expression is a condition. */
+ /// Find the condition expression if this sub-expression is a condition.
HInstruction get conditionExpression {
HInstruction last = end.last;
if (last is HConditionalBranch || last is HSwitch) return last.inputs[0];
@@ -580,7 +580,7 @@
detach(instruction);
}
- /** Linear search for [instruction]. */
+ /// Linear search for [instruction].
bool contains(HInstruction instruction) {
HInstruction cursor = first;
while (cursor != null) {
@@ -760,10 +760,8 @@
}
}
- /**
- * Rewrites all uses of the [from] instruction to using the [to]
- * instruction instead.
- */
+ /// Rewrites all uses of the [from] instruction to using the [to]
+ /// instruction instead.
void rewrite(HInstruction from, HInstruction to) {
for (HInstruction use in from.usedBy) {
use.rewriteInput(from, to);
@@ -772,11 +770,9 @@
from.usedBy.clear();
}
- /**
- * Rewrites all uses of the [from] instruction to using either the
- * [to] instruction, or a [HCheck] instruction that has better type
- * information on [to], and that dominates the user.
- */
+ /// Rewrites all uses of the [from] instruction to using either the
+ /// [to] instruction, or a [HCheck] instruction that has better type
+ /// information on [to], and that dominates the user.
void rewriteWithBetterUser(HInstruction from, HInstruction to) {
// BUG(11841): Turn this method into a phase to be run after GVN phases.
Link<HCheck> better = const Link<HCheck>();
@@ -992,11 +988,9 @@
bool get isMovable => useGvn();
- /**
- * A pure instruction is an instruction that does not have any side
- * effect, nor any dependency. They can be moved anywhere in the
- * graph.
- */
+ /// A pure instruction is an instruction that does not have any side
+ /// effect, nor any dependency. They can be moved anywhere in the
+ /// graph.
bool isPure(AbstractValueDomain domain) {
return !sideEffects.hasSideEffects() &&
!sideEffects.dependsOnSomething() &&
@@ -1105,9 +1099,7 @@
AbstractBool isPrimitiveOrNull(AbstractValueDomain domain) =>
domain.isPrimitiveOrNull(instructionType);
- /**
- * Type of the instruction.
- */
+ /// Type of the instruction.
AbstractValue instructionType;
Selector get selector => null;
@@ -1185,7 +1177,7 @@
}
}
- /** Removes all occurrences of [instruction] from [list]. */
+ /// Removes all occurrences of [instruction] from [list].
void removeFromList(List<HInstruction> list, HInstruction instruction) {
int length = list.length;
int i = 0;
@@ -1200,7 +1192,7 @@
list.length = length;
}
- /** Removes all occurrences of [user] from [usedBy]. */
+ /// Removes all occurrences of [user] from [usedBy].
void removeUser(HInstruction user) {
removeFromList(usedBy, user);
}
@@ -1299,10 +1291,8 @@
}
}
- /**
- * Return whether the instructions do not belong to a loop or
- * belong to the same loop.
- */
+ /// Return whether the instructions do not belong to a loop or
+ /// belong to the same loop.
bool hasSameLoopHeaderAs(HInstruction other) {
return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
}
@@ -1466,10 +1456,8 @@
String toString() => 'HRef(${value})';
}
-/**
- * Late instructions are used after the main optimization phases. They capture
- * codegen decisions just prior to generating JavaScript.
- */
+/// Late instructions are used after the main optimization phases. They capture
+/// codegen decisions just prior to generating JavaScript.
abstract class HLateInstruction extends HInstruction {
HLateInstruction(List<HInstruction> inputs, AbstractValue type)
: super(inputs, type);
@@ -1488,13 +1476,11 @@
bool dataEquals(HInstruction other) => true;
}
-/**
- * A [HCheck] instruction is an instruction that might do a dynamic
- * check at runtime on another instruction. To have proper instruction
- * dependencies in the graph, instructions that depend on the check
- * being done reference the [HCheck] instruction instead of the
- * instruction itself.
- */
+/// A [HCheck] instruction is an instruction that might do a dynamic
+/// check at runtime on another instruction. To have proper instruction
+/// dependencies in the graph, instructions that depend on the check
+/// being done reference the [HCheck] instruction instead of the
+/// instruction itself.
abstract class HCheck extends HInstruction {
HCheck(inputs, type) : super(inputs, type) {
setUseGvn();
@@ -1512,10 +1498,9 @@
static const int ALWAYS_ABOVE_ZERO = 2;
static const int ALWAYS_BELOW_LENGTH = 3;
static const int ALWAYS_TRUE = 4;
- /**
- * Details which tests have been done statically during compilation.
- * Default is that all checks must be performed dynamically.
- */
+
+ /// Details which tests have been done statically during compilation.
+ /// Default is that all checks must be performed dynamically.
int staticChecks = FULL_CHECK;
HBoundsCheck(length, index, array, type)
@@ -1644,9 +1629,7 @@
/// The type arguments passed in this dynamic invocation.
List<DartType> get typeArguments;
- /**
- * Returns whether this call is on an interceptor object.
- */
+ /// Returns whether this call is on an interceptor object.
bool isCallOnInterceptor(JClosedWorld closedWorld) {
return isInterceptedCall && receiver.isInterceptor(closedWorld);
}
@@ -1776,7 +1759,7 @@
/// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
List<InterfaceType> instantiatedTypes;
- /** The first input must be the target. */
+ /// The first input must be the target.
HInvokeStatic(this.element, inputs, AbstractValue type, this.typeArguments,
{this.targetCanThrow: true, bool isIntercepted: false})
: super(inputs, type) {
@@ -1791,7 +1774,7 @@
}
class HInvokeSuper extends HInvokeStatic {
- /** The class where the call to super is being done. */
+ /// The class where the call to super is being done.
final ClassEntity caller;
final bool isSetter;
final Selector selector;
@@ -1816,9 +1799,7 @@
return isCallOnInterceptor(closedWorld) ? inputs[1] : inputs[0];
}
- /**
- * Returns whether this call is on an interceptor object.
- */
+ /// Returns whether this call is on an interceptor object.
bool isCallOnInterceptor(JClosedWorld closedWorld) {
return isInterceptedCall && receiver.isInterceptor(closedWorld);
}
@@ -1974,10 +1955,8 @@
String toString() => "GetLength()";
}
-/**
- * HReadModifyWrite is a late stage instruction for a field (property) update
- * via an assignment operation or pre- or post-increment.
- */
+/// HReadModifyWrite is a late stage instruction for a field (property) update
+/// via an assignment operation or pre- or post-increment.
class HReadModifyWrite extends HLateInstruction {
static const ASSIGN_OP = 0;
static const PRE_OP = 1;
@@ -2242,11 +2221,9 @@
bool dataEquals(HInstruction other) => true;
}
-/**
- * An [HSwitch] instruction has one input for the incoming
- * value, and one input per constant that it can switch on.
- * Its block has one successor per constant, and one for the default.
- */
+/// An [HSwitch] instruction has one input for the incoming
+/// value, and one input per constant that it can switch on.
+/// Its block has one successor per constant, and one for the default.
class HSwitch extends HControlFlow {
HSwitch(AbstractValueDomain domain, List<HInstruction> inputs)
: super(domain, inputs);
@@ -2254,11 +2231,9 @@
HConstant constant(int index) => inputs[index + 1];
HInstruction get expression => inputs[0];
- /**
- * Provides the target to jump to if none of the constants match
- * the expression. If the switch had no default case, this is the
- * following join-block.
- */
+ /// Provides the target to jump to if none of the constants match
+ /// the expression. If the switch had no default case, this is the
+ /// following join-block.
HBasicBlock get defaultTarget => block.successors.last;
accept(HVisitor visitor) => visitor.visitSwitch(this);
@@ -2551,11 +2526,9 @@
bool dataEquals(HInstruction other) => true;
}
-/**
- * An [HLocalValue] represents a local. Unlike [HParameterValue]s its
- * first use must be in an HLocalSet. That is, [HParameterValue]s have a
- * value from the start, whereas [HLocalValue]s need to be initialized first.
- */
+/// An [HLocalValue] represents a local. Unlike [HParameterValue]s its
+/// first use must be in an HLocalSet. That is, [HParameterValue]s have a
+/// value from the start, whereas [HLocalValue]s need to be initialized first.
class HLocalValue extends HInstruction {
HLocalValue(Entity variable, AbstractValue type)
: super(<HInstruction>[], type) {
@@ -2823,15 +2796,13 @@
}
}
-/**
- * A "one-shot" interceptor is a call to a synthetized method that
- * will fetch the interceptor of its first parameter, and make a call
- * on a given selector with the remaining parameters.
- *
- * In order to share the same optimizations with regular interceptor
- * calls, this class extends [HInvokeDynamic] and also has the null
- * constant as the first input.
- */
+/// A "one-shot" interceptor is a call to a synthetized method that
+/// will fetch the interceptor of its first parameter, and make a call
+/// on a given selector with the remaining parameters.
+///
+/// In order to share the same optimizations with regular interceptor
+/// calls, this class extends [HInvokeDynamic] and also has the null
+/// constant as the first input.
class HOneShotInterceptor extends HInvokeDynamic {
List<DartType> typeArguments;
Set<ClassEntity> interceptedClasses;
@@ -2855,7 +2826,7 @@
accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
}
-/** An [HLazyStatic] is a static that is initialized lazily at first read. */
+/// An [HLazyStatic] is a static that is initialized lazily at first read.
class HLazyStatic extends HInstruction {
final FieldEntity element;
@@ -2904,10 +2875,8 @@
bool isAllocation(AbstractValueDomain domain) => true;
}
-/**
- * The primitive array indexing operation. Note that this instruction
- * does not throw because we generate the checks explicitly.
- */
+/// The primitive array indexing operation. Note that this instruction
+/// does not throw because we generate the checks explicitly.
class HIndex extends HInstruction {
final Selector selector;
HIndex(HInstruction receiver, HInstruction index, this.selector,
@@ -2939,10 +2908,8 @@
bool dataEquals(HIndex other) => true;
}
-/**
- * The primitive array assignment operation. Note that this instruction
- * does not throw because we generate the checks explicitly.
- */
+/// The primitive array assignment operation. Note that this instruction
+/// does not throw because we generate the checks explicitly.
class HIndexAssign extends HInstruction {
final Selector selector;
HIndexAssign(AbstractValueDomain domain, HInstruction receiver,
@@ -3065,11 +3032,9 @@
}
}
-/**
- * HIsViaInterceptor is a late-stage instruction for a type test that can be
- * done entirely on an interceptor. It is not a HCheck because the checked
- * input is not one of the inputs.
- */
+/// HIsViaInterceptor is a late-stage instruction for a type test that can be
+/// done entirely on an interceptor. It is not a HCheck because the checked
+/// input is not one of the inputs.
class HIsViaInterceptor extends HLateInstruction {
final DartType typeExpression;
HIsViaInterceptor(
@@ -3323,10 +3288,8 @@
toString() => "string concat";
}
-/**
- * The part of string interpolation which converts and interpolated expression
- * into a String value.
- */
+/// The part of string interpolation which converts and interpolated expression
+/// into a String value.
class HStringify extends HInstruction {
HStringify(HInstruction input, AbstractValue type)
: super(<HInstruction>[input], type) {
@@ -3338,7 +3301,7 @@
toString() => "stringify";
}
-/** Non-block-based (aka. traditional) loop information. */
+/// Non-block-based (aka. traditional) loop information.
class HLoopInformation {
final HBasicBlock header;
final List<HBasicBlock> blocks;
@@ -3346,7 +3309,7 @@
final List<LabelDefinition> labels;
final JumpTarget target;
- /** Corresponding block information for the loop. */
+ /// Corresponding block information for the loop.
HLoopBlockInformation loopBlockInformation;
HLoopInformation(this.header, this.target, this.labels)
@@ -3379,37 +3342,29 @@
}
}
-/**
- * Embedding of a [HBlockInformation] for block-structure based traversal
- * in a dominator based flow traversal by attaching it to a basic block.
- * To go back to dominator-based traversal, a [HSubGraphBlockInformation]
- * structure can be added in the block structure.
- */
+/// Embedding of a [HBlockInformation] for block-structure based traversal
+/// in a dominator based flow traversal by attaching it to a basic block.
+/// To go back to dominator-based traversal, a [HSubGraphBlockInformation]
+/// structure can be added in the block structure.
class HBlockFlow {
final HBlockInformation body;
final HBasicBlock continuation;
HBlockFlow(this.body, this.continuation);
}
-/**
- * Information about a syntactic-like structure.
- */
+/// Information about a syntactic-like structure.
abstract class HBlockInformation {
HBasicBlock get start;
HBasicBlock get end;
bool accept(HBlockInformationVisitor visitor);
}
-/**
- * Information about a statement-like structure.
- */
+/// Information about a statement-like structure.
abstract class HStatementInformation extends HBlockInformation {
bool accept(HStatementInformationVisitor visitor);
}
-/**
- * Information about an expression-like structure.
- */
+/// Information about an expression-like structure.
abstract class HExpressionInformation extends HBlockInformation {
bool accept(HExpressionInformationVisitor visitor);
HInstruction get conditionExpression;
@@ -3435,10 +3390,8 @@
abstract class HBlockInformationVisitor
implements HStatementInformationVisitor, HExpressionInformationVisitor {}
-/**
- * Generic class wrapping a [SubGraph] as a block-information until
- * all structures are handled properly.
- */
+/// Generic class wrapping a [SubGraph] as a block-information until
+/// all structures are handled properly.
class HSubGraphBlockInformation implements HStatementInformation {
final SubGraph subGraph;
HSubGraphBlockInformation(this.subGraph);
@@ -3450,10 +3403,8 @@
visitor.visitSubGraphInfo(this);
}
-/**
- * Generic class wrapping a [SubExpression] as a block-information until
- * expressions structures are handled properly.
- */
+/// Generic class wrapping a [SubExpression] as a block-information until
+/// expressions structures are handled properly.
class HSubExpressionBlockInformation implements HExpressionInformation {
final SubExpression subExpression;
HSubExpressionBlockInformation(this.subExpression);
@@ -3467,7 +3418,7 @@
visitor.visitSubExpressionInfo(this);
}
-/** A sequence of separate statements. */
+/// A sequence of separate statements.
class HStatementSequenceInformation implements HStatementInformation {
final List<HStatementInformation> statements;
HStatementSequenceInformation(this.statements);
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 72a69eb..40917cf 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -182,10 +182,8 @@
return false;
}
-/**
- * If both inputs to known operations are available execute the operation at
- * compile-time.
- */
+/// If both inputs to known operations are available execute the operation at
+/// compile-time.
class SsaInstructionSimplifier extends HBaseVisitor
implements OptimizationPhase {
// We don't produce constant-folded strings longer than this unless they have
@@ -1253,7 +1251,8 @@
field, _globalInferenceResults);
}
- return new HFieldGet(field, receiver, type, isAssignable: isAssignable);
+ return new HFieldGet(field, receiver, type, isAssignable: isAssignable)
+ ..sourceInformation = node.sourceInformation;
}
HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
@@ -1289,7 +1288,8 @@
}
}
HFieldSet result =
- new HFieldSet(_abstractValueDomain, field, receiver, value);
+ new HFieldSet(_abstractValueDomain, field, receiver, value)
+ ..sourceInformation = node.sourceInformation;
_log?.registerFieldSet(node, result);
return result;
}
@@ -2819,11 +2819,9 @@
}
}
-/**
- * Optimization phase that tries to eliminate memory loads (for example
- * [HFieldGet]), when it knows the value stored in that memory location, and
- * stores that overwrite with the same value.
- */
+/// Optimization phase that tries to eliminate memory loads (for example
+/// [HFieldGet]), when it knows the value stored in that memory location, and
+/// stores that overwrite with the same value.
class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
final Compiler compiler;
final JClosedWorld closedWorld;
diff --git a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
index f6bfb90..5f2e064 100644
--- a/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_branch_builder.dart
@@ -58,10 +58,8 @@
new SubExpression(conditionBranch.block, conditionExitBlock);
}
- /**
- * Returns true if the locals of the [fromBranch] may be reused. A [:true:]
- * return value implies that [mayReuseFromLocals] was set to [:true:].
- */
+ /// Returns true if the locals of the [fromBranch] may be reused. A [:true:]
+ /// return value implies that [mayReuseFromLocals] was set to [:true:].
bool mergeLocals(SsaBranch fromBranch, SsaBranch toBranch,
{bool mayReuseFromLocals}) {
LocalsHandler fromLocals = fromBranch.exitLocals;
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index a4b3de8..ee7bc98 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -12,11 +12,9 @@
import '../world.dart' show JClosedWorld;
import 'nodes.dart';
-/**
- * Outputs SSA code in a format readable by Hydra IR.
- * Tracing is disabled by default, see ../tracer.dart for how
- * to enable it.
- */
+/// Outputs SSA code in a format readable by Hydra IR.
+/// Tracing is disabled by default, see ../tracer.dart for how
+/// to enable it.
class HTracer extends HGraphVisitor with TracerUtil {
final JClosedWorld closedWorld;
final Namer namer;
diff --git a/pkg/compiler/lib/src/ssa/validate.dart b/pkg/compiler/lib/src/ssa/validate.dart
index 31e9125..1f93b4e 100644
--- a/pkg/compiler/lib/src/ssa/validate.dart
+++ b/pkg/compiler/lib/src/ssa/validate.dart
@@ -132,7 +132,7 @@
super.visitBasicBlock(block);
}
- /** Returns how often [instruction] is contained in [instructions]. */
+ /// Returns how often [instruction] is contained in [instructions].
static int countInstruction(
List<HInstruction> instructions, HInstruction instruction) {
int result = 0;
@@ -142,11 +142,9 @@
return result;
}
- /**
- * Returns true if the predicate returns true for every instruction in the
- * list. The argument to [f] is an instruction with the count of how often
- * it appeared in the list [instructions].
- */
+ /// Returns true if the predicate returns true for every instruction in the
+ /// list. The argument to [f] is an instruction with the count of how often
+ /// it appeared in the list [instructions].
static bool everyInstruction(List<HInstruction> instructions, Function f) {
var copy = new List<HInstruction>.from(instructions);
// TODO(floitsch): there is currently no way to sort HInstructions before
diff --git a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
index acdfd27..a4bfd96 100644
--- a/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
+++ b/pkg/compiler/lib/src/ssa/value_range_analyzer.dart
@@ -58,11 +58,9 @@
}
}
-/**
- * A [Value] represents both symbolic values like the value of a
- * parameter, or the length of an array, and concrete values, like
- * constants.
- */
+/// A [Value] represents both symbolic values like the value of a
+/// parameter, or the length of an array, and concrete values, like
+/// constants.
abstract class Value {
final ValueRangeInfo info;
const Value(this.info);
@@ -97,10 +95,8 @@
bool get isZero => false;
}
-/**
- * The [MarkerValue] class is used to recognize ranges of loop
- * updates.
- */
+/// The [MarkerValue] class is used to recognize ranges of loop
+/// updates.
class MarkerValue extends Value {
/// If [positive] is true (respectively false), the marker goes
/// to [MaxIntValue] (respectively [MinIntValue]) when being added
@@ -124,9 +120,7 @@
}
}
-/**
- * An [IntValue] contains a constant integer value.
- */
+/// An [IntValue] contains a constant integer value.
class IntValue extends Value {
final BigInt value;
@@ -192,10 +186,8 @@
bool get isZero => value == BigInt.zero;
}
-/**
- * The [MaxIntValue] represents the maximum value an integer can have,
- * which is currently +infinity.
- */
+/// The [MaxIntValue] represents the maximum value an integer can have,
+/// which is currently +infinity.
class MaxIntValue extends Value {
const MaxIntValue() : super(null);
Value operator +(Value other) => this;
@@ -208,10 +200,8 @@
bool get isPositive => true;
}
-/**
- * The [MinIntValue] represents the minimum value an integer can have,
- * which is currently -infinity.
- */
+/// The [MinIntValue] represents the minimum value an integer can have,
+/// which is currently -infinity.
class MinIntValue extends Value {
const MinIntValue() : super(null);
Value operator +(Value other) => this;
@@ -224,10 +214,8 @@
bool get isPositive => false;
}
-/**
- * The [UnknownValue] is the sentinel in our analysis to mark an
- * operation that could not be done because of too much complexity.
- */
+/// The [UnknownValue] is the sentinel in our analysis to mark an
+/// operation that could not be done because of too much complexity.
class UnknownValue extends Value {
const UnknownValue() : super(null);
Value operator +(Value other) => const UnknownValue();
@@ -240,9 +228,7 @@
String toString() => 'Unknown';
}
-/**
- * A symbolic value representing an [HInstruction].
- */
+/// A symbolic value representing an [HInstruction].
class InstructionValue extends Value {
final HInstruction instruction;
InstructionValue(this.instruction, info) : super(info);
@@ -293,18 +279,14 @@
String toString() => 'Instruction: $instruction';
}
-/**
- * Special value for instructions whose type is a positive integer.
- */
+/// Special value for instructions whose type is a positive integer.
class PositiveValue extends InstructionValue {
PositiveValue(HInstruction instruction, info) : super(instruction, info);
bool get isPositive => true;
}
-/**
- * Represents a binary operation on two [Value], where the operation
- * did not yield a canonical value.
- */
+/// Represents a binary operation on two [Value], where the operation
+/// did not yield a canonical value.
class BinaryOperationValue extends Value {
final Value left;
final Value right;
@@ -457,11 +439,9 @@
String toString() => '-$value';
}
-/**
- * A [Range] represents the possible integer values an instruction
- * can have, from its [lower] bound to its [upper] bound, both
- * included.
- */
+/// A [Range] represents the possible integer values an instruction
+/// can have, from its [lower] bound to its [upper] bound, both
+/// included.
class Range {
final Value lower;
final Value upper;
@@ -473,10 +453,8 @@
Range.unbound(info) : this(const MinIntValue(), const MaxIntValue(), info);
- /**
- * Checks if the given values are unknown, and creates a
- * range that does not have any unknown values.
- */
+ /// Checks if the given values are unknown, and creates a
+ /// range that does not have any unknown values.
Range.normalize(Value low, Value up, info)
: this(low == const UnknownValue() ? const MinIntValue() : low,
up == const UnknownValue() ? const MaxIntValue() : up, info);
@@ -579,25 +557,19 @@
String toString() => '[$lower, $upper]';
}
-/**
- * Visits the graph in dominator order, and computes value ranges for
- * integer instructions. While visiting the graph, this phase also
- * removes unnecessary bounds checks, and comparisons that are proven
- * to be true or false.
- */
+/// Visits the graph in dominator order, and computes value ranges for
+/// integer instructions. While visiting the graph, this phase also
+/// removes unnecessary bounds checks, and comparisons that are proven
+/// to be true or false.
class SsaValueRangeAnalyzer extends HBaseVisitor implements OptimizationPhase {
String get name => 'SSA value range builder';
- /**
- * List of [HRangeConversion] instructions created by the phase. We
- * save them here in order to remove them once the phase is done.
- */
+ /// List of [HRangeConversion] instructions created by the phase. We
+ /// save them here in order to remove them once the phase is done.
final List<HRangeConversion> conversions = <HRangeConversion>[];
- /**
- * Value ranges for integer instructions. This map gets populated by
- * the dominator tree visit.
- */
+ /// Value ranges for integer instructions. This map gets populated by
+ /// the dominator tree visit.
final Map<HInstruction, Range> ranges = new Map<HInstruction, Range>();
final JClosedWorld closedWorld;
@@ -1088,9 +1060,7 @@
}
}
-/**
- * Tries to find a range for the update instruction of a loop phi.
- */
+/// Tries to find a range for the update instruction of a loop phi.
class LoopUpdateRecognizer extends HBaseVisitor {
final JClosedWorld closedWorld;
final Map<HInstruction, Range> ranges;
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index 3bb3c85..6837537 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -6,9 +6,7 @@
import '../js_backend/js_backend.dart';
import 'nodes.dart';
-/**
- * The [LiveRange] class covers a range where an instruction is live.
- */
+/// The [LiveRange] class covers a range where an instruction is live.
class LiveRange {
final int start;
// [end] is not final because it can be updated due to loops.
@@ -20,14 +18,10 @@
String toString() => '[$start $end[';
}
-/**
- * The [LiveInterval] class contains the list of ranges where an
- * instruction is live.
- */
+/// The [LiveInterval] class contains the list of ranges where an
+/// instruction is live.
class LiveInterval {
- /**
- * The id where the instruction is defined.
- */
+ /// The id where the instruction is defined.
int start;
final List<LiveRange> ranges;
LiveInterval() : ranges = <LiveRange>[];
@@ -38,10 +32,8 @@
LiveInterval.forCheck(this.start, LiveInterval checkedInterval)
: ranges = checkedInterval.ranges;
- /**
- * Update all ranges that are contained in [from, to[ to
- * die at [to].
- */
+ /// Update all ranges that are contained in [from, to[ to
+ /// die at [to].
void loopUpdate(int from, int to) {
for (LiveRange range in ranges) {
if (from <= range.start && range.end < to) {
@@ -50,16 +42,12 @@
}
}
- /**
- * Add a new range to this interval.
- */
+ /// Add a new range to this interval.
void add(LiveRange interval) {
ranges.add(interval);
}
- /**
- * Returns true if one of the ranges of this interval dies at [at].
- */
+ /// Returns true if one of the ranges of this interval dies at [at].
bool diesAt(int at) {
for (LiveRange range in ranges) {
if (range.end == at) return true;
@@ -74,53 +62,39 @@
}
}
-/**
- * The [LiveEnvironment] class contains the liveIn set of a basic
- * block. A liveIn set of a block contains the instructions that are
- * live when entering that block.
- */
+/// The [LiveEnvironment] class contains the liveIn set of a basic
+/// block. A liveIn set of a block contains the instructions that are
+/// live when entering that block.
class LiveEnvironment {
- /**
- * The instruction id where the basic block starts. See
- * [SsaLiveIntervalBuilder.instructionId].
- */
+ /// The instruction id where the basic block starts. See
+ /// [SsaLiveIntervalBuilder.instructionId].
int startId;
- /**
- * The instruction id where the basic block ends.
- */
+ /// The instruction id where the basic block ends.
final int endId;
- /**
- * Loop markers that will be updated once the loop header is
- * visited. The liveIn set of the loop header will be merged into this
- * environment. [loopMarkers] is a mapping from block header to the
- * end instruction id of the loop exit block.
- */
+ /// Loop markers that will be updated once the loop header is
+ /// visited. The liveIn set of the loop header will be merged into this
+ /// environment. [loopMarkers] is a mapping from block header to the
+ /// end instruction id of the loop exit block.
final Map<HBasicBlock, int> loopMarkers;
- /**
- * The instructions that are live in this basic block. The values of
- * the map contain the instruction ids where the instructions die.
- * It will be used when adding a range to the live interval of an
- * instruction.
- */
+ /// The instructions that are live in this basic block. The values of
+ /// the map contain the instruction ids where the instructions die.
+ /// It will be used when adding a range to the live interval of an
+ /// instruction.
final Map<HInstruction, int> liveInstructions;
- /**
- * Map containing the live intervals of instructions.
- */
+ /// Map containing the live intervals of instructions.
final Map<HInstruction, LiveInterval> liveIntervals;
LiveEnvironment(this.liveIntervals, this.endId)
: liveInstructions = new Map<HInstruction, int>(),
loopMarkers = new Map<HBasicBlock, int>();
- /**
- * Remove an instruction from the liveIn set. This method also
- * updates the live interval of [instruction] to contain the new
- * range: [id, / id contained in [liveInstructions] /].
- */
+ /// Remove an instruction from the liveIn set. This method also
+ /// updates the live interval of [instruction] to contain the new
+ /// range: [id, / id contained in [liveInstructions] /].
void remove(HInstruction instruction, int id) {
LiveInterval interval =
liveIntervals.putIfAbsent(instruction, () => new LiveInterval());
@@ -132,20 +106,16 @@
liveInstructions.remove(instruction);
}
- /**
- * Add [instruction] to the liveIn set. If the instruction is not
- * already in the set, we save the id where it dies.
- */
+ /// Add [instruction] to the liveIn set. If the instruction is not
+ /// already in the set, we save the id where it dies.
void add(HInstruction instruction, int userId) {
// Note that we are visiting the graph in post-dominator order, so
// the first time we see a variable is when it dies.
liveInstructions.putIfAbsent(instruction, () => userId);
}
- /**
- * Merge this environment with [other]. Update the end id of
- * instructions in case they are different between this and [other].
- */
+ /// Merge this environment with [other]. Update the end id of
+ /// instructions in case they are different between this and [other].
void mergeWith(LiveEnvironment other) {
other.liveInstructions.forEach((HInstruction instruction, int existingId) {
// If both environments have the same instruction id of where
@@ -180,31 +150,23 @@
String toString() => liveInstructions.toString();
}
-/**
- * Builds the live intervals of each instruction. The algorithm visits
- * the graph post-dominator tree to find the last uses of an
- * instruction, and computes the liveIns of each basic block.
- */
+/// Builds the live intervals of each instruction. The algorithm visits
+/// the graph post-dominator tree to find the last uses of an
+/// instruction, and computes the liveIns of each basic block.
class SsaLiveIntervalBuilder extends HBaseVisitor {
final Set<HInstruction> generateAtUseSite;
final Set<HInstruction> controlFlowOperators;
- /**
- * A counter to assign start and end ids to live ranges. The initial
- * value is not relevant. Note that instructionId goes downward to ease
- * reasoning about live ranges (the first instruction of a graph has
- * the lowest id).
- */
+ /// A counter to assign start and end ids to live ranges. The initial
+ /// value is not relevant. Note that instructionId goes downward to ease
+ /// reasoning about live ranges (the first instruction of a graph has
+ /// the lowest id).
int instructionId = 0;
- /**
- * The liveIns of basic blocks.
- */
+ /// The liveIns of basic blocks.
final Map<HBasicBlock, LiveEnvironment> liveInstructions;
- /**
- * The live intervals of instructions.
- */
+ /// The live intervals of instructions.
final Map<HInstruction, LiveInterval> liveIntervals;
SsaLiveIntervalBuilder(this.generateAtUseSite, this.controlFlowOperators)
@@ -384,11 +346,9 @@
}
}
-/**
- * Represents a copy from one instruction to another. The codegen
- * also uses this class to represent a copy from one variable to
- * another.
- */
+/// Represents a copy from one instruction to another. The codegen
+/// also uses this class to represent a copy from one variable to
+/// another.
class Copy<T> {
final T source;
final T destination;
@@ -398,20 +358,14 @@
String toString() => '$destination <- $source';
}
-/**
- * A copy handler contains the copies that a basic block needs to do
- * after executing all its instructions.
- */
+/// A copy handler contains the copies that a basic block needs to do
+/// after executing all its instructions.
class CopyHandler {
- /**
- * The copies from an instruction to a phi of the successor.
- */
+ /// The copies from an instruction to a phi of the successor.
final List<Copy<HInstruction>> copies;
- /**
- * Assignments from an instruction that does not need a name (e.g. a
- * constant) to the phi of a successor.
- */
+ /// Assignments from an instruction that does not need a name (e.g. a
+ /// constant) to the phi of a successor.
final List<Copy<HInstruction>> assignments;
CopyHandler()
@@ -431,21 +385,18 @@
bool get isEmpty => copies.isEmpty && assignments.isEmpty;
}
-/**
- * Contains the mapping between instructions and their names for code
- * generation, as well as the [CopyHandler] for each basic block.
- */
+/// Contains the mapping between instructions and their names for code
+/// generation, as well as the [CopyHandler] for each basic block.
class VariableNames {
final Map<HInstruction, String> ownName;
final Map<HBasicBlock, CopyHandler> copyHandlers;
// Used to control heuristic that determines how local variables are declared.
final Set<String> allUsedNames;
- /**
- * Name that is used as a temporary to break cycles in
- * parallel copies. We make sure this name is not being used
- * anywhere by reserving it when we allocate names for instructions.
- */
+
+ /// Name that is used as a temporary to break cycles in
+ /// parallel copies. We make sure this name is not being used
+ /// anywhere by reserving it when we allocate names for instructions.
final String swapTemp;
String getSwapTemp() {
@@ -488,9 +439,7 @@
}
}
-/**
- * Allocates variable names for instructions, making sure they don't collide.
- */
+/// Allocates variable names for instructions, making sure they don't collide.
class VariableNamer {
final VariableNames names;
final Namer _namer;
@@ -586,9 +535,7 @@
return name;
}
- /**
- * Frees [instruction]'s name so it can be used for other instructions.
- */
+ /// Frees [instruction]'s name so it can be used for other instructions.
void freeName(HInstruction instruction) {
String ownName = names.ownName[instruction];
if (ownName != null) {
@@ -604,18 +551,16 @@
}
}
-/**
- * Visits all blocks in the graph, sets names to instructions, and
- * creates the [CopyHandler] for each block. This class needs to have
- * the liveIns set as well as all the live intervals of instructions.
- * It visits the graph in dominator order, so that at each entry of a
- * block, the instructions in its liveIns set have names.
- *
- * When visiting a block, it goes through all instructions. For each
- * instruction, it frees the names of the inputs that die at that
- * instruction, and allocates a name to the instruction. For each phi,
- * it adds a copy to the CopyHandler of the corresponding predecessor.
- */
+/// Visits all blocks in the graph, sets names to instructions, and
+/// creates the [CopyHandler] for each block. This class needs to have
+/// the liveIns set as well as all the live intervals of instructions.
+/// It visits the graph in dominator order, so that at each entry of a
+/// block, the instructions in its liveIns set have names.
+///
+/// When visiting a block, it goes through all instructions. For each
+/// instruction, it frees the names of the inputs that die at that
+/// instruction, and allocates a name to the instruction. For each phi,
+/// it adds a copy to the CopyHandler of the corresponding predecessor.
class SsaVariableAllocator extends HBaseVisitor {
final Namer _namer;
final Map<HBasicBlock, LiveEnvironment> liveInstructions;
@@ -645,10 +590,8 @@
});
}
- /**
- * Returns whether [instruction] needs a name. Instructions that
- * have no users or that are generated at use site do not need a name.
- */
+ /// Returns whether [instruction] needs a name. Instructions that
+ /// have no users or that are generated at use site do not need a name.
bool needsName(instruction) {
if (instruction is HThis) return false;
if (instruction is HParameterValue) return true;
@@ -657,9 +600,7 @@
return !instruction.nonCheck().isCodeMotionInvariant();
}
- /**
- * Returns whether [instruction] dies at the instruction [at].
- */
+ /// Returns whether [instruction] dies at the instruction [at].
bool diesAt(HInstruction instruction, HInstruction at) {
LiveInterval atInterval = liveIntervals[at];
LiveInterval instructionInterval = liveIntervals[instruction];
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index 9a8f51c..f4e7870 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -11,10 +11,8 @@
import 'util/util.dart' show Indentation;
import 'world.dart' show JClosedWorld;
-/**
- * If non-null, we only trace methods whose name match the regexp defined by the
- * given pattern.
- */
+/// If non-null, we only trace methods whose name match the regexp defined by
+/// the given pattern.
String get TRACE_FILTER_PATTERN =>
TRACE_FILTER_PATTERN_FROM_ENVIRONMENT ?? TRACE_FILTER_PATTERN_FOR_TEST;
@@ -22,10 +20,8 @@
const String.fromEnvironment("DUMP_IR");
String TRACE_FILTER_PATTERN_FOR_TEST;
-/**
- * Dumps the intermediate representation after each phase in a format
- * readable by IR Hydra.
- */
+/// Dumps the intermediate representation after each phase in a format
+/// readable by IR Hydra.
class Tracer extends TracerUtil {
final JClosedWorld closedWorld;
final Namer namer;
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index 181714f..e5707ad 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -150,8 +150,8 @@
}
class ClassHierarchyImpl implements ClassHierarchy {
- /// Tag used for identifying serialized [ClassHierarchy] objects in a debugging
- /// data stream.
+ /// Tag used for identifying serialized [ClassHierarchy] objects in a
+ /// debugging data stream.
static const String tag = 'class-hierarchy';
final CommonElements _commonElements;
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 395639e..2c9980d 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -138,11 +138,9 @@
/// Invariant: Elements are declaration elements.
final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: Elements are declaration elements.
- */
+ /// Documentation wanted -- johnniwinther
+ ///
+ /// Invariant: Elements are declaration elements.
final Set<FunctionEntity> staticFunctionsNeedingGetter =
new Set<FunctionEntity>();
final Set<FunctionEntity> methodsNeedingSuperGetter =
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index f854843..1367e6d 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -9,6 +9,7 @@
library compiler.universe.feature;
import '../elements/types.dart';
+import '../ir/runtime_type_analysis.dart';
import '../util/util.dart';
/// A language feature that may be seen in the program.
@@ -148,21 +149,6 @@
}
}
-/// Enum for recognized use kinds of `Object.runtimeType`.
-enum RuntimeTypeUseKind {
- /// Unknown use of `Object.runtimeType`. This is the fallback value if the
- /// usage didn't match any of the recogized patterns.
- unknown,
-
- /// `Object.runtimeType` used in a pattern like
- /// `a.runtimeType == b.runtimeType`.
- equals,
-
- /// `Object.runtimeType` used in a pattern like `'${e.runtimeType}'` or
- /// `e.runtimeType.toString()`.
- string,
-}
-
/// A use of `Object.runtimeType`.
class RuntimeTypeUse {
/// The use kind of `Object.runtimeType`.
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 6119207..fee6d25 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -311,11 +311,9 @@
/// Invariant: Elements are declaration elements.
final Set<FieldEntity> allReferencedStaticFields = new Set<FieldEntity>();
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: Elements are declaration elements.
- */
+ /// Documentation wanted -- johnniwinther
+ ///
+ /// Invariant: Elements are declaration elements.
final Set<FunctionEntity> methodsNeedingSuperGetter =
new Set<FunctionEntity>();
final Map<String, Map<Selector, SelectorConstraints>> _invokedNames =
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index 47f974e..0696300 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -233,9 +233,7 @@
bool get isOperator => kind == SelectorKind.OPERATOR;
bool get isUnaryOperator => isOperator && argumentCount == 0;
- /**
- * The member name for invocation mirrors created from this selector.
- */
+ /// The member name for invocation mirrors created from this selector.
String get invocationMirrorMemberName => isSetter ? '$name=' : name;
int get invocationMirrorKind {
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 1336828..9ba793f 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -33,8 +33,8 @@
}
/// The use of a dynamic property. [selector] defined the name and kind of the
-/// property and [receiverConstraint] defines the known constraint for the object on which
-/// the property is accessed.
+/// property and [receiverConstraint] defines the known constraint for the
+/// object on which the property is accessed.
class DynamicUse {
final Selector selector;
@@ -47,9 +47,9 @@
var constraint = receiverConstraint;
if (constraint is StrongModeConstraint) {
if (constraint.isThis) {
- sb.write('<');
+ sb.write('this:');
} else if (constraint.isExact) {
- sb.write('=');
+ sb.write('exact:');
}
sb.write(constraint.cls.name);
} else {
diff --git a/pkg/compiler/lib/src/util/features.dart b/pkg/compiler/lib/src/util/features.dart
index 57aeba2..5263b40 100644
--- a/pkg/compiler/lib/src/util/features.dart
+++ b/pkg/compiler/lib/src/util/features.dart
@@ -25,9 +25,13 @@
_features[key] = value;
}
- String operator [](String key) => _features[key];
+ Object operator [](String key) => _features[key];
- String remove(String key) => _features.remove(key);
+ Object remove(String key) => _features.remove(key);
+
+ bool get isEmpty => _features.isEmpty;
+
+ bool get isNotEmpty => _features.isNotEmpty;
void forEach(void Function(String, Object) f) {
_features.forEach(f);
diff --git a/pkg/compiler/lib/src/util/indentation.dart b/pkg/compiler/lib/src/util/indentation.dart
index 9709f78..fb7cc21 100644
--- a/pkg/compiler/lib/src/util/indentation.dart
+++ b/pkg/compiler/lib/src/util/indentation.dart
@@ -69,9 +69,7 @@
return tag;
}
- /**
- * Adds given string to result string.
- */
+ /// Adds given string to result string.
void add(String string) {
sb.write(string);
}
@@ -79,12 +77,10 @@
/// Adds default parameters for [node] into [params].
void addDefaultParameters(N node, Map params) {}
- /**
- * Adds given node type to result string.
- * The method "opens" the node, meaning that all output after calling
- * this method and before calling closeNode() will represent contents
- * of given node.
- */
+ /// Adds given node type to result string.
+ /// The method "opens" the node, meaning that all output after calling
+ /// this method and before calling closeNode() will represent contents
+ /// of given node.
void openNode(N node, String type, [Map params]) {
if (params == null) params = new Map();
addCurrentIndent();
@@ -95,9 +91,7 @@
pushTag(type);
}
- /**
- * Adds given node to result string.
- */
+ /// Adds given node to result string.
void openAndCloseNode(N node, String type, [Map params]) {
if (params == null) params = {};
addCurrentIndent();
@@ -107,9 +101,7 @@
sb.write("/>\n");
}
- /**
- * Closes current node type.
- */
+ /// Closes current node type.
void closeNode() {
String tag = popTag();
addCurrentIndent();
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 297efca..785253d 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -114,10 +114,8 @@
return a.length == b.length && a.containsAll(b) && b.containsAll(a);
}
-/**
- * File name prefix used to shorten the file name in stack traces printed by
- * [trace].
- */
+/// File name prefix used to shorten the file name in stack traces printed by
+/// [trace].
String stackTraceFilePrefix = null;
/// Writes the characters of [string] on [buffer]. The characters
diff --git a/pkg/compiler/tool/status_files/update_all.dart b/pkg/compiler/tool/status_files/update_all.dart
index cc05227..bf09b28 100644
--- a/pkg/compiler/tool/status_files/update_all.dart
+++ b/pkg/compiler/tool/status_files/update_all.dart
@@ -110,8 +110,8 @@
}
print('build create_sdk');
- ProcessResult result = Process
- .runSync(python, ['./tools/build.py', '-m', 'release', 'create_sdk']);
+ ProcessResult result = Process.runSync(
+ python, ['./tools/build.py', '-m', 'release', 'create_sdk']);
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
diff --git a/pkg/compiler/tool/track_memory.dart b/pkg/compiler/tool/track_memory.dart
index f6ef38d..c5c2d03 100644
--- a/pkg/compiler/tool/track_memory.dart
+++ b/pkg/compiler/tool/track_memory.dart
@@ -172,9 +172,9 @@
if (now < 1024) {
string = ' ${now}b';
} else if (now < mega) {
- string = ' ${(now/1024).toStringAsFixed(0)}K';
+ string = ' ${(now / 1024).toStringAsFixed(0)}K';
} else {
- string = ' ${(now/mega).toStringAsFixed(1)}M';
+ string = ' ${(now / mega).toStringAsFixed(1)}M';
}
if (string.length < 10) string = '${' ' * (8 - string.length)}$string';
sb.write(string);
diff --git a/pkg/dartfix/README.md b/pkg/dartfix/README.md
index 3b4ef5b..45f61cb 100644
--- a/pkg/dartfix/README.md
+++ b/pkg/dartfix/README.md
@@ -1,28 +1,92 @@
-# dartfix
+The `dartfix` tool is a command-line interface
+for making automated updates to your Dart code.
+The tool isn't in the Dart SDK;
+instead, it's distributed in the [`dartfix` package.][dartfix]
-dartfix is a tool for migrating Dart source to newer versions of the Dart SDK,
-and fixing common issues including:
-
-* Converting classes used as mixins to use the
- [new mixin syntax](https://github.com/dart-lang/language/issues/7)
-* Converting [double literals to int literals](https://github.com/dart-lang/language/issues/4)
- where applicable
-* Moving named constructor type arguments from the name to the type
## Usage
-To activate the package
-```
- pub global activate dartfix
+> **Important:**
+> Save a copy of your source code before making changes with `dartfix`.
+> Unlike [dartfmt][], which makes only safe changes (usually to whitespace),
+> `dartfix` can make changes that you might need to undo or modify.
+
+Before you can use the `dartfix` tool, you need to
+[install it](#installing-and-updating-dartfix), as described below.
+Then invoke it with the name of the directory that you want to update.
+When you're ready to make the suggested changes,
+add the `--overwrite` option.
+
+```terminal
+$ dartfix examples/misc
+... summary of recommended changes ...
+$ dartfix examples/misc --overwrite
```
-Once activated, dart fix can be run using
+## Features
+
+As of release 0.1.3, `dartfix` can make the following changes to your code:
+
+* Convert code to use the following [features added to Dart in 2.1][]:
+ * Find classes used as mixins, and convert them to use the `mixin` keyword
+ instead of `class`.
+ * Find `double` literals that end in `.0`, and remove the `.0`.
+* Move named constructor type arguments from the name to the type. <br>
+ For example, given `class A<T> { A.from(Object obj) { } }`,
+ `dartfix` changes constructor invocations in the following way:
+
+ ```
+ Original code:
+ A.from<String>(anObject) // Invokes the `A.from` named constructor.
+
+ Code produced by dartfix:
+ A<String>.from(anObject) // Same, but the type is directly after `A`.
+ ```
+
+## Installing and updating dartfix
+
+The easiest way to use `dartfix` is to [globally install][] it,
+so that it can be [in your path][PATH]:
+
+```terminal
+$ pub global activate dartfix
```
- pub global run dartfix:fix <target directory>
-```
-or if you have
-[setup your path](https://www.dartlang.org/tools/pub/cmd/pub-global#running-a-script-from-your-path)
-to include the pub bin directory, then simply
-```
- dartfix <target directory>
-```
+
+Use the same command to update `dartfix`.
+We recommend updating `dartfix` whenever you update your Dart SDK
+or when a new feature is released.
+
+## Options
+
+<dl>
+ <dt><code>--[no-]color</code></dt>
+ <dd> Use colors when printing messages. On by default. </dd>
+
+ <dt><code>-f, --force</code></dt>
+ <dd>Apply the recommended changes even if the input code has errors.
+ </dd>
+
+ <dt><code>-h, --help</code></dt>
+ <dd>See a complete list of `dartfix` options.</dd>
+
+ <dt><code>-v, --verbose</code></dt>
+ <dd>Verbose output.</dd>
+
+ <dt><code>-w, --overwrite</code></dt>
+ <dd>Apply the recommended changes.</dd>
+</dl>
+
+
+## Filing issues
+
+If you want a new fix, first look at [dartfix issues][]
+and star the fixes you want.
+If no issue exists for the fix, [create a GitHub issue.][new issue]
+
+[dartfix]: https://pub.dartlang.org/packages/dartfix
+[dartfmt]: https://www.dartlang.org/tools/dartfmt
+[features added to Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
+[globally install]: https://www.dartlang.org/tools/pub/cmd/pub-global
+[new issue]: https://github.com/dart-lang/sdk/issues/new?title=dartfix%20request%3A%20%3CSUMMARIZE%20REQUEST%20HERE%3E
+[dartfix issues]: https://github.com/dart-lang/sdk/issues?q=is%3Aissue+is%3Aopen+label%3Aanalyzer-dartfix
+[PATH]: https://www.dartlang.org/tools/pub/cmd/pub-global#running-a-script-from-your-path
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 6edbe05..d8063b5 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -74,7 +74,7 @@
final Dart2TypeSystem rules;
/// Errors that were produced during compilation, if any.
- final List<AnalysisError> errors;
+ final ErrorCollector errors;
JSTypeRep jsTypeRep;
@@ -5681,8 +5681,10 @@
var nearest = (lexeme.startsWith("0x") || lexeme.startsWith("0X"))
? '0x${valueInJS.toRadixString(16)}'
: '$valueInJS';
- errors.add(AnalysisError(_currentCompilationUnit.source, node.offset,
- node.length, invalidJSInteger, [lexeme, nearest]));
+ errors.add(
+ _currentCompilationUnit.lineInfo,
+ AnalysisError(_currentCompilationUnit.source, node.offset,
+ node.length, invalidJSInteger, [lexeme, nearest]));
}
return JS.LiteralNumber('$valueInJS');
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index aa5d565..cec419b 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -9,14 +9,15 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
-import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -241,16 +242,13 @@
var bundle = PackageBundle.fromBuffer(summaryBytes);
/// Create an analysis context to contain the state for this build unit.
- var context =
- AnalysisEngine.instance.createAnalysisContext() as AnalysisContextImpl;
- context.sourceFactory = sourceFactory;
+ var context = RestrictedAnalysisContext(
+ analysisOptions, declaredVariables, sourceFactory);
var resultProvider = InputPackagesResultProvider(
context,
SummaryDataStore([])
..addStore(summaryData)
..addBundle(null, bundle));
- context.resultProvider = resultProvider;
- context.contentCache = _ContentCacheWrapper(fsState);
var resynthesizer = resultProvider.resynthesizer;
_extensionTypes ??= ExtensionTypeSet(context.typeProvider, resynthesizer);
@@ -315,10 +313,7 @@
this._fsState,
this._resourceProvider);
- AnalysisContextImpl get context => resynthesizer.context;
-
- /// Clean up any state used by this driver.
- void dispose() => context.dispose();
+ TypeProvider get typeProvider => resynthesizer.typeProvider;
/// True if [uri] refers to a Dart library (i.e. a Dart source file exists
/// with this uri, and it is not a part file).
@@ -339,9 +334,9 @@
declaredVariables,
resynthesizer.sourceFactory,
(uri) => _isLibraryUri('$uri'),
- context,
+ resynthesizer.context,
resynthesizer,
- InheritanceManager2(context.typeSystem),
+ InheritanceManager2(resynthesizer.typeSystem),
libraryFile,
_resourceProvider);
// TODO(jmesserly): ideally we'd use the existing public `analyze()` method,
@@ -360,51 +355,3 @@
return resynthesizer.getLibraryElement(uri);
}
}
-
-/// [ContentCache] wrapper around [FileSystemState].
-class _ContentCacheWrapper implements ContentCache {
- final FileSystemState fsState;
-
- _ContentCacheWrapper(this.fsState);
-
- @override
- void accept(ContentCacheVisitor visitor) {
- throw new UnimplementedError();
- }
-
- @override
- String getContents(Source source) {
- return _getFileForSource(source).content;
- }
-
- @override
- bool getExists(Source source) {
- if (source.isInSystemLibrary) {
- return true;
- }
- String uriStr = source.uri.toString();
- if (fsState.externalSummaries != null &&
- fsState.externalSummaries.hasUnlinkedUnit(uriStr)) {
- return true;
- }
- return _getFileForSource(source).exists;
- }
-
- @override
- int getModificationStamp(Source source) {
- if (source.isInSystemLibrary) {
- return 0;
- }
- return _getFileForSource(source).exists ? 0 : -1;
- }
-
- @override
- String setContents(Source source, String contents) {
- throw new UnimplementedError();
- }
-
- FileState _getFileForSource(Source source) {
- String path = source.fullName;
- return fsState.getFileForPath(path);
- }
-}
diff --git a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
index 0943c39..1528546 100644
--- a/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/error_helpers.dart
@@ -2,33 +2,87 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:collection';
+
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/error_processor.dart' show ErrorProcessor;
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions;
import 'package:path/path.dart' as path;
-/// Sorts and formats errors, returning the error messages.
-List<String> formatErrors(AnalysisContext context, List<AnalysisError> errors) {
- sortErrors(context, errors);
- var result = <String>[];
- for (var e in errors) {
- var m = formatError(context, e);
- if (m != null) result.add(m);
- }
- return result;
-}
+class ErrorCollector {
+ final bool _replCompile;
+ final AnalysisOptions _options;
+ SplayTreeMap<AnalysisError, String> _errors;
-// TODO(jmesserly): this code was taken from analyzer_cli.
-// It really should be in some common place so we can share it.
-// TODO(jmesserly): this shouldn't depend on `context` but we need it to compute
-// `errorSeverity` due to some APIs that need fixing.
-void sortErrors(AnalysisContext context, List<AnalysisError> errors) {
- errors.sort((AnalysisError error1, AnalysisError error2) {
+ ErrorCollector(this._options, this._replCompile) {
+ _errors = SplayTreeMap<AnalysisError, String>(_compareErrors);
+ }
+
+ bool get hasFatalErrors => _errors.keys.any(_isFatalError);
+
+ Iterable<String> get formattedErrors => _errors.values;
+
+ void add(LineInfo lineInfo, AnalysisError error) {
+ if (_shouldIgnoreError(error)) return;
+
+ // Skip hints, some like TODOs are not useful.
+ if (_errorSeverity(error).ordinal <= ErrorSeverity.INFO.ordinal) return;
+
+ _errors[error] = _formatError(lineInfo, error);
+ }
+
+ void addAll(LineInfo lineInfo, Iterable<AnalysisError> errors) {
+ for (var e in errors) add(lineInfo, e);
+ }
+
+ ErrorSeverity _errorSeverity(AnalysisError error) {
+ var errorCode = error.errorCode;
+ if (errorCode == StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_BLOCK ||
+ errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_GETTER ||
+ errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_METHOD) {
+ // These are normally hints, but they should be errors when running DDC, so
+ // that users won't be surprised by behavioral differences between DDC and
+ // dart2js.
+ return ErrorSeverity.ERROR;
+ }
+
+ // TODO(jmesserly): remove support for customizing error levels via
+ // analysis_options from DDC. (it won't work with --kernel).
+ return ErrorProcessor.getProcessor(_options, error)?.severity ??
+ errorCode.errorSeverity;
+ }
+
+ String _formatError(LineInfo lineInfo, AnalysisError error) {
+ var location = lineInfo.getLocation(error.offset);
+
+ // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
+ return (StringBuffer()
+ ..write('[${_errorSeverity(error).displayName}] ')
+ ..write(error.message)
+ ..write(' (${path.prettyUri(error.source.uri)}')
+ ..write(
+ ', line ${location.lineNumber}, col ${location.columnNumber})'))
+ .toString();
+ }
+
+ bool _shouldIgnoreError(AnalysisError error) {
+ var uri = error.source.uri;
+ if (uri.scheme != 'dart') return false;
+ var sdkLib = uri.pathSegments[0];
+ if (sdkLib == 'html' || sdkLib == 'svg' || sdkLib == '_interceptors') {
+ var c = error.errorCode;
+ return c == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 ||
+ c == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 ||
+ c == StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS;
+ }
+ return false;
+ }
+
+ int _compareErrors(AnalysisError error1, AnalysisError error2) {
// severity
- var severity1 = errorSeverity(context, error1);
- var severity2 = errorSeverity(context, error2);
- int compare = severity2.compareTo(severity1);
+ int compare = _errorSeverity(error2).compareTo(_errorSeverity(error1));
if (compare != 0) return compare;
// path
@@ -42,64 +96,22 @@
// compare message, in worst case.
return error1.message.compareTo(error2.message);
- });
-}
-
-// TODO(jmesserly): this was from analyzer_cli, we should factor it differently.
-String formatError(AnalysisContext context, AnalysisError error) {
- var severity = errorSeverity(context, error);
- // Skip hints, some like TODOs are not useful.
- if (severity.ordinal <= ErrorSeverity.INFO.ordinal) return null;
-
- var lineInfo = context.computeLineInfo(error.source);
- var location = lineInfo.getLocation(error.offset);
-
- // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2)
- return (StringBuffer()
- ..write('[${severity.displayName}] ')
- ..write(error.message)
- ..write(' (${path.prettyUri(error.source.uri)}')
- ..write(', line ${location.lineNumber}, col ${location.columnNumber})'))
- .toString();
-}
-
-ErrorSeverity errorSeverity(AnalysisContext context, AnalysisError error) {
- var errorCode = error.errorCode;
- if (errorCode == StrongModeCode.TOP_LEVEL_FUNCTION_LITERAL_BLOCK ||
- errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_GETTER ||
- errorCode == StrongModeCode.TOP_LEVEL_INSTANCE_METHOD) {
- // These are normally hints, but they should be errors when running DDC, so
- // that users won't be surprised by behavioral differences between DDC and
- // dart2js.
- return ErrorSeverity.ERROR;
}
- // TODO(jmesserly): this Analyzer API totally bonkers, but it's what
- // analyzer_cli and server use.
- //
- // Among the issues with ErrorProcessor.getProcessor:
- // * it needs to be called per-error, so it's a performance trap.
- // * it can return null
- // * using AnalysisError directly is now suspect, it's a correctness trap
- // * it requires an AnalysisContext
- return ErrorProcessor.getProcessor(context.analysisOptions, error)
- ?.severity ??
- errorCode.errorSeverity;
-}
+ bool _isFatalError(AnalysisError e) {
+ if (_errorSeverity(e) != ErrorSeverity.ERROR) return false;
-bool isFatalError(AnalysisContext context, AnalysisError e, bool replCompile) {
- if (errorSeverity(context, e) != ErrorSeverity.ERROR) return false;
-
- // These errors are not fatal in the REPL compile mode as we
- // allow access to private members across library boundaries
- // and those accesses will show up as undefined members unless
- // additional analyzer changes are made to support them.
- // TODO(jacobr): consider checking that the identifier name
- // referenced by the error is private.
- return !replCompile ||
- (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER &&
- e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER &&
- e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD);
+ // These errors are not fatal in the REPL compile mode as we
+ // allow access to private members across library boundaries
+ // and those accesses will show up as undefined members unless
+ // additional analyzer changes are made to support them.
+ // TODO(jacobr): consider checking that the identifier name
+ // referenced by the error is private.
+ return !_replCompile ||
+ (e.errorCode != StaticTypeWarningCode.UNDEFINED_GETTER &&
+ e.errorCode != StaticTypeWarningCode.UNDEFINED_SETTER &&
+ e.errorCode != StaticTypeWarningCode.UNDEFINED_METHOD);
+ }
}
const invalidImportDartMirrors = StrongModeCode(
diff --git a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
index 120f7dc..851d47b 100644
--- a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
@@ -18,7 +18,7 @@
final ClassElement _jsString;
JSTypeRep(this.rules, LinkedAnalysisDriver driver)
- : types = driver.context.typeProvider,
+ : types = driver.typeProvider,
_jsBool = driver.getClass('dart:_interceptors', 'JSBool'),
_jsString = driver.getClass('dart:_interceptors', 'JSString'),
_jsNumber = driver.getClass('dart:_interceptors', 'JSNumber');
diff --git a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
index f62c54c..179dbb1 100644
--- a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
@@ -10,7 +10,6 @@
show LibraryElement, UriReferencedElement;
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:args/args.dart' show ArgParser, ArgResults;
import 'package:path/path.dart' as path;
@@ -57,7 +56,6 @@
AnalyzerOptions analyzerOptions,
CompilerOptions options) {
var trees = <CompilationUnit>[];
- var errors = <AnalysisError>[];
var explicitSources = <Uri>[];
var compilingSdk = false;
@@ -70,7 +68,17 @@
}
var driver = compilerDriver.linkLibraries(explicitSources, analyzerOptions);
+ var errors = ErrorCollector(driver.analysisOptions, options.replCompile);
for (var libraryUri in driver.libraryUris) {
+ var analysisResults = driver.analyzeLibrary(libraryUri);
+
+ CompilationUnit definingUnit;
+ for (var result in analysisResults.values) {
+ if (result.file.uriStr == libraryUri) definingUnit = result.unit;
+ errors.addAll(result.unit.lineInfo, result.errors);
+ trees.add(result.unit);
+ }
+
var library = driver.getLibrary(libraryUri);
// TODO(jmesserly): remove "dart:mirrors" from DDC's SDK, and then remove
@@ -78,29 +86,19 @@
if (!compilingSdk && !options.emitMetadata) {
var node = _getDartMirrorsImport(library);
if (node != null) {
- errors.add(AnalysisError(library.source, node.uriOffset, node.uriEnd,
- invalidImportDartMirrors));
+ errors.add(
+ definingUnit.lineInfo,
+ AnalysisError(library.source, node.uriOffset, node.uriEnd,
+ invalidImportDartMirrors));
}
}
-
- var analysisResults = driver.analyzeLibrary(libraryUri);
- for (var result in analysisResults.values) {
- errors.addAll(_filterJsErrors(libraryUri, result.errors));
- trees.add(result.unit);
- }
- }
-
- var context = driver.context;
-
- bool anyFatalErrors() {
- return errors.any((e) => isFatalError(context, e, options.replCompile));
}
JS.Program jsProgram;
- if (options.unsafeForceCompile || !anyFatalErrors()) {
+ if (options.unsafeForceCompile || !errors.hasFatalErrors) {
var codeGenerator = CodeGenerator(
driver,
- driver.context.typeProvider,
+ driver.typeProvider,
compilerDriver.summaryData,
options,
compilerDriver.extensionTypes,
@@ -110,37 +108,19 @@
} catch (e) {
// If force compilation failed, suppress the exception and report the
// static errors instead. Otherwise, rethrow an internal compiler error.
- if (!anyFatalErrors()) rethrow;
+ if (!errors.hasFatalErrors) rethrow;
}
- if (!options.unsafeForceCompile && anyFatalErrors()) {
+ if (!options.unsafeForceCompile && errors.hasFatalErrors) {
jsProgram = null;
}
}
var jsModule = JSModuleFile(
- formatErrors(context, errors), options, jsProgram, driver.summaryBytes);
- driver.dispose();
+ errors.formattedErrors.toList(), options, jsProgram, driver.summaryBytes);
return jsModule;
}
-Iterable<AnalysisError> _filterJsErrors(
- String libraryUriStr, Iterable<AnalysisError> errors) {
- if (libraryUriStr == 'dart:html' ||
- libraryUriStr == 'dart:svg' ||
- libraryUriStr == 'dart:_interceptors') {
- return errors.where((error) {
- return error.errorCode !=
- StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 &&
- error.errorCode !=
- StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 &&
- error.errorCode !=
- StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS;
- });
- }
- return errors;
-}
-
UriReferencedElement _getDartMirrorsImport(LibraryElement library) {
return library.imports.firstWhere(_isDartMirrorsImort, orElse: () => null) ??
library.exports.firstWhere(_isDartMirrorsImort, orElse: () => null);
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 503c60f..5c91caa 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -883,8 +883,7 @@
summaryData.addBundle(null, sdkSummaryBundle);
}
- // TODO(jmesserly): can we avoid creating an analysis context entirely?
- // It doesn't look like StoreBasedSummaryResynthesizer uses much of it.
+ // TODO(jmesserly): use RestrictedAnalysisContext.
var context = a.AnalysisEngine.instance.createAnalysisContext()
as a.AnalysisContextImpl;
context.sourceFactory = a.SourceFactory(
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 6a31922..035611f 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -116,6 +116,8 @@
final TypeEnvironment types;
+ final ClassHierarchy hierarchy;
+
/// Information about virtual and overridden fields/getters/setters in the
/// class we're currently compiling, or `null` if we aren't compiling a class.
ClassPropertyModel _classProperties;
@@ -202,9 +204,9 @@
var types = TypeSchemaEnvironment(coreTypes, hierarchy);
var constants = DevCompilerConstants(types, declaredVariables);
var nativeTypes = NativeTypeSet(coreTypes, constants);
- var jsTypeRep = JSTypeRep(types);
+ var jsTypeRep = JSTypeRep(types, hierarchy);
return ProgramCompiler._(coreTypes, coreTypes.index, nativeTypes, constants,
- types, jsTypeRep, NullableInference(jsTypeRep), options);
+ types, hierarchy, jsTypeRep, NullableInference(jsTypeRep), options);
}
ProgramCompiler._(
@@ -213,6 +215,7 @@
this._extensionTypes,
this._constants,
this.types,
+ this.hierarchy,
this._typeRep,
this._nullableInference,
this.options)
@@ -230,8 +233,6 @@
syncIterableClass = sdk.getClass('dart:_js_helper', 'SyncIterable'),
asyncStarImplClass = sdk.getClass('dart:async', '_AsyncStarImpl');
- ClassHierarchy get hierarchy => types.hierarchy;
-
Uri get currentLibraryUri => _currentLibrary.importUri;
bool get emitMetadata => options.emitMetadata;
@@ -5118,6 +5119,14 @@
visitTypeLiteralConstant(node) => defaultConstant(node);
@override
visitPartialInstantiationConstant(node) => defaultConstant(node);
+ @override
+ visitEnvironmentBoolConstant(node) => defaultConstant(node);
+ @override
+ visitEnvironmentIntConstant(node) => defaultConstant(node);
+ @override
+ visitEnvironmentStringConstant(node) => defaultConstant(node);
+ @override
+ visitUnevaluatedConstant(node) => defaultConstant(node);
}
bool isSdkInternalRuntime(Library l) =>
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index 52329f7..b05b840 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -187,8 +187,7 @@
{bool enableAsserts: false})
: unavailableConstant = InstanceConstant(null, [], {}),
super(_ConstantsBackend(types.coreTypes), types, types.coreTypes,
- enableAsserts,
- errorReporter: const _ErrorReporter()) {
+ enableAsserts, const _ErrorReporter()) {
env = EvaluationEnvironment();
}
@@ -311,7 +310,7 @@
lowerListConstant(constant) => constant;
}
-class _ErrorReporter extends ErrorReporterBase {
+class _ErrorReporter extends SimpleErrorReporter {
const _ErrorReporter();
@override
diff --git a/pkg/dev_compiler/lib/src/kernel/js_typerep.dart b/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
index b43b1b0..7c4cba7 100644
--- a/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
@@ -2,6 +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.
+import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/type_environment.dart';
@@ -9,13 +10,14 @@
class JSTypeRep extends SharedJSTypeRep<DartType> {
final TypeEnvironment types;
+ final ClassHierarchy hierarchy;
final CoreTypes coreTypes;
final Class _jsBool;
final Class _jsNumber;
final Class _jsString;
- JSTypeRep(this.types)
+ JSTypeRep(this.types, this.hierarchy)
: coreTypes = types.coreTypes,
_jsBool =
types.coreTypes.index.getClass('dart:_interceptors', 'JSBool'),
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 8e212cf..76b6570 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -146,7 +146,8 @@
// This allows us to find the `@notNull` annotation if it exists.
var implClass = jsTypeRep.getImplementationClass(targetClass.rawType);
if (implClass != null) {
- var member = types.hierarchy.getDispatchTarget(implClass, target.name);
+ var member =
+ jsTypeRep.hierarchy.getDispatchTarget(implClass, target.name);
if (member != null) target = member;
}
}
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index 73981f7..e7cb728 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -487,8 +487,10 @@
@override
visitComponent(Component node) {
+ var hierarchy = ClassHierarchy(node);
inference ??= NullableInference(JSTypeRep(
- fe.TypeSchemaEnvironment(CoreTypes(node), ClassHierarchy(node)),
+ fe.TypeSchemaEnvironment(CoreTypes(node), hierarchy),
+ hierarchy,
));
if (useAnnotations) {
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
index ab94a36..781a0c9 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
@@ -572,3 +572,30 @@
iterator);
}
}
+
+@patch
+abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
+ @patch
+ Node _splayMin(Node node) {
+ Node current = node;
+ while (current.left != null) {
+ Node left = current.left;
+ current.left = left.right;
+ left.right = current;
+ current = left;
+ }
+ return current;
+ }
+
+ @patch
+ Node _splayMax(Node node) {
+ Node current = node;
+ while (current.right != null) {
+ Node right = current.right;
+ current.right = right.left;
+ right.left = current;
+ current = right;
+ }
+ return current;
+ }
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
index 7c96274..70ccace 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
@@ -81,8 +81,8 @@
}
}
}
- return "Type '${typeName(from)}' is not a subtype of "
- "expected type '${typeName(to)}'.";
+ return "Expected a value of type '${typeName(to)}', "
+ "but got one of type '${typeName(from)}'";
}
/// The symbol that references the thrown Dart Object (typically but not
@@ -156,8 +156,11 @@
/// Subclass of JS `Error` that wraps a thrown Dart object, and evaluates the
/// message lazily by calling `toString()` on the wrapped Dart object.
///
-/// Also creates a pointer from the Dart [Error] to the JS Error
-/// (via [_jsError]). This is used to implement [Error.stackTrace].
+/// Also creates a pointer from the thrown Dart object to the JS Error
+/// (via [_jsError]). This is used to implement [Error.stackTrace], but also
+/// provides a way to recover the stack trace if we lose track of it.
+/// [Error] requires preserving the original stack trace if an error is
+/// rethrown, so we only update the pointer if it wasn't already set.
///
/// TODO(jmesserly): Dart Errors should simply be JS Errors.
final Object DartError = JS(
@@ -166,14 +169,15 @@
constructor(error) {
super();
this[#] = error;
- if (error instanceof # && error[#] == null) error[#] = this;
+ if (error != null && typeof error == "object" && error[#] == null) {
+ error[#] = this;
+ }
}
get message() {
return #(this[#]);
}
}''',
_thrownValue,
- Error,
_jsError,
_jsError,
_toString,
@@ -222,7 +226,15 @@
/// the correct JS stack trace (visible if JavaScript ends up handling it). To
/// fix that, we use [RethrownDartError] to preserve the Dart trace and make
/// sure it gets displayed in the JS error message.
+///
+/// If the stack trace is null, this will preserve the original stack trace
+/// on the exception, if available, otherwise it will capture the current stack
+/// trace.
Object createErrorWithStack(Object exception, StackTrace trace) {
+ if (trace == null) {
+ var error = JS('', '#[#]', exception, _jsError);
+ return error != null ? error : JS('', 'new #(#)', DartError, exception);
+ }
if (trace is _StackTrace) {
/// Optimization: if this stack trace and exception already have a matching
/// Error, we can just rethrow it.
@@ -231,9 +243,7 @@
return originalError;
}
}
- var error = JS('', 'new #(#)', RethrownDartError, exception);
- JS('', '#[#] = #', error, _stackTrace, trace);
- return error;
+ return JS('', 'new #(#, #)', RethrownDartError, exception, trace);
}
// This is a utility function: it is only intended to be called from dev
diff --git a/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart b/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
index fb34f25..445f0cb 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/interceptors.dart
@@ -8,7 +8,7 @@
import 'dart:_internal' hide Symbol;
import 'dart:_js_helper';
import 'dart:_foreign_helper' show JS, JSExportName;
-import 'dart:math' show Random;
+import 'dart:math' show Random, ln2;
import 'dart:_runtime' as dart;
part 'js_array.dart';
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_number.dart b/pkg/dev_compiler/tool/input_sdk/private/js_number.dart
index f539a10..2a1fb74 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_number.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_number.dart
@@ -218,7 +218,40 @@
}
@notNull
- int get hashCode => JS('int', '# & 0x1FFFFFFF', this);
+ int get hashCode {
+ int intValue = JS('int', '# | 0', this);
+ // Fast exit for integers in signed 32-bit range. Masking converts -0.0 to 0
+ // and ensures that result fits in JavaScript engine's Smi range.
+ if (this == intValue) return 0x1FFFFFFF & intValue;
+
+ // We would like to access the exponent and mantissa as integers but there
+ // are no JavaScript operations that do this, so use log2-floor-pow-divide
+ // to extract the values.
+ num absolute = JS('num', 'Math.abs(#)', this);
+ num lnAbsolute = JS('num', 'Math.log(#)', absolute);
+ num log2 = lnAbsolute / ln2;
+ // Floor via '# | 0' converts NaN to zero so the final result is not NaN.
+ int floorLog2 = JS('int', '# | 0', log2);
+ num factor = JS('num', 'Math.pow(2, #)', floorLog2);
+ num scaled = absolute < 1 ? absolute / factor : factor / absolute;
+ // [scaled] is in the range [0.5, 1].
+
+ // Multiply and truncate to pick up all the mantissa bits. Multiplying by
+ // 0x20000000000000 (which has 53 zero bits) converts the mantissa into an
+ // integer. There are interesting subsets where all the bit variance is in
+ // the most significant bits of the mantissa (e.g. 0.5, 0.625, 0.75), so we
+ // need to mix in the most significant bits. We do this by scaling with a
+ // constant that has many bits set to use the multiplier to mix in bits from
+ // all over the mantissa into low positions.
+ num rescaled1 = scaled * 0x20000000000000;
+ num rescaled2 = scaled * 0x0C95A6C285A6C9;
+ int d1 = JS('int', '# | 0', rescaled1);
+ int d2 = JS('int', '# | 0', rescaled2);
+ // Mix in exponent to distinguish e.g. 1.25 from 2.5.
+ int d3 = floorLog2;
+ int h = 0x1FFFFFFF & ((d1 + d2) * (601 * 997) + d3 * (1259));
+ return h;
+ }
@notNull
JSNumber operator -() => JS('num', r'-#', this);
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 8e2ff95..9a59d3d 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -8,6 +8,8 @@
*/
library expect;
+import 'package:meta/meta.dart';
+
/**
* Expect is used for tests that do not want to make use of the
* Dart unit test library - for example, the core language tests.
@@ -265,6 +267,7 @@
}
// Unconditional failure.
+ @alwaysThrows
static void fail(String msg) {
_fail("Expect.fail('$msg')");
}
@@ -647,6 +650,7 @@
static String _getMessage(String reason) =>
(reason == null) ? "" : ", '$reason'";
+ @alwaysThrows
static void _fail(String message) {
throw new ExpectException(message);
}
diff --git a/pkg/expect/pubspec.yaml b/pkg/expect/pubspec.yaml
index d4b48a4..2a7405d 100644
--- a/pkg/expect/pubspec.yaml
+++ b/pkg/expect/pubspec.yaml
@@ -8,3 +8,6 @@
test assertions.
environment:
sdk: ">=0.8.10+6 <3.0.0"
+
+dependencies:
+ meta: any
diff --git a/pkg/front_end/analysis_options.yaml b/pkg/front_end/analysis_options.yaml
index d5ea4fe..ae13d06 100644
--- a/pkg/front_end/analysis_options.yaml
+++ b/pkg/front_end/analysis_options.yaml
@@ -9,6 +9,8 @@
# Allow having TODOs in the code
todo: ignore
- # Allow deprecated calls (although it would be nice to have a distinction
- # between internal and external deprecated calls).
+ # Allow cross-package deprecated calls
+ # TODO(srawlins): clean these up and remove this "ignore."
deprecated_member_use: ignore
+ # Allow deprecated calls from within the same package
+ deprecated_member_use_from_same_package: ignore
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index cb41df3..85222be 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -8,7 +8,7 @@
import 'diagnostic_message.dart' show DiagnosticMessageHandler;
-import 'experimental_flags.dart' show ExperimentalFlag;
+import 'experimental_flags.dart' show ExperimentalFlag, parseExperimentalFlag;
import 'file_system.dart' show FileSystem;
@@ -120,12 +120,12 @@
/// directly, while relative URIs are resolved from the [sdkRoot].
// TODO(sigmund): provide also a flag to load this data from a file (like
// libraries.json)
- Map<String, List<Uri>> targetPatches = {};
+ Map<String, List<Uri>> targetPatches = <String, List<Uri>>{};
/// Enable or disable experimental features. Features mapping to `true` are
/// explicitly enabled. Features mapping to `false` are explicitly disabled.
/// Features not mentioned in the map will have their default value.
- Map<ExperimentalFlag, bool> experimentalFlags = {};
+ Map<ExperimentalFlag, bool> experimentalFlags = <ExperimentalFlag, bool>{};
/// The target platform that will consume the compiled code.
///
@@ -192,4 +192,35 @@
/// Whether to generate bytecode.
bool bytecode = false;
+
+ /// Whether to write a file (e.g. a dill file) when reporting a crash.
+ bool writeFileOnCrashReport = true;
+}
+
+/// Parse experimental flags from a list of strings, each of which is either a
+/// flag name or a flag name prefixed by 'no-'. Return a map of flags to their
+/// values that can be passed to [experimentalFlags].
+///
+/// If an unknown flag is mentioned, or a flag is mentioned more than once,
+/// the supplied error handler is called with an error message.
+Map<ExperimentalFlag, bool> parseExperimentalFlags(
+ Iterable<String> experiments, void onError(String message)) {
+ Map<ExperimentalFlag, bool> flags = <ExperimentalFlag, bool>{};
+ if (experiments == null) return flags;
+ for (String experiment in experiments) {
+ bool value = true;
+ if (experiment.startsWith("no-")) {
+ value = false;
+ experiment = experiment.substring(3);
+ }
+ ExperimentalFlag flag = parseExperimentalFlag(experiment);
+ if (flag == null) {
+ onError("Unknown experiment: " + experiment);
+ } else if (flags.containsKey(flag)) {
+ onError("Experiment mentioned more than once: " + experiment);
+ } else {
+ flags[flag] = value;
+ }
+ }
+ return flags;
}
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 82225f3..188c88b 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -12,6 +12,8 @@
import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
+import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+
import '../api_prototype/file_system.dart' show FileSystem;
import '../base/processed_options.dart' show ProcessedOptions;
@@ -30,10 +32,13 @@
import 'compiler_state.dart' show InitializedCompilerState;
-export '../api_prototype/compiler_options.dart' show CompilerOptions;
+export '../api_prototype/compiler_options.dart'
+ show CompilerOptions, parseExperimentalFlags;
export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
+export '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+
export '../api_prototype/file_system.dart'
show FileSystem, FileSystemEntity, FileSystemException;
@@ -98,11 +103,22 @@
Target target,
Uri librariesSpecificationUri,
Uri sdkPlatformUri,
- Uri packagesFileUri) {
+ Uri packagesFileUri,
+ {Map<ExperimentalFlag, bool> experimentalFlags}) {
+ bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
+ if (a == null || b == null) return a == b;
+ if (a.length != b.length) return false;
+ for (var flag in a.keys) {
+ if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
+ }
+ return true;
+ }
+
if (oldState != null &&
oldState.options.packagesFileUri == packagesFileUri &&
oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
- oldState.options.linkedDependencies[0] == sdkPlatformUri) {
+ oldState.options.linkedDependencies[0] == sdkPlatformUri &&
+ mapEqual(oldState.options.experimentalFlags, experimentalFlags)) {
return oldState;
}
@@ -111,7 +127,8 @@
..legacyMode = target.legacyMode
..linkedDependencies = [sdkPlatformUri]
..librariesSpecificationUri = librariesSpecificationUri
- ..packagesFileUri = packagesFileUri;
+ ..packagesFileUri = packagesFileUri
+ ..experimentalFlags = experimentalFlags;
ProcessedOptions processedOpts = new ProcessedOptions(options: options);
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 206df5f..4ef234d 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -291,6 +291,9 @@
/// Whether to generate bytecode.
bool get bytecode => _raw.bytecode;
+ /// Whether to write a file (e.g. a dill file) when reporting a crash.
+ bool get writeFileOnCrashReport => _raw.writeFileOnCrashReport;
+
Target _target;
Target get target => _target ??=
_raw.target ?? new NoneTarget(new TargetFlags(legacyMode: legacyMode));
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 860d1cb..3c4f54a 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -61,6 +61,7 @@
/// superclass.
bool get isMixinApplication => mixedInType != null;
+ @override
bool get isNamedMixinApplication {
return isMixinApplication && super.isNamedMixinApplication;
}
diff --git a/pkg/front_end/lib/src/fasta/builder/declaration.dart b/pkg/front_end/lib/src/fasta/builder/declaration.dart
index d340033..1584102 100644
--- a/pkg/front_end/lib/src/fasta/builder/declaration.dart
+++ b/pkg/front_end/lib/src/fasta/builder/declaration.dart
@@ -60,6 +60,10 @@
bool get isTypeVariable => false;
+ bool get isMixinApplication => false;
+
+ bool get isNamedMixinApplication => false;
+
/// Applies [patch] to this declaration.
void applyPatch(Declaration patch) {
unsupported("${runtimeType}.applyPatch", charOffset, fileUri);
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index a7a9771..e4f8c41 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -29,8 +29,6 @@
bool get isTypeDeclaration => true;
- bool get isMixinApplication => false;
-
@override
String get fullNameForErrors => name;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index 4f3acc7..7d8cea1 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -14,7 +14,7 @@
TypeVariableBuilder(
String name, this.bound, LibraryBuilder compilationUnit, int charOffset)
- : super(null, null, name, compilationUnit, charOffset);
+ : super(null, 0, name, compilationUnit, charOffset);
bool get isTypeVariable => true;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index fb395c3..bba4295 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -4,7 +4,7 @@
library fasta.dill_class_builder;
-import 'package:kernel/ast.dart' show Class, DartType, Member;
+import 'package:kernel/ast.dart' show Class, DartType, Member, Supertype;
import '../problems.dart' show unimplemented;
@@ -18,10 +18,10 @@
import '../modifier.dart' show abstractMask;
-import 'dill_member_builder.dart' show DillMemberBuilder;
-
import 'dill_library_builder.dart' show DillLibraryBuilder;
+import 'dill_member_builder.dart' show DillMemberBuilder;
+
class DillClassBuilder extends KernelClassBuilder {
final Class cls;
@@ -41,6 +41,17 @@
parent,
cls.fileOffset);
+ KernelTypeBuilder get supertype {
+ KernelTypeBuilder supertype = super.supertype;
+ if (supertype == null) {
+ Supertype targetSupertype = cls.supertype;
+ if (targetSupertype == null) return null;
+ super.supertype =
+ supertype = computeTypeBuilder(library, targetSupertype);
+ }
+ return supertype;
+ }
+
@override
Class get actualCls => cls;
@@ -88,7 +99,9 @@
/// superclass.
bool get isMixinApplication => cls.isMixinApplication;
- KernelTypeBuilder get mixedInType => unimplemented("mixedInType", -1, null);
+ KernelTypeBuilder get mixedInType {
+ return computeTypeBuilder(library, cls.mixedInType);
+ }
void set mixedInType(KernelTypeBuilder mixin) {
unimplemented("mixedInType=", -1, null);
@@ -98,3 +111,10 @@
int computeModifiers(Class cls) {
return cls.isAbstract ? abstractMask : 0;
}
+
+KernelTypeBuilder computeTypeBuilder(
+ DillLibraryBuilder library, Supertype supertype) {
+ return supertype == null
+ ? null
+ : library.loader.computeTypeBuilder(supertype.asInterfaceType);
+}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index 2a4eb8d..026c070 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -6,14 +6,37 @@
import 'dart:async' show Future;
-import 'package:kernel/ast.dart' show Library, Component, Source;
+import 'package:kernel/ast.dart'
+ show
+ BottomType,
+ Class,
+ Component,
+ DartType,
+ DartTypeVisitor,
+ DynamicType,
+ FunctionType,
+ InterfaceType,
+ InvalidType,
+ Library,
+ Source,
+ TypeParameter,
+ TypeParameterType,
+ TypedefType,
+ VoidType;
import '../fasta_codes.dart'
show SummaryTemplate, Template, templateDillOutlineSummary;
import '../compiler_context.dart' show CompilerContext;
-import '../kernel/kernel_builder.dart' show LibraryBuilder;
+import '../kernel/kernel_builder.dart'
+ show
+ DynamicTypeBuilder,
+ KernelNamedTypeBuilder,
+ KernelTypeBuilder,
+ KernelTypeVariableBuilder,
+ LibraryBuilder,
+ VoidTypeBuilder;
import '../loader.dart' show Loader;
@@ -21,6 +44,8 @@
import '../target_implementation.dart' show TargetImplementation;
+import 'dill_class_builder.dart' show DillClassBuilder;
+
import 'dill_library_builder.dart' show DillLibraryBuilder;
class DillLoader extends Loader<Library> {
@@ -75,4 +100,72 @@
library.finalizeExports();
});
}
+
+ KernelTypeBuilder computeTypeBuilder(DartType type) {
+ return type.accept(new TypeBuilderComputer(this));
+ }
+}
+
+class TypeBuilderComputer implements DartTypeVisitor<KernelTypeBuilder> {
+ final DillLoader loader;
+
+ const TypeBuilderComputer(this.loader);
+
+ KernelTypeBuilder defaultDartType(DartType node) {
+ throw "Unsupported";
+ }
+
+ KernelTypeBuilder visitInvalidType(InvalidType node) {
+ throw "Not implemented";
+ }
+
+ KernelTypeBuilder visitDynamicType(DynamicType node) {
+ return new KernelNamedTypeBuilder("dynamic", null)
+ ..bind(new DynamicTypeBuilder<KernelTypeBuilder, DartType>(
+ const DynamicType(), loader.coreLibrary, -1));
+ }
+
+ KernelTypeBuilder visitVoidType(VoidType node) {
+ return new KernelNamedTypeBuilder("dynamic", null)
+ ..bind(new VoidTypeBuilder<KernelTypeBuilder, VoidType>(
+ const VoidType(), loader.coreLibrary, -1));
+ }
+
+ KernelTypeBuilder visitBottomType(BottomType node) {
+ throw "Not implemented";
+ }
+
+ KernelTypeBuilder visitInterfaceType(InterfaceType node) {
+ Class kernelClass = node.classNode;
+ Library kernelLibrary = kernelClass.enclosingLibrary;
+ DillLibraryBuilder library = loader.builders[kernelLibrary.importUri];
+ String name = kernelClass.name;
+ DillClassBuilder cls = library[name];
+ List<KernelTypeBuilder> arguments;
+ List<DartType> kernelArguments = node.typeArguments;
+ if (kernelArguments.isNotEmpty) {
+ arguments = new List<KernelTypeBuilder>(kernelArguments.length);
+ for (int i = 0; i < kernelArguments.length; i++) {
+ arguments[i] = kernelArguments[i].accept(this);
+ }
+ }
+ return new KernelNamedTypeBuilder(name, arguments)..bind(cls);
+ }
+
+ KernelTypeBuilder visitFunctionType(FunctionType node) {
+ throw "Not implemented";
+ }
+
+ KernelTypeBuilder visitTypeParameterType(TypeParameterType node) {
+ TypeParameter parameter = node.parameter;
+ Class kernelClass = parameter.parent;
+ Library kernelLibrary = kernelClass.enclosingLibrary;
+ DillLibraryBuilder library = loader.builders[kernelLibrary.importUri];
+ return new KernelNamedTypeBuilder(parameter.name, null)
+ ..bind(new KernelTypeVariableBuilder.fromKernel(parameter, library));
+ }
+
+ KernelTypeBuilder visitTypedefType(TypedefType node) {
+ throw "Not implemented";
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index 7b54cd3..cfd35fb 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -62,6 +62,8 @@
name == "" &&
(charOffset == parent.charOffset || charOffset == -1);
}
+
+ bool get isField => member is Field;
}
int computeModifiers(Member member) {
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index bfea29e..3712941 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -3323,9 +3323,9 @@
commas, for example, --fatal=errors,warnings.
--enable-experiment=<flag>
- --disable-experiment=<flag>
Enable or disable an experimental flag, used to guard features currently
- in development. Multiple experiments can be separated by commas.""");
+ in development. Prefix an experiment name with 'no-' to disable it.
+ Multiple experiments can be separated by commas.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeFastaUsageShort = messageFastaUsageShort;
@@ -4550,27 +4550,67 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
- String
- string)> templateInitializeFromDillNotSelfContained = const Template<
- Message Function(String string)>(
+ String string,
+ Uri
+ uri_)> templateInitializeFromDillNotSelfContained = const Template<
+ Message Function(String string, Uri uri_)>(
messageTemplate:
- r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug. The Dart team would greatly appreciate if you would take a moment to report this problem at http://dartbug.com/new.""",
+ r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
withArguments: _withArgumentsInitializeFromDillNotSelfContained);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
+const Code<Message Function(String string, Uri uri_)>
codeInitializeFromDillNotSelfContained =
- const Code<Message Function(String string)>(
+ const Code<Message Function(String string, Uri uri_)>(
"InitializeFromDillNotSelfContained",
templateInitializeFromDillNotSelfContained,
severity: Severity.warning);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInitializeFromDillNotSelfContained(String string) {
+Message _withArgumentsInitializeFromDillNotSelfContained(
+ String string, Uri uri_) {
if (string.isEmpty) throw 'No string provided';
+ String uri = relativizeUri(uri_);
return new Message(codeInitializeFromDillNotSelfContained,
message:
- """Tried to initialize from a previous compilation (${string}), but the file was not self-contained. This might be a bug. The Dart team would greatly appreciate if you would take a moment to report this problem at http://dartbug.com/new.""",
+ """Tried to initialize from a previous compilation (${string}), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
+ arguments: {'string': string, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+ templateInitializeFromDillNotSelfContainedNoDump =
+ const Template<Message Function(String string)>(
+ messageTemplate:
+ r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
+ withArguments: _withArgumentsInitializeFromDillNotSelfContainedNoDump);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+ codeInitializeFromDillNotSelfContainedNoDump =
+ const Code<Message Function(String string)>(
+ "InitializeFromDillNotSelfContainedNoDump",
+ templateInitializeFromDillNotSelfContainedNoDump,
+ severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializeFromDillNotSelfContainedNoDump(String string) {
+ if (string.isEmpty) throw 'No string provided';
+ return new Message(codeInitializeFromDillNotSelfContainedNoDump,
+ message:
+ """Tried to initialize from a previous compilation (${string}), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
arguments: {'string': string});
}
@@ -4578,29 +4618,74 @@
const Template<
Message Function(
String string,
- String
- string2)> templateInitializeFromDillUnknownProblem = const Template<
- Message Function(String string, String string2)>(
+ String string2,
+ Uri
+ uri_)> templateInitializeFromDillUnknownProblem = const Template<
+ Message Function(String string, String string2, Uri uri_)>(
messageTemplate:
- r"""Tried to initialize from a previous compilation (#string), but couldn't. Error message was '#string2'. This might be a bug. The Dart team would greatly appreciate if you would take a moment to report this problem at http://dartbug.com/new.""",
+ r"""Tried to initialize from a previous compilation (#string), but couldn't.
+Error message was '#string2'. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
withArguments: _withArgumentsInitializeFromDillUnknownProblem);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
+const Code<Message Function(String string, String string2, Uri uri_)>
codeInitializeFromDillUnknownProblem =
- const Code<Message Function(String string, String string2)>(
+ const Code<Message Function(String string, String string2, Uri uri_)>(
"InitializeFromDillUnknownProblem",
templateInitializeFromDillUnknownProblem,
severity: Severity.warning);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsInitializeFromDillUnknownProblem(
+ String string, String string2, Uri uri_) {
+ if (string.isEmpty) throw 'No string provided';
+ if (string2.isEmpty) throw 'No string provided';
+ String uri = relativizeUri(uri_);
+ return new Message(codeInitializeFromDillUnknownProblem,
+ message:
+ """Tried to initialize from a previous compilation (${string}), but couldn't.
+Error message was '${string2}'. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
+ arguments: {'string': string, 'string2': string2, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String string2)>
+ templateInitializeFromDillUnknownProblemNoDump =
+ const Template<Message Function(String string, String string2)>(
+ messageTemplate:
+ r"""Tried to initialize from a previous compilation (#string), but couldn't.
+Error message was '#string2'. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
+ withArguments: _withArgumentsInitializeFromDillUnknownProblemNoDump);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+ codeInitializeFromDillUnknownProblemNoDump =
+ const Code<Message Function(String string, String string2)>(
+ "InitializeFromDillUnknownProblemNoDump",
+ templateInitializeFromDillUnknownProblemNoDump,
+ severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializeFromDillUnknownProblemNoDump(
String string, String string2) {
if (string.isEmpty) throw 'No string provided';
if (string2.isEmpty) throw 'No string provided';
- return new Message(codeInitializeFromDillUnknownProblem,
+ return new Message(codeInitializeFromDillUnknownProblemNoDump,
message:
- """Tried to initialize from a previous compilation (${string}), but couldn't. Error message was '${string2}'. This might be a bug. The Dart team would greatly appreciate if you would take a moment to report this problem at http://dartbug.com/new.""",
+ """Tried to initialize from a previous compilation (${string}), but couldn't.
+Error message was '${string2}'. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
arguments: {'string': string, 'string2': string2});
}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 91a78a6..795a5d9 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -52,10 +52,14 @@
import 'dill/dill_target.dart' show DillTarget;
+import 'util/error_reporter_file_copier.dart' show saveAsGzip;
+
import 'fasta_codes.dart'
show
templateInitializeFromDillNotSelfContained,
- templateInitializeFromDillUnknownProblem;
+ templateInitializeFromDillNotSelfContainedNoDump,
+ templateInitializeFromDillUnknownProblem,
+ templateInitializeFromDillUnknownProblemNoDump;
import 'hybrid_file_system.dart' show HybridFileSystem;
@@ -67,6 +71,8 @@
import 'library_graph.dart' show LibraryGraph;
+import 'messages.dart' show Message;
+
import 'source/source_library_builder.dart' show SourceLibraryBuilder;
import 'ticker.dart' show Ticker;
@@ -121,8 +127,7 @@
int bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
if (initializeFromDillUri != null) {
try {
- bytesLength +=
- await initializeFromDill(summaryBytes, uriTranslator, c, data);
+ bytesLength += await initializeFromDill(uriTranslator, c, data);
} catch (e) {
// We might have loaded x out of y libraries into the component.
// To avoid any unforeseen problems start over.
@@ -130,25 +135,37 @@
if (e is InvalidKernelVersionError || e is PackageChangedError) {
// Don't report any warning.
- } else if (e is CanonicalNameError) {
- dillLoadedData.loader.addProblem(
- templateInitializeFromDillNotSelfContained
- .withArguments(initializeFromDillUri.toString()),
- TreeNode.noOffset,
- 1,
- null);
} else {
- // Unknown error: Report problem as such.
- dillLoadedData.loader.addProblem(
- templateInitializeFromDillUnknownProblem.withArguments(
- initializeFromDillUri.toString(), "$e"),
- TreeNode.noOffset,
- 1,
- null);
+ Uri gzInitializedFrom;
+ if (c.options.writeFileOnCrashReport) {
+ gzInitializedFrom = saveAsGzip(
+ data.initializationBytes, "initialize_from.dill");
+ recordTemporaryFileForTesting(gzInitializedFrom);
+ }
+ if (e is CanonicalNameError) {
+ Message message = gzInitializedFrom != null
+ ? templateInitializeFromDillNotSelfContained.withArguments(
+ initializeFromDillUri.toString(), gzInitializedFrom)
+ : templateInitializeFromDillNotSelfContainedNoDump
+ .withArguments(initializeFromDillUri.toString());
+ dillLoadedData.loader
+ .addProblem(message, TreeNode.noOffset, 1, null);
+ } else {
+ // Unknown error: Report problem as such.
+ Message message = gzInitializedFrom != null
+ ? templateInitializeFromDillUnknownProblem.withArguments(
+ initializeFromDillUri.toString(),
+ "$e",
+ gzInitializedFrom)
+ : templateInitializeFromDillUnknownProblemNoDump
+ .withArguments(initializeFromDillUri.toString(), "$e");
+ dillLoadedData.loader
+ .addProblem(message, TreeNode.noOffset, 1, null);
+ }
}
}
} else if (componentToInitializeFrom != null) {
- initializeFromComponent(summaryBytes, uriTranslator, c, data);
+ initializeFromComponent(uriTranslator, c, data);
}
appendLibraries(data, bytesLength);
@@ -165,6 +182,7 @@
});
if (userBuilders.isEmpty) userBuilders = null;
}
+ data.initializationBytes = null;
Set<Uri> invalidatedUris = this.invalidatedUris.toSet();
if ((data.includeUserLoadedLibraries &&
@@ -256,10 +274,10 @@
List<Library> outputLibraries;
if (data.includeUserLoadedLibraries || fullComponent) {
outputLibraries = computeTransitiveClosure(compiledLibraries,
- mainMethod, entryPoint, reusedLibraries, data, hierarchy);
+ mainMethod, entryPoint, reusedLibraries, hierarchy);
} else {
computeTransitiveClosure(compiledLibraries, mainMethod, entryPoint,
- reusedLibraries, data, hierarchy);
+ reusedLibraries, hierarchy);
outputLibraries = compiledLibraries;
}
@@ -281,7 +299,6 @@
Procedure mainMethod,
Uri entry,
List<LibraryBuilder> reusedLibraries,
- IncrementalCompilerData data,
ClassHierarchy hierarchy) {
List<Library> result = new List<Library>.from(inputLibraries);
Map<Uri, Library> libraryMap = <Uri, Library>{};
@@ -351,10 +368,7 @@
}
// This procedure will try to load the dill file and will crash if it cannot.
- Future<int> initializeFromDill(
- List<int> summaryBytes,
- UriTranslator uriTranslator,
- CompilerContext c,
+ Future<int> initializeFromDill(UriTranslator uriTranslator, CompilerContext c,
IncrementalCompilerData data) async {
int bytesLength = 0;
FileSystemEntity entity =
@@ -363,6 +377,7 @@
List<int> initializationBytes = await entity.readAsBytes();
if (initializationBytes != null) {
ticker.logMs("Read $initializeFromDillUri");
+ data.initializationBytes = initializationBytes;
// We're going to output all we read here so lazy loading it
// doesn't make sense.
@@ -393,10 +408,7 @@
}
// This procedure will set up compiler from [componentToInitializeFrom].
- void initializeFromComponent(
- List<int> summaryBytes,
- UriTranslator uriTranslator,
- CompilerContext c,
+ void initializeFromComponent(UriTranslator uriTranslator, CompilerContext c,
IncrementalCompilerData data) {
ticker.logMs("Read initializeFromComponent");
@@ -671,6 +683,7 @@
}
void recordInvalidatedImportUrisForTesting(List<Uri> uris) {}
+ void recordTemporaryFileForTesting(Uri uri) {}
}
class PackageChangedError {
@@ -681,4 +694,5 @@
bool includeUserLoadedLibraries = false;
Procedure userLoadedUriMain = null;
Component component = null;
+ List<int> initializationBytes = null;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 61fe4bd..505559d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -17,6 +17,8 @@
messageInheritedMembersConflict,
messageInheritedMembersConflictCause1,
messageInheritedMembersConflictCause2,
+ templateDuplicatedDeclaration,
+ templateDuplicatedDeclarationCause,
templateMissingImplementationCause,
templateMissingImplementationNotAbstract;
@@ -45,6 +47,22 @@
return !name.isPrivate || name.library == library.target;
}
+/// Returns true if [a] is a class member conflict with [b]. [a] is assumed to
+/// be declared in the class, [b] is assumed to be inherited.
+///
+/// See the section named "Class Member Conflicts" in [Dart Programming
+/// Language Specification](
+/// ../../../../../../docs/language/dartLangSpec.tex#classMemberConflicts).
+bool isInheritanceConflict(Declaration a, Declaration b) {
+ if (a.isField) return !(b.isField || b.isGetter || b.isSetter);
+ if (b.isField) return !(a.isField || a.isGetter || a.isSetter);
+ return memberKind(a.target) != memberKind(b.target);
+}
+
+bool impliesSetter(Declaration declaration) {
+ return declaration.isField && !(declaration.isFinal || declaration.isConst);
+}
+
class ClassHierarchyBuilder {
final Map<KernelClassBuilder, ClassHierarchyNode> nodes =
<KernelClassBuilder, ClassHierarchyNode>{};
@@ -53,71 +71,105 @@
bool hasNoSuchMethod = false;
- int abstractMemberCount = 0;
+ List<Declaration> abstractMembers = null;
ClassHierarchyBuilder(this.objectClass);
- Declaration handleOverride(KernelClassBuilder cls, Declaration member,
- Declaration superMember, MergeKind mergeKind) {
- if (member.next != null || superMember.next != null) {
+ /// A merge conflict arises when merging two lists that each have an element
+ /// with the same name.
+ ///
+ /// If [mergeKind] is `MergeKind.superclass`, [a] should override [b].
+ ///
+ /// If [mergeKind] is `MergeKind.interfaces`, we need to record them and
+ /// solve the conflict later.
+ ///
+ /// If [mergeKind] is `MergeKind.supertypes`, [a] should implement [b], and
+ /// [b] is implicitly abstract.
+ Declaration handleMergeConflict(KernelClassBuilder cls, Declaration a,
+ Declaration b, MergeKind mergeKind) {
+ if (a == b) return a;
+ if (a.next != null || b.next != null) {
// Don't check overrides involving duplicated members.
- return member;
+ return a;
}
- Member target = member.target;
- Member superTarget = superMember.target;
- if ((memberKind(target) ?? ProcedureKind.Getter) !=
- (memberKind(superTarget) ?? ProcedureKind.Getter)) {
- String name = member.fullNameForErrors;
- if (mergeKind == MergeKind.interfaces) {
- cls.addProblem(messageInheritedMembersConflict, cls.charOffset,
- cls.fullNameForErrors.length,
- context: <LocatedMessage>[
- messageInheritedMembersConflictCause1.withLocation(
- member.fileUri, member.charOffset, name.length),
- messageInheritedMembersConflictCause2.withLocation(
- superMember.fileUri, superMember.charOffset, name.length),
- ]);
- } else {
- cls.addProblem(messageDeclaredMemberConflictsWithInheritedMember,
- member.charOffset, name.length,
- context: <LocatedMessage>[
- messageDeclaredMemberConflictsWithInheritedMemberCause
- .withLocation(
- superMember.fileUri, superMember.charOffset, name.length)
- ]);
- }
+ if (isInheritanceConflict(a, b)) {
+ reportInheritanceConflict(cls, a, b, mergeKind);
}
- if (target.name == noSuchMethodName && !target.isAbstract) {
- hasNoSuchMethod = true;
- }
- Declaration result = member;
+ Declaration result = a;
if (mergeKind == MergeKind.interfaces) {
- // TODO(ahe): Combine the signatures of member and superMember.
- } else if (target.isAbstract) {
- if (!superTarget.isAbstract) {
+ // TODO(ahe): Combine the signatures of a and b. See the section named
+ // "Combined Member Signatures" in [Dart Programming Language
+ // Specification](
+ // ../../../../../../docs/language/dartLangSpec.tex#combinedMemberSignatures).
+ } else if (a.target.isAbstract) {
+ if (mergeKind == MergeKind.superclass && !b.target.isAbstract) {
// An abstract method doesn't override an implemention inherited from a
// superclass.
- result = superMember;
+ result = b;
} else {
- abstractMemberCount++;
+ (abstractMembers ??= <Declaration>[]).add(a);
}
}
+
+ if (mergeKind == MergeKind.superclass &&
+ result.fullNameForErrors == noSuchMethodName.name &&
+ result.parent != objectClass) {
+ hasNoSuchMethod = true;
+ }
+
return result;
}
- void handleNewMember(Declaration member, MergeKind mergeKind) {
- Member target = member.target;
- if (mergeKind == MergeKind.superclass && target.isAbstract) {
- abstractMemberCount++;
+ void reportInheritanceConflict(KernelClassBuilder cls, Declaration a,
+ Declaration b, MergeKind mergeKind) {
+ String name = a.fullNameForErrors;
+ if (mergeKind == MergeKind.interfaces) {
+ cls.addProblem(messageInheritedMembersConflict, cls.charOffset,
+ cls.fullNameForErrors.length,
+ context: <LocatedMessage>[
+ messageInheritedMembersConflictCause1.withLocation(
+ a.fileUri, a.charOffset, name.length),
+ messageInheritedMembersConflictCause2.withLocation(
+ b.fileUri, b.charOffset, name.length),
+ ]);
+ } else {
+ cls.addProblem(messageDeclaredMemberConflictsWithInheritedMember,
+ a.charOffset, name.length,
+ context: <LocatedMessage>[
+ messageDeclaredMemberConflictsWithInheritedMemberCause.withLocation(
+ b.fileUri, b.charOffset, name.length)
+ ]);
}
}
- void handleInheritance(
- KernelClassBuilder cls, Declaration member, MergeKind mergeKind) {
+ /// If [mergeKind] is `MergeKind.superclass` [member] is declared in current
+ /// class, and isn't overriding a method from the superclass.
+ ///
+ /// If [mergeKind] is `MergeKind.interfaces`, [member] is ignored for now.
+ ///
+ /// If [mergeKind] is `MergeKind.supertypes`, [member] isn't
+ /// implementing/overriding anything.
+ void handleOnlyA(Declaration member, MergeKind mergeKind) {
Member target = member.target;
if (mergeKind == MergeKind.superclass && target.isAbstract) {
+ (abstractMembers ??= <Declaration>[]).add(member);
+ }
+ }
+
+ /// If [mergeKind] is `MergeKind.superclass` [member] is being inherited from
+ /// a superclass.
+ ///
+ /// If [mergeKind] is `MergeKind.interfaces`, [member] is ignored for now.
+ ///
+ /// If [mergeKind] is `MergeKind.supertypes`, [member] is implicitly
+ /// abstract, and not implemented.
+ void handleOnlyB(
+ KernelClassBuilder cls, Declaration member, MergeKind mergeKind) {
+ Member target = member.target;
+ if (mergeKind == MergeKind.supertypes ||
+ (mergeKind == MergeKind.superclass && target.isAbstract)) {
if (isNameVisibleIn(target.name, cls.library)) {
- abstractMemberCount++;
+ (abstractMembers ??= <Declaration>[]).add(member);
}
}
if (member.parent != objectClass &&
@@ -128,6 +180,8 @@
}
void add(KernelClassBuilder cls) {
+ assert(!hasNoSuchMethod);
+ assert(abstractMembers == null);
if (cls.isPatch) {
// TODO(ahe): What about patch classes. Have we injected patched members
// into the class-builder's scope?
@@ -153,65 +207,80 @@
scope = mixin.scope;
}
}
- List<Declaration> sortedLocals =
+ // TODO(ahe): Consider if removing static members from [localMembers] and
+ // [localSetters] makes sense. It depends on what semantic checks we need
+ // to perform with respect to static members and inherited members with the
+ // same name.
+ List<Declaration> localMembers =
new List<Declaration>.from(scope.local.values)
..sort(compareDeclarations);
- List<Declaration> sortedSetters =
+ List<Declaration> localSetters =
new List<Declaration>.from(scope.setters.values)
..sort(compareDeclarations);
- List<Declaration> allMembers;
- List<Declaration> allSetters;
+ localSetters = mergeAccessors(cls, localMembers, localSetters);
+ List<Declaration> classMembers;
+ List<Declaration> classSetters;
List<Declaration> interfaceMembers;
List<Declaration> interfaceSetters;
if (supernode == null) {
// This should be Object.
- interfaceMembers = allMembers = sortedLocals;
- interfaceSetters = allSetters = sortedSetters;
+ classMembers = localMembers;
+ classSetters = localSetters;
} else {
- allMembers = merge(
- cls, sortedLocals, supernode.classMembers, MergeKind.superclass);
- allSetters = merge(
- cls, sortedSetters, supernode.classSetters, MergeKind.superclass);
+ classMembers = merge(
+ cls, localMembers, supernode.classMembers, MergeKind.superclass);
+ classSetters = merge(
+ cls, localSetters, supernode.classSetters, MergeKind.superclass);
List<KernelTypeBuilder> interfaces = cls.interfaces;
if (interfaces != null) {
MergeResult result = mergeInterfaces(cls, supernode, interfaces);
interfaceMembers = result.mergedMembers;
interfaceSetters = result.mergedSetters;
} else {
- interfaceMembers = allMembers;
- interfaceSetters = allSetters;
+ interfaceMembers = supernode.interfaceMembers;
+ interfaceSetters = supernode.interfaceSetters;
+ }
+ if (interfaceMembers != null) {
+ interfaceMembers =
+ merge(cls, classMembers, interfaceMembers, MergeKind.supertypes);
+ }
+ if (interfaceMembers != null) {
+ interfaceSetters =
+ merge(cls, classSetters, interfaceSetters, MergeKind.supertypes);
}
}
- nodes[cls] = new ClassHierarchyNode(
- cls, scope, allMembers, allSetters, interfaceMembers, interfaceSetters);
- mergeAccessors(cls, allMembers, allSetters);
+ nodes[cls] = new ClassHierarchyNode(cls, scope, classMembers, classSetters,
+ interfaceMembers, interfaceSetters);
- if (abstractMemberCount != 0 && !cls.isAbstract) {
+ if (abstractMembers != null && !cls.isAbstract) {
if (!hasNoSuchMethod) {
- reportMissingMembers(cls, allMembers, allSetters);
+ reportMissingMembers(cls);
+ } else {
+ installNsmHandlers(cls);
}
- installNsmHandlers(cls);
}
hasNoSuchMethod = false;
- abstractMemberCount = 0;
+ abstractMembers = null;
}
MergeResult mergeInterfaces(KernelClassBuilder cls,
ClassHierarchyNode supernode, List<KernelTypeBuilder> interfaces) {
List<List<Declaration>> memberLists =
- List<List<Declaration>>(interfaces.length + 1);
+ new List<List<Declaration>>(interfaces.length + 1);
List<List<Declaration>> setterLists =
- List<List<Declaration>>(interfaces.length + 1);
+ new List<List<Declaration>>(interfaces.length + 1);
memberLists[0] = supernode.interfaceMembers;
setterLists[0] = supernode.interfaceSetters;
for (int i = 0; i < interfaces.length; i++) {
ClassHierarchyNode interfaceNode = getNode(interfaces[i]);
if (interfaceNode == null) {
- memberLists[i + 1] = <Declaration>[];
- setterLists[i + 1] = <Declaration>[];
+ memberLists[i + 1] = null;
+ setterLists[i + 1] = null;
} else {
- memberLists[i + 1] = interfaceNode.interfaceMembers;
- setterLists[i + 1] = interfaceNode.interfaceSetters;
+ memberLists[i + 1] =
+ interfaceNode.interfaceMembers ?? interfaceNode.classMembers;
+ setterLists[i + 1] =
+ interfaceNode.interfaceSetters ?? interfaceNode.classSetters;
}
}
return new MergeResult(
@@ -226,7 +295,15 @@
while (input.length > 1) {
List<List<Declaration>> output = <List<Declaration>>[];
for (int i = 0; i < input.length - 1; i += 2) {
- output.add(merge(cls, input[i], input[i + 1], MergeKind.interfaces));
+ List<Declaration> first = input[i];
+ List<Declaration> second = input[i + 1];
+ if (first == null) {
+ output.add(second);
+ } else if (second == null) {
+ output.add(first);
+ } else {
+ output.add(merge(cls, first, second, MergeKind.interfaces));
+ }
}
if (input.length.isOdd) {
output.add(input.last);
@@ -236,99 +313,94 @@
return input.single;
}
- /// Merge [and check] accessors. This entails removing setters corresponding
- /// to fields, and checking that setters don't override regular methods.
- void mergeAccessors(KernelClassBuilder cls, List<Declaration> allMembers,
- List<Declaration> allSetters) {
- List<Declaration> overriddenSetters;
+ /// Merge [and check] accessors. This entails copying mutable fields to
+ /// setters to simulate implied setters, and checking that setters don't
+ /// override regular methods.
+ List<Declaration> mergeAccessors(KernelClassBuilder cls,
+ List<Declaration> members, List<Declaration> setters) {
+ final List<Declaration> mergedSetters = new List<Declaration>.filled(
+ members.length + setters.length, null,
+ growable: true);
+ int storeIndex = 0;
int i = 0;
int j = 0;
- while (i < allMembers.length && j < allSetters.length) {
- Declaration member = allMembers[i];
- Declaration setter = allSetters[j];
+ while (i < members.length && j < setters.length) {
+ final Declaration member = members[i];
+ final Declaration setter = setters[j];
final int compare = compareDeclarations(member, setter);
if (compare == 0) {
- if (member.isField) {
- // TODO(ahe): What happens if we have both a field and a setter
- // declared in the same class?
- if (!member.isFinal && !member.isConst) {
- // The field overrides the setter.
- (overriddenSetters ??= <Declaration>[]).add(setter);
- Member target = setter.target;
- if (target.isAbstract) {
- abstractMemberCount--;
- }
- }
- } else if (!member.isGetter) {
- String name = member.fullNameForErrors;
+ if (member.isField ? impliesSetter(member) : !member.isGetter) {
+ // [member] conflicts with [setter].
+ final String name = member.fullNameForErrors;
cls.library.addProblem(
- messageDeclaredMemberConflictsWithInheritedMember,
- member.charOffset,
+ templateDuplicatedDeclaration.withArguments(name),
+ setter.charOffset,
name.length,
- member.fileUri,
+ setter.fileUri,
context: <LocatedMessage>[
- messageDeclaredMemberConflictsWithInheritedMemberCause
+ templateDuplicatedDeclarationCause
+ .withArguments(name)
.withLocation(
- setter.fileUri, setter.charOffset, name.length)
+ member.fileUri, member.charOffset, name.length)
]);
}
+ mergedSetters[storeIndex++] = setter;
i++;
j++;
} else if (compare < 0) {
+ if (impliesSetter(member)) {
+ mergedSetters[storeIndex++] = member;
+ }
i++;
} else {
+ mergedSetters[storeIndex++] = setters[j];
j++;
}
}
- // One of of the two lists is now exhausted. What remains in the other list
- // cannot be a conflict.
+ while (i < members.length) {
+ final Declaration member = members[i];
+ if (impliesSetter(member)) {
+ mergedSetters[storeIndex++] = member;
+ }
+ i++;
+ }
+ while (j < setters.length) {
+ mergedSetters[storeIndex++] = setters[j];
+ j++;
+ }
- if (overriddenSetters != null) {
- // Remove [overriddenSetters] from [allSetters] by copying [allSetters]
- // to itself.
- int i = 0;
- int j = 0;
- int storeIndex = 0;
- while (i < allSetters.length && j < overriddenSetters.length) {
- if (allSetters[i] == overriddenSetters[j]) {
- i++;
- j++;
- } else {
- allSetters[storeIndex++] = allSetters[i++];
- }
- }
- while (i < allSetters.length) {
- allSetters[storeIndex++] = allSetters[i++];
- }
- allSetters.length = storeIndex;
+ if (storeIndex == j) {
+ return setters;
+ } else {
+ return mergedSetters..length = storeIndex;
}
}
- void reportMissingMembers(KernelClassBuilder cls,
- List<Declaration> allMembers, List<Declaration> allSetters) {
- List<LocatedMessage> context = <LocatedMessage>[];
- List<String> missingNames = <String>[];
- for (int j = 0; j < 2; j++) {
- List<Declaration> members = j == 0 ? allMembers : allSetters;
- for (int i = 0; i < members.length; i++) {
- Declaration declaration = members[i];
- Member target = declaration.target;
- if (target.isAbstract && isNameVisibleIn(target.name, cls.library)) {
- String name = declaration.fullNameForErrors;
- String parentName = declaration.parent.fullNameForErrors;
- String displayName =
- declaration.isSetter ? "$parentName.$name=" : "$parentName.$name";
- missingNames.add(displayName);
- context.add(templateMissingImplementationCause
- .withArguments(displayName)
- .withLocation(
- declaration.fileUri, declaration.charOffset, name.length));
- }
+ void reportMissingMembers(KernelClassBuilder cls) {
+ Map<String, LocatedMessage> contextMap = <String, LocatedMessage>{};
+ for (int i = 0; i < abstractMembers.length; i++) {
+ Declaration declaration = abstractMembers[i];
+ Member target = declaration.target;
+ if (isNameVisibleIn(target.name, cls.library)) {
+ String name = declaration.fullNameForErrors;
+ String parentName = declaration.parent.fullNameForErrors;
+ String displayName =
+ declaration.isSetter ? "$parentName.$name=" : "$parentName.$name";
+ contextMap[displayName] = templateMissingImplementationCause
+ .withArguments(displayName)
+ .withLocation(
+ declaration.fileUri, declaration.charOffset, name.length);
}
}
+ if (contextMap.isEmpty) return;
+ List<String> names = new List<String>.from(contextMap.keys)..sort();
+ List<LocatedMessage> context = <LocatedMessage>[];
+ for (int i = 0; i < names.length; i++) {
+ context.add(contextMap[names[i]]);
+ }
cls.addProblem(
templateMissingImplementationNotAbstract.withArguments(
- cls.fullNameForErrors, missingNames),
+ cls.fullNameForErrors, names),
cls.charOffset,
cls.fullNameForErrors.length,
context: context);
@@ -339,16 +411,20 @@
}
ClassHierarchyNode getNode(KernelTypeBuilder type) {
- if (type is KernelNamedTypeBuilder) {
- Declaration declaration = type.declaration;
- if (declaration is KernelClassBuilder) {
- ClassHierarchyNode node = nodes[declaration];
- if (node == null && declaration is KernelClassBuilder) {
- add(declaration);
- node = nodes[declaration];
- }
- return node;
+ Declaration declaration = getDeclaration(type);
+ if (declaration is KernelClassBuilder) {
+ ClassHierarchyNode node = nodes[declaration];
+ if (node == null) {
+ bool savedHasNoSuchMethod = hasNoSuchMethod;
+ hasNoSuchMethod = false;
+ List<Declaration> savedAbstractMembers = abstractMembers;
+ abstractMembers = null;
+ add(declaration);
+ hasNoSuchMethod = savedHasNoSuchMethod;
+ abstractMembers = savedAbstractMembers;
+ node = nodes[declaration];
}
+ return node;
}
return null;
}
@@ -357,51 +433,57 @@
return type is KernelNamedTypeBuilder ? type.declaration : null;
}
- List<Declaration> merge(
- KernelClassBuilder cls,
- List<Declaration> localMembers,
- List<Declaration> superMembers,
- MergeKind mergeKind) {
- final List<Declaration> mergedMembers = new List<Declaration>.filled(
- localMembers.length + superMembers.length, null,
+ List<Declaration> merge(KernelClassBuilder cls, List<Declaration> aList,
+ List<Declaration> bList, MergeKind mergeKind) {
+ final List<Declaration> result = new List<Declaration>.filled(
+ aList.length + bList.length, null,
growable: true);
-
- int mergedMemberCount = 0;
-
+ int storeIndex = 0;
int i = 0;
int j = 0;
- while (i < localMembers.length && j < superMembers.length) {
- final Declaration localMember = localMembers[i];
- final Declaration superMember = superMembers[j];
- final int compare = compareDeclarations(localMember, superMember);
+ while (i < aList.length && j < bList.length) {
+ final Declaration a = aList[i];
+ final Declaration b = bList[j];
+ if (a.isStatic) {
+ i++;
+ continue;
+ }
+ if (b.isStatic) {
+ j++;
+ continue;
+ }
+ final int compare = compareDeclarations(a, b);
if (compare == 0) {
- mergedMembers[mergedMemberCount++] =
- handleOverride(cls, localMember, superMember, mergeKind);
+ result[storeIndex++] = handleMergeConflict(cls, a, b, mergeKind);
i++;
j++;
} else if (compare < 0) {
- handleNewMember(localMember, mergeKind);
- mergedMembers[mergedMemberCount++] = localMember;
+ handleOnlyA(a, mergeKind);
+ result[storeIndex++] = a;
i++;
} else {
- handleInheritance(cls, superMember, mergeKind);
- mergedMembers[mergedMemberCount++] = superMember;
+ handleOnlyB(cls, b, mergeKind);
+ result[storeIndex++] = b;
j++;
}
}
- while (i < localMembers.length) {
- final Declaration localMember = localMembers[i];
- handleNewMember(localMember, mergeKind);
- mergedMembers[mergedMemberCount++] = localMember;
+ while (i < aList.length) {
+ final Declaration a = aList[i];
+ if (!a.isStatic) {
+ handleOnlyA(a, mergeKind);
+ result[storeIndex++] = a;
+ }
i++;
}
- while (j < superMembers.length) {
- final Declaration superMember = superMembers[j];
- handleInheritance(cls, superMember, mergeKind);
- mergedMembers[mergedMemberCount++] = superMember;
+ while (j < bList.length) {
+ final Declaration b = bList[j];
+ if (!b.isStatic) {
+ handleOnlyB(cls, b, mergeKind);
+ result[storeIndex++] = b;
+ }
j++;
}
- return mergedMembers..length = mergedMemberCount;
+ return result..length = storeIndex;
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 08834e4..7d20b9c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -740,15 +740,15 @@
DartType context =
inferrer.typeSchemaEnvironment.unfutureType(typeContext);
if (context is InterfaceType) {
- if (inferrer.classHierarchy
- .isSubclassOf(inferrer.coreTypes.setClass, context.classNode) &&
+ if (inferrer.classHierarchy.isSubtypeOf(
+ context.classNode, inferrer.coreTypes.iterableClass) &&
!inferrer.classHierarchy
- .isSubclassOf(inferrer.coreTypes.mapClass, context.classNode)) {
+ .isSubtypeOf(context.classNode, inferrer.coreTypes.mapClass)) {
// Set literal
SetLiteralJudgment setLiteral = new SetLiteralJudgment([],
- typeArgument: const ImplicitTypeArgument(),
- isConst: node.isConst);
- node.replaceWith(setLiteral);
+ typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
+ ..fileOffset = node.fileOffset;
+ node.parent.replaceChild(node, setLiteral);
visitSetLiteralJudgment(setLiteral, typeContext);
node.inferredType = setLiteral.inferredType;
return;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index b7372a5..06cdc67 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -8,16 +8,20 @@
show
Constant,
DartType,
+ EnvironmentBoolConstant,
+ EnvironmentIntConstant,
+ EnvironmentStringConstant,
ListConstant,
MapConstant,
NullConstant,
StaticInvocation,
+ StringConstant,
TreeNode;
import 'package:kernel/transformations/constants.dart'
show ConstantsBackend, ErrorReporter;
-import '../problems.dart' show unimplemented;
+import '../problems.dart' show unexpected, unimplemented;
class KernelConstantsBackend extends ConstantsBackend {
@override
@@ -40,7 +44,24 @@
if (nativeName == 'Bool_fromEnvironment' ||
nativeName == 'Integer_fromEnvironment' ||
nativeName == 'String_fromEnvironment') {
- return namedArguments['defaultValue'] ?? new NullConstant();
+ if (positionalArguments.length == 1 &&
+ positionalArguments.first is StringConstant &&
+ (namedArguments.length == 0 ||
+ (namedArguments.length == 1 &&
+ namedArguments.containsKey('defaultValue')))) {
+ StringConstant name = positionalArguments.first;
+ Constant defaultValue =
+ namedArguments['defaultValue'] ?? new NullConstant();
+ if (nativeName == 'Bool_fromEnvironment') {
+ return new EnvironmentBoolConstant(name.value, defaultValue);
+ }
+ if (nativeName == 'Integer_fromEnvironment') {
+ return new EnvironmentIntConstant(name.value, defaultValue);
+ }
+ return new EnvironmentStringConstant(name.value, defaultValue);
+ }
+ return unexpected('valid constructor invocation', node.toString(),
+ node.fileOffset, node.location.file);
}
return unimplemented('constant evaluation of ${nativeName}',
node.fileOffset, node.location.file);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
index 4f966c7..d34ba34 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
@@ -133,9 +133,9 @@
/// }
members["index"] = new KernelFieldBuilder(null, intType, "index",
- finalMask | hasInitializerMask, parent, charOffset);
+ finalMask | hasInitializerMask, parent, charOffset, charOffset);
members["_name"] = new KernelFieldBuilder(null, stringType, "_name",
- finalMask | hasInitializerMask, parent, charOffset);
+ finalMask | hasInitializerMask, parent, charOffset, charOffset);
KernelConstructorBuilder constructorBuilder = new KernelConstructorBuilder(
null,
constMask,
@@ -160,6 +160,7 @@
"values",
constMask | staticMask | hasInitializerMask,
parent,
+ charOffset,
charOffset);
members["values"] = valuesBuilder;
KernelProcedureBuilder toStringBuilder = new KernelProcedureBuilder(
@@ -218,6 +219,7 @@
name,
constMask | staticMask | hasInitializerMask,
parent,
+ enumConstantInfo.charOffset,
enumConstantInfo.charOffset);
metadataCollector?.setDocumentationComment(
fieldBuilder.target, documentationComment);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 9870fb2..adf0f98 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -33,10 +33,11 @@
final KernelTypeBuilder type;
KernelFieldBuilder(this.metadata, this.type, String name, int modifiers,
- Declaration compilationUnit, int charOffset)
+ Declaration compilationUnit, int charOffset, int charEndOffset)
: field = new ShadowField(null, type == null,
fileUri: compilationUnit?.fileUri)
- ..fileOffset = charOffset,
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset,
super(name, modifiers, compilationUnit, charOffset);
void set initializer(Expression value) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 3f46eb3..96f2460 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -39,6 +39,8 @@
VariableDeclaration,
VoidType;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+
import 'package:kernel/clone.dart' show CloneVisitor;
import 'package:kernel/src/bounds_checks.dart'
@@ -597,13 +599,14 @@
KernelTypeBuilder type,
String name,
int charOffset,
+ int charEndOffset,
Token initializerTokenForInference,
bool hasInitializer) {
if (hasInitializer) {
modifiers |= hasInitializerMask;
}
KernelFieldBuilder field = new KernelFieldBuilder(
- metadata, type, name, modifiers, this, charOffset);
+ metadata, type, name, modifiers, this, charOffset, charEndOffset);
addBuilder(name, field, charOffset);
if (initializerTokenForInference != null) {
assert(type == null);
@@ -1651,6 +1654,7 @@
void checkBoundsInMethodInvocation(
DartType receiverType,
TypeEnvironment typeEnvironment,
+ ClassHierarchy hierarchy,
TypeInferrerImpl typeInferrer,
Name name,
Member interfaceTarget,
@@ -1668,14 +1672,13 @@
return;
}
// TODO(dmitryas): Find a better way than relying on [interfaceTarget].
- Member method = typeEnvironment.hierarchy.getDispatchTarget(klass, name) ??
- interfaceTarget;
+ Member method = hierarchy.getDispatchTarget(klass, name) ?? interfaceTarget;
if (method == null || method is! Procedure) {
return;
}
if (klass != method.enclosingClass) {
- Supertype parent = typeEnvironment.hierarchy
- .getClassAsInstanceOf(klass, method.enclosingClass);
+ Supertype parent =
+ hierarchy.getClassAsInstanceOf(klass, method.enclosingClass);
klass = method.enclosingClass;
receiverTypeArguments = parent.typeArguments;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 39ea072..75f57a8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -44,7 +44,7 @@
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import 'package:kernel/transformations/constants.dart' as constants
- show transformLibraries;
+ show SimpleErrorReporter, transformLibraries;
import '../../api_prototype/file_system.dart' show FileSystem;
@@ -754,7 +754,8 @@
new KernelConstantsBackend(),
loader.coreTypes,
new TypeEnvironment(loader.coreTypes, loader.hierarchy,
- legacyMode: false));
+ legacyMode: false),
+ const constants.SimpleErrorReporter());
ticker.logMs("Evaluated constants");
}
backendTarget.performModularTransformationsOnLibraries(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
index 241bb28..c427799 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_variable_builder.dart
@@ -36,7 +36,7 @@
super(name, bound, compilationUnit, charOffset);
KernelTypeVariableBuilder.fromKernel(
- TypeParameter parameter, KernelLibraryBuilder compilationUnit)
+ TypeParameter parameter, LibraryBuilder compilationUnit)
: actualParameter = parameter,
super(parameter.name, null, compilationUnit, parameter.fileOffset);
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index 049af7e..38fa92c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -14,6 +14,9 @@
DartType,
DoubleConstant,
DynamicType,
+ EnvironmentBoolConstant,
+ EnvironmentIntConstant,
+ EnvironmentStringConstant,
Field,
FunctionType,
InvalidType,
@@ -32,6 +35,7 @@
TypeLiteralConstant,
TypeParameter,
TypeParameterType,
+ UnevaluatedConstant,
VoidType;
import 'package:kernel/visitor.dart' show ConstantVisitor, DartTypeVisitor;
@@ -41,6 +45,8 @@
import '../fasta_codes.dart'
show Message, templateTypeOrigin, templateTypeOriginWithFileUri;
+import '../problems.dart' show unsupported;
+
/// A pretty-printer for Kernel types and constants with the ability to label
/// raw types with numeric markers in Dart comments (e.g. `/*1*/`) to
/// distinguish different types with the same name. This is used in diagnostic
@@ -306,6 +312,22 @@
void visitTypeLiteralConstant(TypeLiteralConstant node) {
node.type.accept(this);
}
+
+ void visitEnvironmentBoolConstant(EnvironmentBoolConstant node) {
+ unsupported('printing unevaluated constants', -1, null);
+ }
+
+ void visitEnvironmentIntConstant(EnvironmentIntConstant node) {
+ unsupported('printing unevaluated constants', -1, null);
+ }
+
+ void visitEnvironmentStringConstant(EnvironmentStringConstant node) {
+ unsupported('printing unevaluated constants', -1, null);
+ }
+
+ void visitUnevaluatedConstant(UnevaluatedConstant node) {
+ unsupported('printing unevaluated constants', -1, null);
+ }
}
class LabeledClassName {
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 2063d4d..6d670a1 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -397,7 +397,9 @@
/// Type arguments were seen during analysis.
final TypeParamOrArgInfo typeArguments;
- /// The token before the trailing question mark or `null` if none.
+ /// The token before the trailing question mark or `null` if either
+ /// 1) there is no trailing question mark, or
+ /// 2) the trailing question mark is not part of the type reference.
Token beforeQuestionMark;
/// The last token in the type reference.
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 72901f5..d5c1cd8 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1305,6 +1305,7 @@
List<FieldInfo> fieldInfos = new List<FieldInfo>(count);
bool isParserRecovery = false;
for (int i = count - 1; i != -1; i--) {
+ int charEndOffset = pop();
Token beforeLast = pop();
Token initializerTokenForInference = pop();
int charOffset = pop();
@@ -1312,8 +1313,8 @@
if (name is ParserRecovery) {
isParserRecovery = true;
} else {
- fieldInfos[i] = new FieldInfo(
- name, charOffset, initializerTokenForInference, beforeLast);
+ fieldInfos[i] = new FieldInfo(name, charOffset,
+ initializerTokenForInference, beforeLast, charEndOffset);
}
}
return isParserRecovery ? null : fieldInfos;
@@ -1515,6 +1516,7 @@
}
push(assignmentOperator.next);
push(beforeLast);
+ push(token.charOffset);
}
@override
@@ -1522,6 +1524,7 @@
debugEvent("NoFieldInitializer");
push(NullValue.FieldInitializer);
push(NullValue.FieldInitializer);
+ push(token.charOffset);
}
@override
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 1f1afc5..2fa5d91 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
@@ -389,6 +389,7 @@
T type,
String name,
int charOffset,
+ int charEndOffset,
Token initializerTokenForInference,
bool hasInitializer);
@@ -397,6 +398,7 @@
for (FieldInfo info in fieldInfos) {
String name = info.name;
int charOffset = info.charOffset;
+ int charEndOffset = info.charEndOffset;
bool hasInitializer = info.initializerTokenForInference != null;
Token initializerTokenForInference =
type != null || legacyMode ? null : info.initializerTokenForInference;
@@ -404,8 +406,16 @@
Token beforeLast = info.beforeLast;
beforeLast.setNext(new Token.eof(beforeLast.next.offset));
}
- addField(documentationComment, metadata, modifiers, type, name,
- charOffset, initializerTokenForInference, hasInitializer);
+ addField(
+ documentationComment,
+ metadata,
+ modifiers,
+ type,
+ name,
+ charOffset,
+ charEndOffset,
+ initializerTokenForInference,
+ hasInitializer);
}
}
@@ -1001,7 +1011,8 @@
final int charOffset;
final Token initializerTokenForInference;
final Token beforeLast;
+ final int charEndOffset;
const FieldInfo(this.name, this.charOffset, this.initializerTokenForInference,
- this.beforeLast);
+ this.beforeLast, this.charEndOffset);
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
index b0f3d1e..3c999dc 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/interface_resolver.dart
@@ -33,7 +33,8 @@
import 'package:kernel/type_algebra.dart' show Substitution;
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/src/hierarchy_based_type_environment.dart'
+ show HierarchyBasedTypeEnvironment;
import '../../base/instrumentation.dart'
show
@@ -675,7 +676,7 @@
class InterfaceResolver {
final TypeInferenceEngine _typeInferenceEngine;
- final TypeEnvironment _typeEnvironment;
+ final HierarchyBasedTypeEnvironment _typeEnvironment;
final Instrumentation _instrumentation;
@@ -1244,8 +1245,8 @@
/// Determines the appropriate substitution to translate type parameters
/// mentioned in the given [candidate] to type parameters on [class_].
Substitution _substitutionFor(Procedure candidate, Class class_) {
- return Substitution.fromInterfaceType(_typeEnvironment.hierarchy
- .getTypeAsInstanceOf(class_.thisType, candidate.enclosingClass));
+ return Substitution.fromInterfaceType(_typeEnvironment.getTypeAsInstanceOf(
+ class_.thisType, candidate.enclosingClass));
}
/// Executes [callback] once for each uniquely named member of [candidates].
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index 23402c5..91df6f16 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -181,7 +181,7 @@
// above is irrelevant; we just need to find the matched superclass,
// substitute, and then iterate through type variables.
var matchingSupertypeOfSubtype =
- environment.hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode);
+ environment.getTypeAsInstanceOf(subtype, supertype.classNode);
if (matchingSupertypeOfSubtype == null) return false;
for (int i = 0; i < supertype.classNode.typeParameters.length; i++) {
if (!_isSubtypeMatch(matchingSupertypeOfSubtype.typeArguments[i],
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 6e93c77..393c70b 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -1607,6 +1607,7 @@
library.checkBoundsInMethodInvocation(
actualReceiverType,
typeSchemaEnvironment,
+ classHierarchy,
this,
actualMethodName,
interfaceTarget,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 1efa0e5..3aa0279 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -23,7 +23,8 @@
import 'package:kernel/type_algebra.dart' show Substitution;
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/src/hierarchy_based_type_environment.dart'
+ show HierarchyBasedTypeEnvironment;
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
@@ -89,7 +90,7 @@
'${typeSchemaToString(lower)} <: <type> <: ${typeSchemaToString(upper)}';
}
-class TypeSchemaEnvironment extends TypeEnvironment {
+class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment {
TypeSchemaEnvironment(CoreTypes coreTypes, ClassHierarchy hierarchy)
: super(coreTypes, hierarchy);
diff --git a/pkg/front_end/lib/src/fasta/util/error_reporter_file_copier.dart b/pkg/front_end/lib/src/fasta/util/error_reporter_file_copier.dart
new file mode 100644
index 0000000..4cddf72
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/util/error_reporter_file_copier.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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' show Directory, File, GZipCodec;
+
+Uri saveAsGzip(List<int> data, String filename) {
+ // TODO(jensj): This should be done via the FileSystem instead, but it
+ // currently doesn't support writing.
+ GZipCodec gZipCodec = new GZipCodec();
+ List<int> gzippedInitializedFromData = gZipCodec.encode(data);
+ Directory tempDir = Directory.systemTemp.createTempSync("$filename");
+ File file = new File("${tempDir.path}/${filename}.gz");
+ file.writeAsBytesSync(gzippedInitializedFromData);
+ return file.uri;
+}
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index eb90f60..a885932 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1587,9 +1587,9 @@
commas, for example, --fatal=errors,warnings.
--enable-experiment=<flag>
- --disable-experiment=<flag>
Enable or disable an experimental flag, used to guard features currently
- in development. Multiple experiments can be separated by commas.
+ in development. Prefix an experiment name with 'no-' to disable it.
+ Multiple experiments can be separated by commas.
FastaCLIArgumentRequired:
template: "Expected value after '#name'."
@@ -2978,13 +2978,47 @@
severity: IGNORED
InitializeFromDillNotSelfContained:
- template: "Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug. The Dart team would greatly appreciate if you would take a moment to report this problem at http://dartbug.com/new."
+ template: |
+ Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
+
+ The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+ If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
+ Either way, you should probably delete the file so it doesn't use unnecessary disk space.
+
+ severity: WARNING
+ frontendInternal: true
+ external: test/incremental_load_from_invalid_dill_test.dart
+
+InitializeFromDillNotSelfContainedNoDump:
+ template: |
+ Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
+
+ The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+
severity: WARNING
frontendInternal: true
external: test/incremental_load_from_invalid_dill_test.dart
InitializeFromDillUnknownProblem:
- template: "Tried to initialize from a previous compilation (#string), but couldn't. Error message was '#string2'. This might be a bug. The Dart team would greatly appreciate if you would take a moment to report this problem at http://dartbug.com/new."
+ template: |
+ Tried to initialize from a previous compilation (#string), but couldn't.
+ Error message was '#string2'. This might be a bug.
+
+ The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+ If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
+ Either way, you should probably delete the file so it doesn't use unnecessary disk space.
+
+ severity: WARNING
+ frontendInternal: true
+ external: test/incremental_load_from_invalid_dill_test.dart
+
+InitializeFromDillUnknownProblemNoDump:
+ template: |
+ Tried to initialize from a previous compilation (#string), but couldn't.
+ Error message was '#string2'. This might be a bug.
+
+ The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+
severity: WARNING
frontendInternal: true
external: test/incremental_load_from_invalid_dill_test.dart
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 8a89ddc..2934b93 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -36,6 +36,9 @@
import 'package:front_end/src/api_prototype/compiler_options.dart'
show CompilerOptions, DiagnosticMessage;
+import 'package:front_end/src/api_prototype/experimental_flags.dart'
+ show ExperimentalFlag;
+
import 'package:front_end/src/api_prototype/standard_file_system.dart'
show StandardFileSystem;
@@ -118,6 +121,7 @@
final Uri vm;
final bool legacyMode;
final bool onlyCrashes;
+ final bool enableSetLiterals;
final Map<Component, KernelTarget> componentToTarget =
<Component, KernelTarget>{};
final Map<Component, StringBuffer> componentToDiagnostics =
@@ -135,6 +139,7 @@
this.legacyMode,
this.platformBinaries,
this.onlyCrashes,
+ this.enableSetLiterals,
bool ignoreExpectations,
bool updateExpectations,
bool updateComments,
@@ -211,13 +216,17 @@
Uri sdk = Uri.base.resolve("sdk/");
Uri vm = Uri.base.resolveUri(new Uri.file(Platform.resolvedExecutable));
Uri packages = Uri.base.resolve(".packages");
+ bool enableSetLiterals = environment["enableSetLiterals"] != "false";
var options = new ProcessedOptions(
options: new CompilerOptions()
..onDiagnostic = (DiagnosticMessage message) {
throw message.plainTextFormatted.join("\n");
}
..sdkRoot = sdk
- ..packagesFileUri = packages);
+ ..packagesFileUri = packages
+ ..experimentalFlags = <ExperimentalFlag, bool>{
+ ExperimentalFlag.setLiterals: enableSetLiterals
+ });
UriTranslator uriTranslator = await options.getUriTranslator();
bool legacyMode = environment.containsKey(LEGACY_MODE);
bool onlyCrashes = environment["onlyCrashes"] == "true";
@@ -238,6 +247,7 @@
? computePlatformBinariesLocation(forceBuildDir: true)
: Uri.base.resolve(platformBinaries),
onlyCrashes,
+ enableSetLiterals,
ignoreExpectations,
updateExpectations,
updateComments,
@@ -302,6 +312,9 @@
errors.write("\n\n");
}
errors.writeAll(message.plainTextFormatted, "\n");
+ }
+ ..experimentalFlags = <ExperimentalFlag, bool>{
+ ExperimentalFlag.setLiterals: context.enableSetLiterals
},
inputs: <Uri>[description.uri]);
return await CompilerContext.runWithOptions(options, (_) async {
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
index 9ae979a..cf270cb 100644
--- a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -75,7 +75,7 @@
stopwatch.reset();
bool initializeResult = await initializedCompile(
dart2jsUrl, fullDillFromInitialized, initializeWith, [invalidateUri]);
- Expect.equals(initializeExpect, initializeResult);
+ Expect.equals(initializeResult, initializeExpect);
print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
"took ${stopwatch.elapsedMilliseconds} ms");
diff --git a/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart b/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
index 8167690..9dc2941 100644
--- a/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_invalid_dill_test.dart
@@ -29,7 +29,9 @@
show
Code,
codeInitializeFromDillNotSelfContained,
- codeInitializeFromDillUnknownProblem;
+ codeInitializeFromDillNotSelfContainedNoDump,
+ codeInitializeFromDillUnknownProblem,
+ codeInitializeFromDillUnknownProblemNoDump;
import 'package:front_end/src/fasta/incremental_compiler.dart'
show IncrementalCompiler;
@@ -63,13 +65,15 @@
CompilerOptions options;
compileExpectInitializeFailAndSpecificWarning(
- Code expectedWarningCode) async {
+ Code expectedWarningCode, bool writeFileOnCrashReport) async {
errorMessages.clear();
warningMessages.clear();
- IncrementalCompiler compiler = new IncrementalCompiler(
- new CompilerContext(
- new ProcessedOptions(options: options, inputs: [entryPoint])),
- initializeFrom);
+ options.writeFileOnCrashReport = writeFileOnCrashReport;
+ DeleteTempFilesIncrementalCompiler compiler =
+ new DeleteTempFilesIncrementalCompiler(
+ new CompilerContext(
+ new ProcessedOptions(options: options, inputs: [entryPoint])),
+ initializeFrom);
await compiler.computeDelta();
if (compiler.initializedFromDill) {
Expect.fail("Expected to not be able to initialized from dill, but did.");
@@ -166,13 +170,28 @@
// Initializing from partial dill should not be ok.
await compileExpectInitializeFailAndSpecificWarning(
- codeInitializeFromDillNotSelfContained);
+ codeInitializeFromDillNotSelfContained, true);
+ await compileExpectInitializeFailAndSpecificWarning(
+ codeInitializeFromDillNotSelfContainedNoDump, false);
// Create a invalid dill file to load from: Should not be ok.
data = new List<int>.filled(42, 42);
fs.entityForUri(initializeFrom).writeAsBytesSync(data);
await compileExpectInitializeFailAndSpecificWarning(
- codeInitializeFromDillUnknownProblem);
+ codeInitializeFromDillUnknownProblem, true);
+ await compileExpectInitializeFailAndSpecificWarning(
+ codeInitializeFromDillUnknownProblemNoDump, false);
+ }
+}
+
+class DeleteTempFilesIncrementalCompiler extends IncrementalCompiler {
+ DeleteTempFilesIncrementalCompiler(CompilerContext context,
+ [Uri initializeFromDillUri])
+ : super(context, initializeFromDillUri);
+
+ void recordTemporaryFileForTesting(Uri uri) {
+ File f = new File.fromUri(uri);
+ if (f.existsSync()) f.deleteSync();
}
}
diff --git a/pkg/front_end/testcases/abstract_members.dart b/pkg/front_end/testcases/abstract_members.dart
index 00f4f14..058cbe9 100644
--- a/pkg/front_end/testcases/abstract_members.dart
+++ b/pkg/front_end/testcases/abstract_members.dart
@@ -38,4 +38,21 @@
cMethod() {}
}
+// This class should have no errors, as it has a non-trivial noSuchMethod.
+class MyMock1 extends B {
+ noSuchMethod(_) => null;
+}
+
+// This class should have no errors, as the abstract method doesn't override
+// the non-trivial noSuchMethod inherited from MyMock1.
+class MyMock2 extends MyMock1 {
+ noSuchMethod(_);
+}
+
+// This class should have an error, the abstract method isn't considered
+// non-trivial.
+class MyMock3 extends B {
+ noSuchMethod(_);
+}
+
main() {}
diff --git a/pkg/front_end/testcases/abstract_members.dart.legacy.expect b/pkg/front_end/testcases/abstract_members.dart.legacy.expect
index 3ac995d..0c85dd2 100644
--- a/pkg/front_end/testcases/abstract_members.dart.legacy.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.legacy.expect
@@ -12,8 +12,12 @@
//
// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
// - A.abstractMethod
-// - A.property3=
// - A.property1=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
// Try to either
// - provide an implementation,
// - inherit an implementation from a superclass or mixin,
@@ -25,12 +29,66 @@
// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'A.abstractMethod' is defined here.
// abstractMethod();
// ^^^^^^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
-// void set property3(_);
-// ^^^^^^^^^
// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'A.property1=' is defined here.
// void set property1(_);
// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
+// void set property3(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: 'Interface1.interfaceMethod1' is defined here.
+// void interfaceMethod1() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'Interface2.interfaceMethod1' is defined here.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:10:8: Context: 'Interface2.interfaceMethod2' is defined here.
+// void interfaceMethod2() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'Interface3.interfaceMethod3' is defined here.
+// void interfaceMethod3() {}
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
+// - A.abstractMethod
+// - A.property1=
+// - A.property2=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class MyMock3 extends B {
+// ^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'A.abstractMethod' is defined here.
+// abstractMethod();
+// ^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'A.property1=' is defined here.
+// void set property1(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:23:12: Context: 'A.property2=' is defined here.
+// void set property2(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
+// void set property3(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: 'Interface1.interfaceMethod1' is defined here.
+// void interfaceMethod1() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'Interface2.interfaceMethod1' is defined here.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:10:8: Context: 'Interface2.interfaceMethod2' is defined here.
+// void interfaceMethod2() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'Interface3.interfaceMethod3' is defined here.
+// void interfaceMethod3() {}
+// ^^^^^^^^^^^^^^^^
// Unhandled errors:
//
@@ -40,8 +98,12 @@
//
// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
// - A.abstractMethod
-// - A.property3=
// - A.property1=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
// Try to either
// - provide an implementation,
// - inherit an implementation from a superclass or mixin,
@@ -50,6 +112,24 @@
//
// class MyClass extends B {
// ^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
+// - A.abstractMethod
+// - A.property1=
+// - A.property2=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class MyMock3 extends B {
+// ^^^^^^^
library;
import self as self;
@@ -110,4 +190,49 @@
no-such-method-forwarder set property1(dynamic _) → void
return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class MyMock1 extends self::B {
+ synthetic constructor •() → self::MyMock1
+ : super self::B::•()
+ ;
+ method noSuchMethod(dynamic _) → dynamic
+ return null;
+ no-such-method-forwarder method interfaceMethod2() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod2, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method abstractMethod() → dynamic
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#abstractMethod, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder method interfaceMethod1() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method interfaceMethod3() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod3, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
+class MyMock2 extends self::MyMock1 {
+ synthetic constructor •() → self::MyMock2
+ : super self::MyMock1::•()
+ ;
+ abstract method noSuchMethod(dynamic _) → dynamic;
+}
+class MyMock3 extends self::B {
+ synthetic constructor •() → self::MyMock3
+ : super self::B::•()
+ ;
+ abstract method noSuchMethod(dynamic _) → dynamic;
+ no-such-method-forwarder get interfaceMethod1() → dynamic
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect b/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
index 1e1ebac..7e489f3 100644
--- a/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
@@ -6,8 +6,12 @@
//
// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
// - A.abstractMethod
-// - A.property3=
// - A.property1=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
// Try to either
// - provide an implementation,
// - inherit an implementation from a superclass or mixin,
@@ -16,6 +20,24 @@
//
// class MyClass extends B {
// ^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
+// - A.abstractMethod
+// - A.property1=
+// - A.property2=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class MyMock3 extends B {
+// ^^^^^^^
library;
import self as self;
@@ -76,4 +98,49 @@
no-such-method-forwarder set property1(dynamic _) → void
return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class MyMock1 extends self::B {
+ synthetic constructor •() → self::MyMock1
+ : super self::B::•()
+ ;
+ method noSuchMethod(dynamic _) → dynamic
+ return null;
+ no-such-method-forwarder method interfaceMethod2() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod2, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method abstractMethod() → dynamic
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#abstractMethod, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder method interfaceMethod1() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method interfaceMethod3() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod3, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
+class MyMock2 extends self::MyMock1 {
+ synthetic constructor •() → self::MyMock2
+ : super self::MyMock1::•()
+ ;
+ abstract method noSuchMethod(dynamic _) → dynamic;
+}
+class MyMock3 extends self::B {
+ synthetic constructor •() → self::MyMock3
+ : super self::B::•()
+ ;
+ abstract method noSuchMethod(dynamic _) → dynamic;
+ no-such-method-forwarder get interfaceMethod1() → dynamic
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/abstract_members.dart.outline.expect b/pkg/front_end/testcases/abstract_members.dart.outline.expect
index 1c95548..e2bf105 100644
--- a/pkg/front_end/testcases/abstract_members.dart.outline.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.outline.expect
@@ -12,8 +12,12 @@
//
// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
// - A.abstractMethod
-// - A.property3=
// - A.property1=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
// Try to either
// - provide an implementation,
// - inherit an implementation from a superclass or mixin,
@@ -25,12 +29,66 @@
// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'A.abstractMethod' is defined here.
// abstractMethod();
// ^^^^^^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
-// void set property3(_);
-// ^^^^^^^^^
// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'A.property1=' is defined here.
// void set property1(_);
// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
+// void set property3(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: 'Interface1.interfaceMethod1' is defined here.
+// void interfaceMethod1() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'Interface2.interfaceMethod1' is defined here.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:10:8: Context: 'Interface2.interfaceMethod2' is defined here.
+// void interfaceMethod2() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'Interface3.interfaceMethod3' is defined here.
+// void interfaceMethod3() {}
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
+// - A.abstractMethod
+// - A.property1=
+// - A.property2=
+// - A.property3=
+// - Interface1.interfaceMethod1
+// - Interface2.interfaceMethod1
+// - Interface2.interfaceMethod2
+// - Interface3.interfaceMethod3
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class MyMock3 extends B {
+// ^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'A.abstractMethod' is defined here.
+// abstractMethod();
+// ^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'A.property1=' is defined here.
+// void set property1(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:23:12: Context: 'A.property2=' is defined here.
+// void set property2(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
+// void set property3(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: 'Interface1.interfaceMethod1' is defined here.
+// void interfaceMethod1() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'Interface2.interfaceMethod1' is defined here.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:10:8: Context: 'Interface2.interfaceMethod2' is defined here.
+// void interfaceMethod2() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'Interface3.interfaceMethod3' is defined here.
+// void interfaceMethod3() {}
+// ^^^^^^^^^^^^^^^^
library;
import self as self;
@@ -95,5 +153,47 @@
no-such-method-forwarder set property1(dynamic _) → void
return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class MyMock1 extends self::B {
+ synthetic constructor •() → self::MyMock1
+ ;
+ method noSuchMethod(dynamic _) → dynamic
+ ;
+ no-such-method-forwarder method interfaceMethod2() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod2, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method abstractMethod() → dynamic
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#abstractMethod, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder method interfaceMethod1() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method interfaceMethod3() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod3, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
+class MyMock2 extends self::MyMock1 {
+ synthetic constructor •() → self::MyMock2
+ ;
+ abstract method noSuchMethod(dynamic _) → dynamic;
+}
+class MyMock3 extends self::B {
+ synthetic constructor •() → self::MyMock3
+ ;
+ abstract method noSuchMethod(dynamic _) → dynamic;
+ no-such-method-forwarder get interfaceMethod1() → dynamic
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/abstract_members.dart.strong.expect b/pkg/front_end/testcases/abstract_members.dart.strong.expect
index 81ff760..c568386 100644
--- a/pkg/front_end/testcases/abstract_members.dart.strong.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.strong.expect
@@ -51,6 +51,52 @@
// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'property1=' is defined here.
// void set property1(_);
// ^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
+// - 'interfaceMethod2'
+// - 'abstractMethod'
+// - 'interfaceMethod1'
+// - 'interfaceMethod1'
+// - 'interfaceMethod3'
+// - 'property3='
+// - 'interfaceMethod1='
+// - 'property1='
+// - 'property2='
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class MyMock3 extends B {
+// ^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:10:8: Context: 'interfaceMethod2' is defined here.
+// void interfaceMethod2() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'abstractMethod' is defined here.
+// abstractMethod();
+// ^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: 'interfaceMethod1' is defined here.
+// void interfaceMethod1() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'interfaceMethod1' is defined here.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'interfaceMethod3' is defined here.
+// void interfaceMethod3() {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'property3=' is defined here.
+// void set property3(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'interfaceMethod1=' is defined here.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'property1=' is defined here.
+// void set property1(_);
+// ^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:23:12: Context: 'property2=' is defined here.
+// void set property2(_);
+// ^^^^^^^^^
// Unhandled errors:
//
@@ -75,6 +121,25 @@
//
// class MyClass extends B {
// ^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:54:7: Error: The non-abstract class 'MyMock3' is missing implementations for these members:
+// - 'interfaceMethod2'
+// - 'abstractMethod'
+// - 'interfaceMethod1'
+// - 'interfaceMethod1'
+// - 'interfaceMethod3'
+// - 'property3='
+// - 'interfaceMethod1='
+// - 'property1='
+// - 'property2='
+// Try to either
+// - provide an implementation,
+// - inherit an implementation from a superclass or mixin,
+// - mark the class as abstract, or
+// - provide a 'noSuchMethod' implementation.
+//
+// class MyMock3 extends B {
+// ^^^^^^^
library;
import self as self;
@@ -135,4 +200,49 @@
no-such-method-forwarder set property1(dynamic _) → void
return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class MyMock1 extends self::B {
+ synthetic constructor •() → self::MyMock1
+ : super self::B::•()
+ ;
+ method noSuchMethod(core::Invocation _) → dynamic
+ return null;
+ no-such-method-forwarder method interfaceMethod2() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod2, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method abstractMethod() → dynamic
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#abstractMethod, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder method interfaceMethod1() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder method interfaceMethod3() → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod3, 0, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock1::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
+class MyMock2 extends self::MyMock1 {
+ synthetic constructor •() → self::MyMock2
+ : super self::MyMock1::•()
+ ;
+ abstract method noSuchMethod(core::Invocation _) → dynamic;
+}
+class MyMock3 extends self::B {
+ synthetic constructor •() → self::MyMock3
+ : super self::B::•()
+ ;
+ abstract method noSuchMethod(core::Invocation _) → dynamic;
+ no-such-method-forwarder get interfaceMethod1() → dynamic
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
+ no-such-method-forwarder set property3(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property1(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+ no-such-method-forwarder set property2(dynamic _) → void
+ return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_full.status b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
index 3c112db..9ceffba 100644
--- a/pkg/front_end/testcases/incremental_bulk_compiler_full.status
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
@@ -9,6 +9,5 @@
language_2/mixin_type_parameter_inference_error_test: Crash # non-identical '#errors'
language_2/part_of_multiple_libs_test: Crash # missing "#errors"
language_2/part_refers_to_core_library_test: Crash # non-identical '#errors'
-language_2/regress_27957_test: Crash # isSynthetic becomes false on C1 SuperInitializer.
language_2/script1_negative_test: Crash # missing "#errors", missing empty library that shouldn't have been there in the first place
language_2/script2_negative_test: Crash # missing "#errors", missing empty library that shouldn't have been there in the first place
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart
index 3796335..aafc9ff 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart
@@ -12,16 +12,16 @@
}
Stream<List<int>> foo() async* {
- yield /*@typeArgs=int*/ [];
+ yield new /*@typeArgs=int*/ List();
yield /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ MyStream();
- yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
+ yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
yield* new /*@typeArgs=List<int>*/ MyStream();
}
Iterable<Map<int, int>> bar() sync* {
- yield /*@typeArgs=int, int*/ {};
+ yield new /*@typeArgs=int, int*/ Map();
yield /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
- yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic, dynamic*/ {};
+ yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic, dynamic*/ Map();
yield* new /*@typeArgs=Map<int, int>*/ List();
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.expect
index bbe604f..4a22da5 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.expect
@@ -8,15 +8,15 @@
return null;
}
static method foo() → asy::Stream<core::List<core::int>> async* {
- yield<dynamic>[];
+ yield core::List::•<dynamic>();
yield self::MyStream::•<dynamic>();
- yield*<dynamic>[];
+ yield* core::List::•<dynamic>();
yield* self::MyStream::•<dynamic>();
}
static method bar() → core::Iterable<core::Map<core::int, core::int>> sync* {
- yield<dynamic, dynamic>{};
+ yield core::Map::•<dynamic, dynamic>();
yield core::List::•<dynamic>();
- yield*<dynamic, dynamic>{};
+ yield* core::Map::•<dynamic, dynamic>();
yield* core::List::•<dynamic>();
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.transformed.expect
index 3c303a7..4d12a56 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.legacy.transformed.expect
@@ -22,7 +22,7 @@
try {
#L1:
{
- if(:controller.{asy::_AsyncStarStreamController::add}(<dynamic>[]))
+ if(:controller.{asy::_AsyncStarStreamController::add}(core::_GrowableList::•<dynamic>(0)))
return null;
else
[yield] null;
@@ -30,7 +30,7 @@
return null;
else
[yield] null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(<dynamic>[]))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(core::_GrowableList::•<dynamic>(0)))
return null;
else
[yield] null;
@@ -60,7 +60,7 @@
function :sync_op(core::_SyncIterator<core::Map<core::int, core::int>> :iterator) → core::bool yielding {
{
{
- :iterator.{core::_SyncIterator::_current} = <dynamic, dynamic>{};
+ :iterator.{core::_SyncIterator::_current} = core::Map::•<dynamic, dynamic>();
[yield] true;
}
{
@@ -68,7 +68,7 @@
[yield] true;
}
{
- :iterator.{core::_SyncIterator::_yieldEachIterable} = <dynamic, dynamic>{};
+ :iterator.{core::_SyncIterator::_yieldEachIterable} = core::Map::•<dynamic, dynamic>();
[yield] true;
}
{
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect
index ea7b44c..5504acd 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.expect
@@ -7,12 +7,12 @@
// yield /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ MyStream();
// ^
//
-// pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
+// pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:68: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
// - 'List' is from 'dart:core'.
// - 'Stream' is from 'dart:async'.
// Try changing the type of the left hand side, or casting the right hand side to 'Stream<List<int>>'.
-// yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
-// ^
+// yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
+// ^
//
// pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:23:67: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Map<int, int>'.
// - 'List' is from 'dart:core'.
@@ -21,12 +21,12 @@
// yield /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
// ^
//
-// pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:24:73: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'Iterable<Map<int, int>>'.
+// pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:24:77: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'Iterable<Map<int, int>>'.
// - 'Map' is from 'dart:core'.
// - 'Iterable' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'Iterable<Map<int, int>>'.
-// yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic, dynamic*/ {};
-// ^
+// yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic, dynamic*/ Map();
+// ^
library test;
import self as self;
@@ -38,35 +38,35 @@
return null;
}
static method foo() → asy::Stream<core::List<core::int>> async* {
- yield<core::int>[];
+ yield core::List::•<core::int>();
yield let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:16:67: Error: A value of type 'MyStream<dynamic>' can't be assigned to a variable of type 'List<int>'.
- 'MyStream' is from 'pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart'.
- 'List' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'List<int>'.
yield /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ MyStream();
^" in self::MyStream::•<dynamic>() as{TypeError} core::List<core::int>;
- yield* let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
+ yield* let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:68: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
- 'List' is from 'dart:core'.
- 'Stream' is from 'dart:async'.
Try changing the type of the left hand side, or casting the right hand side to 'Stream<List<int>>'.
- yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
- ^" in <dynamic>[] as{TypeError} asy::Stream<core::List<core::int>>;
+ yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
+ ^" in core::List::•<dynamic>() as{TypeError} asy::Stream<core::List<core::int>>;
yield* self::MyStream::•<core::List<core::int>>();
}
static method bar() → core::Iterable<core::Map<core::int, core::int>> sync* {
- yield<core::int, core::int>{};
+ yield core::Map::•<core::int, core::int>();
yield let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:23:67: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Map<int, int>'.
- 'List' is from 'dart:core'.
- 'Map' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'Map<int, int>'.
yield /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
^" in core::List::•<dynamic>() as{TypeError} core::Map<core::int, core::int>;
- yield* let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:24:73: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'Iterable<Map<int, int>>'.
+ yield* let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:24:77: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'Iterable<Map<int, int>>'.
- 'Map' is from 'dart:core'.
- 'Iterable' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'Iterable<Map<int, int>>'.
- yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic, dynamic*/ {};
- ^" in <dynamic, dynamic>{} as{TypeError} core::Iterable<core::Map<core::int, core::int>>;
+ yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic, dynamic*/ Map();
+ ^" in core::Map::•<dynamic, dynamic>() as{TypeError} core::Iterable<core::Map<core::int, core::int>>;
yield* core::List::•<core::Map<core::int, core::int>>();
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
index 85ffbbc7..4ff259f 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
@@ -22,7 +22,7 @@
try {
#L1:
{
- if(:controller.{asy::_AsyncStarStreamController::add}(<core::int>[]))
+ if(:controller.{asy::_AsyncStarStreamController::add}(core::_GrowableList::•<core::int>(0)))
return null;
else
[yield] null;
@@ -35,12 +35,12 @@
return null;
else
[yield] null;
- if(:controller.{asy::_AsyncStarStreamController::addStream}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:68: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
- 'List' is from 'dart:core'.
- 'Stream' is from 'dart:async'.
Try changing the type of the left hand side, or casting the right hand side to 'Stream<List<int>>'.
- yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
- ^" in <dynamic>[] as{TypeError} asy::Stream<core::List<core::int>>))
+ yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic*/ List();
+ ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int>>))
return null;
else
[yield] null;
@@ -70,7 +70,7 @@
function :sync_op(core::_SyncIterator<core::Map<core::int, core::int>> :iterator) → core::bool yielding {
{
{
- :iterator.{core::_SyncIterator::_current} = <core::int, core::int>{};
+ :iterator.{core::_SyncIterator::_current} = core::Map::•<core::int, core::int>();
[yield] true;
}
{
@@ -83,12 +83,12 @@
[yield] true;
}
{
- :iterator.{core::_SyncIterator::_yieldEachIterable} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:24:73: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'Iterable<Map<int, int>>'.
+ :iterator.{core::_SyncIterator::_yieldEachIterable} = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:24:77: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'Iterable<Map<int, int>>'.
- 'Map' is from 'dart:core'.
- 'Iterable' is from 'dart:core'.
Try changing the type of the left hand side, or casting the right hand side to 'Iterable<Map<int, int>>'.
- yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic, dynamic*/ {};
- ^" in <dynamic, dynamic>{} as{TypeError} core::Iterable<core::Map<core::int, core::int>>;
+ yield* /*error:YIELD_OF_INVALID_TYPE*/ new /*@typeArgs=dynamic, dynamic*/ Map();
+ ^" in core::Map::•<dynamic, dynamic>() as{TypeError} core::Iterable<core::Map<core::int, core::int>>;
[yield] true;
}
{
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart
index 03941bd..3b9b207 100644
--- a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart
@@ -40,9 +40,9 @@
b = /*error:INVALID_ASSIGNMENT*/ "hi";
b = new B(3);
c1 = /*@typeArgs=dynamic*/ [];
- c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
+ c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
c2 = /*@typeArgs=dynamic*/ [];
- c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
+ c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
d = /*@typeArgs=dynamic, dynamic*/ {};
d = /*error:INVALID_ASSIGNMENT*/ 3;
e = new A();
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
index bee075a..9075c6f 100644
--- a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
@@ -26,19 +26,19 @@
// b = /*error:INVALID_ASSIGNMENT*/ "hi";
// ^
//
-// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:68: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
-// - 'Map' is from 'dart:core'.
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+// - 'Set' is from 'dart:core'.
// - 'List' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
-// c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
-// ^
+// c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+// ^
//
-// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:68: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
-// - 'Map' is from 'dart:core'.
+// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:59: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
+// - 'Set' is from 'dart:core'.
// - 'List' is from 'dart:core'.
// Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
-// c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
-// ^
+// c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic*/ {};
+// ^
//
// pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
// - 'Map' is from 'dart:core'.
@@ -85,6 +85,7 @@
library test;
import self as self;
import "dart:core" as core;
+import "dart:collection" as col;
class A extends core::Object {
field core::int x = null;
@@ -132,19 +133,9 @@
^" in "hi" as{TypeError} self::B;
self::b = new self::B::•(3);
self::c1 = <dynamic>[];
- self::c1 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:43:68: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
- - 'Map' is from 'dart:core'.
- - 'List' is from 'dart:core'.
-Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
- c1 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
- ^" in <dynamic, dynamic>{} as{TypeError} core::List<dynamic>;
+ self::c1 = let final core::Set<dynamic> #t6 = col::LinkedHashSet::•<dynamic>() in #t6;
self::c2 = <dynamic>[];
- self::c2 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:45:68: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'List<dynamic>'.
- - 'Map' is from 'dart:core'.
- - 'List' is from 'dart:core'.
-Try changing the type of the left hand side, or casting the right hand side to 'List<dynamic>'.
- c2 = /*error:INVALID_ASSIGNMENT*/ /*@typeArgs=dynamic, dynamic*/ {};
- ^" in <dynamic, dynamic>{} as{TypeError} core::List<dynamic>;
+ self::c2 = let final core::Set<dynamic> #t7 = col::LinkedHashSet::•<dynamic>() in #t7;
self::d = <dynamic, dynamic>{};
self::d = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart:47:36: Error: A value of type 'int' can't be assigned to a variable of type 'Map<dynamic, dynamic>'.
- 'Map' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/legacy.status b/pkg/front_end/testcases/legacy.status
index 04f06f8..e603fd2 100644
--- a/pkg/front_end/testcases/legacy.status
+++ b/pkg/front_end/testcases/legacy.status
@@ -125,6 +125,7 @@
runtime_checks_new/mixin_forwarding_stub_getter: RuntimeError # Test exercises strong mode semantics
runtime_checks_new/mixin_forwarding_stub_setter: RuntimeError # Test exercises strong mode semantics
runtime_checks_new/stub_checked_via_target: RuntimeError # Test exercises strong mode semantics
+set_literals/disambiguation_rule: RuntimeError
type_variable_as_super: Fail
uninitialized_fields: Fail # Fasta and dartk disagree on static initializers
void_methods: Fail # Bad return from setters.
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.expect
index af73d67..6742c9b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.expect
@@ -1,17 +1,17 @@
// Formatted problems:
//
-// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-// void foo(int x) {}
-// ^^^
-// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:12:12: Context: This is the inherited member.
+// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:12:12: Error: 'foo' is already declared in this scope.
// void set foo(int x);
// ^^^
+// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:10:8: Context: Previous declaration of 'foo'.
+// void foo(int x) {}
+// ^^^
// Unhandled errors:
//
-// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-// void foo(int x) {}
-// ^^^
+// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:12:12: Error: 'foo' is already declared in this scope.
+// void set foo(int x);
+// ^^^
library;
import self as self;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.transformed.expect
index 37f1f55..e9e7677 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.legacy.transformed.expect
@@ -1,8 +1,8 @@
// Unhandled errors:
//
-// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-// void foo(int x) {}
-// ^^^
+// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:12:12: Error: 'foo' is already declared in this scope.
+// void set foo(int x);
+// ^^^
library;
import self as self;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect
index 51ebf0c..d8c8b38 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect
@@ -1,11 +1,11 @@
// Formatted problems:
//
-// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-// void foo(int x) {}
-// ^^^
-// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:12:12: Context: This is the inherited member.
+// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:12:12: Error: 'foo' is already declared in this scope.
// void set foo(int x);
// ^^^
+// pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart:10:8: Context: Previous declaration of 'foo'.
+// void foo(int x) {}
+// ^^^
library;
import self as self;
diff --git a/pkg/front_end/testcases/rasta/super.dart.legacy.expect b/pkg/front_end/testcases/rasta/super.dart.legacy.expect
index ffacfe6..473cece 100644
--- a/pkg/front_end/testcases/rasta/super.dart.legacy.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.legacy.expect
@@ -1,11 +1,11 @@
// Formatted problems:
//
-// pkg/front_end/testcases/rasta/super.dart:26:8: Error: Can't declare a member that conflicts with an inherited one.
-// void n() {}
-// ^
-// pkg/front_end/testcases/rasta/super.dart:27:7: Context: This is the inherited member.
+// pkg/front_end/testcases/rasta/super.dart:27:7: Error: 'n' is already declared in this scope.
// set n(_) {}
// ^
+// pkg/front_end/testcases/rasta/super.dart:26:8: Context: Previous declaration of 'n'.
+// void n() {}
+// ^
//
// pkg/front_end/testcases/rasta/super.dart:43:5: Error: '+' is not a prefix operator.
// Try removing '+'.
@@ -239,9 +239,9 @@
// Unhandled errors:
//
-// pkg/front_end/testcases/rasta/super.dart:26:8: Error: Can't declare a member that conflicts with an inherited one.
-// void n() {}
-// ^
+// pkg/front_end/testcases/rasta/super.dart:27:7: Error: 'n' is already declared in this scope.
+// set n(_) {}
+// ^
//
// pkg/front_end/testcases/rasta/super.dart:43:5: Error: '+' is not a prefix operator.
// Try removing '+'.
diff --git a/pkg/front_end/testcases/rasta/super.dart.legacy.transformed.expect b/pkg/front_end/testcases/rasta/super.dart.legacy.transformed.expect
index 3a83d7b..f92047d 100644
--- a/pkg/front_end/testcases/rasta/super.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.legacy.transformed.expect
@@ -1,8 +1,8 @@
// Unhandled errors:
//
-// pkg/front_end/testcases/rasta/super.dart:26:8: Error: Can't declare a member that conflicts with an inherited one.
-// void n() {}
-// ^
+// pkg/front_end/testcases/rasta/super.dart:27:7: Error: 'n' is already declared in this scope.
+// set n(_) {}
+// ^
//
// pkg/front_end/testcases/rasta/super.dart:43:5: Error: '+' is not a prefix operator.
// Try removing '+'.
diff --git a/pkg/front_end/testcases/rasta/super.dart.outline.expect b/pkg/front_end/testcases/rasta/super.dart.outline.expect
index 8798c49..c3496aa 100644
--- a/pkg/front_end/testcases/rasta/super.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.outline.expect
@@ -1,11 +1,11 @@
// Formatted problems:
//
-// pkg/front_end/testcases/rasta/super.dart:26:8: Error: Can't declare a member that conflicts with an inherited one.
-// void n() {}
-// ^
-// pkg/front_end/testcases/rasta/super.dart:27:7: Context: This is the inherited member.
+// pkg/front_end/testcases/rasta/super.dart:27:7: Error: 'n' is already declared in this scope.
// set n(_) {}
// ^
+// pkg/front_end/testcases/rasta/super.dart:26:8: Context: Previous declaration of 'n'.
+// void n() {}
+// ^
library;
import self as self;
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart
new file mode 100644
index 0000000..15f76e8
--- /dev/null
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async' show FutureOr;
+
+import 'dart:collection' show LinkedHashMap, LinkedHashSet;
+
+main() async {
+ Map<int, bool> m = {};
+ Set<int> s = {};
+ Iterable<int> i = {};
+ LinkedHashSet<int> lhs = {};
+ LinkedHashMap<int, bool> lhm = {};
+
+ Map<int, bool> fm = await mapfun();
+ Set<int> fs = await setfun();
+ Iterable<int> fi = await iterablefun();
+ LinkedHashSet<int> flhs = await lhsfun();
+ LinkedHashMap<int, bool> flhm = await lhmfun();
+
+ Map<int, bool> fm2 = await mapfun2();
+ Set<int> fs2 = await setfun2();
+ Iterable<int> fi2 = await iterablefun2();
+ LinkedHashSet<int> flhs2 = await lhsfun2();
+ LinkedHashMap<int, bool> flhm2 = await lhmfun2();
+}
+
+Future<Map<int, bool>> mapfun() async => {};
+Future<Set<int>> setfun() async => {};
+Future<Iterable<int>> iterablefun() async => {};
+Future<LinkedHashSet<int>> lhsfun() async => {};
+Future<LinkedHashMap<int, bool>> lhmfun() async => {};
+
+FutureOr<Map<int, bool>> mapfun2() => {};
+FutureOr<Set<int>> setfun2() => {};
+FutureOr<Iterable<int>> iterablefun2() => {};
+FutureOr<LinkedHashSet<int>> lhsfun2() => {};
+FutureOr<LinkedHashMap<int, bool>> lhmfun2() => {};
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.legacy.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.legacy.expect
new file mode 100644
index 0000000..932c7ea
--- /dev/null
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.legacy.expect
@@ -0,0 +1,43 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+import "dart:async" as asy;
+
+static method main() → dynamic async {
+ core::Map<core::int, core::bool> m = <dynamic, dynamic>{};
+ core::Set<core::int> s = <dynamic, dynamic>{};
+ core::Iterable<core::int> i = <dynamic, dynamic>{};
+ col::LinkedHashSet<core::int> lhs = <dynamic, dynamic>{};
+ col::LinkedHashMap<core::int, core::bool> lhm = <dynamic, dynamic>{};
+ core::Map<core::int, core::bool> fm = await self::mapfun();
+ core::Set<core::int> fs = await self::setfun();
+ core::Iterable<core::int> fi = await self::iterablefun();
+ col::LinkedHashSet<core::int> flhs = await self::lhsfun();
+ col::LinkedHashMap<core::int, core::bool> flhm = await self::lhmfun();
+ core::Map<core::int, core::bool> fm2 = await self::mapfun2();
+ core::Set<core::int> fs2 = await self::setfun2();
+ core::Iterable<core::int> fi2 = await self::iterablefun2();
+ col::LinkedHashSet<core::int> flhs2 = await self::lhsfun2();
+ col::LinkedHashMap<core::int, core::bool> flhm2 = await self::lhmfun2();
+}
+static method mapfun() → asy::Future<core::Map<core::int, core::bool>> async
+ return <dynamic, dynamic>{};
+static method setfun() → asy::Future<core::Set<core::int>> async
+ return <dynamic, dynamic>{};
+static method iterablefun() → asy::Future<core::Iterable<core::int>> async
+ return <dynamic, dynamic>{};
+static method lhsfun() → asy::Future<col::LinkedHashSet<core::int>> async
+ return <dynamic, dynamic>{};
+static method lhmfun() → asy::Future<col::LinkedHashMap<core::int, core::bool>> async
+ return <dynamic, dynamic>{};
+static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
+ return <dynamic, dynamic>{};
+static method setfun2() → asy::FutureOr<core::Set<core::int>>
+ return <dynamic, dynamic>{};
+static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
+ return <dynamic, dynamic>{};
+static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
+ return <dynamic, dynamic>{};
+static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
+ return <dynamic, dynamic>{};
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.legacy.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.legacy.transformed.expect
new file mode 100644
index 0000000..7ed15e3
--- /dev/null
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.legacy.transformed.expect
@@ -0,0 +1,202 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method main() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ core::Map<core::int, core::bool> m = <dynamic, dynamic>{};
+ core::Set<core::int> s = <dynamic, dynamic>{};
+ core::Iterable<core::int> i = <dynamic, dynamic>{};
+ col::LinkedHashSet<core::int> lhs = <dynamic, dynamic>{};
+ col::LinkedHashMap<core::int, core::bool> lhm = <dynamic, dynamic>{};
+ [yield] let dynamic #t1 = asy::_awaitHelper(self::mapfun(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Map<core::int, core::bool> fm = :result;
+ [yield] let dynamic #t2 = asy::_awaitHelper(self::setfun(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Set<core::int> fs = :result;
+ [yield] let dynamic #t3 = asy::_awaitHelper(self::iterablefun(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Iterable<core::int> fi = :result;
+ [yield] let dynamic #t4 = asy::_awaitHelper(self::lhsfun(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashSet<core::int> flhs = :result;
+ [yield] let dynamic #t5 = asy::_awaitHelper(self::lhmfun(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashMap<core::int, core::bool> flhm = :result;
+ [yield] let dynamic #t6 = asy::_awaitHelper(self::mapfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Map<core::int, core::bool> fm2 = :result;
+ [yield] let dynamic #t7 = asy::_awaitHelper(self::setfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Set<core::int> fs2 = :result;
+ [yield] let dynamic #t8 = asy::_awaitHelper(self::iterablefun2(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Iterable<core::int> fi2 = :result;
+ [yield] let dynamic #t9 = asy::_awaitHelper(self::lhsfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashSet<core::int> flhs2 = :result;
+ [yield] let dynamic #t10 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashMap<core::int, core::bool> flhm2 = :result;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method mapfun() → asy::Future<core::Map<core::int, core::bool>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::Map<core::int, core::bool>> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Map<core::int, core::bool>>();
+ asy::FutureOr<core::Map<core::int, core::bool>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = <dynamic, dynamic>{};
+ break #L2;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method setfun() → asy::Future<core::Set<core::int>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::Set<core::int>> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Set<core::int>>();
+ asy::FutureOr<core::Set<core::int>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ :return_value = <dynamic, dynamic>{};
+ break #L3;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method iterablefun() → asy::Future<core::Iterable<core::int>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::Iterable<core::int>> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Iterable<core::int>>();
+ asy::FutureOr<core::Iterable<core::int>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ :return_value = <dynamic, dynamic>{};
+ break #L4;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method lhsfun() → asy::Future<col::LinkedHashSet<core::int>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<col::LinkedHashSet<core::int>> :async_completer = new asy::_AsyncAwaitCompleter::•<col::LinkedHashSet<core::int>>();
+ asy::FutureOr<col::LinkedHashSet<core::int>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L5:
+ {
+ :return_value = <dynamic, dynamic>{};
+ break #L5;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method lhmfun() → asy::Future<col::LinkedHashMap<core::int, core::bool>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<col::LinkedHashMap<core::int, core::bool>> :async_completer = new asy::_AsyncAwaitCompleter::•<col::LinkedHashMap<core::int, core::bool>>();
+ asy::FutureOr<col::LinkedHashMap<core::int, core::bool>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L6:
+ {
+ :return_value = <dynamic, dynamic>{};
+ break #L6;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
+ return <dynamic, dynamic>{};
+static method setfun2() → asy::FutureOr<core::Set<core::int>>
+ return <dynamic, dynamic>{};
+static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
+ return <dynamic, dynamic>{};
+static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
+ return <dynamic, dynamic>{};
+static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
+ return <dynamic, dynamic>{};
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.outline.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.outline.expect
new file mode 100644
index 0000000..4c67211
--- /dev/null
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.outline.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method main() → dynamic
+ ;
+static method mapfun() → asy::Future<core::Map<core::int, core::bool>>
+ ;
+static method setfun() → asy::Future<core::Set<core::int>>
+ ;
+static method iterablefun() → asy::Future<core::Iterable<core::int>>
+ ;
+static method lhsfun() → asy::Future<col::LinkedHashSet<core::int>>
+ ;
+static method lhmfun() → asy::Future<col::LinkedHashMap<core::int, core::bool>>
+ ;
+static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
+ ;
+static method setfun2() → asy::FutureOr<core::Set<core::int>>
+ ;
+static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
+ ;
+static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
+ ;
+static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
+ ;
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect
new file mode 100644
index 0000000..e5e3a65
--- /dev/null
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect
@@ -0,0 +1,97 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+// - 'Map' is from 'dart:core'.
+// - 'LinkedHashMap' is from 'dart:collection'.
+// Change the type of the map literal or the context in which it is used.
+// LinkedHashMap<int, bool> lhm = {};
+// ^
+//
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+// - 'Map' is from 'dart:core'.
+// - 'LinkedHashMap' is from 'dart:collection'.
+// Change the type of the map literal or the context in which it is used.
+// Future<LinkedHashMap<int, bool>> lhmfun() async => {};
+// ^
+//
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
+// - 'Set' is from 'dart:core'.
+// - 'FutureOr' is from 'dart:async'.
+// - 'LinkedHashSet' is from 'dart:collection'.
+// Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashSet<int>>'.
+// FutureOr<LinkedHashSet<int>> lhsfun2() => {};
+// ^
+//
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
+// - 'Map' is from 'dart:core'.
+// - 'FutureOr' is from 'dart:async'.
+// - 'LinkedHashMap' is from 'dart:collection'.
+// Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashMap<int, bool>>'.
+// FutureOr<LinkedHashMap<int, bool>> lhmfun2() => {};
+// ^
+
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+import "dart:async" as asy;
+
+static method main() → dynamic async {
+ core::Map<core::int, core::bool> m = <core::int, core::bool>{};
+ core::Set<core::int> s = let final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>() in #t1;
+ core::Iterable<core::int> i = let final core::Set<core::int> #t2 = col::LinkedHashSet::•<core::int>() in #t2;
+ col::LinkedHashSet<core::int> lhs = (let final core::Set<dynamic> #t3 = col::LinkedHashSet::•<dynamic>() in #t3) as{TypeError} col::LinkedHashSet<core::int>;
+ col::LinkedHashMap<core::int, core::bool> lhm = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+ - 'Map' is from 'dart:core'.
+ - 'LinkedHashMap' is from 'dart:collection'.
+Change the type of the map literal or the context in which it is used.
+ LinkedHashMap<int, bool> lhm = {};
+ ^" in <dynamic, dynamic>{};
+ core::Map<core::int, core::bool> fm = await self::mapfun();
+ core::Set<core::int> fs = await self::setfun();
+ core::Iterable<core::int> fi = await self::iterablefun();
+ col::LinkedHashSet<core::int> flhs = await self::lhsfun();
+ col::LinkedHashMap<core::int, core::bool> flhm = await self::lhmfun();
+ core::Map<core::int, core::bool> fm2 = await self::mapfun2();
+ core::Set<core::int> fs2 = await self::setfun2();
+ core::Iterable<core::int> fi2 = await self::iterablefun2();
+ col::LinkedHashSet<core::int> flhs2 = await self::lhsfun2();
+ col::LinkedHashMap<core::int, core::bool> flhm2 = await self::lhmfun2();
+}
+static method mapfun() → asy::Future<core::Map<core::int, core::bool>> async
+ return <core::int, core::bool>{};
+static method setfun() → asy::Future<core::Set<core::int>> async
+ return let final core::Set<core::int> #t5 = col::LinkedHashSet::•<core::int>() in #t5;
+static method iterablefun() → asy::Future<core::Iterable<core::int>> async
+ return let final core::Set<core::int> #t6 = col::LinkedHashSet::•<core::int>() in #t6;
+static method lhsfun() → asy::Future<col::LinkedHashSet<core::int>> async
+ return (let final core::Set<dynamic> #t7 = col::LinkedHashSet::•<dynamic>() in #t7) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+static method lhmfun() → asy::Future<col::LinkedHashMap<core::int, core::bool>> async
+ return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+ - 'Map' is from 'dart:core'.
+ - 'LinkedHashMap' is from 'dart:collection'.
+Change the type of the map literal or the context in which it is used.
+Future<LinkedHashMap<int, bool>> lhmfun() async => {};
+ ^" in <dynamic, dynamic>{};
+static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
+ return <core::int, core::bool>{};
+static method setfun2() → asy::FutureOr<core::Set<core::int>>
+ return let final core::Set<core::int> #t9 = col::LinkedHashSet::•<core::int>() in #t9;
+static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
+ return let final core::Set<core::int> #t10 = col::LinkedHashSet::•<core::int>() in #t10;
+static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
+ return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
+ - 'Set' is from 'dart:core'.
+ - 'FutureOr' is from 'dart:async'.
+ - 'LinkedHashSet' is from 'dart:collection'.
+Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashSet<int>>'.
+FutureOr<LinkedHashSet<int>> lhsfun2() => {};
+ ^" in (let final core::Set<dynamic> #t12 = col::LinkedHashSet::•<dynamic>() in #t12) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
+ return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
+ - 'Map' is from 'dart:core'.
+ - 'FutureOr' is from 'dart:async'.
+ - 'LinkedHashMap' is from 'dart:collection'.
+Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashMap<int, bool>>'.
+FutureOr<LinkedHashMap<int, bool>> lhmfun2() => {};
+ ^" in <dynamic, dynamic>{} as{TypeError} asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>;
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
new file mode 100644
index 0000000..9b60cf8
--- /dev/null
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
@@ -0,0 +1,224 @@
+library;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method main() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ core::Map<core::int, core::bool> m = <core::int, core::bool>{};
+ core::Set<core::int> s = let final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>() in #t1;
+ core::Iterable<core::int> i = let final core::Set<core::int> #t2 = col::LinkedHashSet::•<core::int>() in #t2;
+ col::LinkedHashSet<core::int> lhs = (let final core::Set<dynamic> #t3 = col::LinkedHashSet::•<dynamic>() in #t3) as{TypeError} col::LinkedHashSet<core::int>;
+ col::LinkedHashMap<core::int, core::bool> lhm = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+ - 'Map' is from 'dart:core'.
+ - 'LinkedHashMap' is from 'dart:collection'.
+Change the type of the map literal or the context in which it is used.
+ LinkedHashMap<int, bool> lhm = {};
+ ^" in <dynamic, dynamic>{};
+ [yield] let dynamic #t5 = asy::_awaitHelper(self::mapfun(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Map<core::int, core::bool> fm = :result;
+ [yield] let dynamic #t6 = asy::_awaitHelper(self::setfun(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Set<core::int> fs = :result;
+ [yield] let dynamic #t7 = asy::_awaitHelper(self::iterablefun(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Iterable<core::int> fi = :result;
+ [yield] let dynamic #t8 = asy::_awaitHelper(self::lhsfun(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashSet<core::int> flhs = :result;
+ [yield] let dynamic #t9 = asy::_awaitHelper(self::lhmfun(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashMap<core::int, core::bool> flhm = :result;
+ [yield] let dynamic #t10 = asy::_awaitHelper(self::mapfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Map<core::int, core::bool> fm2 = :result;
+ [yield] let dynamic #t11 = asy::_awaitHelper(self::setfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Set<core::int> fs2 = :result;
+ [yield] let dynamic #t12 = asy::_awaitHelper(self::iterablefun2(), :async_op_then, :async_op_error, :async_op) in null;
+ core::Iterable<core::int> fi2 = :result;
+ [yield] let dynamic #t13 = asy::_awaitHelper(self::lhsfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashSet<core::int> flhs2 = :result;
+ [yield] let dynamic #t14 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
+ col::LinkedHashMap<core::int, core::bool> flhm2 = :result;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method mapfun() → asy::Future<core::Map<core::int, core::bool>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::Map<core::int, core::bool>> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Map<core::int, core::bool>>();
+ asy::FutureOr<core::Map<core::int, core::bool>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = <core::int, core::bool>{};
+ break #L2;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method setfun() → asy::Future<core::Set<core::int>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::Set<core::int>> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Set<core::int>>();
+ asy::FutureOr<core::Set<core::int>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ :return_value = let final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>() in #t15;
+ break #L3;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method iterablefun() → asy::Future<core::Iterable<core::int>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::Iterable<core::int>> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Iterable<core::int>>();
+ asy::FutureOr<core::Iterable<core::int>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ :return_value = let final core::Set<core::int> #t16 = col::LinkedHashSet::•<core::int>() in #t16;
+ break #L4;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method lhsfun() → asy::Future<col::LinkedHashSet<core::int>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<col::LinkedHashSet<core::int>> :async_completer = new asy::_AsyncAwaitCompleter::•<col::LinkedHashSet<core::int>>();
+ asy::FutureOr<col::LinkedHashSet<core::int>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L5:
+ {
+ :return_value = (let final core::Set<dynamic> #t17 = col::LinkedHashSet::•<dynamic>() in #t17) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+ break #L5;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method lhmfun() → asy::Future<col::LinkedHashMap<core::int, core::bool>> /* originally async */ {
+ final asy::_AsyncAwaitCompleter<col::LinkedHashMap<core::int, core::bool>> :async_completer = new asy::_AsyncAwaitCompleter::•<col::LinkedHashMap<core::int, core::bool>>();
+ asy::FutureOr<col::LinkedHashMap<core::int, core::bool>> :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dynamic :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L6:
+ {
+ :return_value = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+ - 'Map' is from 'dart:core'.
+ - 'LinkedHashMap' is from 'dart:collection'.
+Change the type of the map literal or the context in which it is used.
+Future<LinkedHashMap<int, bool>> lhmfun() async => {};
+ ^" in <dynamic, dynamic>{};
+ break #L6;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
+ return <core::int, core::bool>{};
+static method setfun2() → asy::FutureOr<core::Set<core::int>>
+ return let final core::Set<core::int> #t19 = col::LinkedHashSet::•<core::int>() in #t19;
+static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
+ return let final core::Set<core::int> #t20 = col::LinkedHashSet::•<core::int>() in #t20;
+static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
+ return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
+ - 'Set' is from 'dart:core'.
+ - 'FutureOr' is from 'dart:async'.
+ - 'LinkedHashSet' is from 'dart:collection'.
+Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashSet<int>>'.
+FutureOr<LinkedHashSet<int>> lhsfun2() => {};
+ ^" in (let final core::Set<dynamic> #t22 = col::LinkedHashSet::•<dynamic>() in #t22) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
+ return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
+ - 'Map' is from 'dart:core'.
+ - 'FutureOr' is from 'dart:async'.
+ - 'LinkedHashMap' is from 'dart:collection'.
+Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashMap<int, bool>>'.
+FutureOr<LinkedHashMap<int, bool>> lhmfun2() => {};
+ ^" in <dynamic, dynamic>{} as{TypeError} asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 20f95d6..f42074f 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -44,6 +44,7 @@
inference/generic_methods_handle_override_of_non_generic_with_generic: TypeCheckError
inference/generic_methods_infer_js_builtin: InstrumentationMismatch # Issue #30029
inference/infer_field_override_multiple: TypeCheckError
+inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TypeCheckError # Issue #35630
inference/infer_method_missing_params: TypeCheckError
inference/infer_type_regardless_of_declaration_order_or_cycles: RuntimeError
inference/infer_types_on_generic_instantiations_4: RuntimeError
@@ -145,6 +146,7 @@
runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError
runtime_checks_new/mixin_forwarding_stub_setter: TypeCheckError
+set_literals/disambiguation_rule: RuntimeError
statements: Crash
type_variable_as_super: RuntimeError
type_variable_prefix: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 08fd945..c4a93e2 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -60,7 +60,7 @@
closure: TextSerializationFailure # Was: Pass
co19_language_metadata_syntax_t04: TextSerializationFailure # Was: Pass
constructor_const_inference: TextSerializationFailure # Was: Pass
-constructor_cycle: Crash # Was: Pass
+constructor_cycle: TextSerializationFailure # Was: Pass
constructor_function_types: TextSerializationFailure # Was: Pass
constructor_initializer_invalid: TextSerializationFailure # Was: RuntimeError # Fails execution after recovery
continue_inference_after_error_lib: TextSerializationFailure # Was: Pass
@@ -312,7 +312,7 @@
inference/infer_final_field_getter_and_setter: TextSerializationFailure # Was: Pass
inference/infer_final_field_getter_only: TextSerializationFailure # Was: Pass
inference/infer_final_field_setter_only: TextSerializationFailure # Was: Pass
-inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TextSerializationFailure # Was: Pass
+inference/infer_from_complex_expressions_if_outer_most_value_is_precise: TypeCheckError # Issue #35630
inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields2: TextSerializationFailure # Was: Pass
inference/infer_from_rhs_only_if_it_wont_conflict_with_overridden_fields: TextSerializationFailure # Was: Pass
inference/infer_from_variables_in_cycle_libs_when_flag_is_on2_a: TextSerializationFailure # Was: Pass
@@ -770,7 +770,7 @@
rasta/issue_000034: TextSerializationFailure # Was: RuntimeError
rasta/issue_000035a: TextSerializationFailure # Was: Pass
rasta/issue_000035: TextSerializationFailure # Was: Pass
-rasta/issue_000036: TextSerializationFailure # Was: RuntimeError
+rasta/issue_000036: RuntimeError
rasta/issue_000039: VerificationError
rasta/issue_000041: TextSerializationFailure # Was: RuntimeError
rasta/issue_000042: TextSerializationFailure # Was: RuntimeError
@@ -950,6 +950,7 @@
runtime_checks_new/stub_from_interface_covariantImpl_from_interface: TextSerializationFailure # Was: Pass
runtime_checks_new/stub_from_interface_covariantImpl_from_super: TextSerializationFailure # Was: Pass
runtime_checks_new/stub_from_interface_covariantInterface_from_class: TextSerializationFailure # Was: Pass
+set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
statements: Crash
static_setter: TextSerializationFailure # Was: Pass
store_load: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 7728f88..d4ccb3a 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -12,10 +12,10 @@
show SingleRootFileSystem;
import 'package:front_end/src/api_prototype/compiler_options.dart'
- show CompilerOptions;
+ show CompilerOptions, parseExperimentalFlags;
import 'package:front_end/src/api_prototype/experimental_flags.dart'
- show ExperimentalFlag, parseExperimentalFlag;
+ show ExperimentalFlag;
import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;
@@ -240,7 +240,6 @@
const Map<String, dynamic> optionSpecification = const <String, dynamic>{
"--bytecode": false,
"--compile-sdk": Uri,
- "--disable-experiment": ",",
"--dump-ir": false,
"--enable-experiment": ",",
"--exclude-source": false,
@@ -269,6 +268,10 @@
"/h": "--help",
};
+void throwCommandLineProblem(String message) {
+ throw new CommandLineProblem.deprecated(message);
+}
+
ProcessedOptions analyzeCommandLine(
String programName,
ParsedArguments parsedArguments,
@@ -343,30 +346,8 @@
});
}
- final List<String> enabledExperiments = options["--enable-experiment"];
- final List<String> disabledExperiments = options["--disable-experiment"];
-
- Map<ExperimentalFlag, bool> experimentalFlags = {};
-
- void setExperimentalFlags(List<String> experiments, bool value) {
- if (experiments != null) {
- for (String experiment in experiments) {
- ExperimentalFlag flag = parseExperimentalFlag(experiment);
- if (flag == null) {
- throw new CommandLineProblem.deprecated(
- "Unknown experiment: " + experiment);
- }
- if (experimentalFlags.containsKey(flag)) {
- throw new CommandLineProblem.deprecated(
- "Experiment mentioned more than once: " + experiment);
- }
- experimentalFlags[flag] = value;
- }
- }
- }
-
- setExperimentalFlags(enabledExperiments, true);
- setExperimentalFlags(disabledExperiments, false);
+ Map<ExperimentalFlag, bool> experimentalFlags = parseExperimentalFlags(
+ options["--enable-experiment"], throwCommandLineProblem);
if (programName == "compile_platform") {
if (arguments.length != 5) {
diff --git a/pkg/kernel/bin/transform.dart b/pkg/kernel/bin/transform.dart
index a2d90ae..157aa9c 100755
--- a/pkg/kernel/bin/transform.dart
+++ b/pkg/kernel/bin/transform.dart
@@ -12,13 +12,15 @@
import 'package:kernel/kernel.dart';
import 'package:kernel/src/tool/batch_util.dart';
import 'package:kernel/target/targets.dart';
-import 'package:kernel/transformations/constants.dart' as constants;
+
+import 'package:kernel/transformations/constants.dart' as constants
+ show SimpleErrorReporter, transformComponent;
+
import 'package:kernel/transformations/continuation.dart' as cont;
import 'package:kernel/transformations/empty.dart' as empty;
import 'package:kernel/transformations/method_call.dart' as method_call;
import 'package:kernel/transformations/mixin_full_resolution.dart' as mix;
import 'package:kernel/transformations/treeshaker.dart' as treeshaker;
-// import 'package:kernel/verifier.dart';
import 'package:kernel/transformations/coq.dart' as coq;
import 'package:kernel/vm/constants_native_effects.dart';
import 'package:kernel/src/tool/command_line_util.dart';
@@ -97,8 +99,9 @@
final Map<String, String> defines = null;
final VmConstantsBackend backend =
new VmConstantsBackend(defines, coreTypes);
- component =
- constants.transformComponent(component, backend, legacyMode: true);
+ component = constants.transformComponent(
+ component, backend, const constants.SimpleErrorReporter(),
+ legacyMode: true);
break;
case 'treeshake':
component = treeshaker.transformComponent(coreTypes, hierarchy, component,
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 865beb6..9408027 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -131,7 +131,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 15;
+ UInt32 formatVersion = 16;
Library[] libraries;
UriSource sourceMap;
List<CanonicalName> canonicalNames;
@@ -926,6 +926,29 @@
DartType type;
}
+type EnvironmentBoolConstant extends Constant {
+ Byte tag = 12;
+ StringReference name;
+ ConstantReference defaultValue;
+}
+
+type EnvironmentIntConstant extends Constant {
+ Byte tag = 13;
+ StringReference name;
+ ConstantReference defaultValue;
+}
+
+type EnvironmentStringConstant extends Constant {
+ Byte tag = 14;
+ StringReference name;
+ ConstantReference defaultValue;
+}
+
+type UnevaluatedConstant extends Constant {
+ Byte tag = 15;
+ Expression expression;
+}
+
abstract type Statement extends Node {}
type ExpressionStatement extends Statement {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 4f16b8a..2bddaf9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -83,7 +83,7 @@
const Node();
accept(Visitor v);
- visitChildren(Visitor v);
+ void visitChildren(Visitor v);
/// Returns the textual representation of this node for use in debugging.
///
@@ -2190,7 +2190,7 @@
type = (type as TypeParameterType).parameter.bound;
}
if (type is InterfaceType) {
- var upcastType = types.hierarchy.getTypeAsInstanceOf(type, superclass);
+ var upcastType = types.getTypeAsInstanceOf(type, superclass);
if (upcastType != null) return upcastType;
} else if (type is BottomType) {
return superclass.bottomType;
@@ -2558,8 +2558,7 @@
if (declaringClass.typeParameters.isEmpty) {
return interfaceTarget.getterType;
}
- var receiver =
- types.hierarchy.getTypeAsInstanceOf(types.thisType, declaringClass);
+ var receiver = types.getTypeAsInstanceOf(types.thisType, declaringClass);
return Substitution.fromInterfaceType(receiver)
.substituteType(interfaceTarget.getterType);
}
@@ -2881,8 +2880,7 @@
DartType getStaticType(TypeEnvironment types) {
if (interfaceTarget == null) return const DynamicType();
Class superclass = interfaceTarget.enclosingClass;
- var receiverType =
- types.hierarchy.getTypeAsInstanceOf(types.thisType, superclass);
+ var receiverType = types.getTypeAsInstanceOf(types.thisType, superclass);
var returnType = Substitution.fromInterfaceType(receiverType)
.substituteType(interfaceTarget.function.returnType);
return Substitution.fromPairs(
@@ -5442,6 +5440,67 @@
DartType getType(TypeEnvironment types) => types.typeType;
}
+abstract class EnvironmentConstant extends Constant {
+ final String name;
+ final Constant defaultValue;
+
+ EnvironmentConstant(this.name, this.defaultValue);
+ visitChildren(Visitor v) {
+ defaultValue.acceptReference(v);
+ }
+}
+
+class EnvironmentBoolConstant extends EnvironmentConstant {
+ EnvironmentBoolConstant(String name, Constant defaultValue)
+ : super(name, defaultValue);
+
+ accept(ConstantVisitor v) => v.visitEnvironmentBoolConstant(this);
+ acceptReference(Visitor v) {
+ return v.visitEnvironmentBoolConstantReference(this);
+ }
+
+ DartType getType(TypeEnvironment types) => types.boolType;
+}
+
+class EnvironmentIntConstant extends EnvironmentConstant {
+ EnvironmentIntConstant(String name, Constant defaultValue)
+ : super(name, defaultValue);
+
+ accept(ConstantVisitor v) => v.visitEnvironmentIntConstant(this);
+ acceptReference(Visitor v) {
+ return v.visitEnvironmentIntConstantReference(this);
+ }
+
+ DartType getType(TypeEnvironment types) => types.intType;
+}
+
+class EnvironmentStringConstant extends EnvironmentConstant {
+ EnvironmentStringConstant(String name, Constant defaultValue)
+ : super(name, defaultValue);
+
+ accept(ConstantVisitor v) => v.visitEnvironmentStringConstant(this);
+ acceptReference(Visitor v) {
+ return v.visitEnvironmentStringConstantReference(this);
+ }
+
+ DartType getType(TypeEnvironment types) => types.stringType;
+}
+
+class UnevaluatedConstant extends Constant {
+ final Expression expression;
+
+ UnevaluatedConstant(this.expression);
+
+ visitChildren(Visitor v) {
+ expression.accept(v);
+ }
+
+ accept(ConstantVisitor v) => v.visitUnevaluatedConstant(this);
+ acceptReference(Visitor v) => v.visitUnevaluatedConstantReference(this);
+
+ DartType getType(TypeEnvironment types) => expression.getStaticType(types);
+}
+
// ------------------------------------------------------------------------
// COMPONENT
// ------------------------------------------------------------------------
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 0c9b61b..59148f3 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -270,6 +270,21 @@
case ConstantTag.TypeLiteralConstant:
final DartType type = readDartType();
return new TypeLiteralConstant(type);
+ case ConstantTag.EnvironmentBoolConstant:
+ final String name = readStringReference();
+ final Constant defaultValue = readConstantReference();
+ return new EnvironmentBoolConstant(name, defaultValue);
+ case ConstantTag.EnvironmentIntConstant:
+ final String name = readStringReference();
+ final Constant defaultValue = readConstantReference();
+ return new EnvironmentIntConstant(name, defaultValue);
+ case ConstantTag.EnvironmentStringConstant:
+ final String name = readStringReference();
+ final Constant defaultValue = readConstantReference();
+ return new EnvironmentStringConstant(name, defaultValue);
+ case ConstantTag.UnevaluatedConstant:
+ final Expression expression = readExpression();
+ return new UnevaluatedConstant(expression);
}
throw fail('unexpected constant tag: $constantTag');
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 892a72b..2e5bb5d 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -243,6 +243,21 @@
} else if (constant is TypeLiteralConstant) {
writeByte(ConstantTag.TypeLiteralConstant);
writeDartType(constant.type);
+ } else if (constant is EnvironmentBoolConstant) {
+ writeByte(ConstantTag.EnvironmentBoolConstant);
+ writeStringReference(constant.name);
+ writeConstantReference(constant.defaultValue);
+ } else if (constant is EnvironmentIntConstant) {
+ writeByte(ConstantTag.EnvironmentIntConstant);
+ writeStringReference(constant.name);
+ writeConstantReference(constant.defaultValue);
+ } else if (constant is EnvironmentStringConstant) {
+ writeByte(ConstantTag.EnvironmentStringConstant);
+ writeStringReference(constant.name);
+ writeConstantReference(constant.defaultValue);
+ } else if (constant is UnevaluatedConstant) {
+ writeByte(ConstantTag.UnevaluatedConstant);
+ writeNode(constant.expression);
} else {
throw new ArgumentError('Unsupported constant $constant');
}
@@ -2048,6 +2063,39 @@
}
@override
+ void visitEnvironmentBoolConstant(EnvironmentBoolConstant node) {
+ throw new UnsupportedError('serialization of EnvironmentBoolConstants');
+ }
+
+ @override
+ void visitEnvironmentBoolConstantReference(EnvironmentBoolConstant node) {
+ throw new UnsupportedError(
+ 'serialization of EnvironmentBoolConstant references');
+ }
+
+ @override
+ void visitEnvironmentIntConstant(EnvironmentIntConstant node) {
+ throw new UnsupportedError('serialization of EnvironmentIntConstants');
+ }
+
+ @override
+ void visitEnvironmentIntConstantReference(EnvironmentIntConstant node) {
+ throw new UnsupportedError(
+ 'serialization of EnvironmentIntConstant references');
+ }
+
+ @override
+ void visitEnvironmentStringConstant(EnvironmentStringConstant node) {
+ throw new UnsupportedError('serialization of EnvironmentStringConstants');
+ }
+
+ @override
+ void visitEnvironmentStringConstantReference(EnvironmentStringConstant node) {
+ throw new UnsupportedError(
+ 'serialization of EnvironmentStringConstant references');
+ }
+
+ @override
void visitFieldReference(Field node) {
throw new UnsupportedError('serialization of Field references');
}
@@ -2192,6 +2240,17 @@
void visitTypedefReference(Typedef node) {
throw new UnsupportedError('serialization of Typedef references');
}
+
+ @override
+ void visitUnevaluatedConstant(UnevaluatedConstant node) {
+ throw new UnsupportedError('serialization of UnevaluatedConstants');
+ }
+
+ @override
+ void visitUnevaluatedConstantReference(UnevaluatedConstant node) {
+ throw new UnsupportedError(
+ 'serialization of UnevaluatedConstant references');
+ }
}
typedef bool LibraryFilter(Library _);
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index a53ccc7..6a34a73 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -117,9 +117,10 @@
static const int MemberReference = 101;
static const int ConstantExpression = 107;
- // 108 is occupied by [RedirectingFactoryConstructor] (member).
- // 109 is occupied by [SetLiteral] (expression).
- // 110 is occupied by [ConstSetLiteral] (expression).
+
+ /// 108 is occupied by [RedirectingFactoryConstructor] (member).
+ /// 109 is occupied by [SetLiteral] (expression).
+ /// 110 is occupied by [ConstSetLiteral] (expression).
static const int SpecializedTagHighBit = 0x80; // 10000000
static const int SpecializedTagMask = 0xF8; // 11111000
@@ -136,7 +137,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
- static const int BinaryFormatVersion = 15;
+ static const int BinaryFormatVersion = 16;
}
abstract class ConstantTag {
@@ -152,4 +153,8 @@
static const int PartialInstantiationConstant = 9;
static const int TearOffConstant = 10;
static const int TypeLiteralConstant = 11;
+ static const int EnvironmentBoolConstant = 12;
+ static const int EnvironmentIntConstant = 13;
+ static const int EnvironmentStringConstant = 14;
+ static const int UnevaluatedConstant = 15;
}
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 1a7de5c..9fa31ec 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -39,9 +39,6 @@
/// [unordered], they are not included.
Iterable<Class> getOrderedClasses(Iterable<Class> unordered);
- /// True if the component contains another class that is a subtype of given one.
- bool hasProperSubtypes(Class class_);
-
// Returns the instantition of each generic supertype implemented by this
// class (e.g. getClassAsInstanceOf applied to all superclasses and
// interfaces).
@@ -697,14 +694,6 @@
}
@override
- bool hasProperSubtypes(Class class_) {
- _ClassInfo info = _infoFor[class_];
- return info.directExtenders.isNotEmpty ||
- info.directImplementers.isNotEmpty ||
- info.directMixers.isNotEmpty;
- }
-
- @override
List<Supertype> genericSupertypesOf(Class class_) {
final supertypes = _infoFor[class_].genericSuperTypes;
if (supertypes == null) return const <Supertype>[];
diff --git a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
new file mode 100644
index 0000000..beae19b
--- /dev/null
+++ b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library kernel.hierarchy_based_type_environment;
+
+import '../ast.dart' show Class, InterfaceType;
+
+import '../class_hierarchy.dart' show ClassHierarchy;
+
+import '../core_types.dart' show CoreTypes;
+
+import '../type_environment.dart' show TypeEnvironment;
+
+class HierarchyBasedTypeEnvironment extends TypeEnvironment {
+ final ClassHierarchy hierarchy;
+
+ HierarchyBasedTypeEnvironment(CoreTypes coreTypes, this.hierarchy,
+ {bool legacyMode: false})
+ : super.fromSubclass(coreTypes, legacyMode: legacyMode);
+
+ @override
+ InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+ return hierarchy.getTypeAsInstanceOf(type, superclass);
+ }
+}
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 57eb05c..2f74c96 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1911,6 +1911,24 @@
endLine(sb.toString());
}
+ visitEnvironmentBoolConstant(EnvironmentBoolConstant node) {
+ final String name = syntheticNames.nameConstant(node);
+ final String defaultValue = syntheticNames.nameConstant(node.defaultValue);
+ endLine(' $name = bool.fromEnvironment(${node.name}, ${defaultValue})');
+ }
+
+ visitEnvironmentIntConstant(EnvironmentIntConstant node) {
+ final String name = syntheticNames.nameConstant(node);
+ final String defaultValue = syntheticNames.nameConstant(node.defaultValue);
+ endLine(' $name = int.fromEnvironment(${node.name}, ${defaultValue})');
+ }
+
+ visitEnvironmentStringConstant(EnvironmentStringConstant node) {
+ final String name = syntheticNames.nameConstant(node);
+ final String defaultValue = syntheticNames.nameConstant(node.defaultValue);
+ endLine(' $name = String.fromEnvironment(${node.name}, ${defaultValue})');
+ }
+
defaultNode(Node node) {
write('<${node.runtimeType}>');
}
diff --git a/pkg/kernel/lib/text/serializer_combinators.dart b/pkg/kernel/lib/text/serializer_combinators.dart
index 46d0237..4b34e70 100644
--- a/pkg/kernel/lib/text/serializer_combinators.dart
+++ b/pkg/kernel/lib/text/serializer_combinators.dart
@@ -9,11 +9,71 @@
import '../ast.dart' show Node;
import 'text_serializer.dart' show Tagger;
+class DeserializationEnvironment<T extends Node> {
+ final Map<String, T> locals = <String, T>{};
+
+ final DeserializationEnvironment<T> parent;
+
+ final Set<String> usedNames = new Set<String>();
+
+ DeserializationEnvironment(this.parent) {
+ if (parent != null) {
+ usedNames.addAll(parent.usedNames);
+ }
+ }
+
+ T lookup(String name) => locals[name] ?? parent?.lookup(name);
+
+ T add(String name, T node) {
+ if (usedNames.contains(name)) {
+ throw StateError("name '$name' is already declared in this scope");
+ }
+ usedNames.add(name);
+ return locals[name] = node;
+ }
+}
+
+class SerializationEnvironment<T extends Node> {
+ final Map<T, String> locals = new Map<T, String>.identity();
+
+ int nameCount;
+
+ final SerializationEnvironment<T> parent;
+
+ static const String separator = "^";
+
+ static final int codeOfZero = "0".codeUnitAt(0);
+
+ static final int codeOfNine = "9".codeUnitAt(0);
+
+ SerializationEnvironment(this.parent) {
+ nameCount = (parent?.nameCount ?? 0);
+ }
+
+ String lookup(T node) => locals[node] ?? parent?.lookup(node);
+
+ String add(T node, String name) {
+ int prefixLength = name.length - 1;
+ bool isOnlyDigits = true;
+ while (prefixLength >= 0 && name[prefixLength] != separator) {
+ int code = name.codeUnitAt(prefixLength);
+ isOnlyDigits = isOnlyDigits && (codeOfZero <= code && code <= codeOfNine);
+ --prefixLength;
+ }
+ if (prefixLength < 0 || !isOnlyDigits) {
+ prefixLength = name.length;
+ }
+ String prefix = name.substring(0, prefixLength);
+ return locals[node] = "$prefix$separator${nameCount++}";
+ }
+}
+
abstract class TextSerializer<T> {
const TextSerializer();
- T readFrom(Iterator<Object> stream);
- void writeTo(StringBuffer buffer, T object);
+ T readFrom(Iterator<Object> stream, DeserializationEnvironment environment);
+ void writeTo(
+ StringBuffer buffer, T object, SerializationEnvironment environment);
/// True if this serializer/deserializer writes/reads nothing. This is true
/// for the serializer [Nothing] and also some serializers derived from it.
@@ -23,9 +83,9 @@
class Nothing extends TextSerializer<void> {
const Nothing();
- void readFrom(Iterator<Object> stream) {}
+ void readFrom(Iterator<Object> stream, DeserializationEnvironment _) {}
- void writeTo(StringBuffer buffer, void ignored) {}
+ void writeTo(StringBuffer buffer, void ignored, SerializationEnvironment _) {}
bool get isEmpty => true;
}
@@ -33,7 +93,7 @@
class DartString extends TextSerializer<String> {
const DartString();
- String readFrom(Iterator<Object> stream) {
+ String readFrom(Iterator<Object> stream, DeserializationEnvironment _) {
if (stream.current is! String) {
throw StateError("expected an atom, found a list");
}
@@ -42,7 +102,7 @@
return result;
}
- void writeTo(StringBuffer buffer, String object) {
+ void writeTo(StringBuffer buffer, String object, SerializationEnvironment _) {
buffer.write(json.encode(object));
}
}
@@ -50,7 +110,7 @@
class DartInt extends TextSerializer<int> {
const DartInt();
- int readFrom(Iterator<Object> stream) {
+ int readFrom(Iterator<Object> stream, DeserializationEnvironment _) {
if (stream.current is! String) {
throw StateError("expected an atom, found a list");
}
@@ -59,7 +119,7 @@
return result;
}
- void writeTo(StringBuffer buffer, int object) {
+ void writeTo(StringBuffer buffer, int object, SerializationEnvironment _) {
buffer.write(object);
}
}
@@ -67,7 +127,7 @@
class DartDouble extends TextSerializer<double> {
const DartDouble();
- double readFrom(Iterator<Object> stream) {
+ double readFrom(Iterator<Object> stream, DeserializationEnvironment _) {
if (stream.current is! String) {
throw StateError("expected an atom, found a list");
}
@@ -76,7 +136,7 @@
return result;
}
- void writeTo(StringBuffer buffer, double object) {
+ void writeTo(StringBuffer buffer, double object, SerializationEnvironment _) {
buffer.write(object);
}
}
@@ -84,7 +144,7 @@
class DartBool extends TextSerializer<bool> {
const DartBool();
- bool readFrom(Iterator<Object> stream) {
+ bool readFrom(Iterator<Object> stream, DeserializationEnvironment _) {
if (stream.current is! String) {
throw StateError("expected an atom, found a list");
}
@@ -100,7 +160,7 @@
return result;
}
- void writeTo(StringBuffer buffer, bool object) {
+ void writeTo(StringBuffer buffer, bool object, SerializationEnvironment _) {
buffer.write(object ? 'true' : 'false');
}
}
@@ -121,7 +181,7 @@
: tags = [],
serializers = [];
- T readFrom(Iterator<Object> stream) {
+ T readFrom(Iterator<Object> stream, DeserializationEnvironment environment) {
if (stream.current is! Iterator) {
throw StateError("expected list, found atom");
}
@@ -134,7 +194,7 @@
for (int i = 0; i < tags.length; ++i) {
if (tags[i] == tag) {
nested.moveNext();
- T result = serializers[i].readFrom(nested);
+ T result = serializers[i].readFrom(nested, environment);
if (nested.moveNext()) {
throw StateError("extra cruft in tagged '${tag}'");
}
@@ -145,7 +205,8 @@
throw StateError("unrecognized tag '${tag}'");
}
- void writeTo(StringBuffer buffer, T object) {
+ void writeTo(
+ StringBuffer buffer, T object, SerializationEnvironment environment) {
String tag = tagger.tag(object);
for (int i = 0; i < tags.length; ++i) {
if (tags[i] == tag) {
@@ -153,7 +214,7 @@
if (!serializers[i].isEmpty) {
buffer.write(" ");
}
- serializers[i].writeTo(buffer, object);
+ serializers[i].writeTo(buffer, object, environment);
buffer.write(")");
return;
}
@@ -171,17 +232,33 @@
Wrapped(this.unwrap, this.wrap, this.contents);
- K readFrom(Iterator<Object> stream) {
- return wrap(contents.readFrom(stream));
+ K readFrom(Iterator<Object> stream, DeserializationEnvironment environment) {
+ return wrap(contents.readFrom(stream, environment));
}
- void writeTo(StringBuffer buffer, K object) {
- contents.writeTo(buffer, unwrap(object));
+ void writeTo(
+ StringBuffer buffer, K object, SerializationEnvironment environment) {
+ contents.writeTo(buffer, unwrap(object), environment);
}
bool get isEmpty => contents.isEmpty;
}
+class ScopedReference<T extends Node> extends TextSerializer<T> {
+ final DartString stringSerializer = const DartString();
+
+ const ScopedReference();
+
+ T readFrom(Iterator<Object> stream, DeserializationEnvironment environment) {
+ return environment.lookup(stringSerializer.readFrom(stream, null));
+ }
+
+ void writeTo(
+ StringBuffer buffer, T object, SerializationEnvironment environment) {
+ stringSerializer.writeTo(buffer, environment.lookup(object), null);
+ }
+}
+
// A serializer/deserializer for pairs.
class Tuple2Serializer<T1, T2> extends TextSerializer<Tuple2<T1, T2>> {
final TextSerializer<T1> first;
@@ -189,14 +266,17 @@
const Tuple2Serializer(this.first, this.second);
- Tuple2<T1, T2> readFrom(Iterator<Object> stream) {
- return new Tuple2(first.readFrom(stream), second.readFrom(stream));
+ Tuple2<T1, T2> readFrom(
+ Iterator<Object> stream, DeserializationEnvironment environment) {
+ return new Tuple2(first.readFrom(stream, environment),
+ second.readFrom(stream, environment));
}
- void writeTo(StringBuffer buffer, Tuple2<T1, T2> object) {
- first.writeTo(buffer, object.first);
+ void writeTo(StringBuffer buffer, Tuple2<T1, T2> object,
+ SerializationEnvironment environment) {
+ first.writeTo(buffer, object.first, environment);
buffer.write(' ');
- second.writeTo(buffer, object.second);
+ second.writeTo(buffer, object.second, environment);
}
}
@@ -214,17 +294,21 @@
const Tuple3Serializer(this.first, this.second, this.third);
- Tuple3<T1, T2, T3> readFrom(Iterator<Object> stream) {
- return new Tuple3(first.readFrom(stream), second.readFrom(stream),
- third.readFrom(stream));
+ Tuple3<T1, T2, T3> readFrom(
+ Iterator<Object> stream, DeserializationEnvironment environment) {
+ return new Tuple3(
+ first.readFrom(stream, environment),
+ second.readFrom(stream, environment),
+ third.readFrom(stream, environment));
}
- void writeTo(StringBuffer buffer, Tuple3<T1, T2, T3> object) {
- first.writeTo(buffer, object.first);
+ void writeTo(StringBuffer buffer, Tuple3<T1, T2, T3> object,
+ SerializationEnvironment environment) {
+ first.writeTo(buffer, object.first, environment);
buffer.write(' ');
- second.writeTo(buffer, object.second);
+ second.writeTo(buffer, object.second, environment);
buffer.write(' ');
- third.writeTo(buffer, object.third);
+ third.writeTo(buffer, object.third, environment);
}
}
@@ -245,19 +329,24 @@
const Tuple4Serializer(this.first, this.second, this.third, this.fourth);
- Tuple4<T1, T2, T3, T4> readFrom(Iterator<Object> stream) {
- return new Tuple4(first.readFrom(stream), second.readFrom(stream),
- third.readFrom(stream), fourth.readFrom(stream));
+ Tuple4<T1, T2, T3, T4> readFrom(
+ Iterator<Object> stream, DeserializationEnvironment environment) {
+ return new Tuple4(
+ first.readFrom(stream, environment),
+ second.readFrom(stream, environment),
+ third.readFrom(stream, environment),
+ fourth.readFrom(stream, environment));
}
- void writeTo(StringBuffer buffer, Tuple4<T1, T2, T3, T4> object) {
- first.writeTo(buffer, object.first);
+ void writeTo(StringBuffer buffer, Tuple4<T1, T2, T3, T4> object,
+ SerializationEnvironment environment) {
+ first.writeTo(buffer, object.first, environment);
buffer.write(' ');
- second.writeTo(buffer, object.second);
+ second.writeTo(buffer, object.second, environment);
buffer.write(' ');
- third.writeTo(buffer, object.third);
+ third.writeTo(buffer, object.third, environment);
buffer.write(' ');
- fourth.writeTo(buffer, object.fourth);
+ fourth.writeTo(buffer, object.fourth, environment);
}
}
@@ -276,7 +365,8 @@
const ListSerializer(this.elements);
- List<T> readFrom(Iterator<Object> stream) {
+ List<T> readFrom(
+ Iterator<Object> stream, DeserializationEnvironment environment) {
if (stream.current is! Iterator) {
throw StateError("expected a list, found an atom");
}
@@ -284,17 +374,18 @@
list.moveNext();
List<T> result = [];
while (list.current != null) {
- result.add(elements.readFrom(list));
+ result.add(elements.readFrom(list, environment));
}
stream.moveNext();
return result;
}
- void writeTo(StringBuffer buffer, List<T> object) {
+ void writeTo(StringBuffer buffer, List<T> object,
+ SerializationEnvironment environment) {
buffer.write('(');
for (int i = 0; i < object.length; ++i) {
if (i != 0) buffer.write(' ');
- elements.writeTo(buffer, object[i]);
+ elements.writeTo(buffer, object[i], environment);
}
buffer.write(')');
}
@@ -305,19 +396,20 @@
const Optional(this.contents);
- T readFrom(Iterator<Object> stream) {
+ T readFrom(Iterator<Object> stream, DeserializationEnvironment environment) {
if (stream.current == '_') {
stream.moveNext();
return null;
}
- return contents.readFrom(stream);
+ return contents.readFrom(stream, environment);
}
- void writeTo(StringBuffer buffer, T object) {
+ void writeTo(
+ StringBuffer buffer, T object, SerializationEnvironment environment) {
if (object == null) {
buffer.write('_');
} else {
- contents.writeTo(buffer, object);
+ contents.writeTo(buffer, object, environment);
}
}
}
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index 9ab7e77..644f15a 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -80,7 +80,7 @@
stream.moveNext();
T result;
try {
- result = serializer.readFrom(stream);
+ result = serializer.readFrom(stream, null);
} catch (exception) {
failures.add(
new TextDeserializationFailure(exception.toString(), uri, offset));
@@ -96,7 +96,7 @@
T node, TextSerializer<T> serializer, Uri uri, int offset) {
StringBuffer buffer = new StringBuffer();
try {
- serializer.writeTo(buffer, node);
+ serializer.writeTo(buffer, node, null);
} catch (exception) {
failures
.add(new TextSerializationFailure(exception.toString(), uri, offset));
@@ -217,28 +217,16 @@
@override
void visitRedirectingFactoryConstructorReference(
- RedirectingFactoryConstructor node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
+ RedirectingFactoryConstructor node) {}
@override
- void visitProcedureReference(Procedure node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
+ void visitProcedureReference(Procedure node) {}
@override
- void visitConstructorReference(Constructor node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
+ void visitConstructorReference(Constructor node) {}
@override
- void visitFieldReference(Field node) {
- storeLastSeenUriAndOffset(node);
- node.visitChildren(this);
- }
+ void visitFieldReference(Field node) {}
@override
void visitTypeLiteralConstantReference(TypeLiteralConstant node) {
@@ -314,18 +302,36 @@
}
@override
- void visitTypedefReference(Typedef node) {
+ void visitEnvironmentBoolConstantReference(EnvironmentBoolConstant node) {
storeLastSeenUriAndOffset(node);
node.visitChildren(this);
}
@override
- void visitClassReference(Class node) {
+ void visitEnvironmentIntConstantReference(EnvironmentIntConstant node) {
storeLastSeenUriAndOffset(node);
node.visitChildren(this);
}
@override
+ void visitEnvironmentStringConstantReference(EnvironmentStringConstant node) {
+ storeLastSeenUriAndOffset(node);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitUnevaluatedConstantReference(UnevaluatedConstant node) {
+ storeLastSeenUriAndOffset(node);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitTypedefReference(Typedef node) {}
+
+ @override
+ void visitClassReference(Class node) {}
+
+ @override
void visitTypeLiteralConstant(TypeLiteralConstant node) {
storeLastSeenUriAndOffset(node);
node.visitChildren(this);
@@ -398,6 +404,30 @@
}
@override
+ void visitEnvironmentBoolConstant(EnvironmentBoolConstant node) {
+ storeLastSeenUriAndOffset(node);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitEnvironmentIntConstant(EnvironmentIntConstant node) {
+ storeLastSeenUriAndOffset(node);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitEnvironmentStringConstant(EnvironmentStringConstant node) {
+ storeLastSeenUriAndOffset(node);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitUnevaluatedConstant(UnevaluatedConstant node) {
+ storeLastSeenUriAndOffset(node);
+ node.visitChildren(this);
+ }
+
+ @override
void visitTypedefType(TypedefType node) {
storeLastSeenUriAndOffset(node);
makeDartTypeRoundTrip(node);
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 2848583..06799f1 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -88,6 +88,16 @@
}
String visitLet(Let _) => "let";
+
+ String visitPropertyGet(PropertyGet _) => "get-prop";
+ String visitPropertySet(PropertySet _) => "set-prop";
+ String visitSuperPropertyGet(SuperPropertyGet _) => "get-super";
+ String visitSuperPropertySet(SuperPropertySet _) => "set-super";
+ String visitMethodInvocation(MethodInvocation _) => "invoke-method";
+ String visitSuperMethodInvocation(SuperMethodInvocation _) => "invoke-super";
+
+ String visitVariableGet(VariableGet _) => "get-var";
+ String visitVariableSet(VariableSet _) => "set-var";
}
TextSerializer<InvalidExpression> invalidExpressionSerializer = new Wrapped(
@@ -361,20 +371,180 @@
keyType: tuple.first, valueType: tuple.second, isConst: true);
}
-TextSerializer<Let> letSerializer = new Wrapped(unwrapLet, wrapLet,
- new Tuple2Serializer(variableDeclarationSerializer, expressionSerializer));
+class LetSerializer extends TextSerializer<Let> {
+ const LetSerializer();
-Tuple2<VariableDeclaration, Expression> unwrapLet(Let expression) {
- return new Tuple2(expression.variable, expression.body);
+ Let readFrom(
+ Iterator<Object> stream, DeserializationEnvironment environment) {
+ VariableDeclaration variable =
+ variableDeclarationSerializer.readFrom(stream, environment);
+ Expression body = expressionSerializer.readFrom(
+ stream,
+ new DeserializationEnvironment(environment)
+ ..add(variable.name, variable));
+ return new Let(variable, body);
+ }
+
+ void writeTo(
+ StringBuffer buffer, Let object, SerializationEnvironment environment) {
+ SerializationEnvironment bodyScope =
+ new SerializationEnvironment(environment);
+ VariableDeclaration variable = object.variable;
+ String oldVariableName = variable.name;
+ String newVariableName = bodyScope.add(variable, oldVariableName);
+ variableDeclarationSerializer.writeTo(
+ buffer, variable..name = newVariableName, environment);
+ variable.name = oldVariableName;
+ buffer.write(' ');
+ expressionSerializer.writeTo(buffer, object.body, bodyScope);
+ }
}
-Let wrapLet(Tuple2<VariableDeclaration, Expression> tuple) {
- return new Let(tuple.first, tuple.second);
+TextSerializer<Let> letSerializer = const LetSerializer();
+
+TextSerializer<PropertyGet> propertyGetSerializer = new Wrapped(
+ unwrapPropertyGet,
+ wrapPropertyGet,
+ new Tuple2Serializer(expressionSerializer, nameSerializer));
+
+Tuple2<Expression, Name> unwrapPropertyGet(PropertyGet expression) {
+ return new Tuple2(expression.receiver, expression.name);
+}
+
+PropertyGet wrapPropertyGet(Tuple2<Expression, Name> tuple) {
+ return new PropertyGet(tuple.first, tuple.second);
+}
+
+TextSerializer<PropertySet> propertySetSerializer = new Wrapped(
+ unwrapPropertySet,
+ wrapPropertySet,
+ new Tuple3Serializer(
+ expressionSerializer, nameSerializer, expressionSerializer));
+
+Tuple3<Expression, Name, Expression> unwrapPropertySet(PropertySet expression) {
+ return new Tuple3(expression.receiver, expression.name, expression.value);
+}
+
+PropertySet wrapPropertySet(Tuple3<Expression, Name, Expression> tuple) {
+ return new PropertySet(tuple.first, tuple.second, tuple.third);
+}
+
+TextSerializer<SuperPropertyGet> superPropertyGetSerializer =
+ new Wrapped(unwrapSuperPropertyGet, wrapSuperPropertyGet, nameSerializer);
+
+Name unwrapSuperPropertyGet(SuperPropertyGet expression) {
+ return expression.name;
+}
+
+SuperPropertyGet wrapSuperPropertyGet(Name name) {
+ return new SuperPropertyGet(name);
+}
+
+TextSerializer<SuperPropertySet> superPropertySetSerializer = new Wrapped(
+ unwrapSuperPropertySet,
+ wrapSuperPropertySet,
+ new Tuple2Serializer(nameSerializer, expressionSerializer));
+
+Tuple2<Name, Expression> unwrapSuperPropertySet(SuperPropertySet expression) {
+ return new Tuple2(expression.name, expression.value);
+}
+
+SuperPropertySet wrapSuperPropertySet(Tuple2<Name, Expression> tuple) {
+ return new SuperPropertySet(tuple.first, tuple.second, null);
+}
+
+TextSerializer<MethodInvocation> methodInvocationSerializer = new Wrapped(
+ unwrapMethodInvocation,
+ wrapMethodInvocation,
+ new Tuple3Serializer(
+ expressionSerializer, nameSerializer, argumentsSerializer));
+
+Tuple3<Expression, Name, Arguments> unwrapMethodInvocation(
+ MethodInvocation expression) {
+ return new Tuple3(expression.receiver, expression.name, expression.arguments);
+}
+
+MethodInvocation wrapMethodInvocation(
+ Tuple3<Expression, Name, Arguments> tuple) {
+ return new MethodInvocation(tuple.first, tuple.second, tuple.third);
+}
+
+TextSerializer<SuperMethodInvocation> superMethodInvocationSerializer =
+ new Wrapped(unwrapSuperMethodInvocation, wrapSuperMethodInvocation,
+ new Tuple2Serializer(nameSerializer, argumentsSerializer));
+
+Tuple2<Name, Arguments> unwrapSuperMethodInvocation(
+ SuperMethodInvocation expression) {
+ return new Tuple2(expression.name, expression.arguments);
+}
+
+SuperMethodInvocation wrapSuperMethodInvocation(Tuple2<Name, Arguments> tuple) {
+ return new SuperMethodInvocation(tuple.first, tuple.second);
+}
+
+TextSerializer<VariableGet> variableGetSerializer = new Wrapped(
+ unwrapVariableGet,
+ wrapVariableGet,
+ new Tuple2Serializer(const ScopedReference<VariableDeclaration>(),
+ new Optional(dartTypeSerializer)));
+
+Tuple2<VariableDeclaration, DartType> unwrapVariableGet(VariableGet node) {
+ return new Tuple2<VariableDeclaration, DartType>(
+ node.variable, node.promotedType);
+}
+
+VariableGet wrapVariableGet(Tuple2<VariableDeclaration, DartType> tuple) {
+ return new VariableGet(tuple.first, tuple.second);
+}
+
+TextSerializer<VariableSet> variableSetSerializer = new Wrapped(
+ unwrapVariableSet,
+ wrapVariableSet,
+ new Tuple2Serializer(
+ const ScopedReference<VariableDeclaration>(), expressionSerializer));
+
+Tuple2<VariableDeclaration, Expression> unwrapVariableSet(VariableSet node) {
+ return new Tuple2<VariableDeclaration, Expression>(node.variable, node.value);
+}
+
+VariableSet wrapVariableSet(Tuple2<VariableDeclaration, Expression> tuple) {
+ return new VariableSet(tuple.first, tuple.second);
}
Case<Expression> expressionSerializer =
new Case.uninitialized(const ExpressionTagger());
+TextSerializer<NamedExpression> namedExpressionSerializer = new Wrapped(
+ unwrapNamedExpression,
+ wrapNamedExpression,
+ new Tuple2Serializer(const DartString(), expressionSerializer));
+
+Tuple2<String, Expression> unwrapNamedExpression(NamedExpression expression) {
+ return new Tuple2(expression.name, expression.value);
+}
+
+NamedExpression wrapNamedExpression(Tuple2<String, Expression> tuple) {
+ return new NamedExpression(tuple.first, tuple.second);
+}
+
+TextSerializer<Arguments> argumentsSerializer = new Wrapped(
+ unwrapArguments,
+ wrapArguments,
+ Tuple3Serializer(
+ new ListSerializer(dartTypeSerializer),
+ new ListSerializer(expressionSerializer),
+ new ListSerializer(namedExpressionSerializer)));
+
+Tuple3<List<DartType>, List<Expression>, List<NamedExpression>> unwrapArguments(
+ Arguments arguments) {
+ return new Tuple3(arguments.types, arguments.positional, arguments.named);
+}
+
+Arguments wrapArguments(
+ Tuple3<List<DartType>, List<Expression>, List<NamedExpression>> tuple) {
+ return new Arguments(tuple.second, types: tuple.first, named: tuple.third);
+}
+
class VariableDeclarationTagger implements Tagger<VariableDeclaration> {
const VariableDeclarationTagger();
@@ -539,6 +709,14 @@
"map",
"const-map",
"let",
+ "get-prop",
+ "set-prop",
+ "get-super",
+ "set-super",
+ "invoke-method",
+ "invoke-super",
+ "get-var",
+ "set-var",
]);
expressionSerializer.serializers.addAll([
stringLiteralSerializer,
@@ -567,6 +745,14 @@
mapLiteralSerializer,
constMapLiteralSerializer,
letSerializer,
+ propertyGetSerializer,
+ propertySetSerializer,
+ superPropertyGetSerializer,
+ superPropertySetSerializer,
+ methodInvocationSerializer,
+ superMethodInvocationSerializer,
+ variableGetSerializer,
+ variableSetSerializer,
]);
dartTypeSerializer.tags.addAll([
"invalid",
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index 4b1208c..17bd047 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -28,37 +28,40 @@
import '../type_algebra.dart';
import '../type_environment.dart';
-Component transformComponent(Component component, ConstantsBackend backend,
+Component transformComponent(
+ Component component, ConstantsBackend backend, ErrorReporter errorReporter,
{bool keepFields: false,
bool legacyMode: false,
bool enableAsserts: false,
bool evaluateAnnotations: true,
CoreTypes coreTypes,
- ClassHierarchy hierarchy,
- ErrorReporter errorReporter: const _SimpleErrorReporter()}) {
+ ClassHierarchy hierarchy}) {
coreTypes ??= new CoreTypes(component);
hierarchy ??= new ClassHierarchy(component);
final typeEnvironment =
new TypeEnvironment(coreTypes, hierarchy, legacyMode: legacyMode);
- transformLibraries(component.libraries, backend, coreTypes, typeEnvironment,
+ transformLibraries(
+ component.libraries, backend, coreTypes, typeEnvironment, errorReporter,
keepFields: keepFields,
legacyMode: legacyMode,
enableAsserts: enableAsserts,
- evaluateAnnotations: evaluateAnnotations,
- errorReporter: errorReporter);
+ evaluateAnnotations: evaluateAnnotations);
return component;
}
-void transformLibraries(List<Library> libraries, ConstantsBackend backend,
- CoreTypes coreTypes, TypeEnvironment typeEnvironment,
+void transformLibraries(
+ List<Library> libraries,
+ ConstantsBackend backend,
+ CoreTypes coreTypes,
+ TypeEnvironment typeEnvironment,
+ ErrorReporter errorReporter,
{bool keepFields: false,
bool legacyMode: false,
bool keepVariables: false,
bool evaluateAnnotations: true,
- bool enableAsserts: false,
- ErrorReporter errorReporter: const _SimpleErrorReporter()}) {
+ bool enableAsserts: false}) {
final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
backend,
keepFields,
@@ -95,8 +98,8 @@
ErrorReporter errorReporter,
{bool legacyMode: false})
: constantEvaluator = new ConstantEvaluator(
- backend, typeEnvironment, coreTypes, enableAsserts,
- legacyMode: legacyMode, errorReporter: errorReporter);
+ backend, typeEnvironment, coreTypes, enableAsserts, errorReporter,
+ legacyMode: legacyMode);
// Transform the library/class members:
@@ -235,32 +238,32 @@
visitVariableDeclaration(VariableDeclaration node) {
transformAnnotations(node.annotations, node);
- if (node.isConst) {
- final Constant constant = tryEvaluateWithContext(node, node.initializer);
-
- // If there was a constant evaluation error we will not continue and
- // simply keep the old [node].
- if (constant == null) {
- return node;
- }
-
- constantEvaluator.env.addVariableValue(node, constant);
-
- if (keepVariables) {
- // So the value of the variable is still available for debugging
- // purposes we convert the constant variable to be a final variable
- // initialized to the evaluated constant expression.
- node.initializer = new ConstantExpression(constant)..parent = node;
- node.isFinal = true;
- node.isConst = false;
- } else {
- // Since we convert all use-sites of constants, the constant
- // [VariableDeclaration] is unused and we'll therefore remove it.
- return null;
- }
- }
if (node.initializer != null) {
- node.initializer = node.initializer.accept(this)..parent = node;
+ if (node.isConst) {
+ final Constant constant =
+ tryEvaluateWithContext(node, node.initializer);
+
+ // If there was a constant evaluation error we will not continue and
+ // simply keep the old [node].
+ if (constant != null) {
+ constantEvaluator.env.addVariableValue(node, constant);
+
+ if (keepVariables) {
+ // So the value of the variable is still available for debugging
+ // purposes we convert the constant variable to be a final variable
+ // initialized to the evaluated constant expression.
+ node.initializer = new ConstantExpression(constant)..parent = node;
+ node.isFinal = true;
+ node.isConst = false;
+ } else {
+ // Since we convert all use-sites of constants, the constant
+ // [VariableDeclaration] is unused and we'll therefore remove it.
+ return null;
+ }
+ }
+ } else {
+ node.initializer = node.initializer.accept(this)..parent = node;
+ }
}
return node;
}
@@ -388,10 +391,9 @@
InstanceBuilder instanceBuilder;
EvaluationEnvironment env;
- ConstantEvaluator(
- this.backend, this.typeEnvironment, this.coreTypes, this.enableAsserts,
- {this.legacyMode: false,
- this.errorReporter = const _SimpleErrorReporter()})
+ ConstantEvaluator(this.backend, this.typeEnvironment, this.coreTypes,
+ this.enableAsserts, this.errorReporter,
+ {this.legacyMode: false})
: canonicalizationCache = <Constant, Constant>{},
nodeCache = <Node, Constant>{};
@@ -817,6 +819,11 @@
});
}
+ visitInvalidExpression(InvalidExpression node) {
+ // Invalid expressions are always distinct, we do not canonicalize them.
+ return new UnevaluatedConstant(node);
+ }
+
visitMethodInvocation(MethodInvocation node) {
// We have no support for generic method invocation atm.
assert(node.arguments.named.isEmpty);
@@ -1472,54 +1479,64 @@
abstract class ErrorReporter {
const ErrorReporter();
- freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type);
- invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
- DartType expectedType);
- invalidBinaryOperandType(List<TreeNode> context, TreeNode node,
- Constant receiver, String op, DartType expectedType, DartType actualType);
- invalidMethodInvocation(
- List<TreeNode> context, TreeNode node, Constant receiver, String op);
- invalidStaticInvocation(
- List<TreeNode> context, TreeNode node, Procedure target);
- invalidStringInterpolationOperand(
- List<TreeNode> context, TreeNode node, Constant constant);
- invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant);
- zeroDivisor(
- List<TreeNode> context, TreeNode node, IntConstant receiver, String op);
- negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
- String op, IntConstant argument);
- nonConstLiteral(List<TreeNode> context, TreeNode node, String klass);
- duplicateKey(List<TreeNode> context, TreeNode node, Constant key);
- failedAssertion(List<TreeNode> context, TreeNode node, String message);
- nonConstantVariableGet(
- List<TreeNode> context, TreeNode node, String variableName);
- deferredLibrary(List<TreeNode> context, TreeNode node, String importName);
-}
-
-abstract class ErrorReporterBase implements ErrorReporter {
- const ErrorReporterBase();
-
- report(List<TreeNode> context, String message, TreeNode node);
-
- getFileUri(TreeNode node) {
+ Uri getFileUri(TreeNode node) {
while (node is! FileUriNode) {
node = node.parent;
}
return (node as FileUriNode).fileUri;
}
- getFileOffset(TreeNode node) {
+ int getFileOffset(TreeNode node) {
while (node.fileOffset == TreeNode.noOffset) {
node = node.parent;
}
return node == null ? TreeNode.noOffset : node.fileOffset;
}
- freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
+ void freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type);
+ void invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
+ DartType expectedType);
+ void invalidBinaryOperandType(List<TreeNode> context, TreeNode node,
+ Constant receiver, String op, DartType expectedType, DartType actualType);
+ void invalidMethodInvocation(
+ List<TreeNode> context, TreeNode node, Constant receiver, String op);
+ void invalidStaticInvocation(
+ List<TreeNode> context, TreeNode node, Procedure target);
+ void invalidStringInterpolationOperand(
+ List<TreeNode> context, TreeNode node, Constant constant);
+ void invalidSymbolName(
+ List<TreeNode> context, TreeNode node, Constant constant);
+ void zeroDivisor(
+ List<TreeNode> context, TreeNode node, IntConstant receiver, String op);
+ void negativeShift(List<TreeNode> context, TreeNode node,
+ IntConstant receiver, String op, IntConstant argument);
+ void nonConstLiteral(List<TreeNode> context, TreeNode node, String klass);
+ void duplicateKey(List<TreeNode> context, TreeNode node, Constant key);
+ void failedAssertion(List<TreeNode> context, TreeNode node, String message);
+ void nonConstantVariableGet(
+ List<TreeNode> context, TreeNode node, String variableName);
+ void deferredLibrary(
+ List<TreeNode> context, TreeNode node, String importName);
+}
+
+class SimpleErrorReporter extends ErrorReporter {
+ const SimpleErrorReporter();
+
+ void report(List<TreeNode> context, String message, TreeNode node) {
+ io.exitCode = 42;
+ final Uri uri = getFileUri(node);
+ final int fileOffset = getFileOffset(node);
+
+ io.stderr.writeln('$uri:$fileOffset Constant evaluation error: $message');
+ }
+
+ @override
+ void freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
report(context, 'Expected type to be instantiated but was ${type}', node);
}
- invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
+ @override
+ void invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
DartType expectedType) {
report(
context,
@@ -1527,7 +1544,8 @@
node);
}
- invalidBinaryOperandType(
+ @override
+ void invalidBinaryOperandType(
List<TreeNode> context,
TreeNode node,
Constant receiver,
@@ -1541,19 +1559,22 @@
node);
}
- invalidMethodInvocation(
+ @override
+ void invalidMethodInvocation(
List<TreeNode> context, TreeNode node, Constant receiver, String op) {
report(context, 'Cannot call "$op" on "$receiver" in constant expression',
node);
}
- invalidStaticInvocation(
+ @override
+ void invalidStaticInvocation(
List<TreeNode> context, TreeNode node, Procedure target) {
report(
context, 'Cannot invoke "$target" inside a constant expression', node);
}
- invalidStringInterpolationOperand(
+ @override
+ void invalidStringInterpolationOperand(
List<TreeNode> context, TreeNode node, Constant constant) {
report(
context,
@@ -1562,7 +1583,9 @@
node);
}
- invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant) {
+ @override
+ void invalidSymbolName(
+ List<TreeNode> context, TreeNode node, Constant constant) {
report(
context,
'The symbol name must be a valid public Dart member name, public '
@@ -1570,7 +1593,8 @@
node);
}
- zeroDivisor(
+ @override
+ void zeroDivisor(
List<TreeNode> context, TreeNode node, IntConstant receiver, String op) {
report(
context,
@@ -1579,8 +1603,9 @@
node);
}
- negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
- String op, IntConstant argument) {
+ @override
+ void negativeShift(List<TreeNode> context, TreeNode node,
+ IntConstant receiver, String op, IntConstant argument) {
report(
context,
"Binary operator '$op' on '${receiver.value}' requires non-negative "
@@ -1588,28 +1613,32 @@
node);
}
- nonConstLiteral(List<TreeNode> context, TreeNode node, String klass) {
+ @override
+ void nonConstLiteral(List<TreeNode> context, TreeNode node, String klass) {
report(
context,
'Cannot have a non-constant $klass literal within a const context.',
node);
}
- duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
+ @override
+ void duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
report(
context,
'Duplicate keys are not allowed in constant maps (found duplicate key "$key")',
node);
}
- failedAssertion(List<TreeNode> context, TreeNode node, String message) {
+ @override
+ void failedAssertion(List<TreeNode> context, TreeNode node, String message) {
report(
context,
'The assertion condition evaluated to "false" with message "$message"',
node);
}
- nonConstantVariableGet(
+ @override
+ void nonConstantVariableGet(
List<TreeNode> context, TreeNode node, String variableName) {
report(
context,
@@ -1618,7 +1647,9 @@
node);
}
- deferredLibrary(List<TreeNode> context, TreeNode node, String importName) {
+ @override
+ void deferredLibrary(
+ List<TreeNode> context, TreeNode node, String importName) {
report(
context,
'Deferred "$importName" cannot be used inside a constant '
@@ -1627,18 +1658,6 @@
}
}
-class _SimpleErrorReporter extends ErrorReporterBase {
- const _SimpleErrorReporter();
-
- report(List<TreeNode> context, String message, TreeNode node) {
- io.exitCode = 42;
- final Uri uri = getFileUri(node);
- final int fileOffset = getFileOffset(node);
-
- io.stderr.writeln('$uri:$fileOffset Constant evaluation error: $message');
- }
-}
-
class IsInstantiatedVisitor extends DartTypeVisitor<bool> {
final _availableVariables = new Set<TypeParameter>();
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 8fa6ea8..11503d0 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -34,7 +34,7 @@
});
}
}
- var visitor = new TypeCheckingVisitor(this, environment);
+ var visitor = new TypeCheckingVisitor(this, environment, hierarchy);
for (var library in component.libraries) {
if (ignoreSdk && library.importUri.scheme == 'dart') continue;
for (var class_ in library.classes) {
@@ -116,12 +116,12 @@
InitializerVisitor<Null> {
final TypeChecker checker;
final TypeEnvironment environment;
+ final ClassHierarchy hierarchy;
CoreTypes get coreTypes => environment.coreTypes;
- ClassHierarchy get hierarchy => environment.hierarchy;
Class get currentClass => environment.thisType.classNode;
- TypeCheckingVisitor(this.checker, this.environment);
+ TypeCheckingVisitor(this.checker, this.environment, this.hierarchy);
void checkAssignable(TreeNode where, DartType from, DartType to) {
checker.checkAssignable(where, from, to);
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index d0603b8..b532e87 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -8,11 +8,13 @@
import 'core_types.dart';
import 'type_algebra.dart';
+import 'src/hierarchy_based_type_environment.dart'
+ show HierarchyBasedTypeEnvironment;
+
typedef void ErrorHandler(TreeNode node, String message);
-class TypeEnvironment extends SubtypeTester {
+abstract class TypeEnvironment extends SubtypeTester {
final CoreTypes coreTypes;
- final ClassHierarchy hierarchy;
@override
final bool legacyMode;
@@ -27,7 +29,13 @@
/// be tolerated. See [typeError].
ErrorHandler errorHandler;
- TypeEnvironment(this.coreTypes, this.hierarchy, {this.legacyMode: false});
+ TypeEnvironment.fromSubclass(this.coreTypes, {this.legacyMode: false});
+
+ factory TypeEnvironment(CoreTypes coreTypes, ClassHierarchy hierarchy,
+ {bool legacyMode: false}) {
+ return new HierarchyBasedTypeEnvironment(coreTypes, hierarchy,
+ legacyMode: legacyMode);
+ }
InterfaceType get objectType => coreTypes.objectClass.rawType;
InterfaceType get nullType => coreTypes.nullClass.rawType;
@@ -82,8 +90,7 @@
// we aren't concerned with it. If a class implements multiple
// instantiations of Future, getTypeAsInstanceOf is responsible for
// picking the least one in the sense required by the spec.
- InterfaceType future =
- hierarchy.getTypeAsInstanceOf(type, coreTypes.futureClass);
+ InterfaceType future = getTypeAsInstanceOf(type, coreTypes.futureClass);
if (future != null) {
return future.typeArguments[0];
}
@@ -143,21 +150,6 @@
if (type1 == doubleType || type2 == doubleType) return doubleType;
return numType;
}
-
- /// Returns true if [class_] has no proper subtypes that are usable as type
- /// argument.
- bool isSealedClass(Class class_) {
- // The sealed core classes have subtypes in the patched SDK, but those
- // classes cannot occur as type argument.
- if (class_ == coreTypes.intClass ||
- class_ == coreTypes.doubleClass ||
- class_ == coreTypes.stringClass ||
- class_ == coreTypes.boolClass ||
- class_ == coreTypes.nullClass) {
- return true;
- }
- return !hierarchy.hasProperSubtypes(class_);
- }
}
/// The part of [TypeEnvironment] that deals with subtype tests.
@@ -167,11 +159,12 @@
InterfaceType get objectType;
InterfaceType get nullType;
InterfaceType get rawFunctionType;
- ClassHierarchy get hierarchy;
Class get futureOrClass;
InterfaceType futureType(DartType type);
bool get legacyMode;
+ InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass);
+
/// Determines if the given type is at the bottom of the type hierarchy. May
/// be overridden in subclasses.
bool isBottom(DartType type) =>
@@ -221,8 +214,7 @@
}
if (subtype is InterfaceType && supertype is InterfaceType) {
- var upcastType =
- hierarchy.getTypeAsInstanceOf(subtype, supertype.classNode);
+ var upcastType = getTypeAsInstanceOf(subtype, supertype.classNode);
if (upcastType == null) return false;
for (int i = 0; i < upcastType.typeArguments.length; ++i) {
// Termination: the 'supertype' parameter decreases in size.
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 177a883..79a3be8 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -295,6 +295,13 @@
defaultConstant(node);
R visitTearOffConstant(TearOffConstant node) => defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
+ R visitEnvironmentBoolConstant(EnvironmentBoolConstant node) =>
+ defaultConstant(node);
+ R visitEnvironmentIntConstant(EnvironmentIntConstant node) =>
+ defaultConstant(node);
+ R visitEnvironmentStringConstant(EnvironmentStringConstant node) =>
+ defaultConstant(node);
+ R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
}
class MemberReferenceVisitor<R> {
@@ -348,6 +355,13 @@
defaultConstant(node);
R visitTearOffConstant(TearOffConstant node) => defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
+ R visitEnvironmentBoolConstant(EnvironmentBoolConstant node) =>
+ defaultConstant(node);
+ R visitEnvironmentIntConstant(EnvironmentIntConstant node) =>
+ defaultConstant(node);
+ R visitEnvironmentStringConstant(EnvironmentStringConstant node) =>
+ defaultConstant(node);
+ R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
// Class references
R visitClassReference(Class node) => null;
@@ -380,6 +394,14 @@
defaultConstantReference(node);
R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
defaultConstantReference(node);
+ R visitEnvironmentBoolConstantReference(EnvironmentBoolConstant node) =>
+ defaultConstantReference(node);
+ R visitEnvironmentIntConstantReference(EnvironmentIntConstant node) =>
+ defaultConstantReference(node);
+ R visitEnvironmentStringConstantReference(EnvironmentStringConstant node) =>
+ defaultConstantReference(node);
+ R visitUnevaluatedConstantReference(UnevaluatedConstant node) =>
+ defaultConstantReference(node);
// Member references
R defaultMemberReference(Member node) => null;
diff --git a/pkg/kernel/test/class_hierarchy_bench.dart b/pkg/kernel/test/class_hierarchy_bench.dart
index cab6148..92ef9cf 100644
--- a/pkg/kernel/test/class_hierarchy_bench.dart
+++ b/pkg/kernel/test/class_hierarchy_bench.dart
@@ -68,15 +68,6 @@
return hierarchies[currentHierarchy];
}
- {
- var classHierarchy = getClassHierarchy();
- if (classHierarchy is ClosedWorldClassHierarchy) {
- for (Class class_ in classes) {
- classHierarchy.hasProperSubtypes(class_);
- }
- }
- }
-
Random rnd = new Random(12345);
const int numQueryTrials = 100000;
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 28b6038..956c0cf 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -45,7 +45,6 @@
// No updated classes, the same hierarchy.
expect(hierarchy.applyTreeChanges([], []), same(hierarchy));
- expect(hierarchy.hasProperSubtypes(a), true);
// Has updated classes, still the same hierarchy (instance). Can answer
// queries about the new classes.
@@ -59,11 +58,9 @@
expect(hierarchy.applyTreeChanges([libWithB], [libWithC]), same(hierarchy));
expect(hierarchy.isSubclassOf(a, c), false);
expect(hierarchy.isSubclassOf(c, a), true);
- expect(hierarchy.hasProperSubtypes(a), true);
// Remove so A should no longer be a super of anything.
expect(hierarchy.applyTreeChanges([libWithC], []), same(hierarchy));
- expect(hierarchy.hasProperSubtypes(a), false);
}
void test_applyMemberChanges() {
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
new file mode 100644
index 0000000..f934baa
--- /dev/null
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+library kernel.text_serializer_from_kernel_nodes_test;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/text/serializer_combinators.dart';
+import 'package:kernel/text/text_reader.dart';
+import 'package:kernel/text/text_serializer.dart';
+
+void main() {
+ initializeSerializers();
+ test();
+}
+
+// Wrappers for testing.
+Expression readExpression(
+ String input, DeserializationEnvironment environment) {
+ TextIterator stream = new TextIterator(input, 0);
+ stream.moveNext();
+ Expression result = expressionSerializer.readFrom(stream, environment);
+ if (stream.moveNext()) {
+ throw StateError("extra cruft in basic literal");
+ }
+ return result;
+}
+
+String writeExpression(
+ Expression expression, SerializationEnvironment environment) {
+ StringBuffer buffer = new StringBuffer();
+ expressionSerializer.writeTo(buffer, expression, environment);
+ return buffer.toString();
+}
+
+class TestCase {
+ final String name;
+ final Node node;
+ final SerializationEnvironment serializationEnvironment;
+ final DeserializationEnvironment deserializationEnvironment;
+ final String expectation;
+
+ TestCase(
+ {this.name,
+ this.node,
+ this.expectation,
+ this.serializationEnvironment,
+ this.deserializationEnvironment});
+}
+
+void test() {
+ List<String> failures = [];
+ List<TestCase> tests = <TestCase>[
+ new TestCase(
+ name: "let dynamic x = 42 in x",
+ node: () {
+ VariableDeclaration x = new VariableDeclaration("x",
+ type: const DynamicType(), initializer: new IntLiteral(42));
+ return new Let(x, new VariableGet(x));
+ }(),
+ expectation:
+ "(let (var \"x^0\" (dynamic) (int 42) ()) (get-var \"x^0\" _))"),
+ new TestCase(
+ name: "let dynamic x = 42 in let Bottom x^0 = null in x",
+ node: () {
+ VariableDeclaration outterLetVar = new VariableDeclaration("x",
+ type: const DynamicType(), initializer: new IntLiteral(42));
+ VariableDeclaration innerLetVar = new VariableDeclaration("x",
+ type: const BottomType(), initializer: new NullLiteral());
+ return new Let(outterLetVar,
+ new Let(innerLetVar, new VariableGet(outterLetVar)));
+ }(),
+ expectation: ""
+ "(let (var \"x^0\" (dynamic) (int 42) ())"
+ " (let (var \"x^1\" (bottom) (null) ())"
+ " (get-var \"x^0\" _)))"),
+ new TestCase(
+ name: "let dynamic x = 42 in let Bottom x^0 = null in x^0",
+ node: () {
+ VariableDeclaration outterLetVar = new VariableDeclaration("x",
+ type: const DynamicType(), initializer: new IntLiteral(42));
+ VariableDeclaration innerLetVar = new VariableDeclaration("x",
+ type: const BottomType(), initializer: new NullLiteral());
+ return new Let(
+ outterLetVar, new Let(innerLetVar, new VariableGet(innerLetVar)));
+ }(),
+ expectation: ""
+ "(let (var \"x^0\" (dynamic) (int 42) ())"
+ " (let (var \"x^1\" (bottom) (null) ())"
+ " (get-var \"x^1\" _)))"),
+ () {
+ VariableDeclaration x =
+ new VariableDeclaration("x", type: const DynamicType());
+ return new TestCase(
+ name: "/* suppose: dynamic x; */ x = 42",
+ node: () {
+ return new VariableSet(x, new IntLiteral(42));
+ }(),
+ expectation: "(set-var \"x^0\" (int 42))",
+ serializationEnvironment: new SerializationEnvironment(null)
+ ..add(x, "x^0"),
+ deserializationEnvironment: new DeserializationEnvironment(null)
+ ..add("x^0", x));
+ }(),
+ ];
+ for (TestCase testCase in tests) {
+ String roundTripInput =
+ writeExpression(testCase.node, testCase.serializationEnvironment);
+ if (roundTripInput != testCase.expectation) {
+ failures.add(''
+ '* initial serialization for test "${testCase.name}"'
+ ' gave output "${roundTripInput}"');
+ }
+
+ TreeNode deserialized =
+ readExpression(roundTripInput, testCase.deserializationEnvironment);
+ String roundTripOutput =
+ writeExpression(deserialized, testCase.serializationEnvironment);
+ if (roundTripOutput != roundTripInput) {
+ failures.add(''
+ '* input "${testCase.name}" gave output "${roundTripOutput}"');
+ }
+ }
+ if (failures.isNotEmpty) {
+ print('Round trip failures:');
+ failures.forEach(print);
+ throw StateError('Round trip failures');
+ }
+}
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index f19b5b8..029b91b 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_test.dart
@@ -16,7 +16,7 @@
Expression readExpression(String input) {
TextIterator stream = new TextIterator(input, 0);
stream.moveNext();
- Expression result = expressionSerializer.readFrom(stream);
+ Expression result = expressionSerializer.readFrom(stream, null);
if (stream.moveNext()) {
throw StateError("extra cruft in basic literal");
}
@@ -25,19 +25,24 @@
String writeExpression(Expression expression) {
StringBuffer buffer = new StringBuffer();
- expressionSerializer.writeTo(buffer, expression);
+ expressionSerializer.writeTo(buffer, expression, null);
return buffer.toString();
}
void test() {
List<String> failures = [];
List<String> tests = [
- "(let (var \"x\" (dynamic) (int 0) ()) (null))",
- "(let (var \"x\" (dynamic) _ ()) (null))",
- "(let (const \"x\" (dynamic) (int 0) ()) (null))",
- "(let (const \"x\" (dynamic) _ ()) (null))",
- "(let (final \"x\" (dynamic) (int 0) ()) (null))",
- "(let (final \"x\" (dynamic) _ ()) (null))",
+ "(get-prop (int 0) (public \"hashCode\"))",
+ "(get-super (public \"hashCode\"))",
+ "(invoke-method (int 0) (public \"foo\") () ((int 1) (int 2)) ())",
+ "(invoke-method (int 0) (public \"foo\") ((dynamic) (void)) "
+ "((int 1) (int 2)) (\"others\" (list (dynamic) ((int 3) (int 4)))))",
+ "(let (var \"x^0\" (dynamic) (int 0) ()) (null))",
+ "(let (var \"x^0\" (dynamic) _ ()) (null))",
+ "(let (const \"x^0\" (dynamic) (int 0) ()) (null))",
+ "(let (const \"x^0\" (dynamic) _ ()) (null))",
+ "(let (final \"x^0\" (dynamic) (int 0) ()) (null))",
+ "(let (final \"x^0\" (dynamic) _ ()) (null))",
"(string \"Hello, 'string'!\")",
"(string \"Hello, \\\"string\\\"!\")",
"(string \"Yeah nah yeah, here is\\nthis really long string haiku\\n"
diff --git a/pkg/kernel/test/type_subtype_test.dart b/pkg/kernel/test/type_subtype_test.dart
index d97c690..753e525 100644
--- a/pkg/kernel/test/type_subtype_test.dart
+++ b/pkg/kernel/test/type_subtype_test.dart
@@ -200,11 +200,16 @@
Class futureClass;
Class futureOrClass;
LazyTypeEnvironment environment;
- bool legacyMode = true;
+ bool legacyMode = false;
InterfaceType futureType(DartType type) =>
new InterfaceType(futureClass, [type]);
+ @override
+ InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+ return hierarchy.getTypeAsInstanceOf(type, superclass);
+ }
+
MockSubtypeTester(
this.hierarchy,
this.objectType,
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 30c3b6c..e1e6bc8 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -37,6 +37,8 @@
import 'package:vm/kernel_front_end.dart' show runWithFrontEndCompilerContext;
import 'package:vm/http_filesystem.dart';
import 'package:vm/target/vm.dart' show VmTarget;
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+ show CompilerOptions, parseExperimentalFlags;
final bool verbose = new bool.fromEnvironment('DFE_VERBOSE');
const String platformKernelFile = 'virtual_platform_kernel.dill';
@@ -67,6 +69,7 @@
final FileSystem fileSystem;
final Uri platformKernelPath;
bool suppressWarnings;
+ List<String> experimentalFlags;
bool bytecode;
String packageConfig;
@@ -76,6 +79,7 @@
Compiler(this.fileSystem, this.platformKernelPath,
{this.suppressWarnings: false,
+ this.experimentalFlags: null,
this.bytecode: false,
this.packageConfig: null}) {
Uri packagesUri = null;
@@ -92,6 +96,13 @@
print("DFE: platformKernelPath: ${platformKernelPath}");
}
+ var expFlags = List<String>();
+ if (experimentalFlags != null) {
+ for (String flag in experimentalFlags) {
+ expFlags.addAll(flag.split(","));
+ }
+ }
+
options = new CompilerOptions()
..fileSystem = fileSystem
..target = new VmTarget(new TargetFlags())
@@ -99,6 +110,8 @@
..sdkSummary = platformKernelPath
..verbose = verbose
..bytecode = bytecode
+ ..experimentalFlags =
+ parseExperimentalFlags(expFlags, (msg) => errors.add(msg))
..onDiagnostic = (DiagnosticMessage message) {
bool printMessage;
switch (message.severity) {
@@ -163,10 +176,12 @@
IncrementalCompilerWrapper(FileSystem fileSystem, Uri platformKernelPath,
{bool suppressWarnings: false,
+ List<String> experimentalFlags: null,
bool bytecode: false,
String packageConfig: null})
: super(fileSystem, platformKernelPath,
suppressWarnings: suppressWarnings,
+ experimentalFlags: experimentalFlags,
bytecode: bytecode,
packageConfig: packageConfig);
@@ -186,6 +201,7 @@
IncrementalCompilerWrapper clone = IncrementalCompilerWrapper(
fileSystem, platformKernelPath,
suppressWarnings: suppressWarnings,
+ experimentalFlags: experimentalFlags,
bytecode: bytecode,
packageConfig: packageConfig);
@@ -213,10 +229,12 @@
SingleShotCompilerWrapper(FileSystem fileSystem, Uri platformKernelPath,
{this.requireMain: false,
bool suppressWarnings: false,
+ List<String> experimentalFlags: null,
bool bytecode: false,
String packageConfig: null})
: super(fileSystem, platformKernelPath,
suppressWarnings: suppressWarnings,
+ experimentalFlags: experimentalFlags,
bytecode: bytecode,
packageConfig: packageConfig);
@@ -240,6 +258,7 @@
Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
List sourceFiles, Uri platformKernelPath, List<int> platformKernel,
{bool suppressWarnings: false,
+ List<String> experimentalFlags: null,
bool bytecode: false,
String packageConfig: null,
String multirootFilepaths,
@@ -268,6 +287,7 @@
// isolate was shut down. Message should be handled here in this script.
compiler = new IncrementalCompilerWrapper(fileSystem, platformKernelPath,
suppressWarnings: suppressWarnings,
+ experimentalFlags: experimentalFlags,
bytecode: bytecode,
packageConfig: packageConfig);
}
@@ -445,10 +465,12 @@
final int isolateId = request[6];
final List sourceFiles = request[7];
final bool suppressWarnings = request[8];
- final bool bytecode = request[9];
- final String packageConfig = request[10];
- final String multirootFilepaths = request[11];
- final String multirootScheme = request[12];
+ final List<String> experimentalFlags =
+ request[9] != null ? request[9].cast<String>() : null;
+ final bool bytecode = request[10];
+ final String packageConfig = request[11];
+ final String multirootFilepaths = request[12];
+ final String multirootScheme = request[13];
if (bytecode) {
// Bytecode generator is hooked into kernel service after kernel component
@@ -507,6 +529,7 @@
compiler = await lookupOrBuildNewIncrementalCompiler(
isolateId, sourceFiles, platformKernelPath, platformKernel,
suppressWarnings: suppressWarnings,
+ experimentalFlags: experimentalFlags,
bytecode: bytecode,
packageConfig: packageConfig,
multirootFilepaths: multirootFilepaths,
@@ -517,6 +540,7 @@
compiler = new SingleShotCompilerWrapper(fileSystem, platformKernelPath,
requireMain: false,
suppressWarnings: suppressWarnings,
+ experimentalFlags: experimentalFlags,
bytecode: bytecode,
packageConfig: packageConfig);
}
@@ -641,6 +665,7 @@
1 /* isolateId chosen randomly */,
[] /* source files */,
false /* suppress warnings */,
+ null /* experimental_flags */,
false /* generate bytecode */,
null /* package_config */,
null /* multirootFilepaths */,
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 11f5bcf..04a58fb 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -830,8 +830,7 @@
locals = new LocalVariables(node);
// TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
constantEvaluator = new ConstantEvaluator(constantsBackend, typeEnvironment,
- coreTypes, /* enableAsserts = */ true,
- errorReporter: errorReporter)
+ coreTypes, /* enableAsserts = */ true, errorReporter)
..env = new EvaluationEnvironment();
labeledStatements = <LabeledStatement, Label>{};
switchCases = <SwitchCase, Label>{};
diff --git a/pkg/vm/lib/constants_error_reporter.dart b/pkg/vm/lib/constants_error_reporter.dart
index eba53b4..cadbc0e 100644
--- a/pkg/vm/lib/constants_error_reporter.dart
+++ b/pkg/vm/lib/constants_error_reporter.dart
@@ -12,11 +12,11 @@
import 'package:front_end/src/api_unstable/vm.dart' as codes;
import 'package:kernel/ast.dart'
- show Constant, DartType, FileUriNode, IntConstant, Procedure, TreeNode;
+ show Constant, DartType, IntConstant, Procedure, TreeNode;
import 'package:kernel/transformations/constants.dart' as constants;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
-class ForwardConstantEvaluationErrors implements constants.ErrorReporter {
+class ForwardConstantEvaluationErrors extends constants.ErrorReporter {
// This will get the currently active [CompilerContext] from a zone variable.
// If there is no active context, this will throw.
final CompilerContext compilerContext = CompilerContext.current;
@@ -25,25 +25,29 @@
ForwardConstantEvaluationErrors(this.typeEnvironment);
- freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
+ @override
+ void freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
final message =
codes.templateConstEvalFreeTypeParameter.withArguments(type);
reportIt(context, message, node);
}
- duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
+ @override
+ void duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
final message = codes.templateConstEvalDuplicateKey.withArguments(key);
reportIt(context, message, node);
}
- invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
+ @override
+ void invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
DartType expectedType) {
final message = codes.templateConstEvalInvalidType.withArguments(
receiver, expectedType, receiver.getType(typeEnvironment));
reportIt(context, message, node);
}
- invalidBinaryOperandType(
+ @override
+ void invalidBinaryOperandType(
List<TreeNode> context,
TreeNode node,
Constant receiver,
@@ -55,54 +59,63 @@
reportIt(context, message, node);
}
- invalidMethodInvocation(
+ @override
+ void invalidMethodInvocation(
List<TreeNode> context, TreeNode node, Constant receiver, String op) {
final message = codes.templateConstEvalInvalidMethodInvocation
.withArguments(op, receiver);
reportIt(context, message, node);
}
- invalidStaticInvocation(
+ @override
+ void invalidStaticInvocation(
List<TreeNode> context, TreeNode node, Procedure target) {
final message = codes.templateConstEvalInvalidStaticInvocation
.withArguments(target.name.toString());
reportIt(context, message, node);
}
- invalidStringInterpolationOperand(
+ @override
+ void invalidStringInterpolationOperand(
List<TreeNode> context, TreeNode node, Constant constant) {
final message = codes.templateConstEvalInvalidStringInterpolationOperand
.withArguments(constant);
reportIt(context, message, node);
}
- invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant) {
+ @override
+ void invalidSymbolName(
+ List<TreeNode> context, TreeNode node, Constant constant) {
final message =
codes.templateConstEvalInvalidSymbolName.withArguments(constant);
reportIt(context, message, node);
}
- zeroDivisor(
+ @override
+ void zeroDivisor(
List<TreeNode> context, TreeNode node, IntConstant receiver, String op) {
final message = codes.templateConstEvalZeroDivisor
.withArguments(op, '${receiver.value}');
reportIt(context, message, node);
}
- negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
- String op, IntConstant argument) {
+ @override
+ void negativeShift(List<TreeNode> context, TreeNode node,
+ IntConstant receiver, String op, IntConstant argument) {
final message = codes.templateConstEvalNegativeShift
.withArguments(op, '${receiver.value}', '${argument.value}');
reportIt(context, message, node);
}
- nonConstLiteral(List<TreeNode> context, TreeNode node, String klass) {
+ @override
+ void nonConstLiteral(List<TreeNode> context, TreeNode node, String klass) {
final message =
codes.templateConstEvalNonConstantLiteral.withArguments(klass);
reportIt(context, message, node);
}
- failedAssertion(List<TreeNode> context, TreeNode node, String string) {
+ @override
+ void failedAssertion(List<TreeNode> context, TreeNode node, String string) {
final message = string == null
? codes.messageConstEvalFailedAssertion
: codes.templateConstEvalFailedAssertionWithMessage
@@ -110,20 +123,23 @@
reportIt(context, message, node);
}
- nonConstantVariableGet(
+ @override
+ void nonConstantVariableGet(
List<TreeNode> context, TreeNode node, String variableName) {
final message = codes.templateConstEvalNonConstantVariableGet
.withArguments(variableName);
reportIt(context, message, node);
}
- deferredLibrary(List<TreeNode> context, TreeNode node, String importName) {
+ @override
+ void deferredLibrary(
+ List<TreeNode> context, TreeNode node, String importName) {
final message =
codes.templateConstEvalDeferredLibrary.withArguments(importName);
reportIt(context, message, node);
}
- reportIt(List<TreeNode> context, codes.Message message, TreeNode node) {
+ void reportIt(List<TreeNode> context, codes.Message message, TreeNode node) {
final Uri uri = getFileUri(node);
final int fileOffset = getFileOffset(node);
@@ -141,18 +157,4 @@
compilerContext.options
.report(locatedMessage, Severity.error, context: contextMessages);
}
-
- getFileUri(TreeNode node) {
- while (node is! FileUriNode) {
- node = node.parent;
- }
- return (node as FileUriNode).fileUri;
- }
-
- getFileOffset(TreeNode node) {
- while (node?.fileOffset == TreeNode.noOffset) {
- node = node.parent;
- }
- return node == null ? TreeNode.noOffset : node.fileOffset;
- }
}
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index d84850d..2105181 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -385,10 +385,10 @@
// TFA will remove constants fields which are unused (and respects the
// vm/embedder entrypoints).
constants.transformComponent(component, vmConstants,
+ new ForwardConstantEvaluationErrors(typeEnvironment),
keepFields: true,
evaluateAnnotations: true,
- enableAsserts: enableAsserts,
- errorReporter: new ForwardConstantEvaluationErrors(typeEnvironment));
+ enableAsserts: enableAsserts);
});
}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 71d48cb..f403b43 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -220,6 +220,7 @@
}
fieldValue.setValue(initializerResult, typeFlowAnalysis,
field.isStatic ? null : args.receiver);
+ fieldValue.isInitialized = true;
return const EmptyType();
}
@@ -732,6 +733,9 @@
final Summary typeGuardSummary;
Type value;
+ /// Flag indicating if field initializer was executed.
+ bool isInitialized = false;
+
_FieldValue(this.field, this.typeGuardSummary)
: staticType = new Type.fromStatic(field.type) {
if (field.initializer == null && _isDefaultValueOfFieldObservable()) {
@@ -1357,7 +1361,7 @@
hierarchyCache = new _ClassHierarchyCache(
this, hierarchy, _genericInterfacesInfo, environment);
summaryCollector = new SummaryCollector(
- target, environment, this, nativeCodeOracle, hierarchyCache);
+ target, environment, hierarchy, this, nativeCodeOracle, hierarchyCache);
_invocationsCache = new _InvocationsCache(this);
workList = new _WorkList(this);
@@ -1385,6 +1389,8 @@
hierarchyCache.seal();
}
+ /// Returns true if analysis found that given member
+ /// could be executed / field could be accessed.
bool isMemberUsed(Member member) {
if (member is Field) {
return _fieldValues.containsKey(member);
@@ -1393,6 +1399,16 @@
}
}
+ /// Returns true if analysis found that initializer of the given [field]
+ /// could be executed.
+ bool isFieldInitializerUsed(Field field) {
+ final fieldValue = _fieldValues[field];
+ if (fieldValue != null) {
+ return fieldValue.isInitialized;
+ }
+ return false;
+ }
+
bool isClassAllocated(Class c) => hierarchyCache.allocatedClasses.contains(c);
Call callSite(TreeNode node) => summaryCollector.callSites[node];
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index af0e734..e9d777b 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -10,6 +10,7 @@
import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import 'package:kernel/type_algebra.dart' show Substitution;
@@ -278,6 +279,7 @@
class SummaryCollector extends RecursiveVisitor<TypeExpr> {
final Target target;
final TypeEnvironment _environment;
+ final ClassHierarchy _hierarchy;
final EntryPointsListener _entryPointsListener;
final NativeCodeOracle _nativeCodeOracle;
final GenericInterfacesInfo _genericInterfacesInfo;
@@ -298,8 +300,13 @@
// Currently only used for factory constructors.
Map<TypeParameter, TypeExpr> _fnTypeVariables;
- SummaryCollector(this.target, this._environment, this._entryPointsListener,
- this._nativeCodeOracle, this._genericInterfacesInfo) {
+ SummaryCollector(
+ this.target,
+ this._environment,
+ this._hierarchy,
+ this._entryPointsListener,
+ this._nativeCodeOracle,
+ this._genericInterfacesInfo) {
assertx(_genericInterfacesInfo != null);
constantAllocationCollector = new ConstantAllocationCollector(this);
}
@@ -992,8 +999,7 @@
assertx(_receiver != null, details: node);
final args = _visitArguments(_receiver, node.arguments);
// Re-resolve target due to partial mixin resolution.
- final target =
- _environment.hierarchy.getDispatchTarget(_superclass, node.name);
+ final target = _hierarchy.getDispatchTarget(_superclass, node.name);
if (target == null) {
return new Type.empty();
} else {
@@ -1021,8 +1027,7 @@
assertx(_receiver != null, details: node);
final args = new Args<TypeExpr>([_receiver]);
// Re-resolve target due to partial mixin resolution.
- final target =
- _environment.hierarchy.getDispatchTarget(_superclass, node.name);
+ final target = _hierarchy.getDispatchTarget(_superclass, node.name);
if (target == null) {
return new Type.empty();
} else {
@@ -1038,8 +1043,8 @@
final value = _visit(node.value);
final args = new Args<TypeExpr>([_receiver, value]);
// Re-resolve target due to partial mixin resolution.
- final target = _environment.hierarchy
- .getDispatchTarget(_superclass, node.name, setter: true);
+ final target =
+ _hierarchy.getDispatchTarget(_superclass, node.name, setter: true);
if (target != null) {
assertx((target is Field) || ((target is Procedure) && target.isSetter));
_entryPointsListener.recordMemberCalledViaThis(target);
@@ -1539,14 +1544,15 @@
final TypeEnvironment _environment;
final SummaryCollector _summaryCollector;
- CreateAllSummariesVisitor(
- Target target, this._environment, GenericInterfacesInfo hierarchy)
+ CreateAllSummariesVisitor(Target target, this._environment,
+ ClassHierarchy hierarchy, GenericInterfacesInfo genericInterfacesInfo)
: _summaryCollector = new SummaryCollector(
target,
_environment,
+ hierarchy,
new EmptyEntryPointsListener(),
new NativeCodeOracle(null, null),
- hierarchy);
+ genericInterfacesInfo);
@override
defaultMember(Member m) {
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 837baeb..4e3103d 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -46,7 +46,8 @@
if (kDumpAllSummaries) {
Statistics.reset();
- new CreateAllSummariesVisitor(target, types, genericInterfacesInfo)
+ new CreateAllSummariesVisitor(
+ target, types, hierarchy, genericInterfacesInfo)
.visitComponent(component);
Statistics.print("All summaries statistics");
}
@@ -73,7 +74,7 @@
new TreeShaker(component, typeFlowAnalysis).transformComponent(component);
- new TFADevirtualization(component, typeFlowAnalysis)
+ new TFADevirtualization(component, typeFlowAnalysis, hierarchy)
.visitComponent(component);
new AnnotateKernel(component, typeFlowAnalysis).visitComponent(component);
@@ -92,9 +93,9 @@
class TFADevirtualization extends Devirtualization {
final TypeFlowAnalysis _typeFlowAnalysis;
- TFADevirtualization(Component component, this._typeFlowAnalysis)
- : super(_typeFlowAnalysis.environment.coreTypes, component,
- _typeFlowAnalysis.environment.hierarchy);
+ TFADevirtualization(
+ Component component, this._typeFlowAnalysis, ClassHierarchy hierarchy)
+ : super(_typeFlowAnalysis.environment.coreTypes, component, hierarchy);
@override
DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
@@ -366,6 +367,8 @@
bool isClassAllocated(Class c) => typeFlowAnalysis.isClassAllocated(c);
bool isMemberUsed(Member m) => _usedMembers.contains(m);
bool isMemberBodyReachable(Member m) => typeFlowAnalysis.isMemberUsed(m);
+ bool isFieldInitializerReachable(Field f) =>
+ typeFlowAnalysis.isFieldInitializerUsed(f);
bool isMemberReferencedFromNativeCode(Member m) =>
typeFlowAnalysis.nativeCodeOracle.isMemberReferencedFromNativeCode(m);
bool isTypedefUsed(Typedef t) => _usedTypedefs.contains(t);
@@ -602,6 +605,30 @@
}
@override
+ TreeNode visitField(Field node) {
+ if (shaker.isMemberBodyReachable(node)) {
+ if (kPrintTrace) {
+ tracePrint("Visiting $node");
+ }
+ shaker.addUsedMember(node);
+ if (node.initializer != null) {
+ if (shaker.isFieldInitializerReachable(node)) {
+ node.transformChildren(this);
+ } else {
+ node.initializer = _makeUnreachableCall([]);
+ }
+ }
+ } else if (shaker.isMemberReferencedFromNativeCode(node)) {
+ // Preserve members referenced from native code to satisfy lookups, even
+ // if they are not reachable. An instance member could be added via
+ // native code entry point but still unreachable if no instances of
+ // its enclosing class are allocated.
+ shaker.addUsedMember(node);
+ }
+ return node;
+ }
+
+ @override
TreeNode visitMethodInvocation(MethodInvocation node) {
node.transformChildren(this);
if (_isUnreachable(node)) {
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 1ec8d87..022c7e1 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -23,15 +23,16 @@
final SummaryCollector _summaryCollector;
final StringBuffer _buf = new StringBuffer();
- PrintSummaries(
- Target target, TypeEnvironment environment, CoreTypes coreTypes)
+ PrintSummaries(Target target, TypeEnvironment environment,
+ CoreTypes coreTypes, ClassHierarchy hierarchy)
: _summaryCollector = new SummaryCollector(
target,
environment,
+ hierarchy,
new EmptyEntryPointsListener(),
new NativeCodeOracle(
null, new ExpressionPragmaAnnotationParser(coreTypes)),
- new GenericInterfacesInfoImpl(environment.hierarchy));
+ new GenericInterfacesInfoImpl(hierarchy));
String print(TreeNode node) {
visitLibrary(node);
@@ -54,11 +55,12 @@
final Library library = component.mainMethod.enclosingLibrary;
final CoreTypes coreTypes = new CoreTypes(component);
- final typeEnvironment =
- new TypeEnvironment(coreTypes, new ClassHierarchy(component));
+ final ClassHierarchy hierarchy = new ClassHierarchy(component);
+ final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
final actual =
- new PrintSummaries(target, typeEnvironment, coreTypes).print(library);
+ new PrintSummaries(target, typeEnvironment, coreTypes, hierarchy)
+ .print(library);
compareResultWithExpectationsFile(source, actual);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
new file mode 100644
index 0000000..6abe2d5
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, 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.
+
+// Tests tree shaking of field initializer for a write-only field.
+// Regression test for https://github.com/dart-lang/sdk/issues/35632.
+
+class A {
+ A() {
+ print('A');
+ }
+}
+
+var field = A();
+
+class B {
+ B() {
+ print('B');
+ }
+}
+
+class C {
+ var instanceField = new B();
+}
+
+void main() {
+ field = null;
+ new C().instanceField = null;
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
new file mode 100644
index 0000000..d8d8757
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
@@ -0,0 +1,23 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+}
+class B extends core::Object {
+ constructor •() → self::B
+ : super core::Object::•() {
+ core::print("B");
+ }
+}
+class C extends core::Object {
+[@vm.inferred-type.metadata=#lib::B?] [@vm.procedure-attributes.metadata=hasDynamicUses:false,hasThisUses:false,hasTearOffUses:false] field self::B instanceField = new self::B::•();
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+[@vm.inferred-type.metadata=dart.core::Null?]static field self::A field = throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+static method main() → void {
+ self::field = null;
+ [@vm.direct-call.metadata=#lib::C::instanceField] new self::C::•().{self::C::instanceField} = null;
+}
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 3eb59b3..0e3e2e2 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -191,6 +191,11 @@
if (defined(is_tsan) && is_tsan) {
ldflags += [ "-fsanitize=thread" ]
}
+
+ if (is_fuchsia) {
+ # safe-stack does not work with the interpreter.
+ cflags += [ "-fno-sanitize=safe-stack" ]
+ }
}
}
diff --git a/runtime/bin/extensions_fuchsia.cc b/runtime/bin/extensions_fuchsia.cc
index a177c4c..64df6b6 100644
--- a/runtime/bin/extensions_fuchsia.cc
+++ b/runtime/bin/extensions_fuchsia.cc
@@ -24,17 +24,7 @@
"_kDartIsolateSnapshotInstructions";
void* Extensions::LoadExtensionLibrary(const char* library_file) {
- int fd = open(library_file, O_RDONLY);
- if (fd < 0) {
- return NULL;
- }
- zx_handle_t vmo;
- zx_status_t status = fdio_get_vmo_clone(fd, &vmo);
- close(fd);
- if (status != ZX_OK) {
- return NULL;
- }
- return dlopen_vmo(vmo, RTLD_LAZY);
+ return dlopen(library_file, RTLD_LAZY);
}
void* Extensions::ResolveSymbol(void* lib_handle, const char* symbol) {
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 98654fe..3cb0462 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -72,6 +72,7 @@
kCore,
kCoreJIT,
kCoreJITAll,
+ kApp,
kAppJIT,
kAppAOTBlobs,
kAppAOTAssembly,
@@ -99,6 +100,7 @@
"core",
"core-jit",
"core-jit-all",
+ "app",
"app-jit",
"app-aot-blobs",
"app-aot-assembly",
@@ -124,6 +126,7 @@
V(assembly, assembly_filename) \
V(dependencies, dependencies_filename) \
V(load_compilation_trace, load_compilation_trace_filename) \
+ V(load_type_feedback, load_type_feedback_filename) \
V(package_root, commandline_package_root) \
V(packages, commandline_packages_file) \
V(save_obfuscation_map, obfuscation_map_filename)
@@ -297,6 +300,7 @@
}
break;
}
+ case kApp:
case kAppJIT: {
if ((load_vm_snapshot_data_filename == NULL) ||
(isolate_snapshot_data_filename == NULL) ||
@@ -452,6 +456,7 @@
case kAppAOTAssembly:
WriteDependenciesWithTarget(assembly_filename);
break;
+ case kApp:
case kAppJIT:
WriteDependenciesWithTarget(isolate_snapshot_data_filename);
// WriteDependenciesWithTarget(isolate_snapshot_instructions_filename);
@@ -563,6 +568,14 @@
Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
CHECK_RESULT(result);
}
+ if ((load_type_feedback_filename != NULL) &&
+ ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
+ uint8_t* buffer = NULL;
+ intptr_t size = 0;
+ ReadFile(load_type_feedback_filename, &buffer, &size);
+ Dart_Handle result = Dart_LoadTypeFeedback(buffer, size);
+ CHECK_RESULT(result);
+ }
}
static void CompileAll() {
@@ -594,11 +607,15 @@
WriteFile(vm_snapshot_data_filename, vm_snapshot_data_buffer,
vm_snapshot_data_size);
if (vm_snapshot_instructions_filename != NULL) {
+ // Create empty file for the convenience of build systems. Makes things
+ // polymorphic with generating core-jit snapshots.
WriteFile(vm_snapshot_instructions_filename, NULL, 0);
}
WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
isolate_snapshot_data_size);
if (isolate_snapshot_instructions_filename != NULL) {
+ // Create empty file for the convenience of build systems. Makes things
+ // polymorphic with generating core-jit snapshots.
WriteFile(isolate_snapshot_instructions_filename, NULL, 0);
}
}
@@ -666,6 +683,27 @@
isolate_snapshot_instructions_size);
}
+static void CreateAndWriteAppSnapshot() {
+ ASSERT(snapshot_kind == kApp);
+ ASSERT(isolate_snapshot_data_filename != NULL);
+
+ Dart_Handle result;
+ uint8_t* isolate_snapshot_data_buffer = NULL;
+ intptr_t isolate_snapshot_data_size = 0;
+
+ result = Dart_CreateSnapshot(NULL, NULL, &isolate_snapshot_data_buffer,
+ &isolate_snapshot_data_size);
+ CHECK_RESULT(result);
+
+ WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
+ isolate_snapshot_data_size);
+ if (isolate_snapshot_instructions_filename != NULL) {
+ // Create empty file for the convenience of build systems. Makes things
+ // polymorphic with generating core-jit snapshots.
+ WriteFile(isolate_snapshot_instructions_filename, NULL, 0);
+ }
+}
+
static void CreateAndWriteAppJITSnapshot() {
ASSERT(snapshot_kind == kAppJIT);
ASSERT(isolate_snapshot_data_filename != NULL);
@@ -898,6 +936,9 @@
LoadCompilationTrace();
CreateAndWriteCoreJITSnapshot();
break;
+ case kApp:
+ CreateAndWriteAppSnapshot();
+ break;
case kAppJIT:
LoadBytecode();
LoadCompilationTrace();
@@ -981,7 +1022,9 @@
} else if ((snapshot_kind == kCoreJITAll) || (snapshot_kind == kCoreJIT) ||
(snapshot_kind == kAppJIT)) {
vm_options.AddArgument("--fields_may_be_reset");
+#if !defined(TARGET_ARCH_IA32)
vm_options.AddArgument("--link_natives_lazily");
+#endif
#if !defined(PRODUCT)
vm_options.AddArgument("--collect_code=false");
#endif
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index bd32e22..cb1dd8d 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -879,11 +879,11 @@
LoadBytecode();
}
- if (Options::load_compilation_trace_filename() != NULL) {
+ if (Options::load_type_feedback_filename() != NULL) {
uint8_t* buffer = NULL;
intptr_t size = 0;
- ReadFile(Options::load_compilation_trace_filename(), &buffer, &size);
- result = Dart_LoadCompilationTrace(buffer, size);
+ ReadFile(Options::load_type_feedback_filename(), &buffer, &size);
+ result = Dart_LoadTypeFeedback(buffer, size);
CHECK_RESULT(result);
}
@@ -922,12 +922,12 @@
}
CHECK_RESULT(result);
- if (Options::save_compilation_trace_filename() != NULL) {
+ if (Options::save_type_feedback_filename() != NULL) {
uint8_t* buffer = NULL;
intptr_t size = 0;
- result = Dart_SaveCompilationTrace(&buffer, &size);
+ result = Dart_SaveTypeFeedback(&buffer, &size);
CHECK_RESULT(result);
- WriteFile(Options::save_compilation_trace_filename(), buffer, size);
+ WriteFile(Options::save_type_feedback_filename(), buffer, size);
}
}
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 5a0377e..2b668ac 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -24,8 +24,8 @@
V(depfile, depfile) \
V(depfile_output_filename, depfile_output_filename) \
V(shared_blobs, shared_blobs_filename) \
- V(save_compilation_trace, save_compilation_trace_filename) \
- V(load_compilation_trace, load_compilation_trace_filename) \
+ V(save_type_feedback, save_type_feedback_filename) \
+ V(load_type_feedback, load_type_feedback_filename) \
V(root_certs_file, root_certs_file) \
V(root_certs_cache, root_certs_cache) \
V(namespace, namespc)
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 5ac0f25..a560eb2 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3152,6 +3152,12 @@
*/
DART_EXPORT Dart_Port Dart_ServiceWaitForLoadPort();
+/*
+ * ====================
+ * Compilation Feedback
+ * ====================
+ */
+
/**
* Record all functions which have been compiled in the current isolate.
*
@@ -3175,6 +3181,29 @@
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length);
+/**
+ * Record runtime feedback for the current isolate, including type feedback
+ * and usage counters.
+ *
+ * \param buffer Returns a pointer to a buffer containing the trace.
+ * This buffer is scope allocated and is only valid until the next call to
+ * Dart_ExitScope.
+ * \param size Returns the size of the buffer.
+ * \return Returns an valid handle upon success.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_SaveTypeFeedback(uint8_t** buffer, intptr_t* buffer_length);
+
+/**
+ * Compile functions using data from Dart_SaveTypeFeedback. The data must from a
+ * VM with the same version and compiler flags.
+ *
+ * \return Returns an error handle if a compilation error was encountered or a
+ * version mismatch is detected.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_LoadTypeFeedback(uint8_t* buffer, intptr_t buffer_length);
+
/*
* ==============
* Precompilation
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 1ec264d..7bea7c9 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -24,7 +24,7 @@
@patch
factory List.from(Iterable elements, {bool growable: true}) {
- if (elements is EfficientLengthIterable) {
+ if (elements is EfficientLengthIterable<E>) {
int length = elements.length;
var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
if (length > 0) {
@@ -36,12 +36,25 @@
}
return list;
}
- List<E> list = new _GrowableList<E>(0);
- for (E e in elements) {
- list.add(e);
+ // If elements is an Iterable<E>, we won't need a type-test for each
+ // element. In the "common case" that elements is an Iterable<E>, this
+ // replaces a type-test on every element with a single type-test before
+ // starting the loop.
+ if (elements is Iterable<E>) {
+ List<E> list = new _GrowableList<E>(0);
+ for (E e in elements) {
+ list.add(e);
+ }
+ if (growable) return list;
+ return makeListFixedLength(list);
+ } else {
+ List<E> list = new _GrowableList<E>(0);
+ for (E e in elements) {
+ list.add(e);
+ }
+ if (growable) return list;
+ return makeListFixedLength(list);
}
- if (growable) return list;
- return makeListFixedLength(list);
}
@patch
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index 07d6afb5..83f12ca 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -908,3 +908,31 @@
@patch
factory LinkedHashSet.identity() => new _CompactLinkedIdentityHashSet<E>();
}
+
+@patch
+abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
+ // We override _splayMin and _splayMax to optimize type-checks.
+ @patch
+ Node _splayMin(Node node) {
+ Node current = node;
+ while (current.left != null) {
+ Node left = internal.unsafeCast<Node>(current.left);
+ current.left = left.right;
+ left.right = current;
+ current = left;
+ }
+ return current;
+ }
+
+ @patch
+ Node _splayMax(Node node) {
+ Node current = node;
+ while (current.right != null) {
+ Node right = internal.unsafeCast<Node>(current.right);
+ current.right = right.left;
+ right.left = current;
+ current = right;
+ }
+ return current;
+ }
+}
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 20ddf7a..8123b0f 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -433,7 +433,8 @@
final int _checkSum;
E current;
- _CompactIterator(table, this._data, this._len, this._offset, this._step)
+ _CompactIterator(
+ _HashBase table, this._data, this._len, this._offset, this._step)
: _table = table,
_checkSum = table._checkSum;
@@ -445,7 +446,7 @@
_offset += _step;
} while (_offset < _len && _HashBase._isDeleted(_data, _data[_offset]));
if (_offset < _len) {
- current = _data[_offset];
+ current = internal.unsafeCast<E>(_data[_offset]);
return true;
} else {
current = null;
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 1b0f849..7b1876d6 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -24,7 +24,8 @@
is64Bit,
makeFixedListUnmodifiable,
makeListFixedLength,
- patch;
+ patch,
+ unsafeCast;
import "dart:async" show Completer, Future, Timer;
@@ -116,8 +117,8 @@
Iterator<T> get iterator {
// Note: _Closure._clone returns _Closure which is not related to
// _SyncGeneratorCallback, which means we need explicit cast.
- return new _SyncIterator<T>(
- (_moveNextFn as _Closure)._clone() as _SyncGeneratorCallback<T>);
+ return new _SyncIterator<T>(unsafeCast<_SyncGeneratorCallback<T>>(
+ unsafeCast<_Closure>(_moveNextFn)._clone()));
}
}
diff --git a/runtime/tools/create_snapshot_file.py b/runtime/tools/create_snapshot_file.py
index d862a45..19ea870 100755
--- a/runtime/tools/create_snapshot_file.py
+++ b/runtime/tools/create_snapshot_file.py
@@ -12,7 +12,7 @@
import string
import subprocess
import sys
-import google3.third_party.dart_lang.v2_1_1_dev_0_1.runtime.tools.utils as utils
+import utils
HOST_OS = utils.GuessOS()
diff --git a/runtime/tools/layering_check.py b/runtime/tools/layering_check.py
new file mode 100755
index 0000000..50a9b25
--- /dev/null
+++ b/runtime/tools/layering_check.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2019, 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.
+
+# Simple tool for verifying that sources from one layer do not reference
+# sources from another layer.
+#
+# Currently it only checks that core runtime headers RUNTIME_LAYER_HEADERS
+# are not included into any sources listed in SHOULD_NOT_DEPEND_ON_RUNTIME.
+
+import glob
+import os
+import re
+import sys
+
+INCLUDE_DIRECTIVE_RE = re.compile(r'^#include "(.*)"')
+
+RUNTIME_LAYER_HEADERS = [
+ 'runtime/vm/isolate.h',
+ 'runtime/vm/object.h',
+ 'runtime/vm/raw_object.h',
+ 'runtime/vm/thread.h',
+]
+
+SHOULD_NOT_DEPEND_ON_RUNTIME = [
+ 'runtime/vm/allocation.h',
+ 'runtime/vm/growable_array.h',
+]
+
+class LayeringChecker(object):
+ def __init__(self, root):
+ self.root = root
+ self.worklist = set()
+ # Mapping from header to a set of files it is included into.
+ self.included_into = dict()
+ # Set of files that were parsed to avoid double parsing.
+ self.loaded = set()
+ # Mapping from headers to their layer.
+ self.file_layers = {file: 'runtime' for file in RUNTIME_LAYER_HEADERS}
+
+ def Check(self):
+ self.AddAllSourcesToWorklist(os.path.join(self.root, 'runtime/vm'))
+ self.BuildIncludesGraph()
+ errors = self.PropagateLayers()
+ errors += self.CheckNotInRuntime(SHOULD_NOT_DEPEND_ON_RUNTIME)
+ return errors
+
+ def CheckNotInRuntime(self, files):
+ """Check that given files do not depend on runtime layer."""
+ errors = []
+ for file in files:
+ if not os.path.exists(os.path.join(self.root, file)):
+ errors.append('File %s does not exist.' % (file))
+ if self.file_layers.get(file) is not None:
+ errors.append(
+ 'LAYERING ERROR: %s includes object.h or raw_object.h' % (file))
+ return errors
+
+ def BuildIncludesGraph(self):
+ while self.worklist:
+ file = self.worklist.pop()
+ deps = self.ExtractIncludes(file)
+ self.loaded.add(file)
+ for d in deps:
+ if d not in self.included_into:
+ self.included_into[d] = set()
+ self.included_into[d].add(file)
+ if d not in self.loaded:
+ self.worklist.add(d)
+
+ def PropagateLayers(self):
+ """Propagate layering information through include graph.
+
+ If A is in layer L and A is included into B then B is in layer L.
+ """
+ errors = []
+ self.worklist = set(self.file_layers.keys())
+ while self.worklist:
+ file = self.worklist.pop()
+ if file not in self.included_into:
+ continue
+ file_layer = self.file_layers[file]
+ for tgt in self.included_into[file]:
+ if tgt in self.file_layers:
+ if self.file_layers[tgt] != file_layer:
+ errors.add('Layer mismatch: %s (%s) is included into %s (%s)' % (
+ file, file_layer, tgt, self.file_layers[tgt]))
+ self.file_layers[tgt] = file_layer
+ self.worklist.add(tgt)
+ return errors
+
+ def AddAllSourcesToWorklist(self, dir):
+ """Add all *.cc and *.h files from dir recursively into worklist."""
+ for file in os.listdir(dir):
+ path = os.path.join(dir, file)
+ if os.path.isdir(path):
+ self.AddAllSourcesToWorklist(path)
+ elif path.endswith('.cc') or path.endswith('.h'):
+ self.worklist.add(os.path.relpath(path, self.root))
+
+ def ExtractIncludes(self, file):
+ """Extract the list of includes from the given file."""
+ deps = set()
+ with open(os.path.join(self.root, file)) as file:
+ for line in file:
+ if line.startswith('namespace dart {'):
+ break
+
+ m = INCLUDE_DIRECTIVE_RE.match(line)
+ if m is not None:
+ header = os.path.join('runtime', m.group(1))
+ if os.path.isfile(os.path.join(self.root,header)):
+ deps.add(header)
+ return deps
+
+def DoCheck(sdk_root):
+ """Run layering check at the given root folder."""
+ return LayeringChecker(sdk_root).Check()
+
+if __name__ == '__main__':
+ errors = DoCheck('.')
+ print '\n'.join(errors)
+ if errors:
+ sys.exit(-1)
+
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index b1a7e93..aa36221 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -37,16 +37,11 @@
#if defined(DEBUG)
if (thread_ != NULL) {
ASSERT(Thread::Current() == thread_);
- BaseIsolate::AssertCurrent(reinterpret_cast<BaseIsolate*>(isolate()));
}
#endif
}
-Isolate* StackResource::isolate() const {
- return thread_ == NULL ? NULL : thread_->isolate();
-}
-
-void StackResource::Init(Thread* thread) {
+void StackResource::Init(ThreadState* thread) {
// We can only have longjumps and exceptions when there is a current
// thread and isolate. If there is no current thread, we don't need to
// protect this case.
@@ -60,7 +55,7 @@
}
}
-void StackResource::UnwindAbove(Thread* thread, StackResource* new_top) {
+void StackResource::UnwindAbove(ThreadState* thread, StackResource* new_top) {
StackResource* current_resource = thread->top_resource();
while (current_resource != new_top) {
current_resource->~StackResource();
@@ -68,16 +63,4 @@
}
}
-#if defined(DEBUG)
-NoSafepointScope::NoSafepointScope(Thread* current_thread)
- : StackResource(current_thread != nullptr ? current_thread
- : Thread::Current()) {
- thread()->IncrementNoSafepointScopeDepth();
-}
-
-NoSafepointScope::~NoSafepointScope() {
- thread()->DecrementNoSafepointScopeDepth();
-}
-#endif // defined(DEBUG)
-
} // namespace dart
diff --git a/runtime/vm/allocation.h b/runtime/vm/allocation.h
index b9af2f9..420b85e 100644
--- a/runtime/vm/allocation.h
+++ b/runtime/vm/allocation.h
@@ -13,8 +13,7 @@
namespace dart {
// Forward declarations.
-class Isolate;
-class Thread;
+class ThreadState;
// Stack resources subclass from this base class. The VM will ensure that the
// destructors of these objects are called before the stack is unwound past the
@@ -23,27 +22,24 @@
// to a stack frame above the frame where these objects were allocated.
class StackResource {
public:
- explicit StackResource(Thread* thread) : thread_(NULL), previous_(NULL) {
+ explicit StackResource(ThreadState* thread) : thread_(NULL), previous_(NULL) {
Init(thread);
}
virtual ~StackResource();
- // Convenient access to the isolate of the thread of this resource.
- Isolate* isolate() const;
-
// The thread that owns this resource.
- Thread* thread() const { return thread_; }
+ ThreadState* thread() const { return thread_; }
// Destroy stack resources of thread until top exit frame.
- static void Unwind(Thread* thread) { UnwindAbove(thread, NULL); }
+ static void Unwind(ThreadState* thread) { UnwindAbove(thread, NULL); }
// Destroy stack resources of thread above new_top, exclusive.
- static void UnwindAbove(Thread* thread, StackResource* new_top);
+ static void UnwindAbove(ThreadState* thread, StackResource* new_top);
private:
- void Init(Thread* thread);
+ void Init(ThreadState* thread);
- Thread* thread_;
+ ThreadState* thread_;
StackResource* previous_;
DISALLOW_ALLOCATION();
@@ -77,27 +73,6 @@
DISALLOW_COPY_AND_ASSIGN(ZoneAllocated);
};
-// Within a NoSafepointScope, the thread must not reach any safepoint. Used
-// around code that manipulates raw object pointers directly without handles.
-#if defined(DEBUG)
-class NoSafepointScope : public StackResource {
- public:
- explicit NoSafepointScope(Thread* thread = nullptr);
- ~NoSafepointScope();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
-};
-#else // defined(DEBUG)
-class NoSafepointScope : public ValueObject {
- public:
- explicit NoSafepointScope(Thread* thread = nullptr) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
-};
-#endif // defined(DEBUG)
-
} // namespace dart
#endif // RUNTIME_VM_ALLOCATION_H_
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 00a16a7..572175d 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1155,6 +1155,9 @@
const Class& super = Class::Handle(cls.SuperClass());
if (!super.IsNull()) {
FinalizeClass(super);
+ if (cls.is_finalized()) {
+ return;
+ }
}
// Mark as loaded and finalized.
cls.Finalize();
@@ -1181,154 +1184,17 @@
}
}
-static void AddRelatedClassesToList(
- const Class& cls,
- GrowableHandlePtrArray<const Class>* load_class_list,
- GrowableHandlePtrArray<const Class>* load_patchclass_list) {
- Zone* zone = Thread::Current()->zone();
- Class& load_class = Class::Handle(zone);
- AbstractType& interface_type = Type::Handle(zone);
- Array& interfaces = Array::Handle(zone);
-
- // Add all the interfaces implemented by the class that have not been
- // already loaded to the load list. Mark the interface as loading so that
- // we don't recursively add it back into the list.
- interfaces ^= cls.interfaces();
- for (intptr_t i = 0; i < interfaces.Length(); i++) {
- interface_type ^= interfaces.At(i);
- load_class ^= interface_type.type_class();
- if (!load_class.is_finalized() &&
- !load_class.is_marked_for_lazy_loading()) {
- load_class_list->Add(load_class);
- load_class.set_is_marked_for_lazy_loading();
- }
- }
-
- // Walk up the super_class chain and add these classes to the list if they
- // have not been already added to the load class list. Mark the class as
- // loading so that we don't recursively add it back into the list.
- load_class ^= cls.SuperClass();
- while (!load_class.IsNull()) {
- if (!load_class.is_finalized() &&
- !load_class.is_marked_for_lazy_loading()) {
- load_class_list->Add(load_class);
- load_class.set_is_marked_for_lazy_loading();
- }
- load_class ^= load_class.SuperClass();
- }
-
- // Add patch classes if they exist to the load patchclass list if they have
- // not already been loaded and patched. Mark the class as loading so that
- // we don't recursively add it back into the list.
- load_class ^= cls.GetPatchClass();
- if (!load_class.IsNull()) {
- if (!load_class.is_finalized() &&
- !load_class.is_marked_for_lazy_loading()) {
- load_patchclass_list->Add(load_class);
- load_class.set_is_marked_for_lazy_loading();
- }
- }
-}
-
RawError* ClassFinalizer::LoadClassMembers(const Class& cls) {
ASSERT(Thread::Current()->IsMutatorThread());
// If class is a top level class it is already loaded.
if (cls.IsTopLevel()) {
return Error::null();
}
- // If the class is already marked for loading return immediately.
- if (cls.is_marked_for_lazy_loading()) {
- return Error::null();
- }
- // If the class is a typedef class there is no need to try and
- // compile it. Just finalize it directly.
- if (cls.IsTypedefClass()) {
-#if defined(DEBUG)
- const Class& closure_cls =
- Class::Handle(Isolate::Current()->object_store()->closure_class());
- ASSERT(closure_cls.is_finalized());
-#endif
- LongJumpScope jump;
- if (setjmp(*jump.Set()) == 0) {
- ClassFinalizer::FinalizeClass(cls);
- return Error::null();
- } else {
- return Thread::Current()->StealStickyError();
- }
- }
-
- Thread* const thread = Thread::Current();
- StackZone zone(thread);
-#if !defined(PRODUCT)
- VMTagScope tagScope(thread, VMTag::kClassLoadingTagId);
- TimelineDurationScope tds(thread, Timeline::GetCompilerStream(),
- "ClassLoading");
- if (tds.enabled()) {
- tds.SetNumArguments(1);
- tds.CopyArgument(0, "class", cls.ToCString());
- }
-#endif // !defined(PRODUCT)
-
- // We remember all the classes that are being lazy loaded in these lists.
- // This also allows us to reset the marked_for_loading state in case we see
- // an error.
- GrowableHandlePtrArray<const Class> load_class_list(thread->zone(), 4);
- GrowableHandlePtrArray<const Class> load_patchclass_list(thread->zone(), 4);
-
- // Load the class and all the interfaces it implements and super classes.
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
- if (FLAG_trace_class_finalization) {
- THR_Print("Lazy Loading Class '%s'\n", cls.ToCString());
- }
-
- // Add the primary class which needs to be load to the load list.
- // Mark the class as loading so that we don't recursively add the same
- // class back into the list.
- load_class_list.Add(cls);
- cls.set_is_marked_for_lazy_loading();
-
- // Add all super classes, interface classes and patch class if one
- // exists to the corresponding lists.
- // NOTE: The load_class_list array keeps growing as more classes are added
- // to it by AddRelatedClassesToList. It is not OK to hoist
- // load_class_list.Length() into a local variable and iterate using the
- // local variable.
- for (intptr_t i = 0; i < load_class_list.length(); i++) {
- AddRelatedClassesToList(load_class_list.At(i), &load_class_list,
- &load_patchclass_list);
- }
-
- // Finish lazy loading of these classes and finialize them.
- for (intptr_t i = (load_class_list.length() - 1); i >= 0; i--) {
- const Class& load_class = load_class_list.At(i);
- ASSERT(!load_class.IsNull());
- ClassFinalizer::FinalizeClass(load_class);
- load_class.reset_is_marked_for_lazy_loading();
- }
- for (intptr_t i = (load_patchclass_list.length() - 1); i >= 0; i--) {
- const Class& load_class = load_patchclass_list.At(i);
- ASSERT(!load_class.IsNull());
- ClassFinalizer::FinalizeClass(load_class);
- load_class.reset_is_marked_for_lazy_loading();
- }
-
+ ClassFinalizer::FinalizeClass(cls);
return Error::null();
} else {
- // Reset the marked for parsing flags.
- for (intptr_t i = 0; i < load_class_list.length(); i++) {
- const Class& load_class = load_class_list.At(i);
- if (load_class.is_marked_for_lazy_loading()) {
- load_class.reset_is_marked_for_lazy_loading();
- }
- }
- for (intptr_t i = 0; i < load_patchclass_list.length(); i++) {
- const Class& load_class = load_patchclass_list.At(i);
- if (load_class.is_marked_for_lazy_loading()) {
- load_class.reset_is_marked_for_lazy_loading();
- }
- }
-
return Thread::Current()->StealStickyError();
}
}
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 27536c5..779e9fe 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -4202,7 +4202,7 @@
ImageWriter* image_writer,
bool vm,
V8SnapshotProfileWriter* profile_writer)
- : StackResource(thread),
+ : ThreadStackResource(thread),
heap_(thread->isolate()->heap()),
zone_(thread->zone()),
kind_(kind),
@@ -4616,7 +4616,7 @@
intptr_t code_order_length = 0;
#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) && \
!defined(TARGET_ARCH_DBC)
- if (Snapshot::IncludesCode(kind_)) {
+ if (kind_ == Snapshot::kFullAOT) {
auto code_objects =
static_cast<CodeSerializationCluster*>(clusters_by_cid_[kCodeCid])
->discovered_objects();
@@ -4866,7 +4866,7 @@
const uint8_t* instructions_buffer,
const uint8_t* shared_data_buffer,
const uint8_t* shared_instructions_buffer)
- : StackResource(thread),
+ : ThreadStackResource(thread),
heap_(thread->isolate()->heap()),
zone_(thread->zone()),
kind_(kind),
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index f1eb0c9..420742d 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -128,7 +128,7 @@
typedef DirectChainedHashMap<SmiObjectIdPairTrait> SmiObjectIdMap;
-class Serializer : public StackResource {
+class Serializer : public ThreadStackResource {
public:
Serializer(Thread* thread,
Snapshot::Kind kind,
@@ -431,7 +431,7 @@
Serializer* serializer_;
};
-class Deserializer : public StackResource {
+class Deserializer : public ThreadStackResource {
public:
Deserializer(Thread* thread,
Snapshot::Kind kind,
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index a05f94f..2a9f62d 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -4,12 +4,14 @@
#include "vm/compilation_trace.h"
+#include "vm/compiler/jit/compiler.h"
#include "vm/globals.h"
#include "vm/log.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/symbols.h"
+#include "vm/version.h"
namespace dart {
@@ -303,6 +305,557 @@
return Compiler::CompileFunction(thread_, function);
}
+TypeFeedbackSaver::TypeFeedbackSaver(WriteStream* stream)
+ : stream_(stream),
+ cls_(Class::Handle()),
+ lib_(Library::Handle()),
+ str_(String::Handle()),
+ fields_(Array::Handle()),
+ field_(Field::Handle()),
+ code_(Code::Handle()),
+ call_sites_(Array::Handle()),
+ call_site_(ICData::Handle()) {}
+
+void TypeFeedbackSaver::WriteHeader() {
+ const char* expected_version = Version::SnapshotString();
+ ASSERT(expected_version != NULL);
+ const intptr_t version_len = strlen(expected_version);
+ stream_->WriteBytes(reinterpret_cast<const uint8_t*>(expected_version),
+ version_len);
+}
+
+void TypeFeedbackSaver::SaveClasses() {
+ ClassTable* table = Isolate::Current()->class_table();
+
+ intptr_t num_cids = table->NumCids();
+ WriteInt(num_cids);
+
+ for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
+ cls_ = table->At(cid);
+ WriteClassByName(cls_);
+ }
+}
+
+void TypeFeedbackSaver::SaveFields() {
+ ClassTable* table = Isolate::Current()->class_table();
+ intptr_t num_cids = table->NumCids();
+ for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
+ cls_ = table->At(cid);
+ WriteClassByName(cls_);
+
+ fields_ = cls_.fields();
+ WriteInt(fields_.Length());
+ for (intptr_t i = 0; i < fields_.Length(); i++) {
+ field_ ^= fields_.At(i);
+
+ str_ = field_.name();
+ str_ = String::RemovePrivateKey(str_);
+ WriteString(str_);
+
+ WriteInt(field_.guarded_cid());
+ WriteInt(field_.is_nullable());
+ }
+ }
+}
+
+void TypeFeedbackSaver::Visit(const Function& function) {
+ if (!function.HasCode()) {
+ return; // Not compiled.
+ }
+
+ cls_ = function.Owner();
+ WriteClassByName(cls_);
+
+ str_ = function.name();
+ str_ = String::RemovePrivateKey(str_);
+ WriteString(str_);
+
+ WriteInt(function.kind());
+ WriteInt(function.token_pos().value());
+
+ code_ = function.CurrentCode();
+ intptr_t usage = function.usage_counter();
+ if (usage < 0) {
+ // Usage is set to INT_MIN while in the background compilation queue ...
+ usage = (usage - INT_MIN) + FLAG_optimization_counter_threshold;
+ } else if (code_.is_optimized()) {
+ // ... and set to 0 when an optimizing compile completes.
+ usage = usage + FLAG_optimization_counter_threshold;
+ }
+ WriteInt(usage);
+
+ WriteInt(function.inlining_depth());
+
+ call_sites_ = function.ic_data_array();
+ if (call_sites_.IsNull()) {
+ call_sites_ = Object::empty_array().raw(); // Remove edge case.
+ }
+
+ // First element is edge counters.
+ WriteInt(call_sites_.Length() - 1);
+ for (intptr_t i = 1; i < call_sites_.Length(); i++) {
+ call_site_ ^= call_sites_.At(i);
+
+ WriteInt(call_site_.deopt_id());
+ WriteInt(call_site_.rebind_rule());
+
+ str_ = call_site_.target_name();
+ str_ = String::RemovePrivateKey(str_);
+ WriteString(str_);
+
+ intptr_t num_checked_arguments = call_site_.NumArgsTested();
+ WriteInt(num_checked_arguments);
+
+ intptr_t num_entries = call_site_.NumberOfChecks();
+ WriteInt(num_entries);
+
+ for (intptr_t entry_index = 0; entry_index < num_entries; entry_index++) {
+ WriteInt(call_site_.GetCountAt(entry_index));
+
+ for (intptr_t argument_index = 0; argument_index < num_checked_arguments;
+ argument_index++) {
+ WriteInt(call_site_.GetClassIdAt(entry_index, argument_index));
+ }
+ }
+ }
+}
+
+void TypeFeedbackSaver::WriteClassByName(const Class& cls) {
+ lib_ = cls.library();
+
+ str_ = lib_.url();
+ WriteString(str_);
+
+ str_ = cls_.Name();
+ str_ = String::RemovePrivateKey(str_);
+ WriteString(str_);
+}
+
+void TypeFeedbackSaver::WriteString(const String& value) {
+ const char* cstr = value.ToCString();
+ intptr_t len = strlen(cstr);
+ stream_->WriteUnsigned(len);
+ stream_->WriteBytes(cstr, len);
+}
+
+TypeFeedbackLoader::TypeFeedbackLoader(Thread* thread)
+ : thread_(thread),
+ zone_(thread->zone()),
+ stream_(nullptr),
+ uri_(String::Handle(zone_)),
+ lib_(Library::Handle(zone_)),
+ cls_name_(String::Handle(zone_)),
+ cls_(Class::Handle(zone_)),
+ field_name_(String::Handle(zone_)),
+ fields_(Array::Handle(zone_)),
+ field_(Field::Handle(zone_)),
+ func_name_(String::Handle(zone_)),
+ func_(Function::Handle(zone_)),
+ call_sites_(Array::Handle(zone_)),
+ call_site_(ICData::Handle(zone_)),
+ target_name_(String::Handle(zone_)),
+ target_(Function::Handle(zone_)),
+ args_desc_(Array::Handle(zone_)),
+ functions_to_compile_(
+ GrowableObjectArray::Handle(zone_, GrowableObjectArray::New())),
+ error_(Error::Handle(zone_)) {}
+
+RawObject* TypeFeedbackLoader::LoadFeedback(ReadStream* stream) {
+ stream_ = stream;
+
+ error_ = CheckHeader();
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+
+ error_ = LoadClasses();
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+
+ error_ = LoadFields();
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+
+ while (stream_->PendingBytes() > 0) {
+ error_ = LoadFunction();
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ }
+
+ while (functions_to_compile_.Length() > 0) {
+ func_ ^= functions_to_compile_.RemoveLast();
+
+ if (Compiler::CanOptimizeFunction(thread_, func_) &&
+ (func_.usage_counter() >= FLAG_optimization_counter_threshold)) {
+ error_ = Compiler::CompileOptimizedFunction(thread_, func_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ }
+ }
+
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Done loading feedback\n");
+ }
+
+ return Error::null();
+}
+
+RawObject* TypeFeedbackLoader::CheckHeader() {
+ const char* expected_version = Version::SnapshotString();
+ ASSERT(expected_version != NULL);
+ const intptr_t version_len = strlen(expected_version);
+ if (stream_->PendingBytes() < version_len) {
+ const intptr_t kMessageBufferSize = 128;
+ char message_buffer[kMessageBufferSize];
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "No snapshot version found, expected '%s'",
+ expected_version);
+ const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
+ return ApiError::New(msg, Heap::kOld);
+ }
+
+ const char* version =
+ reinterpret_cast<const char*>(stream_->AddressOfCurrentPosition());
+ ASSERT(version != NULL);
+ if (strncmp(version, expected_version, version_len)) {
+ const intptr_t kMessageBufferSize = 256;
+ char message_buffer[kMessageBufferSize];
+ char* actual_version = Utils::StrNDup(version, version_len);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "Wrong snapshot version, expected '%s' found '%s'",
+ expected_version, actual_version);
+ free(actual_version);
+ const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
+ return ApiError::New(msg, Heap::kOld);
+ }
+ stream_->Advance(version_len);
+
+ return Error::null();
+}
+
+RawObject* TypeFeedbackLoader::LoadClasses() {
+ num_cids_ = ReadInt();
+
+ cid_map_ = new intptr_t[num_cids_];
+ for (intptr_t cid = 0; cid < num_cids_; cid++) {
+ cid_map_[cid] = kIllegalCid;
+ }
+ for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) {
+ cid_map_[cid] = cid;
+ }
+
+ for (intptr_t cid = kNumPredefinedCids; cid < num_cids_; cid++) {
+ cls_ = ReadClassByName();
+ if (!cls_.IsNull()) {
+ cid_map_[cid] = cls_.id();
+ }
+ }
+
+ return Error::null();
+}
+
+RawObject* TypeFeedbackLoader::LoadFields() {
+ for (intptr_t cid = kNumPredefinedCids; cid < num_cids_; cid++) {
+ cls_ = ReadClassByName();
+ bool skip = cls_.IsNull();
+
+ intptr_t num_fields = ReadInt();
+ if (!skip && (num_fields > 0)) {
+ error_ = cls_.EnsureIsFinalized(thread_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ fields_ = cls_.fields();
+ }
+
+ for (intptr_t i = 0; i < num_fields; i++) {
+ field_name_ = ReadString();
+ intptr_t guarded_cid = cid_map_[ReadInt()];
+ intptr_t is_nullable = ReadInt();
+
+ if (skip) {
+ continue;
+ }
+
+ if (i >= fields_.Length()) {
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Missing field %s\n", field_name_.ToCString());
+ }
+ continue;
+ }
+
+ field_ ^= fields_.At(i);
+ if (!String::EqualsIgnoringPrivateKey(String::Handle(field_.name()),
+ field_name_)) {
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Missing field %s\n", field_name_.ToCString());
+ }
+ continue;
+ }
+
+ if (guarded_cid == kIllegalCid) {
+ // Guarded CID from feedback is not in current program: assume the field
+ // will become polymorphic.
+ field_.set_guarded_cid(kDynamicCid);
+ field_.set_is_nullable(true);
+ } else if ((field_.guarded_cid() != kIllegalCid) &&
+ (field_.guarded_cid() == guarded_cid)) {
+ // Guarded CID from feedback is different from initialized guarded CID
+ // in the current program: assume the field will become polymorphic.
+ field_.set_guarded_cid(kDynamicCid);
+ field_.set_is_nullable(true);
+ } else {
+ field_.set_guarded_cid(guarded_cid);
+ field_.set_is_nullable(is_nullable || field_.is_nullable());
+ }
+
+ // TODO(rmacnak): Merge other field type feedback.
+ field_.set_guarded_list_length(Field::kNoFixedLength);
+ field_.set_guarded_list_length_in_object_offset(
+ Field::kUnknownLengthOffset);
+ field_.set_static_type_exactness_state(
+ StaticTypeExactnessState::NotTracking());
+ field_.DeoptimizeDependentCode();
+ }
+ }
+
+ return Error::null();
+}
+
+RawObject* TypeFeedbackLoader::LoadFunction() {
+ bool skip = false;
+
+ cls_ = ReadClassByName();
+ if (!cls_.IsNull()) {
+ error_ = cls_.EnsureIsFinalized(thread_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ } else {
+ skip = true;
+ }
+
+ func_name_ = ReadString(); // Without private mangling.
+ RawFunction::Kind kind = static_cast<RawFunction::Kind>(ReadInt());
+ intptr_t token_pos = ReadInt();
+ intptr_t usage = ReadInt();
+ intptr_t inlining_depth = ReadInt();
+ intptr_t num_call_sites = ReadInt();
+
+ if (!skip) {
+ func_ = FindFunction(kind, token_pos);
+ if (func_.IsNull()) {
+ skip = true;
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Missing function %s %s\n", func_name_.ToCString(),
+ Function::KindToCString(kind));
+ }
+ }
+ }
+
+ if (!skip) {
+ error_ = Compiler::CompileFunction(thread_, func_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ call_sites_ = func_.ic_data_array();
+ if (call_sites_.IsNull()) {
+ call_sites_ = Object::empty_array().raw(); // Remove edge case.
+ }
+ if (call_sites_.Length() != num_call_sites + 1) {
+ skip = true;
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Mismatched call site count %s %" Pd " %" Pd "\n",
+ func_name_.ToCString(), call_sites_.Length(), num_call_sites);
+ }
+ }
+ }
+
+ // First element is edge counters.
+ for (intptr_t i = 1; i <= num_call_sites; i++) {
+ intptr_t deopt_id = ReadInt();
+ intptr_t rebind_rule = ReadInt();
+ target_name_ = ReadString();
+ intptr_t num_checked_arguments = ReadInt();
+ intptr_t num_entries = ReadInt();
+
+ if (!skip) {
+ call_site_ ^= call_sites_.At(i);
+ if ((call_site_.deopt_id() != deopt_id) ||
+ (call_site_.rebind_rule() != rebind_rule) ||
+ (call_site_.NumArgsTested() != num_checked_arguments)) {
+ skip = true;
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Mismatched call site %s\n", call_site_.ToCString());
+ }
+ }
+ }
+
+ for (intptr_t entry_index = 0; entry_index < num_entries; entry_index++) {
+ intptr_t entry_usage = ReadInt();
+ bool skip_entry = skip;
+ GrowableArray<intptr_t> cids(num_checked_arguments);
+
+ for (intptr_t argument_index = 0; argument_index < num_checked_arguments;
+ argument_index++) {
+ intptr_t cid = cid_map_[ReadInt()];
+ cids.Add(cid);
+ if (cid == kIllegalCid) {
+ // Alternative: switch to a sentinel value such as kDynamicCid and
+ // have the optimizer generate a megamorphic call.
+ skip_entry = true;
+ }
+ }
+
+ if (skip_entry) {
+ continue;
+ }
+
+ intptr_t reuse_index = call_site_.FindCheck(cids);
+ if (reuse_index == -1) {
+ cls_ = thread_->isolate()->class_table()->At(cids[0]);
+ // Use target name and args descriptor from the current program
+ // instead of saved feedback to get the correct private mangling and
+ // ensure no arity mismatch crashes.
+ target_name_ = call_site_.target_name();
+ args_desc_ = call_site_.arguments_descriptor();
+ target_ = Resolver::ResolveDynamicForReceiverClass(
+ cls_, target_name_, ArgumentsDescriptor(args_desc_));
+ if (!target_.IsNull()) {
+ if (num_checked_arguments == 1) {
+ call_site_.AddReceiverCheck(cids[0], target_, entry_usage);
+ } else {
+ call_site_.AddCheck(cids, target_, entry_usage);
+ }
+ }
+ } else {
+ call_site_.IncrementCountAt(reuse_index, entry_usage);
+ }
+ }
+ }
+
+ if (!skip) {
+ func_.set_usage_counter(usage);
+ func_.set_inlining_depth(inlining_depth);
+
+ // Delay compilation until all feedback is loaded so feedback is available
+ // for inlined functions.
+ functions_to_compile_.Add(func_);
+ }
+
+ return Error::null();
+}
+
+RawFunction* TypeFeedbackLoader::FindFunction(RawFunction::Kind kind,
+ intptr_t token_pos) {
+ if (cls_name_.Equals(Symbols::TopLevel())) {
+ func_ = lib_.LookupFunctionAllowPrivate(func_name_);
+ } else {
+ func_ = cls_.LookupFunctionAllowPrivate(func_name_);
+ }
+
+ if (!func_.IsNull()) {
+ // Found regular method.
+ } else if (kind == RawFunction::kMethodExtractor) {
+ ASSERT(Field::IsGetterName(func_name_));
+ // Without private mangling:
+ String& name = String::Handle(zone_, Field::NameFromGetter(func_name_));
+ func_ = cls_.LookupFunctionAllowPrivate(name);
+ if (!func_.IsNull() && func_.IsDynamicFunction()) {
+ name = func_.name(); // With private mangling.
+ name = Field::GetterName(name);
+ func_ = func_.GetMethodExtractor(name);
+ } else {
+ func_ = Function::null();
+ }
+ } else if (kind == RawFunction::kDynamicInvocationForwarder) {
+ // Without private mangling:
+ String& name = String::Handle(
+ zone_, Function::DemangleDynamicInvocationForwarderName(func_name_));
+ func_ = cls_.LookupFunctionAllowPrivate(name);
+ if (!func_.IsNull() && func_.IsDynamicFunction()) {
+ name = func_.name(); // With private mangling.
+ name = Function::CreateDynamicInvocationForwarderName(name);
+ func_ = func_.CreateDynamicInvocationForwarder(name);
+ } else {
+ func_ = Function::null();
+ }
+ } else if (kind == RawFunction::kClosureFunction) {
+ // Note this lookup relies on parent functions appearing before child
+ // functions in the serialized feedback, so the parent will have already
+ // been unoptimized compilated and the child function created and added to
+ // ObjectStore::closure_functions_.
+ const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle(
+ zone_, thread_->isolate()->object_store()->closure_functions());
+ bool found = false;
+ for (intptr_t i = 0; i < closure_functions.Length(); i++) {
+ func_ ^= closure_functions.At(i);
+ if ((func_.Owner() == cls_.raw()) &&
+ (func_.token_pos().value() == token_pos)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ func_ = Function::null();
+ }
+ } else {
+ // This leaves unhandled:
+ // - kInvokeFieldDispatcher (how to get a valid args descriptor?)
+ // - static field getters
+ // - static field initializers (not retained by the field object)
+ }
+
+ if (!func_.IsNull()) {
+ if (kind == RawFunction::kImplicitClosureFunction) {
+ func_ = func_.ImplicitClosureFunction();
+ }
+ if (func_.is_abstract() || (func_.kind() != kind)) {
+ func_ = Function::null();
+ }
+ }
+
+ return func_.raw();
+}
+
+RawClass* TypeFeedbackLoader::ReadClassByName() {
+ uri_ = ReadString();
+ cls_name_ = ReadString();
+
+ lib_ = Library::LookupLibrary(thread_, uri_);
+ if (lib_.IsNull()) {
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Missing library %s\n", uri_.ToCString());
+ }
+ return Class::null();
+ }
+
+ if (cls_name_.Equals(Symbols::TopLevel())) {
+ cls_ = lib_.toplevel_class();
+ } else {
+ cls_ = lib_.SlowLookupClassAllowMultiPartPrivate(cls_name_);
+ if (cls_.IsNull()) {
+ if (FLAG_trace_compilation_trace) {
+ THR_Print("Missing class %s %s\n", uri_.ToCString(),
+ cls_name_.ToCString());
+ }
+ }
+ }
+ return cls_.raw();
+}
+
+RawString* TypeFeedbackLoader::ReadString() {
+ intptr_t len = stream_->ReadUnsigned();
+ const char* cstr =
+ reinterpret_cast<const char*>(stream_->AddressOfCurrentPosition());
+ stream_->Advance(len);
+ return Symbols::New(thread_, cstr, len);
+}
+
#endif // !defined(DART_PRECOMPILED_RUNTIME)
} // namespace dart
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index 7e489d9..106dbbe 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -6,7 +6,6 @@
#define RUNTIME_VM_COMPILATION_TRACE_H_
#include "platform/assert.h"
-#include "vm/compiler/jit/compiler.h"
#include "vm/object.h"
#include "vm/program_visitor.h"
#include "vm/zone_text_buffer.h"
@@ -58,6 +57,71 @@
Object& error_;
};
+class TypeFeedbackSaver : public FunctionVisitor {
+ public:
+ explicit TypeFeedbackSaver(WriteStream* stream);
+
+ void WriteHeader();
+ void SaveClasses();
+ void SaveFields();
+ void Visit(const Function& function);
+
+ private:
+ void WriteClassByName(const Class& cls);
+ void WriteString(const String& value);
+ void WriteInt(intptr_t value) { stream_->Write(static_cast<int32_t>(value)); }
+
+ WriteStream* const stream_;
+ Class& cls_;
+ Library& lib_;
+ String& str_;
+ Array& fields_;
+ Field& field_;
+ Code& code_;
+ Array& call_sites_;
+ ICData& call_site_;
+};
+
+class TypeFeedbackLoader : public ValueObject {
+ public:
+ explicit TypeFeedbackLoader(Thread* thread);
+
+ RawObject* LoadFeedback(ReadStream* stream);
+
+ private:
+ RawObject* CheckHeader();
+ RawObject* LoadClasses();
+ RawObject* LoadFields();
+ RawObject* LoadFunction();
+ RawFunction* FindFunction(RawFunction::Kind kind, intptr_t token_pos);
+
+ RawClass* ReadClassByName();
+ RawString* ReadString();
+ intptr_t ReadInt() { return stream_->Read<int32_t>(); }
+
+ Thread* thread_;
+ Zone* zone_;
+ ReadStream* stream_;
+ intptr_t num_cids_;
+ intptr_t* cid_map_;
+ String& uri_;
+ Library& lib_;
+ String& cls_name_;
+ Class& cls_;
+ String& field_name_;
+ Array& fields_;
+ Field& field_;
+ String& func_name_;
+ Function& func_;
+ Array& call_sites_;
+ ICData& call_site_;
+ String& target_name_;
+ Function& target_;
+ Array& args_desc_;
+ GrowableObjectArray& functions_to_compile_;
+ Object& error_;
+};
+
} // namespace dart
#endif // RUNTIME_VM_COMPILATION_TRACE_H_
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 1e6a8b3..9c0544a 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -415,6 +415,44 @@
TryOptimizeDoubleOperation(instr, op_kind);
}
+// Modulo against a constant power-of-two can be optimized into a mask.
+// x % y -> x & (y - 1)
+Definition* AotCallSpecializer::TryOptimizeMod(TemplateDartCall<0>* instr,
+ Token::Kind op_kind,
+ Value* left_value,
+ Value* right_value) {
+ if (!right_value->BindsToConstant()) {
+ return nullptr;
+ }
+
+ const Object& rhs = right_value->BoundConstant();
+ int64_t modulus = Utils::Abs(rhs.IsSmi() ? Smi::Cast(rhs).Value()
+ : Mint::Cast(rhs).value());
+ if (!Utils::IsPowerOfTwo(modulus) || !Smi::IsValid(modulus - 1)) {
+ return nullptr;
+ }
+
+ left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
+
+#if defined(TARGET_ARCH_ARM)
+ Definition* right_definition = new (Z) UnboxedConstantInstr(
+ Smi::ZoneHandle(Z, Smi::New(modulus - 1)), kUnboxedInt32);
+ InsertBefore(instr, right_definition, /*env=*/NULL, FlowGraph::kValue);
+ right_definition = new (Z)
+ UnboxedIntConverterInstr(kUnboxedInt32, kUnboxedInt64,
+ new (Z) Value(right_definition), DeoptId::kNone);
+ InsertBefore(instr, right_definition, /*env=*/NULL, FlowGraph::kValue);
+#else
+ Definition* right_definition = new (Z) UnboxedConstantInstr(
+ Smi::ZoneHandle(Z, Smi::New(modulus - 1)), kUnboxedInt64);
+ InsertBefore(instr, right_definition, /*env=*/NULL, FlowGraph::kValue);
+#endif
+ right_value = new (Z) Value(right_definition);
+ return new (Z)
+ BinaryInt64OpInstr(Token::kBIT_AND, left_value, right_value,
+ DeoptId::kNone, Instruction::kNotSpeculative);
+}
+
bool AotCallSpecializer::TryOptimizeIntegerOperation(TemplateDartCall<0>* instr,
Token::Kind op_kind) {
if (instr->type_args_len() != 0) {
@@ -500,10 +538,13 @@
}
break;
}
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
- // TODO(ajcbik): 32-bit archs too?
case Token::kMOD:
+ replacement = TryOptimizeMod(instr, op_kind, left_value, right_value);
+ if (replacement != nullptr) break;
case Token::kTRUNCDIV:
+#if !defined(TARGET_ARCH_X64) && !defined(TARGET_ARCH_ARM64)
+ // TODO(ajcbik): 32-bit archs too?
+ break;
#endif
case Token::kSHL:
case Token::kSHR:
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.h b/runtime/vm/compiler/aot/aot_call_specializer.h
index 404f2ba..c40aa8b 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.h
+++ b/runtime/vm/compiler/aot/aot_call_specializer.h
@@ -66,6 +66,11 @@
bool TryExpandCallThroughGetter(const Class& receiver_class,
InstanceCallInstr* call);
+ Definition* TryOptimizeMod(TemplateDartCall<0>* instr,
+ Token::Kind op_kind,
+ Value* left_value,
+ Value* right_value);
+
Precompiler* precompiler_;
bool has_unique_no_such_method_;
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index d250b51..1fc69d6 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1901,9 +1901,9 @@
}
void Precompiler::BindStaticCalls() {
- class BindStaticCallsVisitor : public FunctionVisitor {
+ class BindAOTStaticCallsVisitor : public FunctionVisitor {
public:
- explicit BindStaticCallsVisitor(Zone* zone)
+ explicit BindAOTStaticCallsVisitor(Zone* zone)
: code_(Code::Handle(zone)),
table_(Array::Handle(zone)),
kind_and_offset_(Smi::Handle(zone)),
@@ -1962,7 +1962,7 @@
Code& target_code_;
};
- BindStaticCallsVisitor visitor(Z);
+ BindAOTStaticCallsVisitor visitor(Z);
// We need both iterations to ensure we visit all the functions that might end
// up in the snapshot. The ProgramVisitor will miss closures from duplicated
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index 8d600d5..2ecb376 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -11,6 +11,7 @@
#include "vm/growable_array.h"
#include "vm/hash_map.h"
#include "vm/object.h"
+#include "vm/thread.h"
namespace dart {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 3d80504..c711b59 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -1142,7 +1142,9 @@
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(R4, arguments_descriptor);
} else {
- __ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
+ if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
+ __ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
+ }
}
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index a2400a3..408f0c7 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -1140,7 +1140,9 @@
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(R4, arguments_descriptor);
} else {
- __ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
+ if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
+ __ LoadImmediate(R4, 0); // GC safe smi zero because of stub.
+ }
}
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 7d0bb49..aa1c822 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -1120,7 +1120,9 @@
if (function.HasOptionalParameters() || function.IsGeneric()) {
__ LoadObject(R10, arguments_descriptor);
} else {
- __ xorl(R10, R10); // GC safe smi zero because of stub.
+ if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
+ __ xorl(R10, R10); // GC safe smi zero because of stub.
+ }
}
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 9d4fc4e..7020590 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -181,10 +181,10 @@
typedef MallocGrowableArray<CidRange> CidRangeVector;
-class HierarchyInfo : public StackResource {
+class HierarchyInfo : public ThreadStackResource {
public:
explicit HierarchyInfo(Thread* thread)
- : StackResource(thread),
+ : ThreadStackResource(thread),
cid_subtype_ranges_(NULL),
cid_subtype_ranges_abstract_(NULL),
cid_subclass_ranges_(NULL) {
@@ -7276,6 +7276,8 @@
// ArgumentError constructor), so it can lazily deopt.
virtual bool ComputeCanDeoptimize() const { return true; }
+ bool IsRedundant(const RangeBoundary& length);
+
// Give a name to the location/input indices.
enum { kLengthPos = 0, kIndexPos = 1 };
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 3bc424f..94c7519 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -2988,8 +2988,12 @@
bool opt) const {
const intptr_t kNumInputs = 0;
const intptr_t kNumTemps = 1;
- LocationSummary* summary = new (zone) LocationSummary(
- zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+ const bool using_shared_stub = UseSharedSlowPathStub(opt);
+ ASSERT((kReservedCpuRegisters & (1 << LR)) != 0);
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps,
+ using_shared_stub ? LocationSummary::kCallOnSharedSlowPath
+ : LocationSummary::kCallOnSlowPath);
summary->set_temp(0, Location::RequiresRegister());
return summary;
}
@@ -3030,7 +3034,6 @@
? Thread::stack_overflow_shared_with_fpu_regs_entry_point_offset()
: Thread::
stack_overflow_shared_without_fpu_regs_entry_point_offset();
- ASSERT(kReservedCpuRegisters & (1 << LR));
__ ldr(LR, Address(THR, entry_point_offset));
__ blx(LR);
compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs);
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index a3a7868..9c03a18 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -2676,8 +2676,12 @@
bool opt) const {
const intptr_t kNumInputs = 0;
const intptr_t kNumTemps = 1;
- LocationSummary* summary = new (zone) LocationSummary(
- zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+ const bool using_shared_stub = UseSharedSlowPathStub(opt);
+ ASSERT((kReservedCpuRegisters & (1 << LR)) != 0);
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps,
+ using_shared_stub ? LocationSummary::kCallOnSharedSlowPath
+ : LocationSummary::kCallOnSlowPath);
summary->set_temp(0, Location::RequiresRegister());
return summary;
}
@@ -2718,8 +2722,6 @@
? Thread::stack_overflow_shared_with_fpu_regs_entry_point_offset()
: Thread::
stack_overflow_shared_without_fpu_regs_entry_point_offset();
- ASSERT(instruction()->locs()->temp(1).IsRegister() &&
- instruction()->locs()->temp(1).reg() == LR);
__ ldr(LR, Address(THR, entry_point_offset));
__ blr(LR);
compiler->RecordSafepoint(instruction()->locs(), kNumSlowPathArgs);
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 9bd6ebb..3b48fc5 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -1782,6 +1782,7 @@
FunctionEntryInstr* entry = nullptr;
Instruction* last = nullptr;
+ Definition* result = nullptr;
// Replace the receiver argument with a redefinition to prevent code from
// the inlined body from being hoisted above the inlined entry.
GrowableArray<Definition*> arguments(call_->ArgumentCount());
@@ -1794,22 +1795,26 @@
owner_->caller_graph(), receiver_cid, target, call_, redefinition,
call_->instance_call()->token_pos(),
call_->instance_call()->ic_data(), graph_entry, &entry, &last,
- owner_->inliner_->speculative_policy())) {
+ &result, owner_->inliner_->speculative_policy())) {
+ // The empty Object constructor is the only case where the inlined body is
+ // empty and there is no result.
+ ASSERT((last != nullptr && result != nullptr) ||
+ MethodRecognizer::RecognizeKind(target) ==
+ MethodRecognizer::kObjectConstructor);
graph_entry->set_normal_entry(entry);
- ASSERT(last->IsDefinition());
// Create a graph fragment.
redefinition->InsertAfter(entry);
InlineExitCollector* exit_collector =
new (Z) InlineExitCollector(owner_->caller_graph(), call_);
- ReturnInstr* result = new (Z)
- ReturnInstr(call_->instance_call()->token_pos(),
- new (Z) Value(last->AsDefinition()), DeoptId::kNone);
+ ReturnInstr* return_result =
+ new (Z) ReturnInstr(call_->instance_call()->token_pos(),
+ new (Z) Value(result), DeoptId::kNone);
owner_->caller_graph()->AppendTo(
- last, result,
+ last, return_result,
call_->env(), // Return can become deoptimization target.
FlowGraph::kEffect);
- entry->set_last_instruction(result);
- exit_collector->AddExit(result);
+ entry->set_last_instruction(return_result);
+ exit_collector->AddExit(return_result);
// Update polymorphic inliner state.
inlined_entries_.Add(graph_entry);
@@ -2391,7 +2396,8 @@
Definition* receiver,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
Definition* array = receiver;
@@ -2428,6 +2434,7 @@
deopt_id != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kValue);
}
+ *result = (*last)->AsDefinition();
return true;
}
@@ -2441,7 +2448,8 @@
FlowGraphInliner::ExactnessInfo* exactness,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
Definition* array = receiver;
@@ -2591,6 +2599,9 @@
needs_store_barrier, index_scale, array_cid, kAlignedAccess,
call->deopt_id(), call->token_pos());
flow_graph->AppendTo(cursor, *last, call->env(), FlowGraph::kEffect);
+ // We need a return value to replace uses of the original definition. However,
+ // the final instruction is a use of 'void operator[]=()', so we use null.
+ *result = flow_graph->constant_null();
return true;
}
@@ -2600,7 +2611,8 @@
Definition* receiver,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
if (!CanUnboxDouble()) {
return false;
}
@@ -2617,6 +2629,7 @@
call->deopt_id(), call->token_pos());
flow_graph->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
*last = double_bin_op;
+ *result = double_bin_op->AsDefinition();
return true;
}
@@ -2627,7 +2640,8 @@
MethodRecognizer::Kind kind,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
if (!CanUnboxDouble()) {
return false;
}
@@ -2642,6 +2656,7 @@
kind, new (Z) Value(receiver), call->deopt_id(), call->token_pos());
flow_graph->AppendTo(*entry, double_test_op, call->env(), FlowGraph::kValue);
*last = double_test_op;
+ *result = double_test_op->AsDefinition();
return true;
}
@@ -2651,7 +2666,8 @@
Definition* receiver,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
Definition* left = receiver;
Definition* right = call->ArgumentAt(1);
@@ -2665,6 +2681,7 @@
new (Z) Value(right), call->deopt_id());
flow_graph->AppendTo(*entry, smi_op, call->env(), FlowGraph::kValue);
*last = smi_op;
+ *result = smi_op->AsDefinition();
return true;
}
@@ -2676,7 +2693,8 @@
Definition* receiver,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
Definition* array = receiver;
Definition* value = call->ArgumentAt(1);
@@ -2691,6 +2709,9 @@
store_barrier_type, call->token_pos());
flow_graph->AppendTo(*entry, store, call->env(), FlowGraph::kEffect);
*last = store;
+ // We need a return value to replace uses of the original definition. However,
+ // the last instruction is a field setter, which returns void, so we use null.
+ *result = flow_graph->constant_null();
return true;
}
@@ -2699,7 +2720,8 @@
Instruction* call,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
*entry =
new (Z) FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
call->GetBlock()->try_index(), DeoptId::kNone);
@@ -2708,6 +2730,7 @@
LoadClassIdInstr(call->PushArgumentAt(0)->value()->CopyWithType(Z));
flow_graph->InsertBefore(call, load_cid, nullptr, FlowGraph::kValue);
*last = load_cid;
+ *result = load_cid->AsDefinition();
return true;
}
@@ -2840,7 +2863,8 @@
intptr_t view_cid,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
ASSERT(array_cid != kIllegalCid);
// Dynamic calls are polymorphic due to:
@@ -2916,6 +2940,7 @@
DeoptId::kNone);
flow_graph->AppendTo(cursor, *last, nullptr, FlowGraph::kValue);
}
+ *result = (*last)->AsDefinition();
return true;
}
@@ -2939,7 +2964,8 @@
intptr_t view_cid,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
ASSERT(array_cid != kIllegalCid);
// Dynamic calls are polymorphic due to:
@@ -3123,6 +3149,9 @@
FlowGraph::kEffect);
*last = store;
}
+ // We need a return value to replace uses of the original definition. However,
+ // the final instruction is a use of 'void operator[]=()', so we use null.
+ *result = flow_graph->constant_null();
return true;
}
@@ -3168,7 +3197,8 @@
intptr_t cid,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
if ((cid != kOneByteStringCid) && (cid != kExternalOneByteStringCid)) {
return false;
}
@@ -3187,6 +3217,7 @@
flow_graph->AppendTo(*last, char_at, NULL, FlowGraph::kValue);
*last = char_at;
+ *result = char_at->AsDefinition();
return true;
}
@@ -3197,7 +3228,8 @@
intptr_t cid,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
if (cid == kDynamicCid) {
ASSERT(call->IsStaticCall());
return false;
@@ -3215,6 +3247,7 @@
(*entry)->InheritDeoptTarget(Z, call);
*last = PrepareInlineStringIndexOp(flow_graph, call, cid, str, index, *entry);
+ *result = (*last)->AsDefinition();
return true;
}
@@ -3231,12 +3264,19 @@
const intptr_t receiver_cid = class_ids[0];
FunctionEntryInstr* entry = nullptr;
Instruction* last = nullptr;
+ Definition* result = nullptr;
auto exactness = call->ic_data()->GetExactnessAt(0);
ExactnessInfo exactness_info{exactness.IsExact(), false};
if (FlowGraphInliner::TryInlineRecognizedMethod(
flow_graph, receiver_cid, target, call,
call->Receiver()->definition(), call->token_pos(), call->ic_data(),
- /*graph_entry=*/nullptr, &entry, &last, policy, &exactness_info)) {
+ /*graph_entry=*/nullptr, &entry, &last, &result, policy,
+ &exactness_info)) {
+ // The empty Object constructor is the only case where the inlined body is
+ // empty and there is no result.
+ ASSERT((last != nullptr && result != nullptr) ||
+ MethodRecognizer::RecognizeKind(target) ==
+ MethodRecognizer::kObjectConstructor);
// Determine if inlining instance methods needs a check.
FlowGraph::ToCheck check = FlowGraph::ToCheck::kNoCheck;
if (MethodRecognizer::PolymorphicTarget(target)) {
@@ -3280,17 +3320,8 @@
}
// Replace all uses of this definition with the result.
if (call->HasUses()) {
- ASSERT(last->IsDefinition());
- Definition* ret = last->AsDefinition();
- if (!ret->HasSSATemp()) {
- // Currently, StoreIndexed and StoreInstanceField are defined as
- // definitions despite producing no value. For now, catch the case
- // where the new inlined code ends with one of those and replace
- // the old uses of the original definition with uses of null.
- ASSERT(ret->IsStoreIndexed() || ret->IsStoreInstanceField());
- ret = flow_graph->constant_null();
- }
- call->ReplaceUsesWith(ret);
+ ASSERT(result->HasSSATemp());
+ call->ReplaceUsesWith(result);
}
// Finally insert the sequence other definition in place of this one in the
// graph.
@@ -3319,6 +3350,7 @@
SpeculativeInliningPolicy* policy) {
FunctionEntryInstr* entry = nullptr;
Instruction* last = nullptr;
+ Definition* result = nullptr;
Definition* receiver = nullptr;
intptr_t receiver_cid = kIllegalCid;
if (!call->function().is_static()) {
@@ -3328,7 +3360,12 @@
if (FlowGraphInliner::TryInlineRecognizedMethod(
flow_graph, receiver_cid, call->function(), call, receiver,
call->token_pos(), call->ic_data(), /*graph_entry=*/nullptr, &entry,
- &last, policy)) {
+ &last, &result, policy)) {
+ // The empty Object constructor is the only case where the inlined body is
+ // empty and there is no result.
+ ASSERT((last != nullptr && result != nullptr) ||
+ MethodRecognizer::RecognizeKind(call->function()) ==
+ MethodRecognizer::kObjectConstructor);
// Remove the original push arguments.
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
PushArgumentInstr* push = call->PushArgumentAt(i);
@@ -3337,17 +3374,8 @@
}
// Replace all uses of this definition with the result.
if (call->HasUses()) {
- ASSERT(last->IsDefinition());
- Definition* ret = last->AsDefinition();
- if (!ret->HasSSATemp()) {
- // Currently, StoreIndexed and StoreInstanceField are defined as
- // definitions despite producing no value. For now, catch the case
- // where the new inlined code ends with one of those and replace
- // the old uses of the original definition with uses of null.
- ASSERT(ret->IsStoreIndexed() || ret->IsStoreInstanceField());
- ret = flow_graph->constant_null();
- }
- call->ReplaceUsesWith(ret);
+ ASSERT(result->HasSSATemp());
+ call->ReplaceUsesWith(result);
}
// Finally insert the sequence other definition in place of this one in the
// graph.
@@ -3409,7 +3437,8 @@
MethodRecognizer::Kind kind,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
if (!ShouldInlineSimd()) {
return false;
}
@@ -3471,6 +3500,7 @@
flow_graph->AppendTo(cursor, *last,
call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kValue);
+ *result = (*last)->AsDefinition();
return true;
}
@@ -3479,7 +3509,8 @@
MethodRecognizer::Kind kind,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
if (!CanUnboxDouble()) {
return false;
}
@@ -3510,6 +3541,7 @@
flow_graph->AppendTo(cursor, *last,
call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kValue);
+ *result = (*last)->AsDefinition();
return true;
}
@@ -3527,7 +3559,8 @@
Instruction* call,
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
- Instruction** last) {
+ Instruction** last,
+ Definition** result) {
// Invoking the _intPow(x, y) implies that both:
// (1) x, y are int
// (2) y >= 0.
@@ -3541,9 +3574,11 @@
if (IsSmiValue(y, &val)) {
if (val == 0) {
*last = flow_graph->GetConstant(Smi::ZoneHandle(Smi::New(1)));
+ *result = (*last)->AsDefinition();
return true;
} else if (val == 1) {
*last = x->definition();
+ *result = (*last)->AsDefinition();
return true;
} else if (1 < val && val <= small_exponent) {
// Lazily construct entry only in this case.
@@ -3555,18 +3590,22 @@
Definition* square =
InlineMul(flow_graph, *entry, x_def, x_def)->AsDefinition();
*last = square;
+ *result = square;
switch (val) {
case 2:
return true;
case 3:
*last = InlineMul(flow_graph, *last, x_def, square);
+ *result = (*last)->AsDefinition();
return true;
case 4:
*last = InlineMul(flow_graph, *last, square, square);
+ *result = (*last)->AsDefinition();
return true;
case 5:
*last = InlineMul(flow_graph, *last, square, square);
*last = InlineMul(flow_graph, *last, x_def, (*last)->AsDefinition());
+ *result = (*last)->AsDefinition();
return true;
}
}
@@ -3575,6 +3614,7 @@
if (IsSmiValue(x, &val)) {
if (val == 1) {
*last = x->definition();
+ *result = x->definition();
return true;
}
}
@@ -3592,6 +3632,7 @@
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
Instruction** last,
+ Definition** result,
SpeculativeInliningPolicy* policy,
FlowGraphInliner::ExactnessInfo* exactness) {
const bool can_speculate = policy->IsAllowedForInlining(call->deopt_id());
@@ -3610,37 +3651,38 @@
case MethodRecognizer::kInt16ArrayGetIndexed:
case MethodRecognizer::kUint16ArrayGetIndexed:
return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kFloat32ArrayGetIndexed:
case MethodRecognizer::kFloat64ArrayGetIndexed:
if (!CanUnboxDouble()) {
return false;
}
return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kFloat32x4ArrayGetIndexed:
case MethodRecognizer::kFloat64x2ArrayGetIndexed:
if (!ShouldInlineSimd()) {
return false;
}
return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kInt32ArrayGetIndexed:
case MethodRecognizer::kUint32ArrayGetIndexed:
if (!CanUnboxInt32()) {
return false;
}
return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kInt64ArrayGetIndexed:
case MethodRecognizer::kUint64ArrayGetIndexed:
if (!ShouldInlineInt64ArrayOps()) {
return false;
}
return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kClassIDgetID:
- return InlineLoadClassId(flow_graph, call, graph_entry, entry, last);
+ return InlineLoadClassId(flow_graph, call, graph_entry, entry, last,
+ result);
default:
break;
}
@@ -3658,7 +3700,7 @@
case MethodRecognizer::kGrowableArraySetIndexedUnchecked:
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, /* value_check = */ NULL, exactness,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kInt8ArraySetIndexed:
case MethodRecognizer::kUint8ArraySetIndexed:
case MethodRecognizer::kUint8ClampedArraySetIndexed:
@@ -3674,7 +3716,7 @@
Cids* value_check = Cids::CreateMonomorphic(Z, kSmiCid);
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, value_check, exactness, graph_entry,
- entry, last);
+ entry, last, result);
}
case MethodRecognizer::kInt32ArraySetIndexed:
case MethodRecognizer::kUint32ArraySetIndexed: {
@@ -3682,7 +3724,7 @@
// implicitly contain unboxing instructions which check for right type.
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, /* value_check = */ NULL, exactness,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
}
case MethodRecognizer::kInt64ArraySetIndexed:
case MethodRecognizer::kUint64ArraySetIndexed:
@@ -3691,7 +3733,7 @@
}
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, /* value_check = */ NULL, exactness,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kFloat32ArraySetIndexed:
case MethodRecognizer::kFloat64ArraySetIndexed: {
if (!CanUnboxDouble()) {
@@ -3700,7 +3742,7 @@
Cids* value_check = Cids::CreateMonomorphic(Z, kDoubleCid);
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, value_check, exactness, graph_entry,
- entry, last);
+ entry, last, result);
}
case MethodRecognizer::kFloat32x4ArraySetIndexed: {
if (!ShouldInlineSimd()) {
@@ -3709,7 +3751,7 @@
Cids* value_check = Cids::CreateMonomorphic(Z, kFloat32x4Cid);
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, value_check, exactness, graph_entry,
- entry, last);
+ entry, last, result);
}
case MethodRecognizer::kFloat64x2ArraySetIndexed: {
if (!ShouldInlineSimd()) {
@@ -3718,171 +3760,171 @@
Cids* value_check = Cids::CreateMonomorphic(Z, kFloat64x2Cid);
return InlineSetIndexed(flow_graph, kind, target, call, receiver,
token_pos, value_check, exactness, graph_entry,
- entry, last);
+ entry, last, result);
}
case MethodRecognizer::kByteArrayBaseGetInt8:
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataInt8ArrayCid, graph_entry, entry,
- last);
+ last, result);
case MethodRecognizer::kByteArrayBaseGetUint8:
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataUint8ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetInt16:
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataInt16ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetUint16:
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataUint16ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetInt32:
if (!CanUnboxInt32()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataInt32ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetUint32:
if (!CanUnboxInt32()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataUint32ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetInt64:
if (!ShouldInlineInt64ArrayOps()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataInt64ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetUint64:
if (!ShouldInlineInt64ArrayOps()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataUint64ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetFloat32:
if (!CanUnboxDouble()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataFloat32ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetFloat64:
if (!CanUnboxDouble()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataFloat64ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetFloat32x4:
if (!ShouldInlineSimd()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataFloat32x4ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseGetInt32x4:
if (!ShouldInlineSimd()) {
return false;
}
return InlineByteArrayBaseLoad(flow_graph, call, receiver, receiver_cid,
kTypedDataInt32x4ArrayCid, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kByteArrayBaseSetInt8:
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataInt8ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetUint8:
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataUint8ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetInt16:
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataInt16ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetUint16:
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataUint16ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetInt32:
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataInt32ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetUint32:
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataUint32ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetInt64:
if (!ShouldInlineInt64ArrayOps()) {
return false;
}
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataInt64ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetUint64:
if (!ShouldInlineInt64ArrayOps()) {
return false;
}
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataUint64ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetFloat32:
if (!CanUnboxDouble()) {
return false;
}
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataFloat32ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetFloat64:
if (!CanUnboxDouble()) {
return false;
}
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataFloat64ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetFloat32x4:
if (!ShouldInlineSimd()) {
return false;
}
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataFloat32x4ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kByteArrayBaseSetInt32x4:
if (!ShouldInlineSimd()) {
return false;
}
return InlineByteArrayBaseStore(flow_graph, target, call, receiver,
receiver_cid, kTypedDataInt32x4ArrayCid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kOneByteStringCodeUnitAt:
case MethodRecognizer::kTwoByteStringCodeUnitAt:
case MethodRecognizer::kExternalOneByteStringCodeUnitAt:
case MethodRecognizer::kExternalTwoByteStringCodeUnitAt:
return InlineStringCodeUnitAt(flow_graph, call, receiver, receiver_cid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kStringBaseCharAt:
return InlineStringBaseCharAt(flow_graph, call, receiver, receiver_cid,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kDoubleAdd:
return InlineDoubleOp(flow_graph, Token::kADD, call, receiver,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kDoubleSub:
return InlineDoubleOp(flow_graph, Token::kSUB, call, receiver,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kDoubleMul:
return InlineDoubleOp(flow_graph, Token::kMUL, call, receiver,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kDoubleDiv:
return InlineDoubleOp(flow_graph, Token::kDIV, call, receiver,
- graph_entry, entry, last);
+ graph_entry, entry, last, result);
case MethodRecognizer::kDouble_getIsNaN:
case MethodRecognizer::kDouble_getIsInfinite:
return InlineDoubleTestOp(flow_graph, call, receiver, kind, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kGrowableArraySetData:
ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
((receiver_cid == kDynamicCid) && call->IsStaticCall()));
@@ -3890,7 +3932,7 @@
(ic_data == NULL || ic_data->NumberOfChecksIs(1)));
return InlineGrowableArraySetter(
flow_graph, Slot::GrowableObjectArray_data(), kEmitStoreBarrier, call,
- receiver, graph_entry, entry, last);
+ receiver, graph_entry, entry, last, result);
case MethodRecognizer::kGrowableArraySetLength:
ASSERT((receiver_cid == kGrowableObjectArrayCid) ||
((receiver_cid == kDynamicCid) && call->IsStaticCall()));
@@ -3898,10 +3940,10 @@
(ic_data == NULL || ic_data->NumberOfChecksIs(1)));
return InlineGrowableArraySetter(
flow_graph, Slot::GrowableObjectArray_length(), kNoStoreBarrier, call,
- receiver, graph_entry, entry, last);
+ receiver, graph_entry, entry, last, result);
case MethodRecognizer::kSmi_bitAndFromSmi:
return InlineSmiBitAndFromSmi(flow_graph, call, receiver, graph_entry,
- entry, last);
+ entry, last, result);
case MethodRecognizer::kFloat32x4Abs:
case MethodRecognizer::kFloat32x4Clamp:
@@ -3965,7 +4007,7 @@
case MethodRecognizer::kFloat32x4Shuffle:
case MethodRecognizer::kInt32x4Shuffle:
return InlineSimdOp(flow_graph, call, receiver, kind, graph_entry, entry,
- last);
+ last, result);
case MethodRecognizer::kMathSqrt:
case MethodRecognizer::kMathDoublePow:
@@ -3977,10 +4019,11 @@
case MethodRecognizer::kMathAtan:
case MethodRecognizer::kMathAtan2:
return InlineMathCFunction(flow_graph, call, kind, graph_entry, entry,
- last);
+ last, result);
case MethodRecognizer::kMathIntPow:
- return InlineMathIntPow(flow_graph, call, graph_entry, entry, last);
+ return InlineMathIntPow(flow_graph, call, graph_entry, entry, last,
+ result);
case MethodRecognizer::kObjectConstructor: {
*entry = new (Z)
@@ -3989,6 +4032,7 @@
(*entry)->InheritDeoptTarget(Z, call);
ASSERT(!call->HasUses());
*last = NULL; // Empty body.
+ *result = NULL; // Since no uses of original call, result will be unused.
return true;
}
@@ -4011,6 +4055,7 @@
*entry, *last,
call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kValue);
+ *result = (*last)->AsDefinition();
return true;
}
@@ -4030,6 +4075,7 @@
*entry, *last,
call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kValue);
+ *result = (*last)->AsDefinition();
return true;
}
}
@@ -4064,6 +4110,7 @@
*entry, *last,
call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kValue);
+ *result = (*last)->AsDefinition();
return true;
}
return false;
@@ -4089,6 +4136,9 @@
*entry, *last,
call->deopt_id() != DeoptId::kNone ? call->env() : NULL,
FlowGraph::kEffect);
+ // We need a return value to replace uses of the original definition.
+ // The final instruction is a use of 'void operator[]=()', so we use null.
+ *result = flow_graph->constant_null();
return true;
}
diff --git a/runtime/vm/compiler/backend/inliner.h b/runtime/vm/compiler/backend/inliner.h
index a516847..34366cf 100644
--- a/runtime/vm/compiler/backend/inliner.h
+++ b/runtime/vm/compiler/backend/inliner.h
@@ -7,6 +7,7 @@
#include "vm/allocation.h"
#include "vm/growable_array.h"
+#include "vm/token_position.h"
namespace dart {
@@ -139,6 +140,7 @@
GraphEntryInstr* graph_entry,
FunctionEntryInstr** entry,
Instruction** last,
+ Definition** result,
SpeculativeInliningPolicy* policy,
ExactnessInfo* exactness = nullptr);
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 7fa08c0..28f2199 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -107,8 +107,8 @@
}
}
}
- if (current->IsCheckArrayBound()) {
- bounds_checks_.Add(current->AsCheckArrayBound());
+ if (current->IsCheckArrayBound() || current->IsGenericCheckBound()) {
+ bounds_checks_.Add(current);
}
}
}
@@ -1017,8 +1017,8 @@
return phi;
}
// Decide between direct or indirect bound.
- Definition* bounded_phi = UnwrapConstraint(limit->value()->definition());
- if (bounded_phi == phi) {
+ Definition* bounded_def = UnwrapConstraint(limit->value()->definition());
+ if (bounded_def == phi) {
// Given a smi bounded loop with smi induction variable
//
// x <- phi(x0, x + 1)
@@ -1037,7 +1037,7 @@
//
// y <= y0 + (M - x0)
//
- InductionVar* bounded_induc = GetSmiInduction(loop, bounded_phi);
+ InductionVar* bounded_induc = GetSmiInduction(loop, bounded_def);
Definition* x0 = GenerateInvariant(bounded_induc->initial());
Definition* y0 = GenerateInvariant(induc->initial());
Definition* m = RangeBoundaryToDefinition(limit->constraint()->max());
@@ -1321,7 +1321,21 @@
BoundsCheckGeneralizer generalizer(this, flow_graph_);
for (intptr_t i = 0; i < bounds_checks_.length(); i++) {
- CheckArrayBoundInstr* check = bounds_checks_[i];
+ // Is this a non-speculative check bound?
+ GenericCheckBoundInstr* aot_check =
+ bounds_checks_[i]->AsGenericCheckBound();
+ if (aot_check != nullptr) {
+ RangeBoundary array_length =
+ RangeBoundary::FromDefinition(aot_check->length()->definition());
+ if (aot_check->IsRedundant(array_length)) {
+ aot_check->ReplaceUsesWith(aot_check->index()->definition());
+ aot_check->RemoveFromGraph();
+ }
+ continue;
+ }
+ // Must be a speculative check bound.
+ CheckArrayBoundInstr* check = bounds_checks_[i]->AsCheckArrayBound();
+ ASSERT(check != nullptr);
RangeBoundary array_length =
RangeBoundary::FromDefinition(check->length()->definition());
if (check->IsRedundant(array_length)) {
@@ -2928,6 +2942,52 @@
return false;
}
+// Check if range boundary and invariant limit are the same boundary.
+static bool IsSameBound(const RangeBoundary& a, InductionVar* b) {
+ ASSERT(InductionVar::IsInvariant(b));
+ if (a.IsSymbol()) {
+ // Check for exactly the same symbol as length.
+ return a.symbol() == b->def() && b->mult() == 1 &&
+ a.offset() == b->offset();
+ } else if (a.IsConstant()) {
+ // Check for constant in right range 0 < c <= length.
+ int64_t c = 0;
+ return InductionVar::IsConstant(b, &c) && 0 < c && c <= a.ConstantValue();
+ }
+ return false;
+}
+
+bool GenericCheckBoundInstr::IsRedundant(const RangeBoundary& length) {
+ // In loop, with index as induction?
+ LoopInfo* loop = GetBlock()->loop_info();
+ if (loop == nullptr) {
+ return false;
+ }
+ InductionVar* induc = loop->LookupInduction(index()->definition());
+ if (induc == nullptr) {
+ return false;
+ }
+ // Under 64-bit wrap-around arithmetic, it is always safe to remove the
+ // bounds check from the following, if initial >= 0 and the corresponding
+ // exit branch dominates the bounds check:
+ // for (int i = initial; i < length; i++)
+ // .... a[i] ....
+ int64_t stride = 0;
+ int64_t initial = 0;
+ if (InductionVar::IsLinear(induc, &stride) &&
+ InductionVar::IsConstant(induc->initial(), &initial)) {
+ if (stride == 1 && initial >= 0) {
+ for (auto bound : induc->bounds()) {
+ if (IsSameBound(length, bound.limit_) &&
+ this->IsDominatedBy(bound.branch_)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
} // namespace dart
#endif // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index 56dc78e..24adeed 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -605,8 +605,8 @@
GrowableArray<BinaryInt64OpInstr*> binary_int64_ops_;
GrowableArray<ShiftIntegerOpInstr*> shift_int64_ops_;
- // All CheckArrayBound instructions.
- GrowableArray<CheckArrayBoundInstr*> bounds_checks_;
+ // All CheckArrayBound/GenericCheckBound instructions.
+ GrowableArray<Instruction*> bounds_checks_;
// All Constraints inserted during InsertConstraints phase. They are treated
// as smi values.
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index 128343a..1e0f613 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -51,6 +51,7 @@
class Function;
class Precompiler;
class SpeculativeInliningPolicy;
+class TimelineStream;
struct CompilerPassState {
CompilerPassState(Thread* thread,
diff --git a/runtime/vm/compiler/compiler_state.h b/runtime/vm/compiler/compiler_state.h
index e9bc675..774f74d 100644
--- a/runtime/vm/compiler/compiler_state.h
+++ b/runtime/vm/compiler/compiler_state.h
@@ -6,6 +6,7 @@
#define RUNTIME_VM_COMPILER_COMPILER_STATE_H_
#include "vm/compiler/cha.h"
+#include "vm/heap/safepoint.h"
#include "vm/thread.h"
namespace dart {
@@ -53,9 +54,10 @@
};
// Global compiler state attached to the thread.
-class CompilerState : public StackResource {
+class CompilerState : public ThreadStackResource {
public:
- explicit CompilerState(Thread* thread) : StackResource(thread), cha_(thread) {
+ explicit CompilerState(Thread* thread)
+ : ThreadStackResource(thread), cha_(thread) {
previous_ = thread->SetCompilerState(this);
}
@@ -127,10 +129,10 @@
CompilerState* previous_;
};
-class DeoptIdScope : public StackResource {
+class DeoptIdScope : public ThreadStackResource {
public:
DeoptIdScope(Thread* thread, intptr_t deopt_id)
- : StackResource(thread),
+ : ThreadStackResource(thread),
prev_deopt_id_(thread->compiler_state().deopt_id()) {
thread->compiler_state().set_deopt_id(deopt_id);
}
@@ -145,10 +147,10 @@
/// Ensures that there were no deopt id allocations during the lifetime of this
/// object.
-class AssertNoDeoptIdsAllocatedScope : public StackResource {
+class AssertNoDeoptIdsAllocatedScope : public ThreadStackResource {
public:
explicit AssertNoDeoptIdsAllocatedScope(Thread* thread)
- : StackResource(thread),
+ : ThreadStackResource(thread),
prev_deopt_id_(thread->compiler_state().deopt_id()) {}
~AssertNoDeoptIdsAllocatedScope() {
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index 8d1c6da..3ac3ecc 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -1293,6 +1293,14 @@
// Note: This is already lowered to InstanceConstant/ListConstant.
UNREACHABLE();
break;
+ case kEnvironmentBoolConstant:
+ case kEnvironmentIntConstant:
+ case kEnvironmentStringConstant:
+ case kUnevaluatedConstant:
+ // We should not see unevaluated constants in the constant table, they
+ // should have been fully evaluated before we get them.
+ UNREACHABLE();
+ break;
default:
UNREACHABLE();
}
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index c3310b8..e901118 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -504,6 +504,7 @@
// Forward declarations.
class Function;
class Library;
+class Object;
class RawFunction;
class RawGrowableObjectArray;
class String;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index e1ee86a..a951991 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -84,16 +84,19 @@
};
static void CheckOffsets() {
+ bool ok = true;
#define CHECK_OFFSET(expr, offset) \
if ((expr) != (offset)) { \
- FATAL2("%s == %" Pd, #expr, (expr)); \
+ OS::PrintErr("%s got %" Pd " expected %" Pd "\n", #expr, (expr), \
+ static_cast<intptr_t>(offset)); \
+ ok = false; \
}
#if defined(TARGET_ARCH_ARM)
// These offsets are embedded in precompiled instructions. We need simarm
// (compiler) and arm (runtime) to agree.
- CHECK_OFFSET(Thread::stack_limit_offset(), 4);
- CHECK_OFFSET(Thread::object_null_offset(), 64);
+ CHECK_OFFSET(Thread::stack_limit_offset(), 28);
+ CHECK_OFFSET(Thread::object_null_offset(), 88);
CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 14);
CHECK_OFFSET(Isolate::object_store_offset(), 20);
NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 168));
@@ -101,12 +104,16 @@
#if defined(TARGET_ARCH_ARM64)
// These offsets are embedded in precompiled instructions. We need simarm64
// (compiler) and arm64 (runtime) to agree.
- CHECK_OFFSET(Thread::stack_limit_offset(), 8);
- CHECK_OFFSET(Thread::object_null_offset(), 120);
+ CHECK_OFFSET(Thread::stack_limit_offset(), 56);
+ CHECK_OFFSET(Thread::object_null_offset(), 168);
CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 26);
CHECK_OFFSET(Isolate::object_store_offset(), 40);
NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 288));
#endif
+
+ if (!ok) {
+ FATAL("CheckOffsets failed.");
+ }
#undef CHECK_OFFSET
}
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7d9b8f5..b01af49 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5922,6 +5922,29 @@
}
DART_EXPORT
+Dart_Handle Dart_SaveTypeFeedback(uint8_t** buffer, intptr_t* buffer_length) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
+#else
+ Thread* thread = Thread::Current();
+ API_TIMELINE_DURATION(thread);
+ DARTSCOPE(thread);
+ CHECK_NULL(buffer);
+ CHECK_NULL(buffer_length);
+
+ WriteStream stream(buffer, ApiReallocate, MB);
+ TypeFeedbackSaver saver(&stream);
+ saver.WriteHeader();
+ saver.SaveClasses();
+ saver.SaveFields();
+ ProgramVisitor::VisitFunctions(&saver);
+ *buffer_length = stream.bytes_written();
+
+ return Api::Success();
+#endif // defined(DART_PRECOMPILED_RUNTIME)
+}
+
+DART_EXPORT
Dart_Handle Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
@@ -5940,6 +5963,25 @@
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
+DART_EXPORT
+Dart_Handle Dart_LoadTypeFeedback(uint8_t* buffer, intptr_t buffer_length) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
+#else
+ Thread* thread = Thread::Current();
+ API_TIMELINE_DURATION(thread);
+ DARTSCOPE(thread);
+ CHECK_NULL(buffer);
+ ReadStream stream(buffer, buffer_length);
+ TypeFeedbackLoader loader(thread);
+ const Object& error = Object::Handle(loader.LoadFeedback(&stream));
+ if (error.IsError()) {
+ return Api::NewHandle(T, Error::Cast(error).raw());
+ }
+ return Api::Success();
+#endif // defined(DART_PRECOMPILED_RUNTIME)
+}
+
DART_EXPORT Dart_Handle Dart_SortClasses() {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index adb7182..8d91094 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -131,9 +131,9 @@
class Api : AllStatic {
public:
// Create on the stack to provide a new throw-safe api scope.
- class Scope : public StackResource {
+ class Scope : public ThreadStackResource {
public:
- explicit Scope(Thread* thread) : StackResource(thread) {
+ explicit Scope(Thread* thread) : ThreadStackResource(thread) {
thread->EnterApiScope();
}
~Scope() { thread()->ExitApiScope(); }
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 4e0acbc..a741a5e 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -93,10 +93,11 @@
// Clears/restores Thread::long_jump_base on construction/destruction.
// Ensures that we do not attempt to long jump across Dart frames.
-class SuspendLongJumpScope : public StackResource {
+class SuspendLongJumpScope : public ThreadStackResource {
public:
explicit SuspendLongJumpScope(Thread* thread)
- : StackResource(thread), saved_long_jump_base_(thread->long_jump_base()) {
+ : ThreadStackResource(thread),
+ saved_long_jump_base_(thread->long_jump_base()) {
thread->set_long_jump_base(NULL);
}
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index 360585e..43f2d64 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -372,7 +372,7 @@
WriteByte(static_cast<uint8_t>(value + kEndUnsignedByteMarker));
}
- void WriteBytes(const uint8_t* addr, intptr_t len) {
+ void WriteBytes(const void* addr, intptr_t len) {
if ((end_ - current_) < len) {
Resize(len);
}
diff --git a/runtime/vm/growable_array.h b/runtime/vm/growable_array.h
index 4788bff..5cd2d0b 100644
--- a/runtime/vm/growable_array.h
+++ b/runtime/vm/growable_array.h
@@ -11,7 +11,7 @@
#define RUNTIME_VM_GROWABLE_ARRAY_H_
#include "platform/growable_array.h"
-#include "vm/thread.h"
+#include "vm/thread_state.h"
#include "vm/zone.h"
namespace dart {
@@ -25,10 +25,10 @@
explicit GrowableArray(intptr_t initial_capacity)
: BaseGrowableArray<T, ValueObject, Zone>(
initial_capacity,
- ASSERT_NOTNULL(Thread::Current()->zone())) {}
+ ASSERT_NOTNULL(ThreadState::Current()->zone())) {}
GrowableArray()
: BaseGrowableArray<T, ValueObject, Zone>(
- ASSERT_NOTNULL(Thread::Current()->zone())) {}
+ ASSERT_NOTNULL(ThreadState::Current()->zone())) {}
};
template <typename T>
@@ -40,10 +40,10 @@
explicit ZoneGrowableArray(intptr_t initial_capacity)
: BaseGrowableArray<T, ZoneAllocated, Zone>(
initial_capacity,
- ASSERT_NOTNULL(Thread::Current()->zone())) {}
+ ASSERT_NOTNULL(ThreadState::Current()->zone())) {}
ZoneGrowableArray()
: BaseGrowableArray<T, ZoneAllocated, Zone>(
- ASSERT_NOTNULL(Thread::Current()->zone())) {}
+ ASSERT_NOTNULL(ThreadState::Current()->zone())) {}
};
// T must be a Handle type.
diff --git a/runtime/vm/handles.cc b/runtime/vm/handles.cc
index 33e2e70..3c429ef 100644
--- a/runtime/vm/handles.cc
+++ b/runtime/vm/handles.cc
@@ -84,7 +84,7 @@
#endif
}
-HandleScope::HandleScope(Thread* thread) : StackResource(thread) {
+HandleScope::HandleScope(Thread* thread) : ThreadStackResource(thread) {
Initialize();
}
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index 7eaf8a6..522aa02 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -8,6 +8,7 @@
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/os.h"
+#include "vm/thread_stack_resource.h"
namespace dart {
@@ -278,7 +279,7 @@
// code that creates some scoped handles.
// ....
// }
-class HandleScope : public StackResource {
+class HandleScope : public ThreadStackResource {
public:
explicit HandleScope(Thread* thread);
~HandleScope();
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index 0a2b76c..1582c79 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -374,7 +374,7 @@
public:
DirectChainedHashMap()
: BaseDirectChainedHashMap<KeyValueTrait, ValueObject>(
- ASSERT_NOTNULL(Thread::Current()->zone())) {}
+ ASSERT_NOTNULL(ThreadState::Current()->zone())) {}
explicit DirectChainedHashMap(Zone* zone)
: BaseDirectChainedHashMap<KeyValueTrait, ValueObject>(
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index a9c9e5d..da5e831 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -8,6 +8,7 @@
#include "platform/utils.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/flags.h"
+#include "vm/heap/become.h"
#include "vm/heap/pages.h"
#include "vm/heap/safepoint.h"
#include "vm/heap/scavenger.h"
@@ -61,23 +62,72 @@
}
}
+void Heap::MakeTLABIterable(Thread* thread) {
+ uword start = thread->top();
+ uword end = thread->end();
+ ASSERT(end >= start);
+ intptr_t size = end - start;
+ ASSERT(Utils::IsAligned(size, kObjectAlignment));
+ if (size >= kObjectAlignment) {
+ // ForwardingCorpse(forwarding to default null) will work as filler.
+ ForwardingCorpse::AsForwarder(start, size);
+ ASSERT(RawObject::FromAddr(start)->Size() == size);
+ }
+}
+
+void Heap::AbandonRemainingTLAB(Thread* thread) {
+ MakeTLABIterable(thread);
+ thread->set_top(0);
+ thread->set_end(0);
+}
+
+intptr_t Heap::CalculateTLABSize() {
+ intptr_t size = new_space_.end() - new_space_.top();
+ return Utils::RoundDown(size, kObjectAlignment);
+}
+
uword Heap::AllocateNew(intptr_t size) {
ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
// Currently, only the Dart thread may allocate in new space.
isolate()->AssertCurrentThreadIsMutator();
Thread* thread = Thread::Current();
uword addr = new_space_.TryAllocateInTLAB(thread, size);
- if (addr == 0) {
- // This call to CollectGarbage might end up "reusing" a collection spawned
- // from a different thread and will be racing to allocate the requested
- // memory with other threads being released after the collection.
- CollectGarbage(kNew);
- addr = new_space_.TryAllocateInTLAB(thread, size);
- if (addr == 0) {
- return AllocateOld(size, HeapPage::kData);
+ if (addr != 0) {
+ return addr;
+ }
+
+ intptr_t tlab_size = CalculateTLABSize();
+ if ((tlab_size > 0) && (size > tlab_size)) {
+ return AllocateOld(size, HeapPage::kData);
+ }
+
+ AbandonRemainingTLAB(thread);
+ if (tlab_size > 0) {
+ uword tlab_top = new_space_.TryAllocateNewTLAB(thread, tlab_size);
+ if (tlab_top != 0) {
+ addr = new_space_.TryAllocateInTLAB(thread, size);
+ ASSERT(addr != 0);
+ return addr;
}
}
- return addr;
+
+ ASSERT(!thread->HasActiveTLAB());
+
+ // This call to CollectGarbage might end up "reusing" a collection spawned
+ // from a different thread and will be racing to allocate the requested
+ // memory with other threads being released after the collection.
+ CollectGarbage(kNew);
+ tlab_size = CalculateTLABSize();
+ uword tlab_top = new_space_.TryAllocateNewTLAB(thread, tlab_size);
+ if (tlab_top != 0) {
+ addr = new_space_.TryAllocateInTLAB(thread, size);
+ // It is possible a GC doesn't clear enough space.
+ // In that case, we must fall through and allocate into old space.
+ if (addr != 0) {
+ return addr;
+ }
+ }
+ return AllocateOld(size, HeapPage::kData);
}
uword Heap::AllocateOld(intptr_t size, HeapPage::PageType type) {
@@ -200,7 +250,7 @@
}
HeapIterationScope::HeapIterationScope(Thread* thread, bool writable)
- : StackResource(thread),
+ : ThreadStackResource(thread),
heap_(isolate()->heap()),
old_space_(heap_->old_space()),
writable_(writable) {
@@ -647,7 +697,7 @@
StackZone stack_zone(Thread::Current());
// Change the new space's top_ with the more up-to-date thread's view of top_
- new_space_.FlushTLS();
+ new_space_.MakeNewSpaceIterable();
ObjectSet* allocated_set =
CreateAllocatedObjectSet(stack_zone.GetZone(), mark_expectation);
@@ -955,7 +1005,7 @@
}
NoHeapGrowthControlScope::NoHeapGrowthControlScope()
- : StackResource(Thread::Current()) {
+ : ThreadStackResource(Thread::Current()) {
Heap* heap = reinterpret_cast<Isolate*>(isolate())->heap();
current_growth_controller_state_ = heap->GrowthControlState();
heap->DisableGrowthControl();
@@ -967,7 +1017,7 @@
}
WritableVMIsolateScope::WritableVMIsolateScope(Thread* thread)
- : StackResource(thread) {
+ : ThreadStackResource(thread) {
if (FLAG_write_protect_vm_isolate) {
Dart::vm_isolate()->heap()->WriteProtect(false);
}
@@ -990,7 +1040,7 @@
}
BumpAllocateScope::BumpAllocateScope(Thread* thread)
- : StackResource(thread), no_reload_scope_(thread->isolate(), thread) {
+ : ThreadStackResource(thread), no_reload_scope_(thread->isolate(), thread) {
ASSERT(!thread->bump_allocate());
// If the background compiler thread is not disabled, there will be a cycle
// between the symbol table lock and the old space data lock.
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 8cedd89..6935bd1 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -281,6 +281,10 @@
static const intptr_t kNewAllocatableSize = 256 * KB;
+ intptr_t CalculateTLABSize();
+ void MakeTLABIterable(Thread* thread);
+ void AbandonRemainingTLAB(Thread* thread);
+
private:
class GCStats : public ValueObject {
public:
@@ -391,7 +395,7 @@
DISALLOW_COPY_AND_ASSIGN(Heap);
};
-class HeapIterationScope : public StackResource {
+class HeapIterationScope : public ThreadStackResource {
public:
explicit HeapIterationScope(Thread* thread, bool writable = false);
~HeapIterationScope();
@@ -416,7 +420,7 @@
DISALLOW_COPY_AND_ASSIGN(HeapIterationScope);
};
-class NoHeapGrowthControlScope : public StackResource {
+class NoHeapGrowthControlScope : public ThreadStackResource {
public:
NoHeapGrowthControlScope();
~NoHeapGrowthControlScope();
@@ -428,7 +432,7 @@
// Note: During this scope all pages are writable and the code pages are
// non-executable.
-class WritableVMIsolateScope : StackResource {
+class WritableVMIsolateScope : ThreadStackResource {
public:
explicit WritableVMIsolateScope(Thread* thread);
~WritableVMIsolateScope();
@@ -446,7 +450,7 @@
// This scope forces heap growth, forces use of the bump allocator, and
// takes the page lock. It is useful e.g. at program startup when allocating
// many objects into old gen (like libraries, classes, and functions).
-class BumpAllocateScope : StackResource {
+class BumpAllocateScope : ThreadStackResource {
public:
explicit BumpAllocateScope(Thread* thread);
~BumpAllocateScope();
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index c47ff50..af5236c 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -267,12 +267,14 @@
for (size_t space = 0; space < ARRAY_SIZE(spaces); ++space) {
const String& obj = String::Handle(String::New("x", spaces[space]));
{
+ HeapIterationScope iteration(thread);
NoSafepointScope no_safepoint;
FindOnly find_only(obj.raw());
EXPECT(obj.raw() == heap->FindObject(&find_only));
}
}
{
+ HeapIterationScope iteration(thread);
NoSafepointScope no_safepoint;
FindNothing find_nothing;
EXPECT(Object::null() == heap->FindObject(&find_nothing));
diff --git a/runtime/vm/heap/safepoint.cc b/runtime/vm/heap/safepoint.cc
index bf5def1..c231b9c 100644
--- a/runtime/vm/heap/safepoint.cc
+++ b/runtime/vm/heap/safepoint.cc
@@ -11,7 +11,8 @@
DEFINE_FLAG(bool, trace_safepoint, false, "Trace Safepoint logic.");
-SafepointOperationScope::SafepointOperationScope(Thread* T) : StackResource(T) {
+SafepointOperationScope::SafepointOperationScope(Thread* T)
+ : ThreadStackResource(T) {
ASSERT(T != NULL);
Isolate* I = T->isolate();
ASSERT(I != NULL);
diff --git a/runtime/vm/heap/safepoint.h b/runtime/vm/heap/safepoint.h
index 191323f..ce84f85 100644
--- a/runtime/vm/heap/safepoint.h
+++ b/runtime/vm/heap/safepoint.h
@@ -8,13 +8,14 @@
#include "vm/globals.h"
#include "vm/lockers.h"
#include "vm/thread.h"
+#include "vm/thread_stack_resource.h"
namespace dart {
// A stack based scope that can be used to perform an operation after getting
// all threads to a safepoint. At the end of the operation all the threads are
// resumed.
-class SafepointOperationScope : public StackResource {
+class SafepointOperationScope : public ThreadStackResource {
public:
explicit SafepointOperationScope(Thread* T);
~SafepointOperationScope();
@@ -136,9 +137,9 @@
* ==> kThreadInGenerated
* - Invalid transition.
*/
-class TransitionSafepointState : public StackResource {
+class TransitionSafepointState : public ThreadStackResource {
public:
- explicit TransitionSafepointState(Thread* T) : StackResource(T) {}
+ explicit TransitionSafepointState(Thread* T) : ThreadStackResource(T) {}
~TransitionSafepointState() {}
SafepointHandler* handler() const {
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 9e3a457..b07afe9 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -447,13 +447,6 @@
resolved_top_ = top_;
end_ = to_->end();
- // Throw out the old information about the from space
- if (isolate->IsMutatorThreadScheduled()) {
- Thread* mutator_thread = isolate->mutator_thread();
- mutator_thread->set_top(top_);
- mutator_thread->set_end(end_);
- }
-
return from;
}
@@ -461,13 +454,10 @@
// All objects in the to space have been copied from the from space at this
// moment.
- // Ensure the mutator thread now has the up-to-date top_ and end_ of the
- // semispace
- if (isolate->IsMutatorThreadScheduled()) {
- Thread* thread = isolate->mutator_thread();
- thread->set_top(top_);
- thread->set_end(end_);
- }
+ // Ensure the mutator thread will fail the next allocation. This will force
+ // mutator to allocate a new TLAB
+ Thread* mutator_thread = isolate->mutator_thread();
+ ASSERT((mutator_thread == NULL) || (!mutator_thread->HasActiveTLAB()));
double avg_frac = stats_history_.Get(0).PromoCandidatesSuccessFraction();
if (stats_history_.Size() >= 2) {
@@ -844,11 +834,45 @@
}
}
-void Scavenger::FlushTLS() const {
+void Scavenger::MakeAllTLABsIterable(Isolate* isolate) const {
+ MonitorLocker ml(isolate->threads_lock(), false);
+ ASSERT(Thread::Current()->IsAtSafepoint() ||
+ (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
+ (Thread::Current()->task_kind() == Thread::kCompactorTask));
+ Thread* current = heap_->isolate()->thread_registry()->active_list();
+ while (current != NULL) {
+ if (current->HasActiveTLAB()) {
+ heap_->MakeTLABIterable(current);
+ }
+ current = current->next();
+ }
+ Thread* mutator_thread = isolate->mutator_thread();
+ if ((mutator_thread != NULL) && (!isolate->IsMutatorThreadScheduled())) {
+ heap_->MakeTLABIterable(mutator_thread);
+ }
+}
+
+void Scavenger::MakeNewSpaceIterable() const {
ASSERT(heap_ != NULL);
- if (heap_->isolate()->IsMutatorThreadScheduled()) {
- Thread* mutator_thread = heap_->isolate()->mutator_thread();
- mutator_thread->heap()->new_space()->set_top(mutator_thread->top());
+ ASSERT(Thread::Current()->IsAtSafepoint() ||
+ (Thread::Current()->task_kind() == Thread::kMarkerTask) ||
+ (Thread::Current()->task_kind() == Thread::kCompactorTask));
+ if (!scavenging_) {
+ MakeAllTLABsIterable(heap_->isolate());
+ }
+}
+
+void Scavenger::AbandonAllTLABs(Isolate* isolate) {
+ ASSERT(Thread::Current()->IsAtSafepoint());
+ MonitorLocker ml(isolate->threads_lock(), false);
+ Thread* current = isolate->thread_registry()->active_list();
+ while (current != NULL) {
+ heap_->AbandonRemainingTLAB(current);
+ current = current->next();
+ }
+ Thread* mutator_thread = isolate->mutator_thread();
+ if ((mutator_thread != NULL) && (!isolate->IsMutatorThreadScheduled())) {
+ heap_->AbandonRemainingTLAB(mutator_thread);
}
}
@@ -856,7 +880,7 @@
ASSERT(Thread::Current()->IsAtSafepoint() ||
(Thread::Current()->task_kind() == Thread::kMarkerTask) ||
(Thread::Current()->task_kind() == Thread::kCompactorTask));
- FlushTLS();
+ MakeNewSpaceIterable();
uword cur = FirstObjectStart();
while (cur < top_) {
RawObject* raw_obj = RawObject::FromAddr(cur);
@@ -867,7 +891,7 @@
void Scavenger::VisitObjects(ObjectVisitor* visitor) const {
ASSERT(Thread::Current()->IsAtSafepoint() ||
(Thread::Current()->task_kind() == Thread::kMarkerTask));
- FlushTLS();
+ MakeNewSpaceIterable();
uword cur = FirstObjectStart();
while (cur < top_) {
RawObject* raw_obj = RawObject::FromAddr(cur);
@@ -882,7 +906,7 @@
RawObject* Scavenger::FindObject(FindObjectVisitor* visitor) const {
ASSERT(!scavenging_);
- FlushTLS();
+ MakeNewSpaceIterable();
uword cur = FirstObjectStart();
if (visitor->VisitRange(cur, top_)) {
while (cur < top_) {
@@ -898,6 +922,26 @@
return Object::null();
}
+uword Scavenger::TryAllocateNewTLAB(Thread* thread, intptr_t size) {
+ ASSERT(Utils::IsAligned(size, kObjectAlignment));
+ ASSERT(heap_ != Dart::vm_isolate()->heap());
+ ASSERT(!scavenging_);
+ MutexLocker ml(&space_lock_);
+ uword result = top_;
+ intptr_t remaining = end_ - top_;
+ if (remaining < size) {
+ return 0;
+ }
+ ASSERT(to_->Contains(result));
+ ASSERT((result & kObjectAlignmentMask) == object_alignment_);
+ top_ += size;
+ ASSERT(to_->Contains(top_) || (top_ == to_->end()));
+ ASSERT(result < top_);
+ thread->set_top(result);
+ thread->set_end(top_);
+ return result;
+}
+
void Scavenger::Scavenge() {
Isolate* isolate = heap_->isolate();
// Ensure that all threads for this isolate are at a safepoint (either stopped
@@ -923,6 +967,13 @@
int64_t safe_point = OS::GetCurrentMonotonicMicros();
heap_->RecordTime(kSafePoint, safe_point - start);
+ AbandonAllTLABs(isolate);
+
+ Thread* mutator_thread = isolate->mutator_thread();
+ if ((mutator_thread != NULL) && (mutator_thread->HasActiveTLAB())) {
+ heap_->AbandonRemainingTLAB(mutator_thread);
+ }
+
// TODO(koda): Make verification more compatible with concurrent sweep.
if (FLAG_verify_before_gc && !FLAG_concurrent_sweep) {
OS::PrintErr("Verifying before Scavenge...");
@@ -931,7 +982,7 @@
}
// Prepare for a scavenge.
- FlushTLS();
+ MakeNewSpaceIterable();
SpaceUsage usage_before = GetCurrentUsage();
intptr_t promo_candidate_words =
(survivor_end_ - FirstObjectStart()) / kWordSize;
@@ -1040,11 +1091,6 @@
// Forces the next scavenge to promote all the objects in the new space.
survivor_end_ = top_;
- if (heap_->isolate()->IsMutatorThreadScheduled()) {
- Thread* mutator_thread = heap_->isolate()->mutator_thread();
- survivor_end_ = mutator_thread->top();
- }
-
Scavenge();
// It is possible for objects to stay in the new space
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index 412395d..bd8ad4f 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -11,6 +11,7 @@
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/heap/spaces.h"
+#include "vm/lockers.h"
#include "vm/raw_object.h"
#include "vm/ring_buffer.h"
#include "vm/virtual_memory.h"
@@ -126,6 +127,8 @@
RawObject* FindObject(FindObjectVisitor* visitor) const;
+ uword TryAllocateNewTLAB(Thread* thread, intptr_t size);
+
uword AllocateGC(intptr_t size) {
ASSERT(Utils::IsAligned(size, kObjectAlignment));
ASSERT(heap_ != Dart::vm_isolate()->heap());
@@ -139,7 +142,7 @@
ASSERT(to_->Contains(result));
ASSERT((result & kObjectAlignmentMask) == object_alignment_);
top_ += size;
- ASSERT(to_->Contains(top_) || (top_ == to_->end()));
+ ASSERT((to_->Contains(top_)) || (top_ == to_->end()));
return result;
}
@@ -148,6 +151,8 @@
ASSERT(heap_ != Dart::vm_isolate()->heap());
ASSERT(thread->IsMutatorThread());
ASSERT(thread->isolate()->IsMutatorThreadScheduled());
+ ASSERT(thread->top() <= top_);
+ ASSERT((thread->end() == 0) || (thread->end() == top_));
#if defined(DEBUG)
if (FLAG_gc_at_alloc) {
ASSERT(!scavenging_);
@@ -164,7 +169,7 @@
ASSERT(to_->Contains(result));
ASSERT((result & kObjectAlignmentMask) == object_alignment_);
top += size;
- ASSERT(to_->Contains(top) || (top == to_->end()));
+ ASSERT((to_->Contains(top)) || (top == to_->end()));
thread->set_top(top);
return result;
}
@@ -221,7 +226,10 @@
void AllocateExternal(intptr_t cid, intptr_t size);
void FreeExternal(intptr_t size);
- void FlushTLS() const;
+ void MakeNewSpaceIterable() const;
+ int64_t FreeSpaceInWords(Isolate* isolate) const;
+ void MakeAllTLABsIterable(Isolate* isolate) const;
+ void AbandonAllTLABs(Isolate* isolate);
private:
// Ids for time and data records in Heap::GCStats.
@@ -323,6 +331,9 @@
bool failed_to_promote_;
+ // Protects new space during the allocation of new TLABs
+ Mutex space_lock_;
+
friend class ScavengerVisitor;
friend class ScavengerWeakVisitor;
diff --git a/runtime/vm/heap/sweeper.cc b/runtime/vm/heap/sweeper.cc
index 8292a7d..7e477d7 100644
--- a/runtime/vm/heap/sweeper.cc
+++ b/runtime/vm/heap/sweeper.cc
@@ -4,6 +4,7 @@
#include "vm/heap/sweeper.h"
+#include "vm/compiler/assembler/assembler.h"
#include "vm/globals.h"
#include "vm/heap/freelist.h"
#include "vm/heap/heap.h"
@@ -48,7 +49,13 @@
}
obj_size = free_end - current;
if (is_executable) {
- memset(reinterpret_cast<void*>(current), 0xcc, obj_size);
+ uword cursor = current;
+ uword end = current + obj_size;
+ while (cursor < end) {
+ *reinterpret_cast<uword*>(cursor) =
+ Assembler::GetBreakInstructionFiller();
+ cursor += kWordSize;
+ }
} else {
#if defined(DEBUG)
memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size);
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 29bbe385..8ea2fdb 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -20,7 +20,7 @@
if (raw_obj->IsHeapObject()) {
uword raw_addr = RawObject::ToAddr(raw_obj);
if (raw_obj->IsFreeListElement() || raw_obj->IsForwardingCorpse()) {
- if (raw_obj->IsMarked()) {
+ if (raw_obj->IsOldObject() && raw_obj->IsMarked()) {
FATAL1("Marked free list element encountered %#" Px "\n", raw_addr);
}
} else {
diff --git a/runtime/vm/heap/verifier.h b/runtime/vm/heap/verifier.h
index f12ba82..d811be6 100644
--- a/runtime/vm/heap/verifier.h
+++ b/runtime/vm/heap/verifier.h
@@ -8,6 +8,7 @@
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/handles.h"
+#include "vm/thread.h"
#include "vm/visitor.h"
namespace dart {
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 22d27a2..4e98f3e 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -24,6 +24,7 @@
class RawArray;
class RawObjectPool;
class RawFunction;
+class RawString;
class RawSubtypeTestCache;
class ObjectPointerVisitor;
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index df87172..7f1e8a2 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -148,7 +148,8 @@
return Isolate::IsVMInternalIsolate(isolate);
}
-NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) {
+NoOOBMessageScope::NoOOBMessageScope(Thread* thread)
+ : ThreadStackResource(thread) {
thread->DeferOOBMessageInterrupts();
}
@@ -157,7 +158,7 @@
}
NoReloadScope::NoReloadScope(Isolate* isolate, Thread* thread)
- : StackResource(thread), isolate_(isolate) {
+ : ThreadStackResource(thread), isolate_(isolate) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
ASSERT(isolate_ != NULL);
AtomicOperations::FetchAndIncrement(&(isolate_->no_reload_scope_depth_));
@@ -2836,10 +2837,6 @@
os_thread->set_thread(thread);
if (is_mutator) {
scheduled_mutator_thread_ = thread;
- if (this != Dart::vm_isolate()) {
- scheduled_mutator_thread_->set_top(heap()->new_space()->top());
- scheduled_mutator_thread_->set_end(heap()->new_space()->end());
- }
}
Thread::SetCurrent(thread);
os_thread->EnableThreadInterrupts();
@@ -2865,7 +2862,7 @@
}
} else {
ASSERT(thread->api_top_scope_ == NULL);
- ASSERT(thread->zone_ == NULL);
+ ASSERT(thread->zone() == NULL);
ASSERT(thread->sticky_error() == Error::null());
}
if (!bypass_safepoint) {
@@ -2878,12 +2875,6 @@
os_thread->set_thread(NULL);
OSThread::SetCurrent(os_thread);
if (is_mutator) {
- if (this != Dart::vm_isolate()) {
- heap()->new_space()->set_top(scheduled_mutator_thread_->top_);
- heap()->new_space()->set_end(scheduled_mutator_thread_->end_);
- }
- scheduled_mutator_thread_->top_ = 0;
- scheduled_mutator_thread_->end_ = 0;
scheduled_mutator_thread_ = NULL;
}
// Even if we unschedule the mutator thread, e.g. via calling
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 278857f..ffa2a03 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -21,6 +21,7 @@
#include "vm/random.h"
#include "vm/tags.h"
#include "vm/thread.h"
+#include "vm/thread_stack_resource.h"
#include "vm/token_position.h"
namespace dart {
@@ -106,7 +107,7 @@
};
// Disallow OOB message handling within this scope.
-class NoOOBMessageScope : public StackResource {
+class NoOOBMessageScope : public ThreadStackResource {
public:
explicit NoOOBMessageScope(Thread* thread);
~NoOOBMessageScope();
@@ -116,7 +117,7 @@
};
// Disallow isolate reload.
-class NoReloadScope : public StackResource {
+class NoReloadScope : public ThreadStackResource {
public:
NoReloadScope(Isolate* isolate, Thread* thread);
~NoReloadScope();
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index ddc9884..4710aad 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -17,7 +17,7 @@
// package:kernel/binary.md.
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 15;
+static const uint32_t kBinaryFormatVersion = 16;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
@@ -147,6 +147,12 @@
kPartialInstantiationConstant = 9,
kTearOffConstant = 10,
kTypeLiteralConstant = 11,
+ // These constants are not expected to be seen by the VM, because all
+ // constants are fully evaluated.
+ kEnvironmentBoolConstant = 12,
+ kEnvironmentIntConstant = 13,
+ kEnvironmentStringConstant = 14,
+ kUnevaluatedConstant = 15,
};
static const int SpecializedIntLiteralBias = 3;
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index d629c76..693078c 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -9,6 +9,7 @@
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
+#include "vm/flags.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/message.h"
@@ -343,6 +344,17 @@
Dart_WeakPersistentHandle handle,
void* peer) {}
+MallocGrowableArray<char*>* KernelIsolate::experimental_flags_ =
+ new MallocGrowableArray<char*>();
+
+void KernelIsolate::AddExperimentalFlag(const char* value) {
+ experimental_flags_->Add(strdup(value));
+}
+
+DEFINE_OPTION_HANDLER(KernelIsolate::AddExperimentalFlag,
+ enable_experiment,
+ "Comma separated list of experimental features.");
+
class KernelCompilationRequest : public ValueObject {
public:
KernelCompilationRequest()
@@ -373,7 +385,8 @@
const Array& type_definitions,
char const* library_uri,
char const* klass,
- bool is_static) {
+ bool is_static,
+ const MallocGrowableArray<char*>* experimental_flags) {
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);
Dart_CObject tag;
@@ -443,12 +456,25 @@
isolate_id.value.as_int64 =
isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0;
- Dart_CObject message;
- message.type = Dart_CObject_kArray;
Dart_CObject suppress_warnings;
suppress_warnings.type = Dart_CObject_kBool;
suppress_warnings.value.as_bool = FLAG_suppress_fe_warnings;
+ intptr_t num_experimental_flags = experimental_flags->length();
+ Dart_CObject** experimental_flags_array =
+ new Dart_CObject*[num_experimental_flags];
+ for (intptr_t i = 0; i < num_experimental_flags; ++i) {
+ experimental_flags_array[i] = new Dart_CObject;
+ experimental_flags_array[i]->type = Dart_CObject_kString;
+ experimental_flags_array[i]->value.as_string = (*experimental_flags)[i];
+ }
+ Dart_CObject experimental_flags_object;
+ experimental_flags_object.type = Dart_CObject_kArray;
+ experimental_flags_object.value.as_array.values = experimental_flags_array;
+ experimental_flags_object.value.as_array.length = num_experimental_flags;
+
+ Dart_CObject message;
+ message.type = Dart_CObject_kArray;
Dart_CObject* message_arr[] = {&tag,
&send_port,
&isolate_id,
@@ -458,7 +484,8 @@
&library_uri_object,
&class_object,
&is_static_object,
- &suppress_warnings};
+ &suppress_warnings,
+ &experimental_flags_object};
message.value.as_array.values = message_arr;
message.value.as_array.length = ARRAY_SIZE(message_arr);
@@ -486,6 +513,11 @@
}
delete[] type_definitions_array;
+ for (intptr_t i = 0; i < num_experimental_flags; ++i) {
+ delete experimental_flags_array[i];
+ }
+ delete[] experimental_flags_array;
+
return result_;
}
@@ -500,7 +532,8 @@
bool incremental_compile,
const char* package_config,
const char* multiroot_filepaths,
- const char* multiroot_scheme) {
+ const char* multiroot_scheme,
+ const MallocGrowableArray<char*>* experimental_flags) {
// Build the [null, send_port, script_uri, platform_kernel,
// incremental_compile, isolate_id, [files]] message for the Kernel isolate.
// tag is used to specify which operation the frontend should perform.
@@ -570,6 +603,19 @@
suppress_warnings.type = Dart_CObject_kBool;
suppress_warnings.value.as_bool = FLAG_suppress_fe_warnings;
+ intptr_t num_experimental_flags = experimental_flags->length();
+ Dart_CObject** experimental_flags_array =
+ new Dart_CObject*[num_experimental_flags];
+ for (intptr_t i = 0; i < num_experimental_flags; ++i) {
+ experimental_flags_array[i] = new Dart_CObject;
+ experimental_flags_array[i]->type = Dart_CObject_kString;
+ experimental_flags_array[i]->value.as_string = (*experimental_flags)[i];
+ }
+ Dart_CObject experimental_flags_object;
+ experimental_flags_object.type = Dart_CObject_kArray;
+ experimental_flags_object.value.as_array.values = experimental_flags_array;
+ experimental_flags_object.value.as_array.length = num_experimental_flags;
+
Dart_CObject bytecode;
bytecode.type = Dart_CObject_kBool;
// Interpreter is supported only on x64 and arm64.
@@ -625,6 +671,7 @@
&isolate_id,
&files,
&suppress_warnings,
+ &experimental_flags_object,
&bytecode,
&package_config_uri,
&multiroot_filepaths_object,
@@ -643,6 +690,11 @@
ml.Wait();
}
+ for (intptr_t i = 0; i < num_experimental_flags; ++i) {
+ delete experimental_flags_array[i];
+ }
+ delete[] experimental_flags_array;
+
return result_;
}
@@ -774,11 +826,11 @@
}
KernelCompilationRequest request;
- return request.SendAndWaitForResponse(kCompileTag, kernel_port, script_uri,
- platform_kernel, platform_kernel_size,
- source_file_count, source_files,
- incremental_compile, package_config,
- multiroot_filepaths, multiroot_scheme);
+ return request.SendAndWaitForResponse(
+ kCompileTag, kernel_port, script_uri, platform_kernel,
+ platform_kernel_size, source_file_count, source_files,
+ incremental_compile, package_config, multiroot_filepaths,
+ multiroot_scheme, experimental_flags_);
}
Dart_KernelCompilationResult KernelIsolate::ListDependencies() {
@@ -793,7 +845,7 @@
KernelCompilationRequest request;
return request.SendAndWaitForResponse(kListDependenciesTag, kernel_port, NULL,
NULL, 0, 0, NULL, false, NULL, NULL,
- NULL);
+ NULL, experimental_flags_);
}
Dart_KernelCompilationResult KernelIsolate::AcceptCompilation() {
@@ -809,7 +861,8 @@
KernelCompilationRequest request;
return request.SendAndWaitForResponse(kAcceptTag, kernel_port, NULL, NULL, 0,
- 0, NULL, true, NULL, NULL, NULL);
+ 0, NULL, true, NULL, NULL, NULL,
+ experimental_flags_);
}
Dart_KernelCompilationResult KernelIsolate::CompileExpressionToKernel(
@@ -831,7 +884,7 @@
KernelCompilationRequest request;
return request.SendAndWaitForResponse(kernel_port, expression, definitions,
type_definitions, library_url, klass,
- is_static);
+ is_static, experimental_flags_);
}
Dart_KernelCompilationResult KernelIsolate::UpdateInMemorySources(
@@ -848,9 +901,9 @@
}
KernelCompilationRequest request;
- return request.SendAndWaitForResponse(kUpdateSourcesTag, kernel_port, NULL,
- NULL, 0, source_files_count,
- source_files, true, NULL, NULL, NULL);
+ return request.SendAndWaitForResponse(
+ kUpdateSourcesTag, kernel_port, NULL, NULL, 0, source_files_count,
+ source_files, true, NULL, NULL, NULL, experimental_flags_);
}
void KernelIsolate::NotifyAboutIsolateShutdown(const Isolate* isolate) {
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index a271351..284177b 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -5,6 +5,8 @@
#ifndef RUNTIME_VM_KERNEL_ISOLATE_H_
#define RUNTIME_VM_KERNEL_ISOLATE_H_
+#include <vector>
+
#include "include/dart_api.h"
#include "include/dart_native_api.h"
@@ -65,6 +67,8 @@
static void NotifyAboutIsolateShutdown(const Isolate* isolate);
+ static void AddExperimentalFlag(const char* value);
+
protected:
static Monitor* monitor_;
static Dart_IsolateCreateCallback create_callback_;
@@ -82,6 +86,8 @@
return create_callback_;
}
+ static MallocGrowableArray<char*>* experimental_flags_;
+
friend class Dart;
friend class Isolate;
friend class RunKernelTask;
diff --git a/runtime/vm/log.h b/runtime/vm/log.h
index b644884..1c4a6d0 100644
--- a/runtime/vm/log.h
+++ b/runtime/vm/log.h
@@ -74,13 +74,13 @@
// Can be nested.
class LogBlock : public StackResource {
public:
- LogBlock(Thread* thread, Log* log)
+ LogBlock(ThreadState* thread, Log* log)
: StackResource(thread), log_(log), cursor_(log->cursor()) {
Initialize();
}
LogBlock()
- : StackResource(Thread::Current()),
+ : StackResource(ThreadState::Current()),
log_(Log::Current()),
cursor_(Log::Current()->cursor()) {
Initialize();
diff --git a/runtime/vm/longjump.h b/runtime/vm/longjump.h
index 9da35b9..a334f15 100644
--- a/runtime/vm/longjump.h
+++ b/runtime/vm/longjump.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2019, 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.
@@ -8,7 +8,7 @@
#include <setjmp.h>
#include "vm/allocation.h"
-#include "vm/isolate.h"
+#include "vm/thread_state.h"
namespace dart {
@@ -17,14 +17,14 @@
class LongJumpScope : public StackResource {
public:
LongJumpScope()
- : StackResource(Thread::Current()),
- top_(NULL),
+ : StackResource(ThreadState::Current()),
+ top_(nullptr),
base_(thread()->long_jump_base()) {
thread()->set_long_jump_base(this);
}
~LongJumpScope() {
- ASSERT(thread() == Thread::Current());
+ ASSERT(thread() == ThreadState::Current());
thread()->set_long_jump_base(base_);
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 55009dc..18b69c3 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3943,15 +3943,6 @@
raw_ptr()->state_bits_));
}
-void Class::set_is_marked_for_lazy_loading() const {
- set_state_bits(MarkedForLazyLoadingBit::update(true, raw_ptr()->state_bits_));
-}
-
-void Class::reset_is_marked_for_lazy_loading() const {
- set_state_bits(
- MarkedForLazyLoadingBit::update(false, raw_ptr()->state_bits_));
-}
-
void Class::set_interfaces(const Array& value) const {
ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->interfaces_, value.raw());
@@ -13046,6 +13037,11 @@
#if defined(DEBUG)
// Used in asserts to verify that a check is not added twice.
bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const {
+ return FindCheck(cids) != -1;
+}
+#endif // DEBUG
+
+intptr_t ICData::FindCheck(const GrowableArray<intptr_t>& cids) const {
const intptr_t len = NumberOfChecks();
for (intptr_t i = 0; i < len; i++) {
GrowableArray<intptr_t> class_ids;
@@ -13059,12 +13055,11 @@
}
}
if (matches) {
- return true;
+ return i;
}
}
- return false;
+ return -1;
}
-#endif // DEBUG
void ICData::WriteSentinelAt(intptr_t index) const {
const intptr_t len = Length();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 22bd10f..f1de141 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -6,7 +6,6 @@
#define RUNTIME_VM_OBJECT_H_
#include <tuple>
-
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/utils.h"
@@ -1130,12 +1129,6 @@
void ResetFinalization() const;
- bool is_marked_for_lazy_loading() const {
- return MarkedForLazyLoadingBit::decode(raw_ptr()->state_bits_);
- }
- void set_is_marked_for_lazy_loading() const;
- void reset_is_marked_for_lazy_loading() const;
-
bool is_const() const { return ConstBit::decode(raw_ptr()->state_bits_); }
void set_is_const() const;
@@ -1318,15 +1311,14 @@
kClassFinalizedSize = 2,
kAbstractBit = kClassFinalizedPos + kClassFinalizedSize, // = 5
kPatchBit = 6,
- kSynthesizedClassBit = 7,
- kMarkedForLazyLoadingBit = 8,
- kMixinAppAliasBit = 9,
- kMixinTypeAppliedBit = 10,
- kFieldsMarkedNullableBit = 11,
- kCycleFreeBit = 12,
- kEnumBit = 13,
- kTransformedMixinApplicationBit = 14,
- kIsAllocatedBit = 15,
+ kSynthesizedClassBit,
+ kMixinAppAliasBit,
+ kMixinTypeAppliedBit,
+ kFieldsMarkedNullableBit,
+ kCycleFreeBit,
+ kEnumBit,
+ kTransformedMixinApplicationBit,
+ kIsAllocatedBit,
};
class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
class ImplementedBit : public BitField<uint16_t, bool, kImplementedBit, 1> {};
@@ -1340,8 +1332,6 @@
class PatchBit : public BitField<uint16_t, bool, kPatchBit, 1> {};
class SynthesizedClassBit
: public BitField<uint16_t, bool, kSynthesizedClassBit, 1> {};
- class MarkedForLazyLoadingBit
- : public BitField<uint16_t, bool, kMarkedForLazyLoadingBit, 1> {};
class FieldsMarkedNullableBit
: public BitField<uint16_t, bool, kFieldsMarkedNullableBit, 1> {};
class CycleFreeBit : public BitField<uint16_t, bool, kCycleFreeBit, 1> {};
@@ -1978,6 +1968,8 @@
bool is_static_call() const;
+ intptr_t FindCheck(const GrowableArray<intptr_t>& cids) const;
+
private:
static RawICData* New();
@@ -4129,7 +4121,8 @@
}
void SetObjectAt(intptr_t index, const Object& obj) const {
ASSERT((TypeAt(index) == kTaggedObject) ||
- (TypeAt(index) == kNativeEntryData));
+ (TypeAt(index) == kNativeEntryData) ||
+ (TypeAt(index) == kImmediate && obj.IsSmi()));
StorePointer(&EntryAddr(index)->raw_obj_, obj.raw());
}
@@ -9311,7 +9304,9 @@
class TupleView {
public:
TupleView(const Array& array, intptr_t index)
- : array_(array), index_(index) {}
+ : array_(array), index_(index) {
+ ASSERT(!array.IsNull());
+ }
template <EnumType kElement>
typename std::tuple_element<kElement, TupleT>::type::RawObjectType* Get()
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 89fe81a..6edb424 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -199,7 +199,7 @@
}
}
-ObjectGraph::ObjectGraph(Thread* thread) : StackResource(thread) {
+ObjectGraph::ObjectGraph(Thread* thread) : ThreadStackResource(thread) {
// The VM isolate has all its objects pre-marked, so iterating over it
// would be a no-op.
ASSERT(thread->isolate() != Dart::vm_isolate());
diff --git a/runtime/vm/object_graph.h b/runtime/vm/object_graph.h
index 838c61d..deb700f 100644
--- a/runtime/vm/object_graph.h
+++ b/runtime/vm/object_graph.h
@@ -6,6 +6,7 @@
#define RUNTIME_VM_OBJECT_GRAPH_H_
#include "vm/allocation.h"
+#include "vm/thread_stack_resource.h"
namespace dart {
@@ -19,7 +20,7 @@
// Example uses:
// - find a retaining path from the isolate roots to a particular object, or
// - determine how much memory is retained by some particular object(s).
-class ObjectGraph : public StackResource {
+class ObjectGraph : public ThreadStackResource {
public:
class Stack;
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 2120380..22abcbb 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -20,7 +20,7 @@
bool OSThread::creation_enabled_ = false;
#if defined(HAS_C11_THREAD_LOCAL)
-thread_local Thread* OSThread::current_vm_thread_ = NULL;
+thread_local ThreadState* OSThread::current_vm_thread_ = NULL;
#endif
OSThread::OSThread()
@@ -214,7 +214,7 @@
creation_enabled_ = true;
}
-OSThread* OSThread::GetOSThreadFromThread(Thread* thread) {
+OSThread* OSThread::GetOSThreadFromThread(ThreadState* thread) {
ASSERT(thread->os_thread() != NULL);
return thread->os_thread();
}
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index aefca34..1fcf0da 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -35,7 +35,7 @@
// Forward declarations.
class Log;
class Mutex;
-class Thread;
+class ThreadState;
class TimelineEventBlock;
class BaseThread {
@@ -48,6 +48,7 @@
bool is_os_thread_;
+ friend class ThreadState;
friend class Thread;
friend class OSThread;
@@ -140,7 +141,7 @@
if (thread->is_os_thread()) {
os_thread = reinterpret_cast<OSThread*>(thread);
} else {
- Thread* vm_thread = reinterpret_cast<Thread*>(thread);
+ ThreadState* vm_thread = reinterpret_cast<ThreadState*>(thread);
os_thread = GetOSThreadFromThread(vm_thread);
}
}
@@ -159,7 +160,7 @@
static void SetCurrent(OSThread* current) { SetCurrentTLS(current); }
#if defined(HAS_C11_THREAD_LOCAL)
- static Thread* CurrentVMThread() { return current_vm_thread_; }
+ static ThreadState* CurrentVMThread() { return current_vm_thread_; }
#endif
// TODO(5411455): Use flag to override default value and Validate the
@@ -225,14 +226,14 @@
// in the windows thread interrupter which is used for profiling.
// We could eliminate this requirement if the windows thread interrupter
// is implemented differently.
- Thread* thread() const { return thread_; }
- void set_thread(Thread* value) { thread_ = value; }
+ ThreadState* thread() const { return thread_; }
+ void set_thread(ThreadState* value) { thread_ = value; }
static void Cleanup();
#ifndef PRODUCT
static ThreadId GetCurrentThreadTraceId();
#endif // PRODUCT
- static OSThread* GetOSThreadFromThread(Thread* thread);
+ static OSThread* GetOSThreadFromThread(ThreadState* thread);
static void AddThreadToListLocked(OSThread* thread);
static void RemoveThreadFromList(OSThread* thread);
static OSThread* CreateAndSetUnknownThread();
@@ -260,7 +261,7 @@
Log* log_;
uword stack_base_;
uword stack_limit_;
- Thread* thread_;
+ ThreadState* thread_;
// thread_list_lock_ cannot have a static lifetime because the order in which
// destructors run is undefined. At the moment this lock cannot be deleted
@@ -272,7 +273,7 @@
static bool creation_enabled_;
#if defined(HAS_C11_THREAD_LOCAL)
- static thread_local Thread* current_vm_thread_;
+ static thread_local ThreadState* current_vm_thread_;
#endif
friend class Isolate; // to access set_thread(Thread*).
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 8b8ce38..885009c 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -79,7 +79,7 @@
: zone_information.StandardName;
intptr_t utf8_len =
WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, NULL, 0, NULL, NULL);
- char* name = Thread::Current()->zone()->Alloc<char>(utf8_len + 1);
+ char* name = ThreadState::Current()->zone()->Alloc<char>(utf8_len + 1);
WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, name, utf8_len, NULL, NULL);
name[utf8_len] = '\0';
return name;
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 2eecb7b..ec0513f 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -4,6 +4,7 @@
#include "vm/program_visitor.h"
+#include "vm/code_patcher.h"
#include "vm/deopt_instructions.h"
#include "vm/hash_map.h"
#include "vm/object.h"
@@ -114,6 +115,66 @@
}
}
+void ProgramVisitor::BindStaticCalls() {
+#if !defined(TARGET_ARCH_DBC)
+ if (FLAG_precompiled_mode) {
+ return;
+ }
+
+ class BindJITStaticCallsVisitor : public FunctionVisitor {
+ public:
+ explicit BindJITStaticCallsVisitor(Zone* zone)
+ : code_(Code::Handle(zone)),
+ table_(Array::Handle(zone)),
+ kind_and_offset_(Smi::Handle(zone)),
+ target_(Object::Handle(zone)),
+ target_code_(Code::Handle(zone)) {}
+
+ void Visit(const Function& function) {
+ if (!function.HasCode()) {
+ return;
+ }
+ code_ = function.CurrentCode();
+ table_ = code_.static_calls_target_table();
+ StaticCallsTable static_calls(table_);
+ for (const auto& view : static_calls) {
+ kind_and_offset_ = view.Get<Code::kSCallTableKindAndOffset>();
+ Code::CallKind kind = Code::KindField::decode(kind_and_offset_.Value());
+ if (kind != Code::kCallViaCode) {
+ continue;
+ }
+ int32_t pc_offset = Code::OffsetField::decode(kind_and_offset_.Value());
+ target_ = view.Get<Code::kSCallTableFunctionTarget>();
+ if (target_.IsNull()) {
+ target_ = view.Get<Code::kSCallTableCodeTarget>();
+ ASSERT(!Code::Cast(target_).IsFunctionCode());
+ // Allocation stub or AllocateContext or AllocateArray or ...
+ } else {
+ const Function& target_func = Function::Cast(target_);
+ if (target_func.HasCode()) {
+ target_code_ = target_func.CurrentCode();
+ } else {
+ target_code_ = StubCode::CallStaticFunction().raw();
+ }
+ uword pc = pc_offset + code_.PayloadStart();
+ CodePatcher::PatchStaticCallAt(pc, code_, target_code_);
+ }
+ }
+ }
+
+ private:
+ Code& code_;
+ Array& table_;
+ Smi& kind_and_offset_;
+ Object& target_;
+ Code& target_code_;
+ };
+
+ BindJITStaticCallsVisitor visitor(Thread::Current()->zone());
+ ProgramVisitor::VisitFunctions(&visitor);
+#endif // !defined(TARGET_ARCH_DBC)
+}
+
void ProgramVisitor::ShareMegamorphicBuckets() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
@@ -821,8 +882,7 @@
StackZone stack_zone(thread);
HANDLESCOPE(thread);
- // TODO(rmacnak): Bind static calls whose target has been compiled. Forward
- // references to disabled code.
+ BindStaticCalls();
ShareMegamorphicBuckets();
DedupStackMaps();
DedupPcDescriptors();
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
index c24abe5..5583cc3 100644
--- a/runtime/vm/program_visitor.h
+++ b/runtime/vm/program_visitor.h
@@ -30,6 +30,7 @@
static void Dedup();
private:
+ static void BindStaticCalls();
static void ShareMegamorphicBuckets();
static void DedupStackMaps();
static void DedupPcDescriptors();
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 3fcb8cf..dcde53e 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -10,6 +10,7 @@
#include "vm/compiler/method_recognizer.h"
#include "vm/exceptions.h"
#include "vm/globals.h"
+#include "vm/object_graph.h"
#include "vm/snapshot.h"
#include "vm/token.h"
#include "vm/token_position.h"
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 2ae6c18..c6cee03 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -2174,11 +2174,13 @@
CodePatcher::PatchStaticCallAt(frame->pc(), caller_code, current_target_code);
caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
if (FLAG_trace_patching) {
- OS::PrintErr("FixCallersTarget: caller %#" Px
- " "
- "target '%s' -> %#" Px "\n",
- frame->pc(), target_function.ToFullyQualifiedCString(),
- current_target_code.EntryPoint());
+ OS::PrintErr(
+ "FixCallersTarget: caller %#" Px
+ " "
+ "target '%s' -> %#" Px " (%s)\n",
+ frame->pc(), target_function.ToFullyQualifiedCString(),
+ current_target_code.EntryPoint(),
+ current_target_code.is_optimized() ? "optimized" : "unoptimized");
}
ASSERT(!current_target_code.IsDisabled());
arguments.SetReturn(current_target_code);
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index 4b19f0d..3ff5758 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -50,6 +50,8 @@
__ blx(TMP);
__ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
__ str(TMP, Address(THR, Thread::vm_tag_offset()));
+ ASSERT((kAbiPreservedCpuRegs & (1 << THR)) != 0);
+ ASSERT((kAbiPreservedCpuRegs & (1 << PP)) != 0);
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 250e05f..a17870c 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -67,6 +67,8 @@
__ str(TMP, Address(THR, Thread::vm_tag_offset()));
__ mov(SP, R25);
__ mov(CSP, R23);
+ ASSERT((kAbiPreservedCpuRegs & (1 << THR)) != 0);
+ ASSERT((kAbiPreservedCpuRegs & (1 << PP)) != 0);
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index 0875c69..f84db6b 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -32,6 +32,8 @@
__ movq(Assembler::VMTagAddress(), RAX);
__ CallCFunction(RAX);
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+ ASSERT((CallingConventions::kCalleeSaveCpuRegisters & (1 << THR)) != 0);
+ ASSERT((CallingConventions::kCalleeSaveCpuRegisters & (1 << PP)) != 0);
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 25fd47c..282f198 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -4110,6 +4110,7 @@
};
static RawObject* GetObjectHelper(Thread* thread, uword addr) {
+ HeapIterationScope iteration(thread);
Object& object = Object::Handle(thread->zone());
{
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 44351459b3c1..015ecfb 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -901,7 +901,7 @@
The _streamListen_ RPC subscribes to a stream in the VM. Once
subscribed, the client will begin receiving events from the stream.
-If the client is not subscribed to the stream, the _103_ (Stream already
+If the client is already subscribed to the stream, the _103_ (Stream already
subscribed) error code is returned.
The _streamId_ parameter may have the following published values:
diff --git a/runtime/vm/service_isolate.h b/runtime/vm/service_isolate.h
index 5759658..e6ecc405f 100644
--- a/runtime/vm/service_isolate.h
+++ b/runtime/vm/service_isolate.h
@@ -12,6 +12,7 @@
namespace dart {
+class Isolate;
class ObjectPointerVisitor;
class SendPort;
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
index 03608d0..8b87a7a 100644
--- a/runtime/vm/simulator_dbc.h
+++ b/runtime/vm/simulator_dbc.h
@@ -14,18 +14,19 @@
namespace dart {
-class Isolate;
-class RawObject;
-class SimulatorSetjmpBuffer;
-class Thread;
-class Code;
class Array;
+class Code;
+class Isolate;
+class ObjectPointerVisitor;
+class RawArray;
+class RawCode;
+class RawFunction;
class RawICData;
class RawImmutableArray;
-class RawArray;
+class RawObject;
class RawObjectPool;
-class RawFunction;
-class ObjectPointerVisitor;
+class SimulatorSetjmpBuffer;
+class Thread;
// Simulator intrinsic handler. It is invoked on entry to the intrinsified
// function via Intrinsic bytecode before the frame is setup.
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 9fea664..7ce25de 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -475,15 +475,7 @@
cls = it.GetNextClass();
if (!cls.is_finalized()) {
if (compile_mode_ == kForceCompile) {
- Error& err = Error::Handle();
- if (cls.is_marked_for_lazy_loading()) {
- const String& error_message = String::Handle(
- String::New("Unable to process 'force compile' request, "
- "while the class is being finalized."));
- err = ApiError::New(error_message);
- } else {
- err = cls.EnsureIsFinalized(thread());
- }
+ Error& err = Error::Handle(cls.EnsureIsFinalized(thread()));
if (!err.IsNull()) {
// Emit an uncompiled range for this class with error information.
JSONObject range(jsarr);
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 71a8559..6709e31 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -102,6 +102,12 @@
__ LoadImmediate(R2, 0);
__ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
+ // Restore the global object pool after returning from runtime (old space is
+ // moving, so the GOP could have been relocated).
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+ }
+
__ LeaveStubFrame();
// The following return can jump to a lazy-deopt stub, which assumes R0
@@ -118,50 +124,25 @@
const RuntimeEntry* target,
intptr_t self_code_stub_offset_from_thread,
bool allow_return) {
- __ Push(LR);
-
// We want the saved registers to appear like part of the caller's frame, so
// we push them before calling EnterStubFrame.
RegisterSet all_registers;
all_registers.AddAllNonReservedRegisters(save_fpu_registers);
+
+ // To make the stack map calculation architecture independent we do the same
+ // as on intel.
+ __ Push(LR);
+
__ PushRegisters(all_registers);
-
- const intptr_t kSavedCpuRegisterSlots =
- Utils::CountOneBitsWord(kDartAvailableCpuRegs);
-
- const intptr_t kSavedFpuRegisterSlots =
- save_fpu_registers ? kNumberOfFpuRegisters * kFpuRegisterSize / kWordSize
- : 0;
-
- const intptr_t kAllSavedRegistersSlots =
- kSavedCpuRegisterSlots + kSavedFpuRegisterSlots;
-
- // Copy down the return address so the stack layout is correct.
- __ ldr(TMP, Address(SPREG, kAllSavedRegistersSlots * kWordSize));
- __ Push(TMP);
-
__ ldr(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
-
__ EnterStubFrame();
-
- __ ldr(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
- __ ldr(R9, Address(THR, Thread::OffsetFromThread(target)));
- __ mov(R4, Operand(/*argument_count=*/0));
- __ ldr(TMP, Address(THR, Thread::call_to_runtime_entry_point_offset()));
- __ blx(TMP);
-
+ __ CallRuntime(*target, /*argument_count=*/0);
if (!allow_return) {
__ Breakpoint();
return;
}
__ LeaveStubFrame();
-
- // Drop "official" return address -- we can just use the one stored above the
- // saved registers.
- __ Drop(1);
-
__ PopRegisters(all_registers);
-
__ Pop(LR);
__ bx(LR);
}
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 91996d9..182a355f 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -125,6 +125,13 @@
// Reset exit frame information in Isolate structure.
__ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+ // Restore the global object pool after returning from runtime (old space is
+ // moving, so the GOP could have been relocated).
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+ __ sub(PP, PP, Operand(kHeapObjectTag)); // Pool in PP is untagged!
+ }
+
__ LeaveStubFrame();
// The following return can jump to a lazy-deopt stub, which assumes R0
@@ -141,50 +148,24 @@
const RuntimeEntry* target,
intptr_t self_code_stub_offset_from_thread,
bool allow_return) {
- __ Push(LR);
-
// We want the saved registers to appear like part of the caller's frame, so
// we push them before calling EnterStubFrame.
RegisterSet all_registers;
all_registers.AddAllNonReservedRegisters(save_fpu_registers);
+
+ // To make the stack map calculation architecture independent we do the same
+ // as on intel.
+ __ Push(LR);
__ PushRegisters(all_registers);
-
- const intptr_t kSavedCpuRegisterSlots =
- Utils::CountOneBitsWord(kDartAvailableCpuRegs);
-
- const intptr_t kSavedFpuRegisterSlots =
- save_fpu_registers ? kNumberOfFpuRegisters * kFpuRegisterSize / kWordSize
- : 0;
-
- const intptr_t kAllSavedRegistersSlots =
- kSavedCpuRegisterSlots + kSavedFpuRegisterSlots;
-
- // Copy down the return address so the stack layout is correct.
- __ ldr(TMP, Address(SPREG, kAllSavedRegistersSlots * kWordSize));
- __ Push(TMP);
-
__ ldr(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
-
__ EnterStubFrame();
-
- __ ldr(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
- __ ldr(R5, Address(THR, Thread::OffsetFromThread(target)));
- __ LoadImmediate(R4, /*argument_count=*/0);
- __ ldr(TMP, Address(THR, Thread::call_to_runtime_entry_point_offset()));
- __ blr(TMP);
-
+ __ CallRuntime(*target, /*argument_count=*/0);
if (!allow_return) {
__ Breakpoint();
return;
}
__ LeaveStubFrame();
-
- // Drop "official" return address -- we can just use the one stored above the
- // saved registers.
- __ Drop(1);
-
__ PopRegisters(all_registers);
-
__ Pop(LR);
__ ret(LR);
}
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 7184e25..bcc2198 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -99,6 +99,12 @@
// Reset exit frame information in Isolate structure.
__ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+ // Restore the global object pool after returning from runtime (old space is
+ // moving, so the GOP could have been relocated).
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ movq(PP, Address(THR, Thread::global_object_pool_offset()));
+ }
+
__ LeaveStubFrame();
// The following return can jump to a lazy-deopt stub, which assumes RAX
@@ -136,12 +142,7 @@
__ movq(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
__ EnterStubFrame();
-
- __ movq(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
- __ movq(RBX, Address(THR, Thread::OffsetFromThread(target)));
- __ movq(R10, Immediate(/*argument_count=*/0));
- __ call(Address(THR, Thread::call_to_runtime_entry_point_offset()));
-
+ __ CallRuntime(*target, /*argument_count=*/0);
if (!allow_return) {
__ Breakpoint();
return;
diff --git a/runtime/vm/tags.cc b/runtime/vm/tags.cc
index fad8fe7..b20b42e 100644
--- a/runtime/vm/tags.cc
+++ b/runtime/vm/tags.cc
@@ -77,7 +77,7 @@
};
VMTagScope::VMTagScope(Thread* thread, uword tag, bool conditional_set)
- : StackResource(thread) {
+ : ThreadStackResource(thread) {
ASSERT(isolate() != NULL);
previous_tag_ = thread->vm_tag();
if (conditional_set) {
diff --git a/runtime/vm/tags.h b/runtime/vm/tags.h
index 7bd6aa9..4f3b665 100644
--- a/runtime/vm/tags.h
+++ b/runtime/vm/tags.h
@@ -6,6 +6,7 @@
#define RUNTIME_VM_TAGS_H_
#include "vm/allocation.h"
+#include "vm/thread_stack_resource.h"
namespace dart {
@@ -75,7 +76,7 @@
static TagEntry entries_[];
};
-class VMTagScope : StackResource {
+class VMTagScope : ThreadStackResource {
public:
VMTagScope(Thread* thread, uword tag, bool conditional_set = true);
~VMTagScope();
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 109ccd4..8756113 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -58,7 +58,7 @@
#define REUSABLE_HANDLE_INITIALIZERS(object) object##_handle_(NULL),
Thread::Thread(Isolate* isolate)
- : BaseThread(false),
+ : ThreadState(false),
stack_limit_(0),
stack_overflow_flags_(0),
write_barrier_mask_(RawObject::kGenerationalBarrierMask),
@@ -77,15 +77,9 @@
resume_pc_(0),
task_kind_(kUnknownTask),
dart_stream_(NULL),
- os_thread_(NULL),
thread_lock_(new Monitor()),
- zone_(NULL),
- current_zone_capacity_(0),
- zone_high_watermark_(0),
api_reusable_scope_(NULL),
api_top_scope_(NULL),
- top_resource_(NULL),
- long_jump_base_(NULL),
no_callback_scope_depth_(0),
#if defined(DEBUG)
top_handle_scope_(NULL),
@@ -141,20 +135,6 @@
if ((Dart::vm_isolate() != NULL) && (isolate != Dart::vm_isolate())) {
InitVMConstants();
}
-
- // This thread should not yet own any zones. If it does, we need to make sure
- // we've accounted for any memory it has already allocated.
- if (zone_ == NULL) {
- ASSERT(current_zone_capacity_ == 0);
- } else {
- Zone* current = zone_;
- uintptr_t total_zone_capacity = 0;
- while (current != NULL) {
- total_zone_capacity += current->CapacityInBytes();
- current = current->previous();
- }
- ASSERT(current_zone_capacity_ == total_zone_capacity);
- }
}
static const double double_nan_constant = NAN;
@@ -245,8 +225,8 @@
jsobj.AddPropertyF("id", "threads/%" Pd "",
OSThread::ThreadIdToIntPtr(os_thread()->trace_id()));
jsobj.AddProperty("kind", TaskKindToCString(task_kind()));
- jsobj.AddPropertyF("_zoneHighWatermark", "%" Pu "", zone_high_watermark_);
- jsobj.AddPropertyF("_zoneCapacity", "%" Pu "", current_zone_capacity_);
+ jsobj.AddPropertyF("_zoneHighWatermark", "%" Pu "", zone_high_watermark());
+ jsobj.AddPropertyF("_zoneCapacity", "%" Pu "", current_zone_capacity());
}
#endif
@@ -471,18 +451,6 @@
return interrupt_bits;
}
-bool Thread::ZoneIsOwnedByThread(Zone* zone) const {
- ASSERT(zone != NULL);
- Zone* current = zone_;
- while (current != NULL) {
- if (current == zone) {
- return true;
- }
- current = current->previous();
- }
- return false;
-}
-
void Thread::DeferOOBMessageInterrupts() {
MonitorLocker ml(thread_lock_);
defer_oob_messages_count_++;
@@ -687,8 +655,8 @@
ValidationPolicy validation_policy) {
ASSERT(visitor != NULL);
- if (zone_ != NULL) {
- zone_->VisitObjectPointers(visitor);
+ if (zone() != NULL) {
+ zone()->VisitObjectPointers(visitor);
}
// Visit objects in thread specific handles area.
@@ -832,7 +800,7 @@
#if defined(DEBUG)
bool Thread::TopErrorHandlerIsSetJump() const {
- if (long_jump_base_ == nullptr) return false;
+ if (long_jump_base() == nullptr) return false;
if (top_exit_frame_info_ == 0) return true;
#if defined(USING_SIMULATOR) || defined(USING_SAFE_STACK)
// False positives: simulator stack and native stack are unordered.
@@ -843,13 +811,13 @@
if ((interpreter_ != nullptr) && interpreter_->HasFrame(top_exit_frame_info_))
return true;
#endif
- return reinterpret_cast<uword>(long_jump_base_) < top_exit_frame_info_;
+ return reinterpret_cast<uword>(long_jump_base()) < top_exit_frame_info_;
#endif
}
bool Thread::TopErrorHandlerIsExitFrame() const {
if (top_exit_frame_info_ == 0) return false;
- if (long_jump_base_ == nullptr) return true;
+ if (long_jump_base() == nullptr) return true;
#if defined(USING_SIMULATOR) || defined(USING_SAFE_STACK)
// False positives: simulator stack and native stack are unordered.
return true;
@@ -859,7 +827,7 @@
if ((interpreter_ != nullptr) && interpreter_->HasFrame(top_exit_frame_info_))
return true;
#endif
- return top_exit_frame_info_ < reinterpret_cast<uword>(long_jump_base_);
+ return top_exit_frame_info_ < reinterpret_cast<uword>(long_jump_base());
#endif
}
#endif // defined(DEBUG)
@@ -891,7 +859,7 @@
}
bool Thread::IsValidZoneHandle(Dart_Handle object) const {
- Zone* zone = zone_;
+ Zone* zone = this->zone();
while (zone != NULL) {
if (zone->handles()->IsValidZoneHandle(reinterpret_cast<uword>(object))) {
return true;
@@ -903,7 +871,7 @@
intptr_t Thread::CountZoneHandles() const {
intptr_t count = 0;
- Zone* zone = zone_;
+ Zone* zone = this->zone();
while (zone != NULL) {
count += zone->handles()->CountZoneHandles();
zone = zone->previous();
@@ -913,7 +881,7 @@
}
bool Thread::IsValidScopedHandle(Dart_Handle object) const {
- Zone* zone = zone_;
+ Zone* zone = this->zone();
while (zone != NULL) {
if (zone->handles()->IsValidScopedHandle(reinterpret_cast<uword>(object))) {
return true;
@@ -925,7 +893,7 @@
intptr_t Thread::CountScopedHandles() const {
intptr_t count = 0;
- Zone* zone = zone_;
+ Zone* zone = this->zone();
while (zone != NULL) {
count += zone->handles()->CountScopedHandles();
zone = zone->previous();
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 9cd5fb5..0df7b36 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -16,6 +16,7 @@
#include "vm/heap/pointer_block.h"
#include "vm/os_thread.h"
#include "vm/runtime_entry_list.h"
+#include "vm/thread_state.h"
namespace dart {
@@ -38,7 +39,6 @@
class Interpreter;
class Isolate;
class Library;
-class LongJumpScope;
class Object;
class OSThread;
class JSONObject;
@@ -201,7 +201,7 @@
// a thread is allocated by EnsureInit before entering an isolate, and destroyed
// automatically when the underlying OS thread exits. NOTE: On Windows, CleanUp
// must currently be called manually (issue 23474).
-class Thread : public BaseThread {
+class Thread : public ThreadState {
public:
// The kind of task this thread is performing. Sampled by the profiler.
enum TaskKind {
@@ -220,13 +220,13 @@
// The currently executing thread, or NULL if not yet initialized.
static Thread* Current() {
#if defined(HAS_C11_THREAD_LOCAL)
- return OSThread::CurrentVMThread();
+ return static_cast<Thread*>(OSThread::CurrentVMThread());
#else
BaseThread* thread = OSThread::GetCurrentTLS();
if (thread == NULL || thread->is_os_thread()) {
return NULL;
}
- return reinterpret_cast<Thread*>(thread);
+ return static_cast<Thread*>(thread);
#endif
}
@@ -317,36 +317,9 @@
return (stack_limit_ & kInterruptsMask) != 0;
}
- // OSThread corresponding to this thread.
- OSThread* os_thread() const { return os_thread_; }
- void set_os_thread(OSThread* os_thread) { os_thread_ = os_thread; }
-
// Monitor corresponding to this thread.
Monitor* thread_lock() const { return thread_lock_; }
- // The topmost zone used for allocation in this thread.
- Zone* zone() const { return zone_; }
-
- bool ZoneIsOwnedByThread(Zone* zone) const;
-
- void IncrementMemoryCapacity(uintptr_t value) {
- current_zone_capacity_ += value;
- if (current_zone_capacity_ > zone_high_watermark_) {
- zone_high_watermark_ = current_zone_capacity_;
- }
- }
-
- void DecrementMemoryCapacity(uintptr_t value) {
- ASSERT(current_zone_capacity_ >= value);
- current_zone_capacity_ -= value;
- }
-
- uintptr_t current_zone_capacity() { return current_zone_capacity_; }
-
- uintptr_t zone_high_watermark() const { return zone_high_watermark_; }
-
- void ResetHighWatermark() { zone_high_watermark_ = current_zone_capacity_; }
-
// The reusable api local scope for this thread.
ApiLocalScope* api_reusable_scope() const { return api_reusable_scope_; }
void set_api_reusable_scope(ApiLocalScope* value) {
@@ -454,28 +427,22 @@
return OFFSET_OF(Thread, top_exit_frame_info_);
}
- StackResource* top_resource() const { return top_resource_; }
- void set_top_resource(StackResource* value) { top_resource_ = value; }
- static intptr_t top_resource_offset() {
- return OFFSET_OF(Thread, top_resource_);
- }
-
// Heap of the isolate that this thread is operating on.
Heap* heap() const { return heap_; }
static intptr_t heap_offset() { return OFFSET_OF(Thread, heap_); }
void set_top(uword value) {
- ASSERT(heap_ != NULL);
top_ = value;
}
void set_end(uword value) {
- ASSERT(heap_ != NULL);
end_ = value;
}
uword top() { return top_; }
uword end() { return end_; }
+ bool HasActiveTLAB() { return end_ > 0; }
+
static intptr_t top_offset() { return OFFSET_OF(Thread, top_); }
static intptr_t end_offset() { return OFFSET_OF(Thread, end_); }
@@ -564,9 +531,6 @@
static bool ObjectAtOffset(intptr_t offset, Object* object);
static intptr_t OffsetFromThread(const RuntimeEntry* runtime_entry);
- LongJumpScope* long_jump_base() const { return long_jump_base_; }
- void set_long_jump_base(LongJumpScope* value) { long_jump_base_ = value; }
-
#if defined(DEBUG)
// For asserts only. Has false positives when running with a simulator or
// SafeStack.
@@ -869,15 +833,9 @@
TaskKind task_kind_;
TimelineStream* dart_stream_;
- OSThread* os_thread_;
Monitor* thread_lock_;
- Zone* zone_;
- uintptr_t current_zone_capacity_;
- uintptr_t zone_high_watermark_;
ApiLocalScope* api_reusable_scope_;
ApiLocalScope* api_top_scope_;
- StackResource* top_resource_;
- LongJumpScope* long_jump_base_;
int32_t no_callback_scope_depth_;
#if defined(DEBUG)
HandleScope* top_handle_scope_;
@@ -939,8 +897,6 @@
void DeferredMarkingStackRelease();
void DeferredMarkingStackAcquire();
- void set_zone(Zone* zone) { zone_ = zone; }
-
void set_safepoint_state(uint32_t value) { safepoint_state_ = value; }
void EnterSafepointUsingLock();
void ExitSafepointUsingLock();
@@ -981,6 +937,30 @@
~DisableThreadInterruptsScope();
};
+// Within a NoSafepointScope, the thread must not reach any safepoint. Used
+// around code that manipulates raw object pointers directly without handles.
+#if defined(DEBUG)
+class NoSafepointScope : public ThreadStackResource {
+ public:
+ explicit NoSafepointScope(Thread* thread = nullptr)
+ : ThreadStackResource(thread != nullptr ? thread : Thread::Current()) {
+ this->thread()->IncrementNoSafepointScopeDepth();
+ }
+ ~NoSafepointScope() { thread()->DecrementNoSafepointScopeDepth(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
+};
+#else // defined(DEBUG)
+class NoSafepointScope : public ValueObject {
+ public:
+ explicit NoSafepointScope(Thread* thread = nullptr) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
+};
+#endif // defined(DEBUG)
+
} // namespace dart
#endif // RUNTIME_VM_THREAD_H_
diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
index 1de2c0c..d8d56b1 100644
--- a/runtime/vm/thread_interrupter.cc
+++ b/runtime/vm/thread_interrupter.cc
@@ -36,16 +36,6 @@
// The ThreadInterrupter has a single monitor (monitor_). This monitor is used
// to synchronize startup, shutdown, and waking up from a deep sleep.
//
-// A thread can only register and unregister itself. Each thread has a heap
-// allocated ThreadState. A thread's ThreadState is lazily allocated the first
-// time the thread is registered. A pointer to a thread's ThreadState is stored
-// in the list of threads registered to receive interrupts (threads_) and in
-// thread local storage. When a thread's ThreadState is being modified, the
-// thread local storage pointer is temporarily set to NULL while the
-// modification is occurring. After the ThreadState has been updated, the
-// thread local storage pointer is set again. This has an important side
-// effect: if the thread is interrupted by a signal handler during a ThreadState
-// update the signal handler will immediately return.
DEFINE_FLAG(bool, trace_thread_interrupter, false, "Trace thread interrupter");
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
index 13c6f8d..c862a22 100644
--- a/runtime/vm/thread_interrupter_win.cc
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -81,7 +81,7 @@
// Currently we sample only threads that are associated
// with an isolate. It is safe to call 'os_thread->thread()'
// here as the thread which is being queried is suspended.
- Thread* thread = os_thread->thread();
+ Thread* thread = static_cast<Thread*>(os_thread->thread());
if (thread != NULL) {
Profiler::SampleThread(thread, its);
}
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index a390528..2052d4a 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -192,7 +192,7 @@
void ThreadRegistry::ReturnToFreelistLocked(Thread* thread) {
ASSERT(thread != NULL);
- ASSERT(thread->os_thread_ == NULL);
+ ASSERT(thread->os_thread() == NULL);
ASSERT(thread->isolate_ == NULL);
ASSERT(thread->heap_ == NULL);
ASSERT(threads_lock()->IsOwnedByCurrentThread());
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index 2d6ad35..fda9474 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -83,6 +83,7 @@
friend class Isolate;
friend class SafepointHandler;
+ friend class Scavenger;
DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
};
diff --git a/runtime/vm/thread_stack_resource.cc b/runtime/vm/thread_stack_resource.cc
new file mode 100644
index 0000000..69faf94
--- /dev/null
+++ b/runtime/vm/thread_stack_resource.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, 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.
+
+#include "vm/thread_stack_resource.h"
+
+#include "platform/assert.h"
+#include "vm/isolate.h"
+#include "vm/thread.h"
+#include "vm/zone.h"
+
+namespace dart {
+
+ThreadStackResource::~ThreadStackResource() {
+#if defined(DEBUG)
+ if (thread() != nullptr) {
+ BaseIsolate::AssertCurrent(reinterpret_cast<BaseIsolate*>(isolate()));
+ }
+#endif
+}
+
+Isolate* ThreadStackResource::isolate() const {
+ return thread()->isolate();
+}
+
+} // namespace dart
diff --git a/runtime/vm/thread_stack_resource.h b/runtime/vm/thread_stack_resource.h
new file mode 100644
index 0000000..abbf521
--- /dev/null
+++ b/runtime/vm/thread_stack_resource.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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.
+
+#ifndef RUNTIME_VM_THREAD_STACK_RESOURCE_H_
+#define RUNTIME_VM_THREAD_STACK_RESOURCE_H_
+
+#include "vm/allocation.h"
+#include "vm/globals.h"
+
+namespace dart {
+
+class Isolate;
+class ThreadState;
+class Thread;
+
+class ThreadStackResource : public StackResource {
+ public:
+ explicit ThreadStackResource(Thread* T)
+ : StackResource(reinterpret_cast<ThreadState*>(T)) {}
+
+ ~ThreadStackResource();
+
+ Thread* thread() const {
+ return reinterpret_cast<Thread*>(StackResource::thread());
+ }
+ Isolate* isolate() const;
+};
+
+} // namespace dart
+
+#endif // RUNTIME_VM_THREAD_STACK_RESOURCE_H_
diff --git a/runtime/vm/thread_state.cc b/runtime/vm/thread_state.cc
new file mode 100644
index 0000000..d5e37e3
--- /dev/null
+++ b/runtime/vm/thread_state.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, 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.
+
+#include "vm/thread_state.h"
+
+#include "vm/zone.h"
+
+namespace dart {
+
+ThreadState::ThreadState(bool is_os_thread) : BaseThread(is_os_thread) {
+ // This thread should not yet own any zones. If it does, we need to make sure
+ // we've accounted for any memory it has already allocated.
+ if (zone_ == nullptr) {
+ ASSERT(current_zone_capacity_ == 0);
+ } else {
+ Zone* current = zone_;
+ uintptr_t total_zone_capacity = 0;
+ while (current != nullptr) {
+ total_zone_capacity += current->CapacityInBytes();
+ current = current->previous();
+ }
+ ASSERT(current_zone_capacity_ == total_zone_capacity);
+ }
+}
+
+ThreadState::~ThreadState() {}
+
+bool ThreadState::ZoneIsOwnedByThread(Zone* zone) const {
+ ASSERT(zone != nullptr);
+ Zone* current = zone_;
+ while (current != nullptr) {
+ if (current == zone) {
+ return true;
+ }
+ current = current->previous();
+ }
+ return false;
+}
+
+} // namespace dart
diff --git a/runtime/vm/thread_state.h b/runtime/vm/thread_state.h
new file mode 100644
index 0000000..85106d2
--- /dev/null
+++ b/runtime/vm/thread_state.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2019, 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.
+
+#ifndef RUNTIME_VM_THREAD_STATE_H_
+#define RUNTIME_VM_THREAD_STATE_H_
+
+#include "vm/os_thread.h"
+
+namespace dart {
+
+class LongJumpScope;
+class Zone;
+
+// ThreadState is a container for auxiliary thread-local state: e.g. it
+// owns a stack of Zones for allocation and a stack of StackResources
+// for stack unwinding.
+//
+// Important: this class is shared between compiler and runtime and
+// as such it should not expose any runtime internals due to layering
+// restrictions.
+class ThreadState : public BaseThread {
+ public:
+ // The currently executing thread, or NULL if not yet initialized.
+ static ThreadState* Current() {
+#if defined(HAS_C11_THREAD_LOCAL)
+ return OSThread::CurrentVMThread();
+#else
+ BaseThread* thread = OSThread::GetCurrentTLS();
+ if (thread == NULL || thread->is_os_thread()) {
+ return NULL;
+ }
+ return static_cast<ThreadState*>(thread);
+#endif
+ }
+
+ explicit ThreadState(bool is_os_thread);
+ ~ThreadState();
+
+ // OSThread corresponding to this thread.
+ OSThread* os_thread() const { return os_thread_; }
+ void set_os_thread(OSThread* os_thread) { os_thread_ = os_thread; }
+
+ // The topmost zone used for allocation in this thread.
+ Zone* zone() const { return zone_; }
+
+ bool ZoneIsOwnedByThread(Zone* zone) const;
+
+ void IncrementMemoryCapacity(uintptr_t value) {
+ current_zone_capacity_ += value;
+ if (current_zone_capacity_ > zone_high_watermark_) {
+ zone_high_watermark_ = current_zone_capacity_;
+ }
+ }
+
+ void DecrementMemoryCapacity(uintptr_t value) {
+ ASSERT(current_zone_capacity_ >= value);
+ current_zone_capacity_ -= value;
+ }
+
+ uintptr_t current_zone_capacity() const { return current_zone_capacity_; }
+ uintptr_t zone_high_watermark() const { return zone_high_watermark_; }
+
+ void ResetHighWatermark() { zone_high_watermark_ = current_zone_capacity_; }
+
+ StackResource* top_resource() const { return top_resource_; }
+ void set_top_resource(StackResource* value) { top_resource_ = value; }
+ static intptr_t top_resource_offset() {
+ return OFFSET_OF(ThreadState, top_resource_);
+ }
+
+ LongJumpScope* long_jump_base() const { return long_jump_base_; }
+ void set_long_jump_base(LongJumpScope* value) { long_jump_base_ = value; }
+
+ private:
+ void set_zone(Zone* zone) { zone_ = zone; }
+
+ OSThread* os_thread_ = nullptr;
+ Zone* zone_ = nullptr;
+ uintptr_t current_zone_capacity_ = 0;
+ uintptr_t zone_high_watermark_ = 0;
+ StackResource* top_resource_ = nullptr;
+ LongJumpScope* long_jump_base_ = nullptr;
+
+ friend class ApiZone;
+ friend class StackZone;
+};
+
+} // namespace dart
+
+#endif // RUNTIME_VM_THREAD_STATE_H_
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index c38fd76..bca4938 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -748,7 +748,7 @@
}
TypeUsageInfo::TypeUsageInfo(Thread* thread)
- : StackResource(thread),
+ : ThreadStackResource(thread),
zone_(thread->zone()),
finder_(zone_),
assert_assignable_types_(),
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index 423b4d7..e8c7044 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -317,7 +317,7 @@
};
// Collects data on how [Type] objects are used in generated code.
-class TypeUsageInfo : public StackResource {
+class TypeUsageInfo : public ThreadStackResource {
public:
explicit TypeUsageInfo(Thread* thread);
~TypeUsageInfo();
diff --git a/runtime/vm/uri.cc b/runtime/vm/uri.cc
index 67fbcbf..5e75ef1 100644
--- a/runtime/vm/uri.cc
+++ b/runtime/vm/uri.cc
@@ -80,7 +80,7 @@
static char* NormalizeEscapes(const char* str, intptr_t len) {
// Allocate the buffer.
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
// We multiply len by three because a percent-escape sequence is
// three characters long (e.g. ' ' -> '%20). +1 for '\0'. We could
// take two passes through the string and avoid the excess
@@ -156,7 +156,7 @@
}
static intptr_t ParseAuthority(const char* authority, ParsedUri* parsed_uri) {
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
const char* current = authority;
intptr_t len = 0;
@@ -191,7 +191,7 @@
// Performs a simple parse of a uri into its components.
// See RFC 3986 Section 3: Syntax.
bool ParseUri(const char* uri, ParsedUri* parsed_uri) {
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
// The first ':' separates the scheme from the rest of the uri. If
// a ':' occurs after the first '/' it doesn't count.
@@ -284,7 +284,7 @@
// The output path will always be less than or equal to the size of
// the input path.
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
char* buffer = zone->Alloc<char>(strlen(path) + 1); // +1 for '\0'
char* output = buffer;
@@ -342,7 +342,7 @@
// See RFC 3986 Section 5.2.3: Merge Paths.
static const char* MergePaths(const char* base_path, const char* ref_path) {
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
if (base_path[0] == '\0') {
// If the base_path is empty, we prepend '/'.
return zone->PrintToString("/%s", ref_path);
@@ -378,7 +378,7 @@
}
static char* BuildUri(const ParsedUri& uri) {
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
ASSERT(uri.path != NULL);
const char* fragment = uri.fragment == NULL ? "" : uri.fragment;
@@ -436,7 +436,7 @@
ParsedUri target;
if (ref.scheme != NULL) {
if (strcmp(ref.scheme, "dart") == 0) {
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
*target_uri = zone->MakeCopyOfString(ref_uri);
return true;
}
@@ -461,7 +461,7 @@
}
if ((base.scheme != NULL) && strcmp(base.scheme, "dart") == 0) {
- Zone* zone = Thread::Current()->zone();
+ Zone* zone = ThreadState::Current()->zone();
*target_uri = zone->MakeCopyOfString(ref_uri);
return true;
}
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 593b76d..82b9645 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -312,6 +312,10 @@
"thread_pool.h",
"thread_registry.cc",
"thread_registry.h",
+ "thread_stack_resource.cc",
+ "thread_stack_resource.h",
+ "thread_state.cc",
+ "thread_state.h",
"timeline.cc",
"timeline.h",
"timeline_analysis.cc",
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 313e452..8227e48 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -75,7 +75,7 @@
}
void Zone::Segment::IncrementMemoryCapacity(uintptr_t size) {
- Thread* current_thread = Thread::Current();
+ ThreadState* current_thread = ThreadState::Current();
if (current_thread != NULL) {
current_thread->IncrementMemoryCapacity(size);
} else if (ApiNativeScope::Current() != NULL) {
@@ -85,7 +85,7 @@
}
void Zone::Segment::DecrementMemoryCapacity(uintptr_t size) {
- Thread* current_thread = Thread::Current();
+ ThreadState* current_thread = ThreadState::Current();
if (current_thread != NULL) {
current_thread->DecrementMemoryCapacity(size);
} else if (ApiNativeScope::Current() != NULL) {
@@ -288,7 +288,7 @@
return OS::VSCreate(this, format, args);
}
-StackZone::StackZone(Thread* thread) : StackResource(thread), zone_() {
+StackZone::StackZone(ThreadState* thread) : StackResource(thread), zone_() {
if (FLAG_trace_zones) {
OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
reinterpret_cast<intptr_t>(this),
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index b892cdc..b4aba7f 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -8,9 +8,8 @@
#include "platform/utils.h"
#include "vm/allocation.h"
#include "vm/handles.h"
-#include "vm/json_stream.h"
#include "vm/memory_region.h"
-#include "vm/thread.h"
+#include "vm/thread_state.h"
namespace dart {
@@ -175,7 +174,7 @@
class StackZone : public StackResource {
public:
// Create an empty zone and set is at the current zone for the Thread.
- explicit StackZone(Thread* thread);
+ explicit StackZone(ThreadState* thread);
// Delete all memory associated with the zone.
~StackZone();
diff --git a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
index 7138c65..fc7a3bf 100644
--- a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -21,6 +21,8 @@
const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
+const int _mask30 = 0x3fffffff; // Low 30 bits.
+
@patch
class HashMap<K, V> {
@patch
@@ -306,14 +308,14 @@
// Only treat unsigned 30-bit integers as numeric keys. This way,
// we avoid converting them to strings when we use them as keys in
// the JavaScript hash table object.
- return key is num && JS('bool', '(# & 0x3ffffff) === #', key, key);
+ return key is num && JS('bool', '(# & #) === #', key, _mask30, key);
}
int _computeHashCode(var key) {
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', key.hashCode);
+ return JS('int', '# & #', key.hashCode, _mask30);
}
static bool _hasTableEntry(var table, var key) {
@@ -382,7 +384,7 @@
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', identityHashCode(key));
+ return JS('int', '# & #', identityHashCode(key), _mask30);
}
int _findBucketIndex(var bucket, var key) {
@@ -426,7 +428,7 @@
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', _hashCode(key));
+ return JS('int', '# & #', _hashCode(key), _mask30);
}
int _findBucketIndex(var bucket, var key) {
@@ -576,7 +578,7 @@
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', identityHashCode(key));
+ return JS('int', '# & #', identityHashCode(key), _mask30);
}
int internalFindBucketIndex(var bucket, var key) {
@@ -669,7 +671,7 @@
// always unboxed (Smi) values. Modification detection will be missed if you
// make exactly some multiple of 2^30 modifications between advances of an
// iterator.
- _modifications = (_modifications + 1) & 0x3ffffff;
+ _modifications = _mask30 & (_modifications + 1);
}
}
@@ -779,7 +781,7 @@
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', _hashCode(key));
+ return JS('int', '# & #', _hashCode(key), _mask30);
}
int internalFindBucketIndex(var bucket, var key) {
@@ -1050,7 +1052,7 @@
// way, we avoid converting them to strings when we use them as
// keys in the JavaScript hash table object.
return element is num &&
- JS('bool', '(# & 0x3ffffff) === #', element, element);
+ JS('bool', '(# & #) === #', element, _mask30, element);
}
int _computeHashCode(var element) {
@@ -1058,7 +1060,7 @@
// issues with problematic elements like '__proto__'. Another
// option would be to throw an exception if the hash code isn't a
// number.
- return JS('int', '# & 0x3ffffff', element.hashCode);
+ return JS('int', '# & #', element.hashCode, _mask30);
}
static bool _hasTableEntry(var table, var key) {
@@ -1114,7 +1116,7 @@
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', identityHashCode(key));
+ return JS('int', '# & #', identityHashCode(key), _mask30);
}
int _findBucketIndex(var bucket, var element) {
@@ -1151,7 +1153,7 @@
// issues with problematic elements like '__proto__'. Another
// option would be to throw an exception if the hash code isn't a
// number.
- return JS('int', '# & 0x3ffffff', _hasher(element));
+ return JS('int', '# & #', _hasher(element), _mask30);
}
bool add(E object) => super._add(object);
@@ -1451,7 +1453,7 @@
// Value cycles after 2^30 modifications. If you keep hold of an
// iterator for that long, you might miss a modification
// detection, and iteration can go sour. Don't do that.
- _modifications = (_modifications + 1) & 0x3ffffff;
+ _modifications = _mask30 & (_modifications + 1);
}
// Create a new cell and link it in as the last one in the list.
@@ -1498,7 +1500,7 @@
// way, we avoid converting them to strings when we use them as
// keys in the JavaScript hash table object.
return element is num &&
- JS('bool', '(# & 0x3ffffff) === #', element, element);
+ JS('bool', '(# & #) === #', element, _mask30, element);
}
int _computeHashCode(var element) {
@@ -1506,7 +1508,7 @@
// issues with problematic elements like '__proto__'. Another
// option would be to throw an exception if the hash code isn't a
// number.
- return JS('int', '# & 0x3ffffff', element.hashCode);
+ return JS('int', '# & #', element.hashCode, _mask30);
}
static _getTableEntry(var table, var key) {
@@ -1559,7 +1561,7 @@
// We force the hash codes to be unsigned 30-bit integers to avoid
// issues with problematic keys like '__proto__'. Another option
// would be to throw an exception if the hash code isn't a number.
- return JS('int', '# & 0x3ffffff', identityHashCode(key));
+ return JS('int', '# & #', identityHashCode(key), _mask30);
}
int _findBucketIndex(var bucket, var element) {
@@ -1600,7 +1602,7 @@
// issues with problematic elements like '__proto__'. Another
// option would be to throw an exception if the hash code isn't a
// number.
- return JS('int', '# & 0x3ffffff', _hasher(element));
+ return JS('int', '# & #', _hasher(element), _mask30);
}
bool add(E element) => super._add(element);
@@ -1671,3 +1673,30 @@
}
}
}
+
+@patch
+abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
+ @patch
+ Node _splayMin(Node node) {
+ Node current = node;
+ while (current.left != null) {
+ Node left = current.left;
+ current.left = left.right;
+ left.right = current;
+ current = left;
+ }
+ return current;
+ }
+
+ @patch
+ Node _splayMax(Node node) {
+ Node current = node;
+ while (current.right != null) {
+ Node right = current.right;
+ current.right = right.left;
+ right.left = current;
+ current = right;
+ }
+ return current;
+ }
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
index afb5062..a8dcc31 100644
--- a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
@@ -11,22 +11,20 @@
import 'dart:collection' show LinkedHashMap, MapBase;
import 'dart:_native_typed_data' show NativeUint8List;
-/**
- * Parses [json] and builds the corresponding parsed JSON value.
- *
- * Parsed JSON values Nare of the types [num], [String], [bool], [Null],
- * [List]s of parsed JSON values or [Map]s from [String] to parsed
- * JSON values.
- *
- * The optional [reviver] function, if provided, is called once for each object
- * or list property parsed. The arguments are the property name ([String]) or
- * list index ([int]), and the value is the parsed value. The return value of
- * the reviver will be used as the value of that property instead of the parsed
- * value. The top level value is passed to the reviver with the empty string as
- * a key.
- *
- * Throws [FormatException] if the input is not valid JSON text.
- */
+/// Parses [json] and builds the corresponding parsed JSON value.
+///
+/// Parsed JSON values Nare of the types [num], [String], [bool], [Null],
+/// [List]s of parsed JSON values or [Map]s from [String] to parsed
+/// JSON values.
+///
+/// The optional [reviver] function, if provided, is called once for each object
+/// or list property parsed. The arguments are the property name ([String]) or
+/// list index ([int]), and the value is the parsed value. The return value of
+/// the reviver will be used as the value of that property instead of the parsed
+/// value. The top level value is passed to the reviver with the empty string
+/// as a key.
+///
+/// Throws [FormatException] if the input is not valid JSON text.
@patch
_parseJson(String source, reviver(key, value)) {
if (source is! String) throw argumentErrorValue(source);
@@ -46,11 +44,9 @@
}
}
-/**
- * Walks the raw JavaScript value [json], replacing JavaScript Objects with
- * Maps. [json] is expected to be freshly allocated so elements can be replaced
- * in-place.
- */
+/// Walks the raw JavaScript value [json], replacing JavaScript Objects with
+/// Maps. [json] is expected to be freshly allocated so elements can be replaced
+/// in-place.
_convertJsonToDart(json, reviver(key, value)) {
assert(reviver != null);
walk(e) {
@@ -365,12 +361,10 @@
}
}
-/**
- * Implements the chunked conversion from a JSON string to its corresponding
- * object.
- *
- * The sink only creates one object, but its input can be chunked.
- */
+/// Implements the chunked conversion from a JSON string to its corresponding
+/// object.
+///
+/// The sink only creates one object, but its input can be chunked.
// TODO(floitsch): don't accumulate everything before starting to decode.
class _JsonDecoderSink extends _StringSinkConversionSink {
final _Reviver _reviver;
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index a5438a4..27d7d25 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -80,14 +80,6 @@
@patch
static apply(Function function, List positionalArguments,
[Map<Symbol, dynamic> namedArguments]) {
- // The lazy and startup emitter use a different implementation. To keep the
- // method small and inlinable, just select the method.
- return JS_GET_FLAG("IS_FULL_EMITTER")
- ? _apply1(function, positionalArguments, namedArguments)
- : _apply2(function, positionalArguments, namedArguments);
- }
-
- static _apply1(function, positionalArguments, namedArguments) {
return Primitives.applyFunction(
function,
positionalArguments,
@@ -95,15 +87,6 @@
// tree-shake _symbolMapToStringMap.
namedArguments == null ? null : _symbolMapToStringMap(namedArguments));
}
-
- static _apply2(function, positionalArguments, namedArguments) {
- return Primitives.applyFunction2(
- function,
- positionalArguments,
- // Use this form so that if namedArguments is always null, we can
- // tree-shake _symbolMapToStringMap.
- namedArguments == null ? null : _symbolMapToStringMap(namedArguments));
- }
}
// Patch for Expando implementation.
@@ -702,11 +685,9 @@
// are not encoded by any encoding table.
static final RegExp _needsNoEncoding = new RegExp(r'^[\-\.0-9A-Z_a-z~]*$');
- /**
- * This is the internal implementation of JavaScript's encodeURI function.
- * It encodes all characters in the string [text] except for those
- * that appear in [canonicalTable], and returns the escaped string.
- */
+ /// This is the internal implementation of JavaScript's encodeURI function.
+ /// It encodes all characters in the string [text] except for those
+ /// that appear in [canonicalTable], and returns the escaped string.
@patch
static String _uriEncode(List<int> canonicalTable, String text,
Encoding encoding, bool spaceToPlus) {
@@ -896,12 +877,10 @@
* and disclaimer.
*/
-/**
- * An implementation for the arbitrarily large integer.
- *
- * The integer number is represented by a sign, an array of 16-bit unsigned
- * integers in little endian format, and a number of used digits in that array.
- */
+/// An implementation for the arbitrarily large integer.
+///
+/// The integer number is represented by a sign, an array of 16-bit unsigned
+/// integers in little endian format, and a number of used digits in that array.
class _BigIntImpl implements BigInt {
// Bits per digit.
static const int _digitBits = 16;
@@ -942,29 +921,27 @@
/// replaced.
final int _used;
- /**
- * Parses [source] as a, possibly signed, integer literal and returns its
- * value.
- *
- * The [source] must be a non-empty sequence of base-[radix] digits,
- * optionally prefixed with a minus or plus sign ('-' or '+').
- *
- * The [radix] must be in the range 2..36. The digits used are
- * first the decimal digits 0..9, and then the letters 'a'..'z' with
- * values 10 through 35. Also accepts upper-case letters with the same
- * values as the lower-case ones.
- *
- * If no [radix] is given then it defaults to 10. In this case, the [source]
- * digits may also start with `0x`, in which case the number is interpreted
- * as a hexadecimal literal, which effectively means that the `0x` is ignored
- * and the radix is instead set to 16.
- *
- * For any int `n` and radix `r`, it is guaranteed that
- * `n == int.parse(n.toRadixString(r), radix: r)`.
- *
- * Throws a [FormatException] if the [source] is not a valid integer literal,
- * optionally prefixed by a sign.
- */
+ /// Parses [source] as a, possibly signed, integer literal and returns its
+ /// value.
+ ///
+ /// The [source] must be a non-empty sequence of base-[radix] digits,
+ /// optionally prefixed with a minus or plus sign ('-' or '+').
+ ///
+ /// The [radix] must be in the range 2..36. The digits used are
+ /// first the decimal digits 0..9, and then the letters 'a'..'z' with
+ /// values 10 through 35. Also accepts upper-case letters with the same
+ /// values as the lower-case ones.
+ ///
+ /// If no [radix] is given then it defaults to 10. In this case, the [source]
+ /// digits may also start with `0x`, in which case the number is interpreted
+ /// as a hexadecimal literal, which effectively means that the `0x` is ignored
+ /// and the radix is instead set to 16.
+ ///
+ /// For any int `n` and radix `r`, it is guaranteed that
+ /// `n == int.parse(n.toRadixString(r), radix: r)`.
+ ///
+ /// Throws a [FormatException] if the [source] is not a valid integer literal,
+ /// optionally prefixed by a sign.
static _BigIntImpl parse(String source, {int radix}) {
var result = _tryParse(source, radix: radix);
if (result == null) {
@@ -1250,22 +1227,18 @@
return absResult;
}
- /**
- * Return the negative value of this integer.
- *
- * The result of negating an integer always has the opposite sign, except
- * for zero, which is its own negation.
- */
+ /// Return the negative value of this integer.
+ ///
+ /// The result of negating an integer always has the opposite sign, except
+ /// for zero, which is its own negation.
_BigIntImpl operator -() {
if (_used == 0) return this;
return new _BigIntImpl._(!_isNegative, _used, _digits);
}
- /**
- * Returns the absolute value of this integer.
- *
- * For any integer `x`, the result is the same as `x < 0 ? -x : x`.
- */
+ /// Returns the absolute value of this integer.
+ ///
+ /// For any integer `x`, the result is the same as `x < 0 ? -x : x`.
_BigIntImpl abs() => _isNegative ? -this : this;
/// Returns this << n *_DIGIT_BITS.
@@ -1355,18 +1328,16 @@
resultDigits[digitShift] = carry;
}
- /**
- * Shift the bits of this integer to the left by [shiftAmount].
- *
- * Shifting to the left makes the number larger, effectively multiplying
- * the number by `pow(2, shiftIndex)`.
- *
- * There is no limit on the size of the result. It may be relevant to
- * limit intermediate values by using the "and" operator with a suitable
- * mask.
- *
- * It is an error if [shiftAmount] is negative.
- */
+ /// Shift the bits of this integer to the left by [shiftAmount].
+ ///
+ /// Shifting to the left makes the number larger, effectively multiplying
+ /// the number by `pow(2, shiftIndex)`.
+ ///
+ /// There is no limit on the size of the result. It may be relevant to
+ /// limit intermediate values by using the "and" operator with a suitable
+ /// mask.
+ ///
+ /// It is an error if [shiftAmount] is negative.
_BigIntImpl operator <<(int shiftAmount) {
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be posititve $shiftAmount");
@@ -1422,15 +1393,13 @@
resultDigits[last] = carry;
}
- /**
- * Shift the bits of this integer to the right by [shiftAmount].
- *
- * Shifting to the right makes the number smaller and drops the least
- * significant bits, effectively doing an integer division by
- *`pow(2, shiftIndex)`.
- *
- * It is an error if [shiftAmount] is negative.
- */
+ /// Shift the bits of this integer to the right by [shiftAmount].
+ ///
+ /// Shifting to the right makes the number smaller and drops the least
+ /// significant bits, effectively doing an integer division by
+ /// `pow(2, shiftIndex)`.
+ ///
+ /// It is an error if [shiftAmount] is negative.
_BigIntImpl operator >>(int shiftAmount) {
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be posititve $shiftAmount");
@@ -1473,12 +1442,10 @@
return _compareDigits(_digits, _used, other._digits, other._used);
}
- /**
- * Compares this to `other`.
- *
- * Returns a negative number if `this` is less than `other`, zero if they are
- * equal, and a positive number if `this` is greater than `other`.
- */
+ /// Compares this to `other`.
+ ///
+ /// Returns a negative number if `this` is less than `other`, zero if they are
+ /// equal, and a positive number if `this` is greater than `other`.
int compareTo(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (_isNegative == other._isNegative) {
@@ -1666,16 +1633,14 @@
return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
}
- /**
- * Bit-wise and operator.
- *
- * Treating both `this` and [other] as sufficiently large two's component
- * integers, the result is a number with only the bits set that are set in
- * both `this` and [other]
- *
- * Of both operands are negative, the result is negative, otherwise
- * the result is non-negative.
- */
+ /// Bit-wise and operator.
+ ///
+ /// Treating both `this` and [other] as sufficiently large two's component
+ /// integers, the result is a number with only the bits set that are set in
+ /// both `this` and [other]
+ ///
+ /// Of both operands are negative, the result is negative, otherwise
+ /// the result is non-negative.
_BigIntImpl operator &(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (_isZero || other._isZero) return zero;
@@ -1706,16 +1671,14 @@
return p._absAndNotSetSign(n1, false);
}
- /**
- * Bit-wise or operator.
- *
- * Treating both `this` and [other] as sufficiently large two's component
- * integers, the result is a number with the bits set that are set in either
- * of `this` and [other]
- *
- * If both operands are non-negative, the result is non-negative,
- * otherwise the result us negative.
- */
+ /// Bit-wise or operator.
+ ///
+ /// Treating both `this` and [other] as sufficiently large two's component
+ /// integers, the result is a number with the bits set that are set in either
+ /// of `this` and [other]
+ ///
+ /// If both operands are non-negative, the result is non-negative,
+ /// otherwise the result us negative.
_BigIntImpl operator |(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (_isZero) return other;
@@ -1748,16 +1711,14 @@
return n1._absAndNotSetSign(p, true)._absAddSetSign(one, true);
}
- /**
- * Bit-wise exclusive-or operator.
- *
- * Treating both `this` and [other] as sufficiently large two's component
- * integers, the result is a number with the bits set that are set in one,
- * but not both, of `this` and [other]
- *
- * If the operands have the same sign, the result is non-negative,
- * otherwise the result is negative.
- */
+ /// Bit-wise exclusive-or operator.
+ ///
+ /// Treating both `this` and [other] as sufficiently large two's component
+ /// integers, the result is a number with the bits set that are set in one,
+ /// but not both, of `this` and [other]
+ ///
+ /// If the operands have the same sign, the result is non-negative,
+ /// otherwise the result is negative.
_BigIntImpl operator ^(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (_isZero) return other;
@@ -1787,14 +1748,12 @@
return p._absXorSetSign(n1, true)._absAddSetSign(one, true);
}
- /**
- * The bit-wise negate operator.
- *
- * Treating `this` as a sufficiently large two's component integer,
- * the result is a number with the opposite bits set.
- *
- * This maps any integer `x` to `-x - 1`.
- */
+ /// The bit-wise negate operator.
+ ///
+ /// Treating `this` as a sufficiently large two's component integer,
+ /// the result is a number with the opposite bits set.
+ ///
+ /// This maps any integer `x` to `-x - 1`.
_BigIntImpl operator ~() {
if (_isZero) return _minusOne;
if (_isNegative) {
@@ -2090,65 +2049,59 @@
return finish(hash);
}
- /**
- * Test whether this value is numerically equal to `other`.
- *
- * If [other] is a [_BigIntImpl] returns whether the two operands have the same
- * value.
- *
- * Returns false if `other` is not a [_BigIntImpl].
- */
+ /// Test whether this value is numerically equal to `other`.
+ ///
+ /// If [other] is a [_BigIntImpl] returns whether the two operands have the
+ /// same value.
+ ///
+ /// Returns false if `other` is not a [_BigIntImpl].
bool operator ==(Object other) =>
other is _BigIntImpl && compareTo(other) == 0;
- /**
- * Returns the minimum number of bits required to store this big integer.
- *
- * The number of bits excludes the sign bit, which gives the natural length
- * for non-negative (unsigned) values. Negative values are complemented to
- * return the bit position of the first bit that differs from the sign bit.
- *
- * To find the number of bits needed to store the value as a signed value,
- * add one, i.e. use `x.bitLength + 1`.
- *
- * ```
- * x.bitLength == (-x-1).bitLength
- *
- * new BigInt.from(3).bitLength == 2; // 00000011
- * new BigInt.from(2).bitLength == 2; // 00000010
- * new BigInt.from(1).bitLength == 1; // 00000001
- * new BigInt.from(0).bitLength == 0; // 00000000
- * new BigInt.from(-1).bitLength == 0; // 11111111
- * new BigInt.from(-2).bitLength == 1; // 11111110
- * new BigInt.from(-3).bitLength == 2; // 11111101
- * new BigInt.from(-4).bitLength == 2; // 11111100
- * ```
- */
+ /// Returns the minimum number of bits required to store this big integer.
+ ///
+ /// The number of bits excludes the sign bit, which gives the natural length
+ /// for non-negative (unsigned) values. Negative values are complemented to
+ /// return the bit position of the first bit that differs from the sign bit.
+ ///
+ /// To find the number of bits needed to store the value as a signed value,
+ /// add one, i.e. use `x.bitLength + 1`.
+ ///
+ /// ```
+ /// x.bitLength == (-x-1).bitLength
+ ///
+ /// new BigInt.from(3).bitLength == 2; // 00000011
+ /// new BigInt.from(2).bitLength == 2; // 00000010
+ /// new BigInt.from(1).bitLength == 1; // 00000001
+ /// new BigInt.from(0).bitLength == 0; // 00000000
+ /// new BigInt.from(-1).bitLength == 0; // 11111111
+ /// new BigInt.from(-2).bitLength == 1; // 11111110
+ /// new BigInt.from(-3).bitLength == 2; // 11111101
+ /// new BigInt.from(-4).bitLength == 2; // 11111100
+ /// ```
int get bitLength {
if (_used == 0) return 0;
if (_isNegative) return (~this).bitLength;
return _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
}
- /**
- * Truncating division operator.
- *
- * Performs a truncating integer division, where the remainder is discarded.
- *
- * The remainder can be computed using the [remainder] method.
- *
- * Examples:
- * ```
- * var seven = new BigInt.from(7);
- * var three = new BigInt.from(3);
- * seven ~/ three; // => 2
- * (-seven) ~/ three; // => -2
- * seven ~/ -three; // => -2
- * seven.remainder(three); // => 1
- * (-seven).remainder(three); // => -1
- * seven.remainder(-three); // => 1
- * ```
- */
+ /// Truncating division operator.
+ ///
+ /// Performs a truncating integer division, where the remainder is discarded.
+ ///
+ /// The remainder can be computed using the [remainder] method.
+ ///
+ /// Examples:
+ /// ```
+ /// var seven = new BigInt.from(7);
+ /// var three = new BigInt.from(3);
+ /// seven ~/ three; // => 2
+ /// (-seven) ~/ three; // => -2
+ /// seven ~/ -three; // => -2
+ /// seven.remainder(three); // => 1
+ /// (-seven).remainder(three); // => -1
+ /// seven.remainder(-three); // => 1
+ /// ```
_BigIntImpl operator ~/(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (other._used == 0) {
@@ -2157,13 +2110,12 @@
return _div(other);
}
- /**
- * Returns the remainder of the truncating division of `this` by [other].
- *
- * The result `r` of this operation satisfies:
- * `this == (this ~/ other) * other + r`.
- * As a consequence the remainder `r` has the same sign as the divider `this`.
- */
+ /// Returns the remainder of the truncating division of `this` by [other].
+ ///
+ /// The result `r` of this operation satisfies:
+ /// `this == (this ~/ other) * other + r`.
+ /// As a consequence the remainder `r` has the same sign as the divider
+ /// `this`.
_BigIntImpl remainder(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (other._used == 0) {
@@ -2175,29 +2127,27 @@
/// Division operator.
double operator /(BigInt other) => this.toDouble() / other.toDouble();
- /** Relational less than operator. */
+ /// Relational less than operator.
bool operator <(BigInt other) => compareTo(other) < 0;
- /** Relational less than or equal operator. */
+ /// Relational less than or equal operator.
bool operator <=(BigInt other) => compareTo(other) <= 0;
- /** Relational greater than operator. */
+ /// Relational greater than operator.
bool operator >(BigInt other) => compareTo(other) > 0;
- /** Relational greater than or equal operator. */
+ /// Relational greater than or equal operator.
bool operator >=(BigInt other) => compareTo(other) >= 0;
- /**
- * Euclidean modulo operator.
- *
- * Returns the remainder of the Euclidean division. The Euclidean division of
- * two integers `a` and `b` yields two integers `q` and `r` such that
- * `a == b * q + r` and `0 <= r < b.abs()`.
- *
- * The sign of the returned value `r` is always positive.
- *
- * See [remainder] for the remainder of the truncating division.
- */
+ /// Euclidean modulo operator.
+ ///
+ /// Returns the remainder of the Euclidean division. The Euclidean division of
+ /// two integers `a` and `b` yields two integers `q` and `r` such that
+ /// `a == b * q + r` and `0 <= r < b.abs()`.
+ ///
+ /// The sign of the returned value `r` is always positive.
+ ///
+ /// See [remainder] for the remainder of the truncating division.
_BigIntImpl operator %(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (other._used == 0) {
@@ -2214,12 +2164,10 @@
return result;
}
- /**
- * Returns the sign of this big integer.
- *
- * Returns 0 for zero, -1 for values less than zero and
- * +1 for values greater than zero.
- */
+ /// Returns the sign of this big integer.
+ ///
+ /// Returns 0 for zero, -1 for values less than zero and
+ /// +1 for values greater than zero.
int get sign {
if (_used == 0) return 0;
return _isNegative ? -1 : 1;
@@ -2256,12 +2204,10 @@
return result;
}
- /**
- * Returns this integer to the power of [exponent] modulo [modulus].
- *
- * The [exponent] must be non-negative and [modulus] must be
- * positive.
- */
+ /// Returns this integer to the power of [exponent] modulo [modulus].
+ ///
+ /// The [exponent] must be non-negative and [modulus] must be
+ /// positive.
_BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
_BigIntImpl exponent = bigExponent;
_BigIntImpl modulus = bigModulus;
@@ -2554,14 +2500,12 @@
return new _BigIntImpl._(false, maxUsed, dDigits);
}
- /**
- * Returns the modular multiplicative inverse of this big integer
- * modulo [modulus].
- *
- * The [modulus] must be positive.
- *
- * It is an error if no modular inverse exists.
- */
+ /// Returns the modular multiplicative inverse of this big integer
+ /// modulo [modulus].
+ ///
+ /// The [modulus] must be positive.
+ ///
+ /// It is an error if no modular inverse exists.
// Returns 1/this % modulus, with modulus > 0.
_BigIntImpl modInverse(BigInt bigInt) {
_BigIntImpl modulus = bigInt;
@@ -2576,19 +2520,17 @@
return _binaryGcd(modulus, tmp, true);
}
- /**
- * Returns the greatest common divisor of this big integer and [other].
- *
- * If either number is non-zero, the result is the numerically greatest
- * integer dividing both `this` and `other`.
- *
- * The greatest common divisor is independent of the order,
- * so `x.gcd(y)` is always the same as `y.gcd(x)`.
- *
- * For any integer `x`, `x.gcd(x)` is `x.abs()`.
- *
- * If both `this` and `other` is zero, the result is also zero.
- */
+ /// Returns the greatest common divisor of this big integer and [other].
+ ///
+ /// If either number is non-zero, the result is the numerically greatest
+ /// integer dividing both `this` and `other`.
+ ///
+ /// The greatest common divisor is independent of the order,
+ /// so `x.gcd(y)` is always the same as `y.gcd(x)`.
+ ///
+ /// For any integer `x`, `x.gcd(x)` is `x.abs()`.
+ ///
+ /// If both `this` and `other` is zero, the result is also zero.
_BigIntImpl gcd(BigInt bigInt) {
_BigIntImpl other = bigInt;
if (_isZero) return other.abs();
@@ -2596,70 +2538,67 @@
return _binaryGcd(this, other, false);
}
- /**
- * Returns the least significant [width] bits of this big integer as a
- * non-negative number (i.e. unsigned representation). The returned value has
- * zeros in all bit positions higher than [width].
- *
- * ```
- * new BigInt.from(-1).toUnsigned(5) == 31 // 11111111 -> 00011111
- * ```
- *
- * This operation can be used to simulate arithmetic from low level languages.
- * For example, to increment an 8 bit quantity:
- *
- * ```
- * q = (q + 1).toUnsigned(8);
- * ```
- *
- * `q` will count from `0` up to `255` and then wrap around to `0`.
- *
- * If the input fits in [width] bits without truncation, the result is the
- * same as the input. The minimum width needed to avoid truncation of `x` is
- * given by `x.bitLength`, i.e.
- *
- * ```
- * x == x.toUnsigned(x.bitLength);
- * ```
- */
+ /// Returns the least significant [width] bits of this big integer as a
+ /// non-negative number (i.e. unsigned representation). The returned value
+ /// has zeros in all bit positions higher than [width].
+ ///
+ /// ```
+ /// new BigInt.from(-1).toUnsigned(5) == 31 // 11111111 -> 00011111
+ /// ```
+ ///
+ /// This operation can be used to simulate arithmetic from low level
+ /// languages. For example, to increment an 8 bit quantity:
+ ///
+ /// ```
+ /// q = (q + 1).toUnsigned(8);
+ /// ```
+ ///
+ /// `q` will count from `0` up to `255` and then wrap around to `0`.
+ ///
+ /// If the input fits in [width] bits without truncation, the result is the
+ /// same as the input. The minimum width needed to avoid truncation of `x` is
+ /// given by `x.bitLength`, i.e.
+ ///
+ /// ```
+ /// x == x.toUnsigned(x.bitLength);
+ /// ```
_BigIntImpl toUnsigned(int width) {
return this & ((one << width) - one);
}
- /**
- * Returns the least significant [width] bits of this integer, extending the
- * highest retained bit to the sign. This is the same as truncating the value
- * to fit in [width] bits using an signed 2-s complement representation. The
- * returned value has the same bit value in all positions higher than [width].
- *
- * ```
- * var big15 = new BigInt.from(15);
- * var big16 = new BigInt.from(16);
- * var big239 = new BigInt.from(239);
- * V--sign bit-V
- * big16.toSigned(5) == -big16 // 00010000 -> 11110000
- * big239.toSigned(5) == big15 // 11101111 -> 00001111
- * ^ ^
- * ```
- *
- * This operation can be used to simulate arithmetic from low level languages.
- * For example, to increment an 8 bit signed quantity:
- *
- * ```
- * q = (q + 1).toSigned(8);
- * ```
- *
- * `q` will count from `0` up to `127`, wrap to `-128` and count back up to
- * `127`.
- *
- * If the input value fits in [width] bits without truncation, the result is
- * the same as the input. The minimum width needed to avoid truncation of `x`
- * is `x.bitLength + 1`, i.e.
- *
- * ```
- * x == x.toSigned(x.bitLength + 1);
- * ```
- */
+ /// Returns the least significant [width] bits of this integer, extending the
+ /// highest retained bit to the sign. This is the same as truncating the
+ /// value to fit in [width] bits using an signed 2-s complement
+ /// representation. The returned value has the same bit value in all
+ /// positions higher than [width].
+ ///
+ /// ```
+ /// var big15 = new BigInt.from(15);
+ /// var big16 = new BigInt.from(16);
+ /// var big239 = new BigInt.from(239);
+ /// V--sign bit-V
+ /// big16.toSigned(5) == -big16 // 00010000 -> 11110000
+ /// big239.toSigned(5) == big15 // 11101111 -> 00001111
+ /// ^ ^
+ /// ```
+ ///
+ /// This operation can be used to simulate arithmetic from low level
+ /// languages. For example, to increment an 8 bit signed quantity:
+ ///
+ /// ```
+ /// q = (q + 1).toSigned(8);
+ /// ```
+ ///
+ /// `q` will count from `0` up to `127`, wrap to `-128` and count back up to
+ /// `127`.
+ ///
+ /// If the input value fits in [width] bits without truncation, the result is
+ /// the same as the input. The minimum width needed to avoid truncation of
+ /// `x` is `x.bitLength + 1`, i.e.
+ ///
+ /// ```
+ /// x == x.toSigned(x.bitLength + 1);
+ /// ```
_BigIntImpl toSigned(int width) {
// The value of binary number weights each bit by a power of two. The
// twos-complement value weights the sign bit negatively. We compute the
@@ -2688,13 +2627,11 @@
return _isNegative ? -result : result;
}
- /**
- * Returns this [_BigIntImpl] as a [double].
- *
- * If the number is not representable as a [double], an
- * approximation is returned. For numerically large integers, the
- * approximation may be infinite.
- */
+ /// Returns this [_BigIntImpl] as a [double].
+ ///
+ /// If the number is not representable as a [double], an
+ /// approximation is returned. For numerically large integers, the
+ /// approximation may be infinite.
double toDouble() {
const int exponentBias = 1075;
// There are 11 bits for the exponent.
@@ -2790,13 +2727,11 @@
return resultBits.buffer.asByteData().getFloat64(0, Endian.little);
}
- /**
- * Returns a String-representation of this integer.
- *
- * The returned string is parsable by [parse].
- * For any `_BigIntImpl` `i`, it is guaranteed that
- * `i == _BigIntImpl.parse(i.toString())`.
- */
+ /// Returns a String-representation of this integer.
+ ///
+ /// The returned string is parsable by [parse].
+ /// For any `_BigIntImpl` `i`, it is guaranteed that
+ /// `i == _BigIntImpl.parse(i.toString())`.
String toString() {
if (_used == 0) return "0";
if (_used == 1) {
@@ -2828,14 +2763,12 @@
return _a + digit - 10;
}
- /**
- * Converts [this] to a string representation in the given [radix].
- *
- * In the string representation, lower-case letters are used for digits above
- * '9', with 'a' being 10 an 'z' being 35.
- *
- * The [radix] argument must be an integer in the range 2 to 36.
- */
+ /// Converts [this] to a string representation in the given [radix].
+ ///
+ /// In the string representation, lower-case letters are used for digits above
+ /// '9', with 'a' being 10 an 'z' being 35.
+ ///
+ /// The [radix] argument must be an integer in the range 2 to 36.
String toRadixString(int radix) {
if (radix > 36) throw new RangeError.range(radix, 2, 36);
diff --git a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
index 4f549a0..5377630 100644
--- a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
@@ -6,152 +6,151 @@
import 'dart:_js_embedded_names' show JsGetName, JsBuiltin;
-/**
- * Emits a JavaScript code fragment parametrized by arguments.
- *
- * Hash characters `#` in the [codeTemplate] are replaced in left-to-right order
- * with expressions that contain the values of, or evaluate to, the arguments.
- * The number of hash marks must match the number or arguments. Although
- * declared with arguments [arg0] through [arg2], the form actually has no limit
- * on the number of arguments.
- *
- * The [typeDescription] argument is interpreted as a description of the
- * behavior of the JavaScript code. Currently it describes the side effects
- * types that may be returned by the expression, with the additional behavior
- * that the returned values may be fresh instances of the types. The type
- * information must be correct as it is trusted by the compiler in
- * optimizations, and it must be precise as possible since it is used for native
- * live type analysis to tree-shake large parts of the DOM libraries. If poorly
- * written, the [typeDescription] will cause unnecessarily bloated programs.
- * (You can check for this by compiling with `--verbose`; there is an info
- * message describing the number of native (DOM) types that can be removed,
- * which usually should be greater than zero.)
- *
- * The [typeDescription] must be a [String]. Two forms of it are supported:
- *
- * 1) a union of types separated by vertical bar `|` symbols, e.g.
- * `"num|String"` describes the union of numbers and Strings. There is no
- * type in Dart that is this precise. The Dart alternative would be `Object`
- * or `dynamic`, but these types imply that the JS-code might also be
- * creating instances of all the DOM types.
- *
- * If `null` is possible, it must be specified explicitly, e.g.
- * `"String|Null"`. [typeDescription] has several extensions to help describe
- * the behavior more accurately. In addition to the union type already
- * described:
- *
- * + `=Object` is a plain JavaScript object. Some DOM methods return
- * instances that have no corresponding Dart type (e.g. cross-frame
- * documents), `=Object` can be used to describe these untyped' values.
- *
- * + `var` or empty string. If the entire [typeDescription] is `var` (or
- * empty string) then the type is `dynamic` but the code is known to not
- * create any instances.
- *
- * Examples:
- *
- * // Parent window might be an opaque cross-frame window.
- * var thing = JS('=Object|Window', '#.parent', myWindow);
- *
- * 2) a sequence of the form `<tag>:<value>;` where `<tag>` is one of
- * `creates`, `returns`, `effects` or `depends`.
- *
- * The first two tags are used to specify the created and returned types of
- * the expression. The value of `creates` and `returns` is a type string as
- * defined in 1).
- *
- * The tags `effects` and `depends` encode the side effects of this call.
- * They can be omitted, in which case the expression is parsed and a safe
- * conservative side-effect estimation is computed.
- *
- * The values of `effects` and `depends` may be 'all', 'none' or a
- * comma-separated list of 'no-index', 'no-instance' and 'no-static'.
- *
- * The value 'all' indicates that the call affects/depends on every
- * side-effect. The flag 'none' signals that the call does not affect
- * (resp. depends on) anything.
- *
- * The value 'no-index' indicates that the call does *not* do (resp. depends
- * on) any array index-store. The flag 'no-instance' indicates that the call
- * does not modify (resp. depends on) any instance variable. Similarly,
- * the 'no-static' value indicates that the call does not modify (resp.
- * depends on) any static variable.
- *
- * The `effects` and `depends` flag must be used in tandem. Either both are
- * specified or none is.
- *
- * Each tag (including the type tags) may only occur once in the sequence.
- *
- * Guidelines:
- *
- * + Do not use any parameter, local, method or field names in the
- * [codeTemplate]. These names are all subject to arbitrary renaming by the
- * compiler. Pass the values in via `#` substition, and test with the
- * `--minify` dart2js command-line option.
- *
- * + The substituted expressions are values, not locations.
- *
- * JS('void', '# += "x"', this.field);
- *
- * `this.field` might not be a substituted as a reference to the field. The
- * generated code might accidentally work as intended, but it also might be
- *
- * var t1 = this.field;
- * t1 += "x";
- *
- * or
- *
- * this.get$field() += "x";
- *
- * The remedy in this case is to expand the `+=` operator, leaving all
- * references to the Dart field as Dart code:
- *
- * this.field = JS('String', '# + "x"', this.field);
- *
- * + Never use `#` in function bodies.
- *
- * This is a variation on the previous guideline. Since `#` is replaced with
- * an *expression* and the expression is only valid in the immediate context,
- * `#` should never appear in a function body. Doing so might defer the
- * evaluation of the expression, and its side effects, until the function is
- * called.
- *
- * For example,
- *
- * var value = foo();
- * var f = JS('', 'function(){return #}', value)
- *
- * might result in no immediate call to `foo` and a call to `foo` on every
- * call to the JavaScript function bound to `f`. This is better:
- *
- * var f = JS('',
- * '(function(val) { return function(){return val}; })(#)', value);
- *
- * Since `#` occurs in the immediately evaluated expression, the expression
- * is immediately evaluated and bound to `val` in the immediate call.
- *
- *
- * Type argument.
- *
- * In Dart 2.0, the type argument additionally constrains the returned type.
- * So, with type inference filling in the type argumemnt,
- *
- * String s = JS('', 'JSON.stringify(#)', x);
- *
- * will be the same as the current meaning of
- *
- * var s = JS('String|Null', 'JSON.stringify(#)', x);
- *
- *
- * Additional notes.
- *
- * In the future we may extend [typeDescription] to include other aspects of the
- * behavior, for example, separating the returned types from the instantiated
- * types to allow the compiler to perform more optimizations around the code.
- *
- * This might be an extension of [JS] or a new function similar to [JS] with
- * additional arguments for the new information.
- */
+/// Emits a JavaScript code fragment parametrized by arguments.
+///
+/// Hash characters `#` in the [codeTemplate] are replaced in left-to-right
+/// order with expressions that contain the values of, or evaluate to, the
+/// arguments. The number of hash marks must match the number or arguments.
+/// Although declared with arguments [arg0] through [arg2], the form actually
+/// has no limit on the number of arguments.
+///
+/// The [typeDescription] argument is interpreted as a description of the
+/// behavior of the JavaScript code. Currently it describes the side effects
+/// types that may be returned by the expression, with the additional behavior
+/// that the returned values may be fresh instances of the types. The type
+/// information must be correct as it is trusted by the compiler in
+/// optimizations, and it must be precise as possible since it is used for
+/// native live type analysis to tree-shake large parts of the DOM libraries.
+/// If poorly written, the [typeDescription] will cause unnecessarily bloated
+/// programs. (You can check for this by compiling with `--verbose`; there is
+/// an info message describing the number of native (DOM) types that can be
+/// removed, which usually should be greater than zero.)
+///
+/// The [typeDescription] must be a [String]. Two forms of it are supported:
+///
+/// 1) a union of types separated by vertical bar `|` symbols, e.g.
+/// `"num|String"` describes the union of numbers and Strings. There is no
+/// type in Dart that is this precise. The Dart alternative would be
+/// `Object` or `dynamic`, but these types imply that the JS-code might also
+/// be creating instances of all the DOM types.
+///
+/// If `null` is possible, it must be specified explicitly, e.g.
+/// `"String|Null"`. [typeDescription] has several extensions to help
+/// describe the behavior more accurately. In addition to the union type
+/// already described:
+///
+/// + `=Object` is a plain JavaScript object. Some DOM methods return
+/// instances that have no corresponding Dart type (e.g. cross-frame
+/// documents), `=Object` can be used to describe these untyped' values.
+///
+/// + `var` or empty string. If the entire [typeDescription] is `var` (or
+/// empty string) then the type is `dynamic` but the code is known to not
+/// create any instances.
+///
+/// Examples:
+///
+/// // Parent window might be an opaque cross-frame window.
+/// var thing = JS('=Object|Window', '#.parent', myWindow);
+///
+/// 2) a sequence of the form `<tag>:<value>;` where `<tag>` is one of
+/// `creates`, `returns`, `effects` or `depends`.
+///
+/// The first two tags are used to specify the created and returned types of
+/// the expression. The value of `creates` and `returns` is a type string as
+/// defined in 1).
+///
+/// The tags `effects` and `depends` encode the side effects of this call.
+/// They can be omitted, in which case the expression is parsed and a safe
+/// conservative side-effect estimation is computed.
+///
+/// The values of `effects` and `depends` may be 'all', 'none' or a
+/// comma-separated list of 'no-index', 'no-instance' and 'no-static'.
+///
+/// The value 'all' indicates that the call affects/depends on every
+/// side-effect. The flag 'none' signals that the call does not affect
+/// (resp. depends on) anything.
+///
+/// The value 'no-index' indicates that the call does *not* do (resp. depends
+/// on) any array index-store. The flag 'no-instance' indicates that the call
+/// does not modify (resp. depends on) any instance variable. Similarly,
+/// the 'no-static' value indicates that the call does not modify (resp.
+/// depends on) any static variable.
+///
+/// The `effects` and `depends` flag must be used in tandem. Either both are
+/// specified or none is.
+///
+/// Each tag (including the type tags) may only occur once in the sequence.
+///
+/// Guidelines:
+///
+/// + Do not use any parameter, local, method or field names in the
+/// [codeTemplate]. These names are all subject to arbitrary renaming by the
+/// compiler. Pass the values in via `#` substition, and test with the
+/// `--minify` dart2js command-line option.
+///
+/// + The substituted expressions are values, not locations.
+///
+/// JS('void', '# += "x"', this.field);
+///
+/// `this.field` might not be a substituted as a reference to the field. The
+/// generated code might accidentally work as intended, but it also might be
+///
+/// var t1 = this.field;
+/// t1 += "x";
+///
+/// or
+///
+/// this.get$field() += "x";
+///
+/// The remedy in this case is to expand the `+=` operator, leaving all
+/// references to the Dart field as Dart code:
+///
+/// this.field = JS('String', '# + "x"', this.field);
+///
+/// + Never use `#` in function bodies.
+///
+/// This is a variation on the previous guideline. Since `#` is replaced
+/// with an *expression* and the expression is only valid in the immediate
+/// context, `#` should never appear in a function body. Doing so might
+/// defer the evaluation of the expression, and its side effects, until the
+/// function is called.
+///
+/// For example,
+///
+/// var value = foo();
+/// var f = JS('', 'function(){return #}', value)
+///
+/// might result in no immediate call to `foo` and a call to `foo` on every
+/// call to the JavaScript function bound to `f`. This is better:
+///
+/// var f = JS('',
+/// '(function(val) { return function(){return val}; })(#)', value);
+///
+/// Since `#` occurs in the immediately evaluated expression, the expression
+/// is immediately evaluated and bound to `val` in the immediate call.
+///
+///
+/// Type argument.
+///
+/// In Dart 2.0, the type argument additionally constrains the returned type.
+/// So, with type inference filling in the type argumemnt,
+///
+/// String s = JS('', 'JSON.stringify(#)', x);
+///
+/// will be the same as the current meaning of
+///
+/// var s = JS('String|Null', 'JSON.stringify(#)', x);
+///
+///
+/// Additional notes.
+///
+/// In the future we may extend [typeDescription] to include other aspects of
+/// the behavior, for example, separating the returned types from the
+/// instantiated types to allow the compiler to perform more optimizations
+/// around the code.
+///
+/// This might be an extension of [JS] or a new function similar to [JS] with
+/// additional arguments for the new information.
// Add additional optional arguments if needed. The method is treated internally
// as a variable argument method.
external T JS<T>(String typeDescription, String codeTemplate,
@@ -176,39 +175,31 @@
arg18,
arg19]);
-/**
- * Converts the Dart closure [function] into a JavaScript closure.
- *
- * Warning: This is no different from [RAW_DART_FUNCTION_REF] which means care
- * must be taken to store the current isolate.
- */
+/// Converts the Dart closure [function] into a JavaScript closure.
+///
+/// Warning: This is no different from [RAW_DART_FUNCTION_REF] which means care
+/// must be taken to store the current isolate.
external DART_CLOSURE_TO_JS(Function function);
-/**
- * Returns a raw reference to the JavaScript function which implements
- * [function].
- *
- * Warning: this is dangerous, you should probably use
- * [DART_CLOSURE_TO_JS] instead. The returned object is not a valid
- * Dart closure, does not store the isolate context or arity.
- *
- * A valid example of where this can be used is as the second argument
- * to V8's Error.captureStackTrace. See
- * https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.
- */
+/// Returns a raw reference to the JavaScript function which implements
+/// [function].
+///
+/// Warning: this is dangerous, you should probably use
+/// [DART_CLOSURE_TO_JS] instead. The returned object is not a valid
+/// Dart closure, does not store the isolate context or arity.
+///
+/// A valid example of where this can be used is as the second argument
+/// to V8's Error.captureStackTrace. See
+/// https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi.
external RAW_DART_FUNCTION_REF(Function function);
-/**
- * Sets the current static state to [staticState].
- */
+/// Sets the current static state to [staticState].
external void JS_SET_STATIC_STATE(staticState);
-/**
- * Returns the interceptor for class [type]. The interceptor is the type's
- * constructor's `prototype` property. [type] will typically be the class, not
- * an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not
- * `JS_INTERCEPTOR_CONSTANT(int)`.
- */
+/// Returns the interceptor for class [type]. The interceptor is the type's
+/// constructor's `prototype` property. [type] will typically be the class, not
+/// an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not
+/// `JS_INTERCEPTOR_CONSTANT(int)`.
external JS_INTERCEPTOR_CONSTANT(Type type);
/// Returns the interceptor for [object].
@@ -216,9 +207,7 @@
/// Calls are replaced with the [HInterceptor] SSA instruction.
external getInterceptor(object);
-/**
- * Returns the object corresponding to Namer.staticStateHolder.
- */
+/// Returns the object corresponding to Namer.staticStateHolder.
external JS_GET_STATIC_STATE();
/// Returns the JS name for [name] from the Namer.
@@ -242,42 +231,36 @@
/// when the program has been analyzed.
external bool JS_GET_FLAG(String name);
-/**
- * Pretend [code] is executed. Generates no executable code. This is used to
- * model effects at some other point in external code. For example, the
- * following models an assignment to foo with an unknown value.
- *
- * var foo;
- *
- * main() {
- * JS_EFFECT((_){ foo = _; })
- * }
- *
- * TODO(sra): Replace this hack with something to mark the volatile or
- * externally initialized elements.
- */
+/// Pretend [code] is executed. Generates no executable code. This is used to
+/// model effects at some other point in external code. For example, the
+/// following models an assignment to foo with an unknown value.
+///
+/// var foo;
+///
+/// main() {
+/// JS_EFFECT((_){ foo = _; })
+/// }
+///
+/// TODO(sra): Replace this hack with something to mark the volatile or
+/// externally initialized elements.
void JS_EFFECT(Function code) {
code(null);
}
-/**
- * Use this class for creating constants that hold JavaScript code.
- * For example:
- *
- * const constant = JS_CONST('typeof window != "undefined");
- *
- * This code will generate:
- * $.JS_CONST_1 = typeof window != "undefined";
- */
+/// Use this class for creating constants that hold JavaScript code.
+/// For example:
+///
+/// const constant = JS_CONST('typeof window != "undefined");
+///
+/// This code will generate:
+/// $.JS_CONST_1 = typeof window != "undefined";
class JS_CONST {
final String code;
const JS_CONST(this.code);
}
-/**
- * JavaScript string concatenation. Inputs must be Strings. Corresponds to the
- * HStringConcat SSA instruction and may be constant-folded.
- */
+/// JavaScript string concatenation. Inputs must be Strings. Corresponds to the
+/// HStringConcat SSA instruction and may be constant-folded.
String JS_STRING_CONCAT(String a, String b) {
// This body is unused, only here for type analysis.
return JS('String', '# + #', a, b);
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
index a9fcb75..3344d39 100644
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
@@ -52,7 +52,7 @@
JS_EMBEDDED_GLOBAL,
JS_INTERCEPTOR_CONSTANT,
JS_STRING_CONCAT;
-import 'dart:math' show Random;
+import 'dart:math' show Random, ln2;
part 'js_array.dart';
part 'js_number.dart';
@@ -123,10 +123,8 @@
dispatchRecordExtension(record) => JS('', '#.e', record);
dispatchRecordIndexability(record) => JS('bool|Null', '#.x', record);
-/**
- * Returns the interceptor for a native class instance. Used by
- * [getInterceptor].
- */
+/// Returns the interceptor for a native class instance. Used by
+/// [getInterceptor].
getNativeInterceptor(object) {
var record = getDispatchProperty(object);
@@ -220,20 +218,18 @@
JS('', '#.set(#, #)', constructorToInterceptor, constructor, interceptor);
}
-/**
- * Data structure used to map a [Type] to the [Interceptor] and constructors for
- * that type. It is JavaScript array of 3N entries of adjacent slots containing
- * a [Type], followed by an [Interceptor] class for the type, followed by a
- * JavaScript object map for the constructors.
- *
- * The value of this variable is set by the compiler and contains only types
- * that are user extensions of native classes where the type occurs as a
- * constant in the program.
- *
- * The compiler, in CustomElementsAnalysis, assumes that [typeToInterceptorMap]
- * is accessed only by code that also calls [findIndexForWebComponentType]. If
- * this assumption is invalidated, the compiler will have to be updated.
- */
+/// Data structure used to map a [Type] to the [Interceptor] and constructors
+/// for that type. It is JavaScript array of 3N entries of adjacent slots
+/// containing a [Type], followed by an [Interceptor] class for the type,
+/// followed by a JavaScript object map for the constructors.
+///
+/// The value of this variable is set by the compiler and contains only types
+/// that are user extensions of native classes where the type occurs as a
+/// constant in the program.
+///
+/// The compiler, in CustomElementsAnalysis, assumes that [typeToInterceptorMap]
+/// is accessed only by code that also calls [findIndexForWebComponentType]. If
+/// this assumption is invalidated, the compiler will have to be updated.
get typeToInterceptorMap {
return JS_EMBEDDED_GLOBAL('', TYPE_TO_INTERCEPTOR_MAP);
}
@@ -256,12 +252,10 @@
return map[index + 1];
}
-/**
- * Returns a JavaScript function that runs the constructor on its argument, or
- * `null` if there is no such constructor.
- *
- * The returned function takes one argument, the web component object.
- */
+/// Returns a JavaScript function that runs the constructor on its argument, or
+/// `null` if there is no such constructor.
+///
+/// The returned function takes one argument, the web component object.
findConstructorForNativeSubclassType(Type type, String name) {
var index = findIndexForNativeSubclassType(type);
if (index == null) return null;
@@ -277,54 +271,52 @@
return JS('', '#.prototype', constructor);
}
-/**
- * The base interceptor class.
- *
- * The code `r.foo(a)` is compiled to `getInterceptor(r).foo$1(r, a)`. The
- * value returned by [getInterceptor] holds the methods separately from the
- * state of the instance. The compiler converts the methods on an interceptor
- * to take the Dart `this` argument as an explicit `receiver` argument. The
- * JavaScript `this` parameter is bound to the interceptor.
- *
- * In order to have uniform call sites, if a method is defined on an
- * interceptor, methods of that name on plain unintercepted classes also use the
- * interceptor calling convention. The plain classes are _self-interceptors_,
- * and for them, `getInterceptor(r)` returns `r`. Methods on plain
- * unintercepted classes have a redundant `receiver` argument and, to enable
- * some optimizations, must ignore `receiver` in favour of `this`.
- *
- * In the case of mixins, a method may be placed on both an intercepted class
- * and an unintercepted class. In this case, the method must use the `receiver`
- * parameter.
- *
- *
- * There are various optimizations of the general call pattern.
- *
- * When the interceptor can be statically determined, it can be used directly:
- *
- * CONSTANT_INTERCEPTOR.foo$1(r, a)
- *
- * If there are only a few classes, [getInterceptor] can be specialized with a
- * more efficient dispatch:
- *
- * getInterceptor$specialized(r).foo$1(r, a)
- *
- * If it can be determined that the receiver is an unintercepted class, it can
- * be called directly:
- *
- * r.foo$1(r, a)
- *
- * If, further, it is known that the call site cannot call a foo that is
- * mixed-in to a native class, then it is known that the explicit receiver is
- * ignored, and space-saving dummy value can be passed instead:
- *
- * r.foo$1(0, a)
- *
- * This class defines implementations of *all* methods on [Object] so no
- * interceptor inherits an implementation from [Object]. This enables the
- * implementations on Object to ignore the explicit receiver argument, which
- * allows dummy receiver optimization.
- */
+/// The base interceptor class.
+///
+/// The code `r.foo(a)` is compiled to `getInterceptor(r).foo$1(r, a)`. The
+/// value returned by [getInterceptor] holds the methods separately from the
+/// state of the instance. The compiler converts the methods on an interceptor
+/// to take the Dart `this` argument as an explicit `receiver` argument. The
+/// JavaScript `this` parameter is bound to the interceptor.
+///
+/// In order to have uniform call sites, if a method is defined on an
+/// interceptor, methods of that name on plain unintercepted classes also use
+/// the interceptor calling convention. The plain classes are
+/// _self-interceptors_, and for them, `getInterceptor(r)` returns `r`. Methods
+/// on plain unintercepted classes have a redundant `receiver` argument and, to
+/// enable some optimizations, must ignore `receiver` in favour of `this`.
+///
+/// In the case of mixins, a method may be placed on both an intercepted class
+/// and an unintercepted class. In this case, the method must use the
+/// `receiver` parameter.
+///
+///
+/// There are various optimizations of the general call pattern.
+///
+/// When the interceptor can be statically determined, it can be used directly:
+///
+/// CONSTANT_INTERCEPTOR.foo$1(r, a)
+///
+/// If there are only a few classes, [getInterceptor] can be specialized with a
+/// more efficient dispatch:
+///
+/// getInterceptor$specialized(r).foo$1(r, a)
+///
+/// If it can be determined that the receiver is an unintercepted class, it can
+/// be called directly:
+///
+/// r.foo$1(r, a)
+///
+/// If, further, it is known that the call site cannot call a foo that is
+/// mixed-in to a native class, then it is known that the explicit receiver is
+/// ignored, and space-saving dummy value can be passed instead:
+///
+/// r.foo$1(0, a)
+///
+/// This class defines implementations of *all* methods on [Object] so no
+/// interceptor inherits an implementation from [Object]. This enables the
+/// implementations on Object to ignore the explicit receiver argument, which
+/// allows dummy receiver optimization.
abstract class Interceptor {
const Interceptor();
@@ -356,9 +348,7 @@
Type get runtimeType => getRuntimeType(this);
}
-/**
- * The interceptor class for [bool].
- */
+/// The interceptor class for [bool].
class JSBool extends Interceptor implements bool {
const JSBool();
@@ -378,13 +368,11 @@
Type get runtimeType => bool;
}
-/**
- * The interceptor class for [Null].
- *
- * This class defines implementations for *all* methods on [Object] since
- * the methods on Object assume the receiver is non-null. This means that
- * JSNull will always be in the interceptor set for methods defined on Object.
- */
+/// The interceptor class for [Null].
+///
+/// This class defines implementations for *all* methods on [Object] since
+/// the methods on Object assume the receiver is non-null. This means that
+/// JSNull will always be in the interceptor set for methods defined on Object.
class JSNull extends Interceptor implements Null {
const JSNull();
@@ -403,37 +391,29 @@
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
-/**
- * The supertype for JSString and JSArray. Used by the backend as to
- * have a type mask that contains the objects that we can use the
- * native JS [] operator and length on.
- */
+/// The supertype for JSString and JSArray. Used by the backend as to
+/// have a type mask that contains the objects that we can use the
+/// native JS [] operator and length on.
abstract class JSIndexable<E> {
int get length;
E operator [](int index);
}
-/**
- * The supertype for JSMutableArray and
- * JavaScriptIndexingBehavior. Used by the backend to have a type mask
- * that contains the objects we can use the JS []= operator on.
- */
+/// The supertype for JSMutableArray and
+/// JavaScriptIndexingBehavior. Used by the backend to have a type mask
+/// that contains the objects we can use the JS []= operator on.
abstract class JSMutableIndexable<E> extends JSIndexable<E> {
operator []=(int index, E value);
}
-/**
- * The interface implemented by JavaScript objects. These are methods in
- * addition to the regular Dart Object methods like [Object.hashCode].
- *
- * This is the type that should be exported by a JavaScript interop library.
- */
+/// The interface implemented by JavaScript objects. These are methods in
+/// addition to the regular Dart Object methods like [Object.hashCode].
+///
+/// This is the type that should be exported by a JavaScript interop library.
abstract class JSObject {}
-/**
- * Interceptor base class for JavaScript objects not recognized as some more
- * specific native type.
- */
+/// Interceptor base class for JavaScript objects not recognized as some more
+/// specific native type.
class JavaScriptObject extends Interceptor implements JSObject {
const JavaScriptObject();
@@ -442,36 +422,28 @@
Type get runtimeType => JSObject;
- /**
- * Returns the result of the JavaScript objects `toString` method.
- */
+ /// Returns the result of the JavaScript objects `toString` method.
String toString() => JS('String', 'String(#)', this);
}
-/**
- * Interceptor for plain JavaScript objects created as JavaScript object
- * literals or `new Object()`.
- */
+/// Interceptor for plain JavaScript objects created as JavaScript object
+/// literals or `new Object()`.
class PlainJavaScriptObject extends JavaScriptObject {
const PlainJavaScriptObject();
}
-/**
- * Interceptor for unclassified JavaScript objects, typically objects with a
- * non-trivial prototype chain.
- *
- * This class also serves as a fallback for unknown JavaScript exceptions.
- */
+/// Interceptor for unclassified JavaScript objects, typically objects with a
+/// non-trivial prototype chain.
+///
+/// This class also serves as a fallback for unknown JavaScript exceptions.
class UnknownJavaScriptObject extends JavaScriptObject {
const UnknownJavaScriptObject();
}
-/**
- * Interceptor for JavaScript function objects and Dart functions that have
- * been converted to JavaScript functions.
- * These interceptor methods are not always used as the JavaScript function
- * object has also been mangled to support Dart function calling conventions.
- */
+/// Interceptor for JavaScript function objects and Dart functions that have
+/// been converted to JavaScript functions.
+/// These interceptor methods are not always used as the JavaScript function
+/// object has also been mangled to support Dart function calling conventions.
class JavaScriptFunction extends JavaScriptObject implements Function {
const JavaScriptFunction();
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index 9d0a48e..c6956d9 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -10,12 +10,10 @@
const _ListConstructorSentinel = const _Growable();
-/**
- * The interceptor class for [List]. The compiler recognizes this
- * class as an interceptor, and changes references to [:this:] to
- * actually use the receiver of the method, which is generated as an extra
- * argument added to each member.
- */
+/// The interceptor class for [List]. The compiler recognizes this
+/// class as an interceptor, and changes references to [:this:] to
+/// actually use the receiver of the method, which is generated as an extra
+/// argument added to each member.
class JSArray<E> extends Interceptor implements List<E>, JSIndexable {
const JSArray();
@@ -28,11 +26,9 @@
return new JSArray<E>.fixed(length);
}
- /**
- * Returns a fresh JavaScript Array, marked as fixed-length.
- *
- * [length] must be a non-negative integer.
- */
+ /// Returns a fresh JavaScript Array, marked as fixed-length.
+ ///
+ /// [length] must be a non-negative integer.
factory JSArray.fixed(int length) {
// Explicit type test is necessary to guard against JavaScript conversions
// in unchecked mode, and against `new Array(null)` which creates a single
@@ -49,16 +45,12 @@
return new JSArray<E>.markFixed(JS('', 'new Array(#)', length));
}
- /**
- * Returns a fresh growable JavaScript Array of zero length length.
- */
+ /// Returns a fresh growable JavaScript Array of zero length length.
factory JSArray.emptyGrowable() => new JSArray<E>.markGrowable(JS('', '[]'));
- /**
- * Returns a fresh growable JavaScript Array with initial length.
- *
- * [validatedLength] must be a non-negative integer.
- */
+ /// Returns a fresh growable JavaScript Array with initial length.
+ ///
+ /// [validatedLength] must be a non-negative integer.
factory JSArray.growable(int length) {
// Explicit type test is necessary to guard against JavaScript conversions
// in unchecked mode.
@@ -68,20 +60,18 @@
return new JSArray<E>.markGrowable(JS('', 'new Array(#)', length));
}
- /**
- * Constructor for adding type parameters to an existing JavaScript Array.
- * The compiler specially recognizes this constructor.
- *
- * var a = new JSArray<int>.typed(JS('JSExtendableArray', '[]'));
- * a is List<int> --> true
- * a is List<String> --> false
- *
- * Usually either the [JSArray.markFixed] or [JSArray.markGrowable]
- * constructors is used instead.
- *
- * The input must be a JavaScript Array. The JS form is just a re-assertion
- * to help type analysis when the input type is sloppy.
- */
+ /// Constructor for adding type parameters to an existing JavaScript Array.
+ /// The compiler specially recognizes this constructor.
+ ///
+ /// var a = new JSArray<int>.typed(JS('JSExtendableArray', '[]'));
+ /// a is List<int> --> true
+ /// a is List<String> --> false
+ ///
+ /// Usually either the [JSArray.markFixed] or [JSArray.markGrowable]
+ /// constructors is used instead.
+ ///
+ /// The input must be a JavaScript Array. The JS form is just a re-assertion
+ /// to help type analysis when the input type is sloppy.
factory JSArray.typed(allocation) => JS('JSArray', '#', allocation);
factory JSArray.markFixed(allocation) =>
@@ -181,9 +171,7 @@
return false;
}
- /**
- * Removes elements matching [test] from [this] List.
- */
+ /// Removes elements matching [test] from [this] List.
void removeWhere(bool test(E element)) {
checkGrowable('removeWhere');
_removeWhere(test, true);
@@ -677,17 +665,15 @@
}
}
-/**
- * Dummy subclasses that allow the backend to track more precise
- * information about arrays through their type. The CPA type inference
- * relies on the fact that these classes do not override [] nor []=.
- *
- * These classes are really a fiction, and can have no methods, since
- * getInterceptor always returns JSArray. We should consider pushing the
- * 'isGrowable' and 'isMutable' checks into the getInterceptor implementation so
- * these classes can have specialized implementations. Doing so will challenge
- * many assumptions in the JS backend.
- */
+/// Dummy subclasses that allow the backend to track more precise
+/// information about arrays through their type. The CPA type inference
+/// relies on the fact that these classes do not override [] nor []=.
+///
+/// These classes are really a fiction, and can have no methods, since
+/// getInterceptor always returns JSArray. We should consider pushing the
+/// 'isGrowable' and 'isMutable' checks into the getInterceptor implementation
+/// so these classes can have specialized implementations. Doing so will
+/// challenge many assumptions in the JS backend.
class JSMutableArray<E> extends JSArray<E> implements JSMutableIndexable {}
class JSFixedArray<E> extends JSMutableArray<E> {}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 3338e9d..9457101 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -646,7 +646,7 @@
return result;
}
- /** [: r"$".codeUnitAt(0) :] */
+ /// [: r"$".codeUnitAt(0) :]
static const int DOLLAR_CHAR_VALUE = 36;
/// Creates a string containing the complete type for the class [className]
@@ -1099,40 +1099,38 @@
0));
}
- /**
- * Implements [Function.apply] for the lazy and startup emitters.
- *
- * There are two types of closures that can reach this function:
- *
- * 1. tear-offs (including tear-offs of static functions).
- * 2. anonymous closures.
- *
- * They are treated differently (although there are lots of similarities).
- * Both have in common that they have
- * a [JsGetName.CALL_CATCH_ALL] and
- * a [JsGetName.REQUIRED_PARAMETER_PROPERTY] property.
- *
- * If the closure supports optional parameters, then they also feature
- * a [JsGetName.DEFAULT_VALUES_PROPERTY] property.
- *
- * The catch-all property is a method that takes all arguments (including
- * all optional positional or named arguments). If the function accepts
- * optional arguments, then the default-values property stores (potentially
- * wrapped in a function) the default values for the optional arguments. If
- * the function accepts optional positional arguments, then the value is a
- * JavaScript array with the default values. Otherwise, when the function
- * accepts optional named arguments, it is a JavaScript object.
- *
- * The default-values property may either contain the value directly, or
- * it can be a function that returns the default-values when invoked.
- *
- * If the function is an anonymous closure, then the catch-all property
- * only contains a string pointing to the property that should be used
- * instead. For example, if the catch-all property contains the string
- * "call$4", then the object's "call$4" property should be used as if it was
- * the value of the catch-all property.
- */
- static applyFunction2(Function function, List positionalArguments,
+ /// Implements [Function.apply] for the lazy and startup emitters.
+ ///
+ /// There are two types of closures that can reach this function:
+ ///
+ /// 1. tear-offs (including tear-offs of static functions).
+ /// 2. anonymous closures.
+ ///
+ /// They are treated differently (although there are lots of similarities).
+ /// Both have in common that they have
+ /// a [JsGetName.CALL_CATCH_ALL] and
+ /// a [JsGetName.REQUIRED_PARAMETER_PROPERTY] property.
+ ///
+ /// If the closure supports optional parameters, then they also feature
+ /// a [JsGetName.DEFAULT_VALUES_PROPERTY] property.
+ ///
+ /// The catch-all property is a method that takes all arguments (including
+ /// all optional positional or named arguments). If the function accepts
+ /// optional arguments, then the default-values property stores (potentially
+ /// wrapped in a function) the default values for the optional arguments. If
+ /// the function accepts optional positional arguments, then the value is a
+ /// JavaScript array with the default values. Otherwise, when the function
+ /// accepts optional named arguments, it is a JavaScript object.
+ ///
+ /// The default-values property may either contain the value directly, or
+ /// it can be a function that returns the default-values when invoked.
+ ///
+ /// If the function is an anonymous closure, then the catch-all property
+ /// only contains a string pointing to the property that should be used
+ /// instead. For example, if the catch-all property contains the string
+ /// "call$4", then the object's "call$4" property should be used as if it was
+ /// the value of the catch-all property.
+ static applyFunction(Function function, List positionalArguments,
Map<String, dynamic> namedArguments) {
// Fast shortcut for the common case.
if (JS('bool', '# instanceof Array', positionalArguments) &&
@@ -1300,162 +1298,6 @@
}
}
- static applyFunction(Function function, List positionalArguments,
- Map<String, dynamic> namedArguments) {
- // Dispatch on presence of named arguments to improve tree-shaking.
- //
- // This dispatch is as simple as possible to help the compiler detect the
- // common case of `null` namedArguments, either via inlining or
- // specialization.
- return namedArguments == null
- ? applyFunctionWithPositionalArguments(function, positionalArguments)
- : applyFunctionWithNamedArguments(
- function, positionalArguments, namedArguments);
- }
-
- static applyFunctionWithPositionalArguments(
- Function function, List positionalArguments) {
- List arguments;
-
- if (positionalArguments != null) {
- if (JS('bool', '# instanceof Array', positionalArguments)) {
- arguments = JS('JSArray', '#', positionalArguments);
- } else {
- arguments = new List.from(positionalArguments);
- }
- } else {
- arguments = [];
- }
-
- if (arguments.length == 0) {
- String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX0);
- if (JS('bool', '!!#[#]', function, selectorName)) {
- return JS('', '#[#]()', function, selectorName);
- }
- } else if (arguments.length == 1) {
- String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX1);
- if (JS('bool', '!!#[#]', function, selectorName)) {
- return JS('', '#[#](#[0])', function, selectorName, arguments);
- }
- } else if (arguments.length == 2) {
- String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX2);
- if (JS('bool', '!!#[#]', function, selectorName)) {
- return JS('', '#[#](#[0],#[1])', function, selectorName, arguments,
- arguments);
- }
- } else if (arguments.length == 3) {
- String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX3);
- if (JS('bool', '!!#[#]', function, selectorName)) {
- return JS('', '#[#](#[0],#[1],#[2])', function, selectorName, arguments,
- arguments, arguments);
- }
- } else if (arguments.length == 4) {
- String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX4);
- if (JS('bool', '!!#[#]', function, selectorName)) {
- return JS('', '#[#](#[0],#[1],#[2],#[3])', function, selectorName,
- arguments, arguments, arguments, arguments);
- }
- } else if (arguments.length == 5) {
- String selectorName = JS_GET_NAME(JsGetName.CALL_PREFIX5);
- if (JS('bool', '!!#[#]', function, selectorName)) {
- return JS('', '#[#](#[0],#[1],#[2],#[3],#[4])', function, selectorName,
- arguments, arguments, arguments, arguments, arguments);
- }
- }
- return _genericApplyFunctionWithPositionalArguments(function, arguments);
- }
-
- static _genericApplyFunctionWithPositionalArguments(
- Function function, List arguments) {
- int argumentCount = arguments.length;
- String selectorName =
- '${JS_GET_NAME(JsGetName.CALL_PREFIX)}\$$argumentCount';
- var jsFunction = JS('var', '#[#]', function, selectorName);
- if (jsFunction == null) {
- var interceptor = getInterceptor(function);
- jsFunction =
- JS('', '#[#]', interceptor, JS_GET_NAME(JsGetName.CALL_CATCH_ALL));
-
- if (jsFunction == null) {
- return functionNoSuchMethod(function, arguments, null);
- }
- ReflectionInfo info = new ReflectionInfo(jsFunction);
- int requiredArgumentCount = info.requiredParameterCount;
- int maxArgumentCount =
- requiredArgumentCount + info.optionalParameterCount;
- if (info.areOptionalParametersNamed ||
- requiredArgumentCount > argumentCount ||
- maxArgumentCount < argumentCount) {
- return functionNoSuchMethod(function, arguments, null);
- }
- arguments = new List.from(arguments);
- for (int pos = argumentCount; pos < maxArgumentCount; pos++) {
- arguments.add(getMetadata(info.defaultValue(pos)));
- }
- }
- // We bound 'this' to [function] because of how we compile
- // closures: escaped local variables are stored and accessed through
- // [function].
- return JS('var', '#.apply(#, #)', jsFunction, function, arguments);
- }
-
- static applyFunctionWithNamedArguments(Function function,
- List positionalArguments, Map<String, dynamic> namedArguments) {
- if (namedArguments.isEmpty) {
- return applyFunctionWithPositionalArguments(
- function, positionalArguments);
- }
- // TODO(ahe): The following code can be shared with
- // JsInstanceMirror.invoke.
- var interceptor = getInterceptor(function);
- var jsFunction =
- JS('', '#[#]', interceptor, JS_GET_NAME(JsGetName.CALL_CATCH_ALL));
-
- if (jsFunction == null) {
- return functionNoSuchMethod(
- function, positionalArguments, namedArguments);
- }
- ReflectionInfo info = new ReflectionInfo(jsFunction);
- if (info == null || !info.areOptionalParametersNamed) {
- return functionNoSuchMethod(
- function, positionalArguments, namedArguments);
- }
-
- if (positionalArguments != null) {
- positionalArguments = new List.from(positionalArguments);
- } else {
- positionalArguments = [];
- }
- // Check the number of positional arguments is valid.
- if (info.requiredParameterCount != positionalArguments.length) {
- return functionNoSuchMethod(
- function, positionalArguments, namedArguments);
- }
- var defaultArguments = new Map();
- for (int i = 0; i < info.optionalParameterCount; i++) {
- int index = i + info.requiredParameterCount;
- var parameterName = info.parameterNameInOrder(index);
- var value = info.defaultValueInOrder(index);
- var defaultValue = getMetadata(value);
- defaultArguments[parameterName] = defaultValue;
- }
- bool bad = false;
- namedArguments.forEach((String parameter, value) {
- if (defaultArguments.containsKey(parameter)) {
- defaultArguments[parameter] = value;
- } else {
- // Extraneous named argument.
- bad = true;
- }
- });
- if (bad) {
- return functionNoSuchMethod(
- function, positionalArguments, namedArguments);
- }
- positionalArguments.addAll(defaultArguments.values);
- return JS('', '#.apply(#, #)', jsFunction, function, positionalArguments);
- }
-
static StackTrace extractStackTrace(Error error) {
return getTraceFromException(JS('', r'#.$thrownJsError', error));
}
@@ -1484,32 +1326,27 @@
}
}
-/**
- * Called by generated code to throw an illegal-argument exception,
- * for example, if a non-integer index is given to an optimized
- * indexed access.
- */
+/// Called by generated code to throw an illegal-argument exception,
+/// for example, if a non-integer index is given to an optimized
+/// indexed access.
@NoInline()
iae(argument) {
throw argumentErrorValue(argument);
}
-/**
- * Called by generated code to throw an index-out-of-range exception, for
- * example, if a bounds check fails in an optimized indexed access. This may
- * also be called when the index is not an integer, in which case it throws an
- * illegal-argument exception instead, like [iae], or when the receiver is null.
- */
+/// Called by generated code to throw an index-out-of-range exception, for
+/// example, if a bounds check fails in an optimized indexed access. This may
+/// also be called when the index is not an integer, in which case it throws an
+/// illegal-argument exception instead, like [iae], or when the receiver is
+/// null.
@NoInline()
ioore(receiver, index) {
if (receiver == null) receiver.length; // Force a NoSuchMethodError.
throw diagnoseIndexError(receiver, index);
}
-/**
- * Diagnoses an indexing error. Returns the ArgumentError or RangeError that
- * describes the problem.
- */
+/// Diagnoses an indexing error. Returns the ArgumentError or RangeError that
+/// describes the problem.
@NoInline()
Error diagnoseIndexError(indexable, index) {
if (index is! int) return new ArgumentError.value(index, 'index');
@@ -1523,10 +1360,8 @@
return new RangeError.value(index, 'index');
}
-/**
- * Diagnoses a range error. Returns the ArgumentError or RangeError that
- * describes the problem.
- */
+/// Diagnoses a range error. Returns the ArgumentError or RangeError that
+/// describes the problem.
@NoInline()
Error diagnoseRangeError(start, end, length) {
if (start is! int) {
@@ -1582,12 +1417,10 @@
return value;
}
-/**
- * Wrap the given Dart object and record a stack trace.
- *
- * The code in [unwrapException] deals with getting the original Dart
- * object out of the wrapper again.
- */
+/// Wrap the given Dart object and record a stack trace.
+///
+/// The code in [unwrapException] deals with getting the original Dart
+/// object out of the wrapper again.
@NoInline()
wrapException(ex) {
if (ex == null) ex = new NullThrownError();
@@ -1619,12 +1452,10 @@
return JS('', r'this.dartException').toString();
}
-/**
- * This wraps the exception and does the throw. It is possible to call this in
- * a JS expression context, where the throw statement is not allowed. Helpers
- * are never inlined, so we don't risk inlining the throw statement into an
- * expression context.
- */
+/// This wraps the exception and does the throw. It is possible to call this in
+/// a JS expression context, where the throw statement is not allowed. Helpers
+/// are never inlined, so we don't risk inlining the throw statement into an
+/// expression context.
throwExpression(ex) {
JS('void', 'throw #', wrapException(ex));
}
@@ -1666,9 +1497,7 @@
throw new ConcurrentModificationError(collection);
}
-/**
- * Helper class for building patterns recognizing native type errors.
- */
+/// Helper class for building patterns recognizing native type errors.
class TypeErrorDecoder {
// Field names are private to help tree-shaking.
@@ -2047,14 +1876,12 @@
ExceptionAndStackTrace(this.dartException, this.stackTrace);
}
-/**
- * Called from catch blocks in generated code to extract the Dart
- * exception from the thrown value. The thrown value may have been
- * created by [wrapException] or it may be a 'native' JS exception.
- *
- * Some native exceptions are mapped to new Dart instances, others are
- * returned unmodified.
- */
+/// Called from catch blocks in generated code to extract the Dart
+/// exception from the thrown value. The thrown value may have been
+/// created by [wrapException] or it may be a 'native' JS exception.
+///
+/// Some native exceptions are mapped to new Dart instances, others are
+/// returned unmodified.
unwrapException(ex) {
/// If error implements Error, save [ex] in [error.$thrownJsError].
/// Otherwise, do nothing. Later, the stack trace can then be extracted from
@@ -2204,10 +2031,8 @@
ex);
}
-/**
- * Called by generated code to fetch the stack trace from an
- * exception. Should never return null.
- */
+/// Called by generated code to fetch the stack trace from an
+/// exception. Should never return null.
StackTrace getTraceFromException(exception) {
if (exception is ExceptionAndStackTrace) {
return exception.stackTrace;
@@ -2244,10 +2069,8 @@
}
}
-/**
- * Called by generated code to build a map literal. [keyValuePairs] is
- * a list of key, value, key, value, ..., etc.
- */
+/// Called by generated code to build a map literal. [keyValuePairs] is
+/// a list of key, value, key, value, ..., etc.
fillLiteralMap(keyValuePairs, Map result) {
// TODO(johnniwinther): Use JSArray to optimize this code instead of calling
// [getLength] and [getIndex].
@@ -2278,10 +2101,8 @@
throw new Exception('Unsupported number of arguments for wrapped closure');
}
-/**
- * Called by generated code to convert a Dart closure to a JS
- * closure when the Dart closure is passed to the DOM.
- */
+/// Called by generated code to convert a Dart closure to a JS
+/// closure when the Dart closure is passed to the DOM.
convertDartClosureToJS(closure, int arity) {
if (closure == null) return null;
var function = JS('var', r'#.$identity', closure);
@@ -2318,40 +2139,36 @@
static const OPTIONAL_PARAMETER_INDEX = 4;
static const DEFAULT_ARGUMENTS_INDEX = 5;
- /**
- * Global counter to prevent reusing function code objects.
- *
- * V8 will share the underlying function code objects when the same string is
- * passed to "new Function". Shared function code objects can lead to
- * sub-optimal performance due to polymorphism, and can be prevented by
- * ensuring the strings are different, for example, by generating a local
- * variable with a name dependent on [functionCounter].
- */
+ /// Global counter to prevent reusing function code objects.
+ ///
+ /// V8 will share the underlying function code objects when the same string is
+ /// passed to "new Function". Shared function code objects can lead to
+ /// sub-optimal performance due to polymorphism, and can be prevented by
+ /// ensuring the strings are different, for example, by generating a local
+ /// variable with a name dependent on [functionCounter].
static int functionCounter = 0;
Closure();
- /**
- * Creates a new closure class for use by implicit getters associated with a
- * method.
- *
- * In other words, creates a tear-off closure.
- *
- * Called from [closureFromTearOff] as well as from reflection when tearing
- * of a method via `getField`.
- *
- * This method assumes that [functions] was created by the JavaScript function
- * `addStubs` in `reflection_data_parser.dart`. That is, a list of JavaScript
- * function objects with properties `$stubName` and `$callName`.
- *
- * Further assumes that [reflectionInfo] is the end of the array created by
- * [dart2js.js_emitter.ContainerBuilder.addMemberMethod] starting with
- * required parameter count or, in case of the new emitter, the runtime
- * representation of the function's type.
- *
- * Caution: this function may be called when building constants.
- * TODO(ahe): Don't call this function when building constants.
- */
+ /// Creates a new closure class for use by implicit getters associated with a
+ /// method.
+ ///
+ /// In other words, creates a tear-off closure.
+ ///
+ /// Called from [closureFromTearOff] as well as from reflection when tearing
+ /// of a method via `getField`.
+ ///
+ /// This method assumes that [functions] was created by the JavaScript
+ /// function `addStubs` in `reflection_data_parser.dart`. That is, a list of
+ /// JavaScript function objects with properties `$stubName` and `$callName`.
+ ///
+ /// Further assumes that [reflectionInfo] is the end of the array created by
+ /// [dart2js.js_emitter.ContainerBuilder.addMemberMethod] starting with
+ /// required parameter count or, in case of the new emitter, the runtime
+ /// representation of the function's type.
+ ///
+ /// Caution: this function may be called when building constants.
+ /// TODO(ahe): Don't call this function when building constants.
static fromTearOff(
receiver,
List functions,
@@ -2913,101 +2730,91 @@
return JS('var', r'#[#]', jsObject, property);
}
-/**
- * Called at the end of unaborted switch cases to get the singleton
- * FallThroughError exception that will be thrown.
- */
+/// Called at the end of unaborted switch cases to get the singleton
+/// FallThroughError exception that will be thrown.
getFallThroughError() => new FallThroughErrorImplementation();
-/**
- * A metadata annotation describing the types instantiated by a native element.
- *
- * The annotation is valid on a native method and a field of a native class.
- *
- * By default, a field of a native class is seen as an instantiation point for
- * all native classes that are a subtype of the field's type, and a native
- * method is seen as an instantiation point fo all native classes that are a
- * subtype of the method's return type, or the argument types of the declared
- * type of the method's callback parameter.
- *
- * An @[Creates] annotation overrides the default set of instantiated types. If
- * one or more @[Creates] annotations are present, the type of the native
- * element is ignored, and the union of @[Creates] annotations is used instead.
- * The names in the strings are resolved and the program will fail to compile
- * with dart2js if they do not name types.
- *
- * The argument to [Creates] is a string. The string is parsed as the names of
- * one or more types, separated by vertical bars `|`. There are some special
- * names:
- *
- * * `=Object`. This means 'exactly Object', which is a plain JavaScript object
- * with properties and none of the subtypes of Object.
- *
- * Example: we may know that a method always returns a specific implementation:
- *
- * @Creates('_NodeList')
- * List<Node> getElementsByTagName(String tag) native;
- *
- * Useful trick: A method can be marked as not instantiating any native classes
- * with the annotation `@Creates('Null')`. This is useful for fields on native
- * classes that are used only in Dart code.
- *
- * @Creates('Null')
- * var _cachedFoo;
- */
+/// A metadata annotation describing the types instantiated by a native element.
+///
+/// The annotation is valid on a native method and a field of a native class.
+///
+/// By default, a field of a native class is seen as an instantiation point for
+/// all native classes that are a subtype of the field's type, and a native
+/// method is seen as an instantiation point fo all native classes that are a
+/// subtype of the method's return type, or the argument types of the declared
+/// type of the method's callback parameter.
+///
+/// An @[Creates] annotation overrides the default set of instantiated types.
+/// If one or more @[Creates] annotations are present, the type of the native
+/// element is ignored, and the union of @[Creates] annotations is used instead.
+/// The names in the strings are resolved and the program will fail to compile
+/// with dart2js if they do not name types.
+///
+/// The argument to [Creates] is a string. The string is parsed as the names of
+/// one or more types, separated by vertical bars `|`. There are some special
+/// names:
+///
+/// * `=Object`. This means 'exactly Object', which is a plain JavaScript object
+/// with properties and none of the subtypes of Object.
+///
+/// Example: we may know that a method always returns a specific implementation:
+///
+/// @Creates('_NodeList')
+/// List<Node> getElementsByTagName(String tag) native;
+///
+/// Useful trick: A method can be marked as not instantiating any native classes
+/// with the annotation `@Creates('Null')`. This is useful for fields on native
+/// classes that are used only in Dart code.
+///
+/// @Creates('Null')
+/// var _cachedFoo;
class Creates {
final String types;
const Creates(this.types);
}
-/**
- * A metadata annotation describing the types returned or yielded by a native
- * element.
- *
- * The annotation is valid on a native method and a field of a native class.
- *
- * By default, a native method or field is seen as returning or yielding all
- * subtypes if the method return type or field type. This annotation allows a
- * more precise set of types to be specified.
- *
- * See [Creates] for the syntax of the argument.
- *
- * Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys.
- *
- * @Returns('String|num|JSExtendableArray')
- * dynamic key;
- *
- * // Equivalent:
- * @Returns('String') @Returns('num') @Returns('JSExtendableArray')
- * dynamic key;
- */
+/// A metadata annotation describing the types returned or yielded by a native
+/// element.
+///
+/// The annotation is valid on a native method and a field of a native class.
+///
+/// By default, a native method or field is seen as returning or yielding all
+/// subtypes if the method return type or field type. This annotation allows a
+/// more precise set of types to be specified.
+///
+/// See [Creates] for the syntax of the argument.
+///
+/// Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys.
+///
+/// @Returns('String|num|JSExtendableArray')
+/// dynamic key;
+///
+/// // Equivalent:
+/// @Returns('String') @Returns('num') @Returns('JSExtendableArray')
+/// dynamic key;
class Returns {
final String types;
const Returns(this.types);
}
-/**
- * A metadata annotation placed on native methods and fields of native classes
- * to specify the JavaScript name.
- *
- * This example declares a Dart field + getter + setter called `$dom_title` that
- * corresponds to the JavaScript property `title`.
- *
- * class Document native "*Foo" {
- * @JSName('title')
- * String $dom_title;
- * }
- */
+/// A metadata annotation placed on native methods and fields of native classes
+/// to specify the JavaScript name.
+///
+/// This example declares a Dart field + getter + setter called `$dom_title`
+/// that corresponds to the JavaScript property `title`.
+///
+/// class Document native "*Foo" {
+/// @JSName('title')
+/// String $dom_title;
+/// }
class JSName {
final String name;
const JSName(this.name);
}
-/**
- * The following methods are called by the runtime to implement
- * checked mode and casts. We specialize each primitive type (eg int, bool), and
- * use the compiler's convention to do is-checks on regular objects.
- */
+/// The following methods are called by the runtime to implement checked mode
+/// and casts. We specialize each primitive type (eg int, bool), and use the
+/// compiler's convention to do is-checks on regular objects.
boolConversionCheck(value) {
if (value is bool) return value;
// One of the following checks will always fail.
@@ -3082,32 +2889,26 @@
throw new CastErrorImplementation(value, unminifyOrTag(name));
}
-/**
- * For types that are not supertypes of native (eg DOM) types,
- * we emit a simple property check to check that an object implements
- * that type.
- */
+/// For types that are not supertypes of native (eg DOM) types,
+/// we emit a simple property check to check that an object implements
+/// that type.
propertyTypeCheck(value, property) {
if (value == null) return value;
if (JS('bool', '!!#[#]', value, property)) return value;
propertyTypeError(value, property);
}
-/**
- * For types that are not supertypes of native (eg DOM) types,
- * we emit a simple property check to check that an object implements
- * that type.
- */
+/// For types that are not supertypes of native (eg DOM) types,
+/// we emit a simple property check to check that an object implements
+/// that type.
propertyTypeCast(value, property) {
if (value == null || JS('bool', '!!#[#]', value, property)) return value;
propertyTypeCastError(value, property);
}
-/**
- * For types that are supertypes of native (eg DOM) types, we use the
- * interceptor for the class because we cannot add a JS property to the
- * prototype at load time.
- */
+/// For types that are supertypes of native (eg DOM) types, we use the
+/// interceptor for the class because we cannot add a JS property to the
+/// prototype at load time.
interceptedTypeCheck(value, property) {
if (value == null) return value;
if ((JS('bool', 'typeof # === "object"', value) ||
@@ -3118,11 +2919,9 @@
propertyTypeError(value, property);
}
-/**
- * For types that are supertypes of native (eg DOM) types, we use the
- * interceptor for the class because we cannot add a JS property to the
- * prototype at load time.
- */
+/// For types that are supertypes of native (eg DOM) types, we use the
+/// interceptor for the class because we cannot add a JS property to the
+/// prototype at load time.
interceptedTypeCast(value, property) {
if (value == null ||
((JS('bool', 'typeof # === "object"', value) ||
@@ -3133,10 +2932,8 @@
propertyTypeCastError(value, property);
}
-/**
- * Specialization of the type check for num and String and their
- * supertype since [value] can be a JS primitive.
- */
+/// Specialization of the type check for num and String and their
+/// supertype since [value] can be a JS primitive.
numberOrStringSuperTypeCheck(value, property) {
if (value == null) return value;
if (value is String) return value;
@@ -3167,10 +2964,8 @@
propertyTypeCastError(value, property);
}
-/**
- * Specialization of the type check for String and its supertype
- * since [value] can be a JS primitive.
- */
+/// Specialization of the type check for String and its supertype
+/// since [value] can be a JS primitive.
stringSuperTypeCheck(value, property) {
if (value == null) return value;
if (value is String) return value;
@@ -3196,10 +2991,8 @@
propertyTypeCastError(value, property);
}
-/**
- * Specialization of the type check for List and its supertypes,
- * since [value] can be a JS array.
- */
+/// Specialization of the type check for List and its supertypes,
+/// since [value] can be a JS array.
listTypeCheck(value) {
if (value == null) return value;
if (value is List) return value;
@@ -3314,17 +3107,15 @@
}
}
-/**
- * Special interface recognized by the compiler and implemented by DOM
- * objects that support integer indexing. This interface is not
- * visible to anyone, and is only injected into special libraries.
- */
+/// Special interface recognized by the compiler and implemented by DOM
+/// objects that support integer indexing. This interface is not
+/// visible to anyone, and is only injected into special libraries.
abstract class JavaScriptIndexingBehavior<E> extends JSMutableIndexable<E> {}
// TODO(lrn): These exceptions should be implemented in core.
// When they are, remove the 'Implementation' here.
-/** Thrown by type assertions that fail. */
+/// Thrown by type assertions that fail.
class TypeErrorImplementation extends Error implements TypeError {
final String message;
@@ -3338,7 +3129,7 @@
String toString() => message;
}
-/** Thrown by the 'as' operator if the cast isn't valid. */
+/// Thrown by the 'as' operator if the cast isn't valid.
class CastErrorImplementation extends Error implements CastError {
// TODO(lrn): Rename to CastError (and move implementation into core).
final String message;
@@ -3367,12 +3158,11 @@
String toString() => 'Switch case fall-through.';
}
-/**
- * Helper function for implementing asserts. The compiler treats this specially.
- *
- * Returns the negation of the condition. That is: `true` if the assert should
- * fail.
- */
+/// Helper function for implementing asserts. The compiler treats this
+/// specially.
+///
+/// Returns the negation of the condition. That is: `true` if the assert should
+/// fail.
bool assertTest(condition) {
// Do bool success check first, it is common and faster than 'is Function'.
if (true == condition) return false;
@@ -3380,44 +3170,34 @@
throw new TypeErrorImplementation(condition, 'bool');
}
-/**
- * Helper function for implementing asserts with messages.
- * The compiler treats this specially.
- */
+/// Helper function for implementing asserts with messages.
+/// The compiler treats this specially.
void assertThrow(Object message) {
throw new _AssertionError(message);
}
-/**
- * Helper function for implementing asserts without messages.
- * The compiler treats this specially.
- */
+/// Helper function for implementing asserts without messages.
+/// The compiler treats this specially.
@NoInline()
void assertHelper(condition) {
if (assertTest(condition)) throw new AssertionError();
}
-/**
- * Called by generated code when a method that must be statically
- * resolved cannot be found.
- */
+/// Called by generated code when a method that must be statically
+/// resolved cannot be found.
void throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {
Symbol memberName = new _symbol_dev.Symbol.unvalidated(name);
throw new NoSuchMethodError(obj, memberName, arguments,
new Map<Symbol, dynamic>(), expectedArgumentNames);
}
-/**
- * Called by generated code when a static field's initializer references the
- * field that is currently being initialized.
- */
+/// Called by generated code when a static field's initializer references the
+/// field that is currently being initialized.
void throwCyclicInit(String staticName) {
throw new CyclicInitializationError(staticName);
}
-/**
- * Error thrown when a runtime error occurs.
- */
+/// Error thrown when a runtime error occurs.
class RuntimeError extends Error {
final message;
RuntimeError(this.message);
@@ -3444,11 +3224,9 @@
String toString() => 'Unsupported operation: $_message';
}
-/**
- * Creates a random number with 64 bits of randomness.
- *
- * This will be truncated to the 53 bits available in a double.
- */
+/// Creates a random number with 64 bits of randomness.
+///
+/// This will be truncated to the 53 bits available in a double.
int random64() {
// TODO(lrn): Use a secure random source.
int int32a = JS('int', '(Math.random() * 0x100000000) >>> 0');
@@ -3460,14 +3238,12 @@
return JS('String', 'JSON.stringify(#)', string);
}
-/**
- * Returns a property name for placing data on JavaScript objects shared between
- * DOM isolates. This happens when multiple programs are loaded in the same
- * JavaScript context (i.e. page). The name is based on [name] but with an
- * additional part that is unique for each isolate.
- *
- * The form of the name is '___dart_$name_$id'.
- */
+/// Returns a property name for placing data on JavaScript objects shared
+/// between DOM isolates. This happens when multiple programs are loaded in the
+/// same JavaScript context (i.e. page). The name is based on [name] but with
+/// an additional part that is unique for each isolate.
+///
+/// The form of the name is '___dart_$name_$id'.
String getIsolateAffinityTag(String name) {
var isolateTagGetter = JS_EMBEDDED_GLOBAL('', GET_ISOLATE_TAG);
return JS('String', '#(#)', isolateTagGetter, name);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_names.dart b/sdk/lib/_internal/js_runtime/lib/js_names.dart
index d3eaa07..572d354 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_names.dart
@@ -139,17 +139,15 @@
return new JSArray.markFixed(result);
}
-/**
- * Returns the (global) unmangled version of [name].
- *
- * Normally, you should use [mangledGlobalNames] directly, but this method
- * doesn't tell the compiler to preserve names. So this method only returns a
- * non-null value if some other component has made the compiler preserve names.
- *
- * This is used, for example, to return unmangled names from TypeImpl.toString
- * *if* names are being preserved for other reasons (use of dart:mirrors, for
- * example).
- */
+/// Returns the (global) unmangled version of [name].
+///
+/// Normally, you should use [mangledGlobalNames] directly, but this method
+/// doesn't tell the compiler to preserve names. So this method only returns a
+/// non-null value if some other component has made the compiler preserve names.
+///
+/// This is used, for example, to return unmangled names from TypeImpl.toString
+/// *if* names are being preserved for other reasons (use of dart:mirrors, for
+/// example).
String unmangleGlobalNameIfPreservedAnyways(String name) {
var names = JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES);
return JsCache.fetch(names, name);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_number.dart b/sdk/lib/_internal/js_runtime/lib/js_number.dart
index 58e5e55..1c030f3 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_number.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_number.dart
@@ -4,15 +4,13 @@
part of _interceptors;
-/**
- * The super interceptor class for [JSInt] and [JSDouble]. The compiler
- * recognizes this class as an interceptor, and changes references to
- * [:this:] to actually use the receiver of the method, which is
- * generated as an extra argument added to each member.
- *
- * Note that none of the methods here delegate to a method defined on JSInt or
- * JSDouble. This is exploited in [tryComputeConstantInterceptor].
- */
+/// The super interceptor class for [JSInt] and [JSDouble]. The compiler
+/// recognizes this class as an interceptor, and changes references to
+/// [:this:] to actually use the receiver of the method, which is
+/// generated as an extra argument added to each member.
+///
+/// Note that none of the methods here delegate to a method defined on JSInt or
+/// JSDouble. This is exploited in [tryComputeConstantInterceptor].
class JSNumber extends Interceptor implements double {
const JSNumber();
@@ -241,7 +239,40 @@
}
}
- int get hashCode => JS('int', '# & 0x1FFFFFFF', this);
+ int get hashCode {
+ int intValue = JS('int', '# | 0', this);
+ // Fast exit for integers in signed 32-bit range. Masking converts -0.0 to 0
+ // and ensures that result fits in JavaScript engine's Smi range.
+ if (this == intValue) return 0x1FFFFFFF & intValue;
+
+ // We would like to access the exponent and mantissa as integers but there
+ // are no JavaScript operations that do this, so use log2-floor-pow-divide
+ // to extract the values.
+ num absolute = JS('num', 'Math.abs(#)', this);
+ num lnAbsolute = JS('num', 'Math.log(#)', absolute);
+ num log2 = lnAbsolute / ln2;
+ // Floor via '# | 0' converts NaN to zero so the final result is not NaN.
+ int floorLog2 = JS('int', '# | 0', log2);
+ num factor = JS('num', 'Math.pow(2, #)', floorLog2);
+ num scaled = absolute < 1 ? absolute / factor : factor / absolute;
+ // [scaled] is in the range [0.5, 1].
+
+ // Multiply and truncate to pick up all the mantissa bits. Multiplying by
+ // 0x20000000000000 (which has 53 zero bits) converts the mantissa into an
+ // integer. There are interesting subsets where all the bit variance is in
+ // the most significant bits of the mantissa (e.g. 0.5, 0.625, 0.75), so we
+ // need to mix in the most significant bits. We do this by scaling with a
+ // constant that has many bits set to use the multiplier to mix in bits from
+ // all over the mantissa into low positions.
+ num rescaled1 = scaled * 0x20000000000000;
+ num rescaled2 = scaled * 0x0C95A6C285A6C9;
+ int d1 = JS('int', '# | 0', rescaled1);
+ int d2 = JS('int', '# | 0', rescaled2);
+ // Mix in exponent to distinguish e.g. 1.25 from 2.5.
+ int d3 = floorLog2;
+ int h = 0x1FFFFFFF & ((d1 + d2) * (601 * 997) + d3 * (1259));
+ return h;
+ }
JSNumber operator -() => JS('num', r'-#', this);
@@ -411,14 +442,12 @@
Type get runtimeType => num;
}
-/**
- * The interceptor class for [int]s.
- *
- * This class implements double (indirectly through JSNumber) since in
- * JavaScript all numbers are doubles, so while we want to treat `2.0` as an
- * integer for some operations, its interceptor should answer `true` to `is
- * double`.
- */
+/// The interceptor class for [int]s.
+///
+/// This class implements double (indirectly through JSNumber) since in
+/// JavaScript all numbers are doubles, so while we want to treat `2.0` as an
+/// integer for some operations, its interceptor should answer `true` to `is
+/// double`.
class JSInt extends JSNumber implements int {
const JSInt();
diff --git a/sdk/lib/_internal/js_runtime/lib/js_primitives.dart b/sdk/lib/_internal/js_runtime/lib/js_primitives.dart
index 40c451c..97577a0 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_primitives.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_primitives.dart
@@ -8,15 +8,13 @@
import 'dart:_foreign_helper' show JS;
-/**
- * This is the low-level method that is used to implement [print]. It is
- * possible to override this function from JavaScript by defining a function in
- * JavaScript called "dartPrint".
- *
- * Notice that it is also possible to intercept calls to [print] from within a
- * Dart program using zones. This means that there is no guarantee that a call
- * to print ends in this method.
- */
+/// This is the low-level method that is used to implement [print]. It is
+/// possible to override this function from JavaScript by defining a function in
+/// JavaScript called "dartPrint".
+///
+/// Notice that it is also possible to intercept calls to [print] from within a
+/// Dart program using zones. This means that there is no guarantee that a call
+/// to print ends in this method.
void printString(String string) {
if (JS('bool', r'typeof dartPrint == "function"')) {
// Support overriding print from JavaScript.
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index b5e84fa..9a6ef99 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -2,43 +2,41 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-/**
- * This part contains helpers for supporting runtime type information.
- *
- * The helper use a mixture of Dart and JavaScript objects. To indicate which is
- * used where we adopt the scheme of using explicit type annotation for Dart
- * objects and 'var' or omitted return type for JavaScript objects.
- *
- * Since bool, int, and String values are represented by the same JavaScript
- * primitives, type annotations are used for these types in all cases.
- *
- * Several methods use a common JavaScript encoding of runtime type information.
- * This encoding is referred to as the type representation which is one of
- * these:
- * 1) a JavaScript constructor for a class C: the represented type is the raw
- * type C.
- * 2) a JavaScript array: the first entry is of type 1 and contains the
- * subtyping flags and the substitution of the type and the rest of the
- * array are the type arguments.
- * 3) `null`: the dynamic type.
- * 4) a JavaScript object representing the function type. For instance, it has
- * the form {ret: rti, args: [rti], opt: [rti], named: {name: rti}} for a
- * function with a return type, regular, optional and named arguments.
- * Generic function types have a 'bounds' property.
- *
- * To check subtype relations between generic classes we use a JavaScript
- * expression that describes the necessary substitution for type arguments.
- * Such a substitution expression can be:
- * 1) `null`, if no substituted check is necessary, because the
- * type variables are the same or there are no type variables in the class
- * that is checked for.
- * 2) A list expression describing the type arguments to be used in the
- * subtype check, if the type arguments to be used in the check do not
- * depend on the type arguments of the object.
- * 3) A function mapping the type variables of the object to be checked to
- * a list expression. The function may also return null, which is equivalent
- * to an array containing only null values.
- */
+/// This part contains helpers for supporting runtime type information.
+///
+/// The helper use a mixture of Dart and JavaScript objects. To indicate which
+/// is used where we adopt the scheme of using explicit type annotation for Dart
+/// objects and 'var' or omitted return type for JavaScript objects.
+///
+/// Since bool, int, and String values are represented by the same JavaScript
+/// primitives, type annotations are used for these types in all cases.
+///
+/// Several methods use a common JavaScript encoding of runtime type
+/// information. This encoding is referred to as the type representation which
+/// is one of these:
+/// 1) a JavaScript constructor for a class C: the represented type is the raw
+/// type C.
+/// 2) a JavaScript array: the first entry is of type 1 and contains the
+/// subtyping flags and the substitution of the type and the rest of the
+/// array are the type arguments.
+/// 3) `null`: the dynamic type.
+/// 4) a JavaScript object representing the function type. For instance, it has
+/// the form {ret: rti, args: [rti], opt: [rti], named: {name: rti}} for a
+/// function with a return type, regular, optional and named arguments.
+/// Generic function types have a 'bounds' property.
+///
+/// To check subtype relations between generic classes we use a JavaScript
+/// expression that describes the necessary substitution for type arguments.
+/// Such a substitution expression can be:
+/// 1) `null`, if no substituted check is necessary, because the
+/// type variables are the same or there are no type variables in the class
+/// that is checked for.
+/// 2) A list expression describing the type arguments to be used in the
+/// subtype check, if the type arguments to be used in the check do not
+/// depend on the type arguments of the object.
+/// 3) A function mapping the type variables of the object to be checked to a
+/// list expression. The function may also return null, which is equivalent
+/// to an array containing only null values.
part of _js_helper;
@@ -67,12 +65,10 @@
}
}
-/**
- * Represents a type variable.
- *
- * This class holds the information needed when reflecting on generic classes
- * and their members.
- */
+/// Represents a type variable.
+///
+/// This class holds the information needed when reflecting on generic classes
+/// and their members.
class TypeVariable {
final Type owner;
final String name;
@@ -157,10 +153,8 @@
return rti == null ? null : getIndex(rti, index);
}
-/**
- * Retrieves the class name from type information stored on the constructor
- * of [object].
- */
+/// Retrieves the class name from type information stored on the constructor
+/// of [object].
String getClassName(var object) {
return rawRtiToJsConstructorName(getRawRuntimeType(getInterceptor(object)));
}
@@ -327,11 +321,9 @@
return '${typeParameters}(${argumentsText}) => ${returnTypeText}';
}
-/**
- * Creates a comma-separated string of human-readable representations of the
- * type representations in the JavaScript array [types] starting at index
- * [startIndex].
- */
+/// Creates a comma-separated string of human-readable representations of the
+/// type representations in the JavaScript array [types] starting at index
+/// [startIndex].
String joinArguments(var types, int startIndex) {
return _joinArguments(types, startIndex, null);
}
@@ -354,11 +346,9 @@
return '<$buffer>';
}
-/**
- * Returns a human-readable representation of the type of [object].
- *
- * In minified mode does *not* use unminified identifiers (even when present).
- */
+/// Returns a human-readable representation of the type of [object].
+///
+/// In minified mode does *not* use unminified identifiers (even when present).
String getRuntimeTypeString(var object) {
if (object is Closure) {
// This excludes classes that implement Function via a `call` method, but
@@ -403,12 +393,10 @@
return new TypeImpl(getRti(object));
}
-/**
- * Applies the [substitution] on the [arguments].
- *
- * See the comment in the beginning of this file for a description of the
- * possible values for [substitution].
- */
+/// Applies the [substitution] on the [arguments].
+///
+/// See the comment in the beginning of this file for a description of the
+/// possible values for [substitution].
substitute(var substitution, var arguments) {
if (substitution == null) return arguments;
assert(isJsFunction(substitution));
@@ -429,18 +417,16 @@
return arguments;
}
-/**
- * Perform a type check with arguments on the Dart object [object].
- *
- * Parameters:
- * - [isField]: the name of the flag/function to check if the object
- * is of the correct class.
- * - [checks]: the (JavaScript) list of type representations for the
- * arguments to check against.
- * - [asField]: the name of the function that transforms the type
- * arguments of [objects] to an instance of the class that we check
- * against.
- */
+/// Perform a type check with arguments on the Dart object [object].
+///
+/// Parameters:
+/// - [isField]: the name of the flag/function to check if the object
+/// is of the correct class.
+/// - [checks]: the (JavaScript) list of type representations for the
+/// arguments to check against.
+/// - [asField]: the name of the function that transforms the type
+/// arguments of [objects] to an instance of the class that we check
+/// against.
bool checkSubtype(Object object, String isField, List checks, String asField) {
if (object == null) return false;
var arguments = getRuntimeTypeInfo(object);
@@ -507,17 +493,15 @@
return areSubtypes(substitute(substitution, arguments), sEnv, checks, tEnv);
}
-/**
- * Checks whether the types of [s] are all subtypes of the types of [t].
- *
- * [s] and [t] are either `null` or JavaScript arrays of type representations,
- * A `null` argument is interpreted as the arguments of a raw type, that is a
- * list of `dynamic`. If [s] and [t] are JavaScript arrays they must be of the
- * same length.
- *
- * See the comment in the beginning of this file for a description of type
- * representations.
- */
+/// Checks whether the types of [s] are all subtypes of the types of [t].
+///
+/// [s] and [t] are either `null` or JavaScript arrays of type representations,
+/// A `null` argument is interpreted as the arguments of a raw type, that is a
+/// list of `dynamic`. If [s] and [t] are JavaScript arrays they must be of the
+/// same length.
+///
+/// See the comment in the beginning of this file for a description of type
+/// representations.
bool areSubtypes(var s, var sEnv, var t, var tEnv) {
// `null` means a raw type.
@@ -545,10 +529,8 @@
return true;
}
-/**
- * Computes the signature by applying the type arguments of [context] as an
- * instance of [contextName] to the signature function [signature].
- */
+/// Computes the signature by applying the type arguments of [context] as an
+/// instance of [contextName] to the signature function [signature].
computeSignature(var signature, var context, var contextName) {
var interceptor = getInterceptor(context);
var typeArguments =
@@ -619,13 +601,11 @@
: null;
}
-/**
- * Tests whether the Dart object [o] is a subtype of the runtime type
- * representation [t].
- *
- * See the comment in the beginning of this file for a description of type
- * representations.
- */
+/// Tests whether the Dart object [o] is a subtype of the runtime type
+/// representation [t].
+///
+/// See the comment in the beginning of this file for a description of type
+/// representations.
bool checkSubtypeOfRuntimeType(o, t) {
if (o == null) return isSupertypeOfNull(t);
if (isTopType(t)) return true;
@@ -678,24 +658,20 @@
return object;
}
-/**
- * Extracts the type arguments from a type representation. The result is a
- * JavaScript array or `null`.
- */
+/// Extracts the type arguments from a type representation. The result is a
+/// JavaScript array or `null`.
getArguments(var type) {
return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null;
}
-/**
- * Checks whether the type represented by the type representation [s] is a
- * subtype of the type represented by the type representation [t].
- *
- * See the comment in the beginning of this file for a description of type
- * representations.
- *
- * The arguments [s] and [t] must be types, usually represented by the
- * constructor of the class, or an array (for generic class types).
- */
+/// Checks whether the type represented by the type representation [s] is a
+/// subtype of the type represented by the type representation [t].
+///
+/// See the comment in the beginning of this file for a description of type
+/// representations.
+///
+/// The arguments [s] and [t] must be types, usually represented by the
+/// constructor of the class, or an array (for generic class types).
bool isSubtype(var s, var t) {
return _isSubtype(s, null, t, null);
}
@@ -1075,16 +1051,12 @@
return array;
}
-/**
- * Calls the JavaScript [function] with the [arguments] with the global scope
- * as the `this` context.
- */
+/// Calls the JavaScript [function] with the [arguments] with the global scope
+/// as the `this` context.
invoke(var function, var arguments) => invokeOn(function, null, arguments);
-/**
- * Calls the JavaScript [function] with the [arguments] with [receiver] as the
- * `this` context.
- */
+/// Calls the JavaScript [function] with the [arguments] with [receiver] as the
+/// `this` context.
Object invokeOn(function, receiver, arguments) {
assert(isJsFunction(function));
assert(arguments == null || isJsArray(arguments));
@@ -1132,18 +1104,14 @@
/// Returns `true` if [o] is a JavaScript object.
bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o);
-/**
- * Returns `true` if the JavaScript values [s] and [t] are identical. We use
- * this helper instead of [identical] because `identical` needs to merge
- * `null` and `undefined` (which we can avoid).
- */
+/// Returns `true` if the JavaScript values [s] and [t] are identical. We use
+/// this helper instead of [identical] because `identical` needs to merge
+/// `null` and `undefined` (which we can avoid).
bool isIdentical(var s, var t) => JS('bool', '# === #', s, t);
-/**
- * Returns `true` if the JavaScript values [s] and [t] are not identical. We use
- * this helper instead of [identical] because `identical` needs to merge
- * `null` and `undefined` (which we can avoid).
- */
+/// Returns `true` if the JavaScript values [s] and [t] are not identical. We
+/// use this helper instead of [identical] because `identical` needs to merge
+/// `null` and `undefined` (which we can avoid).
bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t);
/// 'Top' bounds are uninteresting: null/undefined and Object.
diff --git a/sdk/lib/_internal/js_runtime/lib/js_string.dart b/sdk/lib/_internal/js_runtime/lib/js_string.dart
index 91e9734..baa47b6 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_string.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_string.dart
@@ -4,12 +4,10 @@
part of _interceptors;
-/**
- * The interceptor class for [String]. The compiler recognizes this
- * class as an interceptor, and changes references to [:this:] to
- * actually use the receiver of the method, which is generated as an extra
- * argument added to each member.
- */
+/// The interceptor class for [String]. The compiler recognizes this
+/// class as an interceptor, and changes references to [:this:] to
+/// actually use the receiver of the method, which is generated as an extra
+/// argument added to each member.
class JSString extends Interceptor implements String, JSIndexable {
const JSString();
@@ -443,12 +441,10 @@
// Note: if you change this, also change the function [S].
String toString() => this;
- /**
- * This is the [Jenkins hash function][1] but using masking to keep
- * values in SMI range.
- *
- * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
- */
+ /// This is the [Jenkins hash function][1] but using masking to keep
+ /// values in SMI range.
+ ///
+ /// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
int get hashCode {
// TODO(ahe): This method shouldn't have to use JS. Update when our
// optimizations are smarter.
diff --git a/sdk/lib/_internal/js_runtime/lib/math_patch.dart b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
index 68bae9a..a3d3fc9 100644
--- a/sdk/lib/_internal/js_runtime/lib/math_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
@@ -84,15 +84,11 @@
return JS('int', '(Math.random() * #) >>> 0', max);
}
- /**
- * Generates a positive random floating point value uniformly distributed on
- * the range from 0.0, inclusive, to 1.0, exclusive.
- */
+ /// Generates a positive random floating point value uniformly distributed on
+ /// the range from 0.0, inclusive, to 1.0, exclusive.
double nextDouble() => JS('double', 'Math.random()');
- /**
- * Generates a random boolean value.
- */
+ /// Generates a random boolean value.
bool nextBool() => JS('bool', 'Math.random() < 0.5');
}
diff --git a/sdk/lib/_internal/js_runtime/lib/native_helper.dart b/sdk/lib/_internal/js_runtime/lib/native_helper.dart
index fa11112..59a3719 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_helper.dart
@@ -38,27 +38,21 @@
return JS('var', 'Object.getPrototypeOf(#)[#]', object, name);
}
-/**
- * Returns a String tag identifying the type of the native object, or `null`.
- * The tag is not the name of the type, but usually the name of the JavaScript
- * constructor function. Initialized by [initHooks].
- */
+/// Returns a String tag identifying the type of the native object, or `null`.
+/// The tag is not the name of the type, but usually the name of the JavaScript
+/// constructor function. Initialized by [initHooks].
Function getTagFunction;
-/**
- * If a lookup via [getTagFunction] on an object [object] that has [tag] fails,
- * this function is called to provide an alternate tag. This allows us to fail
- * gracefully if we can make a good guess, for example, when browsers add novel
- * kinds of HTMLElement that we have never heard of. Initialized by
- * [initHooks].
- */
+/// If a lookup via [getTagFunction] on an object [object] that has [tag] fails,
+/// this function is called to provide an alternate tag. This allows us to fail
+/// gracefully if we can make a good guess, for example, when browsers add novel
+/// kinds of HTMLElement that we have never heard of. Initialized by
+/// [initHooks].
Function alternateTagFunction;
-/**
- * Returns the prototype for the JavaScript constructor named by an input tag.
- * Returns `null` if there is no such constructor, or if pre-patching of the
- * constructor is to be avoided. Initialized by [initHooks].
- */
+/// Returns the prototype for the JavaScript constructor named by an input tag.
+/// Returns `null` if there is no such constructor, or if pre-patching of the
+/// constructor is to be avoided. Initialized by [initHooks].
Function prototypeForTagFunction;
String toStringForNativeObject(var obj) {
@@ -73,9 +67,7 @@
int hashCodeForNativeObject(object) => Primitives.objectHashCode(object);
-/**
- * Sets a JavaScript property on an object.
- */
+/// Sets a JavaScript property on an object.
void defineProperty(var obj, String property, var value) {
JS(
'void',
@@ -97,20 +89,16 @@
'depends:none;effects:none;', JsBuiltin.dartObjectConstructor));
}
-/**
- * A JavaScript object mapping tags to the constructors of interceptors.
- * This is a JavaScript object with no prototype.
- *
- * Example: 'HTMLImageElement' maps to the ImageElement class constructor.
- */
+/// A JavaScript object mapping tags to the constructors of interceptors.
+/// This is a JavaScript object with no prototype.
+///
+/// Example: 'HTMLImageElement' maps to the ImageElement class constructor.
get interceptorsByTag => JS_EMBEDDED_GLOBAL('=Object', INTERCEPTORS_BY_TAG);
-/**
- * A JavaScript object mapping tags to `true` or `false`.
- *
- * Example: 'HTMLImageElement' maps to `true` since, as there are no subclasses
- * of ImageElement, it is a leaf class in the native class hierarchy.
- */
+/// A JavaScript object mapping tags to `true` or `false`.
+///
+/// Example: 'HTMLImageElement' maps to `true` since, as there are no subclasses
+/// of ImageElement, it is a leaf class in the native class hierarchy.
get leafTags => JS_EMBEDDED_GLOBAL('=Object', LEAF_TAGS);
String findDispatchTagForInterceptorClass(interceptorClassConstructor) {
@@ -118,17 +106,13 @@
'', r'#.#', interceptorClassConstructor, NATIVE_SUPERCLASS_TAG_NAME);
}
-/**
- * Cache of dispatch records for instances. This is a JavaScript object used as
- * a map. Keys are instance tags, e.g. "!SomeThing". The cache permits the
- * sharing of one dispatch record between multiple instances.
- */
+/// Cache of dispatch records for instances. This is a JavaScript object used
+/// as a map. Keys are instance tags, e.g. "!SomeThing". The cache permits the
+/// sharing of one dispatch record between multiple instances.
var dispatchRecordsForInstanceTags;
-/**
- * Cache of interceptors indexed by uncacheable tags, e.g. "~SomeThing".
- * This is a JavaScript object used as a map.
- */
+/// Cache of interceptors indexed by uncacheable tags, e.g. "~SomeThing".
+/// This is a JavaScript object used as a map.
var interceptorsForUncacheableTags;
lookupInterceptor(String tag) {
@@ -155,12 +139,10 @@
/// A 'discriminator' function is to be used. TBD.
const DISCRIMINATED_MARK = '*';
-/**
- * Returns the interceptor for a native object, or returns `null` if not found.
- *
- * A dispatch record is cached according to the specification of the dispatch
- * tag for [obj].
- */
+/// Returns the interceptor for a native object, or returns `null` if not found.
+///
+/// A dispatch record is cached according to the specification of the dispatch
+/// tag for [obj].
@NoInline()
lookupAndCacheInterceptor(obj) {
assert(!isDartObject(obj));
@@ -270,10 +252,8 @@
}
}
-/**
- * [proto] should have no shadowing prototypes that are not also assigned a
- * dispatch rescord.
- */
+/// [proto] should have no shadowing prototypes that are not also assigned a
+/// dispatch rescord.
setNativeSubclassDispatchRecord(proto, interceptor) {
setDispatchProperty(proto, makeLeafDispatchRecord(interceptor));
}
@@ -338,41 +318,39 @@
}
}
-/**
- * Initializes [getTagFunction] and [alternateTagFunction].
- *
- * These functions are 'hook functions', collectively 'hooks'. They initialized
- * by applying a series of hooks transformers. Built-in hooks transformers deal
- * with various known browser behaviours.
- *
- * Each hook tranformer takes a 'hooks' input which is a JavaScript object
- * containing the hook functions, and returns the same or a new object with
- * replacements. The replacements can wrap the originals to provide alternate
- * or modified behaviour.
- *
- * { getTag: function(obj) {...},
- * getUnknownTag: function(obj, tag) {...},
- * prototypeForTag: function(tag) {...},
- * discriminator: function(tag) {...},
- * }
- *
- * * getTag(obj) returns the dispatch tag, or `null`.
- * * getUnknownTag(obj, tag) returns a tag when [getTag] fails.
- * * prototypeForTag(tag) returns the prototype of the constructor for tag,
- * or `null` if not available or prepatching is undesirable.
- * * discriminator(tag) returns a function TBD.
- *
- * The web site can adapt a dart2js application by loading code ahead of the
- * dart2js application that defines hook transformers to be after the built in
- * ones. Code defining a transformer HT should use the following pattern to
- * ensure multiple transformers can be composed:
- *
- * (dartNativeDispatchHooksTransformer =
- * window.dartNativeDispatchHooksTransformer || []).push(HT);
- *
- *
- * TODO: Implement and describe dispatch tags and their caching methods.
- */
+/// Initializes [getTagFunction] and [alternateTagFunction].
+///
+/// These functions are 'hook functions', collectively 'hooks'. They
+/// initialized by applying a series of hooks transformers. Built-in hooks
+/// transformers deal with various known browser behaviours.
+///
+/// Each hook tranformer takes a 'hooks' input which is a JavaScript object
+/// containing the hook functions, and returns the same or a new object with
+/// replacements. The replacements can wrap the originals to provide alternate
+/// or modified behaviour.
+///
+/// { getTag: function(obj) {...},
+/// getUnknownTag: function(obj, tag) {...},
+/// prototypeForTag: function(tag) {...},
+/// discriminator: function(tag) {...},
+/// }
+///
+/// * getTag(obj) returns the dispatch tag, or `null`.
+/// * getUnknownTag(obj, tag) returns a tag when [getTag] fails.
+/// * prototypeForTag(tag) returns the prototype of the constructor for tag,
+/// or `null` if not available or prepatching is undesirable.
+/// * discriminator(tag) returns a function TBD.
+///
+/// The web site can adapt a dart2js application by loading code ahead of the
+/// dart2js application that defines hook transformers to be after the built in
+/// ones. Code defining a transformer HT should use the following pattern to
+/// ensure multiple transformers can be composed:
+///
+/// (dartNativeDispatchHooksTransformer =
+/// window.dartNativeDispatchHooksTransformer || []).push(HT);
+///
+///
+/// TODO: Implement and describe dispatch tags and their caching methods.
void initHooks() {
// The initial simple hooks:
var hooks = JS('', '#()', _baseHooks);
@@ -478,14 +456,12 @@
discriminator: discriminator };
}''');
-/**
- * Returns the name of the constructor function for browsers where
- * `object.constructor.name` is not reliable.
- *
- * This function is split out of [_fallbackConstructorHooksTransformerGenerator]
- * as it is called from both the dispatch hooks and via
- * [constructorNameFallback] from objectToString.
- */
+/// Returns the name of the constructor function for browsers where
+/// `object.constructor.name` is not reliable.
+///
+/// This function is split out of
+/// [_fallbackConstructorHooksTransformerGenerator] as it is called from both
+/// the dispatch hooks and via [constructorNameFallback] from objectToString.
const _constructorNameFallback = const JS_CONST(r'''
function getTagFallback(o) {
var s = Object.prototype.toString.call(o);
diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
index 7889c36..9fa9070 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
@@ -2,10 +2,8 @@
// 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.
-/**
- * Specialized integers and floating point numbers,
- * with SIMD support and efficient lists.
- */
+/// Specialized integers and floating point numbers,
+/// with SIMD support and efficient lists.
library dart.typed_data.implementation;
import 'dart:collection' show ListMixin;
@@ -99,20 +97,16 @@
}
}
-/**
- * A fixed-length list of Float32x4 numbers that is viewable as a
- * [TypedData]. For long lists, this implementation will be considerably more
- * space- and time-efficient than the default [List] implementation.
- */
+/// A fixed-length list of Float32x4 numbers that is viewable as a
+/// [TypedData]. For long lists, this implementation will be considerably more
+/// space- and time-efficient than the default [List] implementation.
class NativeFloat32x4List extends Object
with ListMixin<Float32x4>, FixedLengthListMixin<Float32x4>
implements Float32x4List {
final NativeFloat32List _storage;
- /**
- * Creates a [Float32x4List] of the specified length (in elements),
- * all of whose elements are initially zero.
- */
+ /// Creates a [Float32x4List] of the specified length (in elements),
+ /// all of whose elements are initially zero.
NativeFloat32x4List(int length)
: _storage = new NativeFloat32List(length * 4);
@@ -131,10 +125,8 @@
Type get runtimeType => Float32x4List;
- /**
- * Creates a [Float32x4List] with the same size as the [elements] list
- * and copies over the elements.
- */
+ /// Creates a [Float32x4List] with the same size as the [elements] list
+ /// and copies over the elements.
factory NativeFloat32x4List.fromList(List<Float32x4> list) {
if (list is NativeFloat32x4List) {
return new NativeFloat32x4List._externalStorage(
@@ -178,20 +170,16 @@
}
}
-/**
- * A fixed-length list of Int32x4 numbers that is viewable as a
- * [TypedData]. For long lists, this implementation will be considerably more
- * space- and time-efficient than the default [List] implementation.
- */
+/// A fixed-length list of Int32x4 numbers that is viewable as a
+/// [TypedData]. For long lists, this implementation will be considerably more
+/// space- and time-efficient than the default [List] implementation.
class NativeInt32x4List extends Object
with ListMixin<Int32x4>, FixedLengthListMixin<Int32x4>
implements Int32x4List {
final Int32List _storage;
- /**
- * Creates a [Int32x4List] of the specified length (in elements),
- * all of whose elements are initially zero.
- */
+ /// Creates a [Int32x4List] of the specified length (in elements),
+ /// all of whose elements are initially zero.
NativeInt32x4List(int length) : _storage = new NativeInt32List(length * 4);
NativeInt32x4List._externalStorage(Int32List storage) : _storage = storage;
@@ -209,10 +197,8 @@
Type get runtimeType => Int32x4List;
- /**
- * Creates a [Int32x4List] with the same size as the [elements] list
- * and copies over the elements.
- */
+ /// Creates a [Int32x4List] with the same size as the [elements] list
+ /// and copies over the elements.
factory NativeInt32x4List.fromList(List<Int32x4> list) {
if (list is NativeInt32x4List) {
return new NativeInt32x4List._externalStorage(
@@ -256,20 +242,16 @@
}
}
-/**
- * A fixed-length list of Float64x2 numbers that is viewable as a
- * [TypedData]. For long lists, this implementation will be considerably more
- * space- and time-efficient than the default [List] implementation.
- */
+/// A fixed-length list of Float64x2 numbers that is viewable as a
+/// [TypedData]. For long lists, this implementation will be considerably more
+/// space- and time-efficient than the default [List] implementation.
class NativeFloat64x2List extends Object
with ListMixin<Float64x2>, FixedLengthListMixin<Float64x2>
implements Float64x2List {
final NativeFloat64List _storage;
- /**
- * Creates a [Float64x2List] of the specified length (in elements),
- * all of whose elements are initially zero.
- */
+ /// Creates a [Float64x2List] of the specified length (in elements),
+ /// all of whose elements are initially zero.
NativeFloat64x2List(int length)
: _storage = new NativeFloat64List(length * 2);
@@ -284,10 +266,8 @@
}
}
- /**
- * Creates a [Float64x2List] with the same size as the [elements] list
- * and copies over the elements.
- */
+ /// Creates a [Float64x2List] with the same size as the [elements] list
+ /// and copies over the elements.
factory NativeFloat64x2List.fromList(List<Float64x2> list) {
if (list is NativeFloat64x2List) {
return new NativeFloat64x2List._externalStorage(
@@ -331,30 +311,22 @@
@Native('ArrayBufferView')
class NativeTypedData implements TypedData {
- /**
- * Returns the byte buffer associated with this object.
- */
+ /// Returns the byte buffer associated with this object.
@Creates('NativeByteBuffer')
// May be Null for IE's CanvasPixelArray.
@Returns('NativeByteBuffer|Null')
final ByteBuffer buffer;
- /**
- * Returns the length of this view, in bytes.
- */
+ /// Returns the length of this view, in bytes.
@JSName('byteLength')
final int lengthInBytes;
- /**
- * Returns the offset in bytes into the underlying byte buffer of this view.
- */
+ /// Returns the offset in bytes into the underlying byte buffer of this view.
@JSName('byteOffset')
final int offsetInBytes;
- /**
- * Returns the number of bytes in the representation of each element in this
- * list.
- */
+ /// Returns the number of bytes in the representation of each element in this
+ /// list.
@JSName('BYTES_PER_ELEMENT')
final int elementSizeInBytes;
@@ -413,24 +385,20 @@
@Native('DataView')
class NativeByteData extends NativeTypedData implements ByteData {
- /**
- * Creates a [ByteData] of the specified length (in elements), all of
- * whose elements are initially zero.
- */
+ /// Creates a [ByteData] of the specified length (in elements), all of
+ /// whose elements are initially zero.
factory NativeByteData(int length) => _create1(_checkLength(length));
- /**
- * Creates an [ByteData] _view_ of the specified region in the specified
- * byte buffer. Changes in the [ByteData] will be visible in the byte
- * buffer and vice versa. If the [offsetInBytes] index of the region is not
- * specified, it defaults to zero (the first byte in the byte buffer).
- * If the length is not specified, it defaults to null, which indicates
- * that the view extends to the end of the byte buffer.
- *
- * Throws [RangeError] if [offsetInBytes] or [length] are negative, or
- * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
- * the length of [buffer].
- */
+ /// Creates an [ByteData] _view_ of the specified region in the specified
+ /// byte buffer. Changes in the [ByteData] will be visible in the byte
+ /// buffer and vice versa. If the [offsetInBytes] index of the region is not
+ /// specified, it defaults to zero (the first byte in the byte buffer).
+ /// If the length is not specified, it defaults to null, which indicates
+ /// that the view extends to the end of the byte buffer.
+ ///
+ /// Throws [RangeError] if [offsetInBytes] or [length] are negative, or
+ /// if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
+ /// the length of [buffer].
factory NativeByteData.view(
ByteBuffer buffer, int offsetInBytes, int length) {
_checkViewArguments(buffer, offsetInBytes, length);
@@ -443,14 +411,12 @@
int get elementSizeInBytes => 1;
- /**
- * Returns the floating point number represented by the four bytes at
- * the specified [byteOffset] in this object, in IEEE 754
- * single-precision binary floating-point format (binary32).
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 4` is greater than the length of this object.
- */
+ /// Returns the floating point number represented by the four bytes at
+ /// the specified [byteOffset] in this object, in IEEE 754
+ /// single-precision binary floating-point format (binary32).
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 4` is greater than the length of this object.
double getFloat32(int byteOffset, [Endian endian = Endian.big]) =>
_getFloat32(byteOffset, Endian.little == endian);
@@ -458,14 +424,12 @@
@Returns('num')
num _getFloat32(int byteOffset, [bool littleEndian]) native;
- /**
- * Returns the floating point number represented by the eight bytes at
- * the specified [byteOffset] in this object, in IEEE 754
- * double-precision binary floating-point format (binary64).
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 8` is greater than the length of this object.
- */
+ /// Returns the floating point number represented by the eight bytes at
+ /// the specified [byteOffset] in this object, in IEEE 754
+ /// double-precision binary floating-point format (binary64).
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 8` is greater than the length of this object.
double getFloat64(int byteOffset, [Endian endian = Endian.big]) =>
_getFloat64(byteOffset, Endian.little == endian);
@@ -473,16 +437,14 @@
@Returns('num')
num _getFloat64(int byteOffset, [bool littleEndian]) native;
- /**
- * Returns the (possibly negative) integer represented by the two bytes at
- * the specified [byteOffset] in this object, in two's complement binary
- * form.
- * The return value will be between 2<sup>15</sup> and 2<sup>15</sup> - 1,
- * inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 2` is greater than the length of this object.
- */
+ /// Returns the (possibly negative) integer represented by the two bytes at
+ /// the specified [byteOffset] in this object, in two's complement binary
+ /// form.
+ /// The return value will be between 2<sup>15</sup> and 2<sup>15</sup> - 1,
+ /// inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 2` is greater than the length of this object.
int getInt16(int byteOffset, [Endian endian = Endian.big]) =>
_getInt16(byteOffset, Endian.little == endian);
@@ -490,16 +452,14 @@
@Returns('int')
int _getInt16(int byteOffset, [bool littleEndian]) native;
- /**
- * Returns the (possibly negative) integer represented by the four bytes at
- * the specified [byteOffset] in this object, in two's complement binary
- * form.
- * The return value will be between 2<sup>31</sup> and 2<sup>31</sup> - 1,
- * inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 4` is greater than the length of this object.
- */
+ /// Returns the (possibly negative) integer represented by the four bytes at
+ /// the specified [byteOffset] in this object, in two's complement binary
+ /// form.
+ /// The return value will be between 2<sup>31</sup> and 2<sup>31</sup> - 1,
+ /// inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 4` is greater than the length of this object.
int getInt32(int byteOffset, [Endian endian = Endian.big]) =>
_getInt32(byteOffset, Endian.little == endian);
@@ -507,39 +467,33 @@
@Returns('int')
int _getInt32(int byteOffset, [bool littleEndian]) native;
- /**
- * Returns the (possibly negative) integer represented by the eight bytes at
- * the specified [byteOffset] in this object, in two's complement binary
- * form.
- * The return value will be between 2<sup>63</sup> and 2<sup>63</sup> - 1,
- * inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 8` is greater than the length of this object.
- */
+ /// Returns the (possibly negative) integer represented by the eight bytes at
+ /// the specified [byteOffset] in this object, in two's complement binary
+ /// form.
+ /// The return value will be between 2<sup>63</sup> and 2<sup>63</sup> - 1,
+ /// inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 8` is greater than the length of this object.
int getInt64(int byteOffset, [Endian endian = Endian.big]) {
throw new UnsupportedError('Int64 accessor not supported by dart2js.');
}
- /**
- * Returns the (possibly negative) integer represented by the byte at the
- * specified [byteOffset] in this object, in two's complement binary
- * representation. The return value will be between -128 and 127, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * greater than or equal to the length of this object.
- */
+ /// Returns the (possibly negative) integer represented by the byte at the
+ /// specified [byteOffset] in this object, in two's complement binary
+ /// representation. The return value will be between -128 and 127, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// greater than or equal to the length of this object.
int getInt8(int byteOffset) native;
- /**
- * Returns the positive integer represented by the two bytes starting
- * at the specified [byteOffset] in this object, in unsigned binary
- * form.
- * The return value will be between 0 and 2<sup>16</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 2` is greater than the length of this object.
- */
+ /// Returns the positive integer represented by the two bytes starting
+ /// at the specified [byteOffset] in this object, in unsigned binary
+ /// form.
+ /// The return value will be between 0 and 2<sup>16</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 2` is greater than the length of this object.
int getUint16(int byteOffset, [Endian endian = Endian.big]) =>
_getUint16(byteOffset, Endian.little == endian);
@@ -547,15 +501,13 @@
@Returns('JSUInt31')
int _getUint16(int byteOffset, [bool littleEndian]) native;
- /**
- * Returns the positive integer represented by the four bytes starting
- * at the specified [byteOffset] in this object, in unsigned binary
- * form.
- * The return value will be between 0 and 2<sup>32</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 4` is greater than the length of this object.
- */
+ /// Returns the positive integer represented by the four bytes starting
+ /// at the specified [byteOffset] in this object, in unsigned binary
+ /// form.
+ /// The return value will be between 0 and 2<sup>32</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 4` is greater than the length of this object.
int getUint32(int byteOffset, [Endian endian = Endian.big]) =>
_getUint32(byteOffset, Endian.little == endian);
@@ -563,172 +515,148 @@
@Returns('JSUInt32')
int _getUint32(int byteOffset, [bool littleEndian]) native;
- /**
- * Returns the positive integer represented by the eight bytes starting
- * at the specified [byteOffset] in this object, in unsigned binary
- * form.
- * The return value will be between 0 and 2<sup>64</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 8` is greater than the length of this object.
- */
+ /// Returns the positive integer represented by the eight bytes starting
+ /// at the specified [byteOffset] in this object, in unsigned binary
+ /// form.
+ /// The return value will be between 0 and 2<sup>64</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 8` is greater than the length of this object.
int getUint64(int byteOffset, [Endian endian = Endian.big]) {
throw new UnsupportedError('Uint64 accessor not supported by dart2js.');
}
- /**
- * Returns the positive integer represented by the byte at the specified
- * [byteOffset] in this object, in unsigned binary form. The
- * return value will be between 0 and 255, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * greater than or equal to the length of this object.
- */
+ /// Returns the positive integer represented by the byte at the specified
+ /// [byteOffset] in this object, in unsigned binary form. The
+ /// return value will be between 0 and 255, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// greater than or equal to the length of this object.
int getUint8(int byteOffset) native;
- /**
- * Sets the four bytes starting at the specified [byteOffset] in this
- * object to the IEEE 754 single-precision binary floating-point
- * (binary32) representation of the specified [value].
- *
- * **Note that this method can lose precision.** The input [value] is
- * a 64-bit floating point value, which will be converted to 32-bit
- * floating point value by IEEE 754 rounding rules before it is stored.
- * If [value] cannot be represented exactly as a binary32, it will be
- * converted to the nearest binary32 value. If two binary32 values are
- * equally close, the one whose least significant bit is zero will be used.
- * Note that finite (but large) values can be converted to infinity, and
- * small non-zero values can be converted to zero.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 4` is greater than the length of this object.
- */
+ /// Sets the four bytes starting at the specified [byteOffset] in this
+ /// object to the IEEE 754 single-precision binary floating-point
+ /// (binary32) representation of the specified [value].
+ ///
+ /// **Note that this method can lose precision.** The input [value] is
+ /// a 64-bit floating point value, which will be converted to 32-bit
+ /// floating point value by IEEE 754 rounding rules before it is stored.
+ /// If [value] cannot be represented exactly as a binary32, it will be
+ /// converted to the nearest binary32 value. If two binary32 values are
+ /// equally close, the one whose least significant bit is zero will be used.
+ /// Note that finite (but large) values can be converted to infinity, and
+ /// small non-zero values can be converted to zero.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 4` is greater than the length of this object.
void setFloat32(int byteOffset, num value, [Endian endian = Endian.big]) =>
_setFloat32(byteOffset, value, Endian.little == endian);
@JSName('setFloat32')
void _setFloat32(int byteOffset, num value, [bool littleEndian]) native;
- /**
- * Sets the eight bytes starting at the specified [byteOffset] in this
- * object to the IEEE 754 double-precision binary floating-point
- * (binary64) representation of the specified [value].
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 8` is greater than the length of this object.
- */
+ /// Sets the eight bytes starting at the specified [byteOffset] in this
+ /// object to the IEEE 754 double-precision binary floating-point
+ /// (binary64) representation of the specified [value].
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 8` is greater than the length of this object.
void setFloat64(int byteOffset, num value, [Endian endian = Endian.big]) =>
_setFloat64(byteOffset, value, Endian.little == endian);
@JSName('setFloat64')
void _setFloat64(int byteOffset, num value, [bool littleEndian]) native;
- /**
- * Sets the two bytes starting at the specified [byteOffset] in this
- * object to the two's complement binary representation of the specified
- * [value], which must fit in two bytes. In other words, [value] must lie
- * between 2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 2` is greater than the length of this object.
- */
+ /// Sets the two bytes starting at the specified [byteOffset] in this
+ /// object to the two's complement binary representation of the specified
+ /// [value], which must fit in two bytes. In other words, [value] must lie
+ /// between 2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 2` is greater than the length of this object.
void setInt16(int byteOffset, int value, [Endian endian = Endian.big]) =>
_setInt16(byteOffset, value, Endian.little == endian);
@JSName('setInt16')
void _setInt16(int byteOffset, int value, [bool littleEndian]) native;
- /**
- * Sets the four bytes starting at the specified [byteOffset] in this
- * object to the two's complement binary representation of the specified
- * [value], which must fit in four bytes. In other words, [value] must lie
- * between 2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 4` is greater than the length of this object.
- */
+ /// Sets the four bytes starting at the specified [byteOffset] in this
+ /// object to the two's complement binary representation of the specified
+ /// [value], which must fit in four bytes. In other words, [value] must lie
+ /// between 2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 4` is greater than the length of this object.
void setInt32(int byteOffset, int value, [Endian endian = Endian.big]) =>
_setInt32(byteOffset, value, Endian.little == endian);
@JSName('setInt32')
void _setInt32(int byteOffset, int value, [bool littleEndian]) native;
- /**
- * Sets the eight bytes starting at the specified [byteOffset] in this
- * object to the two's complement binary representation of the specified
- * [value], which must fit in eight bytes. In other words, [value] must lie
- * between 2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 8` is greater than the length of this object.
- */
+ /// Sets the eight bytes starting at the specified [byteOffset] in this
+ /// object to the two's complement binary representation of the specified
+ /// [value], which must fit in eight bytes. In other words, [value] must lie
+ /// between 2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 8` is greater than the length of this object.
void setInt64(int byteOffset, int value, [Endian endian = Endian.big]) {
throw new UnsupportedError('Int64 accessor not supported by dart2js.');
}
- /**
- * Sets the byte at the specified [byteOffset] in this object to the
- * two's complement binary representation of the specified [value], which
- * must fit in a single byte. In other words, [value] must be between
- * -128 and 127, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * greater than or equal to the length of this object.
- */
+ /// Sets the byte at the specified [byteOffset] in this object to the
+ /// two's complement binary representation of the specified [value], which
+ /// must fit in a single byte. In other words, [value] must be between
+ /// -128 and 127, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// greater than or equal to the length of this object.
void setInt8(int byteOffset, int value) native;
- /**
- * Sets the two bytes starting at the specified [byteOffset] in this object
- * to the unsigned binary representation of the specified [value],
- * which must fit in two bytes. in other words, [value] must be between
- * 0 and 2<sup>16</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 2` is greater than the length of this object.
- */
+ /// Sets the two bytes starting at the specified [byteOffset] in this object
+ /// to the unsigned binary representation of the specified [value],
+ /// which must fit in two bytes. in other words, [value] must be between
+ /// 0 and 2<sup>16</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 2` is greater than the length of this object.
void setUint16(int byteOffset, int value, [Endian endian = Endian.big]) =>
_setUint16(byteOffset, value, Endian.little == endian);
@JSName('setUint16')
void _setUint16(int byteOffset, int value, [bool littleEndian]) native;
- /**
- * Sets the four bytes starting at the specified [byteOffset] in this object
- * to the unsigned binary representation of the specified [value],
- * which must fit in four bytes. in other words, [value] must be between
- * 0 and 2<sup>32</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 4` is greater than the length of this object.
- */
+ /// Sets the four bytes starting at the specified [byteOffset] in this object
+ /// to the unsigned binary representation of the specified [value],
+ /// which must fit in four bytes. in other words, [value] must be between
+ /// 0 and 2<sup>32</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 4` is greater than the length of this object.
void setUint32(int byteOffset, int value, [Endian endian = Endian.big]) =>
_setUint32(byteOffset, value, Endian.little == endian);
@JSName('setUint32')
void _setUint32(int byteOffset, int value, [bool littleEndian]) native;
- /**
- * Sets the eight bytes starting at the specified [byteOffset] in this object
- * to the unsigned binary representation of the specified [value],
- * which must fit in eight bytes. in other words, [value] must be between
- * 0 and 2<sup>64</sup> - 1, inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative, or
- * `byteOffset + 8` is greater than the length of this object.
- */
+ /// Sets the eight bytes starting at the specified [byteOffset] in this object
+ /// to the unsigned binary representation of the specified [value],
+ /// which must fit in eight bytes. in other words, [value] must be between
+ /// 0 and 2<sup>64</sup> - 1, inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative, or
+ /// `byteOffset + 8` is greater than the length of this object.
void setUint64(int byteOffset, int value, [Endian endian = Endian.big]) {
throw new UnsupportedError('Uint64 accessor not supported by dart2js.');
}
- /**
- * Sets the byte at the specified [byteOffset] in this object to the
- * unsigned binary representation of the specified [value], which must fit
- * in a single byte. in other words, [value] must be between 0 and 255,
- * inclusive.
- *
- * Throws [RangeError] if [byteOffset] is negative,
- * or greater than or equal to the length of this object.
- */
+ /// Sets the byte at the specified [byteOffset] in this object to the
+ /// unsigned binary representation of the specified [value], which must fit
+ /// in a single byte. in other words, [value] must be between 0 and 255,
+ /// inclusive.
+ ///
+ /// Throws [RangeError] if [byteOffset] is negative,
+ /// or greater than or equal to the length of this object.
void setUint8(int byteOffset, int value) native;
static NativeByteData _create1(arg) =>
@@ -1159,11 +1087,9 @@
JS('NativeUint8List', 'new Uint8Array(#, #, #)', arg1, arg2, arg3);
}
-/**
- * Implementation of Dart Float32x4 immutable value type and operations.
- * Float32x4 stores 4 32-bit floating point values in "lanes".
- * The lanes are "x", "y", "z", and "w" respectively.
- */
+/// Implementation of Dart Float32x4 immutable value type and operations.
+/// Float32x4 stores 4 32-bit floating point values in "lanes".
+/// The lanes are "x", "y", "z", and "w" respectively.
class NativeFloat32x4 implements Float32x4 {
final double x;
final double y;
@@ -1494,11 +1420,9 @@
}
}
-/**
- * Interface of Dart Int32x4 and operations.
- * Int32x4 stores 4 32-bit bit-masks in "lanes".
- * The lanes are "x", "y", "z", and "w" respectively.
- */
+/// Interface of Dart Int32x4 and operations.
+/// Int32x4 stores 4 32-bit bit-masks in "lanes".
+/// The lanes are "x", "y", "z", and "w" respectively.
class NativeInt32x4 implements Int32x4 {
final int x;
final int y;
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index a588b08..77f746b 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -7,31 +7,27 @@
// Helper method used by internal libraries.
regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
-/**
- * Returns a native version of the RegExp with the global flag set.
- *
- * The RegExp's `lastIndex` property is zero when it is returned.
- *
- * The returned regexp is shared, and its `lastIndex` property may be
- * modified by other uses, so the returned regexp must be used immediately
- * when it's returned, with no user-provided code run in between.
- */
+/// Returns a native version of the RegExp with the global flag set.
+///
+/// The RegExp's `lastIndex` property is zero when it is returned.
+///
+/// The returned regexp is shared, and its `lastIndex` property may be
+/// modified by other uses, so the returned regexp must be used immediately
+/// when it's returned, with no user-provided code run in between.
regExpGetGlobalNative(JSSyntaxRegExp regexp) {
var nativeRegexp = regexp._nativeGlobalVersion;
JS('void', '#.lastIndex = 0', nativeRegexp);
return nativeRegexp;
}
-/**
- * Computes the number of captures in a regexp.
- *
- * This currently involves creating a new RegExp object with a different
- * source and running it against the empty string (the last part is usually
- * fast).
- *
- * The JSSyntaxRegExp could cache the result, and set the cache any time
- * it finds a match.
- */
+/// Computes the number of captures in a regexp.
+///
+/// This currently involves creating a new RegExp object with a different
+/// source and running it against the empty string (the last part is usually
+/// fast).
+///
+/// The JSSyntaxRegExp could cache the result, and set the cache any time
+/// it finds a match.
int regExpCaptureCount(JSSyntaxRegExp regexp) {
var nativeAnchoredRegExp = regexp._nativeAnchoredVersion;
var match = JS('JSExtendableArray', '#.exec("")', nativeAnchoredRegExp);
@@ -239,7 +235,7 @@
}
}
-/** Find the first match of [regExp] in [string] at or after [start]. */
+/// Find the first match of [regExp] in [string] at or after [start].
Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
return regExp._execGlobal(string, start);
}
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 5bc9a6c..9856d55 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -147,32 +147,14 @@
// anchored at [node].
// and that node is returned. It should replace the reference to [node]
// in any parent tree or root pointer.
- Node _splayMin(Node node) {
- Node current = node;
- while (current.left != null) {
- Node left = current.left;
- current.left = left.right;
- left.right = current;
- current = left;
- }
- return current;
- }
+ external Node _splayMin(Node node);
// Emulates splaying with a key that is greater than any in the subtree
// anchored at [node].
// After this, the largest element in the tree is the root of the subtree,
// and that node is returned. It should replace the reference to [node]
// in any parent tree or root pointer.
- Node _splayMax(Node node) {
- Node current = node;
- while (current.right != null) {
- Node right = current.right;
- current.right = right.left;
- right.left = current;
- current = right;
- }
- return current;
- }
+ external Node _splayMax(Node node);
Node _remove(K key) {
if (_root == null) return null;
diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
index 1f46d11..b24c0ea 100644
--- a/sdk/lib/core/date_time.dart
+++ b/sdk/lib/core/date_time.dart
@@ -237,10 +237,10 @@
* The time part is a two digit hour,
* then optionally a two digit minutes value,
* then optionally a two digit seconds value, and
- * then optionally a '.' followed by a one-to-six digit second fraction.
+ * then optionally a '.' or ',' followed by a one-to-six digit second fraction.
* The minutes and seconds may be separated from the previous parts by a
* ':'.
- * Examples: "12", "12:30:24.124", "123010.50".
+ * Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
* * An optional time-zone offset part,
* possibly separated from the previous by a space.
* The time zone is either 'z' or 'Z', or it is a signed two digit hour
@@ -261,6 +261,7 @@
*
* * `"2012-02-27 13:27:00"`
* * `"2012-02-27 13:27:00.123456z"`
+ * * `"2012-02-27 13:27:00,123456z"`
* * `"20120227 13:27:00"`
* * `"20120227T132700"`
* * `"20120227"`
@@ -852,7 +853,7 @@
* time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
* minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
* seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
- * micros_opt ::= <empty> | '.' digit{1,6}
+ * micros_opt ::= <empty> | ('.' | ',') digit{1,6}
* timezone_opt ::= <empty> | space_opt timezone
* space_opt :: ' ' | <empty>
* timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
@@ -860,6 +861,6 @@
*/
static final RegExp _parseFormat = new RegExp(
r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
- r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{1,6}))?)?)?' // Time part.
+ r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,6}))?)?)?' // Time part.
r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
}
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index a293b48..4cf78b9 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -21,6 +21,13 @@
* This does not wait for any asynchronous operations to terminate. Using
* [exit] is therefore very likely to lose data.
*
+ * While debugging, the VM will not respect the `--pause-isolates-on-exit`
+ * flag if [exit] is called as invoking this method causes the Dart VM
+ * process to shutdown immediately. To properly break on exit, consider
+ * calling [debugger] from `dart:developer` or [Isolate.pause] from
+ * `dart:isolate` on [Isolate.current] to pause the isolate before
+ * invoking [exit].
+ *
* The handling of exit codes is platform specific.
*
* On Linux and OS X an exit code for normal termination will always
diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
index 658c834..f33a7a8 100644
--- a/sdk/lib/math/math.dart
+++ b/sdk/lib/math/math.dart
@@ -145,8 +145,9 @@
*
* This corresponds to the `pow` function defined in the IEEE Standard 754-2008.
*
- * Notice that an [int] result cannot overflow, but a [double] result might
- * be [double.infinity].
+ * Notice that the result may overflow. If integers are represented as 64-bit
+ * numbers, an integer result may be truncated, and a double result may overflow
+ * to positive or negative [double.infinity].
*/
external num pow(num x, num exponent);
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 10ad9d2..b620f62 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -56,7 +56,55 @@
[ $compiler == fasta ]
Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
-Language/Statements/For/syntax_t20 tatements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
+LanguageFeatures/Constant_update2018/*: Crash, Pass # Please triage these failures
+LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/03: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/04: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A02_t03/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A02_t03/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A02_t03/03: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A03_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/03: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/04: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/05: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/06: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/07: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/08: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/09: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/04: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/05: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/06: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/08: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/semantics_A04_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/semantics_A01_t01/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/semantics_A01_t01/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/semantics_A01_t01/09: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/semantics_A01_t01/10: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/semantics_A05_t01: Pass
+LanguageFeatures/Set-literals/semantics_A05_t05/01: MissingCompileTimeError # Exact types
+LanguageFeatures/Set-literals/semantics_A05_t05/02: MissingCompileTimeError # Exact types
+LanguageFeatures/Set-literals/semantics_A05_t05/03: MissingCompileTimeError # Exact types
+LanguageFeatures/Set-literals/set_literals_A01_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/set_literals_A02_t01: Pass # CompileTimeError on $fasta
+LanguageFeatures/Set-literals/set_literals_A04_t02/01: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/02: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/03: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/04: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/05: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/11: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/12: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/set_literals_A04_t02/13: MissingCompileTimeError # Issue 35608
+LanguageFeatures/Set-literals/syntax_compatibility_A01_t01: Pass # CompileTimeError on $fasta
[ $runtime == vm ]
LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Slow # Does many calls
@@ -769,6 +817,93 @@
LibTest/isolate/ReceivePort/firstWhere_A02_t01: RuntimeError
LibTest/isolate/ReceivePort/transform_A01_t01: RuntimeError
+[ $runtime == vm && $arch != simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
+LanguageFeatures/Constant_update2018/CastOperator_A01_t01: DartkCrash
+LanguageFeatures/Constant_update2018/CastOperator_A02_t01: DartkCrash
+LanguageFeatures/Constant_update2018/CastOperator_A02_t02: DartkCrash
+LanguageFeatures/Constant_update2018/CastOperator_A03_t01/02: Pass
+LanguageFeatures/Constant_update2018/CastOperator_A03_t01/03: Pass
+LanguageFeatures/Constant_update2018/CastOperator_A03_t02/01: DartkCrash
+LanguageFeatures/Constant_update2018/CastOperator_A04_t01: Pass
+LanguageFeatures/Constant_update2018/CastOperator_A04_t02: DartkCrash
+LanguageFeatures/Constant_update2018/EqualityOperator_A01_t03: DartkCrash
+LanguageFeatures/Constant_update2018/EqualityOperator_A01_t04: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A01_t01: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A01_t02: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A02_t01: Fail
+LanguageFeatures/Constant_update2018/NewOperators_A02_t02: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A02_t03: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A02_t04: Fail
+LanguageFeatures/Constant_update2018/NewOperators_A02_t05: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A02_t06: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A02_t07: Fail
+LanguageFeatures/Constant_update2018/NewOperators_A02_t08: DartkCrash
+LanguageFeatures/Constant_update2018/NewOperators_A02_t09: DartkCrash
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t02: DartkCrash
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A01_t05: DartkCrash
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t02: DartkCrash
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A02_t05: DartkCrash
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05: DartkCrash
+LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t06: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t01: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A01_t02: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t01: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A02_t02: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t01: Pass
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t02: Pass
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t03/01: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A03_t04/01: DartkCrash
+LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t01: Pass
+LanguageFeatures/Constant_update2018/TypeTestOperator_A04_t02: Pass
+LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/03: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t02/04: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t03/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t03/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A02_t03/03: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A03_t01: Pass
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/03: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/04: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/05: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/06: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/07: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/08: MissingCompileTimeError
+LanguageFeatures/Set-literals/constant_set_literals_A05_t01/09: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/04: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/05: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/06: MissingCompileTimeError
+LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/08: MissingCompileTimeError
+LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: Pass
+LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: RuntimeError
+LanguageFeatures/Set-literals/semantics_A01_t01/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A01_t01/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A01_t01/09: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A01_t01/10: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A04_t01: Pass
+LanguageFeatures/Set-literals/semantics_A05_t05/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A05_t05/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A05_t05/03: MissingCompileTimeError
+LanguageFeatures/Set-literals/semantics_A05_t01: RuntimeError
+LanguageFeatures/Set-literals/set_literals_A01_t01: Pass
+LanguageFeatures/Set-literals/set_literals_A02_t01: Pass
+LanguageFeatures/Set-literals/set_literals_A04_t02/01: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/02: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/03: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/04: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/05: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/11: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/12: MissingCompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t02/13: MissingCompileTimeError
+LanguageFeatures/Set-literals/syntax_compatibility_A01_t01: Pass
+
[ $runtime != vm && $fasta ]
Language/Classes/Constructors/Constant_Constructors/potentially_constant_expression_t01: MissingCompileTimeError # Issue 34192
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index 9e1560e..715352e 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -71,9 +71,11 @@
class StaticTypeVisitorBase extends StaticTypeVisitor {
VariableScopeModel variableScopeModel;
- StaticTypeVisitorBase(ir.Component component)
- : super(new ir.TypeEnvironment(
- new ir.CoreTypes(component), new ir.ClassHierarchy(component)));
+ StaticTypeVisitorBase(
+ ir.Component component, ir.ClassHierarchy classHierarchy)
+ : super(
+ new ir.TypeEnvironment(new ir.CoreTypes(component), classHierarchy),
+ classHierarchy);
@override
bool get useAsserts => false;
@@ -132,7 +134,7 @@
DynamicVisitor(this.reporter, this.component, this._allowedListPath,
this.analyzedUrisFilter)
- : super(component);
+ : super(component, new ir.ClassHierarchy(component));
void run({bool verbose = false, bool generate = false}) {
if (!generate && _allowedListPath != null) {
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index cb3e829..5f6fdad 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -264,9 +264,6 @@
"pkg/compiler/lib/src/ssa/value_set.dart": {
"Dynamic invocation of 'add'.": 2
},
- "pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart": {
- "Dynamic access of 'scheme'.": 1
- },
"pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart": {
"Dynamic access of 'keys'.": 1,
"Dynamic invocation of 'toSet'.": 1,
@@ -281,4 +278,4 @@
"Dynamic access of 'superclass'.": 1,
"Dynamic access of 'needsTearOff'.": 1
}
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
index 6d8613f..d546a06 100644
--- a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
+++ b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
@@ -31,7 +31,8 @@
}
class Visitor extends StaticTypeVisitorBase {
- Visitor(ir.Component component) : super(component);
+ Visitor(ir.Component component)
+ : super(component, new ir.ClassHierarchy(component));
ir.DartType getStaticType(ir.Expression node) {
if (typeEnvironment == null) {
diff --git a/tests/compiler/dart2js/codegen/class_codegen_test.dart b/tests/compiler/dart2js/codegen/class_codegen_test.dart
index a9439f9..bb22e20 100644
--- a/tests/compiler/dart2js/codegen/class_codegen_test.dart
+++ b/tests/compiler/dart2js/codegen/class_codegen_test.dart
@@ -66,14 +66,14 @@
twoClasses() async {
String generated = await compileAll(TEST_ONE);
- Expect.isTrue(generated.contains(new RegExp('A: {[ \n]*"\\^": "Object;"')));
- Expect.isTrue(generated.contains(new RegExp('B: {[ \n]*"\\^": "Object;"')));
+ Expect.isTrue(generated.contains('A: function A()'));
+ Expect.isTrue(generated.contains('B: function B()'));
}
subClass() async {
checkOutput(String generated) {
- Expect.isTrue(generated.contains(new RegExp('A: {[ \n]*"\\^": "Object;"')));
- Expect.isTrue(generated.contains(new RegExp('B: {[ \n]*"\\^": "A;"')));
+ Expect.isTrue(generated.contains(RegExp(r'_inherit\(.\.A, .\.Object\)')));
+ Expect.isTrue(generated.contains(RegExp(r'_inherit\(.\.B, .\.A\)')));
}
checkOutput(await compileAll(TEST_TWO));
@@ -82,12 +82,15 @@
fieldTest() async {
String generated = await compileAll(TEST_FOUR);
- Expect.isTrue(generated
- .contains(new RegExp('B: {[ \n]*"\\^": "A;y,z,x",[ \n]*static:')));
+ Expect.isTrue(generated.contains(RegExp(r'B: function B\(t0, t1, t2\) {'
+ r'\s*this.y = t0;'
+ r'\s*this.z = t1;'
+ r'\s*this.x = t2;')));
}
constructor1() async {
String generated = await compileAll(TEST_FIVE);
+ print('--------------------\n$generated\n');
Expect.isTrue(generated.contains(new RegExp(r"new [$A-Z]+\.A\(a\);")));
}
diff --git a/tests/compiler/dart2js/codegen/gvn_test.dart b/tests/compiler/dart2js/codegen/gvn_test.dart
index 54f4d30..678d9fc 100644
--- a/tests/compiler/dart2js/codegen/gvn_test.dart
+++ b/tests/compiler/dart2js/codegen/gvn_test.dart
@@ -108,24 +108,22 @@
main() {
runTests() async {
await compile(TEST_ONE, entry: 'foo', check: (String generated) {
- RegExp regexp = new RegExp(r"1 \+ [a-z]+");
+ RegExp regexp = RegExp(r"1 \+ [a-z]+");
checkNumberOfMatches(regexp.allMatches(generated).iterator, 1);
});
await compile(TEST_TWO, entry: 'foo', check: (String generated) {
- checkNumberOfMatches(
- new RegExp("length").allMatches(generated).iterator, 1);
+ checkNumberOfMatches(RegExp("length").allMatches(generated).iterator, 1);
});
await compile(TEST_THREE, entry: 'foo', check: (String generated) {
- checkNumberOfMatches(
- new RegExp("number").allMatches(generated).iterator, 1);
+ checkNumberOfMatches(RegExp("number").allMatches(generated).iterator, 1);
});
await compile(TEST_FOUR, entry: 'foo', check: (String generated) {
- checkNumberOfMatches(new RegExp("shr").allMatches(generated).iterator, 1);
+ checkNumberOfMatches(RegExp("shr").allMatches(generated).iterator, 1);
});
await compileAll(TEST_FIVE).then((generated) {
checkNumberOfMatches(
- new RegExp("get\\\$foo").allMatches(generated).iterator, 1);
+ RegExp(r"get\$foo\(").allMatches(generated).iterator, 1);
});
await compileAll(TEST_SIX).then((generated) {
Expect.isTrue(generated.contains('for (t1 = a.field === 54; t1;)'));
diff --git a/tests/compiler/dart2js/codegen/no_constructor_body_test.dart b/tests/compiler/dart2js/codegen/no_constructor_body_test.dart
index e34f13c..7edc700 100644
--- a/tests/compiler/dart2js/codegen/no_constructor_body_test.dart
+++ b/tests/compiler/dart2js/codegen/no_constructor_body_test.dart
@@ -20,9 +20,8 @@
main() {
runTest() async {
String generated = await compileAll(TEST);
-
- Expect.isTrue(generated
- .contains(new RegExp('A: {[ \n]*"\\^": "Object;",[ \n]*static:')));
+ // No methods (including no constructor body method.
+ Expect.isTrue(generated.contains('.A.prototype = {}'));
}
asyncTest(() async {
diff --git a/tests/compiler/dart2js/codegen/no_duplicate_constructor_body_test.dart b/tests/compiler/dart2js/codegen/no_duplicate_constructor_body_test.dart
index 194fce2..8d18091 100644
--- a/tests/compiler/dart2js/codegen/no_duplicate_constructor_body_test.dart
+++ b/tests/compiler/dart2js/codegen/no_duplicate_constructor_body_test.dart
@@ -18,9 +18,14 @@
main() {
runTest() async {
String generated = await compileAll(CODE);
- RegExp regexp = new RegExp(r'\A: {[ \n]*"\^": "[A-Za-z]+;"');
+
+ RegExp regexp = RegExp(r'\.A\.prototype = {');
Iterator<Match> matches = regexp.allMatches(generated).iterator;
checkNumberOfMatches(matches, 1);
+
+ RegExp regexp2 = RegExp(r'A\$\w+: function');
+ Iterator<Match> matches2 = regexp2.allMatches(generated).iterator;
+ checkNumberOfMatches(matches2, 1);
}
asyncTest(() async {
diff --git a/tests/compiler/dart2js/deferred/inline_restrictions_test.dart b/tests/compiler/dart2js/deferred/inline_restrictions_test.dart
index 4d11985..70df323 100644
--- a/tests/compiler/dart2js/deferred/inline_restrictions_test.dart
+++ b/tests/compiler/dart2js/deferred/inline_restrictions_test.dart
@@ -57,7 +57,8 @@
// Test that inlineSameContext was inlined into lib1.
RegExp re4 = new RegExp(r"inline same context");
- Expect.isFalse(re4.hasMatch(lib3Output));
+ // Output can be null when it contains no code.
+ Expect.isTrue(lib3Output == null || !re4.hasMatch(lib3Output));
Expect.isTrue(re4.hasMatch(lib1Output));
});
}
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index 35e36e9..c891f34 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -103,7 +103,6 @@
: this.compiler = compiler,
super(compiler,
generateSourceMap: compiler.options.generateSourceMap,
- useStartupEmitter: compiler.options.useStartupEmitter,
useMultiSourceInfo: compiler.options.useMultiSourceInfo,
useNewSourceInfo: compiler.options.useNewSourceInfo);
diff --git a/tests/compiler/dart2js/end_to_end/uri_retention_test.dart b/tests/compiler/dart2js/end_to_end/uri_retention_test.dart
deleted file mode 100644
index 1fb8a72..0000000
--- a/tests/compiler/dart2js/end_to_end/uri_retention_test.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.test.uri_retention_test;
-
-import 'dart:async';
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/compiler_new.dart';
-import 'package:compiler/src/commandline_options.dart';
-import 'package:expect/expect.dart';
-import '../helpers/memory_compiler.dart' show runCompiler, OutputCollector;
-
-Future<String> compileSources(sources, {bool minify}) async {
- var options = <String>[];
- if (minify) options.add(Flags.minify);
- OutputCollector outputCollector = new OutputCollector();
- await runCompiler(
- memorySourceFiles: sources,
- options: options,
- outputProvider: outputCollector);
- return outputCollector.getOutput('', OutputType.js);
-}
-
-Future test(sources, {bool libName, bool fileName}) {
- return compileSources(sources, minify: false).then((output) {
- // Unminified the sources should always contain the library name and the
- // file name.
- Expect.isTrue(output.contains("main_lib"));
- Expect.isTrue(output.contains("main.dart"));
- }).then((_) {
- compileSources(sources, minify: true).then((output) {
- Expect.equals(libName, output.contains("main_lib"));
- Expect.isFalse(output.contains("main.dart"));
- });
- });
-}
-
-void main() {
- runTests() async {
- await test(MEMORY_SOURCE_FILES1, libName: false, fileName: false);
- }
-
- asyncTest(() async {
- print('--test from kernel------------------------------------------------');
- await runTests();
- });
-}
-
-const MEMORY_SOURCE_FILES1 = const <String, String>{
- 'main.dart': """
-library main_lib;
-
-class A {
- final uri = "foo";
-}
-
-main() {
- print(Uri.base);
- print(new A().uri);
-}
-""",
-};
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index f9b8ebf..e7becbd 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -11,6 +11,7 @@
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/util/features.dart';
import 'package:expect/expect.dart';
import 'package:sourcemap_testing/src/annotated_code_helper.dart';
@@ -687,6 +688,87 @@
}
}
+class FeaturesDataInterpreter implements DataInterpreter<Features> {
+ const FeaturesDataInterpreter();
+
+ @override
+ String isAsExpected(Features actualFeatures, String expectedData) {
+ if (expectedData == '*') {
+ return null;
+ } else if (expectedData == '') {
+ return actualFeatures.isNotEmpty ? "Expected empty data." : null;
+ } else {
+ List<String> errorsFound = [];
+ Features expectedFeatures = Features.fromText(expectedData);
+ expectedFeatures.forEach((String key, Object expectedValue) {
+ Object actualValue = actualFeatures[key] ?? '';
+ if (expectedValue == '') {
+ if (actualValue != '') {
+ errorsFound.add('Non-empty data found for $key');
+ }
+ } else if (expectedValue == '*') {
+ return;
+ } else if (expectedValue is List) {
+ if (actualValue is List) {
+ List actualList = actualValue.toList();
+ for (Object expectedObject in expectedValue) {
+ String expectedText = '$expectedObject';
+ bool matchFound = false;
+ if (expectedText.endsWith('*')) {
+ // Wildcard matcher.
+ String prefix =
+ expectedText.substring(0, expectedText.indexOf('*'));
+ List matches = [];
+ for (Object actualObject in actualList) {
+ if ('$actualObject'.startsWith(prefix)) {
+ matches.add(actualObject);
+ matchFound = true;
+ }
+ }
+ for (Object match in matches) {
+ actualList.remove(match);
+ }
+ } else {
+ for (Object actualObject in actualList) {
+ if (expectedText == '$actualObject') {
+ actualList.remove(actualObject);
+ matchFound = true;
+ break;
+ }
+ }
+ }
+ if (!matchFound) {
+ errorsFound.add("No match found for $key=[$expectedText]");
+ }
+ }
+ if (actualList.isNotEmpty) {
+ errorsFound
+ .add("Extra data found $key=[${actualList.join(',')}]");
+ }
+ } else {
+ errorsFound.add("List data expected for $key: "
+ "expected '$expectedValue', found '${actualValue}'");
+ }
+ } else if (expectedValue != actualValue) {
+ errorsFound.add(
+ "Mismatch for $key: expected '$expectedValue', found '${actualValue}");
+ }
+ });
+ return errorsFound.isNotEmpty ? errorsFound.join(', ') : null;
+ }
+ }
+
+ @override
+ String getText(Features actualData) {
+ return actualData.getText();
+ }
+
+ @override
+ bool isEmpty(Features actualData) {
+ return actualData == null || actualData.isEmpty;
+ }
+}
+
/// Checks [compiledData] against the expected data in [expectedMap] derived
/// from [code].
Future<bool> checkCode<T>(
@@ -715,8 +797,9 @@
reportError(
data.compiler.reporter,
actualData.sourceSpan,
- 'EXTRA $mode DATA for ${id.descriptor} = '
- '${colorizeActual('${IdValue.idToString(id, actualText)}')} for ${actualData.objectText}. '
+ 'EXTRA $mode DATA for ${id.descriptor}:\n '
+ 'object : ${actualData.objectText}\n '
+ 'actual : ${colorizeActual('${IdValue.idToString(id, actualText)}')}\n '
'Data was expected for these ids: ${expectedMap.keys}');
if (filterActualData == null || filterActualData(null, actualData)) {
hasLocalFailure = true;
@@ -730,7 +813,7 @@
reportError(
data.compiler.reporter,
actualData.sourceSpan,
- 'UNEXPECTED $mode DATA for ${id.descriptor}: \n '
+ 'UNEXPECTED $mode DATA for ${id.descriptor}:\n '
'detail : ${colorizeMessage(unexpectedMessage)}\n '
'object : ${actualData.objectText}\n '
'expected: ${colorizeExpected('$expected')}\n '
diff --git a/tests/compiler/dart2js/impact/data/classes.dart b/tests/compiler/dart2js/impact/data/classes.dart
index a31b32f..bacab72 100644
--- a/tests/compiler/dart2js/impact/data/classes.dart
+++ b/tests/compiler/dart2js/impact/data/classes.dart
@@ -240,7 +240,7 @@
}
/*strong.element: testInstanceGenericMethod:
- dynamic=[GenericClass.genericMethod<bool>(1)],
+ dynamic=[exact:GenericClass.genericMethod<bool>(1)],
static=[
GenericClass.generative(0),
assertIsSubtype,
diff --git a/tests/compiler/dart2js/impact/data/exact.dart b/tests/compiler/dart2js/impact/data/exact.dart
new file mode 100644
index 0000000..11a6d2d
--- /dev/null
+++ b/tests/compiler/dart2js/impact/data/exact.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, 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.
+
+/*element: A.:static=[Object.(0)]*/
+class A {
+ method1() {}
+ method2() {}
+ method3() {}
+}
+
+/*element: B.:static=[A.(0)]*/
+class B extends A {
+ method1() {}
+ method2() {}
+ method3() {}
+}
+
+/*element: C.:static=[B.(0)]*/
+class C extends B {
+ method1() {}
+ method2() {}
+ method3() {}
+}
+
+/*element: main:static=[callOnEffectivelyFinalB(0),callOnNewB(0),callOnNewC(0)]*/
+main() {
+ callOnNewB();
+ callOnNewC();
+ callOnEffectivelyFinalB();
+ callOnEffectivelyFinalB();
+}
+
+/*element: callOnNewB:dynamic=[exact:B.method1(0)],static=[B.(0)]*/
+callOnNewB() {
+ new B().method1();
+}
+
+/*element: callOnNewC:dynamic=[exact:C.method2(0)],static=[C.(0)]*/
+callOnNewC() {
+ new C().method2();
+}
+
+/*element: callOnEffectivelyFinalB:dynamic=[exact:B.method3(0)],static=[B.(0)]*/
+callOnEffectivelyFinalB() {
+ A a = new B();
+ a.method3();
+}
diff --git a/tests/compiler/dart2js/impact/data/future_or.dart b/tests/compiler/dart2js/impact/data/future_or.dart
new file mode 100644
index 0000000..c119fbe
--- /dev/null
+++ b/tests/compiler/dart2js/impact/data/future_or.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+
+/*element: main:
+ dynamic=[runtimeType],
+ runtimeType=[unknown:FutureOr<int>],
+ static=[Future.value(1),assertIsSubtype,print(1),throwTypeError],
+ type=[inst:JSDouble,inst:JSInt,inst:JSNumber,inst:JSPositiveInt,inst:JSUInt31,inst:JSUInt32]
+*/
+@pragma('dart2js:disableFinal')
+void main() {
+ FutureOr<int> i = new Future<int>.value(0);
+ print(i.runtimeType);
+}
diff --git a/tests/compiler/dart2js/impact/data/runtime_type.dart b/tests/compiler/dart2js/impact/data/runtime_type.dart
index 32fa0a7..96fac37 100644
--- a/tests/compiler/dart2js/impact/data/runtime_type.dart
+++ b/tests/compiler/dart2js/impact/data/runtime_type.dart
@@ -5,8 +5,8 @@
/*element: Class1a.:static=[Object.(0)]*/
class Class1a<T> {
/*element: Class1a.==:
- dynamic=[<Class1a.runtimeType,Object.runtimeType,Type.==],
- runtimeType=[equals:Class1a<Class1a.T>/dynamic]
+ dynamic=[this:Class1a.runtimeType,Object.runtimeType,Type.==],
+ runtimeType=[equals:Class1a<Class1a.T>/Object]
*/
bool operator ==(other) {
return runtimeType == other.runtimeType;
@@ -16,8 +16,8 @@
/*element: Class1b.:static=[Class1a.(0)]*/
class Class1b<T> extends Class1a<T> {
/*element: Class1b.==:
- dynamic=[<Class1b.runtimeType,Object.runtimeType,Type.==],
- runtimeType=[equals:dynamic/Class1b<Class1b.T>]
+ dynamic=[this:Class1b.runtimeType,Object.runtimeType,Type.==],
+ runtimeType=[equals:Object/Class1b<Class1b.T>]
*/
bool operator ==(other) {
return other.runtimeType == runtimeType;
@@ -27,8 +27,8 @@
/*element: Class1c.:static=[Object.(0)]*/
class Class1c<T> implements Class1a<T> {
/*element: Class1c.==:
- dynamic=[<Class1c.runtimeType,Object.==,Object.runtimeType,Type.==],
- runtimeType=[equals:Class1c<Class1c.T>/dynamic],
+ dynamic=[this:Class1c.runtimeType,Object.==,Object.runtimeType,Type.==],
+ runtimeType=[equals:Class1c<Class1c.T>/Object],
type=[inst:JSNull]
*/
bool operator ==(other) {
@@ -39,8 +39,8 @@
/*element: Class1d.:static=[Object.(0)]*/
class Class1d<T> implements Class1a<T> {
/*element: Class1d.==:
- dynamic=[<Class1d.runtimeType,Object.==,Object.runtimeType,Type.==],
- runtimeType=[equals:dynamic/Class1d<Class1d.T>],
+ dynamic=[this:Class1d.runtimeType,Object.==,Object.runtimeType,Type.==],
+ runtimeType=[equals:Object/Class1d<Class1d.T>],
type=[inst:JSNull]
*/
bool operator ==(other) {
@@ -379,7 +379,7 @@
notEquals4(Class3 a, Class4 b) => a?.runtimeType != b?.runtimeType;
/*element: main:
- dynamic=[Class1a.==],
+ dynamic=[exact:Class1a.==],
static=[
Class1a.(0),
Class1b.(0),
diff --git a/tests/compiler/dart2js/impact/data/this.dart b/tests/compiler/dart2js/impact/data/this.dart
index 2579dda..73a03d1 100644
--- a/tests/compiler/dart2js/impact/data/this.dart
+++ b/tests/compiler/dart2js/impact/data/this.dart
@@ -10,12 +10,12 @@
/*element: Class.field2:type=[inst:JSNull]*/
var field2;
- /*element: Class.method1:dynamic=[<Class.method2(0)]*/
+ /*element: Class.method1:dynamic=[this:Class.method2(0)]*/
method1() {
method2();
}
- /*element: Class.method2:dynamic=[<Class.field1=,<Class.field2]*/
+ /*element: Class.method2:dynamic=[this:Class.field1=,this:Class.field2]*/
method2() {
field1 = field2;
}
@@ -31,7 +31,7 @@
/*element: Subclass.method1:*/
method1() {}
- /*element: Subclass.method2:dynamic=[<Subclass.method3(0)]*/
+ /*element: Subclass.method2:dynamic=[this:Subclass.method3(0)]*/
method2() {
method3();
}
diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart
index d1cc0b1b..e59b077 100644
--- a/tests/compiler/dart2js/impact/impact_test.dart
+++ b/tests/compiler/dart2js/impact/impact_test.dart
@@ -33,12 +33,12 @@
static const String runtimeTypeUse = 'runtimeType';
}
-class ImpactDataComputer extends DataComputer<String> {
+class ImpactDataComputer extends DataComputer<Features> {
const ImpactDataComputer();
@override
void computeMemberData(Compiler compiler, MemberEntity member,
- Map<Id, ActualData<String>> actualMap,
+ Map<Id, ActualData<Features>> actualMap,
{bool verbose: false}) {
KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
WorldImpact impact = compiler.impactCache[member];
@@ -72,10 +72,11 @@
}
}
Id id = computeEntityId(node);
- actualMap[id] = new ActualData<String>(
- id, features.getText(), computeSourceSpanFromTreeNode(node), member);
+ actualMap[id] = new ActualData<Features>(
+ id, features, computeSourceSpanFromTreeNode(node), member);
}
@override
- DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+ DataInterpreter<Features> get dataValidator =>
+ const FeaturesDataInterpreter();
}
diff --git a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
index d721dc7..aeb3108 100644
--- a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
@@ -17,11 +17,18 @@
}
runTest() async {
- CompilationResult result = await runCompiler(memorySourceFiles: {
- 'main.dart': '''
+ // Pretend this is a dart2js_native test to allow use of 'native' keyword
+ // and import of private libraries.
+ String main = 'sdk/tests/compiler/dart2js_native/main.dart';
+ Uri entryPoint = Uri.parse('memory:$main');
+
+ CompilationResult result =
+ await runCompiler(entryPoint: entryPoint, memorySourceFiles: {
+ main: '''
class A {
method1() {}
method2() {}
+ method4() {}
get getter => 42;
set setter(_) {}
}
@@ -29,6 +36,7 @@
class B {
method1() {}
method2() {}
+ method5() {}
get getter => 42;
set setter(_) {}
}
@@ -36,6 +44,7 @@
class C extends A {
method1() {}
method2() {}
+ method4() {}
get getter => 42;
set setter(_) {}
}
@@ -43,6 +52,7 @@
class D implements B {
method1() {}
method2() {}
+ method5() {}
get getter => 42;
set setter(_) {}
}
@@ -50,6 +60,7 @@
class E implements A {
method1() {}
method2() {}
+ method4() {}
get getter => 42;
set setter(_) {}
}
@@ -57,6 +68,7 @@
class F extends B {
method1() {}
method2() {}
+ method5() {}
get getter => 42;
set setter(_) {}
}
@@ -64,6 +76,7 @@
class G {
method1() {}
method2() {}
+ method4() {}
get getter => 42;
set setter(_) {}
}
@@ -73,6 +86,7 @@
class I {
method1() {}
method2() {}
+ method4() {}
get getter => 42;
set setter(_) {}
}
@@ -124,6 +138,12 @@
}
main() {
+ method1();
+ method2();
+}
+
+@pragma('dart2js:disableFinal')
+method1() {
A a = new A();
B b = new B();
a.method1();
@@ -148,14 +168,21 @@
new Class1b();
new Class2().c(0, 1, 2);
}
+
+method2() {
+ A a = new A();
+ B b = new B();
+ a.method4();
+ b.method5();
+}
'''
});
Expect.isTrue(result.isSuccess);
Compiler compiler = result.compiler;
Map<String, List<String>> expectedLiveMembersMap = <String, List<String>>{
- 'A': ['method1', 'getter'],
- 'B': ['method2', 'setter'],
+ 'A': ['method1', 'getter', 'method4'],
+ 'B': ['method2', 'setter', 'method5'],
'C': ['method1', 'getter'],
'D': ['method2', 'setter'],
'G': ['method1', 'getter'],
diff --git a/tests/compiler/dart2js/rti/emission/closure_function_type.dart b/tests/compiler/dart2js/rti/emission/closure_function_type.dart
index 56d1d56..aed5de1 100644
--- a/tests/compiler/dart2js/rti/emission/closure_function_type.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_function_type.dart
@@ -8,7 +8,7 @@
test(o) => o is Function();
main() {
- test(/*checks=[],functionType,instance*/ () {});
+ test(/*checks=[$signature],instance*/ () {});
test(
/*strong.checks=[],instance*/
diff --git a/tests/compiler/dart2js/rti/emission/closure_signature.dart b/tests/compiler/dart2js/rti/emission/closure_signature.dart
index b1250b0..aedf5f6 100644
--- a/tests/compiler/dart2js/rti/emission/closure_signature.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_signature.dart
@@ -13,7 +13,7 @@
@NoInline()
f() {
- return /*checks=[],functionType,instance*/ (int t) {};
+ return /*checks=[$signature],instance*/ (int t) {};
}
}
diff --git a/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1.dart b/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1.dart
index 3123b79..dc43c4b 100644
--- a/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1.dart
+++ b/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
main() {
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
T id<T>(T t) => t;
int Function(int) x = id;
diff --git a/tests/compiler/dart2js/rti/emission/subtype_named_args.dart b/tests/compiler/dart2js/rti/emission/subtype_named_args.dart
index 759210b..cb83d5e 100644
--- a/tests/compiler/dart2js/rti/emission/subtype_named_args.dart
+++ b/tests/compiler/dart2js/rti/emission/subtype_named_args.dart
@@ -53,50 +53,50 @@
main() {
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({D a, B b, C c, A d}) {} is classesFunc);
Expect.isTrue(
- /*checks=[],functionType,instance*/
+ /*checks=[$signature],instance*/
({A a, A b, A c, A d}) {} is classesFunc);
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({D a, A1 b, A1 c, A1 d}) {} is classesFunc);
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({D a, A2 b, A2 c, A2 d}) {} is classesFunc);
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({D a, D b, D c, D d}) {} is classesFunc);
Expect.isTrue(
- /*checks=[],functionType,instance*/
+ /*checks=[$signature],instance*/
({var a, var b, var c, var d}) {} is classesFunc);
- Expect.isTrue(/*checks=[],functionType,instance*/
+ Expect.isTrue(/*checks=[$signature],instance*/
({Object a, Object b, Object c, Object d}) {} is classesFunc);
- Expect.isTrue(/*checks=[],functionType,instance*/
+ Expect.isTrue(/*checks=[$signature],instance*/
({Map<num, num> m, List<List<A1>> l, G<A, A1, A1, A1> g}) {}
is genericsFunc);
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({Map<int, int> m, List<List<D>> l, G<D, D, D, D> g}) {} is genericsFunc);
Expect.isTrue(
- /*checks=[],functionType,instance*/
+ /*checks=[$signature],instance*/
({var m, var l, var g}) {} is genericsFunc);
Expect.isTrue(
- /*checks=[],functionType,instance*/
+ /*checks=[$signature],instance*/
({Object m, Object l, Object g}) {} is genericsFunc);
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({A x, G y, mixFunc z, var v}) {} is dynamicFunc);
Expect.isTrue(
- /*strong.checks=[],functionType,instance*/
+ /*strong.checks=[$signature],instance*/
/*omit.checks=[],instance*/
({int x, bool y, List<Map> z, classesFunc v}) {} is dynamicFunc);
@@ -106,7 +106,7 @@
{okWithClassesFunc_1 f1,
okWithGenericsFunc_1 f2,
okWithDynamicFunc_1 f3}) {} is funcFunc);
- Expect.isTrue(/*checks=[],functionType,instance*/
+ Expect.isTrue(/*checks=[$signature],instance*/
(
{okWithClassesFunc_2 f1,
okWithGenericsFunc_2 f2,
diff --git a/tests/compiler/dart2js/serialization/data/custom_types.dart b/tests/compiler/dart2js/serialization/data/custom_types.dart
new file mode 100644
index 0000000..a301473
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/data/custom_types.dart
@@ -0,0 +1,31 @@
+// 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 {
+ method() {
+ Object c = this;
+ return c;
+ }
+}
+
+main() {
+ exactInterfaceType();
+ thisInterfaceType();
+ doesNotCompleteType();
+}
+
+exactInterfaceType() {
+ Object c = new A();
+ return c;
+}
+
+thisInterfaceType() {
+ new A().method();
+}
+
+doesNotCompleteType() {
+ Object c = throw '';
+ // ignore: dead_code
+ return c;
+}
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
index aacf1c6..bc504c76 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
@@ -53,6 +53,7 @@
CallPosition.getSemanticPositionForCall(node);
sourcePositionKind = callPosition.sourcePositionKind;
break;
+ case StepKind.ACCESS:
case StepKind.NEW:
case StepKind.RETURN:
case StepKind.BREAK:
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index 7b45545..8826468 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -523,6 +523,7 @@
/// Called when [node] defines a step of the given [kind] at the given
/// [offset] when the generated JavaScript code.
void onStep(js.Node node, Offset offset, StepKind kind) {
+ if (kind == StepKind.ACCESS) return;
register(kind, node);
}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/getter_inlining.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/getter_inlining.dart
new file mode 100644
index 0000000..ea1874b
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/getter_inlining.dart
@@ -0,0 +1,16 @@
+class MyClass {
+ int fieldName;
+
+ MyClass(this.fieldName);
+
+ int get getterName => /*1:getterName(inlined)*/ fieldName;
+}
+
+@pragma('dart2js:noInline')
+confuse(x) => x;
+
+main() {
+ confuse(new MyClass(3));
+ var m = confuse(null);
+ m. /*0:main*/ getterName;
+}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
new file mode 100644
index 0000000..9b5ab60
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
@@ -0,0 +1,16 @@
+class MyClass {
+ int fieldName;
+
+ MyClass(this.fieldName);
+
+ set setterName(int v) => /*1:setterName(inlined)*/ fieldName = v;
+}
+
+@pragma('dart2js:noInline')
+confuse(x) => x;
+
+main() {
+ confuse(new MyClass(3));
+ var m = confuse(null);
+ m. /*0:main*/ setterName = 2;
+}
diff --git a/tests/compiler/dart2js/static_type/static_type_test.dart b/tests/compiler/dart2js/static_type/static_type_test.dart
index 070d0f6..1f935d8 100644
--- a/tests/compiler/dart2js/static_type/static_type_test.dart
+++ b/tests/compiler/dart2js/static_type/static_type_test.dart
@@ -8,6 +8,7 @@
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/ir/cached_static_type.dart';
+import 'package:compiler/src/ir/static_type_base.dart';
import 'package:compiler/src/kernel/element_map_impl.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
import 'package:kernel/ast.dart' as ir;
@@ -55,7 +56,9 @@
compiler.reporter,
actualMap,
new CachedStaticType(
- getTypeEnvironment(elementMap), staticTypeCache))
+ getTypeEnvironment(elementMap),
+ staticTypeCache,
+ new ThisInterfaceType.from(node.enclosingClass?.thisType)))
.run(node);
}
diff --git a/tests/compiler/dart2js/static_type/type_promotion_data/bottom.dart b/tests/compiler/dart2js/static_type/type_promotion_data/bottom.dart
new file mode 100644
index 0000000..1c94829
--- /dev/null
+++ b/tests/compiler/dart2js/static_type/type_promotion_data/bottom.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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 {}
+
+main() {
+ conditionNullElse(null);
+ conditionNullThen(null);
+}
+
+conditionNullElse(dynamic o) {
+ /*{}*/ o;
+ /*{}*/ o is A ? /*{o:[{true:A}|A]}*/ o : null;
+ /*{}*/ o;
+}
+
+conditionNullThen(dynamic o) {
+ /*{}*/ o;
+ /*{}*/ o is! A ? null : /*{o:[{true:A}|A]}*/ o;
+ /*{}*/ o;
+}
diff --git a/tests/compiler/dart2js_extra/35341_test.dart b/tests/compiler/dart2js_extra/35341_test.dart
index 027182f..80310f0 100644
--- a/tests/compiler/dart2js_extra/35341_test.dart
+++ b/tests/compiler/dart2js_extra/35341_test.dart
@@ -8,7 +8,6 @@
@pragma('dart2js:disableFinal')
void main() {
- FutureOr<int> i = 0;
- i = new Future<int>.value(0);
+ FutureOr<int> i = new Future<int>.value(0);
print(i.runtimeType);
}
diff --git a/tests/corelib_2/date_time_parse_test.dart b/tests/corelib_2/date_time_parse_test.dart
index 74cc78f..6b3d58d 100644
--- a/tests/corelib_2/date_time_parse_test.dart
+++ b/tests/corelib_2/date_time_parse_test.dart
@@ -18,9 +18,13 @@
if (supportsMicroseconds) {
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
"2012-02-27 13:27:00.123456z");
+ check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
+ "2012-02-27 13:27:00,123456z");
} else {
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
"2012-02-27 13:27:00.123z");
+ check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
+ "2012-02-27 13:27:00,123z");
}
check(new DateTime(2012, 02, 27, 13, 27), "20120227 13:27:00");
check(new DateTime(2012, 02, 27, 13, 27), "20120227T132700");
diff --git a/tests/language_2/checked_method_error_order_test.dart b/tests/language_2/checked_method_error_order_test.dart
index c5370cf..04279f8 100644
--- a/tests/language_2/checked_method_error_order_test.dart
+++ b/tests/language_2/checked_method_error_order_test.dart
@@ -22,7 +22,8 @@
if (e is TypeError) {
var m = e.message.toString();
return m.contains("is not a subtype of type 'int'") ||
- m.contains("is not a subtype of expected type 'int'");
+ m.contains(
+ "Expected a value of type 'int', but got one of type 'String'");
}
return false;
});
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index fb08b21..fa02ab6 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -93,7 +93,6 @@
regress_29784_test/02: MissingCompileTimeError # Issue 29784
regress_30339_test: CompileTimeError
regress_33479_test/01: Crash # Issue #33479
-set_literals/*: Skip
setter3_test/01: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837
setter3_test/02: CompileTimeError # Invalid test, see https://github.com/dart-lang/sdk/issues/33837
super_bound_closure_test/none: CompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index c38a4b3..afc42ff 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -60,7 +60,6 @@
partial_tearoff_instantiation_test/07: Pass # for the wrong reason.
partial_tearoff_instantiation_test/08: Pass # for the wrong reason.
private_method_tearoff_test: RuntimeError
-set_literals/*: Skip
type_constants_test/none: RuntimeError # Issue 35052
vm/*: SkipByDesign # Tests for the VM.
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 8047938..03b555e 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -193,15 +193,6 @@
implicit_creation/implicit_const_not_default_values_test/e7: MissingCompileTimeError
implicit_creation/implicit_const_not_default_values_test/e8: MissingCompileTimeError
mixin_method_override_test/G4: Crash # Assertion error: mixin_full_resolution.dart': 'src.typeParameters.length == dst.typeParameters.length': is not true.
-set_literals/invalid_set_literal_test/08: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/09: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/10: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/29: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/30: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/31: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/32: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/33: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/34: MissingCompileTimeError # Requires constant evaluation
vm/regress_33469_test/01: MissingCompileTimeError
vm/regress_33469_test/02: MissingCompileTimeError
vm/regress_33469_test/03: MissingCompileTimeError
@@ -236,6 +227,16 @@
mixin_declaration/mixin_declaration_superinvocation_application_test/08: MissingCompileTimeError
mixin_method_override_test/G5: Crash # Issue 34354
regress_22976_test/*: CompileTimeError # Issue 31935
+set_literals/invalid_set_literal_test/08: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/09: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/10: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/23: MissingCompileTimeError # Exact types
+set_literals/invalid_set_literal_test/29: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/30: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/31: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/32: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/33: MissingCompileTimeError # Requires constant evaluation
+set_literals/invalid_set_literal_test/34: MissingCompileTimeError # Requires constant evaluation
syntax_test/28: MissingCompileTimeError # Issue 29763 - low priority
syntax_test/29: MissingCompileTimeError # Issue 29763 - low priority
syntax_test/30: MissingCompileTimeError # Issue 29763 - low priority
diff --git a/tests/language_2/vm/bitnot_int_test.dart b/tests/language_2/vm/bitnot_int_test.dart
new file mode 100644
index 0000000..f52d66b
--- /dev/null
+++ b/tests/language_2/vm/bitnot_int_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10
+
+import "package:expect/expect.dart";
+
+// Tests for long bit-not under 64-bit arithmetic wrap-around semantics.
+
+final int maxInt32 = 2147483647;
+final int minInt32 = -2147483648;
+final int maxInt64 = 0x7fffffffffffffff;
+final int minInt64 = 0x8000000000000000;
+
+int bitnot(int x) {
+ return ~x;
+}
+
+doConstant() {
+ Expect.equals(0, bitnot(-1));
+ Expect.equals(-1, bitnot(0));
+ Expect.equals(-2, bitnot(1));
+
+ Expect.equals(minInt32, bitnot(maxInt32));
+ Expect.equals(maxInt32, bitnot(minInt32));
+ Expect.equals(minInt64, bitnot(maxInt64));
+ Expect.equals(maxInt64, bitnot(minInt64)); // sic!
+}
+
+doVar() {
+ int d = 0;
+ for (int i = -88; i < 10; i++) {
+ d += bitnot(i);
+ }
+ Expect.equals(3773, d);
+}
+
+main() {
+ // Repeat tests to enter JIT (when applicable).
+ for (int i = 0; i < 20; i++) {
+ doConstant();
+ doVar();
+ }
+}
diff --git a/tests/language_2/vm/modtruncdiv_int_test.dart b/tests/language_2/vm/modtruncdiv_int_test.dart
index 7a84d1a..8314628 100644
--- a/tests/language_2/vm/modtruncdiv_int_test.dart
+++ b/tests/language_2/vm/modtruncdiv_int_test.dart
@@ -79,6 +79,17 @@
Expect.equals(1, mod(maxInt32 + 1, maxInt32));
Expect.equals(maxInt32 - 2, mod(minInt32 - 1, maxInt32));
Expect.equals(0, mod(minInt32 + 1, maxInt32));
+
+ Expect.equals(15, mod(-1, 16));
+ Expect.equals(15, mod(-17, 16));
+ Expect.equals(15, mod(-1, -16));
+ Expect.equals(15, mod(-17, -16));
+ Expect.equals(100, mod(100, 1 << 32));
+ Expect.equals(100, mod(100, -(1 << 32)));
+ Expect.equals((1 << 32) - 1, mod((1 << 35) - 1, 1 << 32));
+ Expect.equals((1 << 32) - 1, mod((1 << 35) - 1, -(1 << 32)));
+ Expect.equals(maxInt64, mod(-1, 1 << 63));
+ Expect.equals(0, mod(minInt64, 1 << 63));
}
doTruncDivConstants() {
diff --git a/tests/lib_2/isolate/kill_regexp_test.dart b/tests/lib_2/isolate/kill_regexp_test.dart
deleted file mode 100644
index 33cb8eb..0000000
--- a/tests/lib_2/isolate/kill_regexp_test.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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.
-
-// VMOptions=--intrinsify
-// VMOptions=--no_intrinsify
-
-import "dart:isolate";
-import "dart:async";
-import "package:expect/expect.dart";
-
-isomain1(replyPort) {
- final regexp = new RegExp('[ab]c');
- while (true) {
- Expect.equals(4, regexp.allMatches("acbcacbc").length);
- }
-}
-
-void main() {
- for (int i = 0; i < 20; ++i) {
- ReceivePort reply = new ReceivePort();
- Isolate.spawn(isomain1, reply.sendPort).then((Isolate isolate) {
- new Timer(new Duration(milliseconds: 50), () {
- print('killing isolate $i');
- isolate.kill(priority: Isolate.immediate);
- });
- });
- reply.close();
- }
-}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index f6628fa..dc0745a 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -131,6 +131,9 @@
[ $compiler != dartdevc && $checked && !$strong ]
async/future_or_only_in_async_test/00: MissingCompileTimeError
+[ $compiler == dartk && $system == macos && $hot_reload && ($arch == simdbc || $arch == simdbc64) ]
+isolate/unresolved_ports_test: Pass, RuntimeError # Issue 35410
+
[ $compiler == none && $mode == product ]
mirrors/library_enumeration_deferred_loading_test: RuntimeError, OK # Deferred loaded eagerly
mirrors/library_import_deferred_loading_test: RuntimeError, OK # Deferred loaded eagerly
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index b5f6efc..ca19533 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -81,7 +81,6 @@
[ $compiler == dartkb && $strong ]
convert/streamed_conversion_json_utf8_decode_test: Pass, Timeout # Please triage.
isolate/isolate_complex_messages_test: Pass, Crash # runtime/vm/object.cc: 17395: error: expected: type_arguments.IsNull() || type_arguments.IsCanonical()
-isolate/kill_regexp_test: Pass, Crash # Issue 35590 - isolate.cc: 2863: error: expected: sticky_error_ == Error::null()
isolate/mandel_isolate_test: Pass, Timeout # Please triage.
isolate/spawn_uri_exported_main_test: Pass, RuntimeError # Please triage: Expect.fail('Isolate was not spawned successfully.')
mirrors/invocation_fuzz_test/emptyarray: Skip # Times out, issue 32232
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index cd92c8e..fcd29ba 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -73,16 +73,26 @@
[ $arch == simdbc64 && $mode == debug && $checked ]
io/web_socket_test: Pass, RuntimeError # Issue 26814.
+[ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
+io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
+
[ $compiler != dart2analyzer && $system == windows ]
io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
+[ $mode == release && $runtime == vm && $system == linux && ($arch == simdbc64 || $arch == x64) ]
+io/http_bind_test: Pass, Timeout # Issue 35192
+
[ $mode == release && $runtime == vm && $system == macos ]
+io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout.
io/named_pipe_script_test: Pass, RuntimeError # Issue 28737
[ $mode == release && $runtime == vm && $system == windows ]
io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout.
io/regress_7191_test: Pass, Timeout # Issue 28374: timeout.
+[ $runtime == dart_precompiled && $system == linux && ($arch == simarm || $arch == simarm64) ]
+io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
+
[ $runtime == vm && !$checked && !$strong ]
io/file_constructor_test: RuntimeError
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 14748a9..c11b0c2 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -26,4 +26,5 @@
Force build while trybots are broken, to check builders for brokenness.
Analyzer branch commits:
-Force build on new analyzer-branch linux build with new workflow
\ No newline at end of file
+Force build on new analyzer-branch linux build with new workflow
+Trigger bots
diff --git a/tools/VERSION b/tools/VERSION
index 604b271..9e72048 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 1
PATCH 1
-PRERELEASE 1
+PRERELEASE 2
PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/bin/generate.dart b/tools/apps/update_homebrew/bin/generate.dart
index e91933f..ea29e06 100644
--- a/tools/apps/update_homebrew/bin/generate.dart
+++ b/tools/apps/update_homebrew/bin/generate.dart
@@ -9,14 +9,14 @@
import 'package:stack_trace/stack_trace.dart';
import 'package:update_homebrew/update_homebrew.dart';
-main(List<String> args) async {
- final parser = new ArgParser()
+void main(List<String> args) async {
+ final parser = ArgParser()
..addOption('revision', abbr: 'r')
- ..addOption('channel', abbr: 'c', allowed: ['dev', 'stable']);
+ ..addOption('channel', abbr: 'c', allowed: supportedChannels);
final options = parser.parse(args);
- final revision = options['revision'];
- final channel = options['channel'];
+ final revision = options['revision'] as String;
+ final channel = options['channel'] as String;
if ([revision, channel].contains(null)) {
print(
"Usage: generate.dart -r revision -c channel <path_to_existing_dart.rb>");
@@ -31,7 +31,7 @@
}
final existingDartRb = options.rest.single;
- var file = new File(existingDartRb);
+ var file = File(existingDartRb);
if (!file.existsSync()) {
print("Expected '$existingDartRb' to exist.");
diff --git a/tools/apps/update_homebrew/bin/update_homebrew.dart b/tools/apps/update_homebrew/bin/update_homebrew.dart
index e61bbdd..691f0a5 100644
--- a/tools/apps/update_homebrew/bin/update_homebrew.dart
+++ b/tools/apps/update_homebrew/bin/update_homebrew.dart
@@ -8,24 +8,24 @@
import 'package:stack_trace/stack_trace.dart';
import 'package:update_homebrew/update_homebrew.dart';
-main(List<String> args) async {
- final parser = new ArgParser()
+void main(List<String> args) async {
+ final parser = ArgParser()
..addOption('revision', abbr: 'r')
- ..addOption('channel', abbr: 'c', allowed: ['dev', 'stable'])
+ ..addOption('channel', abbr: 'c', allowed: supportedChannels)
..addOption('key', abbr: 'k');
final options = parser.parse(args);
- final revision = options['revision'];
- final channel = options['channel'];
+ final revision = options['revision'] as String;
+ final channel = options['channel'] as String;
if ([revision, channel].contains(null)) {
print("Usage: update_homebrew.dart -r revision -c channel [-k ssh_key]\n"
- " ssh_key should allow pushes to ${GITHUB_REPO} on github");
+ " ssh_key should allow pushes to $githubRepo on github");
exitCode = 1;
return;
}
Map<String, String> gitEnvironment;
- final key = options['key'];
+ final key = options['key'] as String;
if (key != null) {
final sshWrapper = Platform.script.resolve('ssh_with_key').toFilePath();
gitEnvironment = {'GIT_SSH': sshWrapper, 'SSH_KEY_PATH': key};
@@ -37,8 +37,8 @@
try {
var repository = tempDir.path;
- await runGit(['clone', 'git@github.com:${GITHUB_REPO}.git', '.'],
- repository, gitEnvironment);
+ await runGit(['clone', 'git@github.com:$githubRepo.git', '.'], repository,
+ gitEnvironment);
await writeHomebrewInfo(channel, revision, repository);
await runGit([
'commit',
diff --git a/tools/apps/update_homebrew/lib/src/impl.dart b/tools/apps/update_homebrew/lib/src/impl.dart
new file mode 100644
index 0000000..2c17713
--- /dev/null
+++ b/tools/apps/update_homebrew/lib/src/impl.dart
@@ -0,0 +1,133 @@
+part of '../update_homebrew.dart';
+
+const _files = {
+ 'dev': [_x64File, _ia32File],
+ 'stable': [_x64File, _ia32File]
+};
+
+const _urlBase = 'https://storage.googleapis.com/dart-archive/channels';
+const _x64File = 'sdk/dartsdk-macos-x64-release.zip';
+const _ia32File = 'sdk/dartsdk-macos-ia32-release.zip';
+
+Future<String> _getHash256(
+ String channel, String revision, String download) async {
+ var client = http.Client();
+ try {
+ var api = storage.StorageApi(client);
+ var media = await api.objects.get('dart-archive',
+ 'channels/$channel/release/$revision/$download.sha256sum',
+ downloadOptions: DownloadOptions.FullMedia) as Media;
+
+ var hashLine = await ascii.decodeStream(media.stream);
+ return RegExp('[0-9a-fA-F]*').stringMatch(hashLine);
+ } finally {
+ client.close();
+ }
+}
+
+Future<String> _getVersion(String channel, String revision) async {
+ var client = http.Client();
+ try {
+ var api = storage.StorageApi(client);
+
+ var media = await api.objects.get(
+ 'dart-archive', 'channels/$channel/release/$revision/VERSION',
+ downloadOptions: DownloadOptions.FullMedia) as Media;
+
+ var versionObject =
+ await json.fuse(ascii).decoder.bind(media.stream).first as Map;
+ return versionObject['version'] as String;
+ } finally {
+ client.close();
+ }
+}
+
+Future<Map<String, String>> _getCurrentRevisions(String repository) async {
+ var revisions = <String, String>{};
+ var lines = await (File(p.join(repository, dartRbFileName))).readAsLines();
+
+ for (var channel in supportedChannels) {
+ /// This RegExp between release/ and /sdk matches
+ /// * 1 digit followed by
+ /// * Any number of letters, numbers, dashes and dots
+ /// This covers both numeric- and version-formatted revisions
+ ///
+ /// Note: all of the regexp escape slashes `\` are double-escaped within the
+ /// Dart string
+ final regExp = RegExp('channels/$channel/release/(\\d[\\w\\d\\-\\.]*)/sdk');
+
+ revisions[channel] =
+ regExp.firstMatch(lines.firstWhere(regExp.hasMatch)).group(1);
+ }
+ return revisions;
+}
+
+Future<Map<String, Map>> _getHashes(Map<String, String> revisions) async {
+ var hashes = <String, Map>{};
+ for (var channel in supportedChannels) {
+ hashes[channel] = {};
+ for (var file in _files[channel]) {
+ var hash = await _getHash256(channel, revisions[channel], file);
+ hashes[channel][file] = hash;
+ }
+ }
+ return hashes;
+}
+
+String _createDartFormula(
+ Map revisions, Map hashes, String devVersion, String stableVersion) =>
+ '''
+class Dart < Formula
+ desc "The Dart SDK"
+ homepage "https://www.dartlang.org/"
+
+ version "$stableVersion"
+ if Hardware::CPU.is_64_bit?
+ url "$_urlBase/stable/release/${revisions['stable']}/$_x64File"
+ sha256 "${hashes['stable'][_x64File]}"
+ else
+ url "$_urlBase/stable/release/${revisions['stable']}/$_ia32File"
+ sha256 "${hashes['stable'][_ia32File]}"
+ end
+
+ devel do
+ version "$devVersion"
+ if Hardware::CPU.is_64_bit?
+ url "$_urlBase/dev/release/${revisions['dev']}/$_x64File"
+ sha256 "${hashes['dev'][_x64File]}"
+ else
+ url "$_urlBase/dev/release/${revisions['dev']}/$_ia32File"
+ sha256 "${hashes['dev'][_ia32File]}"
+ end
+ end
+
+ def install
+ libexec.install Dir["*"]
+ bin.install_symlink "#{libexec}/bin/dart"
+ bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]
+ end
+
+ def shim_script(target)
+ <<~EOS
+ #!/usr/bin/env bash
+ exec "#{prefix}/#{target}" "\$@"
+ EOS
+ end
+
+ def caveats; <<~EOS
+ Please note the path to the Dart SDK:
+ #{opt_libexec}
+ EOS
+ end
+
+ test do
+ (testpath/"sample.dart").write <<~EOS
+ void main() {
+ print(r"test message");
+ }
+ EOS
+
+ assert_equal "test message\\n", shell_output("#{bin}/dart sample.dart")
+ end
+end
+''';
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 890a127..c2018d7 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -7,166 +7,34 @@
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as p;
-const GITHUB_REPO = 'dart-lang/homebrew-dart';
+part 'src/impl.dart';
-const CHANNELS = const ['dev', 'stable'];
-
-const FILES = const {
- 'dev': const [x64File, ia32File],
- 'stable': const [x64File, ia32File]
-};
-
-const urlBase = 'https://storage.googleapis.com/dart-archive/channels';
-const x64File = 'sdk/dartsdk-macos-x64-release.zip';
-const ia32File = 'sdk/dartsdk-macos-ia32-release.zip';
+const githubRepo = 'dart-lang/homebrew-dart';
const dartRbFileName = 'dart.rb';
-Future<String> getHash256(
- String channel, String revision, String download) async {
- var client = new http.Client();
- try {
- var api = new storage.StorageApi(client);
- var media = await api.objects.get('dart-archive',
- 'channels/$channel/release/$revision/$download.sha256sum',
- downloadOptions: DownloadOptions.FullMedia);
+Iterable<String> get supportedChannels => _files.keys;
- var hashLine = await ascii.decodeStream(media.stream);
- return new RegExp('[0-9a-fA-F]*').stringMatch(hashLine);
- } finally {
- client.close();
- }
-}
-
-Future<String> getVersion(String channel, String revision) async {
- var client = new http.Client();
- try {
- var api = new storage.StorageApi(client);
-
- var media = await api.objects.get(
- 'dart-archive', 'channels/$channel/release/$revision/VERSION',
- downloadOptions: DownloadOptions.FullMedia);
-
- var versionObject =
- await json.fuse(ascii).decoder.bind(media.stream).first as Map;
- return versionObject['version'];
- } finally {
- client.close();
- }
-}
-
-Future<Map> getCurrentRevisions(String repository) async {
- var revisions = <String, String>{};
- var lines =
- await (new File(p.join(repository, dartRbFileName))).readAsLines();
-
- for (var channel in CHANNELS) {
- /// This RegExp between release/ and /sdk matches
- /// * 1 digit followed by
- /// * Any number of letters, numbers, dashes and dots
- /// This covers both numeric- and version-formatted revisions
- ///
- /// Note: all of the regexp escape slashes `\` are double-escaped within the
- /// Dart string
- final regExp =
- new RegExp('channels/$channel/release/(\\d[\\w\\d\\-\\.]*)/sdk');
-
- revisions[channel] =
- regExp.firstMatch(lines.firstWhere(regExp.hasMatch)).group(1);
- }
- return revisions;
-}
-
-Future<Map> getHashes(Map revisions) async {
- var hashes = <String, Map>{};
- for (var channel in CHANNELS) {
- hashes[channel] = {};
- for (var file in FILES[channel]) {
- var hash = await getHash256(channel, revisions[channel], file);
- hashes[channel][file] = hash;
- }
- }
- return hashes;
-}
-
-Future writeHomebrewInfo(
+Future<void> writeHomebrewInfo(
String channel, String revision, String repository) async {
- var revisions = await getCurrentRevisions(repository);
+ var revisions = await _getCurrentRevisions(repository);
if (revisions[channel] == revision) {
print("Channel $channel is already at revision $revision in homebrew.");
exit(0);
}
revisions[channel] = revision;
- var hashes = await getHashes(revisions);
- var devVersion = await getVersion('dev', revisions['dev']);
+ var hashes = await _getHashes(revisions);
+ var devVersion = await _getVersion('dev', revisions['dev']);
- var stableVersion = await getVersion('stable', revisions['stable']);
+ var stableVersion = await _getVersion('stable', revisions['stable']);
- await new File(p.join(repository, dartRbFileName)).writeAsString(
- createDartFormula(revisions, hashes, devVersion, stableVersion),
+ await File(p.join(repository, dartRbFileName)).writeAsString(
+ _createDartFormula(revisions, hashes, devVersion, stableVersion),
flush: true);
}
-String createDartFormula(
- Map revisions, Map hashes, String devVersion, String stableVersion) =>
- '''
-class Dart < Formula
- desc "The Dart SDK"
- homepage "https://www.dartlang.org/"
-
- version "$stableVersion"
- if MacOS.prefer_64_bit?
- url "$urlBase/stable/release/${revisions['stable']}/$x64File"
- sha256 "${hashes['stable'][x64File]}"
- else
- url "$urlBase/stable/release/${revisions['stable']}/$ia32File"
- sha256 "${hashes['stable'][ia32File]}"
- end
-
- devel do
- version "$devVersion"
- if MacOS.prefer_64_bit?
- url "$urlBase/dev/release/${revisions['dev']}/$x64File"
- sha256 "${hashes['dev'][x64File]}"
- else
- url "$urlBase/dev/release/${revisions['dev']}/$ia32File"
- sha256 "${hashes['dev'][ia32File]}"
- end
- end
-
- def install
- libexec.install Dir["*"]
- bin.install_symlink "#{libexec}/bin/dart"
- bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]
- end
-
- def shim_script(target)
- <<~EOS
- #!/usr/bin/env bash
- exec "#{prefix}/#{target}" "\$@"
- EOS
- end
-
- def caveats; <<~EOS
- Please note the path to the Dart SDK:
- #{opt_libexec}
- EOS
- end
-
- test do
- (testpath/"sample.dart").write <<~EOS
- void main() {
- print(r"test message");
- }
- EOS
-
- assert_equal "test message\\n", shell_output("#{bin}/dart sample.dart")
- end
-end
-''';
-
-Future runGit(List<String> args, String repository,
+Future<void> runGit(List<String> args, String repository,
Map<String, String> gitEnvironment) async {
print("git ${args.join(' ')}");
diff --git a/tools/apps/update_homebrew/pubspec.yaml b/tools/apps/update_homebrew/pubspec.yaml
index 7e342b6..9089614 100644
--- a/tools/apps/update_homebrew/pubspec.yaml
+++ b/tools/apps/update_homebrew/pubspec.yaml
@@ -1,5 +1,9 @@
name: update_homebrew
-version: 0.1.0
+
+publish_to: none
+environment:
+ sdk: '>=2.0.0 <3.0.0'
+
dependencies:
_discoveryapis_commons: ^0.1.3+1
args: ^1.5.0
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 8a731d5..a617489 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -117,6 +117,7 @@
"out/DebugSIMDBC64/",
"out/DebugX64/",
"out/ProductX64/",
+ "out/ReleaseAndroidARM/",
"out/ReleaseIA32/",
"out/ReleaseSIMARM/",
"out/ReleaseSIMARM64/",
@@ -134,6 +135,7 @@
"samples/",
"samples-dev/",
"tools/",
+ "third_party/android_tools/sdk/platform-tools/adb",
"third_party/gsutil/",
"third_party/pkg/",
"third_party/pkg_tested/",
@@ -176,7 +178,7 @@
"runtime": "vm",
"timeout": 240,
"use-sdk": true
- }},
+ }},
"unittest-asserts-(release|debug)-(linux|mac|win)": {
"options": {
"compiler": "dartk",
@@ -184,15 +186,15 @@
"runtime": "vm",
"timeout": 240,
"use-sdk": true
- }},
+ }},
"unittest-asserts-no-sdk-(linux|mac|win)": {
- "options": {
- "compiler": "dartk",
- "enable-asserts": true,
- "mode": "release",
- "runtime": "vm",
- "timeout": 240
- }},
+ "options": {
+ "compiler": "dartk",
+ "enable-asserts": true,
+ "mode": "release",
+ "runtime": "vm",
+ "timeout": 240
+ }},
"unittest-analyzer_use_fasta-linux": {
"options": {
"compiler": "none",
@@ -201,76 +203,47 @@
"use-sdk": true,
"vm-options": ["-DuseFastaParser=true"],
"builder-tag": "analyzer_use_fasta"
- }},
+ }},
"dartk-asan-linux-release-(ia32|x64)": {
"options": {
"builder-tag": "asan",
"timeout": 240
- }},
+ }},
"dart2js-(linux|mac|win)-chrome": {
"options": {
"use-sdk": true
- }},
+ }},
"dart2js-(linux|win)-firefox": {
"options": {
"use-sdk": true
- }},
+ }},
"dart2js-win-(ie11|edge)": {
"options": {
"use-sdk": true
- }},
+ }},
"dart2js-mac-safari": {
"options": {
"use-sdk": true
- }},
- "dart2js-faststartup-(linux|mac|win)-chrome": {
- "options": {
- "fast-startup": true,
- "use-sdk": true
- }},
- "dart2js-faststartup-(linux|win)-firefox": {
- "options": {
- "fast-startup": true,
- "use-sdk": true
- }},
- "dart2js-faststartup-win-(ie11|edge)": {
- "options": {
- "fast-startup": true,
- "use-sdk": true
- }},
- "dart2js-faststartup-mac-safari": {
- "options": {
- "fast-startup": true,
- "use-sdk": true
- }},
+ }},
"dart2js-minified-csp-linux-chrome": {
"options": {
"minified": true,
"csp": true,
"use-sdk": true
- }},
- "dart2js-minified-faststartup-csp-linux-chrome": {
- "options": {
- "minified": true,
- "csp": true,
- "fast-startup": true,
- "use-sdk": true
- }},
+ }},
"dart2js-minified-linux-d8": {
"options": {
"minified": true,
"use-sdk": true
- }},
- "dart2js-minified-faststartup-linux-d8": {
- "options": {
- "minified": true,
- "fast-startup": true,
- "use-sdk": true
- }},
+ }},
"dart2js-hostasserts-linux-ia32-d8": {
"options": {
"host-checked": true
- }},
+ }},
+ "dartkp-android-release-arm": {
+ "options": {
+ "use-blobs": true
+ }},
"dartkp-linux-release-(simarm|simarm64)": {
"options": {
"use-blobs": true
@@ -293,10 +266,15 @@
"options": {
"vm-options": ["--no-enable-malloc-hooks"]
}},
- "dartkp-bare-linux-release-x64": {
+ "dartkp-bare-linux-(debug|release)-x64": {
"options": {
"vm-options": ["--no-enable-malloc-hooks", "--use-bare-instructions"]
}},
+ "dartkp-bare-linux-(debug|release)-(simarm|simarm64)": {
+ "options": {
+ "vm-options": ["--no-enable-malloc-hooks", "--use-bare-instructions"],
+ "use-blobs": true
+ }},
"dartk-(linux|mac)-(debug|release)-(ia32|x64)": { },
"dartk-checked-linux-release-x64": {
"options": {
@@ -310,49 +288,49 @@
"options": {
"builder-tag": "optimization_counter_threshold",
"vm-options": ["--optimization-counter-threshold=5"]
- }},
+ }},
"dartk-reload-linux-(debug|release)-x64": {
"options": {
"hot-reload": true
- }},
+ }},
"dartk-reload-mac-(debug|release)-simdbc64": {
"options": {
"hot-reload": true
- }},
+ }},
"dartk-reload-rollback-linux-(debug|release)-x64": {
"options": {
"hot-reload-rollback": true
- }},
+ }},
"app_jitk-linux-(debug|product|release)-x64": { },
"dartkb-interpret-linux-(debug|release)-x64": {
"options": {
"vm-options": ["--enable_interpreter", "--compilation-counter-threshold=-1"]
- }},
+ }},
"dartkb-mixed-linux-(debug|release)-x64": {
"options": {
"vm-options": ["--enable_interpreter"]
- }},
+ }},
"dartkb-compile-linux-(debug|release)-x64": {
"options": {
"vm-options": ["--use_bytecode_compiler"]
- }},
+ }},
"(dartdevc|dartdevk)-checked-(linux|mac|win)-release-chrome": {
"options": {
"checked": true,
"use-sdk": true
- }},
+ }},
"fasta-(linux|mac|win)": { },
"analyzer-(linux|mac|win)": {
"options": {
"compiler": "dart2analyzer",
"use-sdk": true
- }},
+ }},
"analyzer-asserts-(linux|mac|win)": {
"options": {
"compiler": "dart2analyzer",
"enable-asserts": true,
"use-sdk": true
- }}
+ }}
},
"builder_configurations": [
{
@@ -487,6 +465,33 @@
},
{
"builders": [
+ "vm-kernel-precomp-android-release-arm"
+ ],
+ "meta": {
+ "description": "This configuration is used by the vm precomp builders on Android."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": [
+ "runtime_kernel",
+ "dart_precompiled_runtime",
+ "--os=android"
+ ]
+ },
+ {
+ "name": "vm tests",
+ "arguments": [
+ "-ndartkp-android-${mode}-${arch}"
+ ],
+ "fileset": "vm-kernel",
+ "shards": 15
+ }
+ ]
+ },
+ {
+ "builders": [
"vm-kernel-precomp-linux-debug-x64",
"vm-kernel-precomp-linux-product-x64",
"vm-kernel-precomp-linux-release-simarm",
@@ -520,7 +525,9 @@
},
{
"builders": [
- "vm-kernel-precomp-bare-linux-release-x64"
+ "vm-kernel-precomp-bare-linux-release-x64",
+ "vm-kernel-precomp-bare-linux-release-simarm",
+ "vm-kernel-precomp-bare-linux-release-simarm64"
],
"meta": {
"description": "This configuration is used by the vm kernel precomp builders using bare instructions."
@@ -1093,78 +1100,6 @@
]
},
{
- "builders": [
- "dart2js-strong-faststartup-linux-x64-chrome",
- "dart2js-strong-faststartup-linux-x64-firefox",
- "dart2js-strong-faststartup-mac-x64-chrome",
- "dart2js-strong-faststartup-mac-x64-safari",
- "dart2js-strong-faststartup-win-x64-chrome",
- "dart2js-strong-faststartup-win-x64-edge",
- "dart2js-strong-faststartup-win-x64-firefox",
- "dart2js-strong-faststartup-win-x64-ie11"
- ],
- "meta": {
- "description": "dart2js browser tests using the fast-startup emitter for Dart 2.0."
- },
- "steps": [
- {
- "name": "build dart",
- "script": "tools/build.py",
- "arguments": ["create_sdk"]
- },
- {
- "name": "dart2js fast-startup tests",
- "arguments": [
- "-ndart2js-faststartup-${system}-${runtime}",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "--exclude_suite=observatory_ui"
- ],
- "shards": 6,
- "fileset": "dart2js"
- },
- {
- "name": "dart2js fast-startup co19_2 tests",
- "arguments": [
- "-ndart2js-faststartup-${system}-${runtime}",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "co19_2"
- ],
- "shards": 6,
- "fileset": "dart2js"
- },
- {
- "name": "dart2js fast-startup package tests",
- "arguments": [
- "-ndart2js-faststartup-${system}-${runtime}",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "pkg"
- ]
- },
- {
- "name": "dart2js fast-startup observatory-ui tests",
- "arguments": [
- "-ndart2js-faststartup-${system}-${runtime}",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "observatory_ui"
- ]
- },
- {
- "name": "dart2js fast-startup extra tests",
- "arguments": [
- "-ndart2js-faststartup-${system}-${runtime}",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "dart2js_extra",
- "dart2js_native"
- ]
- }
- ]
- },
- {
"builders": ["dart2js-minified-strong-linux-x64-d8"],
"meta": {
"description": "dart2js tests for Dart 2.0."
@@ -1186,16 +1121,6 @@
"fileset": "dart2js"
},
{
- "name": "dart2js fast-startup tests",
- "arguments": [
- "-ndart2js-minified-faststartup-linux-d8",
- "--dart2js-batch",
- "--exclude_suite=observatory_ui"
- ],
- "shards": 6,
- "fileset": "dart2js"
- },
- {
"name": "dart2js package tests",
"arguments": [
"-ndart2js-minified-linux-d8",
@@ -1219,31 +1144,6 @@
"dart2js_extra",
"dart2js_native"
]
- },
- {
- "name": "dart2js fast-startup package tests",
- "arguments": [
- "-ndart2js-minified-faststartup-linux-d8",
- "--dart2js-batch",
- "pkg"
- ]
- },
- {
- "name": "dart2js fast-startup observatory-ui tests",
- "arguments": [
- "-ndart2js-minified-faststartup-linux-d8",
- "--dart2js-batch",
- "observatory_ui"
- ]
- },
- {
- "name": "dart2js fast-startup extra tests",
- "arguments": [
- "-ndart2js-minified-faststartup-linux-d8",
- "--dart2js-batch",
- "dart2js_extra",
- "dart2js_native"
- ]
}
]
},
@@ -1270,17 +1170,6 @@
"fileset": "dart2js"
},
{
- "name": "dart2js fast-startup tests",
- "arguments": [
- "-ndart2js-minified-faststartup-csp-linux-chrome",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "--exclude_suite=observatory_ui"
- ],
- "shards": 4,
- "fileset": "dart2js"
- },
- {
"name": "dart2js package tests",
"arguments": [
"-ndart2js-minified-csp-linux-chrome",
@@ -1306,34 +1195,6 @@
"dart2js_extra",
"dart2js_native"
]
- },
- {
- "name": "dart2js fast-startup package tests",
- "arguments": [
- "-ndart2js-minified-faststartup-csp-linux-chrome",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "pkg"
- ]
- },
- {
- "name": "dart2js fast-startup observatory-ui tests",
- "arguments": [
- "-ndart2js-minified-faststartup-csp-linux-chrome",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "observatory_ui"
- ]
- },
- {
- "name": "dart2js fast-startup extra tests",
- "arguments": [
- "-ndart2js-minified-faststartup-csp-linux-chrome",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "dart2js_extra",
- "dart2js_native"
- ]
}
]
},
diff --git a/tools/bots/update_flakiness.dart b/tools/bots/update_flakiness.dart
index c791b94..514592b 100755
--- a/tools/bots/update_flakiness.dart
+++ b/tools/bots/update_flakiness.dart
@@ -57,14 +57,7 @@
testData["current"] = result["result"];
testData["current_counter"] = 1;
}
- // Remove this code once all files are updated
- const occurrencesMisspelled = "occurences";
- var occurrences = testData[occurrencesMisspelled];
- if (occurrences != null) {
- testData["occurrences"] = occurrences;
- testData.remove(occurrencesMisspelled);
- }
- occurrences = testData.putIfAbsent("occurrences", () => <String, dynamic>{});
+ var occurrences = testData.putIfAbsent("occurrences", () => <String, dynamic>{});
occurrences.putIfAbsent(result["result"], () => 0);
occurrences[result["result"]]++;
}
@@ -79,6 +72,9 @@
for (final key in keys) {
final testData = data[key];
if (testData["outcomes"].length < 2) continue;
+ // Remove this code once all files are updated
+ const occurrencesMisspelled = "occurences";
+ if (testData.containsKey(occurrencesMisspelled)) continue;
// Forgive tests that have become deterministic again. If they flake less
// than once in a 100 (p<1%), then if they flake again, the probability of
// them getting past 5 runs of deflaking is 1%^5 = 0.00000001%.
diff --git a/tools/build.py b/tools/build.py
index a4ccf5e..237c486 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -16,6 +16,10 @@
HOST_CPUS = utils.GuessCpus()
SCRIPT_DIR = os.path.dirname(sys.argv[0])
DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
+AVAILABLE_ARCHS = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
+ 'simarmv5te', 'armv5te', 'simarm64', 'arm64',
+ 'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']
+
usage = """\
usage: %%prog [options] [targets]
@@ -28,8 +32,7 @@
result = optparse.OptionParser(usage=usage)
result.add_option("-a", "--arch",
help='Target architectures (comma-separated).',
- metavar='[all,ia32,x64,simarm,arm,simarmv6,armv6,simarmv5te,armv5te,'
- 'simarm64,arm64,simdbc,armsimdbc]',
+ metavar='[all,' + ','.join(AVAILABLE_ARCHS) + ']',
default=utils.GuessArchitecture())
result.add_option("-b", "--bytecode",
help='Build with the kernel bytecode interpreter. DEPRECATED.',
@@ -82,10 +85,7 @@
print "Unknown mode %s" % mode
return False
for arch in options.arch:
- archs = ['ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6',
- 'simarmv5te', 'armv5te', 'simarm64', 'arm64',
- 'simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']
- if not arch in archs:
+ if not arch in AVAILABLE_ARCHS:
print "Unknown arch %s" % arch
return False
options.os = [ProcessOsOption(os_name) for os_name in options.os]
@@ -301,10 +301,9 @@
if not ProcessOptions(options, args):
parser.print_help()
return 1
- # Determine which targets to build. The default is the "create_sdk" target,
- # as the "all" target is unsupported and not built on any of the bots.
+ # Determine which targets to build. By default we build the "all" target.
if len(args) == 0:
- targets = ['create_sdk']
+ targets = ['all']
else:
targets = args
diff --git a/tools/generate_idefiles.py b/tools/generate_idefiles.py
index 51b41e6..900c25c 100755
--- a/tools/generate_idefiles.py
+++ b/tools/generate_idefiles.py
@@ -50,7 +50,7 @@
if gn_result != 0:
return gn_result
- out_folder = utils.GetBuildRoot(HOST_OS, mode="debug", arch="x64")
+ out_folder = utils.GetBuildRoot(HOST_OS, mode="debug", arch=options.arch)
if not os.path.isdir(out_folder):
return 1
@@ -136,6 +136,10 @@
help="Target directory.",
default=utils.DART_DIR)
+ parser.add_argument("-a", "--arch",
+ help="Target architecture for runtime sources.",
+ default="x64")
+
options = parser.parse_args(argv[1:])
return GenerateIdeFiles(options)
diff --git a/tools/testing/dart/android.dart b/tools/testing/dart/android.dart
index 5cb232a..20e5fca 100644
--- a/tools/testing/dart/android.dart
+++ b/tools/testing/dart/android.dart
@@ -393,9 +393,6 @@
* Helper to list all adb devices available.
*/
class AdbHelper {
- // This particular device seems to be flakily going offline / having problems.
- static const blackListedDeviceIds = const <String>['06ada00c003b6f92'];
-
static RegExp _deviceLineRegexp =
new RegExp(r'^([a-zA-Z0-9_-]+)[ \t]+device$', multiLine: true);
@@ -408,7 +405,6 @@
return _deviceLineRegexp
.allMatches(result.stdout as String)
.map((Match m) => m.group(1))
- .where((String deviceId) => !blackListedDeviceIds.contains(deviceId))
.toList();
});
}
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 4cecd58..3afc50e 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -566,8 +566,6 @@
Set<String> _testListPossibleFilenames;
RegExp _selectorFilenameRegExp;
- static final Uri co19SuiteLocation = Repository.uri.resolve("tests/co19_2/");
-
StandardTestSuite(TestConfiguration configuration, String suiteName,
Path suiteDirectory, List<String> statusFilePaths,
{bool recursive: false})
@@ -1249,8 +1247,6 @@
Map<String, dynamic> readOptionsFromFile(Uri uri) {
if (uri.path.endsWith('.dill')) {
return optionsFromKernelFile();
- } else if ("$uri".startsWith("$co19SuiteLocation")) {
- return readOptionsFromCo19File(uri);
}
RegExp testOptionsRegExp = new RegExp(r"// VMOptions=(.*)");
RegExp environmentRegExp = new RegExp(r"// Environment=(.*)");
@@ -1394,9 +1390,11 @@
//
// Redo this code once we have a more precise test framework for detecting
// and locating these errors.
- var hasSyntaxError = contents.contains("/*@syntax-error=");
- var hasCompileError =
- hasSyntaxError || contents.contains("/*@compile-error=");
+ final hasSyntaxError = contents.contains("@syntax-error");
+ final hasCompileError =
+ hasSyntaxError || contents.contains("@compile-error");
+ final hasRuntimeError = contents.contains("@runtime-error");
+ final hasStaticWarning = contents.contains("@static-warning");
return {
"vmOptions": result,
@@ -1409,8 +1407,8 @@
"packages": packages,
"hasSyntaxError": hasSyntaxError,
"hasCompileError": hasCompileError,
- "hasRuntimeError": false,
- "hasStaticWarning": false,
+ "hasRuntimeError": hasRuntimeError,
+ "hasStaticWarning": hasStaticWarning,
"otherScripts": otherScripts,
"otherResources": otherResources,
"isMultitest": isMultitest,
@@ -1460,50 +1458,6 @@
if (!needsVmOptions) return [[]];
return optionsFromFile['vmOptions'] as List<List<String>>;
}
-
- /**
- * Read options from a co19 test file.
- *
- * The reason this is different from [readOptionsFromFile] is that
- * co19 is developed based on a contract which defines certain test
- * tags. These tags may appear unused, but should not be removed
- * without consulting with the co19 team.
- *
- * Also, [readOptionsFromFile] recognizes a number of additional
- * tags that are not appropriate for use in general tests of
- * conformance to the Dart language. Any Dart implementation must
- * pass the co19 test suite as is, and not require extra flags,
- * environment variables, configuration files, etc.
- */
- Map<String, dynamic> readOptionsFromCo19File(Uri uri) {
- String contents = decodeUtf8(new File.fromUri(uri).readAsBytesSync());
-
- bool hasSyntaxError = contents.contains("@syntax-error");
- bool hasCompileError =
- hasSyntaxError || contents.contains("@compile-error");
- bool hasRuntimeError = contents.contains("@runtime-error");
- bool hasStaticWarning = contents.contains("@static-warning");
- bool isMultitest = multiTestRegExp.hasMatch(contents);
-
- return {
- "vmOptions": <List<String>>[[]],
- "sharedOptions": <String>[],
- "dart2jsOptions": <String>[],
- "dartOptions": null,
- "packageRoot": null,
- "hasSyntaxError": hasSyntaxError,
- "hasCompileError": hasCompileError,
- "hasRuntimeError": hasRuntimeError,
- "hasStaticWarning": hasStaticWarning,
- "otherScripts": <String>[],
- "otherResources": <String>[],
- "isMultitest": isMultitest,
- "isMultiHtmlTest": false,
- "subtestNames": <String>[],
- "isolateStubs": '',
- "containsDomImport": false,
- };
- }
}
/// Used for testing packages in one-off settings, i.e., we pass in the actual