@@ -51,6 +51,7 @@ class Transformer {
51
51
filterDeclSet = filterDeclSet.toList (),
52
52
namer = UniqueNamer ();
53
53
54
+ /// Transforms a TypeScript AST Node [TSNode] into a Dart representable [Node]
54
55
void transform (TSNode node) {
55
56
if (nodes.contains (node)) return ;
56
57
@@ -71,7 +72,6 @@ class Transformer {
71
72
_transformClassOrInterface (node as TSObjectDeclaration ),
72
73
_ => throw Exception ('Unsupported Declaration Kind: ${node .kind }' )
73
74
};
74
- // ignore: dead_code This line will not be dead in future decl additions
75
75
nodeMap.add (decl);
76
76
}
77
77
@@ -696,9 +696,16 @@ class Transformer {
696
696
constraint: getJSTypeAlternative (constraint));
697
697
}
698
698
699
- /// Parses the type
699
+ /// Parses a TypeScript AST Type Node [TSTypeNode] into a [Type] Node
700
+ /// used to represent a type
700
701
///
701
- /// TODO(https://github.com/dart-lang/web/issues/383): Add support for `typeof` types
702
+ /// [parameter] represents whether the [TSTypeNode] is being passed in
703
+ /// the context of a parameter, which is mainly used to differentiate between
704
+ /// using [num] and [double] in the context of a [JSNumber]
705
+ ///
706
+ /// [typeArg] represents whether the [TSTypeNode] is being passed in the
707
+ /// context of a type argument, as Dart core types are not allowed in
708
+ /// type arguments
702
709
Type _transformType (TSTypeNode type,
703
710
{bool parameter = false , bool typeArg = false }) {
704
711
switch (type.kind) {
@@ -794,6 +801,15 @@ class Transformer {
794
801
_ => throw UnimplementedError (
795
802
'Unsupported Literal Kind ${literal .kind }' )
796
803
});
804
+ case TSSyntaxKind .TypeQuery :
805
+ final typeQuery = type as TSTypeQueryNode ;
806
+
807
+ // TODO(nikeokoronkwo): Refactor this once #402 lands, https://github.com/dart-lang/web/pull/415
808
+ final exprName = typeQuery.exprName;
809
+ final typeArguments = typeQuery.typeArguments? .toDart;
810
+
811
+ return _getTypeFromDeclaration (exprName, typeArguments,
812
+ typeArg: typeArg, isNotTypableDeclaration: true );
797
813
case TSSyntaxKind .ArrayType :
798
814
return BuiltinType .primitiveType (PrimitiveType .array, typeParams: [
799
815
getJSTypeAlternative (
@@ -838,9 +854,27 @@ class Transformer {
838
854
}
839
855
}
840
856
857
+ /// Get the type of a type node named [typeName] by referencing its
858
+ /// declaration
859
+ ///
860
+ /// This method uses the TypeScript type checker [ts.TSTypeChecker] to get the
861
+ /// declaration associated with the [TSTypeNode] using its [typeName] , and
862
+ /// refer to that type either as a [ReferredType] if defined in the file, or
863
+ /// not directly supported by `dart:js_interop` , or as a [BuiltinType] if
864
+ /// supported by `dart:js_interop`
865
+ ///
866
+ /// [typeArg] represents whether the [TSTypeNode] is being passed in the
867
+ /// context of a type argument, as Dart core types are not allowed in
868
+ /// type arguments
869
+ ///
870
+ /// [isNotTypableDeclaration] represents whether the declaration to search for
871
+ /// or refer to is not a typable declaration (i.e a declaration suitable for
872
+ /// use in a `typeof` type node, such as a variable). This reduces checks on
873
+ /// supported `dart:js_interop` types and related [EnumDeclaration] -like and
874
+ /// [TypeDeclaration] -like checks
841
875
Type _getTypeFromDeclaration (
842
876
TSIdentifier typeName, List <TSTypeNode >? typeArguments,
843
- {bool typeArg = false }) {
877
+ {bool typeArg = false , bool isNotTypableDeclaration = false }) {
844
878
final name = typeName.text;
845
879
var declarationsMatching = nodeMap.findByName (name);
846
880
@@ -849,12 +883,14 @@ class Transformer {
849
883
// TODO(https://github.com/dart-lang/web/issues/380): A better name
850
884
// for this, and adding support for "supported declarations"
851
885
// (also a better name for that)
852
- final supportedType = BuiltinType .referred (name,
853
- typeParams: (typeArguments ?? [])
854
- .map ((t) => getJSTypeAlternative (_transformType (t)))
855
- .toList ());
856
- if (supportedType case final resultType? ) {
857
- return resultType;
886
+ if (! isNotTypableDeclaration) {
887
+ final supportedType = BuiltinType .referred (name,
888
+ typeParams: (typeArguments ?? [])
889
+ .map ((t) => getJSTypeAlternative (_transformType (t)))
890
+ .toList ());
891
+ if (supportedType case final resultType? ) {
892
+ return resultType;
893
+ }
858
894
}
859
895
860
896
final symbol = typeChecker.getSymbolAtLocation (typeName);
@@ -870,22 +906,24 @@ class Transformer {
870
906
throw Exception ('Found no declaration matching $name ' );
871
907
}
872
908
873
- // check if this is from dom
874
- final declarationSource = declaration.getSourceFile ().fileName;
875
- if (p.basename (declarationSource) == 'lib.dom.d.ts' ||
876
- declarationSource.contains ('dom' )) {
877
- // dom declaration: supported by package:web
878
- // TODO(nikeokoronkwo): It is possible that we may get a type
879
- // that isn't in `package:web`
880
- return PackageWebType .parse (name,
881
- typeParams: (typeArguments ?? [])
882
- .map (_transformType)
883
- .map (getJSTypeAlternative)
884
- .toList ());
885
- }
909
+ if (! isNotTypableDeclaration) {
910
+ // check if this is from dom
911
+ final declarationSource = declaration.getSourceFile ().fileName;
912
+ if (p.basename (declarationSource) == 'lib.dom.d.ts' ||
913
+ declarationSource.contains ('dom' )) {
914
+ // dom declaration: supported by package:web
915
+ // TODO(nikeokoronkwo): It is possible that we may get a type
916
+ // that isn't in `package:web`
917
+ return PackageWebType .parse (name,
918
+ typeParams: typeArguments
919
+ ? .map ((t) => getJSTypeAlternative (_transformType (t)))
920
+ .toList () ??
921
+ []);
922
+ }
886
923
887
- if (declaration.kind == TSSyntaxKind .TypeParameter ) {
888
- return GenericType (name: name);
924
+ if (declaration.kind == TSSyntaxKind .TypeParameter ) {
925
+ return GenericType (name: name);
926
+ }
889
927
}
890
928
891
929
transform (declaration);
@@ -896,23 +934,45 @@ class Transformer {
896
934
// TODO: In the case of overloading, should/shouldn't we handle more than one declaration?
897
935
final firstNode = declarationsMatching.whereType <NamedDeclaration >().first;
898
936
899
- // For Typealiases, we can either return the type itself
900
- // or the JS Alternative (if its underlying type isn't a JS type)
901
- switch (firstNode) {
902
- case TypeAliasDeclaration (type: final t):
903
- case EnumDeclaration (baseType: final t):
904
- final jsType = getJSTypeAlternative (t);
905
- if (jsType != t && typeArg) return jsType;
937
+ if (! isNotTypableDeclaration) {
938
+ // For Typealiases, we can either return the type itself
939
+ // or the JS Alternative (if its underlying type isn't a JS type)
940
+ switch (firstNode) {
941
+ case TypeAliasDeclaration (type: final t):
942
+ case EnumDeclaration (baseType: final t):
943
+ final jsType = getJSTypeAlternative (t);
944
+ if (jsType != t && typeArg) return jsType;
945
+ }
906
946
}
907
947
908
- return firstNode.asReferredType (
948
+ final asReferredType = firstNode.asReferredType (
909
949
(typeArguments ?? [])
910
950
.map ((type) => _transformType (type, typeArg: true ))
911
951
.toList (),
912
952
);
953
+
954
+ if (asReferredType case ReferredDeclarationType (type: final type)
955
+ when type is BuiltinType ) {
956
+ final jsType = getJSTypeAlternative (type);
957
+ if (jsType != type && typeArg) asReferredType.type = jsType;
958
+ }
959
+
960
+ return asReferredType;
913
961
}
914
962
915
- NodeMap filter () {
963
+ /// Filters out the declarations generated from the [transform] function and
964
+ /// returns the declarations needed based on:
965
+ ///
966
+ /// - Whether they are exported (contains the `export` keyword, or is in an
967
+ /// export declaration captured by [exportSet] )
968
+ /// - Whether they are denoted to be included in configuration
969
+ /// ([filterDeclSet] )
970
+ ///
971
+ /// The function also goes through declaration dependencies and filters those
972
+ /// in too
973
+ ///
974
+ /// Returns a [NodeMap] containing a map of the declared nodes and IDs.
975
+ NodeMap filterAndReturn () {
916
976
final filteredDeclarations = NodeMap ();
917
977
918
978
// filter out for export declarations
@@ -1026,8 +1086,11 @@ class Transformer {
1026
1086
t.id.toString (): t
1027
1087
});
1028
1088
break ;
1029
- case final BuiltinType _:
1030
- // primitive types are generated by default
1089
+ case BuiltinType (typeParams: final typeParams) when typeParams.isNotEmpty:
1090
+ filteredDeclarations.addAll ({
1091
+ for (final t in typeParams.where ((t) => t is ! BuiltinType ))
1092
+ t.id.toString (): t
1093
+ });
1031
1094
break ;
1032
1095
case final ReferredType r:
1033
1096
filteredDeclarations.add (r.declaration);
0 commit comments