blob: be04c302a18171cd423537a511a41492663f6cb1 [file] [log] [blame]
// 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.
/// @docImport 'package:dartdoc/src/model/model_element.dart';
library;
import 'package:collection/collection.dart';
import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/nameable.dart';
import 'package:dartdoc/src/model/package_graph.dart';
import 'package:test/test.dart';
const _separator = '.';
abstract class Base with Nameable, CommentReferable {
@override
PackageGraph get packageGraph => throw UnimplementedError();
List<Base> get children;
Base? parent;
/// Utility function to quickly build structures similar to [ModelElement]
/// hierarchies in dartdoc in tests.
/// Returns the added (or already existing) [Base].
Base add(String newName);
CommentReferable? lookup<T extends CommentReferable?>(
String value, {
bool Function(CommentReferable?)? filter,
}) {
return referenceBy(value.split(_separator), filter: filter ?? (_) => true);
}
@override
Iterable<CommentReferable>? get referenceGrandparentOverrides => null;
}
class Top extends Base {
@override
final String name;
@override
final List<TopChild> children;
Top(this.name, this.children);
@override
Base add(String newName) {
Base retval;
var newNameSplit = newName.split(_separator).toList();
var parent = children.firstWhereOrNull((c) => c.name == newNameSplit.first);
if (parent == null) {
parent = TopChild(newNameSplit.last, [], this);
children.add(parent);
retval = parent;
}
retval = parent;
if (newNameSplit.length > 1) {
retval = parent.add(newNameSplit.sublist(1).join(_separator));
}
return retval;
}
@override
Map<String, CommentReferable> get referenceChildren =>
Map.fromEntries(children.map((c) => MapEntry(c.name, c)));
@override
Iterable<CommentReferable> get referenceParents => [];
}
abstract class Child extends Base {
@override
List<Child> get children;
@override
Base add(String newName) {
Base retval;
var newNameSplit = newName.split(_separator).toList();
var child = children.firstWhereOrNull((c) => c.name == newNameSplit.first);
if (child == null) {
child = GenericChild(newNameSplit.last, [], this);
children.add(child);
}
retval = child;
if (newNameSplit.length > 1) {
retval = child.add(newNameSplit.sublist(1).join(_separator));
}
return retval;
}
}
class TopChild extends Child {
@override
final String name;
@override
final List<GenericChild> children;
final Top _parent;
@override
Top get parent => _parent;
TopChild(this.name, this.children, this._parent);
@override
Map<String, CommentReferable> get referenceChildren =>
Map.fromEntries(children.map((c) => MapEntry(c.name, c)));
@override
Iterable<CommentReferable> get referenceParents => [parent];
}
class GenericChild extends Child {
@override
final String name;
@override
final List<GenericChild> children;
final Base _parent;
@override
Base get parent => _parent;
GenericChild(this.name, this.children, this._parent);
@override
Map<String, CommentReferable> get referenceChildren =>
Map.fromEntries(children.map((c) => MapEntry(c.name, c)));
@override
Iterable<CommentReferable> get referenceParents => [parent];
}
class GrandparentOverrider extends GenericChild {
@override
final Iterable<Base> referenceGrandparentOverrides;
GrandparentOverrider(super.name, super.children, super.parent,
this.referenceGrandparentOverrides);
}
void main() {
group('Basic comment reference lookups', () {
late Top referable;
setUp(() {
referable = Top('top', []);
referable.add('lib1');
referable.add('lib2');
referable.add('lib3');
referable.add('lib1.class1');
referable.add('lib1.class2');
referable.add('lib1.class2.member1');
referable.add('lib2');
referable.add('lib2.class3');
referable.add('lib3.lib3.lib3');
});
test('Check that basic lookups work', () {
expect(referable.lookup('lib1')?.name, equals('lib1'));
expect(referable.lookup('lib2')?.name, equals('lib2'));
expect(referable.lookup('lib1.class2.member1')?.name, equals('member1'));
expect(referable.lookup('lib2.class3')?.name, equals('class3'));
});
test('Check that filters work', () {
expect(referable.lookup('lib3'), isA<TopChild>());
expect(referable.lookup('lib3', filter: (r) => r is GenericChild),
isA<GenericChild>());
});
test('Check that grandparent overrides work', () {
referable.add('lib4');
var i1 = referable.add('lib4.intermediate1');
var i1target = referable.add('lib4.intermediate1.target');
referable.add('lib4.intermediate2');
var i2target = referable.add('lib4.intermediate2.target');
var i2other = referable.add('lib4.intermediate2.other');
var i2notFromHere = referable.add('lib4.intermediate2.notFromHere');
var overrider = GrandparentOverrider('fromHere', [], i2other, [i1]);
i2other.children.add(overrider);
expect(i2notFromHere.lookup('target'), i2target);
// Ordinarily, since overrider's parent is i2target, we would expect this
// to work the same. But it has an override.
expect(overrider.lookup('target'), i1target);
expect(overrider.lookup('intermediate2.target'), i2target);
});
});
}