@@ -36,7 +36,7 @@ bool enumClassAllowsAnyValue(String name) {
36
36
37
37
String generateDartForTypes (List <AstNode > types) {
38
38
final buffer = IndentableStringBuffer ();
39
- _getSorted (types).forEach ((t) => _writeType (buffer, t));
39
+ _getSortedUnique (types).forEach ((t) => _writeType (buffer, t));
40
40
final formattedCode = _formatCode (buffer.toString ());
41
41
return formattedCode.trim () + '\n ' ; // Ensure a single trailing newline.
42
42
}
@@ -95,9 +95,27 @@ List<Field> _getAllFields(Interface interface) {
95
95
.toList ();
96
96
}
97
97
98
- /// Returns a copy of the list sorted by name.
99
- List <AstNode > _getSorted (List <AstNode > items) {
100
- final sortedList = items.toList ();
98
+ /// Returns a copy of the list sorted by name with duplicates (by name+type) removed.
99
+ List <AstNode > _getSortedUnique (List <AstNode > items) {
100
+ final uniqueByName = < String , AstNode > {};
101
+ items.forEach ((item) {
102
+ // It's fine to have the same name used for different types (eg. namespace +
103
+ // type alias) but some types are just duplicated entirely in the spec in
104
+ // different positions which should not be emitted twice.
105
+ final nameTypeKey = '${item .name }|${item .runtimeType }' ;
106
+ if (uniqueByName.containsKey (nameTypeKey)) {
107
+ // At the time of writing, there were two duplicated types:
108
+ // - TextDocumentSyncKind (same defintion in both places)
109
+ // - TextDocumentSyncOptions (first definition is just a subset)
110
+ // If this list grows, consider handling this better - or try to have the
111
+ // spec updated to be unambigious.
112
+ print ('WARN: More than one definition for $nameTypeKey .' );
113
+ }
114
+
115
+ // Keep the last one as in some cases the first definition is less specific.
116
+ uniqueByName[nameTypeKey] = item;
117
+ });
118
+ final sortedList = uniqueByName.values.toList ();
101
119
sortedList.sort ((item1, item2) => item1.name.compareTo (item2.name));
102
120
return sortedList;
103
121
}
@@ -199,7 +217,7 @@ void _writeCanParseMethod(IndentableStringBuffer buffer, Interface interface) {
199
217
}
200
218
buffer.write ('!(' );
201
219
_writeTypeCheckCondition (
202
- buffer, "obj['${field .name }']" , field.type, 'reporter' );
220
+ buffer, interface , "obj['${field .name }']" , field.type, 'reporter' );
203
221
buffer
204
222
..write (')) {' )
205
223
..indent ()
@@ -302,7 +320,7 @@ void _writeEnumClass(IndentableStringBuffer buffer, Namespace namespace) {
302
320
..indent ();
303
321
if (allowsAnyValue) {
304
322
buffer.writeIndentedln ('return ' );
305
- _writeTypeCheckCondition (buffer, 'obj' , typeOfValues, 'reporter' );
323
+ _writeTypeCheckCondition (buffer, null , 'obj' , typeOfValues, 'reporter' );
306
324
buffer.writeln (';' );
307
325
} else {
308
326
buffer
@@ -445,7 +463,8 @@ void _writeFromJsonCodeForUnion(
445
463
446
464
// Dynamic matches all type checks, so only emit it if required.
447
465
if (! isDynamic) {
448
- _writeTypeCheckCondition (buffer, valueCode, type, 'nullLspJsonReporter' );
466
+ _writeTypeCheckCondition (
467
+ buffer, null , valueCode, type, 'nullLspJsonReporter' );
449
468
buffer.write (' ? ' );
450
469
}
451
470
@@ -609,7 +628,7 @@ void _writeMember(IndentableStringBuffer buffer, Member member) {
609
628
}
610
629
611
630
void _writeMembers (IndentableStringBuffer buffer, List <Member > members) {
612
- _getSorted (members).forEach ((m) => _writeMember (buffer, m));
631
+ _getSortedUnique (members).forEach ((m) => _writeMember (buffer, m));
613
632
}
614
633
615
634
void _writeToJsonFieldsForResponseMessage (
@@ -685,8 +704,8 @@ void _writeType(IndentableStringBuffer buffer, AstNode type) {
685
704
}
686
705
}
687
706
688
- void _writeTypeCheckCondition (IndentableStringBuffer buffer, String valueCode,
689
- TypeBase type, String reporter) {
707
+ void _writeTypeCheckCondition (IndentableStringBuffer buffer,
708
+ Interface interface , String valueCode, TypeBase type, String reporter) {
690
709
type = resolveTypeAlias (type);
691
710
692
711
final dartType = type.dartType;
@@ -703,17 +722,20 @@ void _writeTypeCheckCondition(IndentableStringBuffer buffer, String valueCode,
703
722
// TODO(dantup): If we're happy to assume we never have two lists in a union
704
723
// we could skip this bit.
705
724
buffer.write (' && ($valueCode .every((item) => ' );
706
- _writeTypeCheckCondition (buffer, 'item' , type.elementType, reporter);
725
+ _writeTypeCheckCondition (
726
+ buffer, interface , 'item' , type.elementType, reporter);
707
727
buffer.write ('))' );
708
728
}
709
729
buffer.write (')' );
710
730
} else if (type is MapType ) {
711
731
buffer.write ('($valueCode is Map' );
712
732
if (fullDartType != 'dynamic' ) {
713
733
buffer..write (' && (' )..write ('$valueCode .keys.every((item) => ' );
714
- _writeTypeCheckCondition (buffer, 'item' , type.indexType, reporter);
734
+ _writeTypeCheckCondition (
735
+ buffer, interface , 'item' , type.indexType, reporter);
715
736
buffer..write ('&& $valueCode .values.every((item) => ' );
716
- _writeTypeCheckCondition (buffer, 'item' , type.valueType, reporter);
737
+ _writeTypeCheckCondition (
738
+ buffer, interface , 'item' , type.valueType, reporter);
717
739
buffer.write (')))' );
718
740
}
719
741
buffer.write (')' );
@@ -724,9 +746,18 @@ void _writeTypeCheckCondition(IndentableStringBuffer buffer, String valueCode,
724
746
if (i != 0 ) {
725
747
buffer.write (' || ' );
726
748
}
727
- _writeTypeCheckCondition (buffer, valueCode, type.types[i], reporter);
749
+ _writeTypeCheckCondition (
750
+ buffer, interface , valueCode, type.types[i], reporter);
728
751
}
729
752
buffer.write (')' );
753
+ } else if (interface != null &&
754
+ interface .typeArgs != null &&
755
+ interface .typeArgs.any ((typeArg) => typeArg.lexeme == fullDartType)) {
756
+ final comment = '/* $fullDartType .canParse($valueCode ) */' ;
757
+ print (
758
+ 'WARN: Unable to write a type check for $valueCode with generic type $fullDartType . '
759
+ 'Please review the generated code annotated with $comment ' );
760
+ buffer.write ('true $comment ' );
730
761
} else {
731
762
throw 'Unable to type check $valueCode against $fullDartType ' ;
732
763
}
0 commit comments