Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: pkg/analyzer/test/src/task/strong/front_end_inference_test.dart

Issue 3002893002: Begin writing tests of the runtime checks needed for Dart 2.0 soundness. (Closed)
Patch Set: Add more annotations to the "checks" category Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/strong/front_end_runtime_check_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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';
6 import 'dart:convert';
7 import 'dart:io';
8
9 import 'package:analyzer/dart/ast/ast.dart'; 5 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 6 import 'package:analyzer/dart/ast/token.dart';
11 import 'package:analyzer/dart/ast/visitor.dart'; 7 import 'package:analyzer/dart/ast/visitor.dart';
12 import 'package:analyzer/dart/element/element.dart'; 8 import 'package:analyzer/dart/element/element.dart';
13 import 'package:analyzer/dart/element/type.dart'; 9 import 'package:analyzer/dart/element/type.dart';
14 import 'package:analyzer/src/dart/analysis/driver.dart'; 10 import 'package:analyzer/src/generated/resolver.dart';
15 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
16 import 'package:analyzer/src/generated/parser.dart';
17 import 'package:analyzer/src/generated/scanner.dart'; 11 import 'package:analyzer/src/generated/scanner.dart';
18 import 'package:analyzer/src/generated/source.dart';
19 import 'package:analyzer/src/generated/utilities_dart.dart';
20 import 'package:front_end/src/base/instrumentation.dart' as fasta; 12 import 'package:front_end/src/base/instrumentation.dart' as fasta;
21 import 'package:front_end/src/fasta/compiler_context.dart' as fasta; 13 import 'package:front_end/src/fasta/compiler_context.dart' as fasta;
22 import 'package:front_end/src/fasta/testing/validating_instrumentation.dart' 14 import 'package:front_end/src/fasta/testing/validating_instrumentation.dart'
23 as fasta; 15 as fasta;
24 import 'package:front_end/src/fasta/util/relativize.dart' show relativizeUri;
25 import 'package:kernel/kernel.dart' as fasta; 16 import 'package:kernel/kernel.dart' as fasta;
26 import 'package:path/path.dart' as pathos;
27 import 'package:test/test.dart'; 17 import 'package:test/test.dart';
28 import 'package:test_reflective_loader/test_reflective_loader.dart'; 18 import 'package:test_reflective_loader/test_reflective_loader.dart';
29 19
30 import '../../dart/analysis/base.dart'; 20 import 'front_end_test_common.dart';
31 21
32 main() { 22 main() {
33 // Use a group() wrapper to specify the timeout. 23 // Use a group() wrapper to specify the timeout.
34 group('front_end_inference_test', () { 24 group('front_end_inference_test', () {
35 defineReflectiveSuite(() { 25 defineReflectiveSuite(() {
36 defineReflectiveTests(RunFrontEndInferenceTest); 26 defineReflectiveTests(RunFrontEndInferenceTest);
37 }); 27 });
38 }, timeout: new Timeout(const Duration(seconds: 120))); 28 }, timeout: new Timeout(const Duration(seconds: 120)));
39 } 29 }
40 30
41 /// Set this to `true` to cause expectation comments to be updated.
42 const bool fixProblems = false;
43
44 @reflectiveTest 31 @reflectiveTest
45 class RunFrontEndInferenceTest { 32 class RunFrontEndInferenceTest extends RunFrontEndTest {
46 test_run() async {
47 String pkgPath = _findPkgRoot();
48 String fePath = pathos.join(pkgPath, 'front_end', 'testcases', 'inference');
49 List<File> dartFiles = new Directory(fePath)
50 .listSync()
51 .where((entry) => entry is File && entry.path.endsWith('.dart'))
52 .map((entry) => entry as File)
53 .toList();
54
55 var allProblems = new StringBuffer();
56 for (File file in dartFiles) {
57 var test = new _FrontEndInferenceTest();
58 await test.setUp();
59 try {
60 String code = file.readAsStringSync();
61 String problems = await test.runTest(file.path, code);
62 if (problems != null) {
63 allProblems.writeln(problems);
64 }
65 } finally {
66 await test.tearDown();
67 }
68 }
69 if (allProblems.isNotEmpty) {
70 fail(allProblems.toString());
71 }
72 }
73
74 /**
75 * Expects that the [Platform.script] is a test inside of `pkg/analyzer/test`
76 * folder, and return the absolute path of the `pkg` folder.
77 */
78 String _findPkgRoot() {
79 String scriptPath = pathos.fromUri(Platform.script);
80 List<String> parts = pathos.split(scriptPath);
81 for (int i = 0; i < parts.length - 2; i++) {
82 if (parts[i] == 'pkg' &&
83 parts[i + 1] == 'analyzer' &&
84 parts[i + 2] == 'test') {
85 return pathos.joinAll(parts.sublist(0, i + 1));
86 }
87 }
88 throw new StateError('Unable to find sdk/pkg/ in $scriptPath');
89 }
90 }
91
92 class _ElementNamer {
93 final ConstructorElement currentFactoryConstructor;
94
95 _ElementNamer(this.currentFactoryConstructor);
96
97 void appendElementName(StringBuffer buffer, Element element) {
98 // Synthetic FunctionElement(s) don't have a name or enclosing library.
99 if (element.isSynthetic && element is FunctionElement) {
100 return;
101 }
102
103 var enclosing = element.enclosingElement;
104 if (enclosing is CompilationUnitElement) {
105 enclosing = enclosing.enclosingElement;
106 } else if (enclosing is ClassElement &&
107 currentFactoryConstructor != null &&
108 identical(enclosing, currentFactoryConstructor.enclosingElement) &&
109 element is TypeParameterElement) {
110 enclosing = currentFactoryConstructor;
111 }
112 if (enclosing != null) {
113 if (enclosing is LibraryElement &&
114 (enclosing.name == 'dart.core' ||
115 enclosing.name == 'dart.async' ||
116 enclosing.name == 'test')) {
117 // For brevity, omit library name
118 } else {
119 appendElementName(buffer, enclosing);
120 buffer.write('::');
121 }
122 }
123
124 String name = element.name ?? '';
125 if (element is ConstructorElement && name == '') {
126 name = '•';
127 } else if (name.endsWith('=') &&
128 element is PropertyAccessorElement &&
129 element.isSetter) {
130 name = name.substring(0, name.length - 1);
131 }
132 buffer.write(name);
133 }
134 }
135
136 class _FrontEndInferenceTest extends BaseAnalysisDriverTest {
137 @override 33 @override
138 AnalysisOptionsImpl createAnalysisOptions() => 34 get testSubdir => 'inference';
139 super.createAnalysisOptions()..enableAssertInitializer = true;
140
141 Future<String> runTest(String path, String code) {
142 return fasta.CompilerContext.runWithDefaultOptions((_) async {
143 Uri uri = provider.pathContext.toUri(path);
144
145 List<int> lineStarts = new LineInfo.fromContent(code).lineStarts;
146 fasta.CompilerContext.current.uriToSource[relativizeUri(uri).toString()] =
147 new fasta.Source(lineStarts, UTF8.encode(code));
148
149 var validation = new fasta.ValidatingInstrumentation();
150 await validation.loadExpectations(uri);
151
152 _addFileAndImports(path, code);
153
154 AnalysisResult result = await driver.getResult(path);
155 result.unit.accept(new _InstrumentationVisitor(validation, uri));
156
157 validation.finish();
158
159 if (validation.hasProblems) {
160 if (fixProblems) {
161 validation.fixSource(uri, true);
162 return null;
163 } else {
164 return validation.problemsAsString;
165 }
166 } else {
167 return null;
168 }
169 });
170 }
171
172 void _addFileAndImports(String path, String code) {
173 provider.newFile(path, code);
174 var source = null;
175 var analysisErrorListener = null;
176 var scanner = new Scanner(
177 source, new CharSequenceReader(code), analysisErrorListener);
178 var token = scanner.tokenize();
179 var compilationUnit =
180 new Parser(source, analysisErrorListener).parseDirectives(token);
181 for (var directive in compilationUnit.directives) {
182 if (directive is UriBasedDirective) {
183 Uri uri = Uri.parse(directive.uri.stringValue);
184 if (uri.scheme == 'dart') {
185 // Ignore these--they should be in the mock SDK.
186 } else if (uri.scheme == '') {
187 var pathSegments = uri.pathSegments;
188 // For these tests we don't support any directory traversal; we just
189 // assume the URI is the name of a file in the same directory as all
190 // the other tests.
191 if (pathSegments.length != 1) fail('URI too complex: $uri');
192 var referencedPath =
193 pathos.join(pathos.dirname(path), pathSegments[0]);
194 if (!provider.getFile(referencedPath).exists) {
195 var referencedCode = new File(referencedPath).readAsStringSync();
196 _addFileAndImports(referencedPath, referencedCode);
197 }
198 }
199 }
200 }
201 }
202 }
203
204 /// Instance of [InstrumentationValue] describing an [ExecutableElement].
205 class _InstrumentationValueForExecutableElement
206 extends fasta.InstrumentationValue {
207 final ExecutableElement element;
208 final _ElementNamer elementNamer;
209
210 _InstrumentationValueForExecutableElement(this.element, this.elementNamer);
211 35
212 @override 36 @override
213 String toString() { 37 void visitUnit(TypeProvider typeProvider, CompilationUnit unit,
214 StringBuffer buffer = new StringBuffer(); 38 fasta.ValidatingInstrumentation validation, Uri uri) {
215 elementNamer.appendElementName(buffer, element); 39 unit.accept(new _InstrumentationVisitor(validation, uri));
216 return buffer.toString();
217 } 40 }
218 } 41 }
219 42
220 /** 43 /**
221 * Instance of [InstrumentationValue] describing a [DartType].
222 */
223 class _InstrumentationValueForType extends fasta.InstrumentationValue {
224 final DartType type;
225 final _ElementNamer elementNamer;
226
227 _InstrumentationValueForType(this.type, this.elementNamer);
228
229 @override
230 String toString() {
231 StringBuffer buffer = new StringBuffer();
232 _appendType(buffer, type);
233 return buffer.toString();
234 }
235
236 void _appendList<T>(StringBuffer buffer, String open, String close,
237 List<T> items, String separator, writeItem(T item),
238 {bool includeEmpty: false}) {
239 if (!includeEmpty && items.isEmpty) {
240 return;
241 }
242 buffer.write(open);
243 bool first = true;
244 for (T item in items) {
245 if (!first) {
246 buffer.write(separator);
247 }
248 writeItem(item);
249 first = false;
250 }
251 buffer.write(close);
252 }
253
254 void _appendParameters(
255 StringBuffer buffer, List<ParameterElement> parameters) {
256 buffer.write('(');
257 bool first = true;
258 ParameterKind lastKind = ParameterKind.REQUIRED;
259 for (var parameter in parameters) {
260 if (!first) {
261 buffer.write(', ');
262 }
263 if (lastKind != parameter.parameterKind) {
264 if (parameter.parameterKind == ParameterKind.POSITIONAL) {
265 buffer.write('[');
266 } else if (parameter.parameterKind == ParameterKind.NAMED) {
267 buffer.write('{');
268 }
269 }
270 if (parameter.parameterKind == ParameterKind.NAMED) {
271 buffer.write(parameter.name);
272 buffer.write(': ');
273 }
274 _appendType(buffer, parameter.type);
275 lastKind = parameter.parameterKind;
276 first = false;
277 }
278 if (lastKind == ParameterKind.POSITIONAL) {
279 buffer.write(']');
280 } else if (lastKind == ParameterKind.NAMED) {
281 buffer.write('}');
282 }
283 buffer.write(')');
284 }
285
286 void _appendType(StringBuffer buffer, DartType type) {
287 if (type is FunctionType) {
288 if (type.typeFormals.isNotEmpty) {
289 _appendTypeFormals(buffer, type.typeFormals);
290 }
291 _appendParameters(buffer, type.parameters);
292 buffer.write(' -> ');
293 _appendType(buffer, type.returnType);
294 } else if (type is InterfaceType) {
295 ClassElement element = type.element;
296 elementNamer.appendElementName(buffer, element);
297 _appendTypeArguments(buffer, type.typeArguments);
298 } else if (type.isBottom) {
299 buffer.write('<BottomType>');
300 } else if (type is TypeParameterType) {
301 elementNamer.appendElementName(buffer, type.element);
302 } else {
303 buffer.write(type.toString());
304 }
305 }
306
307 void _appendTypeArguments(StringBuffer buffer, List<DartType> typeArguments) {
308 _appendList<DartType>(buffer, '<', '>', typeArguments, ', ',
309 (type) => _appendType(buffer, type));
310 }
311
312 void _appendTypeFormals(
313 StringBuffer buffer, List<TypeParameterElement> typeFormals) {
314 _appendList<TypeParameterElement>(buffer, '<', '>', typeFormals, ', ',
315 (formal) {
316 buffer.write(formal.name);
317 buffer.write(' extends ');
318 if (formal.bound == null) {
319 buffer.write('Object');
320 } else {
321 _appendType(buffer, formal.bound);
322 }
323 });
324 }
325 }
326
327 /**
328 * Instance of [InstrumentationValue] describing a list of [DartType]s.
329 */
330 class _InstrumentationValueForTypeArgs extends fasta.InstrumentationValue {
331 final List<DartType> types;
332 final _ElementNamer elementNamer;
333
334 const _InstrumentationValueForTypeArgs(this.types, this.elementNamer);
335
336 @override
337 String toString() => types
338 .map((type) =>
339 new _InstrumentationValueForType(type, elementNamer).toString())
340 .join(', ');
341 }
342
343 /**
344 * Visitor for ASTs that reports instrumentation for types. 44 * Visitor for ASTs that reports instrumentation for types.
345 */ 45 */
346 class _InstrumentationVisitor extends RecursiveAstVisitor<Null> { 46 class _InstrumentationVisitor extends RecursiveAstVisitor<Null> {
347 final fasta.Instrumentation _instrumentation; 47 final fasta.Instrumentation _instrumentation;
348 final Uri uri; 48 final Uri uri;
349 _ElementNamer elementNamer = new _ElementNamer(null); 49 ElementNamer elementNamer = new ElementNamer(null);
350 50
351 _InstrumentationVisitor(this._instrumentation, this.uri); 51 _InstrumentationVisitor(this._instrumentation, this.uri);
352 52
353 visitBinaryExpression(BinaryExpression node) { 53 visitBinaryExpression(BinaryExpression node) {
354 super.visitBinaryExpression(node); 54 super.visitBinaryExpression(node);
355 _recordTarget(node.operator.charOffset, node.staticElement); 55 _recordTarget(node.operator.charOffset, node.staticElement);
356 } 56 }
357 57
358 @override 58 @override
359 visitConstructorDeclaration(ConstructorDeclaration node) { 59 visitConstructorDeclaration(ConstructorDeclaration node) {
360 _ElementNamer oldElementNamer = elementNamer; 60 ElementNamer oldElementNamer = elementNamer;
361 if (node.factoryKeyword != null) { 61 if (node.factoryKeyword != null) {
362 // Factory constructors are represented in kernel as static methods, so 62 // Factory constructors are represented in kernel as static methods, so
363 // their type parameters get replicated, e.g.: 63 // their type parameters get replicated, e.g.:
364 // class C<T> { 64 // class C<T> {
365 // factory C.ctor() { 65 // factory C.ctor() {
366 // T t; // Refers to C::T 66 // T t; // Refers to C::T
367 // ... 67 // ...
368 // } 68 // }
369 // } 69 // }
370 // gets converted to: 70 // gets converted to:
371 // class C<T> { 71 // class C<T> {
372 // static C<T> C.ctor<T>() { 72 // static C<T> C.ctor<T>() {
373 // T t; // Refers to C::ctor::T 73 // T t; // Refers to C::ctor::T
374 // ... 74 // ...
375 // } 75 // }
376 // } 76 // }
377 // So to match kernel behavior, we have to arrange for this renaming to 77 // So to match kernel behavior, we have to arrange for this renaming to
378 // happen during output. 78 // happen during output.
379 elementNamer = new _ElementNamer(node.element); 79 elementNamer = new ElementNamer(node.element);
380 } 80 }
381 super.visitConstructorDeclaration(node); 81 super.visitConstructorDeclaration(node);
382 elementNamer = oldElementNamer; 82 elementNamer = oldElementNamer;
383 } 83 }
384 84
385 @override 85 @override
386 visitDeclaredIdentifier(DeclaredIdentifier node) { 86 visitDeclaredIdentifier(DeclaredIdentifier node) {
387 super.visitDeclaredIdentifier(node); 87 super.visitDeclaredIdentifier(node);
388 if (node.type == null) { 88 if (node.type == null) {
389 _recordType(node.identifier.offset, node.element.type); 89 _recordType(node.identifier.offset, node.element.type);
390 } 90 }
391 } 91 }
392 92
393 @override 93 @override
394 visitFunctionDeclaration(FunctionDeclaration node) { 94 visitFunctionDeclaration(FunctionDeclaration node) {
395 super.visitFunctionDeclaration(node); 95 super.visitFunctionDeclaration(node);
396 96
397 bool isSetter = node.element.kind == ElementKind.SETTER; 97 bool isSetter = node.element.kind == ElementKind.SETTER;
398 bool isLocalFunction = node.element is LocalElement && 98 bool isLocalFunction = node.element is LocalElement &&
399 node.element.enclosingElement is! CompilationUnitElement; 99 node.element.enclosingElement is! CompilationUnitElement;
400 100
401 if (isSetter || isLocalFunction) { 101 if (isSetter || isLocalFunction) {
402 if (node.returnType == null) { 102 if (node.returnType == null) {
403 _instrumentation.record( 103 _instrumentation.record(
404 uri, 104 uri,
405 node.name.offset, 105 node.name.offset,
406 isSetter ? 'topType' : 'returnType', 106 isSetter ? 'topType' : 'returnType',
407 new _InstrumentationValueForType( 107 new InstrumentationValueForType(
408 node.element.returnType, elementNamer)); 108 node.element.returnType, elementNamer));
409 } 109 }
410 var parameters = node.functionExpression.parameters; 110 var parameters = node.functionExpression.parameters;
411 for (var parameter in parameters.parameters) { 111 for (var parameter in parameters.parameters) {
412 // Note: it's tempting to check `parameter.type == null`, but that 112 // Note: it's tempting to check `parameter.type == null`, but that
413 // doesn't work because of function-typed formal parameter syntax. 113 // doesn't work because of function-typed formal parameter syntax.
414 if (parameter.element.hasImplicitType) { 114 if (parameter.element.hasImplicitType) {
415 _recordType(parameter.identifier.offset, parameter.element.type); 115 _recordType(parameter.identifier.offset, parameter.element.type);
416 } 116 }
417 } 117 }
418 } 118 }
419 } 119 }
420 120
421 visitFunctionExpression(FunctionExpression node) { 121 visitFunctionExpression(FunctionExpression node) {
422 super.visitFunctionExpression(node); 122 super.visitFunctionExpression(node);
423 if (node.parent is! FunctionDeclaration) { 123 if (node.parent is! FunctionDeclaration) {
424 DartType type = node.staticType; 124 DartType type = node.staticType;
425 if (type is FunctionType) { 125 if (type is FunctionType) {
426 _instrumentation.record(uri, node.parameters.offset, 'returnType', 126 _instrumentation.record(uri, node.parameters.offset, 'returnType',
427 new _InstrumentationValueForType(type.returnType, elementNamer)); 127 new InstrumentationValueForType(type.returnType, elementNamer));
428 List<FormalParameter> parameters = node.parameters.parameters; 128 List<FormalParameter> parameters = node.parameters.parameters;
429 for (int i = 0; i < parameters.length; i++) { 129 for (int i = 0; i < parameters.length; i++) {
430 FormalParameter parameter = parameters[i]; 130 FormalParameter parameter = parameters[i];
431 NormalFormalParameter normalParameter = 131 NormalFormalParameter normalParameter =
432 parameter is DefaultFormalParameter 132 parameter is DefaultFormalParameter
433 ? parameter.parameter 133 ? parameter.parameter
434 : parameter; 134 : parameter;
435 if (normalParameter is SimpleFormalParameter && 135 if (normalParameter is SimpleFormalParameter &&
436 normalParameter.type == null) { 136 normalParameter.type == null) {
437 _recordType(parameter.offset, type.parameters[i].type); 137 _recordType(parameter.offset, type.parameters[i].type);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 !node.inDeclarationContext() && 262 !node.inDeclarationContext() &&
563 (node.inGetterContext() || node.inSetterContext())) { 263 (node.inGetterContext() || node.inSetterContext())) {
564 _recordTarget(node.offset, element); 264 _recordTarget(node.offset, element);
565 } 265 }
566 void recordPromotions(DartType elementType) { 266 void recordPromotions(DartType elementType) {
567 if (node.inGetterContext() && !node.inDeclarationContext()) { 267 if (node.inGetterContext() && !node.inDeclarationContext()) {
568 int offset = node.offset; 268 int offset = node.offset;
569 DartType type = node.staticType; 269 DartType type = node.staticType;
570 if (!identical(type, elementType)) { 270 if (!identical(type, elementType)) {
571 _instrumentation.record(uri, offset, 'promotedType', 271 _instrumentation.record(uri, offset, 'promotedType',
572 new _InstrumentationValueForType(type, elementNamer)); 272 new InstrumentationValueForType(type, elementNamer));
573 } 273 }
574 } 274 }
575 } 275 }
576 276
577 if (element is LocalVariableElement) { 277 if (element is LocalVariableElement) {
578 recordPromotions(element.type); 278 recordPromotions(element.type);
579 } else if (element is ParameterElement) { 279 } else if (element is ParameterElement) {
580 recordPromotions(element.type); 280 recordPromotions(element.type);
581 } 281 }
582 } 282 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 f.typeFormals.isEmpty) { 317 f.typeFormals.isEmpty) {
618 return _recoverTypeArguments(g, f); 318 return _recoverTypeArguments(g, f);
619 } else { 319 } else {
620 return const []; 320 return const [];
621 } 321 }
622 } 322 }
623 323
624 void _recordTarget(int offset, Element element) { 324 void _recordTarget(int offset, Element element) {
625 if (element is ExecutableElement) { 325 if (element is ExecutableElement) {
626 _instrumentation.record(uri, offset, 'target', 326 _instrumentation.record(uri, offset, 'target',
627 new _InstrumentationValueForExecutableElement(element, elementNamer)); 327 new InstrumentationValueForExecutableElement(element, elementNamer));
628 } 328 }
629 } 329 }
630 330
631 void _recordTopType(int offset, DartType type) { 331 void _recordTopType(int offset, DartType type) {
632 _instrumentation.record(uri, offset, 'topType', 332 _instrumentation.record(uri, offset, 'topType',
633 new _InstrumentationValueForType(type, elementNamer)); 333 new InstrumentationValueForType(type, elementNamer));
634 } 334 }
635 335
636 void _recordType(int offset, DartType type) { 336 void _recordType(int offset, DartType type) {
637 _instrumentation.record(uri, offset, 'type', 337 _instrumentation.record(uri, offset, 'type',
638 new _InstrumentationValueForType(type, elementNamer)); 338 new InstrumentationValueForType(type, elementNamer));
639 } 339 }
640 340
641 void _recordTypeArguments(int offset, List<DartType> typeArguments) { 341 void _recordTypeArguments(int offset, List<DartType> typeArguments) {
642 _instrumentation.record(uri, offset, 'typeArgs', 342 _instrumentation.record(uri, offset, 'typeArgs',
643 new _InstrumentationValueForTypeArgs(typeArguments, elementNamer)); 343 new InstrumentationValueForTypeArgs(typeArguments, elementNamer));
644 } 344 }
645 345
646 /// Based on DDC code generator's `_recoverTypeArguments` 346 /// Based on DDC code generator's `_recoverTypeArguments`
647 Iterable<DartType> _recoverTypeArguments(FunctionType g, FunctionType f) { 347 Iterable<DartType> _recoverTypeArguments(FunctionType g, FunctionType f) {
648 assert(identical(g.element, f.element)); 348 assert(identical(g.element, f.element));
649 assert(g.typeFormals.isNotEmpty && f.typeFormals.isEmpty); 349 assert(g.typeFormals.isNotEmpty && f.typeFormals.isEmpty);
650 assert(g.typeFormals.length + g.typeArguments.length == 350 assert(g.typeFormals.length + g.typeArguments.length ==
651 f.typeArguments.length); 351 f.typeArguments.length);
652 return f.typeArguments.skip(g.typeArguments.length); 352 return f.typeArguments.skip(g.typeArguments.length);
653 } 353 }
654 } 354 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/task/strong/front_end_runtime_check_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698