lsp-mcp 0.1.0

MCP server providing unified access to Language Server Protocol features
Documentation
pub mod workspace;
pub mod hover;
pub mod definition;
pub mod references;
pub mod completion;
pub mod diagnostics;
pub mod symbols;
pub mod rename;

use crate::error::Result;
use crate::lsp::LanguageServerManager;
use lsp_types::Position;
use std::path::Path;
use std::sync::Arc;
use url::Url;

/// Helper to convert file path to URL
pub fn file_to_url(path: &Path) -> Result<Url> {
    Url::from_file_path(path).map_err(|_| {
        crate::error::LspMcpError::FileNotFound(path.to_path_buf())
    })
}

/// Helper to convert URL to file path string
pub fn url_to_path_string(url: &Url) -> String {
    url.to_file_path()
        .map(|p| p.to_string_lossy().to_string())
        .unwrap_or_else(|_| url.to_string())
}

/// Helper to read file contents
pub fn read_file(path: &Path) -> Result<String> {
    std::fs::read_to_string(path).map_err(|e| crate::error::LspMcpError::Io(e))
}

/// Helper to create LSP position
pub fn make_position(line: u32, character: u32) -> Position {
    Position { line, character }
}

/// Helper to ensure document is open before operation
pub fn ensure_document_open(
    manager: &LanguageServerManager,
    file_path: &Path,
) -> Result<(Arc<crate::lsp::LspClient>, Url)> {
    let client = manager.get_client_for_file(file_path)?;
    let uri = file_to_url(file_path)?;

    // Read file content
    let content = read_file(file_path)?;

    // Detect language ID
    let language_id = client.language().language_id();

    // Open the document (idempotent - server handles duplicates)
    client.open_document(&uri, &content, language_id)?;

    Ok((client, uri))
}