Chromium Code Reviews| 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 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:convert'; | 6 import 'dart:convert'; |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/visitor.dart'; | 10 import 'package:analyzer/dart/ast/visitor.dart'; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 return null; | 147 return null; |
| 148 } else { | 148 } else { |
| 149 return validation.problemsAsString; | 149 return validation.problemsAsString; |
| 150 } | 150 } |
| 151 } else { | 151 } else { |
| 152 return null; | 152 return null; |
| 153 } | 153 } |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 | 156 |
| 157 /// Instance of [InstrumentationValue] describing a [MethodElement]. | 157 /// Instance of [InstrumentationValue] describing an [ExecutableElement]. |
| 158 class _InstrumentationValueForMethodElement extends fasta.InstrumentationValue { | 158 class _InstrumentationValueForExecutableElement |
| 159 final MethodElement element; | 159 extends fasta.InstrumentationValue { |
| 160 final ExecutableElement element; | |
| 160 final _ElementNamer elementNamer; | 161 final _ElementNamer elementNamer; |
| 161 | 162 |
| 162 _InstrumentationValueForMethodElement(this.element, this.elementNamer); | 163 _InstrumentationValueForExecutableElement(this.element, this.elementNamer); |
| 163 | 164 |
| 164 @override | 165 @override |
| 165 String toString() { | 166 String toString() { |
| 166 StringBuffer buffer = new StringBuffer(); | 167 StringBuffer buffer = new StringBuffer(); |
| 167 elementNamer.appendElementName(buffer, element); | 168 elementNamer.appendElementName(buffer, element); |
| 168 return buffer.toString(); | 169 return buffer.toString(); |
| 169 } | 170 } |
| 170 } | 171 } |
| 171 | 172 |
| 172 /** | 173 /** |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 // } | 288 // } |
| 288 // } | 289 // } |
| 289 // So to match kernel behavior, we have to arrange for this renaming to | 290 // So to match kernel behavior, we have to arrange for this renaming to |
| 290 // happen during output. | 291 // happen during output. |
| 291 elementNamer = new _ElementNamer(node.element); | 292 elementNamer = new _ElementNamer(node.element); |
| 292 } | 293 } |
| 293 super.visitConstructorDeclaration(node); | 294 super.visitConstructorDeclaration(node); |
| 294 elementNamer = oldElementNamer; | 295 elementNamer = oldElementNamer; |
| 295 } | 296 } |
| 296 | 297 |
| 298 @override | |
| 299 visitDeclaredIdentifier(DeclaredIdentifier node) { | |
| 300 super.visitDeclaredIdentifier(node); | |
| 301 if (node.type == null) { | |
| 302 _recordType(node.identifier.offset, node.element.type); | |
| 303 } | |
| 304 } | |
| 305 | |
| 297 visitFunctionExpression(FunctionExpression node) { | 306 visitFunctionExpression(FunctionExpression node) { |
| 298 super.visitFunctionExpression(node); | 307 super.visitFunctionExpression(node); |
| 299 if (node.parent is! FunctionDeclaration) { | 308 if (node.parent is! FunctionDeclaration) { |
| 300 DartType type = node.staticType; | 309 DartType type = node.staticType; |
| 301 if (type is FunctionType) { | 310 if (type is FunctionType) { |
| 302 _instrumentation.record(uri, node.offset, 'returnType', | 311 _instrumentation.record(uri, node.offset, 'returnType', |
| 303 new _InstrumentationValueForType(type.returnType, elementNamer)); | 312 new _InstrumentationValueForType(type.returnType, elementNamer)); |
| 304 List<FormalParameter> parameters = node.parameters.parameters; | 313 List<FormalParameter> parameters = node.parameters.parameters; |
| 305 for (int i = 0; i < parameters.length; i++) { | 314 for (int i = 0; i < parameters.length; i++) { |
| 306 FormalParameter parameter = parameters[i]; | 315 FormalParameter parameter = parameters[i]; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 if (node.typeArguments == null) { | 367 if (node.typeArguments == null) { |
| 359 DartType type = node.staticType; | 368 DartType type = node.staticType; |
| 360 if (type is InterfaceType) { | 369 if (type is InterfaceType) { |
| 361 _recordTypeArguments(node.offset, type.typeArguments); | 370 _recordTypeArguments(node.offset, type.typeArguments); |
| 362 } | 371 } |
| 363 } | 372 } |
| 364 } | 373 } |
| 365 | 374 |
| 366 visitMethodInvocation(MethodInvocation node) { | 375 visitMethodInvocation(MethodInvocation node) { |
| 367 super.visitMethodInvocation(node); | 376 super.visitMethodInvocation(node); |
| 368 _recordMethodTarget(node.methodName.offset, node.methodName.staticElement); | 377 if (node.target != null) { |
| 378 _recordMethodTarget( | |
| 379 node.methodName.offset, node.methodName.staticElement); | |
| 380 } | |
| 369 if (node.typeArguments == null) { | 381 if (node.typeArguments == null) { |
| 370 var inferredTypeArguments = _getInferredFunctionTypeArguments( | 382 var inferredTypeArguments = _getInferredFunctionTypeArguments( |
| 371 node.function.staticType, | 383 node.function.staticType, |
| 372 node.staticInvokeType, | 384 node.staticInvokeType, |
| 373 node.typeArguments) | 385 node.typeArguments) |
| 374 .toList(); | 386 .toList(); |
| 375 if (inferredTypeArguments.isNotEmpty) { | 387 if (inferredTypeArguments.isNotEmpty) { |
| 376 _recordTypeArguments(node.methodName.offset, inferredTypeArguments); | 388 _recordTypeArguments(node.methodName.offset, inferredTypeArguments); |
| 377 } | 389 } |
| 378 } | 390 } |
| 379 } | 391 } |
| 380 | 392 |
| 393 @override | |
| 394 visitPrefixedIdentifier(PrefixedIdentifier node) { | |
| 395 super.visitPrefixedIdentifier(node); | |
| 396 if (node.prefix.staticElement is! PrefixElement && | |
| 397 node.prefix.staticElement is! ClassElement) { | |
| 398 if (node.identifier.inGetterContext()) { | |
| 399 _recordMethodTarget( | |
| 400 node.identifier.offset, node.identifier.staticElement); | |
| 401 } | |
| 402 } | |
| 403 } | |
| 404 | |
| 381 visitPrefixExpression(PrefixExpression node) { | 405 visitPrefixExpression(PrefixExpression node) { |
| 382 super.visitPrefixExpression(node); | 406 super.visitPrefixExpression(node); |
| 383 _recordMethodTarget(node.operator.charOffset, node.staticElement); | 407 _recordMethodTarget(node.operator.charOffset, node.staticElement); |
| 384 } | 408 } |
| 385 | 409 |
| 410 @override | |
| 411 visitPropertyAccess(PropertyAccess node) { | |
| 412 super.visitPropertyAccess(node); | |
| 413 if (node.propertyName.inGetterContext()) { | |
| 414 _recordMethodTarget( | |
| 415 node.propertyName.offset, node.propertyName.staticElement); | |
| 416 } | |
| 417 } | |
| 418 | |
| 386 visitSimpleIdentifier(SimpleIdentifier node) { | 419 visitSimpleIdentifier(SimpleIdentifier node) { |
| 387 super.visitSimpleIdentifier(node); | 420 super.visitSimpleIdentifier(node); |
| 388 Element element = node.staticElement; | 421 Element element = node.staticElement; |
| 389 void recordPromotions(DartType elementType) { | 422 void recordPromotions(DartType elementType) { |
| 390 if (node.inGetterContext() && !node.inDeclarationContext()) { | 423 if (node.inGetterContext() && !node.inDeclarationContext()) { |
| 391 int offset = node.offset; | 424 int offset = node.offset; |
| 392 DartType type = node.staticType; | 425 DartType type = node.staticType; |
| 393 if (!identical(type, elementType)) { | 426 if (!identical(type, elementType)) { |
| 394 _instrumentation.record(uri, offset, 'promotedType', | 427 _instrumentation.record(uri, offset, 'promotedType', |
| 395 new _InstrumentationValueForType(type, elementNamer)); | 428 new _InstrumentationValueForType(type, elementNamer)); |
| 396 } | 429 } |
| 397 } | 430 } |
| 398 } | 431 } |
| 399 | 432 |
| 400 if (element is LocalVariableElement) { | 433 if (element is LocalVariableElement) { |
| 401 recordPromotions(element.type); | 434 recordPromotions(element.type); |
| 402 } else if (element is ParameterElement) { | 435 } else if (element is ParameterElement) { |
| 403 recordPromotions(element.type); | 436 recordPromotions(element.type); |
| 404 } | 437 } |
| 405 } | 438 } |
| 406 | 439 |
| 407 @override | |
| 408 visitDeclaredIdentifier(DeclaredIdentifier node) { | |
| 409 super.visitDeclaredIdentifier(node); | |
| 410 if (node.type == null) { | |
| 411 _recordType(node.identifier.offset, node.element.type); | |
| 412 } | |
| 413 } | |
| 414 | |
| 415 visitVariableDeclarationList(VariableDeclarationList node) { | 440 visitVariableDeclarationList(VariableDeclarationList node) { |
| 416 super.visitVariableDeclarationList(node); | 441 super.visitVariableDeclarationList(node); |
| 417 if (node.type == null) { | 442 if (node.type == null) { |
| 418 for (VariableDeclaration variable in node.variables) { | 443 for (VariableDeclaration variable in node.variables) { |
| 419 VariableElement element = variable.element; | 444 VariableElement element = variable.element; |
| 420 if (element is LocalVariableElement) { | 445 if (element is LocalVariableElement) { |
| 421 _recordType(variable.name.offset, element.type); | 446 _recordType(variable.name.offset, element.type); |
| 422 } else { | 447 } else { |
| 423 _recordTopType(variable.name.offset, element.type); | 448 _recordTopType(variable.name.offset, element.type); |
| 424 } | 449 } |
| 425 } | 450 } |
| 426 } | 451 } |
| 427 } | 452 } |
| 428 | 453 |
| 429 /// Based on DDC code generator's `_emitFunctionTypeArguments` | 454 /// Based on DDC code generator's `_emitFunctionTypeArguments` |
| 430 Iterable<DartType> _getInferredFunctionTypeArguments( | 455 Iterable<DartType> _getInferredFunctionTypeArguments( |
| 431 DartType g, DartType f, TypeArgumentList typeArgs) { | 456 DartType g, DartType f, TypeArgumentList typeArgs) { |
| 432 if (g is FunctionType && | 457 if (g is FunctionType && |
| 433 g.typeFormals.isNotEmpty && | 458 g.typeFormals.isNotEmpty && |
| 434 f is FunctionType && | 459 f is FunctionType && |
| 435 f.typeFormals.isEmpty) { | 460 f.typeFormals.isEmpty) { |
| 436 return _recoverTypeArguments(g, f); | 461 return _recoverTypeArguments(g, f); |
| 437 } else { | 462 } else { |
| 438 return const []; | 463 return const []; |
| 439 } | 464 } |
| 440 } | 465 } |
| 441 | 466 |
| 442 void _recordMethodTarget(int offset, Element element) { | 467 void _recordMethodTarget(int offset, Element element) { |
|
scheglov
2017/05/31 18:40:13
Maybe this method should also be renamed.
Paul Berry
2017/05/31 19:08:33
Good point. Renamed to "_recordTarget".
| |
| 443 if (element is MethodElement) { | 468 if (element is ExecutableElement) { |
| 444 _instrumentation.record(uri, offset, 'target', | 469 _instrumentation.record(uri, offset, 'target', |
| 445 new _InstrumentationValueForMethodElement(element, elementNamer)); | 470 new _InstrumentationValueForExecutableElement(element, elementNamer)); |
| 446 } | 471 } |
| 447 } | 472 } |
| 448 | 473 |
| 449 void _recordTopType(int offset, DartType type) { | 474 void _recordTopType(int offset, DartType type) { |
| 450 _instrumentation.record(uri, offset, 'topType', | 475 _instrumentation.record(uri, offset, 'topType', |
| 451 new _InstrumentationValueForType(type, elementNamer)); | 476 new _InstrumentationValueForType(type, elementNamer)); |
| 452 } | 477 } |
| 453 | 478 |
| 454 void _recordType(int offset, DartType type) { | 479 void _recordType(int offset, DartType type) { |
| 455 _instrumentation.record(uri, offset, 'type', | 480 _instrumentation.record(uri, offset, 'type', |
| 456 new _InstrumentationValueForType(type, elementNamer)); | 481 new _InstrumentationValueForType(type, elementNamer)); |
| 457 } | 482 } |
| 458 | 483 |
| 459 void _recordTypeArguments(int offset, List<DartType> typeArguments) { | 484 void _recordTypeArguments(int offset, List<DartType> typeArguments) { |
| 460 _instrumentation.record(uri, offset, 'typeArgs', | 485 _instrumentation.record(uri, offset, 'typeArgs', |
| 461 new _InstrumentationValueForTypeArgs(typeArguments, elementNamer)); | 486 new _InstrumentationValueForTypeArgs(typeArguments, elementNamer)); |
| 462 } | 487 } |
| 463 | 488 |
| 464 /// Based on DDC code generator's `_recoverTypeArguments` | 489 /// Based on DDC code generator's `_recoverTypeArguments` |
| 465 Iterable<DartType> _recoverTypeArguments(FunctionType g, FunctionType f) { | 490 Iterable<DartType> _recoverTypeArguments(FunctionType g, FunctionType f) { |
| 466 assert(identical(g.element, f.element)); | 491 assert(identical(g.element, f.element)); |
| 467 assert(g.typeFormals.isNotEmpty && f.typeFormals.isEmpty); | 492 assert(g.typeFormals.isNotEmpty && f.typeFormals.isEmpty); |
| 468 assert(g.typeFormals.length + g.typeArguments.length == | 493 assert(g.typeFormals.length + g.typeArguments.length == |
| 469 f.typeArguments.length); | 494 f.typeArguments.length); |
| 470 return f.typeArguments.skip(g.typeArguments.length); | 495 return f.typeArguments.skip(g.typeArguments.length); |
| 471 } | 496 } |
| 472 } | 497 } |
| OLD | NEW |