| 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'; |
| 10 import 'package:analyzer/dart/ast/visitor.dart'; |
| 11 import 'package:analyzer/dart/element/element.dart'; |
| 12 import 'package:analyzer/dart/element/type.dart'; |
| 13 import 'package:analyzer/src/dart/analysis/driver.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; | 14 import 'package:analyzer/src/generated/source.dart'; |
| 10 import 'package:front_end/src/base/instrumentation.dart' as fasta; | 15 import 'package:front_end/src/base/instrumentation.dart' as fasta; |
| 11 import 'package:front_end/src/fasta/compiler_context.dart' as fasta; | 16 import 'package:front_end/src/fasta/compiler_context.dart' as fasta; |
| 12 import 'package:front_end/src/fasta/testing/validating_instrumentation.dart' | 17 import 'package:front_end/src/fasta/testing/validating_instrumentation.dart' |
| 13 as fasta; | 18 as fasta; |
| 14 import 'package:kernel/kernel.dart' as fasta; | 19 import 'package:kernel/kernel.dart' as fasta; |
| 15 import 'package:path/path.dart' as pathos; | 20 import 'package:path/path.dart' as pathos; |
| 16 import 'package:test/test.dart'; | 21 import 'package:test/test.dart'; |
| 17 | 22 |
| 18 import '../../dart/analysis/base.dart'; | 23 import '../../dart/analysis/base.dart'; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 } catch (_) { | 61 } catch (_) { |
| 57 print(_); | 62 print(_); |
| 58 } finally { | 63 } finally { |
| 59 await test.tearDown(); | 64 await test.tearDown(); |
| 60 } | 65 } |
| 61 } | 66 } |
| 62 } | 67 } |
| 63 | 68 |
| 64 class _FrontEndInferenceTest extends BaseAnalysisDriverTest { | 69 class _FrontEndInferenceTest extends BaseAnalysisDriverTest { |
| 65 Future<Null> runTest(String path, String code) async { | 70 Future<Null> runTest(String path, String code) async { |
| 66 var uri = provider.pathContext.toUri(path); | 71 Uri uri = provider.pathContext.toUri(path); |
| 67 | 72 |
| 68 List<int> lineStarts = new LineInfo.fromContent(code).lineStarts; | 73 List<int> lineStarts = new LineInfo.fromContent(code).lineStarts; |
| 69 fasta.CompilerContext.current.uriToSource[uri.toString()] = | 74 fasta.CompilerContext.current.uriToSource[uri.toString()] = |
| 70 new fasta.Source(lineStarts, UTF8.encode(code)); | 75 new fasta.Source(lineStarts, UTF8.encode(code)); |
| 71 | 76 |
| 72 var validation = new fasta.ValidatingInstrumentation(); | 77 var validation = new fasta.ValidatingInstrumentation(); |
| 73 await validation.loadExpectations(uri); | 78 await validation.loadExpectations(uri); |
| 74 | 79 |
| 75 driver.test.instrumentation = new _Instrumentation(validation); | |
| 76 provider.newFile(path, code); | 80 provider.newFile(path, code); |
| 77 await driver.getResult(path); | 81 |
| 82 AnalysisResult result = await driver.getResult(path); |
| 83 result.unit.accept(new _InstrumentationVisitor(validation, uri)); |
| 78 | 84 |
| 79 validation.finish(); | 85 validation.finish(); |
| 80 | 86 |
| 81 if (validation.hasProblems) { | 87 if (validation.hasProblems) { |
| 82 var problem = validation.problemsAsString; | 88 fail(validation.problemsAsString); |
| 83 fail(problem); | |
| 84 } | 89 } |
| 85 } | 90 } |
| 86 } | 91 } |
| 87 | 92 |
| 88 class _Instrumentation implements fasta.Instrumentation { | 93 /** |
| 89 final fasta.Instrumentation instrumentation; | 94 * Instance of [InstrumentationValue] describing a [DartType]. |
| 90 final Set<String> _seenKeys = new Set<String>(); | 95 */ |
| 96 class _InstrumentationValueForType extends fasta.InstrumentationValue { |
| 97 final DartType type; |
| 91 | 98 |
| 92 _Instrumentation(this.instrumentation); | 99 _InstrumentationValueForType(this.type); |
| 93 | 100 |
| 94 @override | 101 @override |
| 95 void record( | 102 String toString() { |
| 96 Uri uri, int offset, String property, fasta.InstrumentationValue value) { | 103 StringBuffer buffer = new StringBuffer(); |
| 97 // Analyzer's resolver reports many of instance creations twice. | 104 _appendType(buffer, type); |
| 98 if (_seenKeys.add('$uri:$offset:$property')) { | 105 return buffer.toString(); |
| 99 instrumentation.record(uri, offset, property, value); | 106 } |
| 107 |
| 108 void _appendElementName(StringBuffer buffer, Element element) { |
| 109 String name = element.name; |
| 110 String libraryName = element.library.name; |
| 111 if (libraryName == '') { |
| 112 throw new StateError('The element $name must be in a named library.'); |
| 113 } |
| 114 if (libraryName != 'dart.core' && |
| 115 libraryName != 'dart.async' && |
| 116 libraryName != 'test') { |
| 117 buffer.write('$libraryName::$name'); |
| 118 } else { |
| 119 buffer.write('$name'); |
| 100 } | 120 } |
| 101 } | 121 } |
| 122 |
| 123 void _appendList<T>(StringBuffer buffer, String open, String close, |
| 124 List<T> items, String separator, writeItem(T item), |
| 125 {bool includeEmpty: false}) { |
| 126 if (!includeEmpty && items.isEmpty) { |
| 127 return; |
| 128 } |
| 129 buffer.write(open); |
| 130 bool first = true; |
| 131 for (T item in items) { |
| 132 if (!first) { |
| 133 buffer.write(separator); |
| 134 } |
| 135 writeItem(item); |
| 136 first = false; |
| 137 } |
| 138 buffer.write(close); |
| 139 } |
| 140 |
| 141 void _appendParameters( |
| 142 StringBuffer buffer, List<ParameterElement> parameters) { |
| 143 _appendList<ParameterElement>(buffer, '(', ')', parameters, ', ', |
| 144 (parameter) { |
| 145 _appendType(buffer, type); |
| 146 buffer.write(' '); |
| 147 buffer.write(parameter.name); |
| 148 }, includeEmpty: true); |
| 149 } |
| 150 |
| 151 void _appendType(StringBuffer buffer, DartType type) { |
| 152 if (type is FunctionType) { |
| 153 Element element = type.element; |
| 154 _appendElementName(buffer, element); |
| 155 _appendTypeArguments(buffer, type.typeArguments); |
| 156 _appendParameters(buffer, type.parameters); |
| 157 buffer.write(' → '); |
| 158 _appendType(buffer, type.returnType); |
| 159 } else if (type is InterfaceType) { |
| 160 ClassElement element = type.element; |
| 161 _appendElementName(buffer, element); |
| 162 _appendTypeArguments(buffer, type.typeArguments); |
| 163 } else { |
| 164 buffer.write(type.toString()); |
| 165 } |
| 166 } |
| 167 |
| 168 void _appendTypeArguments(StringBuffer buffer, List<DartType> typeArguments) { |
| 169 _appendList<DartType>(buffer, '<', '>', typeArguments, ', ', |
| 170 (type) => _appendType(buffer, type)); |
| 171 } |
| 102 } | 172 } |
| 173 |
| 174 /** |
| 175 * Instance of [InstrumentationValue] describing a list of [DartType]s. |
| 176 */ |
| 177 class _InstrumentationValueForTypeArgs extends fasta.InstrumentationValue { |
| 178 final List<DartType> types; |
| 179 |
| 180 const _InstrumentationValueForTypeArgs(this.types); |
| 181 |
| 182 @override |
| 183 String toString() => types |
| 184 .map((type) => new _InstrumentationValueForType(type).toString()) |
| 185 .join(', '); |
| 186 } |
| 187 |
| 188 /** |
| 189 * Visitor for ASTs that reports instrumentation for types. |
| 190 */ |
| 191 class _InstrumentationVisitor extends RecursiveAstVisitor<Null> { |
| 192 final fasta.Instrumentation _instrumentation; |
| 193 final Uri uri; |
| 194 |
| 195 _InstrumentationVisitor(this._instrumentation, this.uri); |
| 196 |
| 197 visitFunctionExpression(FunctionExpression node) { |
| 198 super.visitFunctionExpression(node); |
| 199 if (node.parent is! FunctionDeclaration) { |
| 200 DartType type = node.staticType; |
| 201 if (type is FunctionType) { |
| 202 _instrumentation.record(uri, node.offset, 'returnType', |
| 203 new _InstrumentationValueForType(type.returnType)); |
| 204 List<FormalParameter> parameters = node.parameters.parameters; |
| 205 for (int i = 0; i < parameters.length; i++) { |
| 206 FormalParameter parameter = parameters[i]; |
| 207 if (parameter is SimpleFormalParameter && parameter.type == null) { |
| 208 _recordType(parameter.offset, type.parameters[i].type); |
| 209 } |
| 210 } |
| 211 } |
| 212 } |
| 213 } |
| 214 |
| 215 visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 216 super.visitInstanceCreationExpression(node); |
| 217 DartType type = node.staticType; |
| 218 if (type is InterfaceType) { |
| 219 if (type.typeParameters.isNotEmpty && |
| 220 node.constructorName.type.typeArguments == null) { |
| 221 _recordTypeArguments(node.offset, type.typeArguments); |
| 222 } |
| 223 } |
| 224 } |
| 225 |
| 226 visitSimpleIdentifier(SimpleIdentifier node) { |
| 227 super.visitSimpleIdentifier(node); |
| 228 Element element = node.staticElement; |
| 229 if (element is LocalVariableElement && node.inGetterContext()) { |
| 230 int offset = node.offset; |
| 231 DartType type = node.staticType; |
| 232 if (identical(type, element.type)) { |
| 233 _instrumentation.record(uri, offset, 'promotedType', |
| 234 const fasta.InstrumentationValueLiteral('none')); |
| 235 } else { |
| 236 _instrumentation.record(uri, offset, 'promotedType', |
| 237 new _InstrumentationValueForType(type)); |
| 238 } |
| 239 } |
| 240 } |
| 241 |
| 242 visitVariableDeclarationList(VariableDeclarationList node) { |
| 243 super.visitVariableDeclarationList(node); |
| 244 if (node.type == null) { |
| 245 for (VariableDeclaration variable in node.variables) { |
| 246 VariableElement element = variable.element; |
| 247 if (element is LocalVariableElement) { |
| 248 _recordType(variable.name.offset, element.type); |
| 249 } else { |
| 250 _recordTopType(variable.name.offset, element.type); |
| 251 } |
| 252 } |
| 253 } |
| 254 } |
| 255 |
| 256 void _recordTopType(int offset, DartType type) { |
| 257 _instrumentation.record( |
| 258 uri, offset, 'topType', new _InstrumentationValueForType(type)); |
| 259 } |
| 260 |
| 261 void _recordType(int offset, DartType type) { |
| 262 _instrumentation.record( |
| 263 uri, offset, 'type', new _InstrumentationValueForType(type)); |
| 264 } |
| 265 |
| 266 void _recordTypeArguments(int offset, List<DartType> typeArguments) { |
| 267 _instrumentation.record(uri, offset, 'typeArgs', |
| 268 new _InstrumentationValueForTypeArgs(typeArguments)); |
| 269 } |
| 270 } |
| OLD | NEW |