Codegen’s GraphSitter library provides powerful APIs for performing complex renaming operations throughout your codebase. This guide will walk you through the process of renaming various code elements and updating their references.

Common use cases include:

  • Renaming functions, classes, or variables across multiple files
  • Updating import statements after renaming modules
  • Refactoring method names in a class hierarchy

Overview

To perform complex renaming, you’ll typically need to rename the symbol and then update all its references. Here’s a basic example:

old_function = codebase.get_file("path/to/file.py").get_function("old_function_name")

# Rename the function and update all references
old_function.rename("new_function_name")

This operation will rename the function and update all call sites and imports referencing this function.

Renaming Functions and Updating Call Sites

When renaming a function, GraphSitter automatically updates all call sites:

function = codebase.get_file("path/to/file.py").get_function("old_function_name")
function.rename("new_function_name")

# All call sites are automatically updated
for call_site in function.call_sites:
    # The call_site will now use the new name
    print(call_site.source)  # This will show "new_name(...)"

Renaming Classes and Updating References

Renaming a class will update all references, including inheritance and instantiations:

old_class = codebase.get_class("OldClassName")
old_class.rename("NewClassName")

# All references are automatically updated
for usage in old_class.symbol_usages:
    # This could be a subclass, an instantiation, or any other reference
    print(usage.source)  # This will show "NewClassName" instead of "OldClassName"

Renaming Across Multiple Files

GraphSitter handles renaming across multiple files seamlessly:

for function in codebase.functions:
    # Filter for functions starting with deprecated_
    if function.name.startswith("deprecated_"):
        # Remove the deprecated_ prefix
        new_name = function.name.replace("deprecated_", "")
        function.rename(new_name)

This will rename all functions starting with “deprecated_” across all files in the codebase.

Renaming Methods in a Class Hierarchy

When renaming methods in a class hierarchy, you need to update the method in the base class and all overrides:

base_class = codebase.get_class("BaseClass")
old_method = base_class.get_method("old_method")

# Rename in base class
old_method.rename("new_method")

# Update in all subclasses
for subclass in base_class.subclasses:
    if old_method := subclass.get_method("old_method"):
        old_method.rename("new_method")

Best Practices

  1. Commit After Major Changes: If you’re making multiple significant changes that may have overlapping edits, use codebase.commit() between them to ensure the codebase graph is up-to-date.

  2. Re-fetch References: After a commit, re-fetch any file or symbol references you’re working with, as they may have become stale.

  3. Handle Errors: Be prepared to handle cases where symbols might not exist, or where renaming might fail due to naming conflicts.

By following these guidelines, you can effectively perform complex renaming operations throughout your codebase while maintaining its integrity and functionality.

Was this page helpful?