ca974e5c4f
Reland same files as https://dart-review.googlesource.com/c/sdk/+/278090 The only major change is parser_impl.dart parsing changes for 'final' This change should allow 'final' for classes and mixins and maintain prior final behaviour for other constructs such as enums, typedefs, or the breaking line which was 'final library = ...;' Change-Id: I3d84fc47479f39df6d5b0dcbe8f92d1fb78a826a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279076 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Kallen Tu <kallentu@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
316 lines
10 KiB
Dart
316 lines
10 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';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:_fe_analyzer_shared/src/parser/parser.dart';
|
|
import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart';
|
|
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
|
|
import 'package:dart_style/dart_style.dart' show DartFormatter;
|
|
|
|
import 'utils/io_utils.dart' show computeRepoDirUri;
|
|
|
|
void main(List<String> 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"));
|
|
List<int> rawBytes = f.readAsBytesSync();
|
|
|
|
Uint8List bytes = new Uint8List(rawBytes.length + 1);
|
|
bytes.setRange(0, rawBytes.length, rawBytes);
|
|
|
|
Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, 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 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/fasta/fasta_codes.dart' as codes;
|
|
import 'package:front_end/src/fasta/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})
|
|
: super(listener,
|
|
useImplicitCreationExpression: useImplicitCreationExpressionInCfe,
|
|
allowPatterns: allowPatterns);
|
|
|
|
String createTrace() {
|
|
List<String> 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 == "<asynchronous suspension>") 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>(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().format("$out");
|
|
}
|
|
|
|
class ParserCreatorListener extends Listener {
|
|
final StringSink out;
|
|
bool insideParserClass = false;
|
|
String? currentMethodName;
|
|
List<String> parameters = [];
|
|
List<String?> parametersNamed = [];
|
|
|
|
ParserCreatorListener(this.out);
|
|
|
|
@override
|
|
void beginClassDeclaration(
|
|
Token begin,
|
|
Token? abstractToken,
|
|
Token? macroToken,
|
|
Token? inlineToken,
|
|
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) {
|
|
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<Token?, Token?> 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) {
|
|
parametersNamed.add(nameToken.lexeme);
|
|
} else {
|
|
parameters.add(nameToken.lexeme);
|
|
}
|
|
}
|
|
}
|