use crate::types::{CodeAction, CodeActionEdit, CodeActionKind};
use perl_lsp_rename::TextEdit;
use perl_parser_core::ast::{Node, NodeKind, SourceLocation};
use super::helpers::Helpers;
pub fn create_extract_variable_action(
node: &Node,
source: &str,
helpers: &Helpers<'_>,
) -> CodeAction {
let expr_text = &source[node.location.start..node.location.end];
let var_name = suggest_variable_name(node);
let stmt_start = helpers.find_statement_start(node.location.start);
let indent = helpers.get_indent_at(stmt_start);
CodeAction {
title: format!("Extract '{}' to variable", helpers.truncate_expr(expr_text, 30)),
kind: CodeActionKind::RefactorExtract,
diagnostics: Vec::new(),
edit: CodeActionEdit {
changes: vec![
TextEdit {
location: SourceLocation { start: stmt_start, end: stmt_start },
new_text: format!("{}my ${} = {};\n", indent, var_name, expr_text),
},
TextEdit { location: node.location, new_text: format!("${}", var_name) },
],
},
is_preferred: false,
}
}
pub fn suggest_variable_name(node: &Node) -> String {
match &node.kind {
NodeKind::FunctionCall { name, .. } => {
let func_name = name.as_str();
match func_name {
"length" | "size" => "len",
"split" => "parts",
"join" => "joined",
"sort" => "sorted",
"reverse" => "reversed",
"grep" | "filter" => "filtered",
"map" => "mapped",
_ => "result",
}
}
NodeKind::MethodCall { method, .. } => {
let method_name = method.as_str();
match method_name {
"new" => "instance",
"clone" | "copy" => "copy",
"get" | "fetch" => "value",
"find" | "search" | "lookup" => "found",
"count" | "size" | "length" => "count",
"name" | "get_name" => "name",
"type" | "get_type" => "type_name",
"to_string" | "stringify" | "as_string" => "str",
"is_valid" | "validate" | "check" => "is_valid",
_ => "result",
}
}
NodeKind::Binary { op, .. } => match op.as_str() {
"+" | "-" | "*" | "/" | "%" => "result",
"." | "x" => "str",
"&&" | "||" | "and" | "or" => "condition",
"==" | "!=" | "<" | ">" | "<=" | ">=" => "is_valid",
"{}" => "val",
"[]" => "elem",
_ => "value",
},
_ => "extracted",
}
.to_string()
}