Skip to content

Add tests for named arguments anywhere in constant #2892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dev_dependencies:
http: ^0.13.3
lints: ^1.0.1
test: ^1.19.0
test_descriptor: ^2.0.0

executables:
dartdoc: null
224 changes: 224 additions & 0 deletions test/constant_values_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// 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:async/async.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:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

import 'src/utils.dart' as utils;

void main() {
// We can not use ExperimentalFeature.releaseVersion or even
// ExperimentalFeature.experimentalReleaseVersion as these are set to null
// even when partial analyzer implementations are available, and are often
// set too high after release.
final constructorTearoffsAllowed =
VersionRange(min: Version.parse('2.15.0-0'), includeMin: true);

// We can not use ExperimentalFeature.releaseVersion or even
// ExperimentalFeature.experimentalReleaseVersion as these are set to null
// even when partial analyzer implementations are available.
final namedArgumentsAnywhereAllowed =
VersionRange(min: Version.parse('2.17.0-0'), includeMin: true);

group('constructor-tearoffs', () {
late Library library;
const libraryName = 'constructor_tearoffs';

final packageGraphMemo = AsyncMemoizer<PackageGraph>();
Future<PackageGraph> bootstrapPackageGraph() =>
packageGraphMemo.runOnce(() => utils.bootBasicPackage(
d.dir(libraryName).io.path,
pubPackageMetaProvider,
PhysicalPackageConfigProvider(),
additionalArguments: ['--no-link-to-remote']));

setUp(() async {
await d.dir(libraryName, [
d.file('pubspec.yaml', '''
name: constructor_tearoffs
version: 0.0.1
environment:
sdk: '>=2.15.0-0 <3.0.0'
'''),
d.file('analysis_options.yaml', '''
analyzer:
enable-experiment:
- constructor-tearoffs
'''),
d.dir('lib', [
d.file('lib.dart', '''
library $libraryName;

class F<T> {
F();

F.alternative();
}

typedef Ft<T> = F<T>;

void func() {}
void funcTypeParams<T extends String, U extends num>(
T something, U different) {}

const aFunc = func;
const aFuncParams = funcTypeParams;
const aFuncWithArgs = funcTypeParams<String, int>;
const aTearOffUnnamedConstructor = F.new;
const aTearOffUnnamedConstructorArgs = F<String>.new;
const aTearOffUnnamedConstructorTypedef = Fstring.new;
const aTearOffUnnamedConstructorArgsTypedef = Ft<String>.new;
const aTearOffNamedConstructor = F.alternative;
const aTearOffNamedConstructorArgs = F<int>.alternative;
'''),
]),
]).create();

library = (await bootstrapPackageGraph())
.libraries
.firstWhere((l) => l.name == libraryName);
});

test('non-generic function reference', () {
var aFuncConstant =
library.constants.firstWhere((c) => c.name == 'aFunc');
expect(aFuncConstant.constantValue, equals('func'));
});

test('generic function reference', () {
var aFuncParamsConstant =
library.constants.firstWhere((c) => c.name == 'aFuncParams');
expect(aFuncParamsConstant.constantValue, equals('funcTypeParams'));
});

test('generic function reference w/ type args', () {
var aFuncWithArgs =
library.constants.firstWhere((c) => c.name == 'aFuncWithArgs');
expect(aFuncWithArgs.constantValue,
equals('funcTypeParams&lt;String, int&gt;'));
});

test('named constructor reference', () {
var aTearOffNamedConstructor = library.constants
.firstWhere((c) => c.name == 'aTearOffNamedConstructor');
expect(aTearOffNamedConstructor.constantValue, equals('F.alternative'));
});

test('named constructor reference w/ type args', () {
var aTearOffNamedConstructorArgs = library.constants
.firstWhere((c) => c.name == 'aTearOffNamedConstructorArgs');
expect(aTearOffNamedConstructorArgs.constantValue,
equals('F&lt;int&gt;.alternative'));
});

test('unnamed constructor reference', () {
var aTearOffUnnamedConstructor = library.constants
.firstWhere((c) => c.name == 'aTearOffUnnamedConstructor');
expect(aTearOffUnnamedConstructor.constantValue, equals('F.new'));
});

test('unnamed constructor reference w/ type args', () {
var aTearOffUnnamedConstructorArgs = library.constants
.firstWhere((c) => c.name == 'aTearOffUnnamedConstructorArgs');
expect(aTearOffUnnamedConstructorArgs.constantValue,
equals('F&lt;String&gt;.new'));
});

test('unnamed typedef constructor reference', () {
var aTearOffUnnamedConstructorTypedef = library.constants
.firstWhere((c) => c.name == 'aTearOffUnnamedConstructorTypedef');
expect(aTearOffUnnamedConstructorTypedef.constantValue,
equals('Fstring.new'));
});

test('unnamed typedef constructor reference w/ type args', () {
var aTearOffUnnamedConstructorArgsTypedef = library.constants
.firstWhere((c) => c.name == 'aTearOffUnnamedConstructorArgsTypedef');
expect(aTearOffUnnamedConstructorArgsTypedef.constantValue,
equals('Ft&lt;String&gt;.new'));
});

test('constant rendering', () {}, skip: true);
}, skip: !constructorTearoffsAllowed.allows(utils.platformVersion));

group('named-arguments-anywhere', () {
late Library library;
const placeholder = '%%__HTMLBASE_dartdoc_internal__%%';
const libraryName = 'named_arguments_anywhere';
const linkPrefix = '$placeholder$libraryName';

final _testPackageGraphExperimentsMemo = AsyncMemoizer<PackageGraph>();
Future<PackageGraph> bootstrapPackageGraph() =>
_testPackageGraphExperimentsMemo.runOnce(() => utils.bootBasicPackage(
d.dir(libraryName).io.path,
pubPackageMetaProvider,
PhysicalPackageConfigProvider(),
additionalArguments: ['--no-link-to-remote']));

setUp(() async {
await d.dir(libraryName, [
d.file('pubspec.yaml', '''
name: named_arguments_anywhere
version: 0.0.1
environment:
sdk: '>=2.17.0-0 <3.0.0'
'''),
d.file('analysis_options.yaml', '''
analyzer:
enable-experiment:
- named-arguments-anywhere
'''),
d.dir('lib', [
d.file('lib.dart', '''
library $libraryName;

class C {
const C(int a, int b, {required int c, required int d});
}

const p = C(1, 2, c: 3, d: 4);

const q = C(1, c: 2, 3, d: 4);

const r = C(c: 1, d: 2, 3, 4);
'''),
]),
]).create();

library = (await bootstrapPackageGraph())
.libraries
.firstWhere((l) => l.name == libraryName);
});

test('named parameters in a const invocation value can be specified last',
() async {
var pConst = library.constants.firstWhere((c) => c.name == 'p');

expect(pConst.constantValue,
equals('<a href="$linkPrefix/C/C.html">C</a>(1, 2, c: 3, d: 4)'));
});

test(
'named parameters in a const invocation value can be specified anywhere',
() async {
var qConst = library.constants.firstWhere((c) => c.name == 'q');

expect(qConst.constantValue,
equals('<a href="$linkPrefix/C/C.html">C</a>(1, c: 2, 3, d: 4)'));
});

test('named parameters in a const invocation value can be specified first',
() async {
var rConst = library.constants.firstWhere((c) => c.name == 'r');

expect(rConst.constantValue,
equals('<a href="$linkPrefix/C/C.html">C</a>(c: 1, d: 2, 3, 4)'));
});
}, skip: !namedArgumentsAnywhereAllowed.allows(utils.platformVersion));
}
47 changes: 0 additions & 47 deletions test/end2end/model_special_cases_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -220,53 +220,6 @@ void main() {
expect(referenceLookup(A, 'new'), equals(MatchingLinkResult(null)));
expect(referenceLookup(At, 'new'), equals(MatchingLinkResult(null)));
});

test('constant rendering', () {
TopLevelVariable aFunc,
aFuncParams,
aTearOffDefaultConstructor,
aTearOffNonDefaultConstructor,
aTearOffNonDefaultConstructorInt,
aTearOffDefaultConstructorArgs;
TopLevelVariable aTearOffDefaultConstructorTypedef;
aFunc =
constructorTearoffs.constants.firstWhere((c) => c.name == 'aFunc');
aFuncParams = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aFuncParams');
aTearOffDefaultConstructor = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aTearOffDefaultConstructor');
aTearOffNonDefaultConstructor = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aTearOffNonDefaultConstructor');
aTearOffNonDefaultConstructorInt = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aTearOffNonDefaultConstructorInt');
aTearOffDefaultConstructorArgs = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aTearOffDefaultConstructorArgs');
aTearOffDefaultConstructorTypedef = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aTearOffDefaultConstructorTypedef');

expect(aFunc.constantValue, equals('func'));
expect(aFuncParams.constantValue, equals('funcTypeParams'));
var aFuncWithArgs = constructorTearoffs.constants
.firstWhere((c) => c.name == 'aFuncWithArgs');
expect(aFuncWithArgs.constantValue,
equals('funcTypeParams&lt;String, int&gt;'));

expect(aTearOffDefaultConstructor.constantValue, equals('F.new'));
expect(aTearOffNonDefaultConstructor.constantValue,
equals('F.alternative'));
expect(aTearOffNonDefaultConstructorInt.constantValue,
equals('F&lt;int&gt;.alternative'));
expect(aTearOffDefaultConstructorArgs.constantValue,
equals('F&lt;String&gt;.new'));

expect(aTearOffDefaultConstructorTypedef.constantValue,
equals('Fstring.new'));
var aTearOffDefaultConstructorArgsTypedef =
constructorTearoffs.constants.firstWhere(
(c) => c.name == 'aTearOffDefaultConstructorArgsTypedef');
expect(aTearOffDefaultConstructorArgsTypedef.constantValue,
equals('Ft&lt;String&gt;.new'));
});
}, skip: !_constructorTearoffsAllowed.allows(utils.platformVersion));
});

Expand Down
17 changes: 0 additions & 17 deletions testing/test_package_experiments/lib/constructor_tearoffs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,3 @@ typedef NotAClass = Function;

/// Mixins don't have constructors either, so disallow `M.new`.
mixin M<T> on C {}

void func() {}
void funcTypeParams<T extends String, U extends num>(
T something, U different) {}

const aFunc = func;
const aFuncParams = funcTypeParams;
const aFuncWithArgs = funcTypeParams<String, int>;

const aTearOffDefaultConstructor = F.new;
const aTearOffNonDefaultConstructor = F.alternative;
const aTearOffNonDefaultConstructorInt = F<int>.alternative;
const aTearOffDefaultConstructorArgs = F<String>.new;

const aTearOffDefaultConstructorTypedef = Fstring.new;

const aTearOffDefaultConstructorArgsTypedef = Ft<String>.new;