pub mod ast_utils;
pub mod batch;
pub mod change_signature;
pub mod extract_function;
pub mod inline;
pub mod introduce_variable;
pub mod move_item;
pub mod preview;
pub mod scope_analyzer;
use crate::database::WindjammerDatabase;
use tower_lsp::lsp_types::*;
pub struct RefactoringEngine<'a> {
db: &'a WindjammerDatabase,
}
impl<'a> RefactoringEngine<'a> {
pub fn new(db: &'a WindjammerDatabase) -> Self {
Self { db }
}
#[allow(dead_code)]
pub fn db(&self) -> &WindjammerDatabase {
self.db
}
pub fn code_actions(
&self,
uri: &Url,
range: Range,
_context: &CodeActionContext,
) -> Vec<CodeActionOrCommand> {
let mut actions = Vec::new();
if range.start != range.end {
if let Some(action) = self.extract_function_action(uri, range) {
actions.push(CodeActionOrCommand::CodeAction(action));
}
}
if let Some(action) = self.inline_variable_action(uri, range.start) {
actions.push(CodeActionOrCommand::CodeAction(action));
}
if range.start != range.end {
if let Some(action) = self.introduce_variable_action(uri, range) {
actions.push(CodeActionOrCommand::CodeAction(action));
}
}
actions
}
fn extract_function_action(&self, uri: &Url, range: Range) -> Option<CodeAction> {
Some(CodeAction {
title: "Extract Function".to_string(),
kind: Some(CodeActionKind::REFACTOR_EXTRACT),
diagnostics: None,
edit: None, command: Some(Command {
title: "Extract Function".to_string(),
command: "windjammer.refactor.extractFunction".to_string(),
arguments: Some(vec![
serde_json::to_value(uri).ok()?,
serde_json::to_value(range).ok()?,
]),
}),
is_preferred: Some(true),
disabled: None,
data: None,
})
}
fn inline_variable_action(&self, _uri: &Url, _position: Position) -> Option<CodeAction> {
None
}
fn introduce_variable_action(&self, _uri: &Url, _range: Range) -> Option<CodeAction> {
None
}
#[allow(dead_code)]
pub fn execute_extract_function(
&self,
uri: &Url,
range: Range,
function_name: &str,
source: &str,
) -> Result<WorkspaceEdit, String> {
let extractor = extract_function::ExtractFunction::new(self.db, uri.clone(), range);
extractor.execute(function_name, source)
}
#[allow(dead_code)]
pub fn execute_inline_variable(
&self,
uri: &Url,
position: Position,
source: &str,
) -> Result<WorkspaceEdit, String> {
let inliner = inline::InlineRefactoring::new(self.db, uri.clone(), position);
inliner.execute(source)
}
#[allow(dead_code)]
pub fn execute_introduce_variable(
&self,
uri: &Url,
range: Range,
variable_name: &str,
source: &str,
) -> Result<WorkspaceEdit, String> {
let introducer = introduce_variable::IntroduceVariable::new(self.db, uri.clone(), range);
introducer.execute(variable_name, source)
}
#[allow(dead_code)]
pub fn execute_change_signature(
&self,
uri: &Url,
position: Position,
changes: &[change_signature::ParameterChange],
source: &str,
) -> Result<WorkspaceEdit, String> {
let changer = change_signature::ChangeSignature::new(self.db, uri.clone(), position);
changer.execute(changes, source)
}
#[allow(dead_code)]
pub fn execute_move_item(
&self,
source_uri: &Url,
target_uri: &Url,
position: Position,
source_content: &str,
target_content: &str,
) -> Result<WorkspaceEdit, String> {
let mover =
move_item::MoveItem::new(self.db, source_uri.clone(), target_uri.clone(), position);
mover.execute(source_content, target_content)
}
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct RefactoringResult {
pub edit: WorkspaceEdit,
pub preview: String,
pub message: String,
}
#[cfg(test)]
mod tests {
#[test]
fn test_refactoring_engine_creation() {
}
}