LSP document symbols

This commit is contained in:
2026-03-07 21:33:12 -08:00
parent 90e36d8faf
commit 92ced8dcd2
6 changed files with 75 additions and 33 deletions

View File

@@ -4,5 +4,8 @@ end_of_line = lf
insert_final_newline = true insert_final_newline = true
indent_size = 2 indent_size = 2
indent_style = space indent_style = space
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile] [Makefile]
indent_style = tab indent_style = tab

View File

@@ -5,7 +5,7 @@
* vscode LSP server module. * vscode LSP server module.
*/ */
import { LSP_checkFile, LSP_updateFile, LSP_hoverInfo, LSP_codeActionInfo } from './newt.js' import { LSP_checkFile, LSP_updateFile, LSP_hoverInfo, LSP_codeActionInfo, LSP_docSymbols } from './newt.js'
import { import {
createConnection, createConnection,
@@ -118,12 +118,20 @@ connection.onCodeAction(({textDocument, range}) => {
return actions return actions
}) })
connection.onDocumentSymbol((params) => {
const uri = params.textDocument.uri;
let symbols = LSP_docSymbols(uri);
console.log("docs got", symbols)
return symbols;
})
connection.onInitialize((_params: InitializeParams): InitializeResult => ({ connection.onInitialize((_params: InitializeParams): InitializeResult => ({
capabilities: { capabilities: {
textDocumentSync: TextDocumentSyncKind.Incremental, textDocumentSync: TextDocumentSyncKind.Incremental,
hoverProvider: true, hoverProvider: true,
definitionProvider: true, definitionProvider: true,
codeActionProvider: true, codeActionProvider: true,
documentSymbolProvider: true,
}, },
})); }));

View File

@@ -1,4 +1,4 @@
import { CodeAction, Diagnostic, Location } from "vscode-languageserver"; import { CodeAction, Diagnostic, DocumentSymbol, Location } from "vscode-languageserver";
export function LSP_updateFile(name: string, content: string): (eta: any) => any; export function LSP_updateFile(name: string, content: string): (eta: any) => any;
export function LSP_checkFile(name: string): Diagnostic[]; export function LSP_checkFile(name: string): Diagnostic[];
@@ -8,3 +8,5 @@ interface HoverResult {
} }
export function LSP_hoverInfo(name: string, row: number, col: number): HoverResult|boolean|null; export function LSP_hoverInfo(name: string, row: number, col: number): HoverResult|boolean|null;
export function LSP_codeActionInfo(name: string, row: number, col: number): CodeAction[]|null; export function LSP_codeActionInfo(name: string, row: number, col: number): CodeAction[]|null;
export function LSP_docSymbols(name: string): DocumentSymbol[] | null;

View File

@@ -29,7 +29,6 @@ pfunc js_castObj : Array (String × JSObject) → JSObject := `(data) => {
return rval return rval
}` }`
-- need case split
jsonToJObject : Json JSObject jsonToJObject : Json JSObject
jsonToJObject (JsonInt x) = js_castInt x jsonToJObject (JsonInt x) = js_castInt x
jsonToJObject (JsonNull) = js_null jsonToJObject (JsonNull) = js_null
@@ -173,6 +172,36 @@ errorToDiag err =
-- These shouldn't escape -- These shouldn't escape
errorToDiag (Postpone fc qn msg) = errorToDiag $ E fc "Postpone \{show qn} \{msg}" errorToDiag (Postpone fc qn msg) = errorToDiag $ E fc "Postpone \{show qn} \{msg}"
getSymbols : M (List Json)
getSymbols = do
top <- getTop
let defs = listValues top.currentMod.modDefs
putStrLn "scan \{show $ length' defs} defs"
go Nil defs
where
getKind : Def Int
getKind Axiom = 12
getKind (TCon _ _) = 23
getKind (DCon _ _ _ _) = 10
getKind (Fn _) = 12
getKind (PrimTCon _) = 23
getKind (PrimFn _ _ _) = 12
getKind (PrimOp _) = 12
-- highlight where hx!
go : List Json List TopEntry M (List Json)
go acc Nil = pure $ reverse acc
go acc ((MkEntry fc name type def eflags) :: rest) =
let range = fcToRange fc in
let kind = getKind def in
let diag = JsonObj
$ ("name" , JsonStr (name.baseName))
:: ("range", range)
:: ("selectionRange", range)
:: ("kind", JsonInt kind)
-- detail
:: Nil
in go (diag :: acc) rest
getInfos : M (List Json) getInfos : M (List Json)
getInfos = do getInfos = do
@@ -225,6 +254,24 @@ checkFile fn = unsafePerformIO $ do
modifyIORef state $ [ topContext := top ] modifyIORef state $ [ topContext := top ]
pure $ jsonToJObject $ JsonArray json pure $ jsonToJObject $ JsonArray json
docSymbols : String JSObject
docSymbols fn = unsafePerformIO $ do
let (base, modName) = decomposeName fn
st <- readIORef state
putStrLn "Symbols for \{fn}"
if st.baseDir /= base
then resetState base
else pure MkUnit
repo <- lspFileSource
(Right (top, json)) <- (do
mod <- processModule emptyFC repo Nil modName
modifyTop [ currentMod := mod; ops := mod.modOps ]
getSymbols).runM st.topContext
| Left err => do
pure $ jsonToJObject $ JsonNull
modifyIORef state $ [ topContext := top ]
pure $ jsonToJObject $ JsonArray json
compileJS : String JSObject compileJS : String JSObject
compileJS fn = unsafePerformIO $ do compileJS fn = unsafePerformIO $ do
let (base, modName) = decomposeName fn let (base, modName) = decomposeName fn
@@ -246,4 +293,4 @@ compileJS fn = unsafePerformIO $ do
#export updateFile checkFile hoverInfo codeActionInfo compileJS #export updateFile checkFile hoverInfo codeActionInfo compileJS docSymbols

View File

@@ -127,25 +127,3 @@ deriveShow fc name = do
pure (left, Just right) pure (left, Just right)
-- -- A description would be nice.
-- deriveShow : FC → QName → M Raw
-- deriveShow fc qn = do
-- top <- getTop
-- case lookup qn top : Maybe TopEntry of
-- Nothing => error {Raw} fc "Can't find \{show qn} in derive Show"
-- -- I want case split too... I need to tie the editor into the repl.
-- (Just (MkEntry fc name type (TCon _ conNames) eflags) ) => ?
-- (Just (MkEntry fc name type (Axiom) eflags) ) => ?
-- (Just (MkEntry fc name type (DCon _ _ _ _) eflags) ) => ?
-- (Just (MkEntry fc name type (Fn _) eflags) ) => ?
-- (Just (MkEntry fc name type (PrimTCon _) eflags) ) => ?
-- (Just (MkEntry fc name type (PrimFn _ _ _) eflags) ) => ?
-- (Just (MkEntry fc name type (PrimOp _) eflags) ) => ?
-- error fc "TODO"
-- HasFC as example of user-defined derivation (when we get to that)
-- SetFC would be nice, too.

View File

@@ -28,15 +28,19 @@ dumpEnv ctx =
go : List String -> Int -> List (Val × String × Val) -> List String -> M (List String) go : List String -> Int -> List (Val × String × Val) -> List String -> M (List String)
go _ _ Nil acc = pure acc go _ _ Nil acc = pure acc
go names k ((v, n, ty) :: xs) acc = if isVar k v -- don't show the = bit for now. Lean folds it.
-- TODO - use Doc and add <+/> as appropriate to printing go names k ((v, n, ty) :: xs) acc = do
then do
ty' <- quote ctx.lvl ty ty' <- quote ctx.lvl ty
go names (1 + k) xs (" \{n} : \{render 90 $ pprint names ty'}":: acc) go names (1 + k) xs (" \{n} : \{render 90 $ pprint names ty'}":: acc)
else do
v' <- quote ctx.lvl v -- go names k ((v, n, ty) :: xs) acc = if isVar k v
ty' <- quote ctx.lvl ty -- then do
go names (1 + k) xs (" \{n} = \{render 90 $ pprint names v'} : \{render 90 $ pprint names ty'}":: acc) -- ty' <- quote ctx.lvl ty
-- go names (1 + k) xs (" \{n} : \{render 90 $ pprint names ty'}":: acc)
-- else do
-- v' <- quote ctx.lvl v
-- ty' <- quote ctx.lvl ty
-- go names (1 + k) xs (" \{n} = \{render 90 $ pprint names v'} : \{render 90 $ pprint names ty'}":: acc)
logMetas : List MetaEntry -> M Unit logMetas : List MetaEntry -> M Unit