- LSPWorkspaceIndex: track open docs, URI→{languageId,content,version}
- LSPDiagnosticsAggregator: merge diagnostics from multiple LSP sources per URI
- LSPCompletionMerger: merge+deduplicate completion items from multiple sources
- LSPOrchestrator: top-level coordinator composing all three + proxy + cross-lang resolver
- Sprint277IntegrationSummary: poly-api (Go+TypeScript) end-to-end integration
26/26 tests passing (5+5+5+5+6). All new headers ≤600 lines.
LoRA recorded: sprint277-2026-03-01 (1 call, 569 tokens).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
103 lines
3.5 KiB
C++
103 lines
3.5 KiB
C++
// Step 1913: LSPWorkspaceIndex
|
|
// Tracks open LSP documents: URI → {languageId, content, version}.
|
|
//
|
|
// t1: open and contains
|
|
// t2: getLanguage and getDocument
|
|
// t3: update changes content and version
|
|
// t4: listUris filters by languageId
|
|
// t5: close removes document; allLanguages reflects current set
|
|
|
|
#include "LSPWorkspaceIndex.h"
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
namespace ws = whetstone;
|
|
|
|
static int p=0,f=0;
|
|
#define T(n) { std::cout<<" "<<#n<<"... "; }
|
|
#define P() { std::cout<<"PASS\n"; ++p; }
|
|
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
|
|
#define C(c,m) if(!(c)){F(m);return;}
|
|
|
|
void t1(){
|
|
T(open_and_contains);
|
|
ws::LSPWorkspaceIndex idx;
|
|
C(idx.size() == 0, "empty initially");
|
|
idx.open("file:///src/main.go", "go", "package main", 1);
|
|
idx.open("file:///src/client.ts", "typescript", "const x=1;", 1);
|
|
C(idx.contains("file:///src/main.go"), "go file present");
|
|
C(idx.contains("file:///src/client.ts"), "ts file present");
|
|
C(!idx.contains("file:///src/other.py"), "py not present");
|
|
C(idx.size() == 2, "size 2");
|
|
P();
|
|
}
|
|
|
|
void t2(){
|
|
T(getLanguage_and_getDocument);
|
|
ws::LSPWorkspaceIndex idx;
|
|
idx.open("file:///a.go", "go", "package main", 1);
|
|
C(idx.getLanguage("file:///a.go") == "go", "language go");
|
|
C(idx.getLanguage("file:///missing.rs") == "", "missing returns empty");
|
|
auto doc = idx.getDocument("file:///a.go");
|
|
C(doc.uri == "file:///a.go", "doc uri");
|
|
C(doc.languageId == "go", "doc languageId");
|
|
C(doc.content == "package main", "doc content");
|
|
C(doc.version == 1, "doc version");
|
|
P();
|
|
}
|
|
|
|
void t3(){
|
|
T(update_changes_content_and_version);
|
|
ws::LSPWorkspaceIndex idx;
|
|
idx.open("file:///b.ts", "typescript", "const x=0;", 1);
|
|
idx.update("file:///b.ts", "const x=42;", 2);
|
|
auto doc = idx.getDocument("file:///b.ts");
|
|
C(doc.content == "const x=42;", "content updated");
|
|
C(doc.version == 2, "version updated");
|
|
// update on missing uri: no crash
|
|
idx.update("file:///nosuchfile.ts", "body", 5);
|
|
C(idx.size() == 1, "still size 1");
|
|
P();
|
|
}
|
|
|
|
void t4(){
|
|
T(listUris_filters_by_languageId);
|
|
ws::LSPWorkspaceIndex idx;
|
|
idx.open("file:///a.go", "go", "package a", 1);
|
|
idx.open("file:///b.go", "go", "package b", 1);
|
|
idx.open("file:///c.ts", "typescript", "const c=1;", 1);
|
|
auto goUris = idx.listUris("go");
|
|
C(goUris.size() == 2, "two go files");
|
|
auto tsUris = idx.listUris("typescript");
|
|
C(tsUris.size() == 1, "one ts file");
|
|
C(tsUris[0] == "file:///c.ts", "ts uri correct");
|
|
auto pyUris = idx.listUris("python");
|
|
C(pyUris.empty(), "no python files");
|
|
P();
|
|
}
|
|
|
|
void t5(){
|
|
T(close_and_allLanguages);
|
|
ws::LSPWorkspaceIndex idx;
|
|
idx.open("file:///x.go", "go", "package x", 1);
|
|
idx.open("file:///y.ts", "typescript", "const y;", 1);
|
|
idx.open("file:///z.rs", "rust", "fn z(){}", 1);
|
|
auto langs = idx.allLanguages(); // sorted
|
|
C(langs.size() == 3, "three languages");
|
|
C(langs[0] == "go", "go");
|
|
C(langs[1] == "rust", "rust");
|
|
C(langs[2] == "typescript", "typescript");
|
|
idx.close("file:///z.rs");
|
|
C(!idx.contains("file:///z.rs"), "rust file closed");
|
|
auto langs2 = idx.allLanguages();
|
|
C(langs2.size() == 2, "two languages after close");
|
|
P();
|
|
}
|
|
|
|
int main(){
|
|
std::cout << "Step 1913: LSPWorkspaceIndex\n";
|
|
t1(); t2(); t3(); t4(); t5();
|
|
std::cout << "\n" << p << "/" << (p+f) << " passed\n";
|
|
return f > 0 ? 1 : 0;
|
|
}
|