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).
This commit is contained in:
Executable
+112
@@ -0,0 +1,112 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user