blob: 97ca5c671b1581cfffebf13cc20b824e2fb3e3e8 [file] [log] [blame]
// Copyright (c) 2023, 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/src/test_utilities/test_code_format.dart';
import 'package:collection/collection.dart';
import 'package:linter/src/rules.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../utils/test_code_extensions.dart';
import 'server_abstract.dart';
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(DocumentLinkTest);
});
}
@reflectiveTest
class DocumentLinkTest extends AbstractLspAnalysisServerTest {
static const _pubBase = 'https://pub.dev/packages/';
static const _lintBase = 'https://dart.dev/tools/linter-rules/';
@override
void setUp() {
registerLintRules();
super.setUp();
}
Future<void> test_analysisOptions_empty() async {
var content = '';
await _test_analysisOptions_links(content, []);
}
Future<void> test_analysisOptions_lint_links_list() async {
var content = '''
linter:
rules:
- /*[0*/prefer_relative_imports/*0]*/
- /*[1*/prefer_single_quotes/*1]*/
- /*[2*/prefer_int_literals/*2]*/
''';
var expectedLinks = [
'${_lintBase}prefer_relative_imports',
'${_lintBase}prefer_single_quotes',
'${_lintBase}prefer_int_literals',
];
await _test_analysisOptions_links(content, expectedLinks);
}
Future<void> test_analysisOptions_lint_links_map() async {
var content = '''
linter:
rules:
/*[0*/prefer_relative_imports/*0]*/: true
/*[1*/prefer_single_quotes/*1]*/: true
/*[2*/prefer_int_literals/*2]*/: false
''';
var expectedLinks = [
'${_lintBase}prefer_relative_imports',
'${_lintBase}prefer_single_quotes',
'${_lintBase}prefer_int_literals',
];
await _test_analysisOptions_links(content, expectedLinks);
}
Future<void> test_analysisOptions_linterRules_empty() async {
var content = '''
linter:
rules:
''';
await _test_pubspec_links(content, []);
}
Future<void> test_analysisOptions_undefinedLint() async {
var content = '''
linter:
rules:
- undefined
- /*[0*/prefer_single_quotes/*0]*/
''';
var expectedLinks = ['${_lintBase}prefer_single_quotes'];
await _test_analysisOptions_links(content, expectedLinks);
}
Future<void> test_exampleLink() async {
var exampleFolderPath = join(projectFolderPath, 'examples', 'api');
var exampleFileUri = Uri.file(join(exampleFolderPath, 'foo.dart'));
var code = TestCode.parse('''
/// {@tool dartpad}
/// ** See code in [!examples/api/foo.dart!] **
/// {@end-tool}
class A {}
''');
newFolder(exampleFolderPath);
newFile(mainFilePath, code.code);
await initialize();
var links = await getDocumentLinks(mainFileUri);
var link = links!.single;
expect(link.range, code.range.range);
expect(link.target, exampleFileUri);
}
Future<void> test_pubspec_empty() async {
var content = '';
await _test_pubspec_links(content, []);
}
Future<void> test_pubspec_packages_empty() async {
var content = '''
dependencies:
''';
await _test_pubspec_links(content, []);
}
Future<void> test_pubspec_packages_git() async {
var content = '''
dependencies:
/*[0*/github_package_1/*0]*/:
git: https://github.com/dart-lang/sdk.git
/*[1*/github_package_2/*1]*/:
git: git@github.com:dart-lang/sdk.git
/*[2*/github_package_3/*2]*/:
git:
url: https://github.com/dart-lang/sdk.git
''';
var expectedLinks = [
'https://github.com/dart-lang/sdk.git',
'https://github.com/dart-lang/sdk.git',
'https://github.com/dart-lang/sdk.git',
];
await _test_pubspec_links(content, expectedLinks);
}
Future<void> test_pubspec_packages_hosted() async {
var content = '''
dependencies:
/*[0*/hosted_package_1/*0]*/:
hosted: https://custom.dart.dev/
/*[1*/hosted_package_2/*1]*/:
hosted:
url: https://custom.dart.dev/
''';
var expectedLinks = [
'https://custom.dart.dev/packages/hosted_package_1',
'https://custom.dart.dev/packages/hosted_package_2',
];
await _test_pubspec_links(content, expectedLinks);
}
Future<void> test_pubspec_packages_pub() async {
var content = '''
dependencies:
/*[0*/pub_package_1/*0]*/: 1.2.3
/*[1*/pub_package_2/*1]*/: ^1.2.3
/*[2*/pub_package_3/*2]*/:
/*[3*/pub_package_4/*3]*/: any
''';
var expectedLinks = [
'${_pubBase}pub_package_1',
'${_pubBase}pub_package_2',
'${_pubBase}pub_package_3',
'${_pubBase}pub_package_4',
];
await _test_pubspec_links(content, expectedLinks);
}
Future<void> test_pubspec_packages_unknown() async {
var content = '''
dependencies:
flutter:
sdk: flutter
foo:
path: foo/
bar:
future_unknown_kind:
''';
await _test_pubspec_links(content, []);
}
Future<void> test_pubspec_packages_withDependencyOverrides() async {
var content = '''
dependencies:
/*[0*/dep_package/*0]*/: 1.0.0
dependency_overrides:
/*[1*/dep_package/*1]*/: 1.2.3
''';
var expectedLinks = ['${_pubBase}dep_package', '${_pubBase}dep_package'];
await _test_pubspec_links(content, expectedLinks);
}
Future<void> test_pubspec_packages_withDevDependencies() async {
var content = '''
dependencies:
/*[0*/dep_package/*0]*/: 1.2.3
dev_dependencies:
/*[1*/dev_dep_package/*1]*/:
''';
var expectedLinks = [
'${_pubBase}dep_package',
'${_pubBase}dev_dep_package',
];
await _test_pubspec_links(content, expectedLinks);
}
Future<void> _test_analysisOptions_links(
String content,
List<String> expected,
) async {
await _test_file_links(
analysisOptionsUri,
analysisOptionsPath,
content,
expected,
);
}
Future<void> _test_file_links(
Uri fileUri,
String filePath,
String content,
List<String> expectedLinks,
) async {
var code = TestCode.parse(content);
// Combine expectedLinks with the ranges from the markers in the content
// so we can verify both ranges and links.
expect(expectedLinks.length, code.ranges.length);
var expectedLinksWithRanges = expectedLinks.mapIndexed(
(i, link) => (code.ranges[i].range, link),
);
newFile(filePath, code.code);
await initialize();
var links = await getDocumentLinks(fileUri);
// Convert the results into the same format as expectedLinksWithRanges.
var linkData =
links!.map((link) => (link.range, link.target?.toString())).toList();
expect(linkData, equals(expectedLinksWithRanges));
}
Future<void> _test_pubspec_links(
String content,
List<String> expected,
) async {
await _test_file_links(pubspecFileUri, pubspecFilePath, content, expected);
}
}