mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 04:31:31 +00:00
145 lines
3.8 KiB
Dart
145 lines
3.8 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:async' show Future;
|
||
|
|
||
|
import 'dart:io' show File;
|
||
|
|
||
|
import 'dart:typed_data' show Uint8List;
|
||
|
|
||
|
import 'package:front_end/src/fasta/parser.dart' show Parser;
|
||
|
|
||
|
import 'package:front_end/src/fasta/parser/listener.dart' show Listener;
|
||
|
|
||
|
import 'package:front_end/src/fasta/command_line_reporting.dart'
|
||
|
as command_line_reporting;
|
||
|
|
||
|
import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart'
|
||
|
show Utf8BytesScanner;
|
||
|
|
||
|
import 'package:front_end/src/scanner/token.dart' show Token;
|
||
|
|
||
|
import 'package:front_end/src/scanner/token.dart';
|
||
|
|
||
|
import 'package:kernel/kernel.dart';
|
||
|
|
||
|
import 'package:testing/testing.dart'
|
||
|
show ChainContext, Result, Step, TestDescription, Chain, runMe;
|
||
|
|
||
|
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 LintTest(),
|
||
|
];
|
||
|
|
||
|
// Override special handling of negative tests.
|
||
|
@override
|
||
|
Result processTestResult(
|
||
|
TestDescription description, Result result, bool last) {
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
List<int> rawBytes;
|
||
|
String cachedText;
|
||
|
List<int> lineStarts;
|
||
|
Uri uri;
|
||
|
|
||
|
void clear() {
|
||
|
rawBytes = null;
|
||
|
cachedText = null;
|
||
|
lineStarts = null;
|
||
|
uri = null;
|
||
|
}
|
||
|
|
||
|
String getErrorMessage(int offset, int squigglyLength, String message) {
|
||
|
Source source = new Source(lineStarts, rawBytes, uri, uri);
|
||
|
Location location = source.getLocation(uri, offset);
|
||
|
return command_line_reporting.formatErrorMessage(
|
||
|
source.getTextLine(location.line),
|
||
|
location,
|
||
|
squigglyLength,
|
||
|
uri.toString(),
|
||
|
message);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class LintTest extends Step<TestDescription, TestDescription, Context> {
|
||
|
const LintTest();
|
||
|
|
||
|
String get name => "lint test";
|
||
|
|
||
|
Future<Result<TestDescription>> run(
|
||
|
TestDescription description, Context context) async {
|
||
|
context.clear();
|
||
|
context.uri = description.uri;
|
||
|
|
||
|
File f = new File.fromUri(context.uri);
|
||
|
context.rawBytes = f.readAsBytesSync();
|
||
|
|
||
|
Uint8List bytes = new Uint8List(context.rawBytes.length + 1);
|
||
|
bytes.setRange(0, context.rawBytes.length, context.rawBytes);
|
||
|
|
||
|
Utf8BytesScanner scanner =
|
||
|
new Utf8BytesScanner(bytes, includeComments: true);
|
||
|
Token firstToken = scanner.tokenize();
|
||
|
context.lineStarts = scanner.lineStarts;
|
||
|
|
||
|
if (firstToken == null) return null;
|
||
|
List<String> problems;
|
||
|
LintListener lintListener =
|
||
|
new LintListener((int offset, int squigglyLength, String message) {
|
||
|
problems ??= new List<String>();
|
||
|
problems.add(context.getErrorMessage(offset, squigglyLength, message));
|
||
|
});
|
||
|
Parser parser = new Parser(lintListener);
|
||
|
parser.parseUnit(firstToken);
|
||
|
|
||
|
if (problems == null) {
|
||
|
return pass(description);
|
||
|
}
|
||
|
return fail(description, problems.join("\n\n"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class LintListener extends Listener {
|
||
|
final Function(int offset, int squigglyLength, String message) onProblem;
|
||
|
|
||
|
LintListener(this.onProblem);
|
||
|
|
||
|
LatestType _latestType;
|
||
|
|
||
|
@override
|
||
|
void beginVariablesDeclaration(
|
||
|
Token token, Token lateToken, Token varFinalOrConst) {
|
||
|
if (!_latestType.type) {
|
||
|
onProblem(
|
||
|
varFinalOrConst.offset, varFinalOrConst.length, "No explicit type.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void handleType(Token beginToken, Token questionMark) {
|
||
|
_latestType = new LatestType(beginToken, true);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
void handleNoType(Token lastConsumed) {
|
||
|
_latestType = new LatestType(lastConsumed, false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class LatestType {
|
||
|
final Token token;
|
||
|
bool type;
|
||
|
|
||
|
LatestType(this.token, this.type);
|
||
|
}
|