| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:analyzer/dart/ast/ast.dart'; | 5 import 'package:analyzer/dart/ast/ast.dart'; |
| 6 import 'package:analyzer/dart/ast/visitor.dart'; | 6 import 'package:analyzer/dart/ast/visitor.dart'; |
| 7 import 'package:analyzer/dart/element/element.dart'; | 7 import 'package:analyzer/dart/element/element.dart'; |
| 8 import 'package:analyzer/dart/element/type.dart'; | 8 import 'package:analyzer/dart/element/type.dart'; |
| 9 import 'package:analyzer/src/dart/element/type.dart'; | 9 import 'package:analyzer/src/dart/element/type.dart'; |
| 10 import 'package:analyzer/src/generated/resolver.dart'; | 10 import 'package:analyzer/src/generated/resolver.dart'; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 _InstrumentationVisitor(this._typeSystem, this._instrumentation, this.uri); | 58 _InstrumentationVisitor(this._typeSystem, this._instrumentation, this.uri); |
| 59 | 59 |
| 60 @override | 60 @override |
| 61 visitAssignmentExpression(AssignmentExpression node) { | 61 visitAssignmentExpression(AssignmentExpression node) { |
| 62 super.visitAssignmentExpression(node); | 62 super.visitAssignmentExpression(node); |
| 63 var leftHandSide = node.leftHandSide; | 63 var leftHandSide = node.leftHandSide; |
| 64 if (leftHandSide is PrefixedIdentifier) { | 64 if (leftHandSide is PrefixedIdentifier) { |
| 65 var staticElement = leftHandSide.identifier.staticElement; | 65 var staticElement = leftHandSide.identifier.staticElement; |
| 66 if (staticElement is PropertyAccessorElement && staticElement.isSetter) { | 66 if (staticElement is PropertyAccessorElement && staticElement.isSetter) { |
| 67 var target = leftHandSide.prefix; | 67 var target = leftHandSide.prefix; |
| 68 _annotateCheckCall( | 68 _annotateCallKind( |
| 69 staticElement, | 69 staticElement, |
| 70 target is ThisExpression, | 70 target is ThisExpression, |
| 71 isDynamicInvoke(leftHandSide.identifier), | 71 isDynamicInvoke(leftHandSide.identifier), |
| 72 target.staticType, | 72 target.staticType, |
| 73 [], | |
| 74 [node.rightHandSide], | |
| 75 leftHandSide.identifier.offset); | 73 leftHandSide.identifier.offset); |
| 76 } | 74 } |
| 77 } | 75 } |
| 78 } | 76 } |
| 79 | 77 |
| 80 @override | 78 @override |
| 81 visitClassDeclaration(ClassDeclaration node) { | 79 visitClassDeclaration(ClassDeclaration node) { |
| 82 super.visitClassDeclaration(node); | 80 super.visitClassDeclaration(node); |
| 83 _emitForwardingStubs(node, node.name.offset); | 81 _emitForwardingStubs(node, node.name.offset); |
| 84 } | 82 } |
| 85 | 83 |
| 86 @override | 84 @override |
| 87 visitClassTypeAlias(ClassTypeAlias node) { | 85 visitClassTypeAlias(ClassTypeAlias node) { |
| 88 super.visitClassTypeAlias(node); | 86 super.visitClassTypeAlias(node); |
| 89 _emitForwardingStubs(node, node.name.offset); | 87 _emitForwardingStubs(node, node.name.offset); |
| 90 } | 88 } |
| 91 | 89 |
| 92 @override | 90 @override |
| 93 visitFormalParameter(FormalParameter node) { | 91 visitFormalParameter(FormalParameter node) { |
| 94 super.visitFormalParameter(node); | 92 super.visitFormalParameter(node); |
| 95 if (node is DefaultFormalParameter) { | 93 if (node is DefaultFormalParameter) { |
| 96 // Already handled via the contained parameter ast object | 94 // Already handled via the contained parameter ast object |
| 97 return; | 95 return; |
| 98 } | 96 } |
| 99 _annotateFormalParameter(node.element, node.identifier.offset, | 97 if (node.element.enclosingElement.enclosingElement is ClassElement) { |
| 100 node.getAncestor((n) => n is ClassDeclaration)); | 98 _annotateFormalParameter(node.element, node.identifier.offset, |
| 99 node.getAncestor((n) => n is ClassDeclaration)); |
| 100 } |
| 101 } | 101 } |
| 102 | 102 |
| 103 @override | 103 @override |
| 104 visitMethodInvocation(MethodInvocation node) { | 104 visitMethodInvocation(MethodInvocation node) { |
| 105 super.visitMethodInvocation(node); | 105 super.visitMethodInvocation(node); |
| 106 var staticElement = node.methodName.staticElement; | 106 var staticElement = node.methodName.staticElement; |
| 107 var target = node.target; | 107 var target = node.target; |
| 108 var isThis = target is ThisExpression || target == null; | 108 var isThis = target is ThisExpression || target == null; |
| 109 if (staticElement is PropertyAccessorElement) { | 109 if (staticElement is PropertyAccessorElement) { |
| 110 // Method invocation resolves to a getter; treat it as a get followed by a | 110 // Method invocation resolves to a getter; treat it as a get followed by a |
| 111 // function invocation. | 111 // function invocation. |
| 112 _annotateCheckReturn( | 112 _annotateCheckReturn( |
| 113 getImplicitOperationCast(node), node.methodName.offset); | 113 getImplicitOperationCast(node), node.methodName.offset); |
| 114 _annotateCheckCall( | 114 _annotateCallKind(null, isThis, isDynamicInvoke(node.methodName), null, |
| 115 null, | |
| 116 isThis, | |
| 117 isDynamicInvoke(node.methodName), | |
| 118 null, | |
| 119 node.typeArguments?.arguments, | |
| 120 node.argumentList.arguments, | |
| 121 node.argumentList.offset); | 115 node.argumentList.offset); |
| 122 } else { | 116 } else { |
| 123 _annotateCheckReturn(getImplicitCast(node), node.argumentList.offset); | 117 _annotateCheckReturn(getImplicitCast(node), node.argumentList.offset); |
| 124 _annotateCheckCall( | 118 _annotateCallKind(staticElement, isThis, isDynamicInvoke(node.methodName), |
| 125 staticElement, | 119 target?.staticType, node.argumentList.offset); |
| 126 isThis, | |
| 127 isDynamicInvoke(node.methodName), | |
| 128 target?.staticType, | |
| 129 node.typeArguments?.arguments, | |
| 130 node.argumentList.arguments, | |
| 131 node.argumentList.offset); | |
| 132 } | 120 } |
| 133 } | 121 } |
| 134 | 122 |
| 135 @override | 123 @override |
| 136 visitPrefixedIdentifier(PrefixedIdentifier node) { | 124 visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 137 super.visitPrefixedIdentifier(node); | 125 super.visitPrefixedIdentifier(node); |
| 138 if (node.identifier.staticElement is MethodElement) { | 126 if (node.identifier.staticElement is MethodElement) { |
| 139 _annotateTearOff(node, node.identifier.offset); | 127 _annotateTearOff(node, node.identifier.offset); |
| 140 } | 128 } |
| 141 } | 129 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 155 if (node.parent.parent is FieldDeclaration) { | 143 if (node.parent.parent is FieldDeclaration) { |
| 156 FieldElement element = node.element; | 144 FieldElement element = node.element; |
| 157 if (!element.isFinal) { | 145 if (!element.isFinal) { |
| 158 var setter = element.setter; | 146 var setter = element.setter; |
| 159 _annotateFormalParameter(setter.parameters[0], node.name.offset, | 147 _annotateFormalParameter(setter.parameters[0], node.name.offset, |
| 160 node.getAncestor((n) => n is ClassDeclaration)); | 148 node.getAncestor((n) => n is ClassDeclaration)); |
| 161 } | 149 } |
| 162 } | 150 } |
| 163 } | 151 } |
| 164 | 152 |
| 165 /// Generates the appropriate `@checkCall` annotation (if any) for a call | 153 /// Generates the appropriate `@callKind` annotation (if any) for a call site. |
| 166 /// site. | |
| 167 /// | 154 /// |
| 168 /// An annotation of `@checkCall=dynamic` indicates that the call is dynamic | 155 /// An annotation of `@callKind=dynamic` indicates that the call is dynamic |
| 169 /// (so it will have to be fully type checked). An annotation of | 156 /// (so it will have to be fully type checked). An annotation of |
| 170 /// "@checkCall=interface(args)" indicates that the call statically resolves | 157 /// `@callKind=closure` indicates that the receiver of the call is a function |
| 171 /// to a member of an interface, but some of the arguments are "semi-typed" so | 158 /// object (so any formals marked as "semiSafe" will have to be type checked). |
| 172 /// they may have to be type checked. `args` lists the positional indices of | 159 /// An annotation of `@callKind=this` indicates that the call goes through |
| 173 /// the semi-typed arguments (counting from 0). If any type parameters need | 160 /// `super` or `this` (so formals marked as "semiSafe" don't need to be type |
| 174 /// to be checked, they are also listed by index, enclosed in `<>`. For | 161 /// checked). No annotation indicates that either the call is static, in |
| 175 /// example, `@checkCall=interface(<0>,1)` means that type parameter 0 and | 162 /// which case no parameters need to be type checked, or it goes through an |
| 176 /// regular parameter 1 are semi-typed. | 163 /// interface, in which case the set of arguments that have to be type checked |
| 177 /// | 164 /// depends on the `@checkInterface` annotations on the static target of the |
| 178 /// [staticElement] is the element being invoked, or `null` if there is no | 165 /// call. |
| 179 /// static element (either because this is a dynamic invocation or because the | 166 void _annotateCallKind(Element staticElement, bool isThis, bool isDynamic, |
| 180 /// thing being invoked is function-typed). | 167 DartType targetType, int offset) { |
| 181 /// | |
| 182 /// [isThis] indicates whether the receiver of the invocation is `this`. | |
| 183 /// | |
| 184 /// [isDynamic] indicates whether analyzer has classified this invocation as a | |
| 185 /// dynamic invocation. | |
| 186 /// | |
| 187 /// [targetType] is the type of the target of the invocation, or `null` if | |
| 188 /// there is no target (e.g. because of implicit `this` or because the thing | |
| 189 /// being invoked is function-typed). | |
| 190 /// | |
| 191 /// [typeArguments] and [arguments] are the type arguments and regular | |
| 192 /// arguments of the invocation, respectively. | |
| 193 /// | |
| 194 /// [offset] is the location of the invocation in source code. | |
| 195 void _annotateCheckCall( | |
| 196 Element staticElement, | |
| 197 bool isThis, | |
| 198 bool isDynamic, | |
| 199 DartType targetType, | |
| 200 List<TypeAnnotation> typeArguments, | |
| 201 List<Expression> arguments, | |
| 202 int offset) { | |
| 203 if (staticElement is FunctionElement && | 168 if (staticElement is FunctionElement && |
| 204 staticElement.enclosingElement is CompilationUnitElement) { | 169 staticElement.enclosingElement is CompilationUnitElement) { |
| 205 // Invocation of a top level function; no annotation needed. | 170 // Invocation of a top level function; no annotation needed. |
| 206 return; | 171 return; |
| 207 } | 172 } |
| 208 if (isDynamic) { | 173 if (isDynamic) { |
| 209 if (targetType == null && | 174 if (targetType == null && |
| 210 staticElement != null && | 175 staticElement != null && |
| 211 staticElement is! MethodElement) { | 176 staticElement is! MethodElement) { |
| 212 // Sometimes analyzer annotates invocations of function objects as | 177 // Sometimes analyzer annotates invocations of function objects as |
| 213 // dynamic (presumably due to "dynamic is bottom" behavior). Ignore | 178 // dynamic (presumably due to "dynamic is bottom" behavior). Ignore |
| 214 // this. | 179 // this. |
| 180 _recordCallKind(offset, 'closure'); |
| 215 } else { | 181 } else { |
| 216 _recordCheckCall(offset, 'dynamic'); | 182 _recordCallKind(offset, 'dynamic'); |
| 217 return; | 183 return; |
| 218 } | 184 } |
| 219 } | 185 } |
| 220 if (staticElement is MethodElement && isThis) { | 186 if (staticElement is MethodElement && !staticElement.isStatic || |
| 221 // Calls through "this" are always typed because the type parameters match | 187 staticElement is PropertyAccessorElement && !staticElement.isStatic) { |
| 222 // up perfectly; no annotation needed. | 188 if (isThis) { |
| 223 return; | 189 _recordCallKind(offset, 'this'); |
| 224 } | 190 return; |
| 225 var semiTypedArgs = <String>[]; | 191 } else { |
| 226 if (typeArguments != null) { | 192 // Interface call; no annotation needed |
| 227 for (int argPosition = 0; | 193 return; |
| 228 argPosition < typeArguments.length; | |
| 229 argPosition++) { | |
| 230 DartType getArgument(FunctionType functionType) { | |
| 231 return functionType.typeFormals[argPosition].bound; | |
| 232 } | |
| 233 | |
| 234 if (_isArgumentSemiTyped(targetType, staticElement, getArgument)) { | |
| 235 semiTypedArgs.add('<$argPosition>'); | |
| 236 } | |
| 237 } | 194 } |
| 238 } | 195 } |
| 239 int argPosition = 0; | 196 _recordCallKind(offset, 'closure'); |
| 240 for (var argument in arguments) { | |
| 241 assert(argument is! NamedExpression); // TODO(paulberry): handle this | |
| 242 DartType getArgument(FunctionType functionType) { | |
| 243 // TODO(paulberry): handle named parameters | |
| 244 if (argPosition >= functionType.normalParameterTypes.length) { | |
| 245 return functionType.optionalParameterTypes[ | |
| 246 argPosition - functionType.normalParameterTypes.length]; | |
| 247 } else { | |
| 248 return functionType.normalParameterTypes[argPosition]; | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 if (_isArgumentSemiTyped(targetType, staticElement, getArgument)) { | |
| 253 semiTypedArgs.add('$argPosition'); | |
| 254 } | |
| 255 ++argPosition; | |
| 256 } | |
| 257 if (semiTypedArgs.isEmpty) { | |
| 258 // We don't annotate invocations where all arguments are typed because | |
| 259 // that's the common case. | |
| 260 } else { | |
| 261 _recordCheckCall( | |
| 262 offset, 'interface(semiTyped:${semiTypedArgs.join(',')})'); | |
| 263 } | |
| 264 } | 197 } |
| 265 | 198 |
| 266 /// Generates the appropriate `@checkReturn` annotation (if any) for a call | 199 /// Generates the appropriate `@checkReturn` annotation (if any) for a call |
| 267 /// site. | 200 /// site. |
| 268 /// | 201 /// |
| 269 /// An annotation of `@checkReturn=type` indicates that the value returned by | 202 /// An annotation of `@checkReturn=type` indicates that the value returned by |
| 270 /// the call will have to be checked to make sure it is an instance of the | 203 /// the call will have to be checked to make sure it is an instance of the |
| 271 /// given type. | 204 /// given type. |
| 272 void _annotateCheckReturn(DartType castType, int offset) { | 205 void _annotateCheckReturn(DartType castType, int offset) { |
| 273 if (castType != null) { | 206 if (castType != null) { |
| 274 _recordCheckReturn(offset, castType); | 207 _recordCheckReturn(offset, castType); |
| 275 } | 208 } |
| 276 } | 209 } |
| 277 | 210 |
| 278 /// Generates the appropriate `@checkFormal` annotation (if any) for a method | 211 /// Generates the appropriate `@checkFormal` and `@checkInterface` annotations |
| 279 /// formal parameter, method type parameter, or field declaration. | 212 /// (if any) for a method formal parameter, method type parameter, or field |
| 213 /// declaration. |
| 280 /// | 214 /// |
| 281 /// When this annotation is generated for a field declaration, it implicitly | 215 /// When these annotations are generated for a field declaration, they |
| 282 /// refers to the value parameter of the synthetic setter. | 216 /// implicitly refer to the value parameter of the synthetic setter. |
| 283 /// | 217 /// |
| 284 /// An annotation of `@checkFormal=unsafe` indicates that the parameter needs | 218 /// An annotation of `@checkFormal=unsafe` indicates that the parameter needs |
| 285 /// to be type checked regardless of the call site. | 219 /// to be type checked regardless of the call site. |
| 286 /// | 220 /// |
| 287 /// An annotation of `@checkFormal=semiSafe` indicates that the parameter | 221 /// An annotation of `@checkFormal=semiSafe` indicates that the parameter |
| 288 /// needs to be type checked when corresponding argument at the call site is | 222 /// needs to be type checked when the call site is annotated |
| 289 /// considered "semi-typed". | 223 /// `@callKind=dynamic` or `@callKind=closure`, or the call site is |
| 224 /// unannotated and the corresponding parameter in the interface target is |
| 225 /// annotated `@checkInterface=semiTyped`. |
| 290 /// | 226 /// |
| 291 /// No annotation indicates that the parameter only needs to be type checked | 227 /// No `@checkFormal` annotation indicates that the parameter only needs to be |
| 292 /// if the call site is a dynamic invocation. | 228 /// type checked if the call site is annotated `@callKind=dynamic`. |
| 293 void _annotateFormalParameter( | 229 void _annotateFormalParameter( |
| 294 Element element, int offset, ClassDeclaration cls) { | 230 Element element, int offset, ClassDeclaration cls) { |
| 295 if (element is ParameterElement && element.isCovariant) { | 231 if (element is ParameterElement && element.isCovariant) { |
| 296 _recordCheckFormal(offset, 'unsafe'); | 232 _recordCheckFormal(offset, 'unsafe'); |
| 297 } else if (cls != null) { | 233 } else if (cls != null) { |
| 298 var covariantParams = getClassCovariantParameters(cls); | 234 var covariantParams = getClassCovariantParameters(cls); |
| 299 if (covariantParams != null && covariantParams.contains(element)) { | 235 if (covariantParams != null && covariantParams.contains(element)) { |
| 300 _recordCheckFormal(offset, 'semiSafe'); | 236 _recordCheckFormal(offset, 'semiSafe'); |
| 301 } | 237 } |
| 302 } | 238 } |
| 239 if (cls?.typeParameters != null) { |
| 240 if (element is ParameterElement) { |
| 241 if (_isFormalSemiTyped( |
| 242 cls.typeParameters.typeParameters, element.type)) { |
| 243 _recordCheckInterface(offset, 'semiTyped'); |
| 244 } |
| 245 } else if (element is TypeParameterElement && element.bound != null) { |
| 246 if (_isFormalSemiTyped( |
| 247 cls.typeParameters.typeParameters, element.bound)) { |
| 248 _recordCheckInterface(offset, 'semiTyped'); |
| 249 } |
| 250 } |
| 251 } |
| 303 } | 252 } |
| 304 | 253 |
| 305 /// Generates the appropriate `@checkTearOff` annotation (if any) for a call | 254 /// Generates the appropriate `@checkTearOff` annotation (if any) for a call |
| 306 /// site. | 255 /// site. |
| 307 /// | 256 /// |
| 308 /// An annotation of `@checkTearOff=type` indicates that the torn off function | 257 /// An annotation of `@checkTearOff=type` indicates that the torn off function |
| 309 /// will have to be checked to make sure it is an instance of the given type. | 258 /// will have to be checked to make sure it is an instance of the given type. |
| 310 void _annotateTearOff(Expression node, int offset) { | 259 void _annotateTearOff(Expression node, int offset) { |
| 311 // TODO(paulberry): handle dynamic tear offs | 260 // TODO(paulberry): handle dynamic tear offs |
| 312 // Note: we don't annotate that non-dynamic tear offs use "interface" | 261 // Note: we don't annotate that non-dynamic tear offs use "interface" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 var returnTypeDescr = _typeToString(member.returnType); | 296 var returnTypeDescr = _typeToString(member.returnType); |
| 348 var stub = '$returnTypeDescr $memberName(${paramDescrs.join(', ')})'; | 297 var stub = '$returnTypeDescr $memberName(${paramDescrs.join(', ')})'; |
| 349 _recordForwardingStub(offset, stub); | 298 _recordForwardingStub(offset, stub); |
| 350 } else { | 299 } else { |
| 351 throw new StateError('Unexpected covariant member $member'); | 300 throw new StateError('Unexpected covariant member $member'); |
| 352 } | 301 } |
| 353 } | 302 } |
| 354 } | 303 } |
| 355 } | 304 } |
| 356 | 305 |
| 357 /// Determines whether an argument at a call site should be considered | 306 /// Determines whether a method formal parameter should be considered |
| 358 /// "semi-typed". | 307 /// "semi-typed". |
| 359 /// | 308 /// |
| 360 /// [targetType] indicates the type of the interface being invoked. | 309 /// [typeParameters] is the list of type parameters of the enclosing class. |
| 361 /// | 310 /// |
| 362 /// [invocationTarget] is the method or getter/setter being invoked. | 311 /// [formalType] is the type of the formal parameter (or the type bound, if |
| 363 /// | 312 /// we are looking at a type parameter of a generic method). |
| 364 /// [getArgument] is a callback for accessing the corresponding argument type | 313 bool _isFormalSemiTyped( |
| 365 /// from a [FunctionType]. | 314 List<TypeParameter> typeParameters, DartType formalType) { |
| 366 bool _isArgumentSemiTyped(InterfaceType targetType, Element invocationTarget, | 315 // To see if this parameter needs to be semi-typed, we try substituting |
| 367 DartType getArgument(FunctionType functionType)) { | 316 // bottom for all the active type parameters. If the resulting parameter |
| 368 bool _checkTypes(DartType originalArgumentType, | 317 // static type is a supertype of its current static type, then that means |
| 369 DartType lookupArgumentType(InterfaceType interfaceType)) { | 318 // that regardless of what we pass in, it won't fail a type check. |
| 370 // If the target type lacks type parameters, then everything is safe. | 319 var substitutedType = formalType.substitute2( |
| 371 if (targetType.typeParameters.isEmpty) return false; | 320 new List<DartType>.filled( |
| 372 | 321 typeParameters.length, BottomTypeImpl.instance), |
| 373 // To see if this argument needs to be semi-typed, we try substituting | 322 typeParameters |
| 374 // bottom in for all the active type parameters. If the resulting | 323 .map((p) => new TypeParameterTypeImpl(p.element)) |
| 375 // argument static type is a supertype of its current static type, then | 324 .toList()); |
| 376 // that means that regardless of what we pass in, it won't fail a type | 325 return !_typeSystem.isSubtypeOf(formalType, substitutedType); |
| 377 // check. | |
| 378 var substitutedInterfaceType = targetType.element.type.instantiate( | |
| 379 new List<DartType>.filled( | |
| 380 targetType.typeParameters.length, BottomTypeImpl.instance)); | |
| 381 var substitutedArgumentType = | |
| 382 lookupArgumentType(substitutedInterfaceType); | |
| 383 return !_typeSystem.isSubtypeOf( | |
| 384 originalArgumentType, substitutedArgumentType); | |
| 385 } | |
| 386 | |
| 387 if (invocationTarget is LocalVariableElement || invocationTarget == null) { | |
| 388 // This is an invocation of a closure, so every argument is semi-typed. | |
| 389 return true; | |
| 390 } else if (invocationTarget is PropertyAccessorElement && | |
| 391 invocationTarget.isSetter) { | |
| 392 return _checkTypes( | |
| 393 invocationTarget.parameters[0].type, | |
| 394 (InterfaceType type) => type | |
| 395 .lookUpSetter(invocationTarget.name, invocationTarget.library) | |
| 396 .parameters[0] | |
| 397 .type); | |
| 398 } else if (invocationTarget is MethodElement) { | |
| 399 return _checkTypes( | |
| 400 getArgument(invocationTarget.type), | |
| 401 (InterfaceType type) => getArgument(type | |
| 402 .lookUpMethod(invocationTarget.name, invocationTarget.library) | |
| 403 .type)); | |
| 404 } else { | |
| 405 throw new UnimplementedError( | |
| 406 'Unexpected invocation target type: ${invocationTarget.runtimeType}'); | |
| 407 } | |
| 408 } | 326 } |
| 409 | 327 |
| 410 void _recordCheckCall(int offset, String safety) { | 328 void _recordCallKind(int offset, String kind) { |
| 411 _instrumentation.record(uri, offset, 'checkCall', | 329 _instrumentation.record( |
| 412 new fasta.InstrumentationValueLiteral(safety)); | 330 uri, offset, 'callKind', new fasta.InstrumentationValueLiteral(kind)); |
| 413 } | 331 } |
| 414 | 332 |
| 415 void _recordCheckFormal(int offset, String safety) { | 333 void _recordCheckFormal(int offset, String safety) { |
| 416 _instrumentation.record(uri, offset, 'checkFormal', | 334 _instrumentation.record(uri, offset, 'checkFormal', |
| 417 new fasta.InstrumentationValueLiteral(safety)); | 335 new fasta.InstrumentationValueLiteral(safety)); |
| 418 } | 336 } |
| 419 | 337 |
| 338 void _recordCheckInterface(int offset, String safety) { |
| 339 _instrumentation.record(uri, offset, 'checkInterface', |
| 340 new fasta.InstrumentationValueLiteral(safety)); |
| 341 } |
| 342 |
| 420 void _recordCheckReturn(int offset, DartType castType) { | 343 void _recordCheckReturn(int offset, DartType castType) { |
| 421 _instrumentation.record(uri, offset, 'checkReturn', | 344 _instrumentation.record(uri, offset, 'checkReturn', |
| 422 new InstrumentationValueForType(castType, _elementNamer)); | 345 new InstrumentationValueForType(castType, _elementNamer)); |
| 423 } | 346 } |
| 424 | 347 |
| 425 void _recordCheckTearOff(int offset, DartType castType) { | 348 void _recordCheckTearOff(int offset, DartType castType) { |
| 426 _instrumentation.record(uri, offset, 'checkTearOff', | 349 _instrumentation.record(uri, offset, 'checkTearOff', |
| 427 new InstrumentationValueForType(castType, _elementNamer)); | 350 new InstrumentationValueForType(castType, _elementNamer)); |
| 428 } | 351 } |
| 429 | 352 |
| 430 void _recordForwardingStub(int offset, String descr) { | 353 void _recordForwardingStub(int offset, String descr) { |
| 431 _instrumentation.record(uri, offset, 'forwardingStub', | 354 _instrumentation.record(uri, offset, 'forwardingStub', |
| 432 new fasta.InstrumentationValueLiteral(descr)); | 355 new fasta.InstrumentationValueLiteral(descr)); |
| 433 } | 356 } |
| 434 | 357 |
| 435 String _typeToString(DartType type) { | 358 String _typeToString(DartType type) { |
| 436 return new InstrumentationValueForType(type, _elementNamer).toString(); | 359 return new InstrumentationValueForType(type, _elementNamer).toString(); |
| 437 } | 360 } |
| 438 } | 361 } |
| OLD | NEW |