Skip to content

Commit 14c9a22

Browse files
authoredMar 20, 2025··
Revert "[CG-7930] new api for removing unused symbols" (#929)
Reverts #855
1 parent c74b337 commit 14c9a22

17 files changed

+104
-2857
lines changed
 

‎src/codegen/sdk/codebase/transaction_manager.py

-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import math
21
import time
32
from collections.abc import Callable
43
from pathlib import Path
@@ -290,22 +289,6 @@ def get_transactions_at_range(self, file_path: Path, start_byte: int, end_byte:
290289

291290
return matching_transactions
292291

293-
def get_transaction_containing_range(self, file_path: Path, start_byte: int, end_byte: int, transaction_order: TransactionPriority | None = None) -> Transaction | None:
294-
"""Returns the nearest transaction that includes the range specified given the filtering criteria."""
295-
if file_path not in self.queued_transactions:
296-
return None
297-
298-
smallest_difference = math.inf
299-
best_fit_transaction = None
300-
for t in self.queued_transactions[file_path]:
301-
if t.start_byte <= start_byte and t.end_byte >= end_byte:
302-
if transaction_order is None or t.transaction_order == transaction_order:
303-
smallest_difference = min(smallest_difference, abs(t.start_byte - start_byte) + abs(t.end_byte - end_byte))
304-
if smallest_difference == 0:
305-
return t
306-
best_fit_transaction = t
307-
return best_fit_transaction
308-
309292
def _get_conflicts(self, transaction: Transaction) -> list[Transaction]:
310293
"""Returns all transactions that overlap with the given transaction"""
311294
overlapping_transactions = []

‎src/codegen/sdk/core/file.py

-7
Original file line numberDiff line numberDiff line change
@@ -943,13 +943,6 @@ def remove_unused_exports(self) -> None:
943943
None
944944
"""
945945

946-
def remove_unused_imports(self) -> None:
947-
# Process each import statement
948-
for import_stmt in self.imports:
949-
# Don't remove imports we can't be sure about
950-
if import_stmt.usage_is_ascertainable():
951-
import_stmt.remove_if_unused()
952-
953946
####################################################################################################################
954947
# MANIPULATIONS
955948
####################################################################################################################

‎src/codegen/sdk/core/import_resolution.py

+6-35
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from typing import TYPE_CHECKING, ClassVar, Generic, Literal, Self, TypeVar, override
66

77
from codegen.sdk.codebase.resolution_stack import ResolutionStack
8+
from codegen.sdk.codebase.transactions import TransactionPriority
89
from codegen.sdk.core.autocommit import commiter, reader, remover, writer
910
from codegen.sdk.core.dataclasses.usage import UsageKind
1011
from codegen.sdk.core.expressions.name import Name
@@ -220,17 +221,6 @@ def is_symbol_import(self) -> bool:
220221
"""
221222
return not self.is_module_import()
222223

223-
@reader
224-
def usage_is_ascertainable(self) -> bool:
225-
"""Returns True if we can determine for sure whether the import is unused or not.
226-
227-
Returns:
228-
bool: True if the usage can be ascertained for the import, False otherwise.
229-
"""
230-
if self.is_wildcard_import() or self.is_sideffect_import():
231-
return False
232-
return True
233-
234224
@reader
235225
def is_wildcard_import(self) -> bool:
236226
"""Returns True if the import symbol is a wildcard import.
@@ -244,16 +234,6 @@ def is_wildcard_import(self) -> bool:
244234
"""
245235
return self.import_type == ImportType.WILDCARD
246236

247-
@reader
248-
def is_sideffect_import(self) -> bool:
249-
# Maybe better name for this
250-
"""Determines if this is a sideffect.
251-
252-
Returns:
253-
bool: True if this is a sideffect import, False otherwise
254-
"""
255-
return self.import_type == ImportType.SIDE_EFFECT
256-
257237
@property
258238
@abstractmethod
259239
def namespace(self) -> str | None:
@@ -681,21 +661,12 @@ def __eq__(self, other: object):
681661

682662
@noapidoc
683663
@reader
684-
def remove_if_unused(self, force: bool = False) -> bool:
685-
"""Removes import if it is not being used. Considers current transaction removals.
686-
687-
Args:
688-
force (bool, optional): If true removes the import even if we cannot ascertain the usage for sure. Defaults to False.
689-
690-
Returns:
691-
bool: True if removed, False if not
692-
"""
693-
if all(usage.match.get_transaction_if_pending_removal() for usage in self.usages):
694-
if not force and not self.usage_is_ascertainable():
695-
return False
664+
def remove_if_unused(self) -> None:
665+
if all(
666+
self.transaction_manager.get_transactions_at_range(self.filepath, start_byte=usage.match.start_byte, end_byte=usage.match.end_byte, transaction_order=TransactionPriority.Remove)
667+
for usage in self.usages
668+
):
696669
self.remove()
697-
return True
698-
return False
699670

700671
@noapidoc
701672
@reader

‎src/codegen/sdk/core/interfaces/editable.py

+1-10
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from rich.pretty import Pretty
1111

1212
from codegen.sdk.codebase.span import Span
13-
from codegen.sdk.codebase.transactions import EditTransaction, InsertTransaction, RemoveTransaction, Transaction, TransactionPriority
13+
from codegen.sdk.codebase.transactions import EditTransaction, InsertTransaction, RemoveTransaction, TransactionPriority
1414
from codegen.sdk.core.autocommit import commiter, reader, remover, repr_func, writer
1515
from codegen.sdk.core.placeholder.placeholder import Placeholder
1616
from codegen.sdk.extensions.utils import get_all_identifiers
@@ -1156,15 +1156,6 @@ def parent_class(self) -> Class | None:
11561156

11571157
return self.parent_of_type(Class)
11581158

1159-
@noapidoc
1160-
def get_transaction_if_pending_removal(self) -> Transaction | None:
1161-
"""Checks if this editable is being removed by some transaction and if so returns it.
1162-
1163-
Returns:
1164-
Transaction|None: The transaction removing the editable
1165-
"""
1166-
return self.transaction_manager.get_transaction_containing_range(self.file.path, self.start_byte, self.end_byte, TransactionPriority.Remove)
1167-
11681159
def _get_ast_children(self) -> list[tuple[str | None, AST]]:
11691160
children = []
11701161
names = {}

‎src/codegen/sdk/core/symbol.py

+1-33
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
from rich.markup import escape
77

8-
from codegen.sdk.codebase.transactions import TransactionPriority
98
from codegen.sdk.core.autocommit import commiter, reader, writer
109
from codegen.sdk.core.dataclasses.usage import UsageKind, UsageType
1110
from codegen.sdk.core.detached_symbols.argument import Argument
@@ -267,38 +266,11 @@ def insert_before(self, new_src: str, fix_indentation: bool = False, newline: bo
267266
return first_node.insert_before(new_src, fix_indentation, newline, priority, dedupe)
268267
return super().insert_before(new_src, fix_indentation, newline, priority, dedupe)
269268

270-
def _post_move_import_cleanup(self, encountered_symbols, strategy):
271-
# =====[ Remove any imports that are no longer used ]=====
272-
from codegen.sdk.core.import_resolution import Import
273-
274-
for dep in self.dependencies:
275-
if strategy != "duplicate_dependencies":
276-
other_usages = [usage.usage_symbol for usage in dep.usages if usage.usage_symbol not in encountered_symbols]
277-
else:
278-
other_usages = [usage.usage_symbol for usage in dep.usages]
279-
if isinstance(dep, Import):
280-
dep.remove_if_unused()
281-
282-
elif isinstance(dep, Symbol):
283-
usages_in_file = [symb for symb in other_usages if symb.file == self.file and not symb.get_transaction_if_pending_removal()]
284-
if dep.get_transaction_if_pending_removal():
285-
if not usages_in_file and strategy != "add_back_edge":
286-
# We are going to assume there is only one such import
287-
if imp_list := [import_str for import_str in self.file._pending_imports if dep.name and dep.name in import_str]:
288-
if insert_import_list := [
289-
transaction
290-
for transaction in self.transaction_manager.queued_transactions[self.file.path]
291-
if imp_list[0] and transaction.new_content and imp_list[0] in transaction.new_content and transaction.transaction_order == TransactionPriority.Insert
292-
]:
293-
self.transaction_manager.queued_transactions[self.file.path].remove(insert_import_list[0])
294-
self.file._pending_imports.remove(imp_list[0])
295-
296269
def move_to_file(
297270
self,
298271
file: SourceFile,
299272
include_dependencies: bool = True,
300273
strategy: Literal["add_back_edge", "update_all_imports", "duplicate_dependencies"] = "update_all_imports",
301-
cleanup_unused_imports: bool = True,
302274
) -> None:
303275
"""Moves the given symbol to a new file and updates its imports and references.
304276
@@ -318,7 +290,7 @@ def move_to_file(
318290
AssertionError: If an invalid strategy is provided.
319291
"""
320292
encountered_symbols = {self}
321-
self._move_to_file(file, encountered_symbols, include_dependencies, strategy, cleanup_unused_imports)
293+
self._move_to_file(file, encountered_symbols, include_dependencies, strategy)
322294

323295
@noapidoc
324296
def _move_to_file(
@@ -327,7 +299,6 @@ def _move_to_file(
327299
encountered_symbols: set[Symbol | Import],
328300
include_dependencies: bool = True,
329301
strategy: Literal["add_back_edge", "update_all_imports", "duplicate_dependencies"] = "update_all_imports",
330-
cleanup_unused_imports: bool = True,
331302
) -> tuple[NodeId, NodeId]:
332303
"""Helper recursive function for `move_to_file`"""
333304
from codegen.sdk.core.import_resolution import Import
@@ -420,9 +391,6 @@ def _move_to_file(
420391
# Delete the original symbol
421392
self.remove()
422393

423-
if cleanup_unused_imports:
424-
self._post_move_import_cleanup(encountered_symbols, strategy)
425-
426394
@property
427395
@reader
428396
@noapidoc

‎src/codegen/sdk/typescript/symbol.py

+10-25
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,12 @@ def _move_to_file(
261261
encountered_symbols: set[Symbol | Import],
262262
include_dependencies: bool = True,
263263
strategy: Literal["add_back_edge", "update_all_imports", "duplicate_dependencies"] = "update_all_imports",
264-
cleanup_unused_imports: bool = True,
265264
) -> tuple[NodeId, NodeId]:
266265
# TODO: Prevent creation of import loops (!) - raise a ValueError and make the agent fix it
267266
# =====[ Arg checking ]=====
268267
if file == self.file:
269268
return file.file_node_id, self.node_id
270269

271-
if imp := file.get_import(self.name):
272-
encountered_symbols.add(imp)
273-
imp.remove()
274-
275270
# =====[ Move over dependencies recursively ]=====
276271
if include_dependencies:
277272
try:
@@ -324,12 +319,7 @@ def _move_to_file(
324319

325320
# =====[ Make a new symbol in the new file ]=====
326321
# This will update all edges etc.
327-
should_export = False
328-
329-
if self.is_exported or [usage for usage in self.usages if usage.usage_symbol not in encountered_symbols and not usage.usage_symbol.get_transaction_if_pending_removal()]:
330-
should_export = True
331-
332-
file.add_symbol(self, should_export=should_export)
322+
file.add_symbol(self)
333323
import_line = self.get_import_string(module=file.import_module_name)
334324

335325
# =====[ Checks if symbol is used in original file ]=====
@@ -339,18 +329,16 @@ def _move_to_file(
339329
# ======[ Strategy: Duplicate Dependencies ]=====
340330
if strategy == "duplicate_dependencies":
341331
# If not used in the original file. or if not imported from elsewhere, we can just remove the original symbol
342-
is_used_in_file = any(usage.file == self.file and usage.node_type == NodeType.SYMBOL for usage in self.symbol_usages)
343332
if not is_used_in_file and not any(usage.kind is UsageKind.IMPORTED and usage.usage_symbol not in encountered_symbols for usage in self.usages):
344333
self.remove()
345334

346335
# ======[ Strategy: Add Back Edge ]=====
347336
# Here, we will add a "back edge" to the old file importing the self
348337
elif strategy == "add_back_edge":
349338
if is_used_in_file:
350-
back_edge_line = import_line
339+
self.file.add_import(import_line)
351340
if self.is_exported:
352-
back_edge_line = back_edge_line.replace("import", "export")
353-
self.file.add_import(back_edge_line)
341+
self.file.add_import(f"export {{ {self.name} }}")
354342
elif self.is_exported:
355343
module_name = file.name
356344
self.file.add_import(f"export {{ {self.name} }} from '{module_name}'")
@@ -361,26 +349,23 @@ def _move_to_file(
361349
# Update the imports in all the files which use this symbol to get it from the new file now
362350
elif strategy == "update_all_imports":
363351
for usage in self.usages:
364-
if isinstance(usage.usage_symbol, TSImport) and usage.usage_symbol.file != file:
352+
if isinstance(usage.usage_symbol, TSImport):
365353
# Add updated import
366-
usage.usage_symbol.file.add_import(import_line)
367-
usage.usage_symbol.remove()
354+
if usage.usage_symbol.resolved_symbol is not None and usage.usage_symbol.resolved_symbol.node_type == NodeType.SYMBOL and usage.usage_symbol.resolved_symbol == self:
355+
usage.usage_symbol.file.add_import(import_line)
356+
usage.usage_symbol.remove()
368357
elif usage.usage_type == UsageType.CHAINED:
369358
# Update all previous usages of import * to the new import name
370359
if usage.match and "." + self.name in usage.match:
371-
if isinstance(usage.match, FunctionCall) and self.name in usage.match.get_name():
360+
if isinstance(usage.match, FunctionCall):
372361
usage.match.get_name().edit(self.name)
373362
if isinstance(usage.match, ChainedAttribute):
374363
usage.match.edit(self.name)
375-
usage.usage_symbol.file.add_import(imp=import_line)
376-
377-
# Add the import to the original file
364+
usage.usage_symbol.file.add_import(import_line)
378365
if is_used_in_file:
379-
self.file.add_import(imp=import_line)
366+
self.file.add_import(import_line)
380367
# Delete the original symbol
381368
self.remove()
382-
if cleanup_unused_imports:
383-
self._post_move_import_cleanup(encountered_symbols, strategy)
384369

385370
def _convert_proptype_to_typescript(self, prop_type: Editable, param: Parameter | None, level: int) -> str:
386371
"""Converts a PropType definition to its TypeScript equivalent."""

0 commit comments

Comments
 (0)
Please sign in to comment.