|
2 | 2 | -- SPDX-License-Identifier: BSD-3-Clause |
3 | 3 | module Swarm.Language.LSP.Definition ( |
4 | 4 | findDefinition, |
| 5 | + DefinitionResult (..), |
5 | 6 | ) where |
6 | 7 |
|
7 | 8 | import Data.List.NonEmpty qualified as NE |
8 | | -import Data.Maybe (mapMaybe, maybeToList) |
| 9 | +import Data.Maybe (maybeToList) |
9 | 10 | import Data.Text.Utf16.Rope.Mixed qualified as R |
| 11 | +import Debug.Trace (traceShow) |
10 | 12 | import Language.LSP.Protocol.Types qualified as J |
11 | 13 | import Language.LSP.Protocol.Types qualified as LSP |
12 | 14 | import Language.LSP.VFS (VirtualFile (VirtualFile), virtualFileText) |
13 | 15 | import Swarm.Language.LSP.Position qualified as P |
14 | 16 | import Swarm.Language.Parser (readTerm') |
15 | | -import Swarm.Language.Parser.Core (defaultParserConfig) |
| 17 | +import Swarm.Language.Parser.Core (ParserError, defaultParserConfig) |
16 | 18 | import Swarm.Language.Pipeline (processParsedTerm) |
17 | | -import Swarm.Language.Syntax (LocVar, Located (..), SrcLoc, Syntax, Syntax' (Syntax'), Term' (..), Var) |
| 19 | +import Swarm.Language.Syntax (Located (..), SrcLoc, Syntax, Syntax' (Syntax'), Term' (..), Var) |
18 | 20 | import Swarm.Language.TDVar (tdVarName) |
19 | | -import Swarm.Language.Types (Polytype) |
| 21 | +import Swarm.Language.Typecheck (ContextualTypeErr) |
| 22 | + |
| 23 | +data DefinitionResult = TError ContextualTypeErr | PError ParserError | Unsupported | NotFound | Found [J.Range] |
20 | 24 |
|
21 | 25 | findDefinition :: |
22 | 26 | J.NormalizedUri -> |
23 | 27 | J.Position -> |
24 | 28 | VirtualFile -> |
25 | | - ([J.Range], [Syntax' Polytype]) |
| 29 | + DefinitionResult |
26 | 30 | findDefinition _ p vf@(VirtualFile _ _ myRope) = |
27 | 31 | either |
28 | | - (const ([], [])) |
29 | | - ( \t -> case t of |
30 | | - Nothing -> ([], []) |
31 | | - Just t' -> findDef t' |
32 | | - ) |
| 32 | + PError |
| 33 | + (maybe Unsupported findDef) |
33 | 34 | (readTerm' defaultParserConfig content) |
34 | 35 | where |
35 | 36 | content = virtualFileText vf |
36 | 37 | absolutePos = |
37 | 38 | R.charLength . fst $ R.charSplitAtPosition (P.lspToRopePosition p) myRope |
38 | 39 |
|
39 | | - findDef :: Syntax -> ([LSP.Range], [Syntax' Polytype]) |
| 40 | + -- build a list from the syntax tree and starting from the position of the cursor (the bottom). |
| 41 | + -- search for the matching definition. |
| 42 | + findDef :: Syntax -> DefinitionResult |
40 | 43 | findDef stx = |
41 | 44 | case processParsedTerm stx of |
42 | | - Left _e -> ([], []) |
| 45 | + Left e -> TError e |
43 | 46 | Right pt -> do |
44 | 47 | let path = P.pathToPosition pt $ fromIntegral absolutePos |
45 | | - |
46 | | - -- The last element in the path is the thing we are looking for |
47 | | - -- get it's name |
48 | 48 | let usage = usageName $ NE.last path |
| 49 | + |
49 | 50 | case usage of |
50 | | - Nothing -> ([], NE.toList path) |
| 51 | + Nothing -> Unsupported |
51 | 52 | Just u -> do |
52 | | - let pathTerms = concatMap syntaxVars $! (NE.drop 1 . NE.reverse $ path) |
53 | | - (mapMaybe (maybeDefPosition u) pathTerms, NE.toList path) |
| 53 | + let pathTerms = concatMap syntaxVars (NE.drop 1 . NE.reverse $ path) |
| 54 | + traceShow pathTerms maybe NotFound Found (traverse (maybeDefPosition u) pathTerms) |
54 | 55 |
|
55 | 56 | -- take a syntax element that we want to find the defintion for and |
56 | 57 | -- a possible syntax element that contains it's defintion |
57 | 58 | -- if this is the matching definition return the position |
58 | 59 | maybeDefPosition :: Var -> (SrcLoc, Var) -> Maybe LSP.Range |
59 | | - maybeDefPosition name' (pos, name) |
| 60 | + maybeDefPosition name (pos, name') |
60 | 61 | | name == name' = P.posToRange myRope pos |
61 | 62 | | otherwise = Nothing |
62 | 63 |
|
63 | 64 | -- | find the name of the syntax element if it is a value level variable |
64 | 65 | -- TODO if we want to support more jump to definitions we should extend this |
65 | 66 | usageName :: Syntax' a -> Maybe Var |
66 | | -usageName (Syntax' _ (TVar name) _ _) = Just name |
67 | | -usageName _ = Nothing |
| 67 | +usageName (Syntax' _ t _ _) = case t of |
| 68 | + (TVar n) -> Just n |
| 69 | + _ -> Nothing |
68 | 70 |
|
69 | 71 | syntaxVars :: Syntax' a -> [(SrcLoc, Var)] |
70 | 72 | syntaxVars (Syntax' _ t _ _) = case t of |
|
0 commit comments