| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:front_end/src/api_prototype/front_end.dart'; |
| import 'package:front_end/src/testing/compiler_common.dart'; |
| import 'package:kernel/kernel.dart'; |
| |
| import 'package:test/test.dart'; |
| |
| void main() { |
| test('summary has no source-info by default', () async { |
| var summary = await summarize(['a.dart'], allSources); |
| var component = loadComponentFromBytes(summary!); |
| |
| // Note: the kernel representation always includes the Uri entries, but |
| // doesn't include the actual source here. |
| for (Source source in component.uriToSource.values) { |
| expect(source.source.length, 0); |
| expect(source.lineStarts!.length, 0); |
| } |
| }); |
| |
| test('summary includes declarations, but no method bodies', () async { |
| var summary = await summarize(['a.dart'], allSources); |
| var component = loadComponentFromBytes(summary!); |
| var aLib = findLibrary(component, 'a.dart'); |
| expect(aLib.importUri.path, '/a/b/c/a.dart'); |
| var classA = aLib.classes.first; |
| expect(classA.name, 'A'); |
| var fooMethod = classA.procedures.first; |
| expect(fooMethod.name.text, 'foo'); |
| expect(fooMethod.function.body is EmptyStatement, isTrue); |
| }); |
| |
| test('dependencies can be combined without conflict', () async { |
| var summaryA = await summarize(['a.dart'], allSources); |
| var sourcesWithA = new Map<String, dynamic>.from(allSources); |
| sourcesWithA['a.dill'] = summaryA; |
| |
| var summaryBC = await summarize(['b.dart', 'c.dart'], sourcesWithA, |
| additionalDills: ['a.dill']); |
| |
| var sourcesWithABC = new Map<String, dynamic>.from(sourcesWithA); |
| sourcesWithABC['bc.dill'] = summaryBC; |
| |
| // Note: a is loaded first, bc.dill have a.dart as an external reference so |
| // we want to ensure loading them here will not create a problem. |
| var summaryD = await summarize(['d.dart'], sourcesWithABC, |
| additionalDills: ['a.dill', 'bc.dill']); |
| |
| checkDSummary(summaryD!); |
| }); |
| |
| test('dependencies can be combined in any order', () async { |
| var summaryA = await summarize(['a.dart'], allSources); |
| var sourcesWithA = new Map<String, dynamic>.from(allSources); |
| sourcesWithA['a.dill'] = summaryA; |
| |
| var summaryBC = await summarize(['b.dart', 'c.dart'], sourcesWithA, |
| additionalDills: ['a.dill']); |
| |
| var sourcesWithABC = new Map<String, dynamic>.from(sourcesWithA); |
| sourcesWithABC['bc.dill'] = summaryBC; |
| |
| // Note: unlike the previous test now bc.dill is loaded first and contains |
| // an external definition of library a.dart. Using this order also works |
| // because we share a CanonicalName root to resolve names across multiple |
| // dill files and because of how the kernel loader merges definitions. |
| var summaryD = await summarize(['d.dart'], sourcesWithABC, |
| additionalDills: ['bc.dill', 'a.dill']); |
| checkDSummary(summaryD!); |
| }); |
| |
| test('dependencies not included in truncated summaries', () async { |
| // Note: by default this test is loading the SDK from summaries. |
| var summaryA = await summarize(['a.dart'], allSources, truncate: true); |
| var component = loadComponentFromBytes(summaryA!); |
| expect(component.libraries.length, 1); |
| expect( |
| component.libraries.single.importUri.path.endsWith('a.dart'), isTrue); |
| |
| var sourcesWithA = new Map<String, dynamic>.from(allSources); |
| sourcesWithA['a.dill'] = summaryA; |
| var summaryB = await summarize(['b.dart'], sourcesWithA, |
| additionalDills: ['a.dill'], truncate: true); |
| component = loadComponentFromBytes(summaryB!); |
| expect(component.libraries.length, 1); |
| expect( |
| component.libraries.single.importUri.path.endsWith('b.dart'), isTrue); |
| }); |
| |
| test('summarization by default is not hermetic', () async { |
| var errors = []; |
| var options = new CompilerOptions()..onDiagnostic = errors.add; |
| await summarize(['b.dart'], allSources, options: options); |
| expect(errors, isEmpty); |
| }); |
| |
| // TODO(sigmund): test trimDependencies when it is part of the public API. |
| } |
| |
| var allSources = <String, String>{ |
| 'a.dart': 'class A { foo() { print("hi"); } }', |
| 'b.dart': 'import "a.dart"; class B extends A {}', |
| 'c.dart': 'class C { bar() => 1; }', |
| 'd.dart': ''' |
| import "a.dart"; |
| import "b.dart"; |
| import "c.dart"; |
| class D extends B with C implements A { }''', |
| }; |
| |
| /// Helper function to check that some expectations from the summary of D. |
| void checkDSummary(List<int> summary) { |
| var component = loadComponentFromBytes(summary); |
| var aLib = findLibrary(component, 'a.dart'); |
| var bLib = findLibrary(component, 'b.dart'); |
| var dLib = findLibrary(component, 'd.dart'); |
| |
| // The type-hierarchy for A, B, D is visible and correct |
| var aClass = aLib.classes.firstWhere((c) => c.name == 'A'); |
| var bClass = bLib.classes.firstWhere((c) => c.name == 'B'); |
| expect(bClass.superclass, same(aClass)); |
| |
| var dClass = dLib.classes.firstWhere((c) => c.name == 'D'); |
| expect(dClass.superclass!.superclass, same(bClass)); |
| |
| var dInterface = dClass.implementedTypes.first.classNode; |
| expect(dInterface, same(aClass)); |
| } |