blob: 7e5b75f92867e97a89119abf9ee70642c415935d [file] [log] [blame]
// 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 'dart:io';
import 'package:analyzer/src/lint/io.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:linter/src/analyzer.dart';
import 'package:linter/src/cli.dart' as cli;
import 'package:linter/src/rules.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
import 'integration/always_require_non_null_named_parameters.dart'
as always_require_non_null_named_parameters;
import 'integration/avoid_private_typedef_functions.dart'
as avoid_private_typedef_functions;
import 'integration/avoid_relative_lib_imports.dart'
as avoid_relative_lib_imports;
import 'integration/avoid_renaming_method_parameters.dart'
as avoid_renaming_method_parameters;
import 'integration/avoid_web_libraries_in_flutter.dart'
as avoid_web_libraries_in_flutter;
import 'integration/cancel_subscriptions.dart' as cancel_subscriptions;
import 'integration/close_sinks.dart' as close_sinks;
import 'integration/directives_ordering.dart' as directives_ordering;
import 'integration/exhaustive_cases.dart' as exhaustive_cases;
import 'integration/file_names.dart' as file_names;
import 'integration/flutter_style_todos.dart' as flutter_style_todos;
import 'integration/lines_longer_than_80_chars.dart'
as lines_longer_than_80_chars;
import 'integration/only_throw_errors.dart' as only_throw_errors;
import 'integration/overridden_fields.dart' as overridden_fields;
import 'integration/packages_file_test.dart' as packages_file_test;
import 'integration/prefer_asserts_in_initializer_lists.dart'
as prefer_asserts_in_initializer_lists;
import 'integration/prefer_const_constructors_in_immutables.dart'
as prefer_const_constructors_in_immutables;
import 'integration/prefer_relative_imports.dart' as prefer_relative_imports;
import 'integration/public_member_api_docs.dart' as public_member_api_docs;
import 'integration/sort_pub_dependencies.dart' as sort_pub_dependencies;
import 'integration/unnecessary_lambdas.dart' as unnecessary_lambdas;
import 'integration/unnecessary_string_escapes.dart'
as unnecessary_string_escapes;
import 'mocks.dart';
import 'rules/experiments/experiments.dart';
void main() {
group('integration', () {
ruleTests();
coreTests();
});
}
void coreTests() {
group('core', () {
group('config', () {
final currentOut = outSink;
final collectingOut = CollectingSink();
setUp(() {
exitCode = 0;
outSink = collectingOut;
});
tearDown(() {
collectingOut.buffer.clear();
outSink = currentOut;
exitCode = 0;
});
test('excludes', () async {
await cli.run(['test/_data/p2', '-c', 'test/_data/p2/lintconfig.yaml']);
expect(
collectingOut.trim(),
stringContainsInOrder(
['4 files analyzed, 1 issue found (2 filtered), in']));
expect(exitCode, 1);
});
test('overrides', () async {
await cli
.run(['test/_data/p2', '-c', 'test/_data/p2/lintconfig2.yaml']);
expect(collectingOut.trim(),
stringContainsInOrder(['4 files analyzed, 0 issues found, in']));
expect(exitCode, 0);
});
test('default', () async {
await cli.run(['test/_data/p2']);
expect(collectingOut.trim(),
stringContainsInOrder(['4 files analyzed, 3 issues found, in']));
expect(exitCode, 1);
});
});
group('pubspec', () {
final currentOut = outSink;
final collectingOut = CollectingSink();
setUp(() => outSink = collectingOut);
tearDown(() {
collectingOut.buffer.clear();
outSink = currentOut;
});
test('bad pubspec', () async {
await cli.run(['test/_data/p3', 'test/_data/p3/_pubpspec.yaml']);
expect(collectingOut.trim(),
startsWith('1 file analyzed, 0 issues found, in'));
});
});
group('canonicalization', () {
final currentOut = outSink;
final collectingOut = CollectingSink();
setUp(() => outSink = collectingOut);
tearDown(() {
collectingOut.buffer.clear();
outSink = currentOut;
});
test('no warnings due to bad canonicalization', () async {
var packagesFilePath = File('test/_data/p4/_packages').absolute.path;
await cli.runLinter(['--packages', packagesFilePath, 'test/_data/p4'],
LinterOptions([]));
expect(collectingOut.trim(),
startsWith('3 files analyzed, 0 issues found, in'));
});
});
group('examples', () {
test('all.yaml', () {
final src = readFile('example/all.yaml');
final options = _getOptionsFromString(src);
var configuredLints =
(options['linter'] as YamlMap)['rules'] as YamlList;
// rules are sorted
expect(
configuredLints, orderedEquals(configuredLints.toList()..sort()));
registerLintRules();
expect(
configuredLints,
unorderedEquals(Analyzer.facade.registeredRules
.where((r) =>
r.maturity != Maturity.deprecated &&
!experiments.contains(r))
.map((r) => r.name)));
});
});
});
}
void ruleTests() {
group('rule', () {
unnecessary_lambdas.main();
exhaustive_cases.main();
avoid_web_libraries_in_flutter.main();
packages_file_test.main();
overridden_fields.main();
close_sinks.main();
cancel_subscriptions.main();
directives_ordering.main();
file_names.main();
flutter_style_todos.main();
lines_longer_than_80_chars.main();
only_throw_errors.main();
always_require_non_null_named_parameters.main();
prefer_asserts_in_initializer_lists.main();
prefer_const_constructors_in_immutables.main();
avoid_relative_lib_imports.main();
prefer_relative_imports.main();
public_member_api_docs.main();
avoid_renaming_method_parameters.main();
avoid_private_typedef_functions.main();
sort_pub_dependencies.main();
unnecessary_string_escapes.main();
});
}
/// Provide the options found in [optionsSource].
Map<String, YamlNode> _getOptionsFromString(String optionsSource) {
final options = <String, YamlNode>{};
if (optionsSource == null) {
return options;
}
final doc = loadYamlNode(optionsSource);
// Empty options.
if (doc is YamlScalar && doc.value == null) {
return options;
}
if ((doc != null) && (doc is! YamlMap)) {
throw Exception(
'Bad options file format (expected map, got ${doc.runtimeType})');
}
if (doc is YamlMap) {
doc.nodes.forEach((k, YamlNode v) {
Object key;
if (k is YamlScalar) {
key = k.value;
}
if (key is! String) {
throw Exception('Bad options file format (expected String scope key, '
'got ${k.runtimeType})');
}
if (v != null && v is! YamlNode) {
throw Exception('Bad options file format (expected Node value, '
'got ${v.runtimeType}: `${v.toString()}`)');
}
options[key as String] = v;
});
}
return options;
}