OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** A formal parameter to a [Method]. */ | 5 /** A formal parameter to a [Method]. */ |
6 class Parameter { | 6 class Parameter { |
7 FormalNode definition; | 7 FormalNode definition; |
| 8 Member method; |
8 | 9 |
9 String name; | 10 String name; |
10 Type type; | 11 Type type; |
11 bool isInitializer = false; | 12 bool isInitializer = false; |
12 | 13 |
13 Value value; | 14 Value value; |
14 | 15 |
15 Parameter(this.definition); | 16 Parameter(this.definition, this.method); |
16 | 17 |
17 resolve(Member method, Type inType) { | 18 resolve() { |
18 name = definition.name.name; | 19 name = definition.name.name; |
19 if (name.startsWith('this.')) { | 20 if (name.startsWith('this.')) { |
20 name = name.substring(5); | 21 name = name.substring(5); |
21 isInitializer = true; | 22 isInitializer = true; |
22 } | 23 } |
23 | 24 |
24 type = inType.resolveType(definition.type, false); | 25 type = method.resolveType(definition.type, false); |
25 | 26 |
26 if (method.isStatic && type.hasTypeParams) { | 27 if (method.isStatic && method.typeParameters === null && type.hasTypeParams)
{ |
27 world.error('using type parameter in static context', definition.span); | 28 world.error('using type parameter in static context', definition.span); |
28 } | 29 } |
29 | 30 |
30 if (definition.value != null) { | 31 if (definition.value != null) { |
31 // To match VM, detect cases where value was not actually specified in | 32 // To match VM, detect cases where value was not actually specified in |
32 // code and don't signal errors. | 33 // code and don't signal errors. |
33 // TODO(jimhug): Clean up after issue #352 is resolved. | 34 // TODO(jimhug): Clean up after issue #352 is resolved. |
34 if (definition.value is NullExpression && | 35 if (definition.value is NullExpression && |
35 definition.value.span.start == definition.span.start) { | 36 definition.value.span.start == definition.span.start) { |
36 return; | 37 return; |
(...skipping 18 matching lines...) Expand all Loading... |
55 genValue(MethodMember method, MethodGenerator context) { | 56 genValue(MethodMember method, MethodGenerator context) { |
56 if (definition.value == null || value != null) return; | 57 if (definition.value == null || value != null) return; |
57 | 58 |
58 if (context == null) { // interface method | 59 if (context == null) { // interface method |
59 context = new MethodGenerator(method, null); | 60 context = new MethodGenerator(method, null); |
60 } | 61 } |
61 value = definition.value.visit(context); | 62 value = definition.value.visit(context); |
62 value = value.convertTo(context, type, definition.value); | 63 value = value.convertTo(context, type, definition.value); |
63 } | 64 } |
64 | 65 |
65 Parameter copyWithNewType(Type newType) { | 66 Parameter copyWithNewType(Member newMethod, Type newType) { |
66 var ret = new Parameter(definition); | 67 var ret = new Parameter(definition, newMethod); |
67 ret.type = newType; | 68 ret.type = newType; |
68 ret.name = name; | 69 ret.name = name; |
69 ret.isInitializer = isInitializer; | 70 ret.isInitializer = isInitializer; |
70 return ret; | 71 return ret; |
71 } | 72 } |
72 | 73 |
73 bool get isOptional() => definition != null && definition.value != null; | 74 bool get isOptional() => definition != null && definition.value != null; |
74 } | 75 } |
75 | 76 |
76 | 77 |
77 interface Named { | 78 class Member extends Element { |
78 String get name(); | |
79 Library get library(); | |
80 bool get isNative(); | |
81 String get jsname(); | |
82 set jsname(String name); | |
83 | |
84 SourceSpan get span(); | |
85 } | |
86 | |
87 class Member implements Named { | |
88 final String name; | |
89 final Type declaringType; | 79 final Type declaringType; |
90 | 80 |
91 String _jsname; | |
92 | |
93 bool isGenerated; | 81 bool isGenerated; |
94 MethodGenerator generator; | 82 MethodGenerator generator; |
95 | 83 |
96 Member(this.name, this.declaringType): isGenerated = false; | 84 Member(String name, Type declaringType) |
97 | 85 : isGenerated = false, this.declaringType = declaringType, |
98 abstract SourceSpan get span(); | 86 super(name, declaringType); |
99 | 87 |
100 abstract bool get isStatic(); | 88 abstract bool get isStatic(); |
101 abstract Type get returnType(); | 89 abstract Type get returnType(); |
102 | 90 |
103 abstract bool get canGet(); | 91 abstract bool get canGet(); |
104 abstract bool get canSet(); | 92 abstract bool get canSet(); |
105 | 93 |
106 abstract void resolve(Type inType); | |
107 | |
108 String get jsname() => _jsname == null ? name : _jsname; | |
109 | |
110 set jsname(String name) => _jsname = name; | |
111 | |
112 Library get library() => declaringType.library; | 94 Library get library() => declaringType.library; |
113 | 95 |
114 bool get isPrivate() => name.startsWith('_'); | 96 bool get isPrivate() => name.startsWith('_'); |
115 | 97 |
116 bool get isConstructor() => false; | 98 bool get isConstructor() => false; |
117 bool get isField() => false; | 99 bool get isField() => false; |
118 bool get isMethod() => false; | 100 bool get isMethod() => false; |
119 bool get isProperty() => false; | 101 bool get isProperty() => false; |
120 bool get isAbstract() => false; | 102 bool get isAbstract() => false; |
121 | 103 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 String get generatedFactoryName() { | 186 String get generatedFactoryName() { |
205 assert(this.isFactory); | 187 assert(this.isFactory); |
206 String prefix = '${declaringType.jsname}.${constructorName}\$'; | 188 String prefix = '${declaringType.jsname}.${constructorName}\$'; |
207 if (name == '') { | 189 if (name == '') { |
208 return '${prefix}factory'; | 190 return '${prefix}factory'; |
209 } else { | 191 } else { |
210 return '${prefix}$name\$factory'; | 192 return '${prefix}$name\$factory'; |
211 } | 193 } |
212 } | 194 } |
213 | 195 |
214 Type resolveType(TypeReference node, bool isRequired) { | |
215 var type = declaringType.resolveType(node, isRequired); | |
216 if (isStatic && type.hasTypeParams) { | |
217 // TODO(jimhug): Is this really so hard? | |
218 world.error('using type parameter in static context', | |
219 node.span); | |
220 } | |
221 return type; | |
222 } | |
223 | |
224 int hashCode() => (declaringType.hashCode() << 4) ^ name.hashCode(); | 196 int hashCode() => (declaringType.hashCode() << 4) ^ name.hashCode(); |
225 } | 197 } |
226 | 198 |
227 | 199 |
228 /** | 200 /** |
229 * Types are treated as first class members of their library's top type. | 201 * Types are treated as first class members of their library's top type. |
230 */ | 202 */ |
231 // TODO(jmesserly): perhaps Type should extend Member, but that can get | 203 // TODO(jmesserly): perhaps Type should extend Member, but that can get |
232 // complicated. | 204 // complicated. |
233 class TypeMember extends Member { | 205 class TypeMember extends Member { |
234 final DefinedType type; | 206 final DefinedType type; |
235 | 207 |
236 TypeMember(DefinedType type) | 208 TypeMember(DefinedType type) |
237 : super(type.name, type.library.topType), | 209 : super(type.name, type.library.topType), |
238 this.type = type; | 210 this.type = type; |
239 | 211 |
240 SourceSpan get span() => type.definition.span; | 212 SourceSpan get span() => type.definition.span; |
241 | 213 |
242 bool get isStatic() => true; | 214 bool get isStatic() => true; |
243 | 215 |
244 // If this really becomes first class, this should return typeof(Type) | 216 // If this really becomes first class, this should return typeof(Type) |
245 Type get returnType() => world.varType; | 217 Type get returnType() => world.varType; |
246 | 218 |
247 bool canInvoke(MethodGenerator context, Arguments args) => false; | 219 bool canInvoke(MethodGenerator context, Arguments args) => false; |
248 bool get canGet() => true; | 220 bool get canGet() => true; |
249 bool get canSet() => false; | 221 bool get canSet() => false; |
250 | 222 |
251 void resolve(Type inType) {} | |
252 | |
253 Value _get(MethodGenerator context, Node node, Value target, | 223 Value _get(MethodGenerator context, Node node, Value target, |
254 [bool isDynamic=false]) { | 224 [bool isDynamic=false]) { |
255 return new Value.type(type, node.span); | 225 return new Value.type(type, node.span); |
256 } | 226 } |
257 | 227 |
258 Value _set(MethodGenerator context, Node node, Value target, Value value, | 228 Value _set(MethodGenerator context, Node node, Value target, Value value, |
259 [bool isDynamic=false]) { | 229 [bool isDynamic=false]) { |
260 world.error('cannot set type', node.span); | 230 world.error('cannot set type', node.span); |
261 } | 231 } |
262 | 232 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 | 290 |
321 SourceSpan get span() => definition == null ? null : definition.span; | 291 SourceSpan get span() => definition == null ? null : definition.span; |
322 | 292 |
323 Type get returnType() => type; | 293 Type get returnType() => type; |
324 | 294 |
325 bool get canGet() => true; | 295 bool get canGet() => true; |
326 bool get canSet() => !isFinal; | 296 bool get canSet() => !isFinal; |
327 | 297 |
328 bool get isField() => true; | 298 bool get isField() => true; |
329 | 299 |
330 resolve(Type inType) { | 300 resolve() { |
331 isStatic = declaringType.isTop; | 301 isStatic = declaringType.isTop; |
332 isFinal = false; | 302 isFinal = false; |
333 if (definition.modifiers != null) { | 303 if (definition.modifiers != null) { |
334 for (var mod in definition.modifiers) { | 304 for (var mod in definition.modifiers) { |
335 if (mod.kind == TokenKind.STATIC) { | 305 if (mod.kind == TokenKind.STATIC) { |
336 if (isStatic) { | 306 if (isStatic) { |
337 world.error('duplicate static modifier', mod.span); | 307 world.error('duplicate static modifier', mod.span); |
338 } | 308 } |
339 isStatic = true; | 309 isStatic = true; |
340 } else if (mod.kind == TokenKind.FINAL) { | 310 } else if (mod.kind == TokenKind.FINAL) { |
341 if (isFinal) { | 311 if (isFinal) { |
342 world.error('duplicate final modifier', mod.span); | 312 world.error('duplicate final modifier', mod.span); |
343 } | 313 } |
344 isFinal = true; | 314 isFinal = true; |
345 } else { | 315 } else { |
346 world.error('${mod} modifier not allowed on field', mod.span); | 316 world.error('${mod} modifier not allowed on field', mod.span); |
347 } | 317 } |
348 } | 318 } |
349 } | 319 } |
350 type = inType.resolveType(definition.type, false); | 320 type = resolveType(definition.type, false); |
351 if (isStatic && type.hasTypeParams) { | 321 if (isStatic && type.hasTypeParams) { |
352 world.error('using type parameter in static context', | 322 world.error('using type parameter in static context', |
353 definition.type.span); | 323 definition.type.span); |
354 } | 324 } |
355 | 325 |
356 if (isStatic && isFinal && value == null) { | 326 if (isStatic && isFinal && value == null) { |
357 world.error('static final field is missing initializer', span); | 327 world.error('static final field is missing initializer', span); |
358 } | 328 } |
359 | 329 |
360 library._addMember(this); | 330 library._addMember(this); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 ConcreteMember c = parentMember; | 497 ConcreteMember c = parentMember; |
528 parent = c.baseMember; | 498 parent = c.baseMember; |
529 } else { | 499 } else { |
530 parent = parentMember; | 500 parent = parentMember; |
531 } | 501 } |
532 | 502 |
533 if (getter == null) getter = parent.getter; | 503 if (getter == null) getter = parent.getter; |
534 if (setter == null) setter = parent.setter; | 504 if (setter == null) setter = parent.setter; |
535 } | 505 } |
536 | 506 |
537 resolve(Type inType) { | 507 resolve() { |
538 if (getter != null) getter.resolve(inType); | 508 if (getter != null) getter.resolve(); |
539 if (setter != null) setter.resolve(inType); | 509 if (setter != null) setter.resolve(); |
540 | 510 |
541 library._addMember(this); | 511 library._addMember(this); |
542 } | 512 } |
543 } | 513 } |
544 | 514 |
545 | 515 |
546 class ConcreteMember extends Member { | 516 class ConcreteMember extends Member { |
547 final Member baseMember; | 517 final Member baseMember; |
548 Type returnType; | 518 Type returnType; |
549 List<Parameter> parameters; | 519 List<Parameter> parameters; |
550 | 520 |
551 ConcreteMember(String name, ConcreteType declaringType, this.baseMember) | 521 ConcreteMember(String name, ConcreteType declaringType, this.baseMember) |
552 : super(name, declaringType) { | 522 : super(name, declaringType) { |
553 parameters = []; | 523 parameters = []; |
554 returnType = baseMember.returnType.resolveTypeParams(declaringType); | 524 returnType = baseMember.returnType.resolveTypeParams(declaringType); |
555 // TODO(jimhug): Optimize not creating new array if new param types. | 525 // TODO(jimhug): Optimize not creating new array if no new param types. |
556 for (var p in baseMember.parameters) { | 526 for (var p in baseMember.parameters) { |
557 var newType = p.type.resolveTypeParams(declaringType); | 527 var newType = p.type.resolveTypeParams(declaringType); |
558 if (newType != p.type) { | 528 if (newType != p.type) { |
559 parameters.add(p.copyWithNewType(newType)); | 529 parameters.add(p.copyWithNewType(this, newType)); |
560 } else { | 530 } else { |
561 parameters.add(p); | 531 parameters.add(p); |
562 } | 532 } |
563 } | 533 } |
564 } | 534 } |
565 | 535 |
566 SourceSpan get span() => baseMember.span; | 536 SourceSpan get span() => baseMember.span; |
567 | 537 |
568 bool get isStatic() => baseMember.isStatic; | 538 bool get isStatic() => baseMember.isStatic; |
569 bool get isAbstract() => baseMember.isAbstract; | 539 bool get isAbstract() => baseMember.isAbstract; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 } | 611 } |
642 } | 612 } |
643 | 613 |
644 | 614 |
645 /** Represents a Dart method or top-level function. */ | 615 /** Represents a Dart method or top-level function. */ |
646 class MethodMember extends Member { | 616 class MethodMember extends Member { |
647 FunctionDefinition definition; | 617 FunctionDefinition definition; |
648 Type returnType; | 618 Type returnType; |
649 List<Parameter> parameters; | 619 List<Parameter> parameters; |
650 | 620 |
| 621 // Could support generic methods in general. Right now only used for |
| 622 // strange corner case of factory methods for generic types. |
| 623 List<ParameterType> typeParameters; |
| 624 |
651 | 625 |
652 Type _functionType; | 626 Type _functionType; |
653 bool isStatic = false; | 627 bool isStatic = false; |
654 bool isAbstract = false; | 628 bool isAbstract = false; |
655 | 629 |
656 // Note: these two modifiers are only legal on constructors | 630 // Note: these two modifiers are only legal on constructors |
657 bool isConst = false; | 631 bool isConst = false; |
658 bool isFactory = false; | 632 bool isFactory = false; |
659 | 633 |
660 /** True if this is a function defined inside another method. */ | 634 /** True if this is a function defined inside another method. */ |
(...skipping 21 matching lines...) Expand all Loading... |
682 bool get isMethod() => !isConstructor; | 656 bool get isMethod() => !isConstructor; |
683 | 657 |
684 bool get isNative() => definition.body is NativeStatement; | 658 bool get isNative() => definition.body is NativeStatement; |
685 | 659 |
686 bool get canGet() => false; // TODO(jimhug): get bound method support. | 660 bool get canGet() => false; // TODO(jimhug): get bound method support. |
687 bool get canSet() => false; | 661 bool get canSet() => false; |
688 | 662 |
689 SourceSpan get span() => definition == null ? null : definition.span; | 663 SourceSpan get span() => definition == null ? null : definition.span; |
690 | 664 |
691 String get constructorName() { | 665 String get constructorName() { |
692 NameTypeReference returnType = definition.returnType; | 666 var returnType = definition.returnType; |
693 if (returnType == null) return ''; | 667 if (returnType == null) return ''; |
| 668 if (returnType is GenericTypeReference) { |
| 669 return ''; |
| 670 } |
694 | 671 |
695 // TODO(jmesserly): make this easier? | 672 // TODO(jmesserly): make this easier? |
696 if (returnType.names != null) { | 673 if (returnType.names != null) { |
697 return returnType.names[0].name; | 674 return returnType.names[0].name; |
698 } else if (returnType.name != null) { | 675 } else if (returnType.name != null) { |
699 return returnType.name.name; | 676 return returnType.name.name; |
700 } | 677 } |
701 world.internalError('no valid constructor name', definition.span); | 678 world.internalError('no valid constructor name', definition.span); |
702 } | 679 } |
703 | 680 |
704 Type get functionType() { | 681 Type get functionType() { |
705 if (_functionType == null) { | 682 if (_functionType == null) { |
706 _functionType = library.getOrAddFunctionType(name, | 683 _functionType = library.getOrAddFunctionType(declaringType, name, definiti
on); |
707 definition, declaringType); | |
708 // TODO(jimhug): Better resolution checks. | 684 // TODO(jimhug): Better resolution checks. |
709 if (parameters == null) { | 685 if (parameters == null) { |
710 resolve(declaringType); | 686 resolve(); |
711 } | 687 } |
712 } | 688 } |
713 return _functionType; | 689 return _functionType; |
714 } | 690 } |
715 | 691 |
716 bool override(Member other) { | 692 bool override(Member other) { |
717 if (!super.override(other)) return false; | 693 if (!super.override(other)) return false; |
718 | 694 |
719 // methods can only override other methods | 695 // methods can only override other methods |
720 if (other.isMethod) { | 696 if (other.isMethod) { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 | 829 |
854 /** | 830 /** |
855 * Invokes this method on the given [target] with the given [args]. | 831 * Invokes this method on the given [target] with the given [args]. |
856 * [node] provides a [SourceSpan] for any error messages. | 832 * [node] provides a [SourceSpan] for any error messages. |
857 */ | 833 */ |
858 Value invoke(MethodGenerator context, Node node, Value target, | 834 Value invoke(MethodGenerator context, Node node, Value target, |
859 Arguments args, [bool isDynamic=false]) { | 835 Arguments args, [bool isDynamic=false]) { |
860 // TODO(jimhug): Fix this hack for ensuring a method is resolved. | 836 // TODO(jimhug): Fix this hack for ensuring a method is resolved. |
861 if (parameters == null) { | 837 if (parameters == null) { |
862 world.info('surprised to need to resolve: ${declaringType.name}.$name'); | 838 world.info('surprised to need to resolve: ${declaringType.name}.$name'); |
863 this.resolve(declaringType); | 839 resolve(); |
864 } | 840 } |
865 | 841 |
866 declaringType.genMethod(this); | 842 declaringType.genMethod(this); |
867 | 843 |
868 if (isStatic || isFactory) { | 844 if (isStatic || isFactory) { |
869 // TODO(sigmund): can we avoid generating the entire type, but only what | 845 // TODO(sigmund): can we avoid generating the entire type, but only what |
870 // we need? | 846 // we need? |
871 declaringType.markUsed(); | 847 declaringType.markUsed(); |
872 } | 848 } |
873 | 849 |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1208 var value = '${val0}${val1}'; | 1184 var value = '${val0}${val1}'; |
1209 value = '"' + value.replaceAll('"', '\\"') + '"'; | 1185 value = '"' + value.replaceAll('"', '\\"') + '"'; |
1210 return new EvaluatedValue(world.stringType, value, value, node.span); | 1186 return new EvaluatedValue(world.stringType, value, value, node.span); |
1211 } | 1187 } |
1212 | 1188 |
1213 // Ensure we generate toString on the right side | 1189 // Ensure we generate toString on the right side |
1214 args.values[0].invoke(context, 'toString', node, Arguments.EMPTY); | 1190 args.values[0].invoke(context, 'toString', node, Arguments.EMPTY); |
1215 return new Value(declaringType, '${target.code} + ${argsCode[0]}', | 1191 return new Value(declaringType, '${target.code} + ${argsCode[0]}', |
1216 node.span); | 1192 node.span); |
1217 } | 1193 } |
1218 } else if (declaringType.isNativeType) { | 1194 } else if (declaringType.isNative) { |
1219 if (name == '\$index') { | 1195 if (name == '\$index') { |
1220 // Note: this could technically propagate constness, but that's not | 1196 // Note: this could technically propagate constness, but that's not |
1221 // specified explicitly and the VM doesn't do that. | 1197 // specified explicitly and the VM doesn't do that. |
1222 return new Value(returnType, '${target.code}[${argsCode[0]}]', node.span
); | 1198 return new Value(returnType, '${target.code}[${argsCode[0]}]', node.span
); |
1223 } else if (name == '\$setindex') { | 1199 } else if (name == '\$setindex') { |
1224 return new Value(returnType, | 1200 return new Value(returnType, |
1225 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span); | 1201 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span); |
1226 } | 1202 } |
1227 } | 1203 } |
1228 | 1204 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1267 world.gen.corejs.useSetIndex = true; | 1243 world.gen.corejs.useSetIndex = true; |
1268 } | 1244 } |
1269 | 1245 |
1270 // Fall back to normal method invocation. | 1246 // Fall back to normal method invocation. |
1271 var argsString = Strings.join(argsCode, ', '); | 1247 var argsString = Strings.join(argsCode, ', '); |
1272 return new Value(inferredResult, '${target.code}.$jsname($argsString)', | 1248 return new Value(inferredResult, '${target.code}.$jsname($argsString)', |
1273 node.span); | 1249 node.span); |
1274 } | 1250 } |
1275 | 1251 |
1276 | 1252 |
1277 resolve(Type inType) { | 1253 resolve() { |
1278 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve | 1254 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve |
1279 isStatic = inType.isTop; | 1255 isStatic = declaringType.isTop; |
1280 isConst = false; | 1256 isConst = false; |
1281 isFactory = false; | 1257 isFactory = false; |
1282 isAbstract = !declaringType.isClass; | 1258 isAbstract = !declaringType.isClass; |
1283 if (definition.modifiers != null) { | 1259 if (definition.modifiers != null) { |
1284 for (var mod in definition.modifiers) { | 1260 for (var mod in definition.modifiers) { |
1285 if (mod.kind == TokenKind.STATIC) { | 1261 if (mod.kind == TokenKind.STATIC) { |
1286 if (isStatic) { | 1262 if (isStatic) { |
1287 world.error('duplicate static modifier', mod.span); | 1263 world.error('duplicate static modifier', mod.span); |
1288 } | 1264 } |
1289 isStatic = true; | 1265 isStatic = true; |
(...skipping 20 matching lines...) Expand all Loading... |
1310 } else { | 1286 } else { |
1311 world.error('${mod} modifier not allowed on method', mod.span); | 1287 world.error('${mod} modifier not allowed on method', mod.span); |
1312 } | 1288 } |
1313 } | 1289 } |
1314 } | 1290 } |
1315 | 1291 |
1316 if (isFactory) { | 1292 if (isFactory) { |
1317 isStatic = true; | 1293 isStatic = true; |
1318 } | 1294 } |
1319 | 1295 |
| 1296 if (definition.typeParameters != null) { |
| 1297 if (!isFactory) { |
| 1298 world.error( |
| 1299 'Only factories are allowed to have explicit type parameters', |
| 1300 definition.typeParameters[0].span); |
| 1301 } else { |
| 1302 typeParameters = definition.typeParameters; |
| 1303 for (var tp in definition.typeParameters) { |
| 1304 tp.enclosingElement = this; |
| 1305 tp.resolve(); |
| 1306 } |
| 1307 } |
| 1308 } |
| 1309 |
1320 // TODO(jimhug): need a better annotation for being an operator method | 1310 // TODO(jimhug): need a better annotation for being an operator method |
1321 if (isOperator && isStatic && !isCallMethod) { | 1311 if (isOperator && isStatic && !isCallMethod) { |
1322 world.error('operator method may not be static "${name}"', span); | 1312 world.error('operator method may not be static "${name}"', span); |
1323 } | 1313 } |
1324 | 1314 |
1325 if (isAbstract) { | 1315 if (isAbstract) { |
1326 if (definition.body != null && | 1316 if (definition.body != null && |
1327 declaringType.definition is! FunctionTypeDefinition) { | 1317 declaringType.definition is! FunctionTypeDefinition) { |
1328 // TODO(jimhug): Creating function types for concrete methods is | 1318 // TODO(jimhug): Creating function types for concrete methods is |
1329 // steadily feeling uglier... | 1319 // steadily feeling uglier... |
1330 world.error('abstract method can not have a body', span); | 1320 world.error('abstract method can not have a body', span); |
1331 } | 1321 } |
1332 if (isStatic && | 1322 if (isStatic && |
1333 declaringType.definition is! FunctionTypeDefinition) { | 1323 declaringType.definition is! FunctionTypeDefinition) { |
1334 world.error('static method can not be abstract', span); | 1324 world.error('static method can not be abstract', span); |
1335 } | 1325 } |
1336 } else { | 1326 } else { |
1337 if (definition.body == null && !isConstructor) { | 1327 if (definition.body == null && !isConstructor) { |
1338 world.error('method needs a body', span); | 1328 world.error('method needs a body', span); |
1339 } | 1329 } |
1340 } | 1330 } |
1341 | 1331 |
1342 if (isConstructor) { | 1332 if (isConstructor && !isFactory) { |
1343 returnType = declaringType; | 1333 returnType = declaringType; |
1344 } else { | 1334 } else { |
1345 // TODO(jimhug): Unify this check and the below with method's | 1335 returnType = resolveType(definition.returnType, false); |
1346 // resolveType method - requires cleaning up inType stuff. | |
1347 returnType = inType.resolveType(definition.returnType, false); | |
1348 | |
1349 if (isStatic && returnType.hasTypeParams) { | |
1350 world.error('using type parameter in static context', | |
1351 definition.returnType.span); | |
1352 } | |
1353 } | 1336 } |
1354 parameters = []; | 1337 parameters = []; |
1355 for (var formal in definition.formals) { | 1338 for (var formal in definition.formals) { |
1356 var param = new Parameter(formal); | 1339 // TODO(jimhug): Clean up construction of Parameters. |
1357 param.resolve(this, inType); | 1340 var param = new Parameter(formal, this); |
| 1341 param.resolve(); |
1358 parameters.add(param); | 1342 parameters.add(param); |
1359 } | 1343 } |
1360 | 1344 |
1361 if (!isLambda) { | 1345 if (!isLambda) { |
1362 library._addMember(this); | 1346 library._addMember(this); |
1363 } | 1347 } |
1364 } | 1348 } |
1365 | |
1366 Type findTypeVariable(TypeReference node, bool isRequired) { | |
1367 if (!this.isFactory || node is! NameTypeReference) { | |
1368 return super.resolveType(node, isRequired); | |
1369 } else { | |
1370 // TODO(ahe): We cannot find any type variables as they aren't | |
1371 // recorded. So we turn this in to a warning instead. | |
1372 return super.resolveType(node, false); | |
1373 } | |
1374 } | |
1375 | |
1376 Type resolveType(TypeReference node, bool isRequired) { | |
1377 if (node !== null && this.isFactory && isRequired) { | |
1378 if (node is GenericTypeReference) { | |
1379 // TODO(ahe): This is bascially a copy of code in | |
1380 // DefinedType.resolveType. More checks should be performed, | |
1381 // such as bounds check, but the code is structured in a way | |
1382 // that makes this hard. | |
1383 GenericTypeReference genericReference = node; | |
1384 var baseType = super.resolveType(genericReference.baseType, isRequired); | |
1385 var typeArguments = []; | |
1386 for (TypeReference ref in genericReference.typeArguments) { | |
1387 // TODO(ahe): This let us ignore T in new Foo<T>, but not in | |
1388 // new Foo<Foo<T>>. | |
1389 typeArguments.add(findTypeVariable(ref, isRequired)); | |
1390 } | |
1391 node.type = baseType.getOrMakeConcreteType(typeArguments); | |
1392 return node.type; | |
1393 } | |
1394 } | |
1395 return super.resolveType(node, isRequired); | |
1396 } | |
1397 } | 1349 } |
1398 | 1350 |
1399 | 1351 |
1400 class MemberSet { | 1352 class MemberSet { |
1401 final String name; | 1353 final String name; |
1402 final List<Member> members; | 1354 final List<Member> members; |
1403 final String jsname; | 1355 final String jsname; |
1404 final bool isVar; | 1356 final bool isVar; |
1405 | 1357 |
1406 MemberSet(Member member, [bool isVar=false]): | 1358 MemberSet(Member member, [bool isVar=false]): |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1706 } | 1658 } |
1707 | 1659 |
1708 void forEach(void f(Member member)) { | 1660 void forEach(void f(Member member)) { |
1709 factories.forEach((_, Map constructors) { | 1661 factories.forEach((_, Map constructors) { |
1710 constructors.forEach((_, Member member) { | 1662 constructors.forEach((_, Member member) { |
1711 f(member); | 1663 f(member); |
1712 }); | 1664 }); |
1713 }); | 1665 }); |
1714 } | 1666 } |
1715 } | 1667 } |
OLD | NEW |