blob: d65ed1c806a9d7895e5870f5ac2d28c26e784ff0 [file] [log] [blame]
// 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:async' show Future;
import 'dart:io' show File;
import 'dart:typed_data' show Uint8List;
import 'package:front_end/src/fasta/scanner.dart' show ErrorToken;
import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart'
show Utf8BytesScanner;
import 'package:front_end/src/scanner/token.dart'
show Token, KeywordToken, BeginToken;
import 'package:front_end/src/scanner/token.dart';
import 'package:testing/testing.dart'
show Chain, ChainContext, Result, Step, TestDescription, runMe;
import 'spell_checking_utils.dart' as spell;
main([List<String> arguments = const []]) =>
runMe(arguments, createContext, "../testing.json");
Future<Context> createContext(
Chain suite, Map<String, String> environment) async {
return new Context();
}
class Context extends ChainContext {
final List<Step> steps = const <Step>[
const SpellTest(),
];
// Override special handling of negative tests.
@override
Result processTestResult(
TestDescription description, Result result, bool last) {
return result;
}
}
class SpellTest extends Step<TestDescription, TestDescription, Context> {
const SpellTest();
String get name => "spell test";
Future<Result<TestDescription>> run(
TestDescription description, Context 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();
if (firstToken == null) return null;
Token token = firstToken;
List<String> errors;
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) {
Set<String> misspelled =
spell.spellcheckString(comment.lexeme, splitAsCode: true);
if (misspelled != null) {
errors ??= new List<String>();
errors.add("Misspelled words around offset ${comment.offset}: "
"${misspelled.toList()}");
}
comment = comment.next;
}
}
if (token is StringToken) {
Set<String> misspelled =
spell.spellcheckString(token.lexeme, splitAsCode: true);
if (misspelled != null) {
errors ??= new List<String>();
errors.add("Misspelled words around offset ${token.offset}: "
"${misspelled.toList()}");
}
} 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 {
// TODO(jensj): Point properly in the source code like compilation errors
// do.
return fail(description, errors.join("\n"));
}
}
}