Skip to content

Commit 8ec6844

Browse files
authored
Add basic comment reference tests plus a small framework (#2658)
* beginnings of tests * Basic tests * dartfmt goodness
1 parent 9d89c34 commit 8ec6844

File tree

2 files changed

+204
-7
lines changed

2 files changed

+204
-7
lines changed

lib/src/markdown_processor.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:dartdoc/src/model/model.dart';
1616
import 'package:dartdoc/src/quiver.dart';
1717
import 'package:dartdoc/src/warnings.dart';
1818
import 'package:markdown/markdown.dart' as md;
19+
import 'package:meta/meta.dart';
1920

2021
const validHtmlTags = [
2122
'a',
@@ -947,7 +948,7 @@ const _referenceLookupWarnings = {
947948
};
948949

949950
md.Node _makeLinkNode(String codeRef, Warnable warnable) {
950-
var result = _getMatchingLinkElement(warnable, codeRef);
951+
var result = getMatchingLinkElement(warnable, codeRef);
951952
var textContent = htmlEscape.convert(codeRef);
952953
var linkedElement = result.modelElement;
953954
if (linkedElement != null) {
@@ -976,7 +977,10 @@ md.Node _makeLinkNode(String codeRef, Warnable warnable) {
976977
return md.Element.text('code', textContent);
977978
}
978979

979-
MatchingLinkResult _getMatchingLinkElement(Warnable warnable, String codeRef) {
980+
@visibleForTesting
981+
MatchingLinkResult getMatchingLinkElement(Warnable warnable, String codeRef,
982+
{bool experimentalReferenceLookup}) {
983+
experimentalReferenceLookup ??= warnable.config.experimentalReferenceLookup;
980984
MatchingLinkResult result, resultOld, resultNew;
981985
// Do a comparison between result types only if the warnings for them are
982986
// enabled, because there's a significant performance penalty.
@@ -989,13 +993,12 @@ MatchingLinkResult _getMatchingLinkElement(Warnable warnable, String codeRef) {
989993
if (resultNew.modelElement != null) {
990994
markdownStats.resolvedNewLookupReferences++;
991995
}
992-
result =
993-
warnable.config.experimentalReferenceLookup ? resultNew : resultOld;
996+
result = experimentalReferenceLookup ? resultNew : resultOld;
994997
if (resultOld.modelElement != null) {
995998
markdownStats.resolvedOldLookupReferences++;
996999
}
9971000
} else {
998-
if (warnable.config.experimentalReferenceLookup) {
1001+
if (experimentalReferenceLookup) {
9991002
result = _getMatchingLinkElementCommentReferable(codeRef, warnable);
10001003
} else {
10011004
result = _getMatchingLinkElementLegacy(codeRef, warnable);

test/end2end/model_test.dart

Lines changed: 196 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'dart:io';
99
import 'package:analyzer/source/line_info.dart';
1010
import 'package:async/async.dart';
1111
import 'package:dartdoc/src/element_type.dart';
12+
import 'package:dartdoc/src/markdown_processor.dart';
1213
import 'package:dartdoc/src/model/feature.dart';
1314
import 'package:dartdoc/src/model/model.dart';
1415
import 'package:dartdoc/src/package_config_provider.dart';
@@ -25,7 +26,7 @@ import 'package:test/test.dart';
2526
import '../src/utils.dart' as utils;
2627

2728
final _testPackageGraphMemo = AsyncMemoizer<PackageGraph>();
28-
Future<PackageGraph> get _testPackageGraph =>
29+
Future<PackageGraph> get testPackageGraph async =>
2930
_testPackageGraphMemo.runOnce(() => utils.bootBasicPackage(
3031
'testing/test_package',
3132
pubPackageMetaProvider,
@@ -80,7 +81,7 @@ void main() {
8081
setUpAll(() async {
8182
// Use model_special_cases_test.dart for tests that require
8283
// a different package graph.
83-
packageGraph = await _testPackageGraph;
84+
packageGraph = await testPackageGraph;
8485
exLibrary = packageGraph.libraries.firstWhere((lib) => lib.name == 'ex');
8586
fakeLibrary =
8687
packageGraph.libraries.firstWhere((lib) => lib.name == 'fake');
@@ -2119,6 +2120,199 @@ void main() {
21192120
});
21202121
});
21212122

2123+
// Put linkage tests here; rendering tests should go to the appropriate
2124+
// [Class], [Extension], etc groups.
2125+
group('Comment References link tests', () {
2126+
ModelFunction doesStuff, function1, topLevelFunction;
2127+
TopLevelVariable incorrectDocReference,
2128+
incorrectDocReferenceFromEx,
2129+
nameWithTwoUnderscores,
2130+
nameWithSingleUnderscore,
2131+
theOnlyThingInTheLibrary;
2132+
Class Apple, BaseClass, baseForDocComments, ExtraSpecialList, string;
2133+
Method doAwesomeStuff, anotherMethod;
2134+
// ignore: unused_local_variable
2135+
Operator bracketOperator, bracketOperatorOtherClass;
2136+
Parameter doAwesomeStuffParam;
2137+
Field forInheriting, action;
2138+
2139+
setUpAll(() async {
2140+
nameWithTwoUnderscores = fakeLibrary.constants
2141+
.firstWhere((v) => v.name == 'NAME_WITH_TWO_UNDERSCORES');
2142+
nameWithSingleUnderscore = fakeLibrary.constants
2143+
.firstWhere((v) => v.name == 'NAME_SINGLEUNDERSCORE');
2144+
string = packageGraph.allLibraries.values
2145+
.firstWhere((e) => e.name == 'dart:core')
2146+
.allClasses
2147+
.firstWhere((c) => c.name == 'String');
2148+
baseForDocComments =
2149+
fakeLibrary.classes.firstWhere((c) => c.name == 'BaseForDocComments');
2150+
doAwesomeStuff = baseForDocComments.instanceMethods
2151+
.firstWhere((m) => m.name == 'doAwesomeStuff');
2152+
anotherMethod = baseForDocComments.instanceMethods
2153+
.firstWhere((m) => m.name == 'anotherMethod');
2154+
doAwesomeStuffParam = doAwesomeStuff.parameters.first;
2155+
topLevelFunction =
2156+
fakeLibrary.functions.firstWhere((f) => f.name == 'topLevelFunction');
2157+
function1 = exLibrary.functions.firstWhere((f) => f.name == 'function1');
2158+
Apple = exLibrary.classes.firstWhere((c) => c.name == 'Apple');
2159+
incorrectDocReference = fakeLibrary.constants
2160+
.firstWhere((v) => v.name == 'incorrectDocReference');
2161+
incorrectDocReferenceFromEx = exLibrary.constants
2162+
.firstWhere((v) => v.name == 'incorrectDocReferenceFromEx');
2163+
theOnlyThingInTheLibrary = packageGraph.libraries
2164+
.firstWhere((l) => l.name == 'csspub')
2165+
.properties
2166+
.firstWhere((v) => v.name == 'theOnlyThingInTheLibrary');
2167+
doesStuff = packageGraph.allLibraries.values
2168+
.firstWhere((l) => l.name == 'anonymous_library')
2169+
.functions
2170+
.firstWhere((f) => f.name == 'doesStuff');
2171+
BaseClass = packageGraph.allLibraries.values
2172+
.firstWhere((l) => l.name == 'two_exports.src.base')
2173+
.classes
2174+
.firstWhere((c) => c.name == 'BaseClass');
2175+
bracketOperator = baseForDocComments.instanceOperators
2176+
.firstWhere((o) => o.name == 'operator []');
2177+
bracketOperatorOtherClass = fakeLibrary.classes
2178+
.firstWhere((c) => c.name == 'SpecialList')
2179+
.instanceOperators
2180+
.firstWhere((o) => o.name == 'operator []');
2181+
ExtraSpecialList =
2182+
fakeLibrary.classes.firstWhere((c) => c.name == 'ExtraSpecialList');
2183+
forInheriting = fakeLibrary.classes
2184+
.firstWhere((c) => c.name == 'ImplicitProperties')
2185+
.allFields
2186+
.firstWhere((n) => n.name == 'forInheriting');
2187+
action = packageGraph.allLibraries.values
2188+
.firstWhere((l) => l.name == 'reexport.somelib')
2189+
.classes
2190+
.firstWhere((c) => c.name == 'BaseReexported')
2191+
.allFields
2192+
.firstWhere((f) => f.name == 'action');
2193+
});
2194+
2195+
/// For comparison purposes, return an equivalent [MatchingLinkResult]
2196+
/// for the defining element returned. May return [originalResult].
2197+
/// We do this to eliminate canonicalization effects from comparison,
2198+
/// as the original lookup code returns canonicalized results and the
2199+
/// new lookup code is only guaranteed to return equivalent results.
2200+
MatchingLinkResult definingLinkResult(MatchingLinkResult originalResult) {
2201+
if (originalResult.modelElement != null) {
2202+
return MatchingLinkResult(
2203+
ModelElement.fromElement(originalResult.modelElement.element,
2204+
originalResult.modelElement.packageGraph),
2205+
warn: originalResult.warn);
2206+
}
2207+
return originalResult;
2208+
}
2209+
2210+
MatchingLinkResult originalLookup(Warnable element, String codeRef) =>
2211+
definingLinkResult(getMatchingLinkElement(element, codeRef,
2212+
experimentalReferenceLookup: false));
2213+
MatchingLinkResult newLookup(Warnable element, String codeRef) =>
2214+
definingLinkResult(getMatchingLinkElement(element, codeRef,
2215+
experimentalReferenceLookup: true));
2216+
2217+
MatchingLinkResult bothLookup(Warnable element, String codeRef) {
2218+
var originalLookupResult = originalLookup(element, codeRef);
2219+
var newLookupResult = newLookup(element, codeRef);
2220+
expect(newLookupResult, equals(originalLookupResult));
2221+
return newLookupResult;
2222+
}
2223+
2224+
test('Verify basic linking inside class', () {
2225+
// parameter of [doAwesomeStuff]
2226+
// Parameter lookups are discarded with the original lookup code
2227+
expect(originalLookup(doAwesomeStuff, 'value'),
2228+
equals(MatchingLinkResult(null, warn: false)));
2229+
expect(newLookup(doAwesomeStuff, 'value'),
2230+
equals(MatchingLinkResult(doAwesomeStuffParam)));
2231+
2232+
// Parent class of [doAwesomeStuff].
2233+
expect(bothLookup(doAwesomeStuff, 'BaseForDocComments'),
2234+
equals(MatchingLinkResult(baseForDocComments)));
2235+
2236+
// Top level constants in the same library as [doAwesomeStuff].
2237+
expect(bothLookup(doAwesomeStuff, 'NAME_WITH_TWO_UNDERSCORES'),
2238+
equals(MatchingLinkResult(nameWithTwoUnderscores)));
2239+
expect(bothLookup(doAwesomeStuff, 'NAME_SINGLEUNDERSCORE'),
2240+
equals(MatchingLinkResult(nameWithSingleUnderscore)));
2241+
2242+
// Top level class from [dart:core].
2243+
// TODO(jcollins-g): dart:core not recognized yet with new lookup code.
2244+
expect(originalLookup(doAwesomeStuff, 'String'),
2245+
equals(MatchingLinkResult(string)));
2246+
2247+
// Another method in the same class.
2248+
expect(bothLookup(doAwesomeStuff, 'anotherMethod'),
2249+
equals(MatchingLinkResult(anotherMethod)));
2250+
2251+
// A top level function in this library.
2252+
// TODO(jcollins-g): top level functions not recognized yet with new lookup code.
2253+
expect(originalLookup(doAwesomeStuff, 'topLevelFunction'),
2254+
equals(MatchingLinkResult(topLevelFunction)));
2255+
2256+
// A top level function in another library imported into this library.
2257+
// TODO(jcollins-g): namespace lookups are not yet implemented with new lookup code.
2258+
expect(originalLookup(doAwesomeStuff, 'function1'),
2259+
equals(MatchingLinkResult(function1)));
2260+
2261+
// A class in another library imported into this library.
2262+
// TODO(jcollins-g): namespace lookups are not yet implemented with new lookup code.
2263+
expect(originalLookup(doAwesomeStuff, 'Apple'),
2264+
equals(MatchingLinkResult(Apple)));
2265+
2266+
// A top level constant in this library sharing the same name as a name in another library.
2267+
// TODO(jcollins-g): namespace lookups are not yet implemented with new lookup code.
2268+
expect(originalLookup(doAwesomeStuff, 'incorrectDocReference'),
2269+
equals(MatchingLinkResult(incorrectDocReference)));
2270+
2271+
// A top level constant in another library.
2272+
// TODO(jcollins-g): namespace lookups are not yet implemented with new lookup code.
2273+
expect(originalLookup(doAwesomeStuff, 'incorrectDocReferenceFromEx'),
2274+
equals(MatchingLinkResult(incorrectDocReferenceFromEx)));
2275+
2276+
// A prefixed constant in another library.
2277+
// TODO(jcollins-g): prefixed namespace lookups are not yet implemented with new lookup code.
2278+
expect(originalLookup(doAwesomeStuff, 'css.theOnlyThingInTheLibrary'),
2279+
equals(MatchingLinkResult(theOnlyThingInTheLibrary)));
2280+
2281+
// A name that exists in this package but is not imported.
2282+
// TODO(jcollins-g): package-wide lookups are not yet implemented with the new lookup code.
2283+
expect(originalLookup(doAwesomeStuff, 'doesStuff'),
2284+
equals(MatchingLinkResult(doesStuff)));
2285+
2286+
// A name of a class from an import of a library that exported that name.
2287+
expect(originalLookup(doAwesomeStuff, 'BaseClass'),
2288+
equals(MatchingLinkResult(BaseClass)));
2289+
2290+
// A bracket operator within this class.
2291+
// TODO(jcollins-g): operator lookups not yet implemented with the new lookup code.
2292+
expect(originalLookup(doAwesomeStuff, 'operator []'),
2293+
equals(MatchingLinkResult(bracketOperator)));
2294+
2295+
// A bracket operator in another class.
2296+
// TODO(jcollins-g): This has never worked...
2297+
//expect(bothLookup(doAwesomeStuff, 'SpecialList.operator []'), equals(MatchingLinkResult(bracketOperatorOtherClass)));
2298+
2299+
// Reference containing a type parameter.
2300+
expect(bothLookup(doAwesomeStuff, 'ExtraSpecialList<Object>'),
2301+
equals(MatchingLinkResult(ExtraSpecialList)));
2302+
2303+
// Reference to an inherited member.
2304+
expect(
2305+
bothLookup(
2306+
doAwesomeStuff, 'ClassWithUnusualProperties.forInheriting'),
2307+
equals(MatchingLinkResult(forInheriting)));
2308+
2309+
// Reference to an inherited member in another library via class name.
2310+
// TODO(jcollins-g): reference to non-imported symbols isn't implemented yet in new lookup.
2311+
expect(originalLookup(doAwesomeStuff, 'ExtendedBaseReexported.action'),
2312+
equals(MatchingLinkResult(action)));
2313+
});
2314+
});
2315+
21222316
group('Extension', () {
21232317
Extension arm, leg, ext, fancyList, uphill;
21242318
Extension documentOnceReexportOne, documentOnceReexportTwo;

0 commit comments

Comments
 (0)