omena-lsp-server 0.3.0

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

#[test]
fn explain_hover_trace_reports_style_selector_definition() {
    let style_uri = "file:///workspace-a/src/App.module.scss";
    let style_text = ".root { color: red; }\n.theme { color: blue; }";
    let mut state = LspShellState::default();
    open_style_document(&mut state, style_uri, style_text);

    let response = handle_lsp_message(
        &mut state,
        json!({
            "jsonrpc": "2.0",
            "id": 2,
            "method": EXPLAIN_HOVER_TRACE_REQUEST,
            "params": {
                "textDocument": {
                    "uri": style_uri,
                },
                "position": {
                    "line": 0,
                    "character": 2,
                },
            },
        }),
    );

    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/product")),
        Some(&json!("omena-lsp-server.explain-hover-trace")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/fileKind")),
        Some(&json!("style")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/matched")),
        Some(&json!(true)),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/definitionCount")),
        Some(&json!(1)),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/definitions/0/name")),
        Some(&json!("root")),
    );
    let rendered_markdown = response
        .as_ref()
        .and_then(|value| value.pointer("/result/renderedMarkdown"))
        .and_then(Value::as_str)
        .unwrap_or_default();
    assert!(
        rendered_markdown.contains("color: red"),
        "rendered markdown: {rendered_markdown}"
    );
}

#[test]
fn explain_hover_trace_reports_source_selector_resolution() -> TestResult {
    let style_uri = "file:///workspace-a/src/App.module.scss";
    let source_uri = "file:///workspace-a/src/App.tsx";
    let style_text = ".foo { color: red; }\n";
    let source_text = "import bind from \"classnames/bind\";\nimport styles from \"./App.module.scss\";\nconst cx = bind.bind(styles);\nexport const view = <div className={cx(\"foo\")} />;\n";
    let mut state = LspShellState::default();
    initialize_workspace(&mut state);
    open_style_document(&mut state, style_uri, style_text);
    open_source_document(&mut state, source_uri, source_text);

    let response = handle_lsp_message(
        &mut state,
        json!({
            "jsonrpc": "2.0",
            "id": 2,
            "method": EXPLAIN_HOVER_TRACE_REQUEST,
            "params": {
                "textDocument": {
                    "uri": source_uri,
                },
                "position": parser_position_for_byte_offset(
                    source_text,
                    fixture_find(source_text, "\"foo\"", "source fixture contains selector")? + 2,
                ),
            },
        }),
    );

    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/product")),
        Some(&json!("omena-lsp-server.explain-hover-trace")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/fileKind")),
        Some(&json!("source")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/matched")),
        Some(&json!(true)),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/matchedCandidateCount")),
        Some(&json!(1)),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/definitionCount")),
        Some(&json!(1)),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/definitions/0/uri")),
        Some(&json!(style_uri)),
    );
    let rendered_markdown = response
        .as_ref()
        .and_then(|value| value.pointer("/result/renderedMarkdown"))
        .and_then(Value::as_str)
        .unwrap_or_default();
    assert!(
        rendered_markdown.contains("color: red"),
        "rendered markdown: {rendered_markdown}"
    );
    Ok(())
}

#[test]
fn explain_hover_trace_reports_domain_class_value_universe() -> TestResult {
    let source_uri = "file:///workspace-a/src/App.tsx";
    let source_text = r#"import { cva } from "class-variance-authority";
const button = cva("btn", {
  variants: {
    intent: {
      primary: "btn-primary",
      secondary: "btn-secondary",
    },
  },
});
const view = button({ intent: "primary" });
"#;
    let mut state = LspShellState::default();
    initialize_workspace(&mut state);
    open_source_document(&mut state, source_uri, source_text);

    let response = handle_lsp_message(
        &mut state,
        json!({
            "jsonrpc": "2.0",
            "id": 2,
            "method": EXPLAIN_HOVER_TRACE_REQUEST,
            "params": {
                "textDocument": {
                    "uri": source_uri,
                },
                "position": parser_position_for_byte_offset(
                    source_text,
                    fixture_find(source_text, "primary\" });", "source fixture contains option")? + 2,
                ),
            },
        }),
    );

    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/hoverKind")),
        Some(&json!("domainClassReference")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/sourceOwner")),
        Some(&json!("button")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/axisName")),
        Some(&json!("intent")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/knownOptions")),
        Some(&json!(["primary", "secondary"])),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/optionName")),
        Some(&json!("primary")),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/prefix")),
        Some(&Value::Null),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/definitionCount")),
        Some(&json!(0)),
    );
    assert_eq!(
        response
            .as_ref()
            .and_then(|value| value.pointer("/result/resolutionPath")),
        Some(&json!([
            "sourceSyntaxIndex",
            "classValueUniverseProvider",
            "sourceDomainReferenceHover",
        ])),
    );
    let rendered_markdown = response
        .as_ref()
        .and_then(|value| value.pointer("/result/renderedMarkdown"))
        .and_then(Value::as_str)
        .unwrap_or_default();
    assert!(
        rendered_markdown.contains("button.intent.primary"),
        "rendered markdown: {rendered_markdown}"
    );
    Ok(())
}

fn initialize_workspace(state: &mut LspShellState) {
    handle_lsp_message(
        state,
        json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "initialize",
            "params": {
                "workspaceFolders": [
                    {
                        "uri": "file:///workspace-a",
                        "name": "workspace-a",
                    },
                ],
            },
        }),
    );
}

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

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