57c326b76d
This makes the arguments to `ScannerConfiguration` required and uses the current enabled-by-default state as default. Furthermore, an extension method is added for `ExperimentalFeatures` (and object already required by the parser) that creates the `ScannerConfiguration` based on the enabled features. This method is used throughout the analyzer and CFE, ensuring that the scanner is set up consistently with the parser. Change-Id: Id51456d5a547b06d0925865e35e01d9dc7d65381 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/493760 Reviewed-by: Jens Johansen <jensj@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
122 lines
3.3 KiB
Dart
122 lines
3.3 KiB
Dart
// Copyright (c) 2025, 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/messages/codes.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/experimental_features.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/forwarding_listener.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/listener.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/parser_impl.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart';
|
|
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
|
|
|
|
void main(List<String> args) {
|
|
if (args.length != 1) {
|
|
throw "Expected 1 argument: <dart file>.";
|
|
}
|
|
File f = new File(args.single);
|
|
if (!f.existsSync()) {
|
|
throw "File $f doesn't exist.";
|
|
}
|
|
Uint8List contentBytes = f.readAsBytesSync();
|
|
ScannerResult scanResult = scan(contentBytes, includeComments: true);
|
|
|
|
const int iterations = 1000;
|
|
|
|
int countTokens = 0;
|
|
{
|
|
Token t = scanResult.tokens;
|
|
while (!t.isEof) {
|
|
countTokens++;
|
|
t = t.next!;
|
|
}
|
|
}
|
|
|
|
// TODO: Should we make 1000 copies of the tokens?
|
|
// Or maybe scan 1000 times?
|
|
/*
|
|
List<Token> tokenStarts = [];
|
|
tokenStarts.add(scanResult.tokens);
|
|
while (tokenStarts.length < iterations) {
|
|
tokenStarts.add(
|
|
scan(
|
|
contentBytes,
|
|
configuration: new ScannerConfiguration(enableTripleShift: true),
|
|
includeComments: true,
|
|
).tokens,
|
|
);
|
|
}
|
|
*/
|
|
|
|
Listener listener = new NullListener();
|
|
if (f.path == "42") {
|
|
// Let's not let it optimize too many things away or do weird optimizations
|
|
// that it can't do in practise.
|
|
listener = new FooListener(f.uri);
|
|
}
|
|
|
|
int numErrors = 0;
|
|
Stopwatch stopwatch = new Stopwatch()..start();
|
|
int lengthProcessed = countTokens;
|
|
|
|
for (int i = 0; i < iterations; i++) {
|
|
Parser parser = new Parser(
|
|
listener,
|
|
experimentalFeatures: const DefaultExperimentalFeatures(),
|
|
);
|
|
Token after = parser.parseUnit(scanResult.tokens);
|
|
if (!after.isEof) {
|
|
throw "parsed returned before eof?!?";
|
|
}
|
|
if (listener is NullListener && listener.hasErrors) {
|
|
numErrors++;
|
|
}
|
|
// Or maybe - maybe as an option - do another scan here?
|
|
}
|
|
|
|
stopwatch.stop();
|
|
print(
|
|
"Parsed $lengthProcessed tokens $iterations times "
|
|
"in ${stopwatch.elapsed}",
|
|
);
|
|
print("Found errors $numErrors times");
|
|
double lengthPerMicrosecond =
|
|
(lengthProcessed * iterations) / stopwatch.elapsedMicroseconds;
|
|
print("That's $lengthPerMicrosecond tokens per microsecond");
|
|
print("");
|
|
}
|
|
|
|
class FooListener extends StackListener {
|
|
List<Message> problems = [];
|
|
|
|
@override
|
|
final Uri uri;
|
|
|
|
FooListener(this.uri);
|
|
|
|
@override
|
|
void addProblem(
|
|
Message message,
|
|
int charOffset,
|
|
int length, {
|
|
bool wasHandled = false,
|
|
List<LocatedMessage>? context,
|
|
}) {
|
|
if (charOffset == 42) {
|
|
throw "$message $charOffset $length $wasHandled $context";
|
|
}
|
|
problems.add(message);
|
|
}
|
|
|
|
@override
|
|
Never internalProblem(Message message, int charOffset, Uri uri) {
|
|
throw UnimplementedError();
|
|
}
|
|
|
|
@override
|
|
bool get isDartLibrary => false;
|
|
}
|