249249declare function spawn<T...>(callback: (T...) -> ())
250250declare function version(): string
251251declare function printidentity(prefix: string?)
252+ """
252253
254+ # Hardcoded types after data types have been defined
255+ POST_DATATYPES_BASE = """
253256export type RBXScriptSignal<T... = ...any> = {
254257 Wait: (self: RBXScriptSignal<T...>) -> T...,
255258 Connect: (self: RBXScriptSignal<T...>, callback: (T...) -> ()) -> RBXScriptConnection,
@@ -603,14 +606,8 @@ def printClasses(dump: ApiDump):
603606 print ()
604607
605608
606- def printDataTypes (types : DataTypesDump ):
607- # Forward declare all the types
608- for klass in types ["DataTypes" ]:
609- if klass ["Name" ] in IGNORED_INSTANCES :
610- continue
611- print (f"type { klass ['Name' ]} = any" )
612-
613- for klass in types ["DataTypes" ]:
609+ def printDataTypes (types : List [DataType ]):
610+ for klass in types :
614611 if klass ["Name" ] in IGNORED_INSTANCES :
615612 continue
616613 name = klass ["Name" ]
@@ -770,6 +767,82 @@ def loadClassesIntoStructures(dump: ApiDump):
770767 CLASSES [klass ["Name" ]] = klass
771768
772769
770+ def topologicalSortDataTypes (dataTypes : List [DataType ]) -> List [DataType ]:
771+ # A child of node in graph indicates that the child references the node
772+ graph : defaultdict [str , set [str ]] = defaultdict (set )
773+
774+ dataTypeNames = {klass ["Name" ] for klass in dataTypes }
775+
776+ def resolveClass (type : Union [ApiValueType , CorrectionsValueType ]):
777+ name = type ["Name" ][:- 1 ] if type ["Name" ][- 1 ] == "?" else type ["Name" ]
778+ if name in dataTypeNames :
779+ return name
780+
781+ return None
782+
783+ def createReference (klassName : str , referenced : str | None ):
784+ if referenced is not None :
785+ if klassName == referenced :
786+ return
787+ graph [referenced ].add (klassName )
788+
789+ for klass in dataTypes :
790+ klassName = klass ["Name" ]
791+
792+ if klassName not in graph :
793+ graph [klassName ] = set ()
794+
795+ for member in klass ["Members" ]:
796+ if member ["MemberType" ] == "Property" :
797+ createReference (klassName , resolveClass (member ["ValueType" ]))
798+ elif (
799+ member ["MemberType" ] == "Function" or member ["MemberType" ] == "Callback"
800+ ):
801+ for param in member ["Parameters" ]:
802+ createReference (klassName , resolveClass (param ["Type" ]))
803+ if "TupleReturns" in member :
804+ for ret in member ["TupleReturns" ]:
805+ createReference (klassName , resolveClass (ret ))
806+ else :
807+ createReference (klassName , resolveClass (member ["ReturnType" ]))
808+ elif member ["MemberType" ] == "Event" :
809+ for param in member ["Parameters" ]:
810+ createReference (klassName , resolveClass (param ["Type" ]))
811+
812+ visited : set [str ] = set ()
813+ tempMark : set [str ] = set ()
814+ sort : List [DataType ] = []
815+
816+ def visit (klass : DataType ):
817+ n = klass ["Name" ]
818+
819+ if n in visited :
820+ return
821+
822+ if n in tempMark :
823+ raise RuntimeError ()
824+
825+ tempMark .add (n )
826+
827+ for child in graph [n ]:
828+ visit (next (filter (lambda d : d ["Name" ] == child , dataTypes )))
829+
830+ tempMark .remove (n )
831+ visited .add (n )
832+ sort .append (klass )
833+
834+ stack : List [DataType ] = []
835+ for klass in dataTypes :
836+ stack .append (klass )
837+
838+ while stack :
839+ klass = stack .pop ()
840+ if klass ["Name" ] not in visited :
841+ visit (klass )
842+
843+ return list (reversed (sort ))
844+
845+
773846# Print global types
774847dataTypes : DataTypesDump = json .loads (requests .get (DATA_TYPES_URL ).text )
775848dump : ApiDump = json .loads (requests .get (API_DUMP_URL ).text )
@@ -783,7 +856,8 @@ def loadClassesIntoStructures(dump: ApiDump):
783856
784857print (START_BASE )
785858printEnums (dump )
786- printDataTypes (dataTypes )
859+ printDataTypes (topologicalSortDataTypes (dataTypes ["DataTypes" ]))
860+ print (POST_DATATYPES_BASE )
787861printClasses (dump )
788862printDataTypeConstructors (dataTypes )
789863print (END_BASE )
0 commit comments