| // 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:front_end/src/fasta/builder/builder.dart'; |
| import 'package:front_end/src/fasta/builder/extension_builder.dart'; |
| import 'package:front_end/src/fasta/kernel/kernel_builder.dart'; |
| import 'package:front_end/src/testing/id.dart' show ActualData, Id; |
| import 'package:front_end/src/testing/features.dart'; |
| import 'package:front_end/src/testing/id_testing.dart' |
| show DataInterpreter, runTests; |
| import 'package:front_end/src/testing/id_testing.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'; |
| |
| main(List<String> args) async { |
| Directory dataDir = new Directory.fromUri(Platform.script.resolve('data')); |
| await runTests(dataDir, |
| args: args, |
| supportedMarkers: sharedMarkers, |
| createUriForFileName: createUriForFileName, |
| onFailure: onFailure, |
| runTest: runTestFor( |
| const ExtensionsDataComputer(), [cfeExtensionMethodsConfig])); |
| } |
| |
| class ExtensionsDataComputer extends DataComputer<Features> { |
| const ExtensionsDataComputer(); |
| |
| @override |
| void computeMemberData(InternalCompilerResult compilerResult, Member member, |
| Map<Id, ActualData<Features>> actualMap, |
| {bool verbose}) { |
| member.accept(new ExtensionsDataExtractor(compilerResult, actualMap)); |
| } |
| |
| @override |
| void computeClassData(InternalCompilerResult compilerResult, Class cls, |
| Map<Id, ActualData<Features>> actualMap, |
| {bool verbose}) { |
| new ExtensionsDataExtractor(compilerResult, actualMap).computeForClass(cls); |
| } |
| |
| @override |
| void computeExtensionData(InternalCompilerResult compilerResult, |
| Extension extension, Map<Id, ActualData<Features>> actualMap, |
| {bool verbose}) { |
| new ExtensionsDataExtractor(compilerResult, actualMap) |
| .computeForExtension(extension); |
| } |
| |
| @override |
| bool get supportsErrors => true; |
| |
| @override |
| Features computeErrorData( |
| InternalCompilerResult compiler, Id id, List<FormattedMessage> errors) { |
| Features features = new Features(); |
| for (FormattedMessage error in errors) { |
| if (error.message.contains(',')) { |
| // TODO(johnniwinther): Support escaping of , in Features. |
| features.addElement(Tags.errors, error.code); |
| } else { |
| features.addElement(Tags.errors, error.message); |
| } |
| } |
| return features; |
| } |
| |
| @override |
| DataInterpreter<Features> get dataValidator => |
| const FeaturesDataInterpreter(); |
| } |
| |
| class Tags { |
| static const String builderName = 'builder-name'; |
| static const String builderTypeParameters = 'builder-type-params'; |
| static const String builderSupertype = 'builder-supertype'; |
| static const String builderInterfaces = 'builder-interfaces'; |
| static const String builderOnTypes = 'builder-onTypes'; |
| static const String builderOnType = 'builder-onType'; |
| static const String builderRequiredParameters = 'builder-params'; |
| static const String builderPositionalParameters = 'builder-pos-params'; |
| static const String builderNamedParameters = 'builder-named-params'; |
| |
| static const String clsName = 'cls-name'; |
| static const String clsTypeParameters = 'cls-type-params'; |
| static const String clsSupertype = 'cls-supertype'; |
| static const String clsInterfaces = 'cls-interfaces'; |
| |
| static const String extensionName = 'extension-name'; |
| static const String extensionTypeParameters = 'extension-type-params'; |
| static const String extensionOnType = 'extension-onType'; |
| static const String extensionMembers = 'extension-members'; |
| |
| static const String memberName = 'member-name'; |
| static const String memberTypeParameters = 'member-type-params'; |
| static const String memberRequiredParameters = 'member-params'; |
| static const String memberPositionalParameters = 'member-pos-params'; |
| static const String memberNamedParameters = 'member-named-params'; |
| |
| static const String errors = 'errors'; |
| |
| static const String hasThis = 'this'; |
| } |
| |
| class ExtensionsDataExtractor extends CfeDataExtractor<Features> { |
| ExtensionsDataExtractor(InternalCompilerResult compilerResult, |
| Map<Id, ActualData<Features>> actualMap) |
| : super(compilerResult, actualMap); |
| |
| @override |
| Features computeClassValue(Id id, Class cls) { |
| ClassBuilder clsBuilder = lookupClassBuilder(compilerResult, cls); |
| if (!clsBuilder.isExtension) { |
| return null; |
| } |
| Features features = new Features(); |
| features[Tags.builderName] = clsBuilder.name; |
| if (clsBuilder.typeVariables != null) { |
| for (TypeVariableBuilder typeVariable in clsBuilder.typeVariables) { |
| features.addElement(Tags.builderTypeParameters, |
| typeVariableBuilderToText(typeVariable)); |
| } |
| } |
| |
| features[Tags.builderSupertype] = clsBuilder.supertype?.name; |
| if (clsBuilder.interfaces != null) { |
| for (TypeBuilder superinterface in clsBuilder.interfaces) { |
| features.addElement(Tags.builderInterfaces, superinterface.name); |
| } |
| } |
| if (clsBuilder.onTypes != null) { |
| for (TypeBuilder onType in clsBuilder.onTypes) { |
| features.addElement(Tags.builderOnTypes, typeBuilderToText(onType)); |
| } |
| } |
| |
| features[Tags.clsName] = cls.name; |
| for (TypeParameter typeParameter in cls.typeParameters) { |
| features.addElement( |
| Tags.clsTypeParameters, typeParameterToText(typeParameter)); |
| } |
| features[Tags.clsSupertype] = cls.supertype?.classNode?.name; |
| for (Supertype superinterface in cls.implementedTypes) { |
| features.addElement(Tags.clsInterfaces, superinterface.classNode.name); |
| } |
| return features; |
| } |
| |
| @override |
| Features computeExtensionValue(Id id, Extension extension) { |
| ExtensionBuilder extensionBuilder = |
| lookupExtensionBuilder(compilerResult, extension); |
| if (!extensionBuilder.isExtension) { |
| return null; |
| } |
| Features features = new Features(); |
| features[Tags.builderName] = extensionBuilder.name; |
| if (extensionBuilder.typeParameters != null) { |
| for (TypeVariableBuilder typeVariable |
| in extensionBuilder.typeParameters) { |
| features.addElement(Tags.builderTypeParameters, |
| typeVariableBuilderToText(typeVariable)); |
| } |
| } |
| if (extensionBuilder.onType != null) { |
| features[Tags.builderOnType] = typeBuilderToText(extensionBuilder.onType); |
| } |
| |
| features[Tags.extensionName] = extension.name; |
| if (extension.onType != null) { |
| features[Tags.extensionOnType] = typeToText(extension.onType); |
| } |
| for (TypeParameter typeParameter in extension.typeParameters) { |
| features.addElement( |
| Tags.extensionTypeParameters, typeParameterToText(typeParameter)); |
| } |
| for (ExtensionMemberDescriptor descriptor in extension.members) { |
| features.addElement( |
| Tags.extensionMembers, extensionMethodDescriptorToText(descriptor)); |
| } |
| return features; |
| } |
| |
| @override |
| Features computeMemberValue(Id id, Member member) { |
| if (!member.isExtensionMember) { |
| return null; |
| } |
| |
| MemberBuilder memberBuilder = lookupMemberBuilder(compilerResult, member); |
| Features features = new Features(); |
| features[Tags.builderName] = memberBuilder.name; |
| if (memberBuilder is FunctionBuilder) { |
| if (memberBuilder.formals != null) { |
| for (FormalParameterBuilder parameter in memberBuilder.formals) { |
| if (parameter.isRequired) { |
| features.addElement(Tags.builderRequiredParameters, parameter.name); |
| } else if (parameter.isPositional) { |
| features.addElement( |
| Tags.builderPositionalParameters, parameter.name); |
| } else { |
| assert(parameter.isNamed); |
| features.addElement(Tags.builderNamedParameters, parameter.name); |
| } |
| } |
| features.markAsUnsorted(Tags.builderRequiredParameters); |
| features.markAsUnsorted(Tags.builderPositionalParameters); |
| features.markAsUnsorted(Tags.builderNamedParameters); |
| } |
| if (memberBuilder.typeVariables != null) { |
| for (TypeVariableBuilder typeVariable in memberBuilder.typeVariables) { |
| features.addElement(Tags.builderTypeParameters, |
| typeVariableBuilderToText(typeVariable)); |
| } |
| features.markAsUnsorted(Tags.builderTypeParameters); |
| } |
| } |
| features[Tags.memberName] = getMemberName(member); |
| if (member.function != null) { |
| for (int index = 0; |
| index < member.function.positionalParameters.length; |
| index++) { |
| VariableDeclaration parameter = |
| member.function.positionalParameters[index]; |
| if (index < member.function.requiredParameterCount) { |
| features.addElement(Tags.memberRequiredParameters, parameter.name); |
| } else { |
| features.addElement(Tags.memberPositionalParameters, parameter.name); |
| } |
| } |
| for (VariableDeclaration parameter in member.function.namedParameters) { |
| features.addElement(Tags.memberNamedParameters, parameter.name); |
| } |
| features.markAsUnsorted(Tags.memberRequiredParameters); |
| features.markAsUnsorted(Tags.memberPositionalParameters); |
| features.markAsUnsorted(Tags.memberNamedParameters); |
| for (TypeParameter typeParameter in member.function.typeParameters) { |
| features.addElement( |
| Tags.memberTypeParameters, typeParameterToText(typeParameter)); |
| } |
| features.markAsUnsorted(Tags.memberTypeParameters); |
| } |
| return features; |
| } |
| |
| @override |
| Features computeNodeValue(Id id, TreeNode node) { |
| if (node is ThisExpression) { |
| Features features = new Features(); |
| features.add(Tags.hasThis); |
| return features; |
| } |
| return null; |
| } |
| } |