CQ. Scan from strings and drop scanner reader shim.

Remove the analyzer-only `scanner/reader.dart` re-export and refactor
`Scanner` to accept source text directly.

* Delete `pkg/analyzer/src/dart/scanner/reader.dart`, which only re-exported
  `_fe_analyzer_shared` reader types.
* Replace the `Scanner(CharacterReader, ...)` factory with
  `Scanner(String contents, ...)`, aligning the API with the underlying
  `scanString` implementation.
* Update analyzer, analysis_server, analyzer_cli, analyzer_plugin, and scrape
  call sites to pass the source string directly instead of constructing
  `CharSequenceReader`.

This removes an unnecessary abstraction layer, reduces
imports/indirection, and makes scanner usage simpler and more uniform
across the repo.

Change-Id: I380b365676c8a62971a3700deadb695d1519d653
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/477600
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov
2026-02-02 11:20:31 -08:00
committed by Commit Queue
parent e293e3bfe9
commit 5273f91b95
13 changed files with 31 additions and 70 deletions
@@ -13,7 +13,6 @@ import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart' as p;
import 'package:analyzer/src/string_source.dart';
@@ -54,13 +53,12 @@ ParseStringResult sortDirectives(String contents, {String? fileName}) {
}) {
var source = StringSource(contents, fullName);
var diagnosticListener = RecordingDiagnosticListener();
var reader = CharSequenceReader(contents);
var featureSet = FeatureSet.fromEnableFlags2(
sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: [],
);
var diagnosticReporter = DiagnosticReporter(diagnosticListener, source);
var scanner = Scanner(reader, diagnosticReporter)
var scanner = Scanner(contents, diagnosticReporter)
..configureFeatures(
featureSetForOverriding: FeatureSet.latestLanguageVersion(),
featureSet: featureSet,
@@ -15,7 +15,6 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
import 'package:dart_style/dart_style.dart' hide TrailingCommas;
@@ -701,7 +700,7 @@ class _MinimalEditComputer {
try {
var scanner =
Scanner(
CharSequenceReader(s),
s,
DiagnosticReporter(
DiagnosticListener.nullListener,
_SourceMock.instance,
@@ -14,7 +14,6 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -25,7 +24,7 @@ List<Token> _getTokens(String text, FeatureSet featureSet) {
var tokens = <Token>[];
var scanner =
Scanner(
CharSequenceReader(text),
text,
DiagnosticReporter(
DiagnosticListener.nullListener,
_SourceMock.instance,
@@ -14,7 +14,6 @@ import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart' as error;
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/glob.dart';
@@ -226,7 +225,7 @@ class Driver {
var featureSet = FeatureSet.latestLanguageVersion();
var scanner =
Scanner(
CharSequenceReader(text),
text,
error.DiagnosticReporter(
error.DiagnosticListener.nullListener,
_TestSource(),
@@ -13,7 +13,6 @@ import 'package:analyzer/source/source.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
@@ -459,7 +458,7 @@ class TokenUtils {
var tokens = <Token>[];
var scanner =
Scanner(
CharSequenceReader(s),
s,
DiagnosticReporter(DiagnosticListener.nullListener, _SourceMock()),
)..configureFeatures(
featureSetForOverriding: featureSet,
@@ -16,7 +16,6 @@ import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/string_source.dart';
@@ -82,10 +81,9 @@ ParseStringResult parseString({
}) {
featureSet ??= FeatureSet.latestLanguageVersion();
var source = StringSource(content, path ?? '');
var reader = CharSequenceReader(content);
var diagnosticCollector = RecordingDiagnosticListener();
var diagnosticReporter = DiagnosticReporter(diagnosticCollector, source);
var scanner = Scanner(reader, diagnosticReporter)
var scanner = Scanner(content, diagnosticReporter)
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
@@ -30,7 +30,6 @@ import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
import 'package:analyzer/src/dart/analysis/unlinked_data.dart';
import 'package:analyzer/src/dart/analysis/unlinked_unit_store.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
import 'package:analyzer/src/exception/exception.dart';
@@ -581,9 +580,8 @@ class FileState {
return performance.run('parseCode', (performance) {
performance.getDataInt('length').add(code.length);
CharSequenceReader reader = CharSequenceReader(code);
var diagnosticReporter = DiagnosticReporter(diagnosticListener, source);
Scanner scanner = Scanner(reader, diagnosticReporter)
Scanner scanner = Scanner(code, diagnosticReporter)
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet.restrictToVersion(packageLanguageVersion),
@@ -1,8 +0,0 @@
// Copyright (c) 2014, 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.
export 'package:_fe_analyzer_shared/src/scanner/reader.dart'
show CharacterReader, CharSequenceReader, SubSequenceReader;
/// This file is intentionally left blank except for exports.
+5 -13
View File
@@ -11,7 +11,6 @@ import 'package:_fe_analyzer_shared/src/scanner/token.dart'
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/translate_error_token.dart'
show translateErrorToken;
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
@@ -62,18 +61,11 @@ class Scanner {
late FeatureSet _featureSet;
/// Initialize a newly created scanner to scan characters from the given
/// [source]. The given character [reader] will be used to read the characters
/// in the source. The given [diagnosticReporter] will be informed of any
/// errors that are found.
factory Scanner(
CharacterReader reader,
DiagnosticReporter diagnosticReporter,
) => Scanner.fasta(
diagnosticReporter,
contents: reader.getContents(),
offset: reader.offset,
);
/// Initializes a scanner to scan the given [contents].
///
/// The [diagnosticReporter] will be informed of any errors that are found.
factory Scanner(String contents, DiagnosticReporter diagnosticReporter) =>
Scanner.fasta(diagnosticReporter, contents: contents);
factory Scanner.fasta(
DiagnosticReporter diagnosticReporter, {
+16 -24
View File
@@ -7,7 +7,6 @@ import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/string_source.dart';
import 'package:analyzer_testing/resource_provider_mixin.dart';
@@ -76,13 +75,11 @@ class LineInfoTest {
String source = "var\r\ni\n=\n1;\n";
GatheringDiagnosticListener listener = GatheringDiagnosticListener();
Scanner scanner =
Scanner(
CharSequenceReader(source),
DiagnosticReporter(listener, TestSource()),
)..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
Scanner(source, DiagnosticReporter(listener, TestSource()))
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
var token = scanner.tokenize();
expect(token.lexeme, 'var');
var lineStarts = scanner.lineStarts;
@@ -96,13 +93,11 @@ class LineInfoTest {
String source = '<!-- @Component(';
GatheringDiagnosticListener listener = GatheringDiagnosticListener();
Scanner scanner =
Scanner(
CharSequenceReader(source),
DiagnosticReporter(listener, TestSource()),
)..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
Scanner(source, DiagnosticReporter(listener, TestSource()))
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
Token token = scanner.tokenize(reportScannerErrors: false);
expect(token, TypeMatcher<UnmatchedToken>());
token = token.next!;
@@ -139,13 +134,11 @@ class LineInfoTest {
Token _scanWithListener(String source, GatheringDiagnosticListener listener) {
Scanner scanner =
Scanner(
CharSequenceReader(source),
DiagnosticReporter(listener, TestSource()),
)..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
Scanner(source, DiagnosticReporter(listener, TestSource()))
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
);
Token result = scanner.tokenize();
LineInfo lineInfo = LineInfo(scanner.lineStarts);
listener.setLineInfo(TestSource(), lineInfo);
@@ -201,9 +194,8 @@ class ScannerTest with ResourceProviderMixin {
Scanner _createScanner(String content) {
var path = convertPath('/test/lib/a.dart');
var source = StringSource(content, path);
var reader = CharSequenceReader(content);
var diagnosticCollector = RecordingDiagnosticListener();
return Scanner(reader, DiagnosticReporter(diagnosticCollector, source));
return Scanner(content, DiagnosticReporter(diagnosticCollector, source));
}
}
@@ -9,7 +9,6 @@ import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/file_source.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/clients/build_resolvers/build_resolvers.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer_testing/resource_provider_mixin.dart';
@@ -27,9 +26,8 @@ class ParseBase with ResourceProviderMixin {
var diagnosticListener = RecordingDiagnosticListener();
var reader = CharSequenceReader(content);
var diagnosticReporter = DiagnosticReporter(diagnosticListener, source);
var scanner = Scanner(reader, diagnosticReporter)
var scanner = Scanner(content, diagnosticReporter)
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
+1 -2
View File
@@ -19,7 +19,6 @@ import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
import 'package:analyzer/src/file_system/file_system.dart';
@@ -234,7 +233,7 @@ ScannerResult tokenize(Source source) {
// first converting to String?
var scanner =
Scanner(
CharSequenceReader(contents),
contents,
DiagnosticReporter(DiagnosticListener.nullListener, source),
)
..configureFeatures(
+1 -3
View File
@@ -13,7 +13,6 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/string_source.dart';
@@ -275,11 +274,10 @@ class Scrape {
var featureSet = FeatureSet.latestLanguageVersion();
// Tokenize the source.
var reader = CharSequenceReader(source);
var stringSource = StringSource(source, file.path);
var diagnosticReporter =
DiagnosticReporter(diagnosticListener, stringSource);
var scanner = Scanner(reader, diagnosticReporter);
var scanner = Scanner(source, diagnosticReporter);
scanner.configureFeatures(
featureSet: featureSet, featureSetForOverriding: featureSet);
var startToken = scanner.tokenize();