OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 |
| 5 import 'dart:collection' show Queue; |
| 6 |
| 7 import 'package:kernel/ast.dart' as ir; |
| 8 import 'package:kernel/checks.dart' show CheckParentPointers; |
| 9 import 'package:kernel/frontend/super_calls.dart' show moveSuperCallLast; |
| 10 |
| 11 import '../compiler.dart' show Compiler; |
| 12 import '../constants/expressions.dart' show TypeConstantExpression; |
| 13 import '../dart_types.dart' |
| 14 show DartType, FunctionType, InterfaceType, TypeKind, TypeVariableType; |
| 15 import '../diagnostics/messages.dart' show MessageKind; |
| 16 import '../diagnostics/spannable.dart' show Spannable; |
| 17 import '../elements/elements.dart' |
| 18 show |
| 19 ClassElement, |
| 20 ConstructorElement, |
| 21 Element, |
| 22 FieldElement, |
| 23 FunctionElement, |
| 24 LibraryElement, |
| 25 MixinApplicationElement, |
| 26 TypeVariableElement; |
| 27 import '../elements/modelx.dart' show ErroneousFieldElementX; |
| 28 import '../tree/tree.dart' show FunctionExpression, Node; |
| 29 import 'kernel_visitor.dart' show IrFunction, KernelVisitor; |
| 30 |
| 31 typedef void WorkAction(); |
| 32 |
| 33 class WorkItem { |
| 34 final Element element; |
| 35 final WorkAction action; |
| 36 |
| 37 WorkItem(this.element, this.action); |
| 38 } |
| 39 |
| 40 class Kernel { |
| 41 final Compiler compiler; |
| 42 |
| 43 final Map<LibraryElement, ir.Library> libraries = |
| 44 <LibraryElement, ir.Library>{}; |
| 45 |
| 46 final Map<ClassElement, ir.Class> classes = <ClassElement, ir.Class>{}; |
| 47 |
| 48 final Map<FunctionElement, ir.Member> functions = |
| 49 <FunctionElement, ir.Member>{}; |
| 50 |
| 51 final Map<FieldElement, ir.Field> fields = <FieldElement, ir.Field>{}; |
| 52 |
| 53 final Map<TypeVariableElement, ir.TypeParameter> typeParameters = |
| 54 <TypeVariableElement, ir.TypeParameter>{}; |
| 55 |
| 56 final Map<TypeVariableElement, ir.TypeParameter> factoryTypeParameters = |
| 57 <TypeVariableElement, ir.TypeParameter>{}; |
| 58 |
| 59 final Set<ir.TreeNode> checkedNodes = new Set<ir.TreeNode>(); |
| 60 |
| 61 final Map<LibraryElement, Map<String, int>> mixinApplicationNamesByLibrary = |
| 62 <LibraryElement, Map<String, int>>{}; |
| 63 |
| 64 /// FIFO queue of work that needs to be completed before the returned AST |
| 65 /// nodes are correct. |
| 66 final Queue<WorkItem> workQueue = new Queue<WorkItem>(); |
| 67 |
| 68 Kernel(this.compiler); |
| 69 |
| 70 void addWork(Element element, WorkAction action) { |
| 71 workQueue.addLast(new WorkItem(element, action)); |
| 72 } |
| 73 |
| 74 void checkMember(Element key, ir.TreeNode value) { |
| 75 if (!checkedNodes.add(value)) return; |
| 76 if (value.parent == null) { |
| 77 internalError(key, "Missing parent on IR node."); |
| 78 } |
| 79 try { |
| 80 CheckParentPointers.check(value); |
| 81 } catch (e, s) { |
| 82 internalError(key, "$e\n$s"); |
| 83 } |
| 84 } |
| 85 |
| 86 void checkLibrary(Element key, ir.Library library) { |
| 87 if (!checkedNodes.add(library)) return; |
| 88 CheckParentPointers.check(library); |
| 89 } |
| 90 |
| 91 void processWorkQueue() { |
| 92 while (workQueue.isNotEmpty) { |
| 93 WorkItem work = workQueue.removeFirst(); |
| 94 work.action(); |
| 95 } |
| 96 assert(() { |
| 97 libraries.forEach(checkLibrary); |
| 98 classes.forEach(checkMember); |
| 99 functions.forEach(checkMember); |
| 100 fields.forEach(checkMember); |
| 101 return true; |
| 102 }); |
| 103 } |
| 104 |
| 105 ir.Name irName(String name, Element element) { |
| 106 ir.Library irLibrary = null; |
| 107 if (name.startsWith("_")) { |
| 108 ClassElement cls = element.enclosingClass; |
| 109 if (cls != null && cls.isMixinApplication) { |
| 110 MixinApplicationElement mixinApplication = cls; |
| 111 element = mixinApplication.mixin; |
| 112 } |
| 113 irLibrary = libraryToIr(element.library); |
| 114 } |
| 115 return new ir.Name(name, irLibrary); |
| 116 } |
| 117 |
| 118 ir.Library libraryToIr(LibraryElement library) { |
| 119 library = library.declaration; |
| 120 return libraries.putIfAbsent(library, () { |
| 121 String name = library.hasLibraryName ? library.libraryName : null; |
| 122 ir.Library libraryNode = new ir.Library(library.canonicalUri, |
| 123 name: name, classes: null, procedures: null, fields: null); |
| 124 addWork(library, () { |
| 125 Queue<ir.Class> classes = new Queue<ir.Class>(); |
| 126 Queue<ir.Member> members = new Queue<ir.Member>(); |
| 127 library.implementation.forEachLocalMember((Element e) { |
| 128 if (e.isClass) { |
| 129 classes.addFirst(classToIr(e)); |
| 130 } else if (e.isFunction || e.isAccessor) { |
| 131 members.addFirst(functionToIr(e)); |
| 132 } else if (e.isField) { |
| 133 members.addFirst(fieldToIr(e)); |
| 134 } else if (e.isTypedef) { |
| 135 // Ignored, typedefs are unaliased on use. |
| 136 } else { |
| 137 internalError(e, "Unhandled library member: $e"); |
| 138 } |
| 139 }); |
| 140 // The elements were inserted in reverse order as forEachLocalMember |
| 141 // above gives them in reversed order. |
| 142 classes.forEach(libraryNode.addClass); |
| 143 members.forEach(libraryNode.addMember); |
| 144 }); |
| 145 return libraryNode; |
| 146 }); |
| 147 } |
| 148 |
| 149 /// Compute a name for [cls]. We want to have unique names in a library, but |
| 150 /// mixin applications can lead to multiple classes with the same name. So |
| 151 /// for those we append `#` and a number. |
| 152 String computeName(ClassElement cls) { |
| 153 String name = cls.name; |
| 154 if (!cls.isUnnamedMixinApplication) return name; |
| 155 Map<String, int> mixinApplicationNames = mixinApplicationNamesByLibrary |
| 156 .putIfAbsent(cls.library.implementation, () => <String, int>{}); |
| 157 int count = mixinApplicationNames.putIfAbsent(name, () => 0); |
| 158 mixinApplicationNames[name] = count + 1; |
| 159 return "$name#$count"; |
| 160 } |
| 161 |
| 162 ir.Class classToIr(ClassElement cls) { |
| 163 cls = cls.declaration; |
| 164 return classes.putIfAbsent(cls, () { |
| 165 String name = computeName(cls); |
| 166 ir.Class classNode = new ir.Class( |
| 167 name: name, |
| 168 isAbstract: cls.isAbstract, |
| 169 typeParameters: null, |
| 170 implementedTypes: null, |
| 171 constructors: null, |
| 172 procedures: null, |
| 173 fields: null); |
| 174 addWork(cls, () { |
| 175 if (cls.supertype != null) { |
| 176 classNode.supertype = interfaceTypeToIr(cls.supertype); |
| 177 } |
| 178 classNode.parent = libraryToIr(cls.library); |
| 179 if (cls.isUnnamedMixinApplication) { |
| 180 classNode.enclosingLibrary.addClass(classNode); |
| 181 } |
| 182 cls.implementation |
| 183 .forEachMember((ClassElement enclosingClass, Element member) { |
| 184 if (member.enclosingClass.declaration != cls) { |
| 185 internalError(cls, "`$member` isn't mine."); |
| 186 } else if (member.isFunction || |
| 187 member.isAccessor || |
| 188 member.isConstructor) { |
| 189 classNode.addMember(functionToIr(member)); |
| 190 } else if (member.isField) { |
| 191 classNode.addMember(fieldToIr(member)); |
| 192 } else { |
| 193 internalError(member, "Unhandled class member: $member"); |
| 194 } |
| 195 }); |
| 196 classNode.typeParameters.addAll(typeVariablesToIr(cls.typeVariables)); |
| 197 for (ir.InterfaceType interface in typesToIr(cls.interfaces.toList())) { |
| 198 classNode.implementedTypes.add(interface); |
| 199 } |
| 200 }); |
| 201 return classNode; |
| 202 }); |
| 203 } |
| 204 |
| 205 bool hasHierarchyProblem(ClassElement cls) => cls.hasIncompleteHierarchy; |
| 206 |
| 207 ir.InterfaceType interfaceTypeToIr(InterfaceType type) { |
| 208 ir.Class cls = classToIr(type.element); |
| 209 if (type.typeArguments.isEmpty) { |
| 210 return cls.rawType; |
| 211 } else { |
| 212 return new ir.InterfaceType(cls, typesToIr(type.typeArguments)); |
| 213 } |
| 214 } |
| 215 |
| 216 // TODO(ahe): Remove this method when dart2js support generic type arguments. |
| 217 List<ir.TypeParameter> typeParametersNotImplemented() { |
| 218 return const <ir.TypeParameter>[]; |
| 219 } |
| 220 |
| 221 ir.FunctionType functionTypeToIr(FunctionType type) { |
| 222 List<ir.TypeParameter> typeParameters = typeParametersNotImplemented(); |
| 223 int requiredParameterCount = type.parameterTypes.length; |
| 224 List<ir.DartType> positionalParameters = |
| 225 new List<ir.DartType>.from(typesToIr(type.parameterTypes)) |
| 226 ..addAll(typesToIr(type.optionalParameterTypes)); |
| 227 Map<String, ir.DartType> namedParameters = <String, ir.DartType>{}; |
| 228 for (int i = 0; i < type.namedParameters.length; i++) { |
| 229 namedParameters[type.namedParameters[i]] = |
| 230 typeToIr(type.namedParameterTypes[i]); |
| 231 } |
| 232 ir.DartType returnType = typeToIr(type.returnType); |
| 233 |
| 234 return new ir.FunctionType(positionalParameters, returnType, |
| 235 namedParameters: namedParameters, |
| 236 typeParameters: typeParameters, |
| 237 requiredParameterCount: requiredParameterCount); |
| 238 } |
| 239 |
| 240 ir.TypeParameterType typeVariableTypeToIr(TypeVariableType type) { |
| 241 return new ir.TypeParameterType(typeVariableToIr(type.element)); |
| 242 } |
| 243 |
| 244 List<ir.DartType> typesToIr(List<DartType> types) { |
| 245 List<ir.DartType> result = new List<ir.DartType>(types.length); |
| 246 for (int i = 0; i < types.length; i++) { |
| 247 result[i] = typeToIr(types[i]); |
| 248 } |
| 249 return result; |
| 250 } |
| 251 |
| 252 ir.DartType typeToIr(DartType type) { |
| 253 switch (type.kind) { |
| 254 case TypeKind.FUNCTION: |
| 255 return functionTypeToIr(type); |
| 256 |
| 257 case TypeKind.INTERFACE: |
| 258 return interfaceTypeToIr(type); |
| 259 |
| 260 case TypeKind.STATEMENT: |
| 261 throw "Internal error: statement type: $type."; |
| 262 |
| 263 case TypeKind.TYPEDEF: |
| 264 type.computeUnaliased(compiler.resolution); |
| 265 return typeToIr(type.unaliased); |
| 266 |
| 267 case TypeKind.TYPE_VARIABLE: |
| 268 return typeVariableTypeToIr(type); |
| 269 |
| 270 case TypeKind.MALFORMED_TYPE: |
| 271 return const ir.InvalidType(); |
| 272 |
| 273 case TypeKind.DYNAMIC: |
| 274 return const ir.DynamicType(); |
| 275 |
| 276 case TypeKind.VOID: |
| 277 return const ir.VoidType(); |
| 278 } |
| 279 } |
| 280 |
| 281 ir.DartType typeLiteralToIr(TypeConstantExpression constant) { |
| 282 return typeToIr(constant.type); |
| 283 } |
| 284 |
| 285 void setParent(ir.Member member, Element element) { |
| 286 if (element.isLocal) { |
| 287 member.parent = elementToIr(element.enclosingElement); |
| 288 } else if (element.isTopLevel) { |
| 289 member.parent = elementToIr(element.library); |
| 290 } else if (element.isClassMember) { |
| 291 member.parent = elementToIr(element.enclosingClass); |
| 292 } else { |
| 293 member.parent = elementToIr(element.enclosingElement); |
| 294 } |
| 295 } |
| 296 |
| 297 bool isNativeMethod(FunctionElement element) { |
| 298 // This method is a (modified) copy of the same method in |
| 299 // `pkg/compiler/lib/src/native/enqueue.dart`. |
| 300 if (!compiler.backend.canLibraryUseNative(element.library)) return false; |
| 301 return compiler.reporter.withCurrentElement(element, () { |
| 302 FunctionExpression functionExpression = |
| 303 element.node?.asFunctionExpression(); |
| 304 if (functionExpression == null) return false; |
| 305 Node body = functionExpression.body; |
| 306 if (body == null) return false; |
| 307 if (identical(body.getBeginToken().stringValue, 'native')) return true; |
| 308 return false; |
| 309 }); |
| 310 } |
| 311 |
| 312 ir.Member functionToIr(FunctionElement function) { |
| 313 if (function.isDeferredLoaderGetter) { |
| 314 internalError(function, "Deferred loader."); |
| 315 } |
| 316 if (function.isLocal) { |
| 317 internalError(function, "Local function."); |
| 318 } |
| 319 if (isSyntheticError(function)) { |
| 320 internalError(function, "Synthetic error function: $function."); |
| 321 } |
| 322 function = function.declaration; |
| 323 return functions.putIfAbsent(function, () { |
| 324 function = function.implementation; |
| 325 ir.Member member; |
| 326 ir.Constructor constructor; |
| 327 ir.Procedure procedure; |
| 328 ir.Name name = irName(function.name, function); |
| 329 bool isNative = isNativeMethod(function); |
| 330 if (function.isGenerativeConstructor) { |
| 331 member = constructor = new ir.Constructor(null, |
| 332 name: name, |
| 333 isConst: function.isConst, |
| 334 isExternal: isNative || function.isExternal, |
| 335 initializers: null); |
| 336 } else { |
| 337 member = procedure = new ir.Procedure(name, null, null, |
| 338 isAbstract: function.isAbstract, |
| 339 isStatic: function.isStatic || |
| 340 function.isTopLevel || |
| 341 function.isFactoryConstructor, |
| 342 isExternal: isNative || function.isExternal, |
| 343 isConst: false); // TODO(ahe): When is this true? |
| 344 } |
| 345 addWork(function, () { |
| 346 setParent(member, function); |
| 347 KernelVisitor visitor = |
| 348 new KernelVisitor(function, function.treeElements, this); |
| 349 beginFactoryScope(function); |
| 350 IrFunction irFunction = visitor.buildFunction(); |
| 351 // TODO(ahe): Add addFunction/set function to [ir.Procedure]. |
| 352 irFunction.node.parent = member; |
| 353 if (irFunction.isConstructor) { |
| 354 assert(irFunction.kind == null); |
| 355 constructor.function = irFunction.node; |
| 356 constructor.initializers = irFunction.initializers; |
| 357 // TODO(ahe): Add setInitializers to [ir.Constructor]. |
| 358 for (ir.Initializer initializer in irFunction.initializers) { |
| 359 initializer.parent = constructor; |
| 360 } |
| 361 moveSuperCallLast(constructor); |
| 362 } else { |
| 363 assert(irFunction.kind != null); |
| 364 procedure.function = irFunction.node; |
| 365 procedure.kind = irFunction.kind; |
| 366 } |
| 367 endFactoryScope(function); |
| 368 assert(() { |
| 369 visitor.locals.forEach(checkMember); |
| 370 return true; |
| 371 }); |
| 372 }); |
| 373 return member; |
| 374 }); |
| 375 } |
| 376 |
| 377 /// Adds the type parameters of the enclosing class of [function] to |
| 378 /// [factoryTypeParameters]. This serves as a local scope for type variables |
| 379 /// resolved inside the factory. |
| 380 /// |
| 381 /// This method solves the problem that a factory method really is a generic |
| 382 /// method that has its own type parameters, one for each type parameter in |
| 383 /// the enclosing class. |
| 384 void beginFactoryScope(FunctionElement function) { |
| 385 assert(factoryTypeParameters.isEmpty); |
| 386 if (!function.isFactoryConstructor) return; |
| 387 ClassElement cls = function.enclosingClass; |
| 388 for (DartType type in cls.typeVariables) { |
| 389 if (type.isTypeVariable) { |
| 390 TypeVariableElement variable = type.element; |
| 391 factoryTypeParameters[variable] = |
| 392 new ir.TypeParameter(variable.name, null); |
| 393 } |
| 394 } |
| 395 for (DartType type in cls.typeVariables) { |
| 396 if (type.isTypeVariable) { |
| 397 TypeVariableElement variable = type.element; |
| 398 factoryTypeParameters[variable].bound = typeToIr(variable.bound); |
| 399 } |
| 400 } |
| 401 } |
| 402 |
| 403 /// Ends the local scope started by [beginFactoryScope]. |
| 404 void endFactoryScope(FunctionElement function) { |
| 405 factoryTypeParameters.clear(); |
| 406 } |
| 407 |
| 408 ir.Field fieldToIr(FieldElement field) { |
| 409 if (isSyntheticError(field)) { |
| 410 internalError(field, "Synthetic error field: $field."); |
| 411 } |
| 412 field = field.declaration; |
| 413 return fields.putIfAbsent(field, () { |
| 414 field = field.implementation; |
| 415 ir.DartType type = |
| 416 field.isMalformed ? const ir.InvalidType() : typeToIr(field.type); |
| 417 ir.Field fieldNode = new ir.Field(irName(field.memberName.text, field), |
| 418 type: type, |
| 419 initializer: null, |
| 420 isFinal: field.isFinal, |
| 421 isStatic: field.isStatic || field.isTopLevel, |
| 422 isConst: field.isConst); |
| 423 addWork(field, () { |
| 424 setParent(fieldNode, field); |
| 425 if (!field.isMalformed && |
| 426 !field.isInstanceMember && |
| 427 field.initializer != null) { |
| 428 KernelVisitor visitor = |
| 429 new KernelVisitor(field, field.treeElements, this); |
| 430 fieldNode.initializer = visitor.buildInitializer() |
| 431 ..parent = fieldNode; |
| 432 } |
| 433 }); |
| 434 return fieldNode; |
| 435 }); |
| 436 } |
| 437 |
| 438 ir.TypeParameter typeVariableToIr(TypeVariableElement variable) { |
| 439 variable = variable.declaration; |
| 440 ir.TypeParameter parameter = factoryTypeParameters[variable]; |
| 441 if (parameter != null) return parameter; |
| 442 return typeParameters.putIfAbsent(variable, () { |
| 443 ir.TypeParameter parameter = new ir.TypeParameter(variable.name, null); |
| 444 addWork(variable, () { |
| 445 // TODO(ahe): This assignment will probably not be correct when dart2js |
| 446 // supports generic methods. |
| 447 ClassElement cls = variable.typeDeclaration; |
| 448 parameter.parent = classToIr(cls); |
| 449 parameter.bound = typeToIr(variable.bound); |
| 450 }); |
| 451 return parameter; |
| 452 }); |
| 453 } |
| 454 |
| 455 List<ir.TypeParameter> typeVariablesToIr(List<DartType> variables) { |
| 456 List<ir.TypeParameter> result = |
| 457 new List<ir.TypeParameter>(variables.length); |
| 458 for (int i = 0; i < variables.length; i++) { |
| 459 TypeVariableType type = variables[i]; |
| 460 result[i] = typeVariableToIr(type.element); |
| 461 } |
| 462 return result; |
| 463 } |
| 464 |
| 465 ir.TreeNode elementToIr(Element element) { |
| 466 if (element.isLibrary) return libraryToIr(element); |
| 467 if (element.isClass) return classToIr(element); |
| 468 if (element.isFunction || element.isAccessor) return functionToIr(element); |
| 469 if (element.isField) return fieldToIr(element); |
| 470 throw "unhandled element: $element"; |
| 471 } |
| 472 |
| 473 void debugMessage(Spannable spannable, String message) { |
| 474 compiler.reporter |
| 475 .reportHintMessage(spannable, MessageKind.GENERIC, {'text': message}); |
| 476 } |
| 477 |
| 478 void internalError(Spannable spannable, String message) { |
| 479 compiler.reporter.internalError(spannable, message); |
| 480 throw message; |
| 481 } |
| 482 |
| 483 ConstructorTarget computeEffectiveTarget( |
| 484 ConstructorElement constructor, DartType type) { |
| 485 constructor = constructor.implementation; |
| 486 Set<ConstructorElement> seen = new Set<ConstructorElement>(); |
| 487 functionToIr(constructor); |
| 488 while (constructor != constructor.effectiveTarget) { |
| 489 type = constructor.computeEffectiveTargetType(type); |
| 490 if (constructor.isGenerativeConstructor) break; |
| 491 if (!seen.add(constructor)) break; |
| 492 constructor = constructor.effectiveTarget.implementation; |
| 493 if (isSyntheticError(constructor)) break; |
| 494 functionToIr(constructor); |
| 495 } |
| 496 return new ConstructorTarget(constructor, type); |
| 497 } |
| 498 |
| 499 /// Returns true if [element] is synthesized to recover or represent a |
| 500 /// semantic error, for example, missing, duplicated, or ambiguous elements. |
| 501 /// However, returns false for elements that have an unrecoverable syntax |
| 502 /// error. Both kinds of element will return true from [Element.isMalformed], |
| 503 /// but they must be handled differently. For example, a static call to |
| 504 /// synthetic error element should be compiled to [ir.InvalidExpression], |
| 505 /// whereas a static call to a method which has a syntax error should be |
| 506 /// compiled to a static call to the method. The method itself will have a |
| 507 /// method body that is [ir.InvalidStatement]. |
| 508 bool isSyntheticError(Element element) { |
| 509 if (element.isAmbiguous) return true; |
| 510 if (element.isError) return true; |
| 511 if (element.isField && element is ErroneousFieldElementX) { |
| 512 return true; |
| 513 } |
| 514 return false; |
| 515 } |
| 516 |
| 517 ir.Procedure getDartCoreMethod(String name) { |
| 518 LibraryElement library = |
| 519 compiler.libraryLoader.lookupLibrary(Uri.parse("dart:core")); |
| 520 Element function = library.implementation.localLookup(name); |
| 521 return functionToIr(function); |
| 522 } |
| 523 |
| 524 ir.Procedure getMalformedTypeErrorBuilder() { |
| 525 return getDartCoreMethod('_malformedTypeError'); |
| 526 } |
| 527 |
| 528 ir.Procedure getUnresolvedConstructorBuilder() { |
| 529 return getDartCoreMethod('_unresolvedConstructorError'); |
| 530 } |
| 531 |
| 532 ir.Procedure getUnresolvedStaticGetterBuilder() { |
| 533 return getDartCoreMethod('_unresolvedStaticGetterError'); |
| 534 } |
| 535 |
| 536 ir.Procedure getUnresolvedStaticSetterBuilder() { |
| 537 return getDartCoreMethod('_unresolvedStaticSetterError'); |
| 538 } |
| 539 |
| 540 ir.Procedure getUnresolvedStaticMethodBuilder() { |
| 541 return getDartCoreMethod('_unresolvedStaticMethodError'); |
| 542 } |
| 543 |
| 544 ir.Procedure getUnresolvedTopLevelGetterBuilder() { |
| 545 return getDartCoreMethod('_unresolvedTopLevelGetterError'); |
| 546 } |
| 547 |
| 548 ir.Procedure getUnresolvedTopLevelSetterBuilder() { |
| 549 return getDartCoreMethod('_unresolvedTopLevelSetterError'); |
| 550 } |
| 551 |
| 552 ir.Procedure getUnresolvedTopLevelMethodBuilder() { |
| 553 return getDartCoreMethod('_unresolvedTopLevelMethodError'); |
| 554 } |
| 555 |
| 556 ir.Procedure getUnresolvedSuperGetterBuilder() { |
| 557 return getDartCoreMethod('_unresolvedSuperGetterError'); |
| 558 } |
| 559 |
| 560 ir.Procedure getUnresolvedSuperSetterBuilder() { |
| 561 return getDartCoreMethod('_unresolvedSuperSetterError'); |
| 562 } |
| 563 |
| 564 ir.Procedure getUnresolvedSuperMethodBuilder() { |
| 565 return getDartCoreMethod('_unresolvedSuperMethodError'); |
| 566 } |
| 567 |
| 568 ir.Procedure getGenericNoSuchMethodBuilder() { |
| 569 return getDartCoreMethod('_genericNoSuchMethod'); |
| 570 } |
| 571 |
| 572 ir.Procedure getFallThroughErrorBuilder() { |
| 573 return getDartCoreMethod('_fallThroughError'); |
| 574 } |
| 575 } |
| 576 |
| 577 class ConstructorTarget { |
| 578 final ConstructorElement element; |
| 579 final DartType type; |
| 580 |
| 581 ConstructorTarget(this.element, this.type); |
| 582 |
| 583 String toString() => "ConstructorTarget($element, $type)"; |
| 584 } |
OLD | NEW |