05b4a4e0a8
This CL add support for introspecting members added in Phase 2 from one macro application to the next. Included is a refactoring of the class/member patching where the origin now owns the patches similar to how library patching now works. Change-Id: Ifdf03461d66be3f5a5df4b5bdb1e3da9f4cfd688 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233462 Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
194 lines
6.9 KiB
Dart
194 lines
6.9 KiB
Dart
// 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:io' show Directory, Platform;
|
|
|
|
import 'package:_fe_analyzer_shared/src/testing/features.dart';
|
|
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
|
|
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
|
|
import 'package:front_end/src/api_prototype/compiler_options.dart';
|
|
import 'package:front_end/src/api_prototype/experimental_flags.dart';
|
|
import 'package:front_end/src/fasta/builder/builder.dart';
|
|
import 'package:front_end/src/fasta/builder/member_builder.dart';
|
|
import 'package:front_end/src/fasta/source/source_class_builder.dart';
|
|
import 'package:front_end/src/fasta/source/source_constructor_builder.dart';
|
|
import 'package:front_end/src/fasta/source/source_factory_builder.dart';
|
|
import 'package:front_end/src/fasta/source/source_member_builder.dart';
|
|
import 'package:front_end/src/fasta/source/source_procedure_builder.dart';
|
|
import 'package:front_end/src/testing/id_testing_helper.dart';
|
|
import 'package:front_end/src/testing/id_testing_utils.dart';
|
|
import 'package:kernel/ast.dart';
|
|
|
|
Future<void> main(List<String> args) async {
|
|
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
|
|
await runTests<Features>(dataDir,
|
|
args: args,
|
|
createUriForFileName: createUriForFileName,
|
|
onFailure: onFailure,
|
|
runTest: runTestFor(const PatchingDataComputer(), [
|
|
new TestConfigWithLanguageVersion(
|
|
cfeMarker, 'cfe with libraries specification',
|
|
librariesSpecificationUri: createUriForFileName('libraries.json'),
|
|
experimentalFlags: {ExperimentalFlag.nonNullable: false},
|
|
allowedExperimentalFlags: const AllowedExperimentalFlags()),
|
|
new TestConfigWithLanguageVersion(cfeWithNnbdMarker,
|
|
'cfe with libraries specification and non-nullable',
|
|
librariesSpecificationUri: createUriForFileName('libraries.json'),
|
|
experimentalFlags: {ExperimentalFlag.nonNullable: true},
|
|
allowedExperimentalFlags: const AllowedExperimentalFlags())
|
|
]),
|
|
skipMap: {
|
|
cfeMarker: [
|
|
'opt_in',
|
|
'opt_in_patch',
|
|
'opt_out',
|
|
'opt_out_patch',
|
|
]
|
|
});
|
|
}
|
|
|
|
class TestConfigWithLanguageVersion extends TestConfig {
|
|
TestConfigWithLanguageVersion(String marker, String name,
|
|
{Uri? librariesSpecificationUri,
|
|
Map<ExperimentalFlag, bool> experimentalFlags = const {},
|
|
AllowedExperimentalFlags? allowedExperimentalFlags})
|
|
: super(marker, name,
|
|
librariesSpecificationUri: librariesSpecificationUri,
|
|
explicitExperimentalFlags: experimentalFlags,
|
|
allowedExperimentalFlags: allowedExperimentalFlags);
|
|
|
|
@override
|
|
void customizeCompilerOptions(CompilerOptions options, TestData testData) {
|
|
options.currentSdkVersion = "2.9999";
|
|
}
|
|
}
|
|
|
|
class PatchingDataComputer extends DataComputer<Features> {
|
|
const PatchingDataComputer();
|
|
|
|
@override
|
|
void computeMemberData(TestResultData testResultData, Member member,
|
|
Map<Id, ActualData<Features>> actualMap,
|
|
{bool? verbose}) {
|
|
member.accept(
|
|
new PatchingDataExtractor(testResultData.compilerResult, actualMap));
|
|
}
|
|
|
|
@override
|
|
void computeClassData(TestResultData testResultData, Class cls,
|
|
Map<Id, ActualData<Features>> actualMap,
|
|
{bool? verbose}) {
|
|
new PatchingDataExtractor(testResultData.compilerResult, actualMap)
|
|
.computeForClass(cls);
|
|
}
|
|
|
|
@override
|
|
void computeLibraryData(TestResultData testResultData, Library library,
|
|
Map<Id, ActualData<Features>> actualMap,
|
|
{bool? verbose}) {
|
|
new PatchingDataExtractor(testResultData.compilerResult, actualMap)
|
|
.computeForLibrary(library);
|
|
}
|
|
|
|
@override
|
|
bool get supportsErrors => true;
|
|
|
|
@override
|
|
Features computeErrorData(
|
|
TestResultData testResultData, Id id, List<FormattedMessage> errors) {
|
|
Features features = new Features();
|
|
features[Tags.error] = errorsToText(errors);
|
|
return features;
|
|
}
|
|
|
|
@override
|
|
DataInterpreter<Features> get dataValidator =>
|
|
const FeaturesDataInterpreter();
|
|
}
|
|
|
|
class Tags {
|
|
static const String scope = 'scope';
|
|
static const String kernelMembers = 'kernel-members';
|
|
static const String initializers = 'initializers';
|
|
static const String error = 'message';
|
|
static const String isNonNullableByDefault = 'nnbd';
|
|
static const String patch = 'patch';
|
|
static const String isAbstract = 'isAbstract';
|
|
}
|
|
|
|
class PatchingDataExtractor extends CfeDataExtractor<Features> {
|
|
PatchingDataExtractor(InternalCompilerResult compilerResult,
|
|
Map<Id, ActualData<Features>> actualMap)
|
|
: super(compilerResult, actualMap);
|
|
|
|
@override
|
|
Features computeLibraryValue(Id id, Library library) {
|
|
Features features = new Features();
|
|
features[Tags.isNonNullableByDefault] = '${library.isNonNullableByDefault}';
|
|
return features;
|
|
}
|
|
|
|
@override
|
|
Features computeClassValue(Id id, Class cls) {
|
|
SourceClassBuilder clsBuilder =
|
|
lookupClassBuilder(compilerResult, cls) as SourceClassBuilder;
|
|
|
|
Features features = new Features();
|
|
if (cls.isAbstract) {
|
|
features.add(Tags.isAbstract);
|
|
}
|
|
clsBuilder.scope.forEach((String name, Builder builder) {
|
|
features.addElement(Tags.scope, name);
|
|
});
|
|
|
|
for (Member m in clsBuilder.actualCls.members) {
|
|
if (m is Procedure &&
|
|
(m.isMemberSignature ||
|
|
(m.isForwardingStub && !m.isForwardingSemiStub))) {
|
|
// Don't include member signatures.
|
|
continue;
|
|
}
|
|
String name = m.name.text;
|
|
if (m is Constructor) {
|
|
name = '${m.enclosingClass.name}.${name}';
|
|
}
|
|
features.addElement(Tags.kernelMembers, name);
|
|
}
|
|
|
|
return features;
|
|
}
|
|
|
|
@override
|
|
Features computeMemberValue(Id id, Member member) {
|
|
Features features = new Features();
|
|
if (member is Constructor) {
|
|
for (Initializer initializer in member.initializers) {
|
|
String desc = initializer.runtimeType.toString();
|
|
if (initializer is FieldInitializer) {
|
|
desc = 'FieldInitializer(${getMemberName(initializer.field)})';
|
|
}
|
|
features.addElement(Tags.initializers, desc);
|
|
}
|
|
}
|
|
SourceMemberBuilder? memberBuilder =
|
|
lookupMemberBuilder(compilerResult, member, required: false)
|
|
as SourceMemberBuilder?;
|
|
List<MemberBuilder>? patchMembers;
|
|
if (memberBuilder is SourceProcedureBuilder) {
|
|
patchMembers = memberBuilder.patchesForTesting;
|
|
}
|
|
if (memberBuilder is DeclaredSourceConstructorBuilder) {
|
|
patchMembers = memberBuilder.patchesForTesting;
|
|
}
|
|
if (memberBuilder is SourceFactoryBuilder) {
|
|
patchMembers = memberBuilder.patchesForTesting;
|
|
}
|
|
if (patchMembers != null) {
|
|
features.add(Tags.patch);
|
|
}
|
|
|
|
return features;
|
|
}
|
|
}
|