4ff075e0da
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / quality (pull_request) Successful in 32s
CI / typecheck (pull_request) Successful in 56s
CI / security (pull_request) Successful in 57s
CI / lint (pull_request) Successful in 3m19s
CI / integration_tests (pull_request) Successful in 3m44s
CI / unit_tests (pull_request) Successful in 6m39s
CI / docker (pull_request) Successful in 1m9s
CI / e2e_tests (pull_request) Successful in 9m38s
CI / coverage (pull_request) Successful in 11m19s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Failing after 1h13m38s
Replace local-mode stubs with real LSP protocol support: - StdioTransport: subprocess management with JSON-RPC framing - LspClient: LSP protocol (initialize/shutdown/diagnostics/completions) - LspLifecycleManager: reference-counted instances, health checks, crash restart - LspRuntime: registry-based server lookup, auto-restart on crash - LspToolAdapter: runtime-delegating handlers with local-mode fallback - LanguageDiscovery: 4-layer detection (extension, shebang, UKO, project) - activate_bindings/deactivate_bindings: actor compiler LSP binding wiring Tests: 27 Behave scenarios, 6 Robot integration tests, 250 existing pass. ISSUES CLOSED: #826
150 lines
6.7 KiB
Gherkin
150 lines
6.7 KiB
Gherkin
Feature: Functional LSP Runtime
|
|
As an actor runtime
|
|
I need LSP servers to provide real code intelligence
|
|
So that actors can get diagnostics and completions
|
|
|
|
# ── StdioTransport ────────────────────────────────────────────────
|
|
|
|
Scenario: StdioTransport rejects empty command
|
|
When I try to create a StdioTransport with empty command
|
|
Then a ValueError should be raised for transport
|
|
|
|
Scenario: StdioTransport reports not alive before start
|
|
Given I create a StdioTransport for "echo"
|
|
Then the transport should not be alive
|
|
|
|
Scenario: StdioTransport start and stop with echo
|
|
Given I create a StdioTransport for "cat"
|
|
When I start the transport
|
|
Then the transport should be alive
|
|
When I stop the transport
|
|
Then the transport should not be alive
|
|
|
|
# ── LspClient ─────────────────────────────────────────────────────
|
|
|
|
Scenario: LspClient starts not initialized
|
|
Given I create an LspClient with a mock transport
|
|
Then the client should not be initialized
|
|
|
|
Scenario: LspClient tracks request IDs
|
|
Given I create an LspClient with a mock transport
|
|
When I get two request IDs from the client
|
|
Then the IDs should be sequential
|
|
|
|
# ── LspLifecycleManager ──────────────────────────────────────────
|
|
|
|
Scenario: LspLifecycleManager starts empty
|
|
Given I create an LspLifecycleManager
|
|
Then the manager should have no running servers
|
|
|
|
Scenario: LspLifecycleManager stop unknown server raises error
|
|
Given I create an LspLifecycleManager
|
|
When I try to stop server "local/unknown" on the manager
|
|
Then an LspServerNotFoundError should be raised for lifecycle
|
|
|
|
Scenario: LspLifecycleManager health check returns false for unknown
|
|
Given I create an LspLifecycleManager
|
|
Then health check for "local/unknown" should return false
|
|
|
|
# ── LspRuntime with registry ─────────────────────────────────────
|
|
|
|
Scenario: LspRuntime start_server rejects empty name
|
|
Given I create a functional LspRuntime
|
|
When I try to start server with empty name and workspace "/tmp"
|
|
Then a ValueError should be raised for runtime
|
|
|
|
Scenario: LspRuntime start_server rejects empty workspace
|
|
Given I create a functional LspRuntime
|
|
When I try to start server "local/test" with empty workspace
|
|
Then a ValueError should be raised for runtime
|
|
|
|
Scenario: LspRuntime start_server raises for unregistered server
|
|
Given I create a functional LspRuntime
|
|
When I try to start unregistered server "local/missing"
|
|
Then an LspServerNotFoundError should be raised for runtime
|
|
|
|
Scenario: LspRuntime get_diagnostics rejects empty name
|
|
Given I create a functional LspRuntime
|
|
When I try to get diagnostics with empty name
|
|
Then a ValueError should be raised for runtime
|
|
|
|
Scenario: LspRuntime get_completions validates line >= 1
|
|
Given I create a functional LspRuntime
|
|
When I try to get completions with line 0
|
|
Then a ValueError should be raised for runtime
|
|
|
|
Scenario: LspRuntime get_completions validates column >= 1
|
|
Given I create a functional LspRuntime
|
|
When I try to get completions with column 0
|
|
Then a ValueError should be raised for runtime
|
|
|
|
# ── LanguageDiscovery ────────────────────────────────────────────
|
|
|
|
Scenario: LanguageDiscovery detects Python from extension
|
|
Given I create a LanguageDiscovery instance
|
|
Then language for "test.py" should be "python"
|
|
And language for "test.pyi" should be "python"
|
|
|
|
Scenario: LanguageDiscovery detects TypeScript from extension
|
|
Given I create a LanguageDiscovery instance
|
|
Then language for "app.ts" should be "typescript"
|
|
And language for "app.tsx" should be "typescriptreact"
|
|
|
|
Scenario: LanguageDiscovery detects Rust from extension
|
|
Given I create a LanguageDiscovery instance
|
|
Then language for "main.rs" should be "rust"
|
|
|
|
Scenario: LanguageDiscovery returns plaintext for unknown
|
|
Given I create a LanguageDiscovery instance
|
|
Then language for "data.xyz" should be "plaintext"
|
|
|
|
Scenario: LanguageDiscovery detects Dockerfile by name
|
|
Given I create a LanguageDiscovery instance
|
|
Then language for "Dockerfile" should be "dockerfile"
|
|
|
|
Scenario: LanguageDiscovery uses project language as fallback
|
|
Given I create a LanguageDiscovery with project language "go"
|
|
Then language for "unknown_file" should be "go"
|
|
|
|
Scenario: LanguageDiscovery cache invalidation works
|
|
Given I create a LanguageDiscovery instance
|
|
When I detect language for "test.py"
|
|
And I invalidate "test.py" from discovery cache
|
|
Then the cache should not contain "test.py"
|
|
|
|
Scenario: LanguageDiscovery detects shebang for Python script
|
|
Given I create a LanguageDiscovery instance
|
|
And I create a temp file with shebang "#!/usr/bin/env python3"
|
|
Then the temp file language should be "python"
|
|
|
|
Scenario: LanguageDiscovery detects shebang for bash script
|
|
Given I create a LanguageDiscovery instance
|
|
And I create a temp file with shebang "#!/bin/bash"
|
|
Then the temp file language should be "shellscript"
|
|
|
|
# ── LspToolAdapter with runtime ──────────────────────────────────
|
|
|
|
Scenario: LspToolAdapter generates runtime-backed handlers when runtime provided
|
|
Given I create an LspToolAdapter with a functional runtime
|
|
And I have an LSP server config with diagnostics capability
|
|
When I generate functional tool specs from the adapter
|
|
Then the tool specs should have runtime handlers
|
|
|
|
Scenario: LspToolAdapter generates local-mode handlers without runtime
|
|
Given I create an LspToolAdapter without runtime
|
|
And I have an LSP server config with diagnostics capability
|
|
When I generate functional tool specs from the adapter
|
|
Then the tool specs should have local-mode handlers
|
|
|
|
# ── Binding activation ───────────────────────────────────────────
|
|
|
|
Scenario: LspRuntime activate_bindings with no bindings returns empty
|
|
Given I create a functional LspRuntime
|
|
When I activate bindings with empty list
|
|
Then the activated servers list should be empty
|
|
|
|
Scenario: LspRuntime activate_bindings skips unregistered servers
|
|
Given I create a functional LspRuntime
|
|
When I activate bindings with unregistered server binding
|
|
Then the activated servers list should be empty
|