mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:43:32 +00:00
507297562c
This reverts commit b905c9a171
.
Reason for revert: Sometimes all_suites.dart can't be found.
Original change's description:
> [cfe] Run `fasta testing` directly
>
> This avoids the precompile step when running
>
> package:testing/src/run_tests.dart
> Change-Id: Idb7569bb865b077440eb750333cfec5b6c48cd91
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345280
> Commit-Queue: Johnni Winther <johnniwinther@google.com>
> Reviewed-by: Jens Johansen <jensj@google.com>
Change-Id: Iedc310eac17fab1b372c03a4852ff0a19f6e2e95
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345500
Auto-Submit: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
196 lines
6.5 KiB
Dart
196 lines
6.5 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' show File, Platform;
|
|
|
|
import 'dart:typed_data' show Uint8List;
|
|
|
|
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show ErrorToken;
|
|
|
|
import 'package:_fe_analyzer_shared/src/scanner/token.dart'
|
|
show BeginToken, KeywordToken, StringToken, Token;
|
|
|
|
import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
|
|
show Utf8BytesScanner;
|
|
|
|
import 'package:front_end/src/fasta/command_line_reporting.dart'
|
|
as command_line_reporting;
|
|
|
|
import 'package:kernel/kernel.dart' show Location, Source;
|
|
|
|
import 'package:testing/testing.dart'
|
|
show Chain, ChainContext, Result, Step, TestDescription;
|
|
|
|
import 'spell_checking_utils.dart' as spell;
|
|
|
|
import 'testing_utils.dart' show filterList;
|
|
|
|
abstract class SpellContext extends ChainContext {
|
|
@override
|
|
final List<Step> steps = const <Step>[
|
|
const SpellTest(),
|
|
];
|
|
|
|
final bool interactive;
|
|
final bool onlyInGit;
|
|
|
|
SpellContext({required this.interactive, required this.onlyInGit});
|
|
|
|
// Override special handling of negative tests.
|
|
@override
|
|
Result processTestResult(
|
|
TestDescription description, Result result, bool last) {
|
|
return result;
|
|
}
|
|
|
|
List<spell.Dictionaries> get dictionaries;
|
|
|
|
bool get onlyDenylisted;
|
|
|
|
String get repoRelativeSuitePath;
|
|
|
|
Set<String> reportedWords = {};
|
|
Set<String> reportedWordsDenylisted = {};
|
|
|
|
@override
|
|
Stream<TestDescription> list(Chain suite) {
|
|
return filterList(suite, onlyInGit, super.list(suite));
|
|
}
|
|
|
|
@override
|
|
Future<void> postRun() {
|
|
String dartPath = Platform.resolvedExecutable;
|
|
Uri suiteUri = spell.repoDir.resolve(repoRelativeSuitePath);
|
|
File suiteFile = new File.fromUri(suiteUri).absolute;
|
|
if (!suiteFile.existsSync()) {
|
|
throw "Specified suite path is invalid.";
|
|
}
|
|
String suitePath = suiteFile.path;
|
|
spell.spellSummarizeAndInteractiveMode(
|
|
reportedWords,
|
|
reportedWordsDenylisted,
|
|
dictionaries,
|
|
interactive,
|
|
'"$dartPath" "$suitePath" -DonlyInGit=$onlyInGit -Dinteractive=true');
|
|
return new Future.value();
|
|
}
|
|
}
|
|
|
|
class SpellTest extends Step<TestDescription, TestDescription, SpellContext> {
|
|
const SpellTest();
|
|
|
|
@override
|
|
String get name => "spell test";
|
|
|
|
@override
|
|
Future<Result<TestDescription>> run(
|
|
TestDescription description, SpellContext context) async {
|
|
File f = new File.fromUri(description.uri);
|
|
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();
|
|
Token? token = firstToken;
|
|
|
|
List<String>? errors;
|
|
Source source = new Source(
|
|
scanner.lineStarts, rawBytes, description.uri, description.uri);
|
|
void addErrorMessage(
|
|
int offset, String word, bool denylisted, List<String>? alternatives) {
|
|
errors ??= <String>[];
|
|
String message;
|
|
if (denylisted) {
|
|
message = "Misspelled word: '$word' has explicitly been denylisted.";
|
|
context.reportedWordsDenylisted.add(word);
|
|
} else {
|
|
message = "The word '$word' is not in our dictionary.";
|
|
context.reportedWords.add(word);
|
|
}
|
|
if (alternatives != null && alternatives.isNotEmpty) {
|
|
message += "\n\nThe following word(s) was 'close' "
|
|
"and in our dictionary: "
|
|
"${alternatives.join(", ")}\n";
|
|
}
|
|
if (context.dictionaries.isNotEmpty) {
|
|
String dictionaryPathString = context.dictionaries
|
|
.map((d) => spell.dictionaryToUri(d).toString())
|
|
.join("\n- ");
|
|
message += "\n\nIf the word is correctly spelled please add "
|
|
"it to one of these files:\n"
|
|
"- $dictionaryPathString\n";
|
|
}
|
|
Location location = source.getLocation(description.uri, offset);
|
|
errors!.add(command_line_reporting.formatErrorMessage(
|
|
source.getTextLine(location.line),
|
|
location,
|
|
word.length,
|
|
description.uri.toString(),
|
|
message));
|
|
}
|
|
|
|
while (token != null) {
|
|
if (token is ErrorToken) {
|
|
// For now just accept that.
|
|
return pass(description);
|
|
}
|
|
if (token.precedingComments != null) {
|
|
Token? comment = token.precedingComments;
|
|
while (comment != null) {
|
|
spell.SpellingResult spellingResult = spell.spellcheckString(
|
|
comment.lexeme,
|
|
splitAsCode: true,
|
|
dictionaries: context.dictionaries);
|
|
if (spellingResult.misspelledWords != null) {
|
|
for (int i = 0; i < spellingResult.misspelledWords!.length; i++) {
|
|
bool denylisted = spellingResult.misspelledWordsDenylisted![i];
|
|
if (context.onlyDenylisted && !denylisted) continue;
|
|
int offset =
|
|
comment.offset + spellingResult.misspelledWordsOffset![i];
|
|
addErrorMessage(offset, spellingResult.misspelledWords![i],
|
|
denylisted, spellingResult.misspelledWordsAlternatives![i]);
|
|
}
|
|
}
|
|
comment = comment.next;
|
|
}
|
|
}
|
|
if (token is StringToken) {
|
|
spell.SpellingResult spellingResult = spell.spellcheckString(
|
|
token.lexeme,
|
|
splitAsCode: true,
|
|
dictionaries: context.dictionaries);
|
|
if (spellingResult.misspelledWords != null) {
|
|
for (int i = 0; i < spellingResult.misspelledWords!.length; i++) {
|
|
bool denylisted = spellingResult.misspelledWordsDenylisted![i];
|
|
if (context.onlyDenylisted && !denylisted) continue;
|
|
int offset =
|
|
token.offset + spellingResult.misspelledWordsOffset![i];
|
|
addErrorMessage(offset, spellingResult.misspelledWords![i],
|
|
denylisted, spellingResult.misspelledWordsAlternatives![i]);
|
|
}
|
|
}
|
|
} else if (token is KeywordToken || token is BeginToken) {
|
|
// Ignored.
|
|
} else if (token.runtimeType.toString() == "SimpleToken") {
|
|
// Ignored.
|
|
} else {
|
|
throw "Unsupported token type: ${token.runtimeType} ($token)";
|
|
}
|
|
|
|
if (token.isEof) break;
|
|
|
|
token = token.next;
|
|
}
|
|
|
|
if (errors == null) {
|
|
return pass(description);
|
|
} else {
|
|
return fail(description, errors!.join("\n\n"));
|
|
}
|
|
}
|
|
}
|