Let the code action actually do edits
This commit is contained in:
@@ -55,6 +55,16 @@ pub enum CodeActionType {
|
||||
|
||||
/// List available code actions for the text range
|
||||
ListAvailable,
|
||||
|
||||
/// Execute a specific code action that matches the provided regex pattern
|
||||
ExecuteAction {
|
||||
/// Regex pattern to match against code action titles
|
||||
/// Must match exactly one code action
|
||||
pattern: String,
|
||||
|
||||
/// Optional arguments to pass to the code action, as arbitrary JSON
|
||||
arguments: Option<serde_json::Value>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct CodeActionTool;
|
||||
@@ -91,6 +101,9 @@ impl Tool for CodeActionTool {
|
||||
CodeActionType::ListAvailable => {
|
||||
format!("List available code actions for '{}'", input.text_range)
|
||||
}
|
||||
CodeActionType::ExecuteAction { pattern, .. } => {
|
||||
format!("Execute code action matching '{}' for '{}'", pattern, input.text_range)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => "Perform code action".to_string(),
|
||||
@@ -226,6 +239,76 @@ impl Tool for CodeActionTool {
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
},
|
||||
CodeActionType::ExecuteAction { pattern, arguments } => {
|
||||
// Get code actions for the range
|
||||
let actions = project
|
||||
.update(cx, |project, cx| {
|
||||
project.code_actions(&buffer, range.clone(), None, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
if actions.is_empty() {
|
||||
return Err(anyhow!("No code actions available for this range"));
|
||||
}
|
||||
|
||||
// Compile the regex pattern
|
||||
let regex = match regex::Regex::new(&pattern) {
|
||||
Ok(regex) => regex,
|
||||
Err(err) => return Err(anyhow!("Invalid regex pattern: {}", err)),
|
||||
};
|
||||
|
||||
// Find all matching actions
|
||||
let matching_actions: Vec<_> = actions
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, action)| {
|
||||
let title = action.lsp_action.title();
|
||||
regex.is_match(title)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Ensure exactly one action matches
|
||||
if matching_actions.is_empty() {
|
||||
return Err(anyhow!("No code actions match the pattern: {}", pattern));
|
||||
} else if matching_actions.len() > 1 {
|
||||
let titles: Vec<_> = matching_actions
|
||||
.iter()
|
||||
.map(|(_, action)| action.lsp_action.title().to_string())
|
||||
.collect();
|
||||
|
||||
return Err(anyhow!(
|
||||
"Pattern '{}' matches multiple code actions: {}",
|
||||
pattern,
|
||||
titles.join(", ")
|
||||
));
|
||||
}
|
||||
|
||||
// Get the single matching action
|
||||
let (_, action) = matching_actions[0];
|
||||
let action = action.clone();
|
||||
|
||||
// If arguments are provided and this is a command action,
|
||||
// we could theoretically modify the command's arguments here,
|
||||
// but for now we'll just log that arguments were provided but ignored
|
||||
if arguments.is_some() {
|
||||
eprintln!("Note: arguments provided to ExecuteAction are currently ignored");
|
||||
}
|
||||
|
||||
let title = action.lsp_action.title().to_string();
|
||||
|
||||
// Apply the selected code action
|
||||
let _transaction = project
|
||||
.update(cx, |project, cx| {
|
||||
project.apply_code_action(buffer.clone(), action, true, cx)
|
||||
})?
|
||||
.await?;
|
||||
|
||||
action_log.update(cx, |log, cx| {
|
||||
log.buffer_edited(buffer.clone(), Vec::new(), cx)
|
||||
})?;
|
||||
|
||||
Ok(format!("Executed code action: {}", title))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,11 +4,24 @@ This tool performs code actions on text ranges in the project, such as:
|
||||
|
||||
- **Rename**: Renames a text range (typically a symbol) across the codebase
|
||||
- **ListAvailable**: Lists all available code actions for a specific text range
|
||||
- **ExecuteAction**: Executes a specific code action matching a regex pattern
|
||||
|
||||
To use this tool, you need to:
|
||||
1. Specify the path to the file containing the text range you want to run an action on
|
||||
2. Choose the code action type (Rename or ListAvailable)
|
||||
3. For both action types: provide context around the text range to identify it uniquely
|
||||
2. Choose the code action type (Rename, ListAvailable, or ExecuteAction)
|
||||
3. For all action types: provide context around the text range to identify it uniquely
|
||||
4. For Rename actions: provide the new name
|
||||
5. For ExecuteAction: provide a regex pattern that uniquely identifies the action to execute, and optional arguments
|
||||
|
||||
The tool will apply the requested code action to all relevant occurrences in the project, or list all available actions for the specified text range.
|
||||
Typical workflow:
|
||||
1. Use the ListAvailable action to discover available code actions for a text range
|
||||
2. Choose one of the listed actions by creating a regex pattern that uniquely matches it
|
||||
3. Execute that specific action using ExecuteAction with the pattern
|
||||
|
||||
The regex pattern must match exactly one code action title. If it matches zero or multiple actions, the tool will return an error with appropriate guidance.
|
||||
|
||||
Examples:
|
||||
- Use `^Extract function$` to match an action titled exactly "Extract function"
|
||||
- Use `Rename to '.*'` to match any action that starts with "Rename to '"
|
||||
|
||||
You can also use the tool to directly guess code actions without first listing them, by providing a regex pattern that might match common code actions like "Extract function", "Extract variable", etc.
|
||||
|
||||
Reference in New Issue
Block a user