blob: 3a95b465c0c16a70ac180e1510789682e7f26ef7 [file] [log] [blame]
// Copyright (c) 2019, 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 'dart:typed_data';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'element_text.dart';
import 'resynthesize_common.dart';
import 'test_strategies.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ResynthesizeAstKeepLinkingTest);
defineReflectiveTests(ResynthesizeAstFromBytesTest);
// defineReflectiveTests(ApplyCheckElementTextReplacements);
});
}
@reflectiveTest
class ApplyCheckElementTextReplacements {
test_applyReplacements() {
applyCheckElementTextReplacements();
}
}
@reflectiveTest
abstract class ResynthesizeAst2Test extends AbstractResynthesizeTest
with ResynthesizeTestCases {
/// The shared SDK bundle, computed once and shared among test invocations.
static _SdkBundle? _sdkBundle;
/// We need to test both cases - when we keep linking libraries (happens for
/// new or invalidated libraries), and when we load libraries from bytes
/// (happens internally in Blaze or when we have cached summaries).
bool get keepLinkingLibraries;
_SdkBundle get sdkBundle {
if (_sdkBundle != null) {
return _sdkBundle!;
}
var featureSet = FeatureSet.latestLanguageVersion();
var inputLibraries = <LinkInputLibrary>[];
for (var sdkLibrary in sdk.sdkLibraries) {
var source = sourceFactory.resolveUri(null, sdkLibrary.shortName)!;
var text = getFile(source.fullName).readAsStringSync();
var unit = parseText(text, featureSet);
var inputUnits = <LinkInputUnit>[];
_addLibraryUnits(source, unit, inputUnits, featureSet);
inputLibraries.add(
LinkInputLibrary(
source: source,
units: inputUnits,
),
);
}
var elementFactory = LinkedElementFactory(
AnalysisContextImpl(
SynchronousSession(
AnalysisOptionsImpl(),
declaredVariables,
),
sourceFactory,
),
_AnalysisSessionForLinking(),
Reference.root(),
);
var sdkLinkResult = link(elementFactory, inputLibraries, true);
return _sdkBundle = _SdkBundle(
resolutionBytes: sdkLinkResult.resolutionBytes,
);
}
@override
Future<LibraryElementImpl> checkLibrary(String text,
{bool allowErrors = false, bool dumpSummaries = false}) async {
var source = addTestSource(text);
var inputLibraries = <LinkInputLibrary>[];
_addNonDartLibraries({}, inputLibraries, source);
var unitsInformativeBytes = <Uri, Uint8List>{};
for (var inputLibrary in inputLibraries) {
for (var inputUnit in inputLibrary.units) {
var informativeBytes = writeUnitInformative(inputUnit.unit);
unitsInformativeBytes[inputUnit.uri] = informativeBytes;
}
}
var analysisContext = AnalysisContextImpl(
SynchronousSession(
AnalysisOptionsImpl()..contextFeatures = featureSet,
declaredVariables,
),
sourceFactory,
);
var elementFactory = LinkedElementFactory(
analysisContext,
_AnalysisSessionForLinking(),
Reference.root(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: {},
resolutionBytes: sdkBundle.resolutionBytes,
),
);
var linkResult = link(elementFactory, inputLibraries, true);
if (!keepLinkingLibraries) {
elementFactory.removeBundle(
inputLibraries.map((e) => e.uriStr).toSet(),
);
elementFactory.addBundle(
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: unitsInformativeBytes,
resolutionBytes: linkResult.resolutionBytes,
),
);
}
return elementFactory.libraryOfUri('${source.uri}')!;
}
void setUp() {
featureSet = FeatureSets.nullSafe;
}
void _addLibraryUnits(
Source definingSource,
CompilationUnit definingUnit,
List<LinkInputUnit> units,
FeatureSet featureSet,
) {
units.add(
LinkInputUnit(
partDirectiveIndex: null,
source: definingSource,
isSynthetic: false,
unit: definingUnit,
),
);
var partDirectiveIndex = -1;
for (var directive in definingUnit.directives) {
if (directive is PartDirective) {
++partDirectiveIndex;
var relativeUriStr = directive.uri.stringValue;
var partSource = sourceFactory.resolveUri(
definingSource,
relativeUriStr,
);
if (partSource != null) {
var text = _readSafely(partSource.fullName);
var unit = parseText(text, featureSet);
units.add(
LinkInputUnit(
partDirectiveIndex: partDirectiveIndex,
partUriStr: relativeUriStr,
source: partSource,
isSynthetic: false,
unit: unit,
),
);
}
}
}
}
void _addNonDartLibraries(
Set<Source> addedLibraries,
List<LinkInputLibrary> libraries,
Source? source,
) {
if (source == null ||
source.uri.isScheme('dart') ||
!addedLibraries.add(source)) {
return;
}
var text = _readSafely(source.fullName);
var unit = parseText(text, featureSet);
var units = <LinkInputUnit>[];
_addLibraryUnits(source, unit, units, featureSet);
libraries.add(
LinkInputLibrary(
source: source,
units: units,
),
);
void addRelativeUriStr(StringLiteral uriNode) {
var uriStr = uriNode.stringValue;
var uriSource = sourceFactory.resolveUri(source, uriStr);
_addNonDartLibraries(addedLibraries, libraries, uriSource);
}
for (var directive in unit.directives) {
if (directive is NamespaceDirective) {
addRelativeUriStr(directive.uri);
for (var configuration in directive.configurations) {
addRelativeUriStr(configuration.uri);
}
}
}
}
String _readSafely(String path) {
try {
var file = resourceProvider.getFile(path);
return file.readAsStringSync();
} catch (_) {
return '';
}
}
}
@reflectiveTest
class ResynthesizeAstFromBytesTest extends ResynthesizeAst2Test {
@override
bool get keepLinkingLibraries => false;
}
@reflectiveTest
class ResynthesizeAstKeepLinkingTest extends ResynthesizeAst2Test {
@override
bool get keepLinkingLibraries => true;
}
class _AnalysisSessionForLinking implements AnalysisSessionImpl {
@override
final ClassHierarchy classHierarchy = ClassHierarchy();
@override
InheritanceManager3 inheritanceManager = InheritanceManager3();
@override
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
class _SdkBundle {
final Uint8List resolutionBytes;
_SdkBundle({
required this.resolutionBytes,
});
}