@@ -51,6 +51,7 @@ class Transformer {
5151 filterDeclSet = filterDeclSet.toList (),
5252 namer = UniqueNamer ();
5353
54+ /// Transforms a TypeScript AST Node [TSNode] into a Dart representable [Node]
5455 void transform (TSNode node) {
5556 if (nodes.contains (node)) return ;
5657
@@ -71,7 +72,6 @@ class Transformer {
7172 _transformClassOrInterface (node as TSObjectDeclaration ),
7273 _ => throw Exception ('Unsupported Declaration Kind: ${node .kind }' )
7374 };
74- // ignore: dead_code This line will not be dead in future decl additions
7575 nodeMap.add (decl);
7676 }
7777
@@ -696,9 +696,16 @@ class Transformer {
696696 constraint: getJSTypeAlternative (constraint));
697697 }
698698
699- /// Parses the type
699+ /// Parses a TypeScript AST Type Node [TSTypeNode] into a [Type] Node
700+ /// used to represent a type
700701 ///
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
702709 Type _transformType (TSTypeNode type,
703710 {bool parameter = false , bool typeArg = false }) {
704711 switch (type.kind) {
@@ -794,6 +801,15 @@ class Transformer {
794801 _ => throw UnimplementedError (
795802 'Unsupported Literal Kind ${literal .kind }' )
796803 });
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 );
797813 case TSSyntaxKind .ArrayType :
798814 return BuiltinType .primitiveType (PrimitiveType .array, typeParams: [
799815 getJSTypeAlternative (
@@ -838,9 +854,27 @@ class Transformer {
838854 }
839855 }
840856
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
841875 Type _getTypeFromDeclaration (
842876 TSIdentifier typeName, List <TSTypeNode >? typeArguments,
843- {bool typeArg = false }) {
877+ {bool typeArg = false , bool isNotTypableDeclaration = false }) {
844878 final name = typeName.text;
845879 var declarationsMatching = nodeMap.findByName (name);
846880
@@ -849,12 +883,14 @@ class Transformer {
849883 // TODO(https://github.com/dart-lang/web/issues/380): A better name
850884 // for this, and adding support for "supported declarations"
851885 // (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+ }
858894 }
859895
860896 final symbol = typeChecker.getSymbolAtLocation (typeName);
@@ -870,22 +906,24 @@ class Transformer {
870906 throw Exception ('Found no declaration matching $name ' );
871907 }
872908
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+ }
886923
887- if (declaration.kind == TSSyntaxKind .TypeParameter ) {
888- return GenericType (name: name);
924+ if (declaration.kind == TSSyntaxKind .TypeParameter ) {
925+ return GenericType (name: name);
926+ }
889927 }
890928
891929 transform (declaration);
@@ -896,23 +934,45 @@ class Transformer {
896934 // TODO: In the case of overloading, should/shouldn't we handle more than one declaration?
897935 final firstNode = declarationsMatching.whereType <NamedDeclaration >().first;
898936
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+ }
906946 }
907947
908- return firstNode.asReferredType (
948+ final asReferredType = firstNode.asReferredType (
909949 (typeArguments ?? [])
910950 .map ((type) => _transformType (type, typeArg: true ))
911951 .toList (),
912952 );
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;
913961 }
914962
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 () {
916976 final filteredDeclarations = NodeMap ();
917977
918978 // filter out for export declarations
@@ -1026,8 +1086,11 @@ class Transformer {
10261086 t.id.toString (): t
10271087 });
10281088 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+ });
10311094 break ;
10321095 case final ReferredType r:
10331096 filteredDeclarations.add (r.declaration);
0 commit comments