10
10
import os
11
11
import sys
12
12
import json
13
- from typing import List , Set , Dict
14
-
15
- #def apiRefTypeName(type_obj):
16
- # return ".".join(type_obj["Parents"] + [type_obj["Name"]])
13
+ from typing import List , Set , Dict , Optional
17
14
18
15
def getApiRefTopLevelType (type_obj ):
19
16
parents = type_obj ["Parents" ]
20
17
if parents :
21
18
return parents [0 ]
22
19
return type_obj ["Name" ]
23
20
24
- #def apiRefName(type_obj):
25
- # return type_obj["Api"] + ":" + apiRefTypeName(type_obj)
26
-
27
21
class DefaultDict (dict ):
28
22
def __init__ (self , factory ):
29
23
self .factory = factory
@@ -40,10 +34,14 @@ class ApiRef:
40
34
return self .combined .__eq__ (other .combined )
41
35
def __hash__ (self ):
42
36
return self .combined .__hash__ ()
37
+ def __str__ (self ):
38
+ return self .combined
39
+ def __repr__ (self ):
40
+ return self .combined
43
41
class ApiTypeNameToApiRefMap :
44
42
def __init__ (self ):
45
- self .top_level : dict [str ,Set [ApiRef ]] = {}
46
- self .nested : dict [str ,Set [ApiRef ]] = {}
43
+ self .top_level : Dict [str ,Set [ApiRef ]] = {}
44
+ self .nested : Dict [str ,Set [ApiRef ]] = {}
47
45
48
46
def getJsonApiRefs (api_refs : Set [ApiRef ], json_obj ):
49
47
if isinstance (json_obj , dict ):
@@ -85,7 +83,7 @@ def main():
85
83
apis = [getApiName (basename ) for basename in os .listdir (api_dir )]
86
84
apis .sort ()
87
85
88
- api_direct_type_refs_table : dict [str ,ApiTypeNameToApiRefMap ] = {}
86
+ api_direct_type_refs_table : Dict [str ,ApiTypeNameToApiRefMap ] = {}
89
87
print ("loading types..." )
90
88
for api_name in apis :
91
89
#print(api_name)
@@ -174,28 +172,68 @@ def main():
174
172
sys .exit ("!!!!!!!!!!! {} not in {} (and {} not in {})" .format (ref .name , api , nested_name , api ))
175
173
# TODO: should we save this nested name? not sure that we need to
176
174
177
-
178
175
print ("types verified" )
179
176
180
- print ("creating deps.dot ..." )
181
- with open ( os . path . join ( script_dir , "deps.dot" ), "w" ) as file :
182
- file . write ( "digraph deps { \n " )
177
+ print ("calculating recursive type references ..." )
178
+ api_recursive_type_refs_table : Dict [ str , dict [ str , Set [ ApiRef ]]] = {}
179
+ with open ( os . path . join ( script_dir , "out-recursive- deps.txt" ), "w" ) as file :
183
180
for api in apis :
181
+ #print("calculating recursive deps on {}...".format(api))
184
182
direct_type_refs_table = api_direct_type_refs_table [api ]
183
+ recursive_type_refs_table = {}
185
184
for type_name ,refs in direct_type_refs_table .top_level .items ():
186
- for ref in refs :
187
- table = api_direct_type_refs_table [ref .api ]
188
- if not isAnonType (ref .name ) and ref .name in table .top_level :
189
- file .write ("\" {}\" -> \" {}\" ;\n " .format (type_name , ref .name ))
190
- file .write ("}\n " )
185
+ recursive_chains : List [List [ApiRef ]] = []
186
+ getRecursiveChains (api_direct_type_refs_table , set (), refs , recursive_chains , None )
187
+ file .write ("{}:{} -> {}\n " .format (api , type_name , recursive_chains ))
188
+ recursive_type_refs_table [type_name ] = recursive_chains
189
+ api_recursive_type_refs_table [api ] = recursive_type_refs_table
190
+ print ("done calculating recursive type references" )
191
+
192
+ print ("searching for cycles..." )
193
+ with open (os .path .join (script_dir , "out-cycles.txt" ), "w" ) as file :
194
+ for api in apis :
195
+ #print("API: {}".format(api))
196
+ table = api_recursive_type_refs_table [api ]
197
+ cycle_count = 0
198
+ for type_name , recursive_chains in table .items ():
199
+ type_api_ref = ApiRef (api , type_name )
200
+ for chain in recursive_chains :
201
+ state = 0
202
+ for ref in chain :
203
+ if ref .api == api :
204
+ if state == 1 :
205
+ state = 2
206
+ break
207
+ else :
208
+ if state == 0 :
209
+ state = 1
210
+ if state == 2 :
211
+ file .write ("{}:{} CHAIN={}\n " .format (api , type_name , chain ))
212
+ cycle_count += 1
213
+ else :
214
+ pass
215
+ #print("NOT CYCLIC: {}:{} CHAIN={}".format(api, type_name, chain))
216
+ if cycle_count > 0 :
217
+ print ("{} cycles: {}:{}" .format (cycle_count , api , type_name ))
191
218
192
219
print ("done" )
193
- #for api in apis:
194
- #for api in [apis[0]]:
195
- # print("calculating recursive deps on {}...".format(api))
196
- # TODO: calculate recursive dependencies
197
220
198
221
222
+ def getRecursiveChains (api_direct_type_refs_table : Dict [str ,ApiTypeNameToApiRefMap ], handled : Set [ApiRef ], refs : Set [ApiRef ], result : List [List [ApiRef ]], current_chain : Optional [List [ApiRef ]]) -> None :
223
+ for ref in refs :
224
+ ref_api_table = api_direct_type_refs_table [ref .api ]
225
+ if not isAnonType (ref .name ) and ref .name in ref_api_table .top_level :
226
+ #file.write("\"{}\" -> \"{}\";\n".format(type_name, ref.name))
227
+ next_chain = current_chain
228
+ if not next_chain :
229
+ next_chain = []
230
+ result .append (next_chain )
231
+ next_chain .append (ref )
232
+
233
+ ref_refs = ref_api_table .top_level [ref .name ]
234
+ if not ref in handled :
235
+ handled .add (ref )
236
+ getRecursiveChains (api_direct_type_refs_table , handled , ref_refs , result , next_chain )
199
237
200
238
def getNestedName (type_name : str , ref : ApiRef ) -> str :
201
239
type_names = type_name .split ("." )
@@ -207,23 +245,5 @@ def getNestedName(type_name: str, ref: ApiRef) -> str:
207
245
i += 1
208
246
return "." .join (type_names + ref_names [i :])
209
247
210
- # recursive_dep_table: dict[str,Set[str]] = {}
211
- # for api in apis:
212
- # recursive_deps: Set[str] = set()
213
- # getRecursiveDeps(api_direct_deps, api, recursive_deps)
214
- # #print("{}: {}".format(api, recursive_deps))
215
- # recursive_dep_table[api] = recursive_deps
216
- # for api in apis:
217
- # recursive_deps = recursive_dep_table[api]
218
- # print("{}: {}".format(api, recursive_deps))
219
- # if api in recursive_deps:
220
- # print("{} is CYCLIC!!!!".format(api))
221
- #
222
- #def getRecursiveDeps(direct_dep_table: Set[Set[str]], name: str, result: Set[str]) -> None:
223
- # for direct_dep in direct_dep_table[name]:
224
- # if not direct_dep in result:
225
- # result.add(direct_dep)
226
- # getRecursiveDeps(direct_dep_table, direct_dep, result)
227
- #
228
248
229
249
main ()
0 commit comments