| 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 | 8 |
| 9 String name; | 9 String name; |
| 10 Type type; | 10 Type type; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 // To match VM, detect cases where value was not actually specified in | 25 // To match VM, detect cases where value was not actually specified in |
| 26 // code and don't signal errors. | 26 // code and don't signal errors. |
| 27 // TODO(jimhug): Clean up after issue #352 is resolved. | 27 // TODO(jimhug): Clean up after issue #352 is resolved. |
| 28 if (definition.value is NullExpression && | 28 if (definition.value is NullExpression && |
| 29 definition.value.span.start == definition.span.start) { | 29 definition.value.span.start == definition.span.start) { |
| 30 return; | 30 return; |
| 31 } | 31 } |
| 32 if (method.isAbstract) { | 32 if (method.isAbstract) { |
| 33 world.error('default value not allowed on abstract methods', | 33 world.error('default value not allowed on abstract methods', |
| 34 definition.span); | 34 definition.span); |
| 35 } else if (!inType.isClass) { | |
| 36 world.error('default value not allowed on interface methods', | |
| 37 definition.span); | |
| 38 } else if (method.name == '\$call' && method.definition.body == null) { | 35 } else if (method.name == '\$call' && method.definition.body == null) { |
| 39 // TODO(jimhug): Need simpler way to detect "true" function types vs. | 36 // TODO(jimhug): Need simpler way to detect "true" function types vs. |
| 40 // regular methods being used as function types for closures. | 37 // regular methods being used as function types for closures. |
| 41 world.error('default value not allowed on function type', | 38 world.error('default value not allowed on function type', |
| 42 definition.span); | 39 definition.span); |
| 43 } | 40 } |
| 44 } | 41 } |
| 45 } | 42 } |
| 46 | 43 |
| 47 genValue(MethodMember method, MethodGenerator context) { | 44 genValue(MethodMember method, MethodGenerator context) { |
| (...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 | 1149 |
| 1153 return target.invokeSpecial(jsname, args, returnType); | 1150 return target.invokeSpecial(jsname, args, returnType); |
| 1154 } | 1151 } |
| 1155 | 1152 |
| 1156 | 1153 |
| 1157 resolve(Type inType) { | 1154 resolve(Type inType) { |
| 1158 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve | 1155 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve |
| 1159 isStatic = inType.isTop; | 1156 isStatic = inType.isTop; |
| 1160 isConst = false; | 1157 isConst = false; |
| 1161 isFactory = false; | 1158 isFactory = false; |
| 1162 isAbstract = false; | 1159 isAbstract = !declaringType.isClass; |
| 1163 if (definition.modifiers != null) { | 1160 if (definition.modifiers != null) { |
| 1164 for (var mod in definition.modifiers) { | 1161 for (var mod in definition.modifiers) { |
| 1165 if (mod.kind == TokenKind.STATIC) { | 1162 if (mod.kind == TokenKind.STATIC) { |
| 1166 if (isStatic) { | 1163 if (isStatic) { |
| 1167 world.error('duplicate static modifier', mod.span); | 1164 world.error('duplicate static modifier', mod.span); |
| 1168 } | 1165 } |
| 1169 isStatic = true; | 1166 isStatic = true; |
| 1170 } else if (isConstructor && mod.kind == TokenKind.CONST) { | 1167 } else if (isConstructor && mod.kind == TokenKind.CONST) { |
| 1171 if (isConst) { | 1168 if (isConst) { |
| 1172 world.error('duplicate const modifier', mod.span); | 1169 world.error('duplicate const modifier', mod.span); |
| 1173 } | 1170 } |
| 1174 isConst = true; | 1171 isConst = true; |
| 1175 } else if (mod.kind == TokenKind.FACTORY) { | 1172 } else if (mod.kind == TokenKind.FACTORY) { |
| 1176 if (isFactory) { | 1173 if (isFactory) { |
| 1177 world.error('duplicate factory modifier', mod.span); | 1174 world.error('duplicate factory modifier', mod.span); |
| 1178 } | 1175 } |
| 1179 isFactory = true; | 1176 isFactory = true; |
| 1180 } else if (mod.kind == TokenKind.ABSTRACT) { | 1177 } else if (mod.kind == TokenKind.ABSTRACT) { |
| 1181 if (isAbstract) { | 1178 if (isAbstract) { |
| 1182 world.error('duplicate abstract modifier', mod.span); | 1179 if (declaringType.isClass) { |
| 1180 world.error('duplicate abstract modifier', mod.span); |
| 1181 } else { |
| 1182 world.error('abstract modifier not allowed on interface members', |
| 1183 mod.span); |
| 1184 } |
| 1183 } | 1185 } |
| 1184 isAbstract = true; | 1186 isAbstract = true; |
| 1185 } else { | 1187 } else { |
| 1186 world.error('${mod} modifier not allowed on method', mod.span); | 1188 world.error('${mod} modifier not allowed on method', mod.span); |
| 1187 } | 1189 } |
| 1188 } | 1190 } |
| 1189 } | 1191 } |
| 1190 | 1192 |
| 1191 if (isFactory) { | 1193 if (isFactory) { |
| 1192 isStatic = true; | 1194 isStatic = true; |
| 1193 } | 1195 } |
| 1194 | 1196 |
| 1195 if (isAbstract) { | 1197 if (isAbstract) { |
| 1196 if (definition.body != null) { | 1198 if (definition.body != null && |
| 1199 declaringType.definition is! FunctionTypeDefinition) { |
| 1200 // TODO(jimhug): Creating function types for concrete methods is |
| 1201 // steadily feeling uglier... |
| 1197 world.error('abstract method can not have a body', | 1202 world.error('abstract method can not have a body', |
| 1198 definition.body.span); | 1203 definition.body.span); |
| 1199 } | 1204 } |
| 1200 if (isStatic) { | 1205 if (isStatic && |
| 1206 declaringType.definition is! FunctionTypeDefinition) { |
| 1201 world.error('static method can not be abstract', definition.span); | 1207 world.error('static method can not be abstract', definition.span); |
| 1202 } | 1208 } |
| 1203 } else { | 1209 } else { |
| 1204 // TODO(jimhug): proper checks for bodies on non-interfaces | 1210 if (definition.body == null && !isConstructor) { |
| 1211 world.error('method needs a body', span); |
| 1212 } |
| 1205 } | 1213 } |
| 1206 | 1214 |
| 1207 if (isConstructor) { | 1215 if (isConstructor) { |
| 1208 returnType = declaringType; | 1216 returnType = declaringType; |
| 1209 } else { | 1217 } else { |
| 1210 // TODO(jimhug): Unify this check and the below with method's | 1218 // TODO(jimhug): Unify this check and the below with method's |
| 1211 // resolveType method - requires cleaning up inType stuff. | 1219 // resolveType method - requires cleaning up inType stuff. |
| 1212 returnType = inType.resolveType(definition.returnType, false); | 1220 returnType = inType.resolveType(definition.returnType, false); |
| 1213 | 1221 |
| 1214 if (isStatic && returnType.hasTypeParams) { | 1222 if (isStatic && returnType.hasTypeParams) { |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1497 } | 1505 } |
| 1498 | 1506 |
| 1499 void forEach(void f(Member member)) { | 1507 void forEach(void f(Member member)) { |
| 1500 factories.forEach((_, Map constructors) { | 1508 factories.forEach((_, Map constructors) { |
| 1501 constructors.forEach((_, Member member) { | 1509 constructors.forEach((_, Member member) { |
| 1502 f(member); | 1510 f(member); |
| 1503 }); | 1511 }); |
| 1504 }); | 1512 }); |
| 1505 } | 1513 } |
| 1506 } | 1514 } |
| OLD | NEW |