Files
bux-lang/tools/smoke_lsp_implementation.sh
T
dimgigov a296f1695d feat(lsp): textDocument/implementation for interfaces (0.13)
Go-to-implementation resolves interface types to implementing types and
interface methods to extend Type for Iface method decls (Circle+Square).
2026-07-19 23:46:17 +03:00

113 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Smoke: textDocument/implementation (bux-lsp 0.13)
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
LSP="$ROOT/tools/bux-lsp"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
if [[ ! -x "$LSP" ]]; then
(cd "$ROOT" && make lsp >/dev/null)
fi
cat > "$TMP/Main.bux" <<'EOF'
interface Drawable {
func Draw(self: &Self);
}
struct Circle {
radius: int;
}
struct Square {
side: int;
}
extend Circle for Drawable {
func Draw(self: &Circle) {
let r: int = self.radius;
}
}
extend Square for Drawable {
func Draw(self: &Square) {
let s: int = self.side;
}
}
func Render(c: Circle) {
c.Draw();
}
func Main() -> int {
return 0;
}
EOF
rpc() {
local body="$1"
local len
len=$(printf '%s' "$body" | wc -c)
printf 'Content-Length: %s\r\n\r\n%s' "$len" "$body"
}
CONTENT_JSON=$(python3 -c 'import json,sys; print(json.dumps(open(sys.argv[1]).read()))' "$TMP/Main.bux")
URI="file://$TMP/Main.bux"
# Drawable interface name ~ line 0 character 10
# Draw iface method ~ line 1 character 9
# c.Draw() call ~ line 22 character 6 (approx)
{
rpc '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"rootUri":"file://'"$TMP"'"}}'
rpc '{"jsonrpc":"2.0","method":"initialized","params":{}}'
rpc '{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"'"$URI"'","languageId":"bux","version":1,"text":'"$CONTENT_JSON"'}}}'
# implementation on interface type Drawable
rpc '{"jsonrpc":"2.0","id":2,"method":"textDocument/implementation","params":{"textDocument":{"uri":"'"$URI"'"},"position":{"line":0,"character":10}}}'
# implementation on iface method Draw
rpc '{"jsonrpc":"2.0","id":3,"method":"textDocument/implementation","params":{"textDocument":{"uri":"'"$URI"'"},"position":{"line":1,"character":9}}}'
rpc '{"jsonrpc":"2.0","id":4,"method":"shutdown","params":null}'
rpc '{"jsonrpc":"2.0","method":"exit","params":null}'
} | "$LSP" 2>/dev/null | tr '\r' '\n' > "$TMP/out.txt"
if ! grep -q '0.13.0' "$TMP/out.txt"; then
echo "WARN: version not 0.13.0"
fi
if ! grep -q 'implementationProvider' "$TMP/out.txt"; then
echo "FAIL: missing implementationProvider capability"
cat "$TMP/out.txt"
exit 1
fi
# id 2: interface → Circle + Square type locations
# Count locations in response for id 2 roughly via line ranges mentioning Circle/Square
# Parse with python for robustness
python3 - <<'PY' "$TMP/out.txt"
import json, sys, re
raw = open(sys.argv[1]).read()
# Split Content-Length messages into JSON bodies
bodies = []
for m in re.finditer(r'Content-Length:\s*(\d+)\s*\n\s*\n', raw):
pass
# Simpler: find all JSON objects with "id"
parts = re.split(r'Content-Length:\s*\d+\s*', raw)
for p in parts:
p = p.strip()
if not p.startswith('{'):
continue
try:
j = json.loads(p)
except Exception:
continue
if j.get('id') == 2:
r = j.get('result') or []
if len(r) < 2:
print(f"FAIL: interface Drawable expected ≥2 implementor types, got {len(r)}")
print(json.dumps(j, indent=2)[:800])
sys.exit(1)
print(f" interface Drawable → {len(r)} type location(s)")
if j.get('id') == 3:
r = j.get('result') or []
if len(r) < 2:
print(f"FAIL: iface method Draw expected ≥2 implementors, got {len(r)}")
print(json.dumps(j, indent=2)[:800])
sys.exit(1)
# Expect two method sites (Circle.Draw + Square.Draw)
print(f" iface Draw → {len(r)} method location(s)")
print("PASS: LSP textDocument/implementation (0.13)")
PY