Skip to content

Commit 41787d0

Browse files
authored
support generic methods (#1282)
* support generic methods * include in detail page * update test expectations * regen test docs
1 parent efd2c0f commit 41787d0

File tree

77 files changed

+511
-14
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+511
-14
lines changed

.analysis_options

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
analyzer:
22
strong-mode: true
3+
language:
4+
enableGenericMethods: true
35
exclude:
46
- 'doc/api/**'
57
- 'lib/templates/*.html'

lib/dartdoc.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class DartDoc {
186186
SourceFactory sourceFactory = new SourceFactory(resolvers);
187187

188188
var options = new AnalysisOptionsImpl();
189+
options.enableGenericMethods = true;
189190

190191
AnalysisEngine.instance.processRequiredPlugins();
191192

lib/src/html/template_data.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ class FunctionTemplateData extends TemplateData<ModelFunction> {
277277
'${function.name} function - ${library.name} library - Dart API';
278278
@override
279279
String get layoutTitle =>
280-
_layoutTitle(function.name, 'function', function.isDeprecated);
280+
_layoutTitle(function.nameWithGenerics, 'function', function.isDeprecated);
281281
@override
282282
String get metaDescription =>
283283
'API docs for the ${function.name} function from the '
@@ -306,7 +306,7 @@ class MethodTemplateData extends TemplateData<Method> {
306306
'${library.name} library - Dart API';
307307
@override
308308
String get layoutTitle =>
309-
_layoutTitle(method.name, method.fullkind, method.isDeprecated);
309+
_layoutTitle(method.nameWithGenerics, method.fullkind, method.isDeprecated);
310310
@override
311311
String get metaDescription =>
312312
'API docs for the ${method.name} method from the ${clazz.name} class, '

lib/src/model.dart

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ class Class extends ModelElement implements EnclosedElement {
528528
// problem if we want to show that info later.
529529
List<ElementType> get mixins => _mixins;
530530

531+
@override
531532
String get nameWithGenerics {
532533
if (!modelType.isParameterizedType) return name;
533534
return '$name&lt;${_typeParameters.map((t) => t.name).join(', ')}&gt;';
@@ -1221,15 +1222,24 @@ class Method extends ModelElement
12211222
implements EnclosedElement {
12221223
bool _isInherited = false;
12231224
Class _enclosingClass;
1225+
List<TypeParameter> typeParameters = [];
12241226

12251227
Method(MethodElement element, Library library) : super(element, library) {
12261228
_modelType = new ElementType(_method.type, this);
1229+
_calcTypeParameters();
12271230
}
12281231

12291232
Method.inherited(MethodElement element, this._enclosingClass, Library library)
12301233
: super(element, library) {
12311234
_modelType = new ElementType(_method.type, this);
12321235
_isInherited = true;
1236+
_calcTypeParameters();
1237+
}
1238+
1239+
void _calcTypeParameters() {
1240+
typeParameters = _method.typeParameters.map((f) {
1241+
return new TypeParameter(f, library);
1242+
}).toList();
12331243
}
12341244

12351245
@override
@@ -1263,6 +1273,18 @@ class Method extends ModelElement
12631273

12641274
String get linkedReturnType => modelType.createLinkedReturnTypeName();
12651275

1276+
@override
1277+
String get nameWithGenerics {
1278+
if (typeParameters.isEmpty) return name;
1279+
return '$name&lt;${typeParameters.map((t) => t.name).join(', ')}&gt;';
1280+
}
1281+
1282+
@override
1283+
String get genericParameters {
1284+
if (typeParameters.isEmpty) return '';
1285+
return '&lt;${typeParameters.map((t) => t.name).join(', ')}&gt;';
1286+
}
1287+
12661288
@override
12671289
Method get overriddenElement {
12681290
ClassElement parent = element.enclosingElement;
@@ -1482,6 +1504,10 @@ abstract class ModelElement implements Comparable, Nameable, Documentable {
14821504
@override
14831505
String get name => element.name;
14841506

1507+
String get nameWithGenerics => name;
1508+
1509+
String get genericParameters => '';
1510+
14851511
@override
14861512
String get oneLineDoc => _documentation.asOneLiner;
14871513

@@ -1673,11 +1699,7 @@ abstract class ModelElement implements Comparable, Nameable, Documentable {
16731699
}
16741700
}
16751701

1676-
var classContent = '';
1677-
if (isDeprecated) {
1678-
classContent = 'class="deprecated" ';
1679-
}
1680-
1702+
var classContent = isDeprecated ? 'class="deprecated" ' : '';
16811703
return '<a ${classContent}href="${href}">$name</a>';
16821704
}
16831705

@@ -1726,9 +1748,18 @@ abstract class ModelElement implements Comparable, Nameable, Documentable {
17261748
class ModelFunction extends ModelElement
17271749
with SourceCodeMixin
17281750
implements EnclosedElement {
1751+
List<TypeParameter> typeParameters = [];
1752+
17291753
ModelFunction(FunctionElement element, Library library)
17301754
: super(element, library) {
17311755
_modelType = new ElementType(_func.type, this);
1756+
_calcTypeParameters();
1757+
}
1758+
1759+
void _calcTypeParameters() {
1760+
typeParameters = _func.typeParameters.map((f) {
1761+
return new TypeParameter(f, library);
1762+
}).toList();
17321763
}
17331764

17341765
@override
@@ -1747,6 +1778,18 @@ class ModelFunction extends ModelElement
17471778

17481779
String get linkedReturnType => modelType.createLinkedReturnTypeName();
17491780

1781+
@override
1782+
String get nameWithGenerics {
1783+
if (typeParameters.isEmpty) return name;
1784+
return '$name&lt;${typeParameters.map((t) => t.name).join(', ')}&gt;';
1785+
}
1786+
1787+
@override
1788+
String get genericParameters {
1789+
if (typeParameters.isEmpty) return '';
1790+
return '&lt;${typeParameters.map((t) => t.name).join(', ')}&gt;';
1791+
}
1792+
17501793
FunctionElement get _func => (element as FunctionElement);
17511794
}
17521795

@@ -2240,6 +2283,7 @@ class Typedef extends ModelElement
22402283
? modelType.createLinkedReturnTypeName()
22412284
: _typedef.returnType.name;
22422285

2286+
@override
22432287
String get nameWithGenerics {
22442288
if (!modelType.isParameterizedType) return name;
22452289
return '$name&lt;${_typeParameters.map((t) => t.name).join(', ')}&gt;';

lib/templates/_callable.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<dt id="{{htmlId}}" class="callable{{ #isInherited }} inherited{{ /isInherited}}">
2-
<span class="name{{#isDeprecated}} deprecated{{/isDeprecated}}">{{{linkedName}}}</span><span class="signature">(<wbr>{{{ linkedParamsNoMetadata }}})
2+
<span class="name{{#isDeprecated}} deprecated{{/isDeprecated}}">{{{linkedName}}}</span><span class="signature">{{{genericParameters}}}(<wbr>{{{ linkedParamsNoMetadata }}})
33
<span class="returntype parameter">&#8594; {{{ linkedReturnType }}}</span>
44
</span>
55
</dt>

lib/templates/_callable_multiline.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
</div>
99
{{/hasAnnotations}}
1010
<span class="returntype">{{{ linkedReturnType }}}</span>
11-
{{>name_summary}}(<wbr>{{#hasParameters}}{{{linkedParamsLines}}}{{/hasParameters}})
11+
{{>name_summary}}{{{genericParameters}}}(<wbr>{{#hasParameters}}{{{linkedParamsLines}}}{{/hasParameters}})

test/model_test.dart

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ void main() {
588588
});
589589

590590
test('get methods', () {
591-
expect(Dog.instanceMethods, hasLength(5));
591+
expect(Dog.instanceMethods, hasLength(6));
592592
});
593593

594594
test('get operators', () {
@@ -637,7 +637,7 @@ void main() {
637637
});
638638

639639
test('F has many inherited methods', () {
640-
expect(F.inheritedMethods, hasLength(8));
640+
expect(F.inheritedMethods, hasLength(9));
641641
expect(
642642
F.inheritedMethods.map((im) => im.name),
643643
equals([
@@ -647,6 +647,7 @@ void main() {
647647
'noSuchMethod',
648648
'test',
649649
'testGeneric',
650+
'testGenericMethod',
650651
'testMethod',
651652
'toString'
652653
]));
@@ -741,6 +742,7 @@ void main() {
741742
String valueByName(var name) {
742743
return animal.constants.firstWhere((f) => f.name == name).constantValue;
743744
}
745+
744746
expect(valueByName('CAT'), equals('const Animal(0)'));
745747
expect(valueByName('DOG'), equals('const Animal(1)'));
746748
expect(valueByName('HORSE'), equals('const Animal(2)'));
@@ -759,11 +761,14 @@ void main() {
759761

760762
group('Function', () {
761763
ModelFunction f1;
764+
ModelFunction genericFunction;
762765
ModelFunction thisIsAsync;
763766
ModelFunction topLevelFunction;
764767

765768
setUp(() {
766-
f1 = exLibrary.functions.single;
769+
f1 = exLibrary.functions.first;
770+
genericFunction =
771+
exLibrary.functions.firstWhere((f) => f.name == 'genericFunction');
767772
thisIsAsync =
768773
fakeLibrary.functions.firstWhere((f) => f.name == 'thisIsAsync');
769774
topLevelFunction =
@@ -848,12 +853,16 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
848853
'<span class="type-annotation"><a href="fake/Callback2.html">Callback2</a></span> '
849854
'<span class="parameter-name">callback</span></span>');
850855
});
856+
857+
test('supports generic methods', () {
858+
expect(genericFunction.nameWithGenerics, 'genericFunction&lt;T&gt;');
859+
});
851860
});
852861

853862
group('Method', () {
854863
Class classB, klass, HasGenerics, Cat, CatString;
855864
Method m1, isGreaterThan, m4, m5, m6, m7, convertToMap, abstractMethod;
856-
Method inheritedClear, testGeneric;
865+
Method inheritedClear, testGeneric, testGenericMethod;
857866

858867
setUp(() {
859868
klass = exLibrary.classes.singleWhere((c) => c.name == 'Klass');
@@ -879,6 +888,10 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
879888
.singleWhere((c) => c.name == 'Dog')
880889
.instanceMethods
881890
.singleWhere((m) => m.name == 'testGeneric');
891+
testGenericMethod = exLibrary.classes
892+
.singleWhere((c) => c.name == 'Dog')
893+
.instanceMethods
894+
.singleWhere((m) => m.name == 'testGenericMethod');
882895
convertToMap = HasGenerics.instanceMethods
883896
.singleWhere((m) => m.name == 'convertToMap');
884897
});
@@ -963,6 +976,10 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans,
963976
expect(functionArgParam.modelType.createLinkedReturnTypeName(), 'String');
964977
});
965978

979+
test('generic method type args are rendered', () {
980+
expect(testGenericMethod.nameWithGenerics, 'testGenericMethod&lt;T&gt;');
981+
});
982+
966983
test('doc for method with no return type', () {
967984
var comment = m5.documentation;
968985
var comment2 = m6.documentation;

test/src/utils.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ class AnalyzerHelper {
7979
SourceFactory sourceFactory = new SourceFactory(resolvers);
8080
AnalysisEngine.instance.processRequiredPlugins();
8181
context = AnalysisEngine.instance.createAnalysisContext();
82+
context.analysisOptions = new AnalysisOptionsImpl()
83+
..enableGenericMethods = true;
8284
context.sourceFactory = sourceFactory;
8385
}
8486

testing/test_package/lib/example.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ get y => 2;
4848

4949
int function1(String s, bool b, lastParam) => 5;
5050

51+
T genericFunction<T>(T arg) {
52+
return arg;
53+
}
54+
5155
typedef String processMessage<T>(String msg);
5256

5357
enum Animal {
@@ -227,6 +231,10 @@ class Dog implements Cat, E {
227231

228232
void testMethod(Iterable it) {}
229233

234+
T testGenericMethod<T>(T arg) {
235+
return arg;
236+
}
237+
230238
@Deprecated("Internal use")
231239
static Dog createDog(String s) {
232240
return new Dog.deprecatedCreate(s);

testing/test_package_docs/ex/Animal-class.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ <h5><a href="ex/ex-library.html">ex</a></h5>
9797

9898
<li class="section-title"><a href="ex/ex-library.html#functions">Functions</a></li>
9999
<li><a href="ex/function1.html">function1</a></li>
100+
<li><a href="ex/genericFunction.html">genericFunction</a></li>
100101

101102
<li class="section-title"><a href="ex/ex-library.html#enums">Enums</a></li>
102103
<li><a href="ex/Animal-class.html">Animal</a></li>

0 commit comments

Comments
 (0)