Skip to content

Commit

Permalink
Add smoke tests for function as type parameter and triple-shift (#2603)
Browse files Browse the repository at this point in the history
* beginning

* first test

* test

* begin extracting annotation

* dartfmt, comment

* Update skip

* Rebuild renderers

* Beginning feature refactor

* Getting there

* obliterate strings

* Final cleanups

* Bypass @Native crashing us in flutter

* Restrict ast import

* Expand feature rendering out and get span classes fixed in parameters

* dartfmt

* Very basic tests

* review comments

* Add tests for triple-shift

* dartfmt

* Add skip outside 2.13
  • Loading branch information
jcollins-g authored Apr 2, 2021
1 parent 342d2d7 commit 31ec93e
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 0 deletions.
50 changes: 50 additions & 0 deletions test/end2end/model_special_cases_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,60 @@ void main() {
VersionRange(min: Version.parse('2.13.0-0'), includeMin: true);
final _genericMetadataAllowed =
VersionRange(min: Version.parse('2.13.0-0'), includeMin: true);
final _tripleShiftAllowed =
VersionRange(min: Version.parse('2.13.0-0'), includeMin: true);

// Experimental features not yet enabled by default. Move tests out of this
// block when the feature is enabled by default.
group('Experiments', () {
group('triple-shift', () {
Library tripleShift;
Class C, E, F;
Extension ShiftIt;
Operator classShift, extensionShift;
Field constantTripleShifted;

setUpAll(() async {
tripleShift = (await _testPackageGraphExperiments)
.libraries
.firstWhere((l) => l.name == 'triple_shift');
C = tripleShift.classes.firstWhere((c) => c.name == 'C');
E = tripleShift.classes.firstWhere((c) => c.name == 'E');
F = tripleShift.classes.firstWhere((c) => c.name == 'F');
ShiftIt = tripleShift.extensions.firstWhere((e) => e.name == 'ShiftIt');
classShift =
C.instanceOperators.firstWhere((o) => o.name.contains('>>>'));
extensionShift =
ShiftIt.instanceOperators.firstWhere((o) => o.name.contains('>>>'));
constantTripleShifted = C.constantFields
.firstWhere((f) => f.name == 'constantTripleShifted');
});

test('constants with triple shift render correctly', () {
expect(constantTripleShifted.constantValue, equals('3 >>> 5'));
});

test('operators exist and are named correctly', () {
expect(classShift.name, equals('operator >>>'));
expect(extensionShift.name, equals('operator >>>'));
});

test(
'inheritance and overriding of triple shift operators works correctly',
() {
var tripleShiftE =
E.instanceOperators.firstWhere((o) => o.name.contains('>>>'));
var tripleShiftF =
F.instanceOperators.firstWhere((o) => o.name.contains('>>>'));

expect(tripleShiftE.isInherited, isTrue);
expect(tripleShiftE.canonicalModelElement, equals(classShift));
expect(tripleShiftE.modelType.returnType.name, equals('C'));
expect(tripleShiftF.isInherited, isFalse);
expect(tripleShiftF.modelType.returnType.name, equals('F'));
});
}, skip: !_tripleShiftAllowed.allows(_platformVersion));

group('generic metadata', () {
Library genericMetadata;
TopLevelVariable f;
Expand Down
1 change: 1 addition & 0 deletions testing/test_package_experiments/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ analyzer:
enable-experiment:
- non-nullable
- nonfunction-type-aliases
- triple-shift
- generic-metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2021, 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.

/// Tests for verifying generic functions as type arguments.
library generic_function_type_args;

late List<T Function<T>(T)> idFunctions;
late S Function<S extends T Function<T>(T)>(S) ff;

typedef F = T Function<T>(T);

class C<T> {
final T value;
const C(this.value);
}

T f<T>(T value) => value;

extension E<T> on T {
T get extensionValue => this;
}

// A generic function type can be a type parameter bound.

// For a type alias:
typedef FB<T extends F> = S Function<S extends T>(S);

// For a class:
class CB<T extends FB<F>> {
final T function;
const CB(this.function);
}

// For a function:
T fb<T extends F>(T value) => value;

extension EB<T extends F> on T {
T get boundExtensionValue => this;

// Any function type has a `call` of its own type?
T get boundCall => this.call;
}

// Can be used as arguments to metadata too.
@C<F>(f)
@CB<FB<F>>(fb)
void main() {}
42 changes: 42 additions & 0 deletions testing/test_package_experiments/lib/triple_shift.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2021, 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.

/// Tests for verifying triple_shift operator, borrowed from the SDK.
library triple_shift;

class C {
static int ctr = 0;

/// Check that constants using a triple shift operator appear correctly.
static const int constantTripleShifted = 3>>>5;
final Object? _text;
C([Object? text]) : _text = text ?? "${++ctr}";

// It's possible to declare a `>>>` operator.
C operator >>>(arg) => C("(${++ctr}:$_text>>>$arg)");

// + binds more strongly than `>>`, `>>>` and `<<`.
C operator +(arg) => C("(${++ctr}:$_text+$arg)");
// Both `>>` and `<<` binds exactly as strongly as `>>>`.
C operator >>(arg) => C("(${++ctr}:$_text>>$arg)");
C operator <<(arg) => C("(${++ctr}:$_text<<$arg)");
// & binds less strongly than `>>`, `>>>` and `<<`.
C operator &(arg) => C("(${++ctr}:$_text&$arg)");

String toString() => "${_text}";
}

class _D extends C {}

class E extends _D {}

class F extends E {
@override
F operator >>>(arg) => F();
}

// Valid in extensions too.
extension ShiftIt<T> on T {
List<T> operator >>>(int count) => List<T>.filled(count, this);
}

0 comments on commit 31ec93e

Please sign in to comment.