Skip to main content
POST
/
tools
/
rename_symbol
Rename Symbol
curl --request POST \
  --url https://api.example.com/tools/rename_symbol
{
  "changes": {
    "range": {
      "start": {},
      "end": {}
    },
    "newText": "<string>"
  },
  "totalEdits": 123,
  "filesAffected": 123
}

Overview

Rename a Python symbol (function, class, variable, parameter, etc.) across your entire workspace. This tool finds all references and provides the exact text edits needed to rename safely.

Request

uri
string
required
File URI (e.g., file:///workspace/main.py)
line
number
required
Line number where symbol appears (0-indexed)
character
number
required
Character position (0-indexed)
newName
string
required
New name for the symbol

Response

changes
object
Map of file URIs to arrays of text edits
totalEdits
number
Total number of edits across all files
filesAffected
number
Number of files that will be modified

Example Request

curl -X POST https://api.pylancemcp.dev/v1/tools/call \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "rename_symbol",
    "arguments": {
      "uri": "file:///workspace/app/utils.py",
      "line": 8,
      "character": 4,
      "newName": "compute_total"
    }
  }'

Example Response

{
  "changes": {
    "file:///workspace/app/utils.py": [
      {
        "range": {
          "start": { "line": 8, "character": 4 },
          "end": { "line": 8, "character": 19 }
        },
        "newText": "compute_total"
      }
    ],
    "file:///workspace/app/views.py": [
      {
        "range": {
          "start": { "line": 42, "character": 12 },
          "end": { "line": 42, "character": 27 }
        },
        "newText": "compute_total"
      },
      {
        "range": {
          "start": { "line": 87, "character": 8 },
          "end": { "line": 87, "character": 23 }
        },
        "newText": "compute_total"
      }
    ],
    "file:///workspace/tests/test_utils.py": [
      {
        "range": {
          "start": { "line": 15, "character": 16 },
          "end": { "line": 15, "character": 31 }
        },
        "newText": "compute_total"
      }
    ]
  },
  "totalEdits": 4,
  "filesAffected": 3
}

Use Cases

Rename Function

# Original: calculate_total
def calculate_total(items: List[Item]) -> float:
    return sum(item.price for item in items)

# Rename to: compute_total
# Result: All 47 references updated across 12 files

def compute_total(items: List[Item]) -> float:
    return sum(item.price for item in items)

Rename Class

# Original: UserModel
class UserModel(BaseModel):
    name: str
    email: str

# Rename to: User
# Result: Class definition + all imports/usages updated

class User(BaseModel):
    name: str
    email: str

Rename Variable

# Original: temp_data
def process():
    temp_data = fetch_data()
    validate(temp_data)
    return temp_data

# Rename to: user_data
# Result: All references in scope updated

def process():
    user_data = fetch_data()
    validate(user_data)
    return user_data

Rename Parameter

# Original: x
def calculate(x: int, y: int) -> int:
    return x + y

# Rename to: amount
# Result: Parameter + all references in function updated

def calculate(amount: int, y: int) -> int:
    return amount + y

What Gets Renamed

Definition

The original symbol definition

All References

Every place the symbol is used

Imports

Import statements are updated

String Literals

Not renamed (only code references)

Safety Features

Scope-Aware: Only renames symbols in the same scope
Conflict Detection: Warns if new name conflicts with existing symbols
Atomic Operation: All files updated together or none at all
Preview First: Get all edits before applying

Applying Edits

The rename tool returns edits but doesn’t apply them automatically. You need to apply the changes:
def apply_rename_edits(rename_result):
    """Apply rename edits to files."""
    for file_uri, edits in rename_result.changes.items():
        file_path = file_uri.replace('file://', '')
        
        # Read file
        with open(file_path, 'r') as f:
            lines = f.readlines()
        
        # Apply edits in reverse order (bottom to top)
        # This prevents line number shifts
        for edit in sorted(edits, 
                          key=lambda e: e.range.start.line, 
                          reverse=True):
            start = edit.range.start
            end = edit.range.end
            
            # Get the line
            line = lines[start.line]
            
            # Replace the text
            new_line = (
                line[:start.character] + 
                edit.new_text + 
                line[end.character:]
            )
            lines[start.line] = new_line
        
        # Write file
        with open(file_path, 'w') as f:
            f.writelines(lines)

# Use it
rename = client.rename_symbol(...)
apply_rename_edits(rename)

Validation

Before renaming, the tool validates:
CheckDescription
Symbol existsPosition must point to a valid symbol
Valid nameNew name must be a valid Python identifier
No conflictsNew name doesn’t shadow existing symbols
RenameableSymbol can be renamed (not a keyword)

Error Responses

CodeReasonSolution
INVALID_NAMENew name is not valid PythonUse valid identifier (letters, numbers, underscore)
NAME_CONFLICTNew name already existsChoose a different name
NO_SYMBOL_FOUNDNo symbol at positionPosition cursor on a valid symbol
CANNOT_RENAMESymbol cannot be renamedBuilt-in symbols can’t be renamed
WORKSPACE_NOT_INDEXEDWorkspace still indexingWait for indexing to complete

Rate Limits

TierRequests/HourRequests/Day
Free525
Hobby1001,000
Pro1,00010,000
EnterpriseUnlimitedUnlimited
Rename operations are expensive. Use sparingly and cache results.

Best Practices

Preview First: Always review the changes before applying them
Use Version Control: Commit before renaming so you can revert if needed
Test After: Run tests after renaming to catch any issues
Atomic Apply: Apply all edits at once, not file by file