blob: 126c2cd9415acab01de91a8a25ecefc002c1be00 [file] [log] [blame]
// Copyright (c) 2022, 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/file_system/memory_file_system.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/package_config_provider.dart';
import 'package:dartdoc/src/package_meta.dart';
import 'package:test/test.dart';
import 'src/test_descriptor_utils.dart' as d;
import 'src/utils.dart';
void main() {
group('parameters', () {
late Library library;
// It is expensive (~10s) to compute a package graph, even skipping
// unreachable Dart SDK libraries, so we set up this package once.
setUpAll(() async {
const libraryName = 'super_parameters';
var packageMetaProvider = testPackageMetaProvider;
var packagePath = await d.createPackage(
libraryName,
libFiles: [
d.file('lib.dart', '''
library $libraryName;
class C {
int? f;
C.requiredPositional(this.f);
C.optionalPositional([this.f]);
C.defaultValue([this.f = 0]);
C.requiredNamed({required this.f});
C.named({this.f});
C.namedWithDefault({this.f = 0});
}
'''),
],
resourceProvider:
packageMetaProvider.resourceProvider as MemoryResourceProvider,
);
var packageConfigProvider =
getTestPackageConfigProvider(packageMetaProvider.defaultSdkDir.path);
packageConfigProvider.addPackageToConfigFor(
packagePath, libraryName, Uri.file('$packagePath/'));
var packageGraph = await bootBasicPackage(
packagePath,
packageMetaProvider,
packageConfigProvider,
);
library = packageGraph.libraries.named(libraryName);
});
test(
'required positional field formal parameters are presented with a '
'linked type', () async {
var requiredPositional = library.constructor('C.requiredPositional');
expect(requiredPositional.linkedParams, matchesCompressed(r'''
<span class="parameter" id="requiredPositional-param-f">
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">f</span>
</span>
'''));
});
test(
'optional positional field formal parameters are presented with a '
'linked type', () async {
var optionalPositional = library.constructor('C.optionalPositional');
expect(optionalPositional.linkedParams, matchesCompressed(r'''
<span class="parameter" id="optionalPositional-param-f">
\[
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">f</span>
\]
</span>
'''));
});
test(
'optional positional field formal parameters, with a default value, '
'are presented with a linked type', () async {
var defaultValue = library.constructor('C.defaultValue');
expect(defaultValue.linkedParams, matchesCompressed(r'''
<span class="parameter" id="defaultValue-param-f">
\[
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">f</span>
=
<span class="default-value">0</span>
\]
</span>
'''));
});
test(
'required named field formal parameters are presented with a '
'linked type', () async {
var requiredNamed = library.constructor('C.requiredNamed');
expect(requiredNamed.linkedParams, matchesCompressed(r'''
<span class="parameter" id="requiredNamed-param-f">
\{
<span>required</span>
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">f</span>
\}
</span>
'''));
});
test('named field formal parameters are presented with a linked type',
() async {
var named = library.constructor('C.named');
expect(named.linkedParams, matchesCompressed(r'''
<span class="parameter" id="named-param-f">
\{
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">f</span>
\}
</span>
'''));
});
test(
'named field formal parameters, with a default value, are presented '
'with a linked type', () async {
var namedWithDefault = library.constructor('C.namedWithDefault');
expect(namedWithDefault.linkedParams, matchesCompressed(r'''
<span class="parameter" id="namedWithDefault-param-f">
\{
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">f</span>
=
<span class="default-value">0</span>
\}
</span>
'''));
});
});
group('super-parameters', skip: !superParametersAllowed, () {
late Library library;
// It is expensive (~10s) to compute a package graph, even skipping
// unreachable Dart SDK libraries, so we set up this package once.
setUpAll(() async {
const libraryName = 'super_parameters';
await d.createPackage(
libraryName,
pubspec: '''
name: super_parameters
version: 0.0.1
environment:
sdk: '>=2.17.0-0 <3.0.0'
''',
analysisOptions: '''
analyzer:
enable-experiment:
- super-parameters
''',
libFiles: [
d.file('lib.dart', '''
library $libraryName;
class C {
C.requiredPositional(int a);
C.optionalPositional([int? a]);
C.defaultValue([int a = 0]);
C.requiredNamed({required int a});
C.named({int? a});
C.namedWithDefault({int a = 0});
int f;
C.fieldFormal(this.f);
C.positionalNum(num g);
}
class D extends C {
D.requiredPositional(super.a) : super.requiredPositional();
D.optionalPositional([super.a]) : super.optionalPositional();
D.defaultValue([super.a = 0]) : super.defaultValue();
D.requiredNamed({required super.a}) : super.requiredNamed();
D.named({super.a}) : super.named();
D.namedWithDefault({int a = 0}) : super.namedWithDefault();
D.fieldFormal(super.f) : super.fieldFormal();
D.positionalNum(int super.g) : super.positionalNum();
}
class E extends D {
E.superIsSuper(super.a) : super.requiredPositional();
}
'''),
],
);
var packageGraph = await bootBasicPackage(
d.dir(libraryName).io.path,
pubPackageMetaProvider,
PhysicalPackageConfigProvider(),
);
library = packageGraph.libraries.named(libraryName);
});
test(
'required positional super-parameters are presented with a linked type',
() async {
var requiredPositional = library.constructor('D.requiredPositional');
expect(requiredPositional.linkedParams, matchesCompressed(r'''
<span class="parameter" id="requiredPositional-param-a">
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">a</span>
</span>
'''));
});
test(
'optional positional super-parameters are presented with a linked type',
() async {
var optionalPositional = library.constructor('D.optionalPositional');
expect(optionalPositional.linkedParams, matchesCompressed(r'''
<span class="parameter" id="optionalPositional-param-a">
\[
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">a</span>
\]
</span>
'''));
});
test(
'optional positional super-parameters, with a default, are presented '
'with a linked type', () async {
var defaultValue = library.constructor('D.defaultValue');
expect(defaultValue.linkedParams, matchesCompressed(r'''
<span class="parameter" id="defaultValue-param-a">
\[
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">a</span>
=
<span class="default-value">0</span>
\]
</span>
'''));
});
test('required named super-parameters are presented with a linked type',
() async {
var requiredNamed = library.constructor('D.requiredNamed');
expect(requiredNamed.linkedParams, matchesCompressed(r'''
<span class="parameter" id="requiredNamed-param-a">
\{
<span>required</span>
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">a</span>
\}
</span>
'''));
});
test('named super-parameters are presented with a linked type', () async {
var named = library.constructor('D.named');
expect(named.linkedParams, matchesCompressed(r'''
<span class="parameter" id="named-param-a">
\{
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>\?
</span>
<span class="parameter-name">a</span>
\}
</span>
'''));
});
test(
'named super-parameters, with a default, are presented with a linked '
'type', () async {
var namedWithDefault = library.constructor('D.namedWithDefault');
expect(namedWithDefault.linkedParams, matchesCompressed(r'''
<span class="parameter" id="namedWithDefault-param-a">
\{
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">a</span>
=
<span class="default-value">0</span>
\}
</span>
'''));
});
test('super-constructor parameter is field formal', () async {
var fieldFormal = library.constructor('D.fieldFormal');
expect(fieldFormal.linkedParams, matchesCompressed(r'''
<span class="parameter" id="fieldFormal-param-f">
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">f</span>
</span>
'''));
});
test('super-constructor parameter is super-parameter', () async {
var superIsSuper = library.constructor('E.superIsSuper');
expect(superIsSuper.linkedParams, matchesCompressed(r'''
<span class="parameter" id="superIsSuper-param-a">
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">a</span>
</span>
'''));
});
test('parameter is subtype of super-constructor parameter', () async {
var positionalNum = library.constructor('D.positionalNum');
expect(positionalNum.linkedParams, matchesCompressed(r'''
<span class="parameter" id="positionalNum-param-g">
<span class="type-annotation">
<a href=".*/dart-core/int-class\.html">int</a>
</span>
<span class="parameter-name">g</span>
</span>
'''));
});
});
}
extension on Library {
Constructor constructor(String name) {
var className = name.split('.').first;
return classes
.firstWhere((c) => c.name == className)
.constructors
.firstWhere((c) => c.name == name);
}
}