Search documentation of Ragex

# Ragex.Editor.Refactor (Ragex v0.4.0)

View Source

Semantic refactoring operations that leverage the knowledge graph.

Provides AST-aware refactoring operations like rename_function and rename_module that automatically update all affected files using the graph to find call sites and dependencies.

## Summary

### Types

refactor_result()

### Functions

change_signature(module_name, function_name, old_arity, signature_changes, opts \\ [])

Changes a function signature by adding, removing, reordering, or renaming parameters.

convert_visibility(module_name, function_name, arity, visibility, opts \\ [])

Converts function visibility between public (def) and private (defp).

extract_function(module_name, source_function, source_arity, new_function_name, line_range, opts \\ [])

Extracts a range of lines from a function into a new function.

extract_module(source_module, new_module, functions, opts \\ [])

Extracts multiple functions from a module into a new module.

inline_function(module_name, function_name, arity, opts \\ [])

Inlines a function by replacing all its calls with the function body.

modify_attributes(module_name, changes, opts \\ [])

Adds, removes, or updates module attributes.

move_function(source_module, target_module, function_name, arity, opts \\ [])

Moves a function from one module to another.

rename_function(module_name, old_name, new_name, arity, opts \\ [])

Renames a function across the entire codebase.

rename_module(old_name, new_name, opts \\ [])

Renames a module across the entire codebase.

rename_parameter(module_name, function_name, arity, old_param_name, new_param_name, opts \\ [])

Renames a function parameter and all its references within the function body.

## Types

# refactor_result()

    @type refactor_result() :: %{
      status: :success | :failure,
      files_modified: non_neg_integer(),
      transaction_result: Ragex.Editor.Transaction.transaction_result()
    }

## Functions

# change_signature(module_name, function_name, old_arity, signature_changes, opts \\ [])

    @spec change_signature(
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      map(),
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Changes a function signature by adding, removing, reordering, or renaming parameters.

## Parameters

- `module_name`: Module containing the function
- `function_name`: Function to modify
- `old_arity`: Current function arity
- `signature_changes`: Map describing the changes (see details below)
- `opts`: Options
  - `:scope` - :module (same file only) or :project (all files, default: :project)
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Signature Changes Format

The `signature_changes` map can contain:

- `:add_params` - List of params to add with defaults
- `:remove_params` - List of param positions to remove (0-indexed)
- `:reorder_params` - New param order
- `:rename_params` - List of renames

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    # Add an optional parameter
    changes = %{add_params: [%{name: :opts, position: 2, default: []}]}
    Refactor.change_signature(:MyModule, :process, 2, changes)

    # Remove second parameter and rename first
    changes = %{
      remove_params: [1],
      rename_params: [{:old_name, :new_name}]
    }
    Refactor.change_signature(:MyModule, :transform, 3, changes)

# convert_visibility(module_name, function_name, arity, visibility, opts \\ [])

    @spec convert_visibility(
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      :public | :private,
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Converts function visibility between public (def) and private (defp).

## Parameters

- `module_name`: Module containing the function
- `function_name`: Function to modify
- `arity`: Function arity
- `visibility`: :public or :private
- `opts`: Options
  - `:add_doc` - Add documentation when making public (default: false)
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure

## Examples

    # Make private function public
    Refactor.convert_visibility(:MyModule, :helper, 1, :public)

    # Make public function private
    Refactor.convert_visibility(:MyModule, :exposed, 2, :private)

# extract_function(module_name, source_function, source_arity, new_function_name, line_range, opts \\ [])

    @spec extract_function(
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      atom() | String.t(),
      {pos_integer(), pos_integer()},
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Extracts a range of lines from a function into a new function.

## Parameters

- `module_name`: Module containing the function
- `source_function`: Function to extract from
- `source_arity`: Arity of source function
- `new_function_name`: Name for the extracted function
- `line_range`: {start_line, end_line} tuple (1-indexed)
- `opts`: Options

  - `:placement` - :after_source | :before_source | :end_of_module (default: :after_source)

  - `:visibility` - :public | :private (default: :private)

  - `:add_doc` - boolean (default: false)
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    # Extract lines 10-15 from MyModule.process/2 into helper/0
    Refactor.extract_function(:MyModule, :process, 2, :helper, {10, 15})

    # Extract as public function at end of module
    Refactor.extract_function(
      :MyModule, :process, 2, :extracted_logic, {10, 15},
      visibility: :public, placement: :end_of_module
    )

# extract_module(source_module, new_module, functions, opts \\ [])

    @spec extract_module(
      atom() | String.t(),
      atom() | String.t(),
      [{atom(), non_neg_integer()}],
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Extracts multiple functions from a module into a new module.

## Parameters

- `source_module`: Source module name
- `new_module`: New module name
- `functions`: List of {function_name, arity} tuples
- `opts`: Options
  - `:file_path` - Explicit path for new module (optional)
  - `:add_moduledoc` - boolean (default: true)
  - `:update_aliases` - boolean (default: true)
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    # Extract helpers into new module
    functions = [{:helper1, 1}, {:helper2, 2}]
    Refactor.extract_module(:MyModule, :MyModule.Helpers, functions)

# inline_function(module_name, function_name, arity, opts \\ [])

    @spec inline_function(
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Inlines a function by replacing all its calls with the function body.

## Parameters

- `module_name`: Module containing the function
- `function_name`: Function to inline
- `arity`: Function arity
- `opts`: Options
  - `:scope` - :module (same file only) or :project (all files, default: :project)
  - `:remove_definition` - Remove function definition after inlining (default: true)
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    # Inline MyModule.helper/1 across entire project
    Refactor.inline_function(:MyModule, :helper, 1)

    # Inline only within the same module, keep definition
    Refactor.inline_function(
      :MyModule, :helper, 1,
      scope: :module, remove_definition: false
    )

# modify_attributes(module_name, changes, opts \\ [])

    @spec modify_attributes(atom() | String.t(), map(), keyword()) ::
      {:ok, refactor_result()} | {:error, term()}

Adds, removes, or updates module attributes.

## Parameters

- `module_name`: Module to modify
- `changes`: Map with :add, :remove, and/or :update keys
- `opts`: Options
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure

## Examples

    # Add and update attributes
    changes = %{
      add: [{:vsn, "1.0.0"}],
      remove: [:deprecated],
      update: [{:moduledoc, "Updated docs"}]
    }
    Refactor.modify_attributes(:MyModule, changes)

# move_function(source_module, target_module, function_name, arity, opts \\ [])

    @spec move_function(
      atom() | String.t(),
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Moves a function from one module to another.

## Parameters

- `source_module`: Source module name
- `target_module`: Target module name
- `function_name`: Function to move
- `arity`: Function arity
- `opts`: Options

  - `:placement` - :start | :end (default: :end)

  - `:update_references` - boolean (default: true)
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    # Move function to existing module
    Refactor.move_function(:MyModule, :MyModule.Utils, :helper, 1)

# rename_function(module_name, old_name, new_name, arity, opts \\ [])

    @spec rename_function(
      atom() | String.t(),
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Renames a function across the entire codebase.

Uses the knowledge graph to find all call sites and updates them atomically.

## Parameters

- `module_name`: Module containing the function (atom or string)
- `old_name`: Current function name (atom or string)
- `new_name`: New function name (atom or string)
- `arity`: Function arity
- `opts`: Options
  - `:validate` - Validate before/after (default: true)
  - `:format` - Format files after editing (default: true)
  - `:scope` - :module (same module only) or :project (all files, default)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    # Rename MyModule.old_func/2 to MyModule.new_func/2 across project
    Refactor.rename_function(:MyModule, :old_func, :new_func, 2)

    # Rename only within the same module
    Refactor.rename_function(:MyModule, :old_func, :new_func, 2, scope: :module)

# rename_module(old_name, new_name, opts \\ [])

    @spec rename_module(atom() | String.t(), atom() | String.t(), keyword()) ::
      {:ok, refactor_result()} | {:error, term()}

Renames a module across the entire codebase.

Updates the module definition and all references (imports, aliases, calls).

## Parameters

- `old_name`: Current module name (atom or string)
- `new_name`: New module name (atom or string)
- `opts`: Options (same as rename_function)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure (with rollback)

## Examples

    Refactor.rename_module(:OldModule, :NewModule)

# rename_parameter(module_name, function_name, arity, old_param_name, new_param_name, opts \\ [])

    @spec rename_parameter(
      atom() | String.t(),
      atom() | String.t(),
      non_neg_integer(),
      atom() | String.t(),
      atom() | String.t(),
      keyword()
    ) :: {:ok, refactor_result()} | {:error, term()}

Renames a function parameter and all its references within the function body.

## Parameters

- `module_name`: Module containing the function
- `function_name`: Function to modify
- `arity`: Function arity
- `old_param_name`: Current parameter name
- `new_param_name`: New parameter name
- `opts`: Options
  - `:validate` - boolean (default: true)
  - `:format` - boolean (default: true)

## Returns

- `{:ok, result}` on success
- `{:error, reason}` on failure

## Examples

    # Rename parameter x to input
    Refactor.rename_parameter(:MyModule, :process, 1, :x, :input)