1616from codegen .sdk .codebase .diff_lite import ChangeType , DiffLite
1717from codegen .sdk .codebase .flagging .flags import Flags
1818from codegen .sdk .codebase .io .file_io import FileIO
19+ from codegen .sdk .codebase .progress .stub_progress import StubProgress
1920from codegen .sdk .codebase .transaction_manager import TransactionManager
2021from codegen .sdk .codebase .validation import get_edges , post_reset_validation
2122from codegen .sdk .core .autocommit import AutoCommit , commiter
3940 from codegen .git .repo_operator .repo_operator import RepoOperator
4041 from codegen .sdk .codebase .io .io import IO
4142 from codegen .sdk .codebase .node_classes .node_classes import NodeClasses
43+ from codegen .sdk .codebase .progress .progress import Progress
4244 from codegen .sdk .core .dataclasses .usage import Usage
4345 from codegen .sdk .core .expressions import Expression
4446 from codegen .sdk .core .external_module import ExternalModule
@@ -111,16 +113,19 @@ class CodebaseContext:
111113 projects : list [ProjectConfig ]
112114 unapplied_diffs : list [DiffLite ]
113115 io : IO
116+ progress : Progress
114117
115118 def __init__ (
116119 self ,
117120 projects : list [ProjectConfig ],
118121 config : CodebaseConfig = DefaultConfig ,
119122 io : IO | None = None ,
123+ progress : Progress | None = None ,
120124 ) -> None :
121125 """Initializes codebase graph and TransactionManager"""
122126 from codegen .sdk .core .parser import Parser
123127
128+ self .progress = progress or StubProgress ()
124129 self ._graph = PyDiGraph ()
125130 self .filepath_idx = {}
126131 self ._ext_module_idx = {}
@@ -371,7 +376,6 @@ def _process_diff_files(self, files_to_sync: Mapping[SyncType, list[Path]], incr
371376 skip_uncache = incremental and ((len (files_to_sync [SyncType .DELETE ]) + len (files_to_sync [SyncType .REPARSE ])) == 0 )
372377 if not skip_uncache :
373378 uncache_all ()
374-
375379 # Step 0: Start the dependency manager and language engine if they exist
376380 # Start the dependency manager. This may or may not run asynchronously, depending on the implementation
377381 if self .dependency_manager is not None :
@@ -429,24 +433,29 @@ def _process_diff_files(self, files_to_sync: Mapping[SyncType, list[Path]], incr
429433 file = self .get_file (file_path )
430434 file .remove_internal_edges ()
431435
436+ task = self .progress .begin ("Reparsing updated files" , count = len (files_to_sync [SyncType .REPARSE ]))
432437 files_to_resolve = []
433438 # Step 4: Reparse updated files
434- for file_path in files_to_sync [SyncType .REPARSE ]:
439+ for idx , file_path in enumerate (files_to_sync [SyncType .REPARSE ]):
440+ task .update (f"Reparsing { self .to_relative (file_path )} " , count = idx )
435441 file = self .get_file (file_path )
436442 to_resolve .extend (file .unparse (reparse = True ))
437443 to_resolve = list (filter (lambda node : self .has_node (node .node_id ) and node is not None , to_resolve ))
438444 file .sync_with_file_content ()
439445 files_to_resolve .append (file )
440-
446+ task . end ()
441447 # Step 5: Add new files as nodes to graph (does not yet add edges)
442- for filepath in files_to_sync [SyncType .ADD ]:
448+ task = self .progress .begin ("Adding new files" , count = len (files_to_sync [SyncType .ADD ]))
449+ for idx , filepath in enumerate (files_to_sync [SyncType .ADD ]):
450+ task .update (f"Adding { self .to_relative (filepath )} " , count = idx )
443451 content = self .io .read_text (filepath )
444452 # TODO: this is wrong with context changes
445453 if filepath .suffix in self .extensions :
446454 file_cls = self .node_classes .file_cls
447455 new_file = file_cls .from_content (filepath , content , self , sync = False , verify_syntax = False )
448456 if new_file is not None :
449457 files_to_resolve .append (new_file )
458+ task .end ()
450459 for file in files_to_resolve :
451460 to_resolve .append (file )
452461 to_resolve .extend (file .get_nodes ())
@@ -474,27 +483,35 @@ def _process_diff_files(self, files_to_sync: Mapping[SyncType, list[Path]], incr
474483 self ._computing = True
475484 try :
476485 logger .info (f"> Computing import resolution edges for { counter [NodeType .IMPORT ]} imports" )
486+ task = self .progress .begin ("Resolving imports" , count = counter [NodeType .IMPORT ])
477487 for node in to_resolve :
478488 if node .node_type == NodeType .IMPORT :
489+ task .update (f"Resolving imports in { node .filepath } " , count = idx )
479490 node ._remove_internal_edges (EdgeType .IMPORT_SYMBOL_RESOLUTION )
480491 node .add_symbol_resolution_edge ()
481492 to_resolve .extend (node .symbol_usages )
493+ task .end ()
482494 if counter [NodeType .EXPORT ] > 0 :
483495 logger .info (f"> Computing export dependencies for { counter [NodeType .EXPORT ]} exports" )
496+ task = self .progress .begin ("Computing export dependencies" , count = counter [NodeType .EXPORT ])
484497 for node in to_resolve :
485498 if node .node_type == NodeType .EXPORT :
499+ task .update (f"Computing export dependencies for { node .filepath } " , count = idx )
486500 node ._remove_internal_edges (EdgeType .EXPORT )
487501 node .compute_export_dependencies ()
488502 to_resolve .extend (node .symbol_usages )
503+ task .end ()
489504 if counter [NodeType .SYMBOL ] > 0 :
490505 from codegen .sdk .core .interfaces .inherits import Inherits
491506
492507 logger .info ("> Computing superclass dependencies" )
508+ task = self .progress .begin ("Computing superclass dependencies" , count = counter [NodeType .SYMBOL ])
493509 for symbol in to_resolve :
494510 if isinstance (symbol , Inherits ):
511+ task .update (f"Computing superclass dependencies for { symbol .filepath } " , count = idx )
495512 symbol ._remove_internal_edges (EdgeType .SUBCLASS )
496513 symbol .compute_superclass_dependencies ()
497-
514+ task . end ()
498515 if not skip_uncache :
499516 uncache_all ()
500517 self ._compute_dependencies (to_resolve , incremental )
@@ -504,17 +521,20 @@ def _process_diff_files(self, files_to_sync: Mapping[SyncType, list[Path]], incr
504521 def _compute_dependencies (self , to_update : list [Importable ], incremental : bool ):
505522 seen = set ()
506523 while to_update :
524+ task = self .progress .begin ("Computing dependencies" , count = len (to_update ))
507525 step = to_update .copy ()
508526 to_update .clear ()
509527 logger .info (f"> Incrementally computing dependencies for { len (step )} nodes" )
510- for current in step :
528+ for idx , current in enumerate (step ):
529+ task .update (f"Computing dependencies for { current .filepath } " , count = idx )
511530 if current not in seen :
512531 seen .add (current )
513532 to_update .extend (current .recompute (incremental ))
514533 if not incremental :
515534 for node in self ._graph .nodes ():
516535 if node not in seen :
517536 to_update .append (node )
537+ task .end ()
518538 seen .clear ()
519539
520540 def build_subgraph (self , nodes : list [NodeId ]) -> PyDiGraph [Importable , Edge ]:
0 commit comments