omena-lsp-server 0.3.0

Rust LSP server boundary scaffold for Omena CSS Modules
Documentation
use super::*;

const WORKSPACE_ROOT: &str = "file:///workspace-a";
const STYLE_URI: &str = "file:///workspace-a/src/App.module.scss";

#[test]
fn sdk_workflows_read_the_open_document_snapshot() -> Result<(), String> {
    let mut state = LspShellState::default();
    open_style(&mut state, 1, ".card { color: red; }");

    let snapshot = request(
        &mut state,
        1,
        "snapshot",
        json!({
            "workspaceRoot": WORKSPACE_ROOT,
        }),
    )?;
    let snapshot_id = snapshot
        .pointer("/result/snapshotId")
        .cloned()
        .ok_or_else(|| "snapshot response must contain an identity".to_string())?;

    let diagnostics = request(
        &mut state,
        2,
        "diagnostics",
        json!({
            "snapshotId": snapshot_id,
            "stylePath": STYLE_URI,
            "styleSource": ".card { color: red; }",
        }),
    )?;
    assert_eq!(
        diagnostics.pointer("/result/summary/classSelectorCount"),
        Some(&json!(1)),
    );
    assert_eq!(
        diagnostics.pointer("/result/snapshotId"),
        snapshot.pointer("/result/snapshotId"),
    );

    let query = request(
        &mut state,
        3,
        "query",
        json!({
            "snapshotId": snapshot_id,
            "queryKind": "styleSummary",
            "input": { "stylePath": STYLE_URI },
        }),
    )?;
    assert_eq!(
        query.pointer("/result/payload/selectorNames/0"),
        Some(&json!("card")),
    );
    Ok(())
}

#[test]
fn sdk_workflow_rejects_a_snapshot_after_document_change() -> Result<(), String> {
    let mut state = LspShellState::default();
    open_style(&mut state, 1, ".card { color: red; }");
    let snapshot = request(
        &mut state,
        1,
        "snapshot",
        json!({
            "workspaceRoot": WORKSPACE_ROOT,
        }),
    )?;
    let snapshot_id = snapshot
        .pointer("/result/snapshotId")
        .cloned()
        .ok_or_else(|| "snapshot response must contain an identity".to_string())?;

    handle_lsp_message(
        &mut state,
        json!({
            "jsonrpc": "2.0",
            "method": "textDocument/didChange",
            "params": {
                "textDocument": { "uri": STYLE_URI, "version": 2 },
                "contentChanges": [{ "text": ".card { color: blue; }" }],
            },
        }),
    );

    let response = request(
        &mut state,
        2,
        "query",
        json!({
            "snapshotId": snapshot_id,
            "queryKind": "styleSummary",
            "input": { "stylePath": STYLE_URI },
        }),
    )?;
    assert_eq!(
        response.pointer("/error/data/error/class"),
        Some(&json!("workspace")),
    );
    assert_eq!(
        response.pointer("/error/data/error/context/code"),
        Some(&json!("workspace.snapshot-mismatch")),
    );
    Ok(())
}

#[test]
fn sdk_workflow_keeps_workspace_roots_isolated() -> Result<(), String> {
    let mut state = LspShellState::default();
    open_style(&mut state, 1, ".card { color: red; }");
    handle_lsp_message(
        &mut state,
        json!({
            "jsonrpc": "2.0",
            "method": "textDocument/didOpen",
            "params": {
                "textDocument": {
                    "uri": "file:///workspace-b/src/Other.module.scss",
                    "languageId": "scss",
                    "version": 1,
                    "text": ".other { color: blue; }",
                },
            },
        }),
    );
    let snapshot = request(
        &mut state,
        1,
        "snapshot",
        json!({
            "workspaceRoot": WORKSPACE_ROOT,
        }),
    )?;
    let response = request(
        &mut state,
        2,
        "query",
        json!({
            "snapshotId": snapshot["result"]["snapshotId"],
            "queryKind": "styleSummary",
            "input": { "stylePath": "file:///workspace-b/src/Other.module.scss" },
        }),
    )?;
    assert_eq!(
        response.pointer("/error/data/error/context/code"),
        Some(&json!("workspace.style-path-not-found")),
    );
    Ok(())
}

fn open_style(state: &mut LspShellState, version: i64, text: &str) {
    handle_lsp_message(
        state,
        json!({
            "jsonrpc": "2.0",
            "method": "textDocument/didOpen",
            "params": {
                "textDocument": {
                    "uri": STYLE_URI,
                    "languageId": "scss",
                    "version": version,
                    "text": text,
                },
            },
        }),
    );
}

fn request(
    state: &mut LspShellState,
    id: u64,
    operation: &str,
    request: Value,
) -> Result<Value, String> {
    handle_lsp_message(
        state,
        json!({
            "jsonrpc": "2.0",
            "id": id,
            "method": SDK_WORKFLOW_REQUEST,
            "params": {
                "workspaceRoot": WORKSPACE_ROOT,
                "operation": operation,
                "request": request,
            },
        }),
    )
    .ok_or_else(|| "SDK workflow request must return a response".to_string())
}