git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
[psc-ide] Provides AST information on completion

* Unifies response formats for the type and complete commands so go-to-definition and type annotations now also show up in completions

commit8dd39654480cb4a8fa1f08b7fb2d07bb14c52396 authorChristoph Hegemann <christoph.hegemann1337@gmail.com> dateSun 11 Sep 2016, 23:17 (10 years ago) parent03260df
13 files changed+122−118
psc-ide-server/PROTOCOL.md+13−22 src/Language/PureScript/Ide.hs+6−6 src/Language/PureScript/Ide/Command.hs+1−1 src/Language/PureScript/Ide/Completion.hs+7−8 src/Language/PureScript/Ide/Matcher.hs+8−8 src/Language/PureScript/Ide/SourceFile.hs+12 src/Language/PureScript/Ide/State.hs+1−4 src/Language/PureScript/Ide/Types.hs+18−16 src/Language/PureScript/Ide/Util.hs+28−24 tests/Language/PureScript/Ide/Integration.hs+7−19 tests/Language/PureScript/Ide/MatcherSpec.hs+9−7 tests/Language/PureScript/Ide/SourceFile/IntegrationSpec.hs+6−1 tests/Language/PureScript/Ide/SourceFileSpec.hs+6−2
psc-ide-server/PROTOCOL.md+13−22
@@ -51,27 +51,7 @@ definition position, if it can be found in the passed source files.
5151```
5252
5353**Result:**
54−The possible types are returned in the same format as completions + eventual position information
55−```json
56−[
57− {
58− "module": "Data.Array",
59− "identifier": "filter",
60− "type": "forall a. (a -> Boolean) -> Array a -> Array a"
61− },
62− {
63− "module": "Data.Array",
64− "identifier": "filter",
65− "type": "forall a. (a -> Boolean) -> Array a -> Array a",
66− "definedAt":
67− {
68− "name": "/path/to/file",
69− "start": [1, 3],
70− "end": [3, 1]
71− }
72− }
73−]
74−```
54+The possible types are returned in the same format as completions
7555
7656### Complete
7757The `complete` command looks up possible completions/corrections.
@@ -104,12 +84,23 @@ The `complete` command looks up possible completions/corrections.
10484
10585The following format is returned as the Result:
10686
87+Both the `definedAt` aswell as the `documentation` field might be `null` if they
88+couldn't be extracted from a source file.
89+
10790```json
10891[
10992 {
11093 "module": "Data.Array",
11194 "identifier": "filter",
112− "type": "forall a. (a -> Boolean) -> Array a -> Array a"
95+ "type": "forall a. (a -> Boolean) -> Array a -> Array a",
96+ "expandedType": "forall a. (a -> Boolean) -> Array a -> Array a",
97+ "definedAt":
98+ {
99+ "name": "/path/to/file",
100+ "start": [1, 3],
101+ "end": [3, 1]
102+ },
103+ "documentation": "A filtering function"
113104 }
114105]
115106```
src/Language/PureScript/Ide.hs+6−6
@@ -38,9 +38,9 @@ import Language.PureScript.Ide.SourceFile
3838import Language.PureScript.Ide.State
3939import Language.PureScript.Ide.Types
4040import Language.PureScript.Ide.Util
41−import System.Directory
42−import System.FilePath
43−import System.FilePath.Glob
41+import System.Directory (getCurrentDirectory, getDirectoryContents, doesDirectoryExist, doesFileExist)
42+import System.FilePath ((</>))
43+import System.FilePath.Glob (glob)
4444
4545-- | Accepts a Commmand and runs it against psc-ide's State. This is the main
4646-- entry point for the server.
@@ -77,7 +77,7 @@ handleCommand c = case c of
7777 case rs of
7878 Right rs' -> answerRequest outfp rs'
7979 Left question ->
80− pure (CompletionResult (map completionFromMatch question))
80+ pure (CompletionResult (map (completionFromMatch . map withEmptyAnn) question))
8181 Rebuild file ->
8282 rebuildFile file
8383 Cwd ->
@@ -88,7 +88,7 @@ handleCommand c = case c of
8888 liftIO exitSuccess
8989
9090findCompletions :: Ide m =>
91− [Filter] -> Matcher IdeDeclaration -> Maybe P.ModuleName -> m Success
91+ [Filter] -> Matcher IdeDeclarationAnn -> Maybe P.ModuleName -> m Success
9292findCompletions filters matcher currentModule = do
9393 modules <- getAllModules currentModule
9494 pure . CompletionResult . map completionFromMatch . getCompletions filters matcher $ modules
@@ -97,7 +97,7 @@ findType :: Ide m =>
9797 Text -> [Filter] -> Maybe P.ModuleName -> m Success
9898findType search filters currentModule = do
9999 modules <- getAllModules currentModule
100− pure . InfoResult . map infoFromMatch . getExactMatches search filters $ modules
100+ pure . CompletionResult . map completionFromMatch . getExactMatches search filters $ modules
101101
102102findPursuitCompletions :: MonadIO m =>
103103 PursuitQuery -> m Success
src/Language/PureScript/Ide/Command.hs+1−1
@@ -34,7 +34,7 @@ data Command
3434 }
3535 | Complete
3636 { completeFilters :: [Filter]
37− , completeMatcher :: Matcher IdeDeclaration
37+ , completeMatcher :: Matcher IdeDeclarationAnn
3838 , completeCurrentModule :: Maybe P.ModuleName
3939 }
4040 | Pursuit
src/Language/PureScript/Ide/Completion.hs+7−8
@@ -9,24 +9,23 @@ import Protolude
99import Language.PureScript.Ide.Filter
1010import Language.PureScript.Ide.Matcher
1111import Language.PureScript.Ide.Types
12−import Language.PureScript.Ide.Util
1312
1413-- | Applies the CompletionFilters and the Matcher to the given Modules
1514-- and sorts the found Completions according to the Matching Score
1615getCompletions
1716 :: [Filter]
18− -> Matcher IdeDeclaration
17+ -> Matcher IdeDeclarationAnn
1918 -> [Module]
20− -> [Match IdeDeclaration]
19+ -> [Match IdeDeclarationAnn]
2120getCompletions filters matcher modules =
22− runMatcher matcher (completionsFromModules discardAnn (applyFilters filters modules))
21+ runMatcher matcher (completionsFromModules (applyFilters filters modules))
2322
2423getExactMatches :: Text -> [Filter] -> [Module] -> [Match IdeDeclarationAnn]
2524getExactMatches search filters modules =
26− completionsFromModules identity (applyFilters (equalityFilter search : filters) modules)
25+ completionsFromModules (applyFilters (equalityFilter search : filters) modules)
2726
28−completionsFromModules :: (IdeDeclarationAnn -> a) -> [Module] -> [Match a]
29−completionsFromModules f = foldMap completionFromModule
27+completionsFromModules :: [Module] -> [Match IdeDeclarationAnn]
28+completionsFromModules = foldMap completionFromModule
3029 where
3130 completionFromModule (moduleName, decls) =
32− map (\x -> Match (moduleName, f x)) decls
31+ map (\x -> Match (moduleName, x)) decls
src/Language/PureScript/Ide/Matcher.hs+8−8
@@ -38,7 +38,7 @@ type ScoredMatch a = (Match a, Double)
3838
3939newtype Matcher a = Matcher (Endo [Match a]) deriving (Monoid)
4040
41−instance FromJSON (Matcher IdeDeclaration) where
41+instance FromJSON (Matcher IdeDeclarationAnn) where
4242 parseJSON = withObject "matcher" $ \o -> do
4343 (matcher :: Maybe Text) <- o .:? "matcher"
4444 case matcher of
@@ -60,17 +60,17 @@ instance FromJSON (Matcher IdeDeclaration) where
6060-- Examples:
6161-- flMa matches flexMatcher. Score: 14.28
6262-- sons matches sortCompletions. Score: 6.25
63−flexMatcher :: Text -> Matcher IdeDeclaration
63+flexMatcher :: Text -> Matcher IdeDeclarationAnn
6464flexMatcher p = mkMatcher (flexMatch p)
6565
66−distanceMatcher :: Text -> Int -> Matcher IdeDeclaration
66+distanceMatcher :: Text -> Int -> Matcher IdeDeclarationAnn
6767distanceMatcher q maxDist = mkMatcher (distanceMatcher' q maxDist)
6868
69−distanceMatcher' :: Text -> Int -> [Match IdeDeclaration] -> [ScoredMatch IdeDeclaration]
69+distanceMatcher' :: Text -> Int -> [Match IdeDeclarationAnn] -> [ScoredMatch IdeDeclarationAnn]
7070distanceMatcher' q maxDist = mapMaybe go
7171 where
7272 go m = let d = dist (T.unpack y)
73− y = identifierFromIdeDeclaration (unwrapMatch m)
73+ y = identifierFromIdeDeclaration (discardAnn (unwrapMatch m))
7474 in if d <= maxDist
7575 then Just (m, 1 / fromIntegral d)
7676 else Nothing
@@ -85,12 +85,12 @@ runMatcher (Matcher m)= appEndo m
8585sortCompletions :: [ScoredMatch a] -> [ScoredMatch a]
8686sortCompletions = sortBy (flip compare `on` snd)
8787
88−flexMatch :: Text -> [Match IdeDeclaration] -> [ScoredMatch IdeDeclaration]
88+flexMatch :: Text -> [Match IdeDeclarationAnn] -> [ScoredMatch IdeDeclarationAnn]
8989flexMatch = mapMaybe . flexRate
9090
91−flexRate :: Text -> Match IdeDeclaration -> Maybe (ScoredMatch IdeDeclaration)
91+flexRate :: Text -> Match IdeDeclarationAnn -> Maybe (ScoredMatch IdeDeclarationAnn)
9292flexRate p c = do
93− score <- flexScore p (identifierFromIdeDeclaration (unwrapMatch c))
93+ score <- flexScore p (identifierFromIdeDeclaration (discardAnn (unwrapMatch c)))
9494 return (c, score)
9595
9696-- FlexMatching ala Sublime.
src/Language/PureScript/Ide/SourceFile.hs+12
@@ -17,12 +17,15 @@
1717module Language.PureScript.Ide.SourceFile
1818 ( parseModule
1919 , getImportsForFile
20+ , extractAstInformation
21+ -- for tests
2022 , extractSpans
2123 , extractTypeAnnotations
2224 ) where
2325
2426import Protolude
2527
28+import qualified Data.Map as Map
2629import qualified Language.PureScript as P
2730import Language.PureScript.Ide.Error
2831import Language.PureScript.Ide.Util
@@ -65,6 +68,15 @@ getImportsForFile fp = do
6568 unwrapImportType (P.Hiding decls) = P.Hiding (map unwrapPositionedRef decls)
6669 unwrapImportType P.Implicit = P.Implicit
6770
71+-- | Extracts AST information from a parsed module
72+extractAstInformation
73+ :: P.Module
74+ -> (DefinitionSites P.SourceSpan, TypeAnnotations)
75+extractAstInformation (P.Module ss _ _ decls _) =
76+ let definitions = Map.fromList (concatMap (extractSpans ss) decls)
77+ typeAnnotations = Map.fromList (extractTypeAnnotations decls)
78+ in (definitions, typeAnnotations)
79+
6880-- | Extracts type annotations for functions from a given Module
6981extractTypeAnnotations
7082 :: [P.Declaration]
src/Language/PureScript/Ide/State.hs+1−4
@@ -180,10 +180,7 @@ populateStage2 = do
180180populateStage2STM :: TVar IdeState -> STM ()
181181populateStage2STM ref = do
182182 modules <- s1Modules <$> getStage1STM ref
183− let astData = map (\(P.Module ss _ _ decls _, _) ->
184− let definitions = M.fromList (concatMap (extractSpans ss) decls)
185− typeAnnotations = M.fromList (extractTypeAnnotations decls)
186− in (definitions, typeAnnotations)) modules
183+ let astData = map (extractAstInformation . fst) modules
187184 setStage2STM ref (Stage2 (AstData astData))
188185
189186-- | Resolves reexports and populates Stage3 with data to be used in queries.
src/Language/PureScript/Ide/Types.hs+18−16
@@ -112,21 +112,25 @@ data Stage3 = Stage3
112112newtype Match a = Match (P.ModuleName, a)
113113 deriving (Show, Eq, Functor)
114114
115−newtype Completion =
116− Completion (Text, Text, Text)
117− deriving (Show,Eq)
118−
119−newtype Info =
120− Info (Text, Text, Text, Maybe P.SourceSpan)
121− deriving (Show,Eq)
122−
123−instance ToJSON Info where
124− toJSON (Info (m, d, t, sourceSpan)) =
125− object ["module" .= m, "identifier" .= d, "type" .= t, "definedAt" .= sourceSpan]
115+-- | A completion as it gets sent to the editors
116+data Completion = Completion
117+ { complModule :: Text
118+ , complIdentifier :: Text
119+ , complType :: Text
120+ , complExpandedType :: Text
121+ , complLocation :: Maybe P.SourceSpan
122+ , complDocumentation :: Maybe Text
123+ } deriving (Show, Eq)
126124
127125instance ToJSON Completion where
128− toJSON (Completion (m, d, t)) =
129− object ["module" .= m, "identifier" .= d, "type" .= t]
126+ toJSON (Completion {..}) =
127+ object [ "module" .= complModule
128+ , "identifier" .= complIdentifier
129+ , "type" .= complType
130+ , "expandedType" .= complExpandedType
131+ , "definedAt" .= complLocation
132+ , "documentation" .= complDocumentation
133+ ]
130134
131135data ModuleImport =
132136 ModuleImport
@@ -164,14 +168,13 @@ identifierFromDeclarationRef _ = ""
164168
165169data Success =
166170 CompletionResult [Completion]
167− | InfoResult [Info]
168171 | TextResult Text
169172 | MultilineTextResult [Text]
170173 | PursuitResult [PursuitResponse]
171174 | ImportList [ModuleImport]
172175 | ModuleList [ModuleIdent]
173176 | RebuildSuccess [P.JSONError]
174− deriving(Show, Eq)
177+ deriving (Show, Eq)
175178
176179encodeSuccess :: (ToJSON a) => a -> Value
177180encodeSuccess res =
@@ -179,7 +182,6 @@ encodeSuccess res =
179182
180183instance ToJSON Success where
181184 toJSON (CompletionResult cs) = encodeSuccess cs
182− toJSON (InfoResult i) = encodeSuccess i
183185 toJSON (TextResult t) = encodeSuccess t
184186 toJSON (MultilineTextResult ts) = encodeSuccess ts
185187 toJSON (PursuitResult resp) = encodeSuccess resp
src/Language/PureScript/Ide/Util.hs+28−24
@@ -20,10 +20,10 @@ module Language.PureScript.Ide.Util
2020 , unwrapPositioned
2121 , unwrapPositionedRef
2222 , completionFromMatch
23− , infoFromMatch
2423 , encodeT
2524 , decodeT
2625 , discardAnn
26+ , withEmptyAnn
2727 , module Language.PureScript.Ide.Conversions
2828 ) where
2929
@@ -48,25 +48,35 @@ identifierFromIdeDeclaration d = case d of
4848discardAnn :: IdeDeclarationAnn -> IdeDeclaration
4949discardAnn (IdeDeclarationAnn _ d) = d
5050
51+withEmptyAnn :: IdeDeclaration -> IdeDeclarationAnn
52+withEmptyAnn = IdeDeclarationAnn emptyAnn
53+
5154unwrapMatch :: Match a -> a
5255unwrapMatch (Match (_, ed)) = ed
5356
54−completionFromMatch :: Match IdeDeclaration -> Completion
55−completionFromMatch = Completion . completionFromMatch'
56−
57−completionFromMatch' :: Match IdeDeclaration -> (Text, Text, Text)
58−completionFromMatch' (Match (m', d)) = case d of
59− IdeValue name type' -> (m, runIdentT name, prettyTypeT type')
60− IdeType name kind -> (m, runProperNameT name, toS (P.prettyPrintKind kind))
61− IdeTypeSynonym name kind -> (m, runProperNameT name, prettyTypeT kind)
62− IdeDataConstructor name _ type' -> (m, runProperNameT name, prettyTypeT type')
63− IdeTypeClass name -> (m, runProperNameT name, "class")
64− IdeValueOperator op ref precedence associativity ->
65− (m, runOpNameT op, showFixity precedence associativity ref op)
66− IdeTypeOperator op ref precedence associativity ->
67− (m, runOpNameT op, showFixity precedence associativity ref op)
57+completionFromMatch :: Match IdeDeclarationAnn -> Completion
58+completionFromMatch (Match (m, IdeDeclarationAnn ann decl)) =
59+ Completion {..}
6860 where
69− m = runModuleNameT m'
61+ (complIdentifier, complExpandedType) = case decl of
62+ IdeValue name type' -> (runIdentT name, prettyTypeT type')
63+ IdeType name kind -> (runProperNameT name, toS (P.prettyPrintKind kind))
64+ IdeTypeSynonym name kind -> (runProperNameT name, prettyTypeT kind)
65+ IdeDataConstructor name _ type' -> (runProperNameT name, prettyTypeT type')
66+ IdeTypeClass name -> (runProperNameT name, "class")
67+ IdeValueOperator op ref precedence associativity ->
68+ (runOpNameT op, showFixity precedence associativity ref op)
69+ IdeTypeOperator op ref precedence associativity ->
70+ (runOpNameT op, showFixity precedence associativity ref op)
71+
72+ complModule = runModuleNameT m
73+
74+ complType = maybe complExpandedType prettyTypeT (annTypeAnnotation ann)
75+
76+ complLocation = annLocation ann
77+
78+ complDocumentation = Nothing
79+
7080 showFixity p a r o =
7181 let asso = case a of
7282 P.Infix -> "infix"
@@ -74,12 +84,6 @@ completionFromMatch' (Match (m', d)) = case d of
7484 P.Infixr -> "infixr"
7585 in T.unwords [asso, show p, r, "as", runOpNameT o]
7686
77−infoFromMatch :: Match IdeDeclarationAnn -> Info
78−infoFromMatch (Match (m, IdeDeclarationAnn ann d)) =
79− Info (a, b, maybe c prettyTypeT (annTypeAnnotation ann), annLocation ann)
80− where
81− (a, b, c) = completionFromMatch' (Match (m, d))
82−
8387encodeT :: (ToJSON a) => a -> Text
8488encodeT = toS . decodeUtf8 . encode
8589
@@ -87,9 +91,9 @@ decodeT :: (FromJSON a) => Text -> Maybe a
8791decodeT = decode . encodeUtf8 . toS
8892
8993unwrapPositioned :: P.Declaration -> P.Declaration
90−unwrapPositioned (P.PositionedDeclaration _ _ x) = x
94+unwrapPositioned (P.PositionedDeclaration _ _ x) = unwrapPositioned x
9195unwrapPositioned x = x
9296
9397unwrapPositionedRef :: P.DeclarationRef -> P.DeclarationRef
94−unwrapPositionedRef (P.PositionedDeclarationRef _ _ x) = x
98+unwrapPositionedRef (P.PositionedDeclarationRef _ _ x) = unwrapPositionedRef x
9599unwrapPositionedRef x = x
tests/Language/PureScript/Ide/Integration.hs+7−19
@@ -37,13 +37,11 @@ module Language.PureScript.Ide.Integration
3737 , getFlexCompletions
3838 , getFlexCompletionsInModule
3939 , getType
40− , getInfo
4140 , rebuildModule
4241 , reset
4342 -- checking results
4443 , resultIsSuccess
4544 , parseCompletions
46− , parseInfo
4745 , parseTextResult
4846 ) where
4947
@@ -158,18 +156,15 @@ loadModules = sendCommand . load
158156loadAll :: IO Text
159157loadAll = sendCommand (load [])
160158
161−getFlexCompletions :: Text -> IO [(Text, Text, Text)]
159+getFlexCompletions :: Text -> IO [(Text, Text, Text, Maybe P.SourceSpan)]
162160getFlexCompletions q = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) Nothing)
163161
164−getFlexCompletionsInModule :: Text -> Text -> IO [(Text, Text, Text)]
162+getFlexCompletionsInModule :: Text -> Text -> IO [(Text, Text, Text, Maybe P.SourceSpan)]
165163getFlexCompletionsInModule q m = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) (Just m))
166164
167−getType :: Text -> IO [(Text, Text, Text)]
165+getType :: Text -> IO [(Text, Text, Text, Maybe P.SourceSpan)]
168166getType q = parseCompletions <$> sendCommand (typeC q [])
169167
170−getInfo :: Text -> IO [P.SourceSpan]
171−getInfo q = parseInfo <$> sendCommand (typeC q [])
172−
173168addImport :: Text -> FilePath -> FilePath -> IO Text
174169addImport identifier fp outfp = sendCommand (addImportC identifier fp outfp)
175170
@@ -254,17 +249,14 @@ withResult p v = do
254249 Left err -> pure (Left err)
255250 Right res -> Right <$> p res
256251
257−completionParser :: Value -> Parser [(Text, Text, Text)]
252+completionParser :: Value -> Parser [(Text, Text, Text, Maybe P.SourceSpan)]
258253completionParser = withArray "res" $ \cs ->
259254 mapM (withObject "completion" $ \o -> do
260255 ident <- o .: "identifier"
261256 module' <- o .: "module"
262257 ty <- o .: "type"
263− pure (module', ident, ty)) (V.toList cs)
264−
265−infoParser :: Value -> Parser [P.SourceSpan]
266−infoParser = withArray "res" $ \cs ->
267− mapM (withObject "info" $ \o -> o .: "definedAt") (V.toList cs)
258+ ss <- o .: "definedAt"
259+ pure (module', ident, ty, ss)) (V.toList cs)
268260
269261valueFromText :: Text -> Value
270262valueFromText = fromJust . decode . toS
@@ -272,14 +264,10 @@ valueFromText = fromJust . decode . toS
272264resultIsSuccess :: Text -> Bool
273265resultIsSuccess = isRight . join . first toS . parseEither unwrapResult . valueFromText
274266
275−parseCompletions :: Text -> [(Text, Text, Text)]
267+parseCompletions :: Text -> [(Text, Text, Text, Maybe P.SourceSpan)]
276268parseCompletions s =
277269 fromJust $ join (rightToMaybe <$> parseMaybe (withResult completionParser) (valueFromText s))
278270
279−parseInfo :: Text -> [P.SourceSpan]
280−parseInfo s =
281− fromJust $ join (rightToMaybe <$> parseMaybe (withResult infoParser) (valueFromText s))
282−
283271parseTextResult :: Text -> Text
284272parseTextResult s =
285273 fromJust $ join (rightToMaybe <$> parseMaybe (withResult (withText "tr" pure)) (valueFromText s))
tests/Language/PureScript/Ide/MatcherSpec.hs+9−7
@@ -9,20 +9,21 @@ import qualified Language.PureScript as P
99import Language.PureScript.Ide.Integration
1010import Language.PureScript.Ide.Matcher
1111import Language.PureScript.Ide.Types
12+import Language.PureScript.Ide.Util
1213import Test.Hspec
1314
14−value :: Text -> IdeDeclaration
15−value s = IdeValue (P.Ident (toS s)) P.REmpty
15+value :: Text -> IdeDeclarationAnn
16+value s = withEmptyAnn (IdeValue (P.Ident (toS s)) P.REmpty)
1617
17−firstResult, secondResult, fiult :: Match IdeDeclaration
18+firstResult, secondResult, fiult :: Match IdeDeclarationAnn
1819firstResult = Match (P.moduleNameFromString "Match", value "firstResult")
1920secondResult = Match (P.moduleNameFromString "Match", value "secondResult")
2021fiult = Match (P.moduleNameFromString "Match", value "fiult")
2122
22−completions :: [Match IdeDeclaration]
23+completions :: [Match IdeDeclarationAnn]
2324completions = [firstResult, secondResult, fiult]
2425
25−runFlex :: Text -> [Match IdeDeclaration]
26+runFlex :: Text -> [Match IdeDeclarationAnn]
2627runFlex s = runMatcher (flexMatcher s) completions
2728
2829setup :: IO ()
@@ -43,5 +44,6 @@ spec = do
4344 cs <- getFlexCompletions ""
4445 cs `shouldBe` []
4546 it "matches on equality" $ do
46− cs <- getFlexCompletions "const"
47− cs `shouldBe` [("MatcherSpec", "const", "forall a b. a -> b -> a")]
47+ -- ignore any position information
48+ (m, i, t, _) : _ <- getFlexCompletions "const"
49+ (m, i, t) `shouldBe` ("MatcherSpec", "const", "forall a b. a -> b -> a")
tests/Language/PureScript/Ide/SourceFile/IntegrationSpec.hs+6−1
@@ -31,6 +31,11 @@ spec = beforeAll_ setup $
3131
3232testCase :: Text -> (Int, Int) -> IO ()
3333testCase s (x, y) = do
34− P.SourceSpan f (P.SourcePos l c) _ : _ <- Integration.getInfo s
34+ P.SourceSpan f (P.SourcePos l c) _ <- getLocation s
3535 toS f `shouldSatisfy` T.isSuffixOf "SourceFileSpec.purs"
3636 (l, c) `shouldBe` (x, y)
37+
38+getLocation :: Text -> IO P.SourceSpan
39+getLocation s = do
40+ (_, _, _, Just location) : _ <- Integration.getType s
41+ pure location
tests/Language/PureScript/Ide/SourceFileSpec.hs+6−2
@@ -13,7 +13,8 @@ span0 = P.SourceSpan "ModuleLevel" (P.SourcePos 0 0) (P.SourcePos 1 1)
1313span1 = P.SourceSpan "" (P.SourcePos 1 1) (P.SourcePos 2 2)
1414span2 = P.SourceSpan "" (P.SourcePos 2 2) (P.SourcePos 3 3)
1515
16−value1, synonym1, class1, class2, data1, data2, foreign1, foreign2, member1 :: P.Declaration
16+typeAnnotation1, value1, synonym1, class1, class2, data1, data2, foreign1, foreign2, member1 :: P.Declaration
17+typeAnnotation1 = P.TypeDeclaration (P.Ident "value1") P.REmpty
1718value1 = P.ValueDeclaration (P.Ident "value1") P.Public [] (Left [])
1819synonym1 = P.TypeSynonymDeclaration (P.ProperName "Synonym1") [] P.REmpty
1920class1 = P.TypeClassDeclaration (P.ProperName "Class1") [] [] []
@@ -26,7 +27,7 @@ foreign2 = P.ExternDataDeclaration (P.ProperName "Foreign2") P.Star
2627member1 = P.TypeDeclaration (P.Ident "member1") P.REmpty
2728
2829spec :: Spec
29−spec =
30+spec = do
3031 describe "Extracting Spans" $ do
3132 it "extracts a span for a value declaration" $
3233 extractSpans span0 (P.PositionedDeclaration span1 [] value1) `shouldBe` [(Left "value1", span1)]
@@ -44,3 +45,6 @@ spec =
4445 extractSpans span0 (P.PositionedDeclaration span1 [] foreign1) `shouldBe` [(Left "foreign1", span1)]
4546 it "extracts a span for a data foreign declaration" $
4647 extractSpans span0 (P.PositionedDeclaration span1 [] foreign2) `shouldBe` [(Right "Foreign2", span1)]
48+ describe "Type annotations" $ do
49+ it "extracts a type annotation" $
50+ extractTypeAnnotations [typeAnnotation1] `shouldBe` [(P.Ident "value1", P.REmpty)]