db7ba1dff2
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
bux-lsp 0.17 publishes in-process diagnostics on open/change/save so editors show red squiggles for lex/parse/type errors in the live buffer. VS Code client discovers tools/bux-lsp, adds status bar/restart, richer syntax/snippets, and docs (docs/LSP.md) for forum/editor setup.
88 lines
3.4 KiB
Bash
Executable File
88 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Smoke: textDocument/publishDiagnostics underlines type/parse errors in the buffer.
|
|
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
|
|
echo "building bux-lsp..."
|
|
(cd "$ROOT" && make lsp >/dev/null)
|
|
fi
|
|
|
|
# Intentionally wrong: String assigned to int
|
|
cat > "$TMP/Main.bux" <<'EOF'
|
|
func Main() -> int {
|
|
let x: int = "boom";
|
|
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"
|
|
|
|
# Also test didChange: fix would clear, re-break would re-publish
|
|
BROKEN2='func Main() -> int {\n let y: int = true;\n return 0;\n}\n'
|
|
BROKEN2_JSON=$(python3 -c 'import json,sys; print(json.dumps(sys.argv[1].encode("utf-8").decode("unicode_escape")))' "$BROKEN2")
|
|
|
|
{
|
|
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"'}}}'
|
|
# Give server a moment is not needed — sync stdio
|
|
rpc '{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"'"$URI"'","version":2},"contentChanges":[{"text":'"$BROKEN2_JSON"'}]}}'
|
|
rpc '{"jsonrpc":"2.0","id":2,"method":"shutdown","params":null}'
|
|
rpc '{"jsonrpc":"2.0","method":"exit","params":null}'
|
|
} | "$LSP" 2>/dev/null | tr '\r' '\n' > "$TMP/out.txt"
|
|
|
|
echo "---- diagnostics excerpt ----"
|
|
grep -o '"method":"textDocument/publishDiagnostics"[^}]*}[^}]*}[^}]*}' "$TMP/out.txt" | head -5 || true
|
|
# Broader: any publishDiagnostics payload
|
|
python3 - <<'PY' "$TMP/out.txt"
|
|
import json, sys, re
|
|
raw = open(sys.argv[1]).read()
|
|
# Split on Content-Length framing remnants — we already stripped \r; bodies are JSON objects
|
|
parts = []
|
|
for m in re.finditer(r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}', raw):
|
|
s = m.group(0)
|
|
if "publishDiagnostics" in s or '"diagnostics"' in s:
|
|
parts.append(s)
|
|
|
|
# More robust: scan for diagnostics arrays via string search
|
|
ok = True
|
|
if "publishDiagnostics" not in raw and "diagnostics" not in raw:
|
|
print("FAIL: no publishDiagnostics notification")
|
|
ok = False
|
|
else:
|
|
# Must mention type mismatch somehow
|
|
low = raw.lower()
|
|
if "cannot assign" not in low and "type" not in low and "error" not in low:
|
|
print("FAIL: diagnostics payload has no error-like message")
|
|
ok = False
|
|
else:
|
|
print("found diagnostics notification with error content")
|
|
# severity 1 = Error
|
|
if '"severity":1' not in raw and '"severity": 1' not in raw:
|
|
print("WARN: severity=1 not found as literal (may be ok)")
|
|
# Expect at least one diagnostic on line 1 (0-based) for `let x: int = "boom"`
|
|
if '"line":1' not in raw and '"line": 1' not in raw:
|
|
# might be line 0 depending on layout
|
|
if '"line":0' not in raw and '"line": 0' not in raw:
|
|
print("WARN: unexpected line numbers")
|
|
print("PASS markers: publishDiagnostics present")
|
|
|
|
if not ok:
|
|
print("---- full output ----")
|
|
print(raw[:4000])
|
|
sys.exit(1)
|
|
print("PASS: LSP diagnostics smoke (error underlines)")
|
|
PY
|