Files
sdk/pkg/linter/test/engine_test.dart
T
Sam Rawlins f2a001d2fd Reland: Improve file structure of linter files.
There is much code in pkg/analyzer/lib/src/lint which is only used by
_tests_ and _tools_ in the linter package. This CL attempts to tidy up
the separation of linter lib code and non-lib code by moving some
files, and moving some source elements, which are only used in tests,
or in tools.

I originally dug into this because I saw `LinterOptions` has a public late field
(dangerous):

`late file_system.ResourceProvider resourceProvider;`

It turns out this field is only initialized in tests and tools, and
then it's read by multiple methods, and it just so happens those
methods are only called during tests or in tools.

Summary of changes:

* Mark LintDriver and DartLinter classes as only used for linter tools
  and tests.
* Remove CamelCaseString class.
* Mark `DartLinter.lintPubspecSource` as `@visibleForTesting`.
* LinterOptions: mark `enabledLints` and `analysisOptions` final, and remove
  `resourceProvider`.
* Remove SourceLinter; it was only used in a few `engine_test.dart` tests in
  linter, but all uses could be replaced with DartLinter.
* Remove linter's `bin/linter.dart`; it is not meant to be used as any sort of
  user entrypoint. The main method is moved to `cli.dart`.
* Move linter's `lib/src/cli.dart` to `tool/cli.dart`.
* analyzer's top-level function `lintFiles`, classes ErrorWatchingSink
  and FileGlobFilter are moved to linter's tool/ directory.
* Delete the engine_test.dart tests which only validate basics of
  linter's old entrypoint.

This reverts commit d1bc88de8f.

Change-Id: I1063aa72c640ad8ab62f76bf89f665cb8b9952dc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/334645
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
2023-11-10 21:25:11 +00:00

173 lines
5.1 KiB
Dart

// Copyright (c) 2015, 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 'package:analyzer/dart/ast/ast.dart' show AstNode, AstVisitor;
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/pub.dart';
import 'package:analyzer/src/string_source.dart' show StringSource;
import 'package:linter/src/utils.dart';
import 'package:test/test.dart';
import 'util/test_utils.dart';
void main() {
defineLinterEngineTests();
}
/// Linter engine tests
void defineLinterEngineTests() {
group('engine', () {
setUp(setUpSharedTestEnvironment);
group('reporter', () {
void doTest(
String label, String expected, Function(PrintingReporter r) report) {
test(label, () {
String? msg;
var reporter = PrintingReporter((m) => msg = m);
report(reporter);
expect(msg, expected);
});
}
doTest('exception', 'EXCEPTION: LinterException: foo',
(r) => r.exception(LinterException('foo')));
doTest('warn', 'WARN: foo', (r) => r.warn('foo'));
});
group('exceptions', () {
test('message', () {
expect(const LinterException('foo').message, 'foo');
});
test('toString', () {
expect(const LinterException().toString(), 'LinterException');
expect(const LinterException('foo').toString(), 'LinterException: foo');
});
});
group('camel case', () {
test('humanize', () {
expect(CamelCaseString('FooBar').humanized, 'Foo Bar');
expect(CamelCaseString('Foo').humanized, 'Foo');
});
test('validation', () {
expect(() => CamelCaseString('foo'),
throwsA(TypeMatcher<ArgumentError>()));
});
test('toString', () {
expect(CamelCaseString('FooBar').toString(), 'FooBar');
});
});
group('groups', () {
test('factory', () {
expect(Group('style').custom, isFalse);
expect(Group('pub').custom, isFalse);
expect(Group('errors').custom, isFalse);
expect(Group('Kustom').custom, isTrue);
});
test('builtins', () {
expect(Group.builtin.contains(Group.style), isTrue);
expect(Group.builtin.contains(Group.errors), isTrue);
expect(Group.builtin.contains(Group.pub), isTrue);
});
});
group('lint driver', () {
test('pubspec', () {
var visited = false;
var options =
LinterOptions(enabledRules: [MockLinter((n) => visited = true)]);
DartLinter(options).lintPubspecSource(contents: 'name: foo_bar');
expect(visited, isTrue);
});
test('error collecting', () {
var error = AnalysisError.tmp(
source: StringSource('foo', ''),
offset: 0,
length: 0,
errorCode: LintCode('MockLint', 'This is a test...'));
var linter = DartLinter(LinterOptions(enabledRules: []))
..onError(error);
expect(linter.errors.contains(error), isTrue);
});
});
group('dtos', () {
group('hyperlink', () {
test('html', () {
var link = Hyperlink('dart', 'http://dart.dev');
expect(link.html, '<a href="http://dart.dev">dart</a>');
});
test('html - strong', () {
var link = Hyperlink('dart', 'http://dart.dev', bold: true);
expect(
link.html, '<a href="http://dart.dev"><strong>dart</strong></a>');
});
});
group('rule', () {
test('comparing', () {
LintRule r1 = MockLintRule('Bar', Group('acme'));
LintRule r2 = MockLintRule('Foo', Group('acme'));
expect(r1.compareTo(r2), -1);
LintRule r3 = MockLintRule('Bar', Group('acme'));
LintRule r4 = MockLintRule('Bar', Group('woody'));
expect(r3.compareTo(r4), -1);
});
});
});
});
}
typedef NodeVisitor = void Function(Object node);
class MockLinter extends LintRule {
final NodeVisitor nodeVisitor;
MockLinter(this.nodeVisitor)
: super(
name: 'MockLint',
group: Group.style,
description: 'Desc',
details: 'And so on...');
@override
PubspecVisitor getPubspecVisitor() => MockPubspecVisitor(nodeVisitor);
@override
AstVisitor getVisitor() => MockVisitor(nodeVisitor);
}
class MockLintRule extends LintRule {
MockLintRule(String name, Group group)
: super(name: name, group: group, description: '', details: '');
@override
AstVisitor getVisitor() => MockVisitor(null);
}
class MockPubspecVisitor extends PubspecVisitor {
final NodeVisitor? nodeVisitor;
MockPubspecVisitor(this.nodeVisitor);
@override
void visitPackageName(PSEntry node) {
nodeVisitor?.call(node);
}
}
class MockVisitor extends GeneralizingAstVisitor {
final NodeVisitor? nodeVisitor;
MockVisitor(this.nodeVisitor);
@override
void visitNode(AstNode node) {
nodeVisitor?.call(node);
}
}