// Copyright (c) 2020, 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. // @dart = 2.9 import 'dart:io' show Directory, Platform; import 'package:_fe_analyzer_shared/src/testing/id.dart'; import 'package:_fe_analyzer_shared/src/testing/id_testing.dart' show DataInterpreter, runTests; 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' show ExperimentalFlag; import 'package:front_end/src/base/nnbd_mode.dart'; import 'package:front_end/src/testing/id_testing_helper.dart'; import 'package:kernel/ast.dart'; import 'package:kernel/src/printer.dart'; const String normalMarker = 'normal'; const String verboseMarker = 'verbose'; const String limitedMarker = 'limited'; const String statementMarker = 'stmt'; const String expressionMarker = 'expr'; const AstTextStrategy normalStrategy = const AstTextStrategy( includeLibraryNamesInMembers: false, includeLibraryNamesInTypes: false, includeAuxiliaryProperties: false, useMultiline: true, maxExpressionDepth: null, maxExpressionsLength: null, maxStatementDepth: null, maxStatementsLength: null); const AstTextStrategy verboseStrategy = const AstTextStrategy( includeLibraryNamesInMembers: true, includeLibraryNamesInTypes: true, includeAuxiliaryProperties: true, useMultiline: true, maxExpressionDepth: null, maxExpressionsLength: null, maxStatementDepth: null, maxStatementsLength: null); const AstTextStrategy limitedStrategy = const AstTextStrategy( includeLibraryNamesInMembers: false, includeLibraryNamesInTypes: false, includeAuxiliaryProperties: false, useMultiline: false, maxExpressionDepth: 5, maxExpressionsLength: 4, maxStatementDepth: 5, maxStatementsLength: 4); AstTextStrategy getStrategy(String marker) { switch (marker) { case normalMarker: return normalStrategy; case verboseMarker: return verboseStrategy; case limitedMarker: return limitedStrategy; } throw new UnsupportedError("Unexpected marker '${marker}'."); } main(List args) async { Directory dataDir = new Directory.fromUri(Platform.script.resolve('data')); await runTests(dataDir, args: args, createUriForFileName: createUriForFileName, onFailure: onFailure, preserveWhitespaceInAnnotations: true, runTest: runTestFor(const TextRepresentationDataComputer(), [ const TextRepresentationConfig(normalMarker, 'normal'), const TextRepresentationConfig(verboseMarker, 'verbose'), const TextRepresentationConfig(limitedMarker, 'limited'), ])); } class TextRepresentationConfig extends TestConfig { const TextRepresentationConfig(String marker, String name) : super(marker, name, explicitExperimentalFlags: const { ExperimentalFlag.nonNullable: true }, nnbdMode: NnbdMode.Strong); void customizeCompilerOptions(CompilerOptions options, TestData testData) { if (testData.name.endsWith('_opt_out.dart')) { options.nnbdMode = NnbdMode.Weak; } } } class TextRepresentationDataComputer extends DataComputer { const TextRepresentationDataComputer(); void computeLibraryData( TestConfig config, InternalCompilerResult compilerResult, Library library, Map> actualMap, {bool verbose}) { new TextRepresentationDataExtractor( compilerResult, actualMap, getStrategy(config.marker)) .computeForLibrary(library); } @override void computeMemberData( TestConfig config, InternalCompilerResult compilerResult, Member member, Map> actualMap, {bool verbose}) { member.accept(new TextRepresentationDataExtractor( compilerResult, actualMap, getStrategy(config.marker))); } @override DataInterpreter get dataValidator => const StringDataInterpreter(); } class TextRepresentationDataExtractor extends CfeDataExtractor { final AstTextStrategy strategy; TextRepresentationDataExtractor(InternalCompilerResult compilerResult, Map> actualMap, this.strategy) : super(compilerResult, actualMap); @override String computeLibraryValue(Id id, Library node) { return 'nnbd=${node.isNonNullableByDefault}'; } @override visitProcedure(Procedure node) { if (!node.name.text.startsWith(expressionMarker) && !node.name.text.startsWith(statementMarker)) { node.function.accept(this); } computeForMember(node); } @override visitField(Field node) { if (!node.name.text.startsWith(expressionMarker) && !node.name.text.startsWith(statementMarker)) { node.initializer?.accept(this); } computeForMember(node); } @override String computeMemberValue(Id id, Member node) { if (node.name.text == 'stmtVariableDeclarationMulti') { print(node); } if (node.name.text.startsWith(expressionMarker)) { if (node is Procedure) { Statement body = node.function.body; if (body is ReturnStatement) { return body.expression.toText(strategy); } } else if (node is Field && node.initializer != null) { return node.initializer.toText(strategy); } } else if (node.name.text.startsWith(statementMarker)) { if (node is Procedure) { Statement body = node.function.body; if (body is Block && body.statements.length == 1) { // Prefix with newline to make multiline text representations more // readable. return '\n${body.statements.single.toText(strategy)}'; } } } return null; } @override String computeNodeValue(Id id, TreeNode node) { if (node is ConstantExpression) { return node.constant.toText(strategy); } else if (node is VariableDeclaration) { DartType type = node.type; if (type is FunctionType && type.typedefType != null) { return type.typedefType.toText(strategy); } else { return type.toText(strategy); } } return null; } }