// 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'; import 'dart:typed_data'; import 'package:_fe_analyzer_shared/src/parser/parser.dart'; import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'; import 'package:dart_style/dart_style.dart' show DartFormatter; import 'utils/io_utils.dart' show computeRepoDirUri; void main(List args) { final Uri repoDir = computeRepoDirUri(); String generated = generateTestParser(repoDir); new File.fromUri(computeTestParserUri(repoDir)) .writeAsStringSync(generated, flush: true); } Uri computeTestParserUri(Uri repoDir) { return repoDir.resolve("pkg/front_end/test/parser_test_parser.dart"); } String generateTestParser(Uri repoDir) { StringBuffer out = new StringBuffer(); File f = new File.fromUri(repoDir .resolve("pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart")); Uint8List rawBytes = f.readAsBytesSync(); Utf8BytesScanner scanner = new Utf8BytesScanner(rawBytes, includeComments: true); Token firstToken = scanner.tokenize(); out.write(r""" // 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 'package:_fe_analyzer_shared/src/experiments/flags.dart'; import 'package:_fe_analyzer_shared/src/parser/assert.dart'; import 'package:_fe_analyzer_shared/src/parser/block_kind.dart'; import 'package:_fe_analyzer_shared/src/parser/constructor_reference_context.dart'; import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart'; import 'package:_fe_analyzer_shared/src/parser/directive_context.dart'; import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'; import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'; import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener; import 'package:_fe_analyzer_shared/src/parser/member_kind.dart'; import 'package:_fe_analyzer_shared/src/parser/parser.dart' show ConstantPatternContext, Parser; import 'package:_fe_analyzer_shared/src/parser/parser_impl.dart' show AwaitOrYieldContext, ForPartsContext, PatternContext; import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart'; import 'package:_fe_analyzer_shared/src/parser/type_info.dart'; import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:front_end/src/codes/cfe_codes.dart' as codes; import 'package:front_end/src/source/diet_parser.dart' show useImplicitCreationExpressionInCfe; // THIS FILE IS AUTO GENERATED BY 'test/parser_test_parser_creator.dart' // Run this command to update it: // 'dart pkg/front_end/test/parser_test_parser_creator.dart' class TestParser extends Parser { int indent = 0; StringBuffer sb = new StringBuffer(); final bool trace; bool _inhibitPrinting = false; TestParser(Listener listener, this.trace, {required bool allowPatterns, required bool enableEnhancedParts}) : super(listener, useImplicitCreationExpression: useImplicitCreationExpressionInCfe, allowPatterns: allowPatterns, enableFeatureEnhancedParts: enableEnhancedParts); String createTrace() { List traceLines = StackTrace.current.toString().split("\n"); for (int i = 0; i < traceLines.length; i++) { // Find first one that's not any of the denylisted ones. String line = traceLines[i]; if (line.contains("parser_test_listener.dart:") || line.contains("parser_suite.dart:") || line.contains("parser_test_parser.dart:") || line == "") { continue; } return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")")); } return "N/A"; } void doPrint(String s) { if (_inhibitPrinting) return; String traceString = ""; if (trace) traceString = " (${createTrace()})"; sb.writeln((" " * indent) + s + traceString); } @override T inhibitPrinting(T Function() callback) { bool previousInhibitPrinting = _inhibitPrinting; _inhibitPrinting = true; try { return callback(); } finally { _inhibitPrinting = previousInhibitPrinting; } } """); ParserCreatorListener listener = new ParserCreatorListener(out); ClassMemberParser parser = new ClassMemberParser(listener); parser.parseUnit(firstToken); out.writeln("}"); return new DartFormatter( languageVersion: DartFormatter.latestShortStyleLanguageVersion) .format("$out"); } class ParserCreatorListener extends Listener { final StringSink out; bool insideParserClass = false; String? currentMethodName; List parameters = []; List parametersNamed = []; ParserCreatorListener(this.out); @override void beginClassDeclaration( Token begin, Token? abstractToken, Token? macroToken, Token? sealedToken, Token? baseToken, Token? interfaceToken, Token? finalToken, Token? augmentToken, Token? mixinToken, Token name) { if (name.lexeme == "Parser") insideParserClass = true; } @override void endClassDeclaration(Token beginToken, Token endToken) { insideParserClass = false; } @override void beginMethod( DeclarationKind declarationKind, Token? augmentToken, Token? externalToken, Token? staticToken, Token? covariantToken, Token? varFinalOrConst, Token? getOrSet, Token name, String? enclosingDeclarationName) { currentMethodName = name.lexeme; } @override void endClassConstructor(Token? getOrSet, Token beginToken, Token beginParam, Token? beginInitializers, Token endToken) { parameters.clear(); parametersNamed.clear(); currentMethodName = null; } @override void endClassMethod(Token? getOrSet, Token beginToken, Token beginParam, Token? beginInitializers, Token endToken) { if (insideParserClass && !currentMethodName!.startsWith("_") && currentMethodName != 'inhibitPrinting') { Token token = beginToken; Token? latestToken; out.writeln(" @override"); out.write(" "); while (true) { if (troubleParameterTokens.containsKey(token)) { if (latestToken != null && latestToken.charEnd < token.charOffset) { out.write(" "); } out.write("dynamic"); token = troubleParameterTokens[token]!; } if (latestToken != null && latestToken.charEnd < token.charOffset) { out.write(" "); } if (token is SimpleToken && token.type == TokenType.FUNCTION) { // Don't write out the '=>'. out.write("{"); break; } out.write(token.lexeme); if (token is BeginToken && token.type == TokenType.OPEN_CURLY_BRACKET && (beginParam.endGroup == endToken || token.charOffset > beginParam.endGroup!.charOffset)) { break; } if (token == endToken) { throw token.runtimeType; } latestToken = token; token = token.next!; } out.write("\n "); out.write("doPrint('$currentMethodName("); String separator = ""; for (int i = 0; i < parameters.length; i++) { out.write(separator); out.write(r"' '$"); out.write(parameters[i]); separator = ", "; } for (int i = 0; i < parametersNamed.length; i++) { out.write(separator); out.write("' '"); out.write(parametersNamed[i]); out.write(r": $"); out.write(parametersNamed[i]); separator = ", "; } out.write(")');\n "); out.write("indent++;\n "); out.write("var result = super.$currentMethodName"); if (getOrSet != null && getOrSet.lexeme == "get") { // no parens out.write(";\n "); } else { out.write("("); String separator = ""; for (int i = 0; i < parameters.length; i++) { out.write(separator); out.write(parameters[i]); separator = ", "; } for (int i = 0; i < parametersNamed.length; i++) { out.write(separator); out.write(parametersNamed[i]); out.write(": "); out.write(parametersNamed[i]); separator = ", "; } out.write(");\n "); } out.write("indent--;\n "); out.write("return result;\n "); out.write("}"); out.write("\n\n"); } parameters.clear(); parametersNamed.clear(); currentMethodName = null; } int formalParametersNestLevel = 0; @override void beginFormalParameters(Token token, MemberKind kind) { formalParametersNestLevel++; } @override void endFormalParameters( int count, Token beginToken, Token endToken, MemberKind kind) { formalParametersNestLevel--; } Token? currentFormalParameterToken; @override void beginFormalParameter(Token token, MemberKind kind, Token? requiredToken, Token? covariantToken, Token? varFinalOrConst) { if (formalParametersNestLevel == 1) { currentFormalParameterToken = token; } } Map troubleParameterTokens = {}; @override void handleIdentifier(Token token, IdentifierContext context) { if (formalParametersNestLevel > 0 && token.lexeme.startsWith("_")) { troubleParameterTokens[currentFormalParameterToken] = null; } } @override void endFormalParameter( Token? thisKeyword, Token? superKeyword, Token? periodAfterThisOrSuper, Token nameToken, Token? initializerStart, Token? initializerEnd, FormalParameterKind kind, MemberKind memberKind) { if (formalParametersNestLevel != 1) { return; } if (troubleParameterTokens.containsKey(currentFormalParameterToken)) { troubleParameterTokens[currentFormalParameterToken] = nameToken; } currentFormalParameterToken = null; if (kind == FormalParameterKind.optionalNamed || kind == FormalParameterKind.requiredNamed) { parametersNamed.add(nameToken.lexeme); } else { parameters.add(nameToken.lexeme); } } }