| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 package com.google.dart.compiler.type; | 5 package com.google.dart.compiler.type; |
| 6 | 6 |
| 7 import com.google.common.annotations.VisibleForTesting; | 7 import com.google.common.annotations.VisibleForTesting; |
| 8 import com.google.common.base.Joiner; | 8 import com.google.common.base.Joiner; |
| 9 import com.google.common.base.Objects; | 9 import com.google.common.base.Objects; |
| 10 import com.google.common.collect.ArrayListMultimap; | 10 import com.google.common.collect.ArrayListMultimap; |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 return "operator " + operator.getSyntax(); | 305 return "operator " + operator.getSyntax(); |
| 306 } | 306 } |
| 307 | 307 |
| 308 private Type analyzeBinaryOperator(DartNode node, Type lhsType, Token operat
or, | 308 private Type analyzeBinaryOperator(DartNode node, Type lhsType, Token operat
or, |
| 309 DartNode diagnosticNode, DartExpression rhs) { | 309 DartNode diagnosticNode, DartExpression rhs) { |
| 310 Type rhsType = nonVoidTypeOf(rhs); | 310 Type rhsType = nonVoidTypeOf(rhs); |
| 311 String methodName = methodNameForBinaryOperator(operator); | 311 String methodName = methodNameForBinaryOperator(operator); |
| 312 HasSourceInfo problemTarget = getOperatorHasSourceInfo(node); | 312 HasSourceInfo problemTarget = getOperatorHasSourceInfo(node); |
| 313 Member member = lookupMember(lhsType, methodName, problemTarget); | 313 Member member = lookupMember(lhsType, methodName, problemTarget); |
| 314 if (member != null) { | 314 if (member != null) { |
| 315 node.setElement(member.getElement()); | 315 Element element = member.getElement(); |
| 316 node.setElement(element); |
| 316 FunctionType methodType = getMethodType(lhsType, member, methodName, dia
gnosticNode); | 317 FunctionType methodType = getMethodType(lhsType, member, methodName, dia
gnosticNode); |
| 318 checkDeprecated(problemTarget, element); |
| 317 Type returnType = checkInvocation(Collections.<DartExpression> singleton
List(rhs), | 319 Type returnType = checkInvocation(Collections.<DartExpression> singleton
List(rhs), |
| 318 diagnosticNode, methodName, methodType); | 320 diagnosticNode, methodName, methodType); |
| 319 // tweak return type for int/int and int/double operators | 321 // tweak return type for int/int and int/double operators |
| 320 { | 322 { |
| 321 boolean lhsInt = intType.equals(lhsType); | 323 boolean lhsInt = intType.equals(lhsType); |
| 322 boolean rhsInt = intType.equals(rhsType); | 324 boolean rhsInt = intType.equals(rhsType); |
| 323 boolean lhsDouble = doubleType.equals(lhsType); | 325 boolean lhsDouble = doubleType.equals(lhsType); |
| 324 boolean rhsDouble = doubleType.equals(rhsType); | 326 boolean rhsDouble = doubleType.equals(rhsType); |
| 325 switch (operator) { | 327 switch (operator) { |
| 326 case ADD: | 328 case ADD: |
| (...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 return voidType; | 1223 return voidType; |
| 1222 } | 1224 } |
| 1223 | 1225 |
| 1224 @Override | 1226 @Override |
| 1225 public Type visitBreakStatement(DartBreakStatement node) { | 1227 public Type visitBreakStatement(DartBreakStatement node) { |
| 1226 return voidType; | 1228 return voidType; |
| 1227 } | 1229 } |
| 1228 | 1230 |
| 1229 @Override | 1231 @Override |
| 1230 public Type visitFunctionObjectInvocation(DartFunctionObjectInvocation node)
{ | 1232 public Type visitFunctionObjectInvocation(DartFunctionObjectInvocation node)
{ |
| 1231 node.setElement(functionType.getElement()); | 1233 ClassElement element = functionType.getElement(); |
| 1234 node.setElement(element); |
| 1235 checkDeprecated(node, element); |
| 1232 return checkInvocation(node, node, null, typeOf(node.getTarget())); | 1236 return checkInvocation(node, node, null, typeOf(node.getTarget())); |
| 1233 } | 1237 } |
| 1234 | 1238 |
| 1235 @Override | 1239 @Override |
| 1236 public Type visitMethodInvocation(DartMethodInvocation node) { | 1240 public Type visitMethodInvocation(DartMethodInvocation node) { |
| 1237 DartIdentifier nameNode = node.getFunctionName(); | 1241 DartIdentifier nameNode = node.getFunctionName(); |
| 1238 String name = node.getFunctionNameString(); | 1242 String name = node.getFunctionNameString(); |
| 1239 Element element = node.getElement(); | 1243 Element element = node.getElement(); |
| 1240 if (element != null && (element.getModifiers().isStatic() | 1244 if (element != null && (element.getModifiers().isStatic() |
| 1241 || Elements.isTopLevel(element))) { | 1245 || Elements.isTopLevel(element))) { |
| 1242 node.setElement(element); | 1246 node.setElement(element); |
| 1247 checkDeprecated(nameNode, element); |
| 1243 return checkInvocation(node, nameNode, name, element.getType()); | 1248 return checkInvocation(node, nameNode, name, element.getType()); |
| 1244 } | 1249 } |
| 1245 DartNode target = node.getTarget(); | 1250 DartNode target = node.getTarget(); |
| 1246 Type receiver = nonVoidTypeOf(target); | 1251 Type receiver = nonVoidTypeOf(target); |
| 1247 Member member = lookupMember(receiver, name, nameNode); | 1252 Member member = lookupMember(receiver, name, nameNode); |
| 1248 if (member != null) { | 1253 if (member != null) { |
| 1249 Element methodElement = member.getElement(); | 1254 Element methodElement = member.getElement(); |
| 1250 node.setElement(methodElement); | 1255 node.setElement(methodElement); |
| 1251 if (nameNode != null) { | 1256 if (nameNode != null) { |
| 1252 nameNode.setElement(methodElement); | 1257 nameNode.setElement(methodElement); |
| 1253 } | 1258 } |
| 1254 } | 1259 } |
| 1260 checkDeprecated(nameNode, nameNode.getElement()); |
| 1255 FunctionType methodType = getMethodType(receiver, member, name, nameNode); | 1261 FunctionType methodType = getMethodType(receiver, member, name, nameNode); |
| 1256 return checkInvocation(node, nameNode, name, methodType); | 1262 return checkInvocation(node, nameNode, name, methodType); |
| 1257 } | 1263 } |
| 1258 | 1264 |
| 1259 @Override | 1265 @Override |
| 1260 public Type visitSuperConstructorInvocation(DartSuperConstructorInvocation n
ode) { | 1266 public Type visitSuperConstructorInvocation(DartSuperConstructorInvocation n
ode) { |
| 1261 return checkConstructorForwarding(node, node.getElement()); | 1267 return checkConstructorForwarding(node, node.getElement()); |
| 1262 } | 1268 } |
| 1263 | 1269 |
| 1264 private Type checkConstructorForwarding(DartInvocation node, ConstructorElem
ent element) { | 1270 private Type checkConstructorForwarding(DartInvocation node, ConstructorElem
ent element) { |
| 1265 if (element == null) { | 1271 if (element == null) { |
| 1266 visit(node.getArguments()); | 1272 visit(node.getArguments()); |
| 1267 return voidType; | 1273 return voidType; |
| 1268 } else { | 1274 } else { |
| 1269 node.setElement(element); | 1275 node.setElement(element); |
| 1276 checkDeprecated(node, element); |
| 1270 checkInvocation(node, node, null, typeAsMemberOf(element, currentClass))
; | 1277 checkInvocation(node, node, null, typeAsMemberOf(element, currentClass))
; |
| 1271 return voidType; | 1278 return voidType; |
| 1272 } | 1279 } |
| 1273 } | 1280 } |
| 1274 | 1281 |
| 1275 @Override | 1282 @Override |
| 1276 public Type visitCase(DartCase node) { | 1283 public Type visitCase(DartCase node) { |
| 1277 node.visitChildren(this); | 1284 node.visitChildren(this); |
| 1278 return voidType; | 1285 return voidType; |
| 1279 } | 1286 } |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1867 // The constructor in the interface is resolved to the type paramete
rs declared in | 1874 // The constructor in the interface is resolved to the type paramete
rs declared in |
| 1868 // the interface, but the constructor body has type parameters resol
ved to the type | 1875 // the interface, but the constructor body has type parameters resol
ved to the type |
| 1869 // parameters in the default class. This substitution patches up th
e type variable | 1876 // parameters in the default class. This substitution patches up th
e type variable |
| 1870 // references used in parameters so they match the concrete class. | 1877 // references used in parameters so they match the concrete class. |
| 1871 substParams = ((ClassElement)constructorElement.getEnclosingElement(
)).getType().getArguments(); | 1878 substParams = ((ClassElement)constructorElement.getEnclosingElement(
)).getType().getArguments(); |
| 1872 } else { | 1879 } else { |
| 1873 substParams = ifaceType.getElement().getTypeParameters(); | 1880 substParams = ifaceType.getElement().getTypeParameters(); |
| 1874 } | 1881 } |
| 1875 List<Type> arguments = ifaceType.getArguments(); | 1882 List<Type> arguments = ifaceType.getArguments(); |
| 1876 ftype = (FunctionType) ftype.subst(arguments, substParams); | 1883 ftype = (FunctionType) ftype.subst(arguments, substParams); |
| 1877 checkInvocation(node, node, null, ftype); | 1884 checkDeprecated(getConstructorNameNode(node), constructorElement); |
| 1885 checkInvocation(node, node, constructorElement.getName(), ftype); |
| 1878 } | 1886 } |
| 1879 } | 1887 } |
| 1880 type.getClass(); // quick null check | 1888 type.getClass(); // quick null check |
| 1881 return type; | 1889 return type; |
| 1882 } | 1890 } |
| 1883 | 1891 |
| 1884 /** | 1892 /** |
| 1885 * @param cls the {@link ClassElement} which has unimplemented members. | 1893 * @param cls the {@link ClassElement} which has unimplemented members. |
| 1886 * @param unimplementedMembers the unimplemented members {@link Element}s. | 1894 * @param unimplementedMembers the unimplemented members {@link Element}s. |
| 1887 * @return the {@link StringBuilder} with message about unimplemented member
s. | 1895 * @return the {@link StringBuilder} with message about unimplemented member
s. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1974 return dynamicType; | 1982 return dynamicType; |
| 1975 } | 1983 } |
| 1976 element = member.getElement(); | 1984 element = member.getElement(); |
| 1977 node.setElement(element); | 1985 node.setElement(element); |
| 1978 Modifiers modifiers = element.getModifiers(); | 1986 Modifiers modifiers = element.getModifiers(); |
| 1979 if (modifiers.isStatic()) { | 1987 if (modifiers.isStatic()) { |
| 1980 return typeError(node.getName(), | 1988 return typeError(node.getName(), |
| 1981 TypeErrorCode.STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE, | 1989 TypeErrorCode.STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE, |
| 1982 name, element.getName()); | 1990 name, element.getName()); |
| 1983 } | 1991 } |
| 1992 // @deprecated |
| 1993 if (element != null && element.getMetadata().isDeprecated()) { |
| 1994 onError(node.getName(), TypeErrorCode.DEPRECATED_ELEMENT, name); |
| 1995 } |
| 1996 // analyze Element |
| 1984 switch (element.getKind()) { | 1997 switch (element.getKind()) { |
| 1985 case DYNAMIC: | 1998 case DYNAMIC: |
| 1986 return dynamicType; | 1999 return dynamicType; |
| 1987 case CONSTRUCTOR: | 2000 case CONSTRUCTOR: |
| 1988 return typeError(node.getName(), TypeErrorCode.MEMBER_IS_A_CONSTRUCTOR
, | 2001 return typeError(node.getName(), TypeErrorCode.MEMBER_IS_A_CONSTRUCTOR
, |
| 1989 name, element.getName()); | 2002 name, element.getName()); |
| 1990 | 2003 |
| 1991 case METHOD: | 2004 case METHOD: |
| 1992 return member.getType(); | 2005 return member.getType(); |
| 1993 | 2006 |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2168 // bit operations, we currently allow them to be used | 2181 // bit operations, we currently allow them to be used |
| 2169 // if the left-hand-side is of type num. | 2182 // if the left-hand-side is of type num. |
| 2170 // TODO(karlklose) find a clean solution, i.e., without a special case
for num. | 2183 // TODO(karlklose) find a clean solution, i.e., without a special case
for num. |
| 2171 if (type.equals(numType)) { | 2184 if (type.equals(numType)) { |
| 2172 return intType; | 2185 return intType; |
| 2173 } else { | 2186 } else { |
| 2174 String name = methodNameForUnaryOperator(node, operator); | 2187 String name = methodNameForUnaryOperator(node, operator); |
| 2175 HasSourceInfo problemTarget = getOperatorHasSourceInfo(node); | 2188 HasSourceInfo problemTarget = getOperatorHasSourceInfo(node); |
| 2176 Member member = lookupMember(type, name, problemTarget); | 2189 Member member = lookupMember(type, name, problemTarget); |
| 2177 if (member != null) { | 2190 if (member != null) { |
| 2178 node.setElement(member.getElement()); | 2191 Element element = member.getElement(); |
| 2192 node.setElement(element); |
| 2179 FunctionType methodType = getMethodType(type, member, name, node); | 2193 FunctionType methodType = getMethodType(type, member, name, node); |
| 2194 checkDeprecated(problemTarget, element); |
| 2180 return checkInvocation(Collections.<DartExpression>emptyList(), no
de, name, methodType); | 2195 return checkInvocation(Collections.<DartExpression>emptyList(), no
de, name, methodType); |
| 2181 } else { | 2196 } else { |
| 2182 return dynamicType; | 2197 return dynamicType; |
| 2183 } | 2198 } |
| 2184 } | 2199 } |
| 2185 case NOT: | 2200 case NOT: |
| 2186 checkAssignable(boolType, expression); | 2201 checkAssignable(boolType, expression); |
| 2187 return boolType; | 2202 return boolType; |
| 2188 case SUB: | 2203 case SUB: |
| 2189 case INC: | 2204 case INC: |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2259 if (type instanceof InterfaceType) { | 2274 if (type instanceof InterfaceType) { |
| 2260 InterfaceType interfaceType = (InterfaceType) type; | 2275 InterfaceType interfaceType = (InterfaceType) type; |
| 2261 Element callElement = interfaceType.getElement().lookupLocalElement(
"call"); | 2276 Element callElement = interfaceType.getElement().lookupLocalElement(
"call"); |
| 2262 if (ElementKind.of(callElement) == ElementKind.METHOD) { | 2277 if (ElementKind.of(callElement) == ElementKind.METHOD) { |
| 2263 node.setElement(callElement); | 2278 node.setElement(callElement); |
| 2264 type = typeAsMemberOf(callElement, interfaceType); | 2279 type = typeAsMemberOf(callElement, interfaceType); |
| 2265 } | 2280 } |
| 2266 } | 2281 } |
| 2267 break; | 2282 break; |
| 2268 } | 2283 } |
| 2284 checkDeprecated(target, element); |
| 2269 return checkInvocation(node, target, name, type); | 2285 return checkInvocation(node, target, name, type); |
| 2270 } | 2286 } |
| 2271 | 2287 |
| 2288 /** |
| 2289 * Report warning if given {@link Element} is deprecated. |
| 2290 */ |
| 2291 private void checkDeprecated(HasSourceInfo nameNode, Element element) { |
| 2292 if (element != null && element.getMetadata().isDeprecated()) { |
| 2293 onError(nameNode, TypeErrorCode.DEPRECATED_ELEMENT, element); |
| 2294 } |
| 2295 } |
| 2296 |
| 2272 private Type checkInvocation(DartInvocation node, DartNode diagnosticNode, S
tring name, | 2297 private Type checkInvocation(DartInvocation node, DartNode diagnosticNode, S
tring name, |
| 2273 Type type) { | 2298 Type type) { |
| 2274 List<DartExpression> argumentNodes = node.getArguments(); | 2299 List<DartExpression> argumentNodes = node.getArguments(); |
| 2275 return checkInvocation(argumentNodes, diagnosticNode, name, type); | 2300 return checkInvocation(argumentNodes, diagnosticNode, name, type); |
| 2276 } | 2301 } |
| 2277 | 2302 |
| 2278 private Type checkInvocation(List<DartExpression> argumentNodes, | 2303 private Type checkInvocation(List<DartExpression> argumentNodes, DartNode di
agnosticNode, |
| 2279 DartNode diagnosticNode, String name, Type type) { | 2304 String name, Type type) { |
| 2280 // Prepare argument types. | 2305 // Prepare argument types. |
| 2281 List<Type> argumentTypes = Lists.newArrayListWithCapacity(argumentNodes.si
ze()); | 2306 List<Type> argumentTypes = Lists.newArrayListWithCapacity(argumentNodes.si
ze()); |
| 2282 for (DartExpression argumentNode : argumentNodes) { | 2307 for (DartExpression argumentNode : argumentNodes) { |
| 2283 Type argumentType = getInvocationArgumentType(argumentNode); | 2308 Type argumentType = getInvocationArgumentType(argumentNode); |
| 2284 argumentTypes.add(argumentType); | 2309 argumentTypes.add(argumentType); |
| 2285 } | 2310 } |
| 2286 // Check that argument types are compatible with type of invoked object. | 2311 // Check that argument types are compatible with type of invoked object. |
| 2287 try { | 2312 try { |
| 2288 switch (TypeKind.of(type)) { | 2313 switch (TypeKind.of(type)) { |
| 2289 case FUNCTION_ALIAS: | 2314 case FUNCTION_ALIAS: |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2531 } | 2556 } |
| 2532 // prevent recursion | 2557 // prevent recursion |
| 2533 if (visited.contains(current)) { | 2558 if (visited.contains(current)) { |
| 2534 return false; | 2559 return false; |
| 2535 } | 2560 } |
| 2536 visited.add(current); | 2561 visited.add(current); |
| 2537 // check type of "current" function type alias | 2562 // check type of "current" function type alias |
| 2538 return hasFunctionTypeAliasReference(visited, target, current); | 2563 return hasFunctionTypeAliasReference(visited, target, current); |
| 2539 } | 2564 } |
| 2540 | 2565 |
| 2566 /** |
| 2567 * @return the {@link DartIdentifier} corresponding to the name of construct
or. |
| 2568 */ |
| 2569 public static DartIdentifier getConstructorNameNode(DartNewExpression node)
{ |
| 2570 DartNode constructor = node.getConstructor(); |
| 2571 return getConstructorNameNode(constructor); |
| 2572 } |
| 2573 |
| 2574 /** |
| 2575 * @return the {@link DartIdentifier} corresponding to the name of construct
or. |
| 2576 */ |
| 2577 public static DartIdentifier getConstructorNameNode(DartNode constructor) { |
| 2578 if (constructor instanceof DartPropertyAccess) { |
| 2579 return ((DartPropertyAccess) constructor).getName(); |
| 2580 } else if (constructor instanceof DartTypeNode) { |
| 2581 return getConstructorNameNode(((DartTypeNode) constructor).getIdentifier
()); |
| 2582 } else { |
| 2583 return (DartIdentifier) constructor; |
| 2584 } |
| 2585 } |
| 2586 |
| 2541 @Override | 2587 @Override |
| 2542 public Type visitIntegerLiteral(DartIntegerLiteral node) { | 2588 public Type visitIntegerLiteral(DartIntegerLiteral node) { |
| 2543 return typeOfLiteral(node); | 2589 return typeOfLiteral(node); |
| 2544 } | 2590 } |
| 2545 | 2591 |
| 2546 @Override | 2592 @Override |
| 2547 public Type visitStringLiteral(DartStringLiteral node) { | 2593 public Type visitStringLiteral(DartStringLiteral node) { |
| 2548 return typeOfLiteral(node); | 2594 return typeOfLiteral(node); |
| 2549 } | 2595 } |
| 2550 | 2596 |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2860 for (VariableElement v : parameters) { | 2906 for (VariableElement v : parameters) { |
| 2861 if (v.isNamed()) { | 2907 if (v.isNamed()) { |
| 2862 named.add(v); | 2908 named.add(v); |
| 2863 } | 2909 } |
| 2864 } | 2910 } |
| 2865 return named; | 2911 return named; |
| 2866 } | 2912 } |
| 2867 } | 2913 } |
| 2868 } | 2914 } |
| 2869 } | 2915 } |
| OLD | NEW |