| Index: pkg/compiler/lib/src/typechecker.dart
|
| diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
|
| index bd230563c9991ea6deef58172796a8e4186da1ea..c3d081ca8e7c7c0cf23f5c3139da02d4ac36c608 100644
|
| --- a/pkg/compiler/lib/src/typechecker.dart
|
| +++ b/pkg/compiler/lib/src/typechecker.dart
|
| @@ -5,53 +5,46 @@
|
| library dart2js.typechecker;
|
|
|
| import 'common.dart';
|
| -import 'common/names.dart' show
|
| - Identifiers;
|
| -import 'common/resolution.dart' show
|
| - Resolution;
|
| -import 'common/tasks.dart' show
|
| - CompilerTask;
|
| -import 'compiler.dart' show
|
| - Compiler;
|
| +import 'common/names.dart' show Identifiers;
|
| +import 'common/resolution.dart' show Resolution;
|
| +import 'common/tasks.dart' show CompilerTask;
|
| +import 'compiler.dart' show Compiler;
|
| import 'constants/expressions.dart';
|
| import 'constants/values.dart';
|
| import 'core_types.dart';
|
| import 'dart_types.dart';
|
| -import 'elements/elements.dart' show
|
| - AbstractFieldElement,
|
| - AstElement,
|
| - AsyncMarker,
|
| - ClassElement,
|
| - ConstructorElement,
|
| - Element,
|
| - Elements,
|
| - EnumClassElement,
|
| - ExecutableElement,
|
| - FieldElement,
|
| - FunctionElement,
|
| - GetterElement,
|
| - InitializingFormalElement,
|
| - LibraryElement,
|
| - Member,
|
| - MemberSignature,
|
| - Name,
|
| - ParameterElement,
|
| - PrivateName,
|
| - PublicName,
|
| - ResolvedAst,
|
| - SetterElement,
|
| - TypeDeclarationElement,
|
| - TypedElement,
|
| - TypedefElement,
|
| - VariableElement;
|
| -import 'resolution/tree_elements.dart' show
|
| - TreeElements;
|
| -import 'resolution/class_members.dart' show
|
| - MembersCreator;
|
| +import 'elements/elements.dart'
|
| + show
|
| + AbstractFieldElement,
|
| + AstElement,
|
| + AsyncMarker,
|
| + ClassElement,
|
| + ConstructorElement,
|
| + Element,
|
| + Elements,
|
| + EnumClassElement,
|
| + ExecutableElement,
|
| + FieldElement,
|
| + FunctionElement,
|
| + GetterElement,
|
| + InitializingFormalElement,
|
| + LibraryElement,
|
| + Member,
|
| + MemberSignature,
|
| + Name,
|
| + ParameterElement,
|
| + PrivateName,
|
| + PublicName,
|
| + ResolvedAst,
|
| + SetterElement,
|
| + TypeDeclarationElement,
|
| + TypedElement,
|
| + TypedefElement,
|
| + VariableElement;
|
| +import 'resolution/tree_elements.dart' show TreeElements;
|
| +import 'resolution/class_members.dart' show MembersCreator;
|
| import 'tree/tree.dart';
|
| -import 'util/util.dart' show
|
| - Link,
|
| - LinkBuilder;
|
| +import 'util/util.dart' show Link, LinkBuilder;
|
|
|
| class TypeCheckerTask extends CompilerTask {
|
| TypeCheckerTask(Compiler compiler) : super(compiler);
|
| @@ -233,7 +226,6 @@ class TypeLiteralAccess extends ElementAccess {
|
| String toString() => 'TypeLiteralAccess($type)';
|
| }
|
|
|
| -
|
| /// An access to the 'call' method of a function type.
|
| class FunctionCallAccess implements ElementAccess {
|
| final Element element;
|
| @@ -250,7 +242,6 @@ class FunctionCallAccess implements ElementAccess {
|
| String toString() => 'FunctionAccess($element, $type)';
|
| }
|
|
|
| -
|
| /// An is-expression that potentially promotes a variable.
|
| class TypePromotion {
|
| final Send node;
|
| @@ -267,7 +258,7 @@ class TypePromotion {
|
| }
|
|
|
| void addHint(DiagnosticMessage hint,
|
| - [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
| + [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
|
| messages.add(new TypePromotionMessage(hint, infos));
|
| }
|
|
|
| @@ -332,9 +323,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|
|
| void registerKnownTypePromotion(TypePromotion typePromotion) {
|
| VariableElement variable = typePromotion.variable;
|
| - Link<TypePromotion> knownTypes =
|
| - typePromotionsMap.putIfAbsent(variable,
|
| - () => const Link<TypePromotion>());
|
| + Link<TypePromotion> knownTypes = typePromotionsMap.putIfAbsent(
|
| + variable, () => const Link<TypePromotion>());
|
| typePromotionsMap[variable] = knownTypes.prepend(typePromotion);
|
| }
|
|
|
| @@ -377,8 +367,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| : this.elements = elements,
|
| this.executableContext = elements.analyzedElement,
|
| this.currentClass = elements.analyzedElement != null
|
| - ? elements.analyzedElement.enclosingClass : null {
|
| -
|
| + ? elements.analyzedElement.enclosingClass
|
| + : null {
|
| if (currentClass != null) {
|
| thisType = currentClass.thisType;
|
| superType = currentClass.supertype;
|
| @@ -392,13 +382,12 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| LibraryElement get currentLibrary => elements.analyzedElement.library;
|
|
|
| reportTypeWarning(Spannable spannable, MessageKind kind,
|
| - [Map arguments = const {}]) {
|
| + [Map arguments = const {}]) {
|
| reporter.reportWarningMessage(spannable, kind, arguments);
|
| }
|
|
|
| - reportMessage(Spannable spannable, MessageKind kind,
|
| - Map arguments,
|
| - {bool isHint: false}) {
|
| + reportMessage(Spannable spannable, MessageKind kind, Map arguments,
|
| + {bool isHint: false}) {
|
| if (isHint) {
|
| reporter.reportHintMessage(spannable, kind, arguments);
|
| } else {
|
| @@ -454,7 +443,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| }
|
|
|
| void checkTypePromotion(Node node, TypePromotion typePromotion,
|
| - {bool checkAccesses: false}) {
|
| + {bool checkAccesses: false}) {
|
| VariableElement variable = typePromotion.variable;
|
| String variableName = variable.name;
|
| List<Node> potentialMutationsIn =
|
| @@ -466,7 +455,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| {'variableName': variableName, 'shownType': typePromotion.type});
|
| List<DiagnosticMessage> infos = <DiagnosticMessage>[];
|
| for (Node mutation in potentialMutationsIn) {
|
| - infos.add(reporter.createMessage(mutation,
|
| + infos.add(reporter.createMessage(
|
| + mutation,
|
| MessageKind.POTENTIAL_MUTATION_HERE,
|
| {'variableName': variableName}));
|
| }
|
| @@ -517,7 +507,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| /// Show type promotions from [left] and [right] in [node] given that the
|
| /// promoted variables are not potentially mutated in [right].
|
| void reshowTypePromotions(Node node, Node left, Node right) {
|
| - for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) {
|
| + for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) {
|
| typePromotion = typePromotion.copy();
|
| checkTypePromotion(right, typePromotion);
|
| showTypePromotion(node, typePromotion);
|
| @@ -533,7 +523,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| /// Analyze [node] in the context of the known types shown in [context].
|
| DartType analyzeInPromotedContext(Node context, Node node) {
|
| Link<TypePromotion> knownForNode = const Link<TypePromotion>();
|
| - for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) {
|
| + for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) {
|
| typePromotion = typePromotion.copy();
|
| checkTypePromotion(node, typePromotion, checkAccesses: true);
|
| knownForNode = knownForNode.prepend(typePromotion);
|
| @@ -556,17 +546,13 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| * checked mode, otherwise a warning is issued.
|
| */
|
| bool checkAssignable(Spannable spannable, DartType from, DartType to,
|
| - {bool isConst: false}) {
|
| + {bool isConst: false}) {
|
| if (!types.isAssignable(from, to)) {
|
| if (compiler.options.enableTypeAssertions && isConst) {
|
| - reporter.reportErrorMessage(
|
| - spannable,
|
| - MessageKind.NOT_ASSIGNABLE,
|
| + reporter.reportErrorMessage(spannable, MessageKind.NOT_ASSIGNABLE,
|
| {'fromType': from, 'toType': to});
|
| } else {
|
| - reporter.reportWarningMessage(
|
| - spannable,
|
| - MessageKind.NOT_ASSIGNABLE,
|
| + reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE,
|
| {'fromType': from, 'toType': to});
|
| }
|
| return false;
|
| @@ -645,7 +631,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| DartType returnType;
|
| final FunctionElement element = elements.getFunctionDefinition(node);
|
| assert(invariant(node, element != null,
|
| - message: 'FunctionExpression with no element'));
|
| + message: 'FunctionExpression with no element'));
|
| if (Elements.isUnresolved(element)) return const DynamicType();
|
| if (element.isGenerativeConstructor) {
|
| type = const DynamicType();
|
| @@ -690,9 +676,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| TypedElement element = elements[node];
|
| assert(invariant(node, element != null,
|
| message: 'Missing element for identifier'));
|
| - assert(invariant(node, element.isVariable ||
|
| - element.isParameter ||
|
| - element.isField,
|
| + assert(invariant(
|
| + node, element.isVariable || element.isParameter || element.isField,
|
| message: 'Unexpected context element ${element}'));
|
| return element.computeType(resolution);
|
| }
|
| @@ -714,19 +699,14 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (name != null &&
|
| Name.isPrivateName(name) &&
|
| element.library != currentLibrary) {
|
| - reportTypeWarning(
|
| - node,
|
| - MessageKind.PRIVATE_ACCESS,
|
| - {'name': name,
|
| - 'libraryName': element.library.libraryOrScriptName});
|
| + reportTypeWarning(node, MessageKind.PRIVATE_ACCESS,
|
| + {'name': name, 'libraryName': element.library.libraryOrScriptName});
|
| }
|
| -
|
| }
|
|
|
| ElementAccess lookupMember(Node node, DartType receiverType, String name,
|
| - MemberKind memberKind, Element receiverElement,
|
| - {bool lookupClassMember: false,
|
| - bool isHint: false}) {
|
| + MemberKind memberKind, Element receiverElement,
|
| + {bool lookupClassMember: false, bool isHint: false}) {
|
| if (receiverType.treatAsDynamic) {
|
| return const DynamicAccess();
|
| }
|
| @@ -745,8 +725,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|
|
| // Compute the access of [name] on [type]. This function takes the special
|
| // 'call' method into account.
|
| - ElementAccess getAccess(Name name,
|
| - DartType unaliasedBound, InterfaceType interface) {
|
| + ElementAccess getAccess(
|
| + Name name, DartType unaliasedBound, InterfaceType interface) {
|
| MemberSignature member = lookupMemberSignature(memberName, interface);
|
| if (member != null) {
|
| return new MemberAccess(member);
|
| @@ -809,11 +789,13 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (memberName.isSimilarTo(member.name)) {
|
| PrivateName privateName = member.name;
|
| reportMessage(
|
| - node,
|
| - MessageKind.PRIVATE_ACCESS,
|
| - {'name': name,
|
| - 'libraryName': privateName.library.libraryOrScriptName},
|
| - isHint: isHint);
|
| + node,
|
| + MessageKind.PRIVATE_ACCESS,
|
| + {
|
| + 'name': name,
|
| + 'libraryName': privateName.library.libraryOrScriptName
|
| + },
|
| + isHint: isHint);
|
| foundPrivateMember = true;
|
| }
|
| }
|
| @@ -824,7 +806,6 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| } else {
|
| interface.element.forEachInterfaceMember(findPrivateMember);
|
| }
|
| -
|
| }
|
| if (!foundPrivateMember) {
|
| switch (memberKind) {
|
| @@ -842,7 +823,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (lookupMemberSignature(memberName.setter, interface) != null) {
|
| // A setter is present so warn explicitly about the missing
|
| // getter.
|
| - reportMessage(node,
|
| + reportMessage(
|
| + node,
|
| MessageKind.UNDEFINED_INSTANCE_GETTER_BUT_SETTER,
|
| {'className': receiverType.name, 'memberName': name},
|
| isHint: isHint);
|
| @@ -874,20 +856,19 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| return const DynamicAccess();
|
| }
|
|
|
| - DartType lookupMemberType(Node node, DartType type, String name,
|
| - MemberKind memberKind,
|
| - {bool isHint: false}) {
|
| + DartType lookupMemberType(
|
| + Node node, DartType type, String name, MemberKind memberKind,
|
| + {bool isHint: false}) {
|
| return lookupMember(node, type, name, memberKind, null, isHint: isHint)
|
| .computeType(resolution);
|
| }
|
|
|
| void analyzeArguments(Send send, Element element, DartType type,
|
| - [LinkBuilder<DartType> argumentTypes]) {
|
| + [LinkBuilder<DartType> argumentTypes]) {
|
| Link<Node> arguments = send.arguments;
|
| type.computeUnaliased(resolution);
|
| DartType unaliasedType = type.unaliased;
|
| if (identical(unaliasedType.kind, TypeKind.FUNCTION)) {
|
| -
|
| /// Report [warning] including info(s) about the declaration of [element]
|
| /// or [type].
|
| void reportWarning(DiagnosticMessage warning) {
|
| @@ -898,10 +879,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (declaration == null) {
|
| declaration = type.element;
|
| } else if (type.isTypedef) {
|
| - infos.add(reporter.createMessage(
|
| - declaration,
|
| - MessageKind.THIS_IS_THE_DECLARATION,
|
| - {'name': element.name}));
|
| + infos.add(reporter.createMessage(declaration,
|
| + MessageKind.THIS_IS_THE_DECLARATION, {'name': element.name}));
|
| declaration = type.element;
|
| }
|
| if (declaration != null) {
|
| @@ -913,13 +892,10 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
|
|
| /// Report a warning on [node] if [argumentType] is not assignable to
|
| /// [parameterType].
|
| - void checkAssignable(Spannable node,
|
| - DartType argumentType,
|
| - DartType parameterType) {
|
| + void checkAssignable(
|
| + Spannable node, DartType argumentType, DartType parameterType) {
|
| if (!types.isAssignable(argumentType, parameterType)) {
|
| - reportWarning(reporter.createMessage(
|
| - node,
|
| - MessageKind.NOT_ASSIGNABLE,
|
| + reportWarning(reporter.createMessage(node, MessageKind.NOT_ASSIGNABLE,
|
| {'fromType': argumentType, 'toType': parameterType}));
|
| }
|
| }
|
| @@ -954,7 +930,6 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| } else {
|
| if (!parameterTypes.moveNext()) {
|
| if (!optionalParameterTypes.moveNext()) {
|
| -
|
| // TODO(johnniwinther): Provide better information on the
|
| // called function.
|
| reportWarning(reporter.createMessage(
|
| @@ -979,12 +954,11 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (parameterTypes.moveNext()) {
|
| // TODO(johnniwinther): Provide better information on the called
|
| // function.
|
| - reportWarning(reporter.createMessage(
|
| - send, MessageKind.MISSING_ARGUMENT,
|
| + reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT,
|
| {'argumentType': parameterTypes.current}));
|
| }
|
| } else {
|
| - while(!arguments.isEmpty) {
|
| + while (!arguments.isEmpty) {
|
| DartType argumentType = analyze(arguments.head);
|
| if (argumentTypes != null) argumentTypes.addLast(argumentType);
|
| arguments = arguments.tail;
|
| @@ -997,15 +971,15 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| // If provided [argumentTypes] is filled with the argument types during
|
| // analysis.
|
| DartType analyzeInvocation(Send node, ElementAccess elementAccess,
|
| - [LinkBuilder<DartType> argumentTypes]) {
|
| + [LinkBuilder<DartType> argumentTypes]) {
|
| DartType type = elementAccess.computeType(resolution);
|
| if (elementAccess.isCallable(compiler)) {
|
| analyzeArguments(node, elementAccess.element, type, argumentTypes);
|
| } else {
|
| - reportTypeWarning(node, MessageKind.NOT_CALLABLE,
|
| - {'elementName': elementAccess.name});
|
| - analyzeArguments(node, elementAccess.element, const DynamicType(),
|
| - argumentTypes);
|
| + reportTypeWarning(
|
| + node, MessageKind.NOT_CALLABLE, {'elementName': elementAccess.name});
|
| + analyzeArguments(
|
| + node, elementAccess.element, const DynamicType(), argumentTypes);
|
| }
|
| type.computeUnaliased(resolution);
|
| type = type.unaliased;
|
| @@ -1021,9 +995,9 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| * Computes the [ElementAccess] for [name] on the [node] possibly using the
|
| * [element] provided for [node] by the resolver.
|
| */
|
| - ElementAccess computeAccess(Send node, String name, Element element,
|
| - MemberKind memberKind,
|
| - {bool lookupClassMember: false}) {
|
| + ElementAccess computeAccess(
|
| + Send node, String name, Element element, MemberKind memberKind,
|
| + {bool lookupClassMember: false}) {
|
| if (Elements.isMalformed(element)) {
|
| return const DynamicAccess();
|
| }
|
| @@ -1045,10 +1019,10 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (receiverType.treatAsDynamic || receiverType.isVoid) {
|
| return const DynamicAccess();
|
| }
|
| - return lookupMember(node, receiverType, name, memberKind,
|
| - elements[node.receiver],
|
| - lookupClassMember: lookupClassMember ||
|
| - element != null && element.isStatic);
|
| + return lookupMember(
|
| + node, receiverType, name, memberKind, elements[node.receiver],
|
| + lookupClassMember:
|
| + lookupClassMember || element != null && element.isStatic);
|
| } else {
|
| return computeResolvedAccess(node, name, element, memberKind);
|
| }
|
| @@ -1058,8 +1032,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| * Computes the [ElementAccess] for [name] on the [node] using the [element]
|
| * provided for [node] by the resolver.
|
| */
|
| - ElementAccess computeResolvedAccess(Send node, String name,
|
| - Element element, MemberKind memberKind) {
|
| + ElementAccess computeResolvedAccess(
|
| + Send node, String name, Element element, MemberKind memberKind) {
|
| if (element == null) {
|
| // foo() where foo is unresolved.
|
| return lookupMember(node, thisType, name, memberKind, null);
|
| @@ -1079,22 +1053,19 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| } else if (element.isFunction) {
|
| // foo() where foo is a method in the same class.
|
| return createResolvedAccess(node, name, element);
|
| - } else if (element.isVariable ||
|
| - element.isParameter ||
|
| - element.isField) {
|
| + } else if (element.isVariable || element.isParameter || element.isField) {
|
| // foo() where foo is a field in the same class.
|
| return createResolvedAccess(node, name, element);
|
| } else if (element.isGetter || element.isSetter) {
|
| return createResolvedAccess(node, name, element);
|
| } else {
|
| - reporter.internalError(element,
|
| - 'Unexpected element kind ${element.kind}.');
|
| + reporter.internalError(
|
| + element, 'Unexpected element kind ${element.kind}.');
|
| return null;
|
| }
|
| }
|
|
|
| - ElementAccess createResolvedAccess(Send node, String name,
|
| - Element element) {
|
| + ElementAccess createResolvedAccess(Send node, String name, Element element) {
|
| checkPrivateAccess(node, element, name);
|
| return createPromotedAccess(element);
|
| }
|
| @@ -1113,12 +1084,12 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| * Computes the type of the access of [name] on the [node] possibly using the
|
| * [element] provided for [node] by the resolver.
|
| */
|
| - DartType computeAccessType(Send node, String name, Element element,
|
| - MemberKind memberKind,
|
| - {bool lookupClassMember: false}) {
|
| - DartType type =
|
| - computeAccess(node, name, element, memberKind,
|
| - lookupClassMember: lookupClassMember).computeType(resolution);
|
| + DartType computeAccessType(
|
| + Send node, String name, Element element, MemberKind memberKind,
|
| + {bool lookupClassMember: false}) {
|
| + DartType type = computeAccess(node, name, element, memberKind,
|
| + lookupClassMember: lookupClassMember)
|
| + .computeType(resolution);
|
| if (type == null) {
|
| reporter.internalError(node, 'Type is null on access of $name on $node.');
|
| }
|
| @@ -1129,8 +1100,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| /// This is used to provided better hints when trying to promote a supertype
|
| /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List`
|
| /// we suggest the use of `List<int>`, which would make promotion valid.
|
| - DartType computeMoreSpecificType(DartType shownType,
|
| - DartType knownType) {
|
| + DartType computeMoreSpecificType(DartType shownType, DartType knownType) {
|
| if (knownType.isInterfaceType &&
|
| shownType.isInterfaceType &&
|
| types.isSubtype(shownType.asRaw(), knownType)) {
|
| @@ -1146,8 +1116,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| // the relation between `A<S, int>` and `A<double, int>`.
|
| MoreSpecificSubtypeVisitor visitor =
|
| new MoreSpecificSubtypeVisitor(types);
|
| - InterfaceType shownTypeGeneric = visitor.computeMoreSpecific(
|
| - shownClass, knownInterfaceType);
|
| + InterfaceType shownTypeGeneric =
|
| + visitor.computeMoreSpecific(shownClass, knownInterfaceType);
|
|
|
| if (shownTypeGeneric != null &&
|
| types.isMoreSpecific(shownTypeGeneric, knownType)) {
|
| @@ -1157,7 +1127,6 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| }
|
| }
|
| return null;
|
| -
|
| }
|
|
|
| static bool _fyiShown = false;
|
| @@ -1166,7 +1135,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (const bool.fromEnvironment('send_stats') &&
|
| executableContext != null &&
|
| // TODO(sigmund): enable also in core libs.
|
| - !executableContext.library.isPlatformLibrary && !type.isDynamic) {
|
| + !executableContext.library.isPlatformLibrary &&
|
| + !type.isDynamic) {
|
| if (!_fyiShown) {
|
| print('FYI experiment to collect send stats is on: '
|
| 'caching types of expressions');
|
| @@ -1236,8 +1206,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| }
|
| }
|
|
|
| - if (variable != null &&
|
| - (variable.isVariable || variable.isParameter)) {
|
| + if (variable != null && (variable.isVariable || variable.isParameter)) {
|
| DartType knownType = getKnownType(variable);
|
| if (!knownType.isDynamic) {
|
| DartType shownType = elements.getType(node.arguments.head);
|
| @@ -1247,29 +1216,29 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| String variableName = variable.name;
|
| if (!types.isSubtype(shownType, knownType)) {
|
| typePromotion.addHint(reporter.createMessage(
|
| - node,
|
| - MessageKind.NOT_MORE_SPECIFIC_SUBTYPE,
|
| - {'variableName': variableName,
|
| - 'shownType': shownType,
|
| - 'knownType': knownType}));
|
| + node, MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, {
|
| + 'variableName': variableName,
|
| + 'shownType': shownType,
|
| + 'knownType': knownType
|
| + }));
|
| } else {
|
| DartType shownTypeSuggestion =
|
| computeMoreSpecificType(shownType, knownType);
|
| if (shownTypeSuggestion != null) {
|
| typePromotion.addHint(reporter.createMessage(
|
| - node,
|
| - MessageKind.NOT_MORE_SPECIFIC_SUGGESTION,
|
| - {'variableName': variableName,
|
| - 'shownType': shownType,
|
| - 'shownTypeSuggestion': shownTypeSuggestion,
|
| - 'knownType': knownType}));
|
| + node, MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, {
|
| + 'variableName': variableName,
|
| + 'shownType': shownType,
|
| + 'shownTypeSuggestion': shownTypeSuggestion,
|
| + 'knownType': knownType
|
| + }));
|
| } else {
|
| typePromotion.addHint(reporter.createMessage(
|
| - node,
|
| - MessageKind.NOT_MORE_SPECIFIC,
|
| - {'variableName': variableName,
|
| - 'shownType': shownType,
|
| - 'knownType': knownType}));
|
| + node, MessageKind.NOT_MORE_SPECIFIC, {
|
| + 'variableName': variableName,
|
| + 'shownType': shownType,
|
| + 'knownType': knownType
|
| + }));
|
| }
|
| }
|
| }
|
| @@ -1278,15 +1247,19 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| }
|
| }
|
| return boolType;
|
| - } if (node.isOperator && identical(name, 'as')) {
|
| + }
|
| + if (node.isOperator && identical(name, 'as')) {
|
| analyze(node.receiver);
|
| return elements.getType(node.arguments.head);
|
| } else if (node.isOperator) {
|
| final Node receiver = node.receiver;
|
| final DartType receiverType = analyze(receiver);
|
| - if (identical(name, '==') || identical(name, '!=')
|
| + if (identical(name, '==') ||
|
| + identical(name, '!=')
|
| // TODO(johnniwinther): Remove these.
|
| - || identical(name, '===') || identical(name, '!==')) {
|
| + ||
|
| + identical(name, '===') ||
|
| + identical(name, '!==')) {
|
| // Analyze argument.
|
| analyze(node.arguments.head);
|
| return boolType;
|
| @@ -1321,24 +1294,34 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (identical(name, '-') && node.arguments.isEmpty) {
|
| operatorName = 'unary-';
|
| }
|
| - assert(invariant(node,
|
| - identical(name, '+') || identical(name, '=') ||
|
| - identical(name, '-') || identical(name, '*') ||
|
| - identical(name, '/') || identical(name, '%') ||
|
| - identical(name, '~/') || identical(name, '|') ||
|
| - identical(name, '&') || identical(name, '^') ||
|
| - identical(name, '~')|| identical(name, '<<') ||
|
| - identical(name, '>>') ||
|
| - identical(name, '<') || identical(name, '>') ||
|
| - identical(name, '<=') || identical(name, '>=') ||
|
| - identical(name, '[]'),
|
| - message: 'Unexpected operator $name'));
|
| + assert(invariant(
|
| + node,
|
| + identical(name, '+') ||
|
| + identical(name, '=') ||
|
| + identical(name, '-') ||
|
| + identical(name, '*') ||
|
| + identical(name, '/') ||
|
| + identical(name, '%') ||
|
| + identical(name, '~/') ||
|
| + identical(name, '|') ||
|
| + identical(name, '&') ||
|
| + identical(name, '^') ||
|
| + identical(name, '~') ||
|
| + identical(name, '<<') ||
|
| + identical(name, '>>') ||
|
| + identical(name, '<') ||
|
| + identical(name, '>') ||
|
| + identical(name, '<=') ||
|
| + identical(name, '>=') ||
|
| + identical(name, '[]'),
|
| + message: 'Unexpected operator $name'));
|
|
|
| // TODO(karlklose): handle `void` in expression context by calling
|
| // [analyzeNonVoid] instead of [analyze].
|
| - ElementAccess access = receiverType.isVoid ? const DynamicAccess()
|
| - : lookupMember(node, receiverType, operatorName,
|
| - MemberKind.OPERATOR, null);
|
| + ElementAccess access = receiverType.isVoid
|
| + ? const DynamicAccess()
|
| + : lookupMember(
|
| + node, receiverType, operatorName, MemberKind.OPERATOR, null);
|
| LinkBuilder<DartType> argumentTypesBuilder = new LinkBuilder<DartType>();
|
| DartType resultType =
|
| analyzeInvocation(node, access, argumentTypesBuilder);
|
| @@ -1387,10 +1370,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| * of the result. This method also handles increment/decrement expressions
|
| * like [: target++ :].
|
| */
|
| - DartType checkAssignmentOperator(SendSet node,
|
| - String operatorName,
|
| - Node valueNode,
|
| - DartType value) {
|
| + DartType checkAssignmentOperator(
|
| + SendSet node, String operatorName, Node valueNode, DartType value) {
|
| assert(invariant(node, !node.isIndex));
|
| Element setterElement = elements[node];
|
| Element getterElement = elements[node.selector];
|
| @@ -1423,18 +1404,15 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| * of the result. This method also handles increment/decrement expressions
|
| * like [: base[key]++ :].
|
| */
|
| - DartType checkIndexAssignmentOperator(SendSet node,
|
| - String operatorName,
|
| - Node valueNode,
|
| - DartType value) {
|
| + DartType checkIndexAssignmentOperator(
|
| + SendSet node, String operatorName, Node valueNode, DartType value) {
|
| assert(invariant(node, node.isIndex));
|
| final DartType base = analyze(node.receiver);
|
| final Node keyNode = node.arguments.head;
|
| final DartType key = analyze(keyNode);
|
|
|
| // [indexGet] is the type of operator[] on [base].
|
| - DartType indexGet = lookupMemberType(
|
| - node, base, '[]', MemberKind.OPERATOR);
|
| + DartType indexGet = lookupMemberType(node, base, '[]', MemberKind.OPERATOR);
|
| if (indexGet is FunctionType) {
|
| FunctionType indexGetType = indexGet;
|
| DartType indexGetKey = firstType(indexGetType.parameterTypes);
|
| @@ -1444,8 +1422,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| // [element] is the type of base[key].
|
| DartType element = indexGetType.returnType;
|
| // [operator] is the type of operator o on [element].
|
| - DartType operator = lookupMemberType(
|
| - node, element, operatorName, MemberKind.OPERATOR);
|
| + DartType operator =
|
| + lookupMemberType(node, element, operatorName, MemberKind.OPERATOR);
|
| if (operator is FunctionType) {
|
| FunctionType operatorType = operator;
|
|
|
| @@ -1457,8 +1435,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| DartType result = operatorType.returnType;
|
|
|
| // [indexSet] is the type of operator[]= on [base].
|
| - DartType indexSet = lookupMemberType(
|
| - node, base, '[]=', MemberKind.OPERATOR);
|
| + DartType indexSet =
|
| + lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
|
| if (indexSet is FunctionType) {
|
| FunctionType indexSetType = indexSet;
|
| DartType indexSetKey = firstType(indexSetType.parameterTypes);
|
| @@ -1487,14 +1465,14 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (identical(name, '=') || identical(name, '??=')) {
|
| // e1 = value
|
| if (node.isIndex) {
|
| - // base[key] = value
|
| + // base[key] = value
|
| final DartType base = analyze(node.receiver);
|
| final Node keyNode = node.arguments.head;
|
| final DartType key = analyze(keyNode);
|
| final Node valueNode = node.arguments.tail.head;
|
| final DartType value = analyze(valueNode);
|
| - DartType indexSet = lookupMemberType(
|
| - node, base, '[]=', MemberKind.OPERATOR);
|
| + DartType indexSet =
|
| + lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
|
| DartType indexSetValue = const DynamicType();
|
| if (indexSet is FunctionType) {
|
| FunctionType indexSetType = indexSet;
|
| @@ -1503,7 +1481,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| indexSetValue = secondType(indexSetType.parameterTypes);
|
| checkAssignable(node.assignmentOperator, value, indexSetValue);
|
| }
|
| - return identical(name, '=') ? value
|
| + return identical(name, '=')
|
| + ? value
|
| : types.computeLeastUpperBound(value, indexSetValue);
|
| } else {
|
| // target = value
|
| @@ -1512,8 +1491,9 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| // Field declaration `Foo target = value;` or initializer
|
| // `this.target = value`. Lookup the getter `target` in the class
|
| // members.
|
| - target = computeAccessType(node, selector.source, element,
|
| - MemberKind.GETTER, lookupClassMember: true);
|
| + target = computeAccessType(
|
| + node, selector.source, element, MemberKind.GETTER,
|
| + lookupClassMember: true);
|
| } else {
|
| // Normal assignment `target = value`.
|
| target = computeAccessType(
|
| @@ -1522,7 +1502,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| final Node valueNode = node.arguments.head;
|
| final DartType value = analyze(valueNode);
|
| checkAssignable(node.assignmentOperator, value, target);
|
| - return identical(name, '=') ? value
|
| + return identical(name, '=')
|
| + ? value
|
| : types.computeLeastUpperBound(value, target);
|
| }
|
| } else if (identical(name, '++') || identical(name, '--')) {
|
| @@ -1541,17 +1522,39 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| // e1 o= e2 for some operator o.
|
| String operatorName;
|
| switch (name) {
|
| - case '+=': operatorName = '+'; break;
|
| - case '-=': operatorName = '-'; break;
|
| - case '*=': operatorName = '*'; break;
|
| - case '/=': operatorName = '/'; break;
|
| - case '%=': operatorName = '%'; break;
|
| - case '~/=': operatorName = '~/'; break;
|
| - case '&=': operatorName = '&'; break;
|
| - case '|=': operatorName = '|'; break;
|
| - case '^=': operatorName = '^'; break;
|
| - case '<<=': operatorName = '<<'; break;
|
| - case '>>=': operatorName = '>>'; break;
|
| + case '+=':
|
| + operatorName = '+';
|
| + break;
|
| + case '-=':
|
| + operatorName = '-';
|
| + break;
|
| + case '*=':
|
| + operatorName = '*';
|
| + break;
|
| + case '/=':
|
| + operatorName = '/';
|
| + break;
|
| + case '%=':
|
| + operatorName = '%';
|
| + break;
|
| + case '~/=':
|
| + operatorName = '~/';
|
| + break;
|
| + case '&=':
|
| + operatorName = '&';
|
| + break;
|
| + case '|=':
|
| + operatorName = '|';
|
| + break;
|
| + case '^=':
|
| + operatorName = '^';
|
| + break;
|
| + case '<<=':
|
| + operatorName = '<<';
|
| + break;
|
| + case '>>=':
|
| + operatorName = '>>';
|
| + break;
|
| default:
|
| reporter.internalError(node, 'Unexpected assignment operator $name.');
|
| }
|
| @@ -1600,8 +1603,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| return coreTypes.symbolType;
|
| }
|
|
|
| - DartType computeConstructorType(ConstructorElement constructor,
|
| - DartType type) {
|
| + DartType computeConstructorType(
|
| + ConstructorElement constructor, DartType type) {
|
| if (Elements.isUnresolved(constructor)) return const DynamicType();
|
| DartType constructorType = constructor.computeType(resolution);
|
| if (identical(type.kind, TypeKind.INTERFACE)) {
|
| @@ -1613,8 +1616,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| while (receiverElement.isMixinApplication) {
|
| receiverElement = receiverElement.supertype.element;
|
| }
|
| - constructorType = constructorType.substByContext(
|
| - interfaceType.asInstanceOf(receiverElement));
|
| + constructorType = constructorType
|
| + .substByContext(interfaceType.asInstanceOf(receiverElement));
|
| } else {
|
| constructorType = constructorType.substByContext(type);
|
| }
|
| @@ -1638,8 +1641,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| InterfaceType listType = elements.getType(node);
|
| DartType listElementType = firstType(listType.typeArguments);
|
| for (Link<Node> link = node.elements.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| Node element = link.head;
|
| DartType elementType = analyze(element);
|
| checkAssignable(element, elementType, listElementType,
|
| @@ -1699,8 +1702,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| // conditions hold:
|
| // - f is not a generative constructor.
|
| // - The return type of f may not be assigned to void.
|
| - reportTypeWarning(node, MessageKind.RETURN_NOTHING,
|
| - {'returnType': expectedReturnType});
|
| + reportTypeWarning(
|
| + node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType});
|
| }
|
| return const StatementType();
|
| }
|
| @@ -1748,8 +1751,9 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| reportTypeWarning(node.type, MessageKind.VOID_VARIABLE);
|
| type = const DynamicType();
|
| }
|
| - for (Link<Node> link = node.definitions.nodes; !link.isEmpty;
|
| - link = link.tail) {
|
| + for (Link<Node> link = node.definitions.nodes;
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| Node definition = link.head;
|
| invariant(definition, definition is Identifier || definition is SendSet,
|
| message: 'expected identifier or initialization');
|
| @@ -1826,8 +1830,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| VariableDefinitions declaredIdentifier =
|
| node.declaredIdentifier.asVariableDefinitions();
|
| if (declaredIdentifier != null) {
|
| - return
|
| - analyzeWithDefault(declaredIdentifier.type, const DynamicType());
|
| + return analyzeWithDefault(declaredIdentifier.type, const DynamicType());
|
| } else {
|
| return analyze(node.declaredIdentifier);
|
| }
|
| @@ -1838,8 +1841,7 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| DartType expressionType = analyze(node.expression);
|
| DartType streamOfDynamic = coreTypes.streamType();
|
| if (!types.isAssignable(expressionType, streamOfDynamic)) {
|
| - reportMessage(node.expression,
|
| - MessageKind.NOT_ASSIGNABLE,
|
| + reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE,
|
| {'fromType': expressionType, 'toType': streamOfDynamic},
|
| isHint: true);
|
| } else {
|
| @@ -1851,11 +1853,14 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| if (streamType != null) {
|
| DartType streamElementType = streamType.typeArguments.first;
|
| if (!types.isAssignable(streamElementType, elementType)) {
|
| - reportMessage(node.expression,
|
| + reportMessage(
|
| + node.expression,
|
| MessageKind.FORIN_NOT_ASSIGNABLE,
|
| - {'currentType': streamElementType,
|
| - 'expressionType': expressionType,
|
| - 'elementType': elementType},
|
| + {
|
| + 'currentType': streamElementType,
|
| + 'expressionType': expressionType,
|
| + 'elementType': elementType
|
| + },
|
| isHint: true);
|
| }
|
| }
|
| @@ -1868,17 +1873,20 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| visitSyncForIn(SyncForIn node) {
|
| DartType elementType = computeForInElementType(node);
|
| DartType expressionType = analyze(node.expression);
|
| - DartType iteratorType = lookupMemberType(node.expression,
|
| - expressionType, Identifiers.iterator, MemberKind.GETTER);
|
| - DartType currentType = lookupMemberType(node.expression,
|
| - iteratorType, Identifiers.current, MemberKind.GETTER,
|
| - isHint: true);
|
| + DartType iteratorType = lookupMemberType(node.expression, expressionType,
|
| + Identifiers.iterator, MemberKind.GETTER);
|
| + DartType currentType = lookupMemberType(
|
| + node.expression, iteratorType, Identifiers.current, MemberKind.GETTER,
|
| + isHint: true);
|
| if (!types.isAssignable(currentType, elementType)) {
|
| - reportMessage(node.expression,
|
| + reportMessage(
|
| + node.expression,
|
| MessageKind.FORIN_NOT_ASSIGNABLE,
|
| - {'currentType': currentType,
|
| - 'expressionType': expressionType,
|
| - 'elementType': elementType},
|
| + {
|
| + 'currentType': currentType,
|
| + 'expressionType': expressionType,
|
| + 'elementType': elementType
|
| + },
|
| isHint: true);
|
| }
|
| analyze(node.body);
|
| @@ -1895,8 +1903,8 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| DartType mapValueType = secondType(mapType.typeArguments);
|
| bool isConst = node.isConst;
|
| for (Link<Node> link = node.entries.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| LiteralMapEntry entry = link.head;
|
| DartType keyType = analyze(entry.key);
|
| checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst);
|
| @@ -1960,21 +1968,20 @@ class TypeCheckerVisitor extends Visitor<DartType> {
|
| for (Node labelOrCase in switchCase.labelsAndCases) {
|
| CaseMatch caseMatch = labelOrCase.asCaseMatch();
|
| if (caseMatch != null) {
|
| - ConstantExpression caseConstant =
|
| - compiler.resolver.constantCompiler.compileNode(
|
| - caseMatch.expression, elements);
|
| - enumValues.remove(
|
| - compiler.constants.getConstantValue(caseConstant));
|
| + ConstantExpression caseConstant = compiler
|
| + .resolver.constantCompiler
|
| + .compileNode(caseMatch.expression, elements);
|
| + enumValues
|
| + .remove(compiler.constants.getConstantValue(caseConstant));
|
| }
|
| }
|
| }
|
| unreferencedFields.addAll(enumValues.values);
|
| if (!unreferencedFields.isEmpty) {
|
| - reporter.reportWarningMessage(
|
| - node, MessageKind.MISSING_ENUM_CASES,
|
| - {'enumType': expressionType,
|
| - 'enumValues': unreferencedFields.map(
|
| - (e) => e.name).join(', ')});
|
| + reporter.reportWarningMessage(node, MessageKind.MISSING_ENUM_CASES, {
|
| + 'enumType': expressionType,
|
| + 'enumValues': unreferencedFields.map((e) => e.name).join(', ')
|
| + });
|
| }
|
| });
|
| }
|
|
|