git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #2193 from kRITZCREEK/psc-ide-parse-modules
7174a75Phil Freeman
LICENSE+270−10
@@ -46,6 +46,7 @@ PureScript uses the following Haskell library packages. Their license files foll
46 bytestring-builder
46 bytestring-builder
47 case-insensitive
47 case-insensitive
48 cereal
48 cereal
49+ clock
49 conduit
50 conduit
50 conduit-extra
51 conduit-extra
51 connection
52 connection
@@ -56,8 +57,10 @@ PureScript uses the following Haskell library packages. Their license files foll
56 deepseq
57 deepseq
57 directory
58 directory
58 dlist
59 dlist
60+ easy-file
59 edit-distance
61 edit-distance
60 exceptions
62 exceptions
63+ fail
61 fast-logger
64 fast-logger
62 filepath
65 filepath
63 fsnotify
66 fsnotify
@@ -82,6 +85,7 @@ PureScript uses the following Haskell library packages. Their license files foll
82 network
85 network
83 network-uri
86 network-uri
84 old-locale
87 old-locale
88+ old-time
85 optparse-applicative
89 optparse-applicative
86 parallel
90 parallel
87 parsec
91 parsec
@@ -91,6 +95,7 @@ PureScript uses the following Haskell library packages. Their license files foll
91 pipes-http
95 pipes-http
92 primitive
96 primitive
93 process
97 process
98+ protolude
94 random
99 random
95 regex-base
100 regex-base
96 regex-tdfa
101 regex-tdfa
@@ -105,6 +110,7 @@ PureScript uses the following Haskell library packages. Their license files foll
105 stm
110 stm
106 stm-chans
111 stm-chans
107 streaming-commons
112 streaming-commons
113+ string-conv
108 syb
114 syb
109 tagged
115 tagged
110 template-haskell
116 template-haskell
@@ -117,6 +123,7 @@ PureScript uses the following Haskell library packages. Their license files foll
117 transformers-compat
123 transformers-compat
118 unix
124 unix
119 unix-compat
125 unix-compat
126+ unix-time
120 unordered-containers
127 unordered-containers
121 utf8-string
128 utf8-string
122 vector
129 vector
@@ -955,6 +962,41 @@ cereal LICENSE file:
955 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
962 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
956 POSSIBILITY OF SUCH DAMAGE.
963 POSSIBILITY OF SUCH DAMAGE.
957
964
965+clock LICENSE file:
966+
967+ Copyright (c) 2009-2012, Cetin Sert
968+ Copyright (c) 2010, Eugene Kirpichov
969+
970+ All rights reserved.
971+
972+ Redistribution and use in source and binary forms, with or without
973+ modification, are permitted provided that the following conditions are
974+ met:
975+
976+ * Redistributions of source code must retain the above copyright
977+ notice, this list of conditions and the following disclaimer.
978+
979+ * Redistributions in binary form must reproduce the above
980+ copyright notice, this list of conditions and the following
981+ disclaimer in the documentation and/or other materials provided
982+ with the distribution.
983+
984+ * The names of contributors may not be used to endorse or promote
985+ products derived from this software without specific prior
986+ written permission.
987+
988+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
989+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
990+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
991+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
992+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
993+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
994+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
995+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
996+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
997+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
998+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
999+
958conduit LICENSE file:
1000conduit LICENSE file:
959
1001
960 Copyright (c) 2012 Michael Snoyman, http://www.yesodweb.com/
1002 Copyright (c) 2012 Michael Snoyman, http://www.yesodweb.com/
@@ -1142,16 +1184,16 @@ data-default-class LICENSE file:
1142 may be used to endorse or promote products derived from this software
1184 may be used to endorse or promote products derived from this software
1143 without specific prior written permission.
1185 without specific prior written permission.
1144
1186
1145− THIS SOFTWARE IS PROVIDED BY LUKAS MAI AND CONTRIBUTORS "AS IS" AND ANY
1187+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1146− EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1188+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1147 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1189 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1148− DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
1190+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
1149− DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1191+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1150− (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1192+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1151− LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
1193+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1152− ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1194+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
1153− (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1195+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1154− SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1196+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1155
1197
1156deepseq LICENSE file:
1198deepseq LICENSE file:
1157
1199
@@ -1295,6 +1337,38 @@ dlist LICENSE file:
1295 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1337 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1296 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1338 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1297
1339
1340+easy-file LICENSE file:
1341+
1342+ Copyright (c) 2009, IIJ Innovation Institute Inc.
1343+ All rights reserved.
1344+
1345+ Redistribution and use in source and binary forms, with or without
1346+ modification, are permitted provided that the following conditions
1347+ are met:
1348+
1349+ * Redistributions of source code must retain the above copyright
1350+ notice, this list of conditions and the following disclaimer.
1351+ * Redistributions in binary form must reproduce the above copyright
1352+ notice, this list of conditions and the following disclaimer in
1353+ the documentation and/or other materials provided with the
1354+ distribution.
1355+ * Neither the name of the copyright holders nor the names of its
1356+ contributors may be used to endorse or promote products derived
1357+ from this software without specific prior written permission.
1358+
1359+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1360+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1361+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1362+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1363+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1364+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
1365+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1366+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1367+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1368+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
1369+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1370+ POSSIBILITY OF SUCH DAMAGE.
1371+
1298edit-distance LICENSE file:
1372edit-distance LICENSE file:
1299
1373
1300 Copyright (c) 2008-2013 Maximilian Bolingbroke
1374 Copyright (c) 2008-2013 Maximilian Bolingbroke
@@ -1354,6 +1428,39 @@ exceptions LICENSE file:
1354 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1428 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1355 POSSIBILITY OF SUCH DAMAGE.
1429 POSSIBILITY OF SUCH DAMAGE.
1356
1430
1431+fail LICENSE file:
1432+
1433+ Copyright (c) 2015, David Luposchainsky & Herbert Valerio Riedel
1434+
1435+ All rights reserved.
1436+
1437+ Redistribution and use in source and binary forms, with or without
1438+ modification, are permitted provided that the following conditions are met:
1439+
1440+ * Redistributions of source code must retain the above copyright
1441+ notice, this list of conditions and the following disclaimer.
1442+
1443+ * Redistributions in binary form must reproduce the above
1444+ copyright notice, this list of conditions and the following
1445+ disclaimer in the documentation and/or other materials provided
1446+ with the distribution.
1447+
1448+ * Neither the name of Herbert Valerio Riedel nor the names of other
1449+ contributors may be used to endorse or promote products derived
1450+ from this software without specific prior written permission.
1451+
1452+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1453+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1454+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1455+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1456+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1457+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1458+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1459+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1460+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1461+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1462+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1463+
1357fast-logger LICENSE file:
1464fast-logger LICENSE file:
1358
1465
1359 Copyright (c) 2009, IIJ Innovation Institute Inc.
1466 Copyright (c) 2009, IIJ Innovation Institute Inc.
@@ -2122,6 +2229,72 @@ old-locale LICENSE file:
2122
2229
2123 -----------------------------------------------------------------------------
2230 -----------------------------------------------------------------------------
2124
2231
2232+old-time LICENSE file:
2233+
2234+ This library (libraries/base) is derived from code from two
2235+ sources:
2236+
2237+ * Code from the GHC project which is largely (c) The University of
2238+ Glasgow, and distributable under a BSD-style license (see below),
2239+
2240+ * Code from the Haskell 98 Report which is (c) Simon Peyton Jones
2241+ and freely redistributable (but see the full license for
2242+ restrictions).
2243+
2244+ The full text of these licenses is reproduced below. Both of the
2245+ licenses are BSD-style or compatible.
2246+
2247+ -----------------------------------------------------------------------------
2248+
2249+ The Glasgow Haskell Compiler License
2250+
2251+ Copyright 2004, The University Court of the University of Glasgow.
2252+ All rights reserved.
2253+
2254+ Redistribution and use in source and binary forms, with or without
2255+ modification, are permitted provided that the following conditions are met:
2256+
2257+ - Redistributions of source code must retain the above copyright notice,
2258+ this list of conditions and the following disclaimer.
2259+
2260+ - Redistributions in binary form must reproduce the above copyright notice,
2261+ this list of conditions and the following disclaimer in the documentation
2262+ and/or other materials provided with the distribution.
2263+
2264+ - Neither name of the University nor the names of its contributors may be
2265+ used to endorse or promote products derived from this software without
2266+ specific prior written permission.
2267+
2268+ THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
2269+ GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2270+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2271+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2272+ UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
2273+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2274+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2275+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2276+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2277+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2278+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2279+ DAMAGE.
2280+
2281+ -----------------------------------------------------------------------------
2282+
2283+ Code derived from the document "Report on the Programming Language
2284+ Haskell 98", is distributed under the following license:
2285+
2286+ Copyright (c) 2002 Simon Peyton Jones
2287+
2288+ The authors intend this Report to belong to the entire Haskell
2289+ community, and so we grant permission to copy and distribute it for
2290+ any purpose, provided that it is reproduced in its entirety,
2291+ including this Notice. Modified versions of this Report may also be
2292+ copied and distributed for any purpose, provided that the modified
2293+ version is clearly presented as such, and that it does not claim to
2294+ be a definition of the Haskell 98 Language.
2295+
2296+ -----------------------------------------------------------------------------
2297+
2125optparse-applicative LICENSE file:
2298optparse-applicative LICENSE file:
2126
2299
2127 Copyright (c) 2012, Paolo Capriotti
2300 Copyright (c) 2012, Paolo Capriotti
@@ -2276,7 +2449,7 @@ pem LICENSE file:
2276
2449
2277pipes LICENSE file:
2450pipes LICENSE file:
2278
2451
2279− Copyright (c) 2012-2014 Gabriel Gonzalez
2452+ Copyright (c) 2012-2016 Gabriel Gonzalez
2280 All rights reserved.
2453 All rights reserved.
2281
2454
2282 Redistribution and use in source and binary forms, with or without modification,
2455 Redistribution and use in source and binary forms, with or without modification,
@@ -2427,6 +2600,28 @@ process LICENSE file:
2427
2600
2428 -----------------------------------------------------------------------------
2601 -----------------------------------------------------------------------------
2429
2602
2603+protolude LICENSE file:
2604+
2605+ Copyright (c) 2016, Stephen Diehl
2606+
2607+ Permission is hereby granted, free of charge, to any person obtaining a copy
2608+ of this software and associated documentation files (the "Software"), to
2609+ deal in the Software without restriction, including without limitation the
2610+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2611+ sell copies of the Software, and to permit persons to whom the Software is
2612+ furnished to do so, subject to the following conditions:
2613+
2614+ The above copyright notice and this permission notice shall be included in
2615+ all copies or substantial portions of the Software.
2616+
2617+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2618+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2619+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2620+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2621+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2622+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2623+ IN THE SOFTWARE.
2624+
2430random LICENSE file:
2625random LICENSE file:
2431
2626
2432 This library (libraries/base) is derived from code from two
2627 This library (libraries/base) is derived from code from two
@@ -2873,6 +3068,39 @@ streaming-commons LICENSE file:
2873 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3068 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2874 SOFTWARE.
3069 SOFTWARE.
2875
3070
3071+string-conv LICENSE file:
3072+
3073+ Copyright (c) 2012, Ozgun Ataman
3074+
3075+ All rights reserved.
3076+
3077+ Redistribution and use in source and binary forms, with or without
3078+ modification, are permitted provided that the following conditions are met:
3079+
3080+ * Redistributions of source code must retain the above copyright
3081+ notice, this list of conditions and the following disclaimer.
3082+
3083+ * Redistributions in binary form must reproduce the above
3084+ copyright notice, this list of conditions and the following
3085+ disclaimer in the documentation and/or other materials provided
3086+ with the distribution.
3087+
3088+ * Neither the name of Ozgun Ataman nor the names of other
3089+ contributors may be used to endorse or promote products derived
3090+ from this software without specific prior written permission.
3091+
3092+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3093+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3094+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3095+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3096+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3097+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3098+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3099+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3100+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3101+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3102+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3103+
2876syb LICENSE file:
3104syb LICENSE file:
2877
3105
2878 This library (libraries/syb) is derived from code from several
3106 This library (libraries/syb) is derived from code from several
@@ -3289,6 +3517,38 @@ unix-compat LICENSE file:
3289 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3517 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3290 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3518 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3291
3519
3520+unix-time LICENSE file:
3521+
3522+ Copyright (c) 2009, IIJ Innovation Institute Inc.
3523+ All rights reserved.
3524+
3525+ Redistribution and use in source and binary forms, with or without
3526+ modification, are permitted provided that the following conditions
3527+ are met:
3528+
3529+ * Redistributions of source code must retain the above copyright
3530+ notice, this list of conditions and the following disclaimer.
3531+ * Redistributions in binary form must reproduce the above copyright
3532+ notice, this list of conditions and the following disclaimer in
3533+ the documentation and/or other materials provided with the
3534+ distribution.
3535+ * Neither the name of the copyright holders nor the names of its
3536+ contributors may be used to endorse or promote products derived
3537+ from this software without specific prior written permission.
3538+
3539+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3540+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3541+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
3542+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
3543+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
3544+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
3545+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3546+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
3547+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3548+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3549+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3550+ POSSIBILITY OF SUCH DAMAGE.
3551+
3292unordered-containers LICENSE file:
3552unordered-containers LICENSE file:
3293
3553
3294 Copyright (c) 2010, Johan Tibell
3554 Copyright (c) 2010, Johan Tibell
psc-ide-server/Main.hs+29−38
@@ -17,21 +17,14 @@
17{-# LANGUAGE OverloadedStrings #-}
17{-# LANGUAGE OverloadedStrings #-}
18{-# LANGUAGE PackageImports #-}
18{-# LANGUAGE PackageImports #-}
19{-# LANGUAGE TemplateHaskell #-}
19{-# LANGUAGE TemplateHaskell #-}
20+{-# LANGUAGE NoImplicitPrelude #-}
20
21
21module Main where
22module Main where
22
23
23−import Prelude ()
24+import Protolude
24−import Prelude.Compat
25
25
26−import Control.Concurrent (forkFinally)
27import Control.Concurrent.STM
26import Control.Concurrent.STM
28−import Control.Exception (bracketOnError, catchJust)
29−import Control.Monad
30−import Control.Monad.Error.Class
31import "monad-logger" Control.Monad.Logger
27import "monad-logger" Control.Monad.Logger
32−import Control.Monad.Reader
33−import Control.Monad.Trans.Except
34−import qualified Data.Text as T
35import qualified Data.Text.IO as T
28import qualified Data.Text.IO as T
36import Data.Version (showVersion)
29import Data.Version (showVersion)
37import Language.PureScript.Ide
30import Language.PureScript.Ide
@@ -43,19 +36,16 @@ import Network hiding (socketPort, accept)
43import Network.BSD (getProtocolNumber)
36import Network.BSD (getProtocolNumber)
44import Network.Socket hiding (PortNumber, Type,
37import Network.Socket hiding (PortNumber, Type,
45 sClose)
38 sClose)
46−import Options.Applicative
39+import Options.Applicative hiding ((<>))
47import System.Directory
40import System.Directory
48import System.FilePath
41import System.FilePath
49−import System.IO
42+import System.IO hiding (putStrLn, print)
50import System.IO.Error (isEOFError)
43import System.IO.Error (isEOFError)
51
44
52import qualified Paths_purescript as Paths
45import qualified Paths_purescript as Paths
53
46
54−-- "Borrowed" from the Idris Compiler
55−-- Copied from upstream impl of listenOn
56−-- bound to localhost interface instead of iNADDR_ANY
57−listenOnLocalhost :: PortID -> IO Socket
47+listenOnLocalhost :: PortNumber -> IO Socket
58−listenOnLocalhost (PortNumber port) = do
48+listenOnLocalhost port = do
59 proto <- getProtocolNumber "tcp"
49 proto <- getProtocolNumber "tcp"
60 localhost <- inet_addr "127.0.0.1"
50 localhost <- inet_addr "127.0.0.1"
61 bracketOnError
51 bracketOnError
@@ -66,59 +56,60 @@ listenOnLocalhost (PortNumber port) = do
66 bindSocket sock (SockAddrInet port localhost)
56 bindSocket sock (SockAddrInet port localhost)
67 listen sock maxListenQueue
57 listen sock maxListenQueue
68 pure sock)
58 pure sock)
69−listenOnLocalhost _ = error "Wrong Porttype"
70
59
71data Options = Options
60data Options = Options
72 { optionsDirectory :: Maybe FilePath
61 { optionsDirectory :: Maybe FilePath
62+ , optionsGlobs :: [FilePath]
73 , optionsOutputPath :: FilePath
63 , optionsOutputPath :: FilePath
74− , optionsPort :: PortID
64+ , optionsPort :: PortNumber
75 , optionsNoWatch :: Bool
65 , optionsNoWatch :: Bool
76 , optionsDebug :: Bool
66 , optionsDebug :: Bool
77 }
67 }
78
68
79main :: IO ()
69main :: IO ()
80main = do
70main = do
81− Options dir outputPath port noWatch debug <- execParser opts
71+ Options dir globs outputPath port noWatch debug <- execParser opts
82 maybe (pure ()) setCurrentDirectory dir
72 maybe (pure ()) setCurrentDirectory dir
83 serverState <- newTVarIO emptyPscIdeState
73 serverState <- newTVarIO emptyPscIdeState
74+ ideState <- newTVarIO emptyIdeState
84 cwd <- getCurrentDirectory
75 cwd <- getCurrentDirectory
85 let fullOutputPath = cwd </> outputPath
76 let fullOutputPath = cwd </> outputPath
86
77
87− doesDirectoryExist fullOutputPath
78+ unlessM (doesDirectoryExist fullOutputPath) $ do
88− >>= flip unless
89− (do putStrLn ("Your output directory didn't exist. I'll create it at: " <> fullOutputPath)
79+ putStrLn ("Your output directory didn't exist. I'll create it at: " <> fullOutputPath)
90− createDirectory fullOutputPath
80+ createDirectory fullOutputPath
91− putStrLn "This usually means you didn't compile your project yet."
81+ putText "This usually means you didn't compile your project yet."
92− putStrLn "psc-ide needs you to compile your project (for example by running pulp build)")
82+ putText "psc-ide needs you to compile your project (for example by running pulp build)"
93
83
94 unless noWatch $
84 unless noWatch $
95− void (forkFinally (watcher serverState fullOutputPath) print)
85+ void (forkFinally (watcher ideState fullOutputPath) print)
96
86
97− let conf = Configuration {confDebug = debug, confOutputPath = outputPath}
87+ let conf = Configuration {confDebug = debug, confOutputPath = outputPath, confGlobs = globs}
98− env = PscIdeEnvironment {envStateVar = serverState, envConfiguration = conf}
88+ env = IdeEnvironment {envStateVar = serverState, ideStateVar = ideState, ideConfiguration = conf}
99 startServer port env
89 startServer port env
100 where
90 where
101 parser =
91 parser =
102 Options
92 Options
103− <$> optional (strOption (long "directory" <> short 'd'))
93+ <$> optional (strOption (long "directory" `mappend` short 'd'))
94+ <*> many (argument str (metavar "Source GLOBS..."))
104− <*> strOption (long "output-directory" <> value "output/")
95+ <*> strOption (long "output-directory" `mappend` value "output/")
105− <*> (PortNumber . fromIntegral <$>
96+ <*> (fromIntegral <$>
106− option auto (long "port" <> short 'p' <> value (4242 :: Integer)))
97+ option auto (long "port" `mappend` short 'p' `mappend` value (4242 :: Integer)))
107 <*> switch (long "no-watch")
98 <*> switch (long "no-watch")
108 <*> switch (long "debug")
99 <*> switch (long "debug")
109 opts = info (version <*> helper <*> parser) mempty
100 opts = info (version <*> helper <*> parser) mempty
110 version = abortOption
101 version = abortOption
111 (InfoMsg (showVersion Paths.version))
102 (InfoMsg (showVersion Paths.version))
112− (long "version" <> help "Show the version number")
103+ (long "version" `mappend` help "Show the version number")
113
104
114−startServer :: PortID -> PscIdeEnvironment -> IO ()
105+startServer :: PortNumber -> IdeEnvironment -> IO ()
115startServer port env = withSocketsDo $ do
106startServer port env = withSocketsDo $ do
116 sock <- listenOnLocalhost port
107 sock <- listenOnLocalhost port
117 runLogger (runReaderT (forever (loop sock)) env)
108 runLogger (runReaderT (forever (loop sock)) env)
118 where
109 where
119− runLogger = runStdoutLoggingT . filterLogger (\_ _ -> confDebug (envConfiguration env))
110+ runLogger = runStdoutLoggingT . filterLogger (\_ _ -> confDebug (ideConfiguration env))
120
111
121− loop :: (PscIde m, MonadLogger m) => Socket -> m ()
112+ loop :: (Ide m, MonadLogger m) => Socket -> m ()
122 loop sock = do
113 loop sock = do
123 accepted <- runExceptT $ acceptCommand sock
114 accepted <- runExceptT $ acceptCommand sock
124 case accepted of
115 case accepted of
@@ -141,8 +132,8 @@ startServer port env = withSocketsDo $ do
141 liftIO (hClose h)
132 liftIO (hClose h)
142
133
143
134
144−acceptCommand :: (MonadIO m, MonadLogger m, MonadError T.Text m)
135+acceptCommand :: (MonadIO m, MonadLogger m, MonadError Text m)
145− => Socket -> m (T.Text, Handle)
136+ => Socket -> m (Text, Handle)
146acceptCommand sock = do
137acceptCommand sock = do
147 h <- acceptConnection
138 h <- acceptConnection
148 $(logDebug) "Accepted a connection"
139 $(logDebug) "Accepted a connection"
psc-ide-server/PROTOCOL.md+3−7
@@ -14,24 +14,20 @@ to detect all the compiled modules in your project and load them.
14
14
15**Params:**
15**Params:**
16 - `modules :: (optional) [ModuleName]`: A list of modules to load.
16 - `modules :: (optional) [ModuleName]`: A list of modules to load.
17− psc-ide-server will try to parse all the declarations in these modules
17+ psc-ide-server will try to parse all the declarations in these modules
18− - `dependencies :: (optional) [ModuleName]`: A list of modules to load
19− including their dependencies. In contrast to the `module` field, all the
20− imports in these Modules will also be loaded.
21
18
22```json
19```json
23{
20{
24 "command": "load",
21 "command": "load",
25 "params": (optional) {
22 "params": (optional) {
26− "modules": (optional)["Module.Name1", "Module.Name2"],
23+ "modules": (optional)["Module.Name1", "Module.Name2"]
27− "dependencies": (optional)["Module.Name3"]
28 }
24 }
29}
25}
30```
26```
31
27
32**Result:**
28**Result:**
33
29
34−The Load Command returns a string.
30+The Load Command returns a string with a summary about the loading process.
35
31
36### Type
32### Type
37The `type` command looks up the type for a given identifier.
33The `type` command looks up the type for a given identifier.
psc-ide-server/README.md+4−1
@@ -10,7 +10,10 @@ A tool which provides editor support for the PureScript programming language.
10* Vim integration is available here: https://github.com/FrigoEU/psc-ide-vim.
10* Vim integration is available here: https://github.com/FrigoEU/psc-ide-vim.
11
11
12## Running the Server
12## Running the Server
13+
13−Start the server by running the `psc-ide-server` executable.
14+Start the server by running the `psc-ide-server [SOURCEGLOBS]` executable, where
15+`SOURCEGLOBS` are (optional) globs that match your PureScript sourcefiles.
16+
14It supports the following options:
17It supports the following options:
15
18
16- `-p / --port` specify a port. Defaults to 4242
19- `-p / --port` specify a port. Defaults to 4242
purescript.cabal+15−11
@@ -106,6 +106,7 @@ library
106 boxes >= 0.1.4 && < 0.2.0,
106 boxes >= 0.1.4 && < 0.2.0,
107 bytestring -any,
107 bytestring -any,
108 containers -any,
108 containers -any,
109+ clock -any,
109 directory >= 1.2,
110 directory >= 1.2,
110 dlist -any,
111 dlist -any,
111 edit-distance -any,
112 edit-distance -any,
@@ -125,6 +126,7 @@ library
125 pipes >= 4.0.0 && < 4.3.0,
126 pipes >= 4.0.0 && < 4.3.0,
126 pipes-http -any,
127 pipes-http -any,
127 process >= 1.2.0 && < 1.5,
128 process >= 1.2.0 && < 1.5,
129+ protolude >= 0.1.5,
128 regex-tdfa -any,
130 regex-tdfa -any,
129 safe >= 0.3.9 && < 0.4,
131 safe >= 0.3.9 && < 0.4,
130 semigroups >= 0.16.2 && < 0.19,
132 semigroups >= 0.16.2 && < 0.19,
@@ -251,22 +253,23 @@ library
251 Language.PureScript.Publish.BoxesHelpers
253 Language.PureScript.Publish.BoxesHelpers
252
254
253 Language.PureScript.Ide
255 Language.PureScript.Ide
256+ Language.PureScript.Ide.CaseSplit
254 Language.PureScript.Ide.Command
257 Language.PureScript.Ide.Command
258+ Language.PureScript.Ide.Completion
259+ Language.PureScript.Ide.Conversions
255 Language.PureScript.Ide.Externs
260 Language.PureScript.Ide.Externs
256 Language.PureScript.Ide.Error
261 Language.PureScript.Ide.Error
257− Language.PureScript.Ide.Pursuit
262+ Language.PureScript.Ide.Imports
258− Language.PureScript.Ide.Completion
259− Language.PureScript.Ide.Matcher
260 Language.PureScript.Ide.Filter
263 Language.PureScript.Ide.Filter
261− Language.PureScript.Ide.Types
264+ Language.PureScript.Ide.Matcher
262− Language.PureScript.Ide.State
265+ Language.PureScript.Ide.Pursuit
263− Language.PureScript.Ide.CaseSplit
266+ Language.PureScript.Ide.Rebuild
264− Language.PureScript.Ide.SourceFile
265− Language.PureScript.Ide.Watcher
266 Language.PureScript.Ide.Reexports
267 Language.PureScript.Ide.Reexports
267− Language.PureScript.Ide.Imports
268+ Language.PureScript.Ide.SourceFile
269+ Language.PureScript.Ide.State
270+ Language.PureScript.Ide.Types
268 Language.PureScript.Ide.Util
271 Language.PureScript.Ide.Util
269− Language.PureScript.Ide.Rebuild
272+ Language.PureScript.Ide.Watcher
270
273
271 Language.PureScript.Interactive
274 Language.PureScript.Interactive
272 Language.PureScript.Interactive.Types
275 Language.PureScript.Interactive.Types
@@ -433,6 +436,7 @@ executable psc-ide-server
433 mtl -any,
436 mtl -any,
434 network -any,
437 network -any,
435 optparse-applicative >= 0.12.1,
438 optparse-applicative >= 0.12.1,
439+ protolude >= 0.1.5,
436 stm -any,
440 stm -any,
437 text -any,
441 text -any,
438 transformers -any,
442 transformers -any,
@@ -473,6 +477,7 @@ test-suite tests
473 optparse-applicative -any,
477 optparse-applicative -any,
474 parsec -any,
478 parsec -any,
475 process -any,
479 process -any,
480+ protolude >= 0.1.5,
476 silently -any,
481 silently -any,
477 stm -any,
482 stm -any,
478 text -any,
483 text -any,
@@ -498,6 +503,5 @@ test-suite tests
498 Language.PureScript.Ide.MatcherSpec
503 Language.PureScript.Ide.MatcherSpec
499 Language.PureScript.Ide.RebuildSpec
504 Language.PureScript.Ide.RebuildSpec
500 Language.PureScript.Ide.ReexportsSpec
505 Language.PureScript.Ide.ReexportsSpec
501− Language.PureScript.IdeSpec
502 buildable: True
506 buildable: True
503 hs-source-dirs: tests
507 hs-source-dirs: tests
src/Language/PureScript/Ide.hs+138−177
@@ -18,24 +18,11 @@
18
18
19module Language.PureScript.Ide
19module Language.PureScript.Ide
20 ( handleCommand
20 ( handleCommand
21− -- for tests
22− , printModules
23 ) where
21 ) where
24
22
25−import Prelude ()
23+import Protolude
26−import Prelude.Compat
27
24
28−import Control.Monad (unless)
29−import Control.Monad.Error.Class
30−import Control.Monad.IO.Class
31import "monad-logger" Control.Monad.Logger
25import "monad-logger" Control.Monad.Logger
32−import Control.Monad.Reader.Class
33−import Data.Foldable
34−import qualified Data.Map.Lazy as M
35−import Data.Maybe (catMaybes, mapMaybe)
36−import Data.Monoid
37−import Data.Text (Text)
38−import qualified Data.Text as T
39import qualified Language.PureScript as P
26import qualified Language.PureScript as P
40import qualified Language.PureScript.Ide.CaseSplit as CS
27import qualified Language.PureScript.Ide.CaseSplit as CS
41import Language.PureScript.Ide.Command
28import Language.PureScript.Ide.Command
@@ -47,199 +34,173 @@ import Language.PureScript.Ide.Imports hiding (Import)
47import Language.PureScript.Ide.Matcher
34import Language.PureScript.Ide.Matcher
48import Language.PureScript.Ide.Pursuit
35import Language.PureScript.Ide.Pursuit
49import Language.PureScript.Ide.Rebuild
36import Language.PureScript.Ide.Rebuild
50−import Language.PureScript.Ide.Reexports
51import Language.PureScript.Ide.SourceFile
37import Language.PureScript.Ide.SourceFile
52import Language.PureScript.Ide.State
38import Language.PureScript.Ide.State
53import Language.PureScript.Ide.Types
39import Language.PureScript.Ide.Types
54import Language.PureScript.Ide.Util
40import Language.PureScript.Ide.Util
55import System.Directory
41import System.Directory
56−import System.Exit
57import System.FilePath
42import System.FilePath
43+import System.FilePath.Glob
58
44
59−handleCommand :: (PscIde m, MonadLogger m, MonadError PscIdeError m) =>
45+handleCommand :: (Ide m, MonadLogger m, MonadError PscIdeError m) =>
60 Command -> m Success
46 Command -> m Success
61−handleCommand (Load [] []) = loadAllModules
47+handleCommand c = case c of
48+ Load [] ->
49+ findAvailableExterns >>= loadModules
62−handleCommand (Load modules deps) =
50+ Load modules ->
63− loadModulesAndDeps modules deps
51+ loadModules modules
64−handleCommand (Type search filters currentModule) =
52+ Type search filters currentModule ->
65− findType search filters currentModule
53+ findType search filters currentModule
66−handleCommand (Complete filters matcher currentModule) =
54+ Complete filters matcher currentModule ->
67− findCompletions filters matcher currentModule
55+ findCompletions filters matcher currentModule
68−handleCommand (Pursuit query Package) =
56+ Pursuit query Package ->
69− findPursuitPackages query
57+ findPursuitPackages query
70−handleCommand (Pursuit query Identifier) =
58+ Pursuit query Identifier ->
71− findPursuitCompletions query
59+ findPursuitCompletions query
72−handleCommand (List LoadedModules) =
60+ List LoadedModules ->
73− printModules
61+ printModules
74−handleCommand (List AvailableModules) =
62+ List AvailableModules ->
75− listAvailableModules
63+ listAvailableModules
76−handleCommand (List (Imports fp)) =
64+ List (Imports fp) ->
77− importsForFile fp
65+ ImportList <$> getImportsForFile fp
78−handleCommand (CaseSplit l b e wca t) =
66+ CaseSplit l b e wca t ->
79− caseSplit l b e wca t
67+ caseSplit l b e wca t
80−handleCommand (AddClause l wca) =
68+ AddClause l wca ->
81− pure $ addClause l wca
69+ addClause l wca
82−handleCommand (Import fp outfp _ (AddImplicitImport mn)) = do
70+ Import fp outfp _ (AddImplicitImport mn) -> do
83− rs <- addImplicitImport fp mn
71+ rs <- addImplicitImport fp mn
84− answerRequest outfp rs
72+ answerRequest outfp rs
85−handleCommand (Import fp outfp filters (AddImportForIdentifier ident)) = do
73+ Import fp outfp filters (AddImportForIdentifier ident) -> do
86− rs <- addImportForIdentifier fp ident filters
74+ rs <- addImportForIdentifier fp ident filters
87− case rs of
75+ case rs of
88− Right rs' -> answerRequest outfp rs'
76+ Right rs' -> answerRequest outfp rs'
77+ Left question ->
89− Left question -> pure $ CompletionResult (mapMaybe completionFromMatch question)
78+ pure (CompletionResult (map completionFromMatch question))
90−handleCommand (Rebuild file) =
79+ Rebuild file ->
91− rebuildFile file
80+ rebuildFile file
92−handleCommand Cwd =
81+ Cwd ->
93− TextResult . T.pack <$> liftIO getCurrentDirectory
82+ TextResult . toS <$> liftIO getCurrentDirectory
83+ Reset ->
94−handleCommand Reset = resetPscIdeState *> pure (TextResult "State has been reset.")
84+ resetIdeState $> TextResult "State has been reset."
85+ Quit ->
95−handleCommand Quit = liftIO exitSuccess
86+ liftIO exitSuccess
96−
87+
97−findCompletions :: (PscIde m) =>
88+findCompletions :: Ide m =>
98 [Filter] -> Matcher -> Maybe P.ModuleName -> m Success
89 [Filter] -> Matcher -> Maybe P.ModuleName -> m Success
99findCompletions filters matcher currentModule = do
90findCompletions filters matcher currentModule = do
100− modules <- getAllModulesWithReexportsAndCache currentModule
91+ modules <- getAllModules2 currentModule
101− pure . CompletionResult . mapMaybe completionFromMatch . getCompletions filters matcher $ modules
92+ pure . CompletionResult . map completionFromMatch . getCompletions filters matcher $ modules
102
93
103−findType :: (PscIde m) =>
94+findType :: Ide m =>
104− DeclIdent -> [Filter] -> Maybe P.ModuleName -> m Success
95+ Text -> [Filter] -> Maybe P.ModuleName -> m Success
105findType search filters currentModule = do
96findType search filters currentModule = do
106− modules <- getAllModulesWithReexportsAndCache currentModule
97+ modules <- getAllModules2 currentModule
107− pure . CompletionResult . mapMaybe completionFromMatch . getExactMatches search filters $ modules
98+ pure . CompletionResult . map completionFromMatch . getExactMatches search filters $ modules
108
99
109−findPursuitCompletions :: (MonadIO m) =>
100+findPursuitCompletions :: MonadIO m =>
110 PursuitQuery -> m Success
101 PursuitQuery -> m Success
111findPursuitCompletions (PursuitQuery q) =
102findPursuitCompletions (PursuitQuery q) =
112 PursuitResult <$> liftIO (searchPursuitForDeclarations q)
103 PursuitResult <$> liftIO (searchPursuitForDeclarations q)
113
104
114−findPursuitPackages :: (MonadIO m) =>
105+findPursuitPackages :: MonadIO m =>
115 PursuitQuery -> m Success
106 PursuitQuery -> m Success
116findPursuitPackages (PursuitQuery q) =
107findPursuitPackages (PursuitQuery q) =
117 PursuitResult <$> liftIO (findPackagesForModuleIdent q)
108 PursuitResult <$> liftIO (findPackagesForModuleIdent q)
118
109
119−loadExtern :: (PscIde m, MonadLogger m, MonadError PscIdeError m) =>
110+printModules :: Ide m => m Success
120− FilePath -> m ()
111+printModules = ModuleList . map runModuleNameT <$> getLoadedModulenames
121−loadExtern fp = do
122− m <- readExternFile fp
123− insertModule m
124
112
125−printModules :: (PscIde m) => m Success
113+outputDirectory :: Ide m => m FilePath
126−printModules = printModules' . pscIdeStateModules <$> getPscIdeState
114+outputDirectory = do
127−
115+ outputPath <- confOutputPath . ideConfiguration <$> ask
128−printModules' :: M.Map ModuleIdent [ExternDecl] -> Success
116+ cwd <- liftIO getCurrentDirectory
129−printModules' = ModuleList . M.keys
117+ pure (cwd </> outputPath)
130
118
131−listAvailableModules :: PscIde m => m Success
119+listAvailableModules :: Ide m => m Success
132listAvailableModules = do
120listAvailableModules = do
133− outputPath <- confOutputPath . envConfiguration <$> ask
121+ oDir <- outputDirectory
134 liftIO $ do
122 liftIO $ do
135− cwd <- getCurrentDirectory
136− dirs <- getDirectoryContents (cwd </> outputPath)
123+ contents <- getDirectoryContents oDir
137− return (ModuleList (listAvailableModules' dirs))
138−
139−listAvailableModules' :: [FilePath] -> [Text]
140−listAvailableModules' dirs =
141− let cleanedModules = filter (`notElem` [".", ".."]) dirs
124+ let cleaned = filter (`notElem` [".", ".."]) contents
142− in map T.pack cleanedModules
125+ return (ModuleList (map toS cleaned))
143
126
144−caseSplit :: (PscIde m, MonadError PscIdeError m) =>
127+caseSplit :: (Ide m, MonadError PscIdeError m) =>
145 Text -> Int -> Int -> CS.WildcardAnnotations -> Text -> m Success
128 Text -> Int -> Int -> CS.WildcardAnnotations -> Text -> m Success
146caseSplit l b e csa t = do
129caseSplit l b e csa t = do
147 patterns <- CS.makePattern l b e csa <$> CS.caseSplit t
130 patterns <- CS.makePattern l b e csa <$> CS.caseSplit t
148 pure (MultilineTextResult patterns)
131 pure (MultilineTextResult patterns)
149
132
133+addClause
134+ :: (MonadError PscIdeError m)
135+ => Text
150−addClause :: Text -> CS.WildcardAnnotations -> Success
136+ -> CS.WildcardAnnotations
137+ -> m Success
151−addClause t wca = MultilineTextResult (CS.addClause t wca)
138+addClause t wca = MultilineTextResult <$> CS.addClause t wca
152−
139+
153−importsForFile :: (MonadIO m, MonadError PscIdeError m) =>
140+-- | Finds all the externs.json files inside the output folder and returns the
154− FilePath -> m Success
141+-- corresponding Modulenames
155−importsForFile fp = do
156− imports <- getImportsForFile fp
157− pure (ImportList imports)
158−
159−-- | The first argument is a set of modules to load. The second argument
160−-- denotes modules for which to load dependencies
161−loadModulesAndDeps :: (PscIde m, MonadLogger m, MonadError PscIdeError m) =>
162− [ModuleIdent] -> [ModuleIdent] -> m Success
163−loadModulesAndDeps mods deps = do
164− r1 <- mapM loadModule (mods ++ deps)
165− r2 <- mapM loadModuleDependencies deps
166− let moduleResults = T.concat r1
167− let dependencyResults = T.concat r2
168− pure (TextResult (moduleResults <> ", " <> dependencyResults))
169−
170−loadModuleDependencies ::(PscIde m, MonadLogger m, MonadError PscIdeError m) =>
171− ModuleIdent -> m Text
172−loadModuleDependencies moduleName = do
173− m <- getModule moduleName
174− case getDependenciesForModule <$> m of
175− Just deps -> do
176− mapM_ loadModule deps
177− -- We need to load the modules, that get reexported from the dependencies
178− depModules <- catMaybes <$> mapM getModule deps
179− -- What to do with errors here? This basically means a reexported dependency
180− -- doesn't exist in the output/ folder
181− traverse_ loadReexports depModules
182− pure ("Dependencies for " <> moduleName <> " loaded.")
183− Nothing -> throwError (ModuleNotFound moduleName)
184−
185−loadReexports :: (PscIde m, MonadLogger m, MonadError PscIdeError m) =>
142+findAvailableExterns :: (Ide m, MonadError PscIdeError m) => m [P.ModuleName]
186− Module -> m [ModuleIdent]
143+findAvailableExterns = do
187−loadReexports m = case getReexports m of
144+ oDir <- outputDirectory
188− [] -> pure []
189− exportDeps -> do
190− -- I'm fine with this crashing on a failed pattern match.
191− -- If this ever fails I'll need to look at GADTs
192− let reexports = map (\(Export mn) -> mn) exportDeps
193− $(logDebug) ("Loading reexports for module: " <> fst m <>
194− " reexports: " <> T.intercalate ", " reexports)
195− traverse_ loadModule reexports
196− exportDepsModules <- catMaybes <$> traverse getModule reexports
197− exportDepDeps <- traverse loadReexports exportDepsModules
198− return $ concat exportDepDeps
199−
200−getDependenciesForModule :: Module -> [ModuleIdent]
201−getDependenciesForModule (_, decls) = mapMaybe getDependencyName decls
202− where getDependencyName (Dependency dependencyName _ _) = Just dependencyName
203− getDependencyName _ = Nothing
204−
205−loadModule :: (PscIde m, MonadLogger m, MonadError PscIdeError m) =>
206− ModuleIdent -> m Text
207−loadModule "Prim" = pure "Prim won't be loaded"
208−loadModule mn = do
209− path <- filePathFromModule mn
210− loadExtern path
211− $(logDebug) ("Loaded extern file at: " <> T.pack path)
212− pure ("Loaded extern file at: " <> T.pack path)
213−
214−loadAllModules :: (PscIde m, MonadLogger m, MonadError PscIdeError m) => m Success
215−loadAllModules = do
216− outputPath <- confOutputPath . envConfiguration <$> ask
217− cwd <- liftIO getCurrentDirectory
218− let outputDirectory = cwd </> outputPath
219− liftIO (doesDirectoryExist outputDirectory)
145+ unlessM (liftIO (doesDirectoryExist oDir))
220− >>= flip unless (throwError (GeneralError "Couldn't locate your output directory"))
146+ (throwError (GeneralError "Couldn't locate your output directory."))
147+ liftIO $ do
221− liftIO (getDirectoryContents outputDirectory)
148+ directories <- getDirectoryContents oDir
222− >>= liftIO . traverse (getExternsPath outputDirectory)
149+ moduleNames <- filterM (checkExternsPath oDir) directories
223− >>= traverse_ loadExtern . catMaybes
150+ pure (P.moduleNameFromString <$> moduleNames)
224− pure (TextResult "All modules loaded.")
225 where
151 where
152+ -- | Takes the output directory and a filepath like "Monad.Control.Eff" and
153+ -- looks up, whether that folder contains an externs.json
226− getExternsPath :: FilePath -> FilePath -> IO (Maybe FilePath)
154+ checkExternsPath :: FilePath -> FilePath -> IO Bool
227− getExternsPath outputDirectory d
155+ checkExternsPath oDir d
228− | d `elem` [".", ".."] = pure Nothing
156+ | d `elem` [".", ".."] = pure False
229 | otherwise = do
157 | otherwise = do
230− let file = outputDirectory </> d </> "externs.json"
158+ let file = oDir </> d </> "externs.json"
231− ex <- doesFileExist file
159+ doesFileExist file
232− if ex
160+
233− then pure (Just file)
161+-- | Finds all matches for the globs specified at the commandline
234− else pure Nothing
162+findAllSourceFiles :: Ide m => m [FilePath]
235−
163+findAllSourceFiles = do
164+ globs <- confGlobs . ideConfiguration <$> ask
165+ liftIO (concatMapM glob globs)
166+
167+-- | Looks up the ExternsFiles for the given Modulenames and loads them into the
168+-- server state. Then proceeds to parse all the specified sourcefiles and
169+-- inserts their ASTs into the state. Finally kicks off an async worker, which
170+-- populates Stage 2 and 3 of the state.
171+loadModules
236−filePathFromModule :: (PscIde m, MonadError PscIdeError m) =>
172+ :: (Ide m, MonadError PscIdeError m, MonadLogger m)
237− ModuleIdent -> m FilePath
173+ => [P.ModuleName]
238−filePathFromModule moduleName = do
174+ -> m Success
239− outputPath <- confOutputPath . envConfiguration <$> ask
175+loadModules moduleNames = do
240− cwd <- liftIO getCurrentDirectory
176+ -- We resolve all the modulenames to externs files and load these into memory.
241− let path = cwd </> outputPath </> T.unpack moduleName </> "externs.json"
177+ oDir <- outputDirectory
242− ex <- liftIO $ doesFileExist path
178+ let efPaths =
243− if ex
179+ map (\mn -> oDir </> P.runModuleName mn </> "externs.json") moduleNames
244− then pure path
180+ efiles <- traverse readExternFile efPaths
245− else throwError (ModuleFileNotFound moduleName)
181+ traverse_ insertExterns efiles
182+
183+ -- We parse all source files, log eventual parse failures if the debug flag
184+ -- was set and insert the succesful parses into the state.
185+ (failures, allModules) <-
186+ partitionEithers <$> (traverse parseModule =<< findAllSourceFiles)
187+ unless (null failures) $
188+ $(logDebug) ("Failed to parse: " <> show failures)
189+ traverse_ insertModule allModules
190+
191+ -- Because we still need the "old" module format to resolve reexports in the
192+ -- worker thread, we insert it into the state aswell.
193+ -- TODO Get rid of this once ModuleOld is gone
194+ traverse_ insertModuleOld efiles
195+
196+ -- Finally we kick off the worker with @async@ and return the number of
197+ -- successfully parsed modules.
198+ env <- ask
199+ let runLogger =
200+ runStdoutLoggingT
201+ . filterLogger (\_ _ -> confDebug (ideConfiguration env))
202+ -- populateStage2 returns Unit for now, so it's fine to discard this result.
203+ -- We might want to block on this in a benchmarking situation.
204+ _ <- liftIO (async (runLogger (runReaderT populateStage2 env)))
205+ pure (TextResult ("Loaded " <> show (length efiles) <> " modules and "
206+ <> show (length allModules) <> " source files."))
src/Language/PureScript/Ide/CaseSplit.hs+25−28
@@ -23,14 +23,8 @@ module Language.PureScript.Ide.CaseSplit
23 , caseSplit
23 , caseSplit
24 ) where
24 ) where
25
25
26−import Prelude ()
26+import Protolude hiding (Constructor)
27−import Prelude.Compat hiding (lex)
27+
28−
29−import Control.Arrow (second)
30−import Control.Monad.Error.Class
31−import Data.List (find)
32−import Data.Monoid
33−import Data.Text (Text)
34import qualified Data.Text as T
28import qualified Data.Text as T
35import qualified Language.PureScript as P
29import qualified Language.PureScript as P
36
30
@@ -42,6 +36,7 @@ import Language.PureScript.Ide.Types
42import Language.PureScript.Ide.Util
36import Language.PureScript.Ide.Util
43
37
44import Text.Parsec as Parsec
38import Text.Parsec as Parsec
39+import qualified Text.PrettyPrint.Boxes as Box
45
40
46type Constructor = (P.ProperName 'P.ConstructorName, [P.Type])
41type Constructor = (P.ProperName 'P.ConstructorName, [P.Type])
47
42
@@ -53,17 +48,17 @@ explicitAnnotations = WildcardAnnotations True
53noAnnotations :: WildcardAnnotations
48noAnnotations :: WildcardAnnotations
54noAnnotations = WildcardAnnotations False
49noAnnotations = WildcardAnnotations False
55
50
56−caseSplit :: (PscIde m, MonadError PscIdeError m) =>
51+caseSplit :: (Ide m, MonadError PscIdeError m) =>
57 Text -> m [Constructor]
52 Text -> m [Constructor]
58caseSplit q = do
53caseSplit q = do
59− type' <- parseType' (T.unpack q)
54+ type' <- parseType' q
60 (tc, args) <- splitTypeConstructor type'
55 (tc, args) <- splitTypeConstructor type'
61 (EDType _ _ (P.DataType typeVars ctors)) <- findTypeDeclaration tc
56 (EDType _ _ (P.DataType typeVars ctors)) <- findTypeDeclaration tc
62 let applyTypeVars = P.everywhereOnTypes (P.replaceAllTypeVars (zip (map fst typeVars) args))
57 let applyTypeVars = P.everywhereOnTypes (P.replaceAllTypeVars (zip (map fst typeVars) args))
63 let appliedCtors = map (second (map applyTypeVars)) ctors
58 let appliedCtors = map (second (map applyTypeVars)) ctors
64 pure appliedCtors
59 pure appliedCtors
65
60
66−findTypeDeclaration :: (PscIde m, MonadError PscIdeError m) =>
61+findTypeDeclaration :: (Ide m, MonadError PscIdeError m) =>
67 P.ProperName 'P.TypeName -> m ExternsDeclaration
62 P.ProperName 'P.TypeName -> m ExternsDeclaration
68findTypeDeclaration q = do
63findTypeDeclaration q = do
69 efs <- getExternFiles
64 efs <- getExternFiles
@@ -113,39 +108,41 @@ makePattern t x y wsa = makePattern' (T.take x t) (T.drop y t)
113 where
108 where
114 makePattern' lhs rhs = map (\ctor -> lhs <> prettyCtor wsa ctor <> rhs)
109 makePattern' lhs rhs = map (\ctor -> lhs <> prettyCtor wsa ctor <> rhs)
115
110
116−addClause :: Text -> WildcardAnnotations -> [Text]
111+addClause :: (MonadError PscIdeError m) => Text -> WildcardAnnotations -> m [Text]
117−addClause s wca =
112+addClause s wca = do
118− let (fName, fType) = parseTypeDeclaration' (T.unpack s)
113+ (fName, fType) <- parseTypeDeclaration' s
119− (args, _) = splitFunctionType fType
114+ let args = splitFunctionType fType
120 template = runIdentT fName <> " " <>
115 template = runIdentT fName <> " " <>
121 T.unwords (map (prettyPrintWildcard wca) args) <>
116 T.unwords (map (prettyPrintWildcard wca) args) <>
122 " = ?" <> (T.strip . runIdentT $ fName)
117 " = ?" <> (T.strip . runIdentT $ fName)
123− in [s, template]
118+ pure [s, template]
124
119
125parseType' :: (MonadError PscIdeError m) =>
120parseType' :: (MonadError PscIdeError m) =>
126− String -> m P.Type
121+ Text -> m P.Type
127parseType' s =
122parseType' s =
128− case P.lex "<psc-ide>" s >>= P.runTokenParser "<psc-ide>" (P.parseType <* Parsec.eof) of
123+ case P.lex "<psc-ide>" (toS s) >>= P.runTokenParser "<psc-ide>" (P.parseType <* Parsec.eof) of
129 Right type' -> pure type'
124 Right type' -> pure type'
130 Left err ->
125 Left err ->
131 throwError (GeneralError ("Parsing the splittype failed with:"
126 throwError (GeneralError ("Parsing the splittype failed with:"
132− ++ show err))
127+ <> show err))
133
128
134−parseTypeDeclaration' :: String -> (P.Ident, P.Type)
129+parseTypeDeclaration' :: (MonadError PscIdeError m) => Text -> m (P.Ident, P.Type)
135parseTypeDeclaration' s =
130parseTypeDeclaration' s =
136 let x = do
131 let x = do
137− ts <- P.lex "" s
132+ ts <- P.lex "" (toS s)
138 P.runTokenParser "" (P.parseDeclaration <* Parsec.eof) ts
133 P.runTokenParser "" (P.parseDeclaration <* Parsec.eof) ts
139 in
134 in
140 case unwrapPositioned <$> x of
135 case unwrapPositioned <$> x of
141− Right (P.TypeDeclaration i t) -> (i, t)
136+ Right (P.TypeDeclaration i t) -> pure (i, t)
142− y -> error (show y)
137+ Right _ -> throwError (GeneralError "Found a non-type-declaration")
143−
138+ Left err ->
139+ throwError (GeneralError ("Parsing the type signature failed with: "
140+ <> toS (Box.render (P.prettyPrintParseError err))))
141+
144−splitFunctionType :: P.Type -> ([P.Type], P.Type)
142+splitFunctionType :: P.Type -> [P.Type]
145−splitFunctionType t = (arguments, returns)
143+splitFunctionType t = fromMaybe [] arguments
146 where
144 where
147− returns = last splitted
148− arguments = init splitted
145+ arguments = initMay splitted
149 splitted = splitType' t
146 splitted = splitType' t
150 splitType' (P.ForAll _ t' _) = splitType' t'
147 splitType' (P.ForAll _ t' _) = splitType' t'
151 splitType' (P.ConstrainedType _ t') = splitType' t'
148 splitType' (P.ConstrainedType _ t') = splitType' t'
src/Language/PureScript/Ide/Command.hs+10−17
@@ -16,25 +16,20 @@
16
16
17module Language.PureScript.Ide.Command where
17module Language.PureScript.Ide.Command where
18
18
19−import Prelude ()
19+import Protolude
20−import Prelude.Compat
21
20
22−import Control.Monad
23import Data.Aeson
21import Data.Aeson
24−import Data.Text (Text)
25import qualified Language.PureScript as P
22import qualified Language.PureScript as P
26import Language.PureScript.Ide.CaseSplit
23import Language.PureScript.Ide.CaseSplit
27import Language.PureScript.Ide.Filter
24import Language.PureScript.Ide.Filter
28import Language.PureScript.Ide.Matcher
25import Language.PureScript.Ide.Matcher
29import Language.PureScript.Ide.Types
26import Language.PureScript.Ide.Types
27+import System.FilePath
30
28
31data Command
29data Command
32− = Load
30+ = Load [P.ModuleName]
33− { loadModules :: [ModuleIdent]
34− , loadDependencies :: [ModuleIdent]
35− }
36 | Type
31 | Type
37− { typeSearch :: DeclIdent
32+ { typeSearch :: Text
38 , typeFilters :: [Filter]
33 , typeFilters :: [Filter]
39 , typeCurrentModule :: Maybe P.ModuleName
34 , typeCurrentModule :: Maybe P.ModuleName
40 }
35 }
@@ -68,12 +63,12 @@ data Command
68
63
69data ImportCommand
64data ImportCommand
70 = AddImplicitImport P.ModuleName
65 = AddImplicitImport P.ModuleName
71− | AddImportForIdentifier DeclIdent
66+ | AddImportForIdentifier Text
72 deriving (Show, Eq)
67 deriving (Show, Eq)
73
68
74instance FromJSON ImportCommand where
69instance FromJSON ImportCommand where
75 parseJSON = withObject "ImportCommand" $ \o -> do
70 parseJSON = withObject "ImportCommand" $ \o -> do
76− (command :: String) <- o .: "importCommand"
71+ (command :: Text) <- o .: "importCommand"
77 case command of
72 case command of
78 "addImplicitImport" ->
73 "addImplicitImport" ->
79 AddImplicitImport <$> (P.moduleNameFromString <$> o .: "module")
74 AddImplicitImport <$> (P.moduleNameFromString <$> o .: "module")
@@ -85,7 +80,7 @@ data ListType = LoadedModules | Imports FilePath | AvailableModules
85
80
86instance FromJSON ListType where
81instance FromJSON ListType where
87 parseJSON = withObject "ListType" $ \o -> do
82 parseJSON = withObject "ListType" $ \o -> do
88− (listType' :: String) <- o .: "type"
83+ (listType' :: Text) <- o .: "type"
89 case listType' of
84 case listType' of
90 "import" -> Imports <$> o .: "file"
85 "import" -> Imports <$> o .: "file"
91 "loadedModules" -> pure LoadedModules
86 "loadedModules" -> pure LoadedModules
@@ -94,7 +89,7 @@ instance FromJSON ListType where
94
89
95instance FromJSON Command where
90instance FromJSON Command where
96 parseJSON = withObject "command" $ \o -> do
91 parseJSON = withObject "command" $ \o -> do
97− (command :: String) <- o .: "command"
92+ (command :: Text) <- o .: "command"
98 case command of
93 case command of
99 "list" -> List <$> o .:? "params" .!= LoadedModules
94 "list" -> List <$> o .:? "params" .!= LoadedModules
100 "cwd" -> pure Cwd
95 "cwd" -> pure Cwd
@@ -103,11 +98,9 @@ instance FromJSON Command where
103 "load" -> do
98 "load" -> do
104 params' <- o .:? "params"
99 params' <- o .:? "params"
105 case params' of
100 case params' of
106− Nothing -> pure (Load [] [])
101+ Nothing -> pure (Load [])
107 Just params ->
102 Just params ->
108− Load
109− <$> params .:? "modules" .!= []
103+ Load <$> (map P.moduleNameFromString <$> params .:? "modules" .!= [])
110− <*> params .:? "dependencies" .!= []
111 "type" -> do
104 "type" -> do
112 params <- o .: "params"
105 params <- o .: "params"
113 Type
106 Type
src/Language/PureScript/Ide/Completion.hs+8−13
@@ -1,12 +1,11 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2module Language.PureScript.Ide.Completion
2module Language.PureScript.Ide.Completion
3+ ( getCompletions
3− (getCompletions, getExactMatches)
4+ , getExactMatches
4− where
5+ ) where
5
6
6−import Prelude ()
7+import Protolude
7−import Prelude.Compat
8
8
9−import Data.Maybe (mapMaybe)
10import Language.PureScript.Ide.Filter
9import Language.PureScript.Ide.Filter
11import Language.PureScript.Ide.Matcher
10import Language.PureScript.Ide.Matcher
12import Language.PureScript.Ide.Types
11import Language.PureScript.Ide.Types
@@ -15,18 +14,14 @@ import Language.PureScript.Ide.Types
15-- and sorts the found Completions according to the Matching Score
14-- and sorts the found Completions according to the Matching Score
16getCompletions :: [Filter] -> Matcher -> [Module] -> [Match]
15getCompletions :: [Filter] -> Matcher -> [Module] -> [Match]
17getCompletions filters matcher modules =
16getCompletions filters matcher modules =
18− runMatcher matcher $ completionsFromModules (applyFilters filters modules)
17+ runMatcher matcher (completionsFromModules (applyFilters filters modules))
19
18
20−getExactMatches :: DeclIdent -> [Filter] -> [Module] -> [Match]
19+getExactMatches :: Text -> [Filter] -> [Module] -> [Match]
21getExactMatches search filters modules =
20getExactMatches search filters modules =
22− completionsFromModules $
23− applyFilters (equalityFilter search : filters) modules
21+ completionsFromModules (applyFilters (equalityFilter search : filters) modules)
24
22
25completionsFromModules :: [Module] -> [Match]
23completionsFromModules :: [Module] -> [Match]
26completionsFromModules = foldMap completionFromModule
24completionsFromModules = foldMap completionFromModule
27 where
25 where
28 completionFromModule :: Module -> [Match]
26 completionFromModule :: Module -> [Match]
29− completionFromModule (moduleIdent, decls) = mapMaybe (matchFromDecl moduleIdent) decls
27+ completionFromModule (moduleName, decls) = map (Match moduleName) decls
30−
31−matchFromDecl :: ModuleIdent -> ExternDecl -> Maybe Match
32−matchFromDecl mi = Just . Match mi
src/Language/PureScript/Ide/Conversions.hsnew file+35
@@ -0,0 +1,35 @@
1+-----------------------------------------------------------------------------
2+--
3+-- Module : Language.PureScript.Ide.Conversions
4+-- Description : Conversions to Text for PureScript types
5+-- Copyright : Christoph Hegemann 2016
6+-- License : MIT (http://opensource.org/licenses/MIT)
7+--
8+-- Maintainer : Christoph Hegemann <christoph.hegemann1337@gmail.com>
9+-- Stability : experimental
10+--
11+-- |
12+-- Conversions to Text for PureScript types
13+-----------------------------------------------------------------------------
14+
15+module Language.PureScript.Ide.Conversions where
16+
17+import Protolude
18+import Data.Text (unwords, lines, strip)
19+import qualified Language.PureScript as P
20+
21+runProperNameT :: P.ProperName a -> Text
22+runProperNameT = toS . P.runProperName
23+
24+runIdentT :: P.Ident -> Text
25+runIdentT = toS . P.runIdent
26+
27+runOpNameT :: P.OpName a -> Text
28+runOpNameT = toS . P.runOpName
29+
30+runModuleNameT :: P.ModuleName -> Text
31+runModuleNameT = toS . P.runModuleName
32+
33+prettyTypeT :: P.Type -> Text
34+prettyTypeT = unwords . map strip . lines . toS . P.prettyPrintType
35+
src/Language/PureScript/Ide/Error.hs+9−12
@@ -14,25 +14,22 @@
14
14
15{-# LANGUAGE OverloadedStrings #-}
15{-# LANGUAGE OverloadedStrings #-}
16module Language.PureScript.Ide.Error
16module Language.PureScript.Ide.Error
17− (ErrorMsg, PscIdeError(..), textError)
17+ ( PscIdeError(..)
18+ , textError
18− where
19+ ) where
19
20
20−import Prelude.Compat
21+import Protolude
21import Data.Aeson
22import Data.Aeson
22−import Data.Monoid
23−import Data.Text (Text, pack)
24import Language.PureScript.Errors.JSON
23import Language.PureScript.Errors.JSON
25import Language.PureScript.Ide.Types (ModuleIdent)
24import Language.PureScript.Ide.Types (ModuleIdent)
26import qualified Text.Parsec.Error as P
25import qualified Text.Parsec.Error as P
27
26
28−type ErrorMsg = String
29−
30data PscIdeError
27data PscIdeError
31− = GeneralError ErrorMsg
28+ = GeneralError Text
32 | NotFound Text
29 | NotFound Text
33 | ModuleNotFound ModuleIdent
30 | ModuleNotFound ModuleIdent
34 | ModuleFileNotFound ModuleIdent
31 | ModuleFileNotFound ModuleIdent
35− | ParseError P.ParseError ErrorMsg
32+ | ParseError P.ParseError Text
36 | RebuildError [JSONError]
33 | RebuildError [JSONError]
37
34
38instance ToJSON PscIdeError where
35instance ToJSON PscIdeError where
@@ -46,7 +43,7 @@ instance ToJSON PscIdeError where
46 ]
43 ]
47
44
48textError :: PscIdeError -> Text
45textError :: PscIdeError -> Text
49−textError (GeneralError msg) = pack msg
46+textError (GeneralError msg) = msg
50textError (NotFound ident) = "Symbol '" <> ident <> "' not found."
47textError (NotFound ident) = "Symbol '" <> ident <> "' not found."
51textError (ModuleNotFound ident) = "Module '" <> ident <> "' not found."
48textError (ModuleNotFound ident) = "Module '" <> ident <> "' not found."
52textError (ModuleFileNotFound ident) = "Extern file for module " <> ident <>" could not be found"
49textError (ModuleFileNotFound ident) = "Extern file for module " <> ident <>" could not be found"
@@ -54,5 +51,5 @@ textError (ParseError parseError msg) = let escape = show
54 -- escape newlines and other special
51 -- escape newlines and other special
55 -- chars so we can send the error
52 -- chars so we can send the error
56 -- over the socket as a single line
53 -- over the socket as a single line
57− in pack $ msg <> ": " <> show (escape parseError)
54+ in msg <> ": " <> escape parseError
58−textError (RebuildError err) = pack (show err)
55+textError (RebuildError err) = show err
src/Language/PureScript/Ide/Externs.hs+32−26
@@ -12,29 +12,24 @@
12-- Handles externs files for psc-ide
12-- Handles externs files for psc-ide
13-----------------------------------------------------------------------------
13-----------------------------------------------------------------------------
14
14
15−{-# LANGUAGE OverloadedStrings #-}
15+{-# LANGUAGE OverloadedStrings #-}
16+{-# LANGUAGE RecordWildCards #-}
17+{-# LANGUAGE FlexibleContexts #-}
16
18
17module Language.PureScript.Ide.Externs
19module Language.PureScript.Ide.Externs
18 ( ExternDecl(..),
20 ( ExternDecl(..),
19 ModuleIdent,
21 ModuleIdent,
20− DeclIdent,
21 readExternFile,
22 readExternFile,
22 convertExterns,
23 convertExterns,
24+ convertModule,
23 unwrapPositioned,
25 unwrapPositioned,
24 unwrapPositionedRef
26 unwrapPositionedRef
25 ) where
27 ) where
26
28
27−import Prelude ()
29+import Protolude
28−import Prelude.Compat
29
30
30−import Control.Monad.Error.Class
31−import Control.Monad.IO.Class
32import Data.Aeson (decodeStrict)
31import Data.Aeson (decodeStrict)
33import Data.List (nub)
32import Data.List (nub)
34−import Data.Maybe (mapMaybe)
35−import Data.Monoid
36−import Data.Text (Text)
37−import qualified Data.Text as T
38import qualified Data.ByteString as BS
33import qualified Data.ByteString as BS
39import Language.PureScript.Ide.Error (PscIdeError (..))
34import Language.PureScript.Ide.Error (PscIdeError (..))
40import Language.PureScript.Ide.Types
35import Language.PureScript.Ide.Types
@@ -42,24 +37,20 @@ import Language.PureScript.Ide.Util
42
37
43import qualified Language.PureScript as P
38import qualified Language.PureScript as P
44
39
40+import System.FilePath
41+
45readExternFile :: (MonadIO m, MonadError PscIdeError m) =>
42readExternFile :: (MonadIO m, MonadError PscIdeError m) =>
46 FilePath -> m P.ExternsFile
43 FilePath -> m P.ExternsFile
47readExternFile fp = do
44readExternFile fp = do
48 parseResult <- liftIO (decodeStrict <$> BS.readFile fp)
45 parseResult <- liftIO (decodeStrict <$> BS.readFile fp)
49 case parseResult of
46 case parseResult of
50− Nothing -> throwError . GeneralError $ "Parsing the extern at: " ++ fp ++ " failed"
47+ Nothing -> throwError . GeneralError $ "Parsing the extern at: " <> toS fp <> " failed"
51 Just externs -> pure externs
48 Just externs -> pure externs
52
49
53−moduleNameToText :: P.ModuleName -> Text
54−moduleNameToText = T.pack . P.runModuleName
55−
56−identToText :: P.Ident -> Text
57−identToText = T.pack . P.runIdent
58−
59−convertExterns :: P.ExternsFile -> Module
50+convertExterns :: P.ExternsFile -> ModuleOld
60−convertExterns ef = (moduleName, exportDecls ++ importDecls ++ decls ++ operatorDecls ++ tyOperatorDecls)
51+convertExterns ef = (runModuleNameT moduleName, exportDecls ++ importDecls ++ decls ++ operatorDecls ++ tyOperatorDecls)
61 where
52 where
62− moduleName = moduleNameToText (P.efModuleName ef)
53+ moduleName = P.efModuleName ef
63 importDecls = convertImport <$> P.efImports ef
54 importDecls = convertImport <$> P.efImports ef
64 exportDecls = mapMaybe (convertExport . unwrapPositionedRef) (P.efExports ef)
55 exportDecls = mapMaybe (convertExport . unwrapPositionedRef) (P.efExports ef)
65 operatorDecls = convertOperator <$> P.efFixities ef
56 operatorDecls = convertOperator <$> P.efFixities ef
@@ -82,12 +73,12 @@ isTypeClassDeclaration _ = False
82
73
83convertImport :: P.ExternsImport -> ExternDecl
74convertImport :: P.ExternsImport -> ExternDecl
84convertImport ei = Dependency
75convertImport ei = Dependency
85− (moduleNameToText (P.eiModule ei))
76+ (runModuleNameT (P.eiModule ei))
86 []
77 []
87− (moduleNameToText <$> P.eiImportedAs ei)
78+ (runModuleNameT <$> P.eiImportedAs ei)
88
79
89convertExport :: P.DeclarationRef -> Maybe ExternDecl
80convertExport :: P.DeclarationRef -> Maybe ExternDecl
90−convertExport (P.ModuleRef mn) = Just (Export (moduleNameToText mn))
81+convertExport (P.ModuleRef mn) = Just (Export (runModuleNameT mn))
91convertExport _ = Nothing
82convertExport _ = Nothing
92
83
93convertDecl :: P.ExternsDeclaration -> Maybe ExternDecl
84convertDecl :: P.ExternsDeclaration -> Maybe ExternDecl
@@ -97,7 +88,7 @@ convertDecl P.EDTypeSynonym{..} = Just $
97convertDecl P.EDDataConstructor{..} = Just $
88convertDecl P.EDDataConstructor{..} = Just $
98 DataConstructor (runProperNameT edDataCtorName) edDataCtorTypeCtor edDataCtorType
89 DataConstructor (runProperNameT edDataCtorName) edDataCtorTypeCtor edDataCtorType
99convertDecl P.EDValue{..} = Just $
90convertDecl P.EDValue{..} = Just $
100− ValueDeclaration (identToText edValueName) edValueType
91+ ValueDeclaration (runIdentT edValueName) edValueType
101convertDecl P.EDClass{..} = Just $ TypeClassDeclaration edClassName
92convertDecl P.EDClass{..} = Just $ TypeClassDeclaration edClassName
102convertDecl P.EDInstance{} = Nothing
93convertDecl P.EDInstance{} = Nothing
103
94
@@ -105,7 +96,7 @@ convertOperator :: P.ExternsFixity -> ExternDecl
105convertOperator P.ExternsFixity{..} =
96convertOperator P.ExternsFixity{..} =
106 ValueOperator
97 ValueOperator
107 efOperator
98 efOperator
108− (T.pack (P.showQualified (either P.runIdent P.runProperName) efAlias))
99+ (toS (P.showQualified (either P.runIdent P.runProperName) efAlias))
109 efPrecedence
100 efPrecedence
110 efAssociativity
101 efAssociativity
111
102
@@ -113,7 +104,7 @@ convertTypeOperator :: P.ExternsTypeFixity -> ExternDecl
113convertTypeOperator P.ExternsTypeFixity{..} =
104convertTypeOperator P.ExternsTypeFixity{..} =
114 TypeOperator
105 TypeOperator
115 efTypeOperator
106 efTypeOperator
116− (T.pack (P.showQualified P.runProperName efTypeAlias))
107+ (toS (P.showQualified P.runProperName efTypeAlias))
117 efTypePrecedence
108 efTypePrecedence
118 efTypeAssociativity
109 efTypeAssociativity
119
110
@@ -124,3 +115,18 @@ unwrapPositioned x = x
124unwrapPositionedRef :: P.DeclarationRef -> P.DeclarationRef
115unwrapPositionedRef :: P.DeclarationRef -> P.DeclarationRef
125unwrapPositionedRef (P.PositionedDeclarationRef _ _ x) = x
116unwrapPositionedRef (P.PositionedDeclarationRef _ _ x) = x
126unwrapPositionedRef x = x
117unwrapPositionedRef x = x
118+
119+convertModule :: ModuleOld -> Module
120+convertModule (mn, decls) = (P.moduleNameFromString (toS mn), mapMaybe convertDeclaration decls)
121+ where convertDeclaration :: ExternDecl -> Maybe IdeDeclaration
122+ convertDeclaration d = case d of
123+ ValueDeclaration i t -> Just (IdeValue i t)
124+ TypeDeclaration i k -> Just (IdeType i k)
125+ TypeSynonymDeclaration i t -> Just (IdeTypeSynonym i t)
126+ DataConstructor i tn t -> Just (IdeDataConstructor i tn t)
127+ TypeClassDeclaration i -> Just (IdeTypeClass i)
128+ ValueOperator n i p a -> Just (IdeValueOperator n i p a)
129+ TypeOperator n i p a -> Just (IdeTypeOperator n i p a)
130+ Dependency{} -> Nothing
131+ ModuleDecl _ _ -> Nothing
132+ Export _ -> Nothing
src/Language/PureScript/Ide/Filter.hs+13−46
@@ -20,22 +20,17 @@ module Language.PureScript.Ide.Filter
20 , moduleFilter
20 , moduleFilter
21 , prefixFilter
21 , prefixFilter
22 , equalityFilter
22 , equalityFilter
23− , dependencyFilter
24 , runFilter
23 , runFilter
25 , applyFilters
24 , applyFilters
26 ) where
25 ) where
27
26
28−import Prelude ()
27+import Protolude hiding (isPrefixOf)
29−import Prelude.Compat
30
28
31−import Control.Monad
32import Data.Aeson
29import Data.Aeson
33−import Data.Foldable
34−import Data.Maybe (listToMaybe, mapMaybe)
35−import Data.Monoid
36−import Data.Text (Text, isPrefixOf)
30+import Data.Text (isPrefixOf)
37import Language.PureScript.Ide.Types
31import Language.PureScript.Ide.Types
38import Language.PureScript.Ide.Util
32import Language.PureScript.Ide.Util
33+import qualified Language.PureScript as P
39
34
40newtype Filter = Filter (Endo [Module]) deriving(Monoid)
35newtype Filter = Filter (Endo [Module]) deriving(Monoid)
41
36
@@ -43,53 +38,29 @@ mkFilter :: ([Module] -> [Module]) -> Filter
43mkFilter = Filter . Endo
38mkFilter = Filter . Endo
44
39
45-- | Only keeps the given Modules
40-- | Only keeps the given Modules
46−moduleFilter :: [ModuleIdent] -> Filter
41+moduleFilter :: [P.ModuleName] -> Filter
47moduleFilter =
42moduleFilter =
48 mkFilter . moduleFilter'
43 mkFilter . moduleFilter'
49
44
50−moduleFilter' :: [ModuleIdent] -> [Module] -> [Module]
45+moduleFilter' :: [P.ModuleName] -> [Module] -> [Module]
51moduleFilter' moduleIdents = filter (flip elem moduleIdents . fst)
46moduleFilter' moduleIdents = filter (flip elem moduleIdents . fst)
52
47
53−-- | Only keeps the given Modules and all of their dependencies
54−dependencyFilter :: [ModuleIdent] -> Filter
55−dependencyFilter = mkFilter . dependencyFilter'
56−
57−dependencyFilter' :: [ModuleIdent] -> [Module] -> [Module]
58−dependencyFilter' moduleIdents mods =
59− moduleFilter' (concatMap (getDepForModule mods) moduleIdents) mods
60− where
61− getDepForModule :: [Module] -> ModuleIdent -> [ModuleIdent]
62− getDepForModule ms moduleIdent =
63− moduleIdent : maybe [] extractDeps (findModule moduleIdent ms)
64−
65− findModule :: ModuleIdent -> [Module] -> Maybe Module
66− findModule i ms = listToMaybe $ filter go ms
67− where go (mn, _) = i == mn
68−
69− extractDeps :: Module -> [ModuleIdent]
70− extractDeps = mapMaybe extractDep . snd
71− where extractDep (Dependency n _ _) = Just n
72− extractDep _ = Nothing
73−
74-- | Only keeps Identifiers that start with the given prefix
48-- | Only keeps Identifiers that start with the given prefix
75prefixFilter :: Text -> Filter
49prefixFilter :: Text -> Filter
76−prefixFilter "" = mkFilter id
50+prefixFilter "" = mkFilter identity
77prefixFilter t = mkFilter $ identFilter prefix t
51prefixFilter t = mkFilter $ identFilter prefix t
78 where
52 where
79− prefix :: ExternDecl -> Text -> Bool
53+ prefix :: IdeDeclaration -> Text -> Bool
80− prefix Export{} _ = False
81− prefix Dependency{} _ = False
82− prefix ed search = search `isPrefixOf` identifierFromExternDecl ed
54+ prefix ed search = search `isPrefixOf` identifierFromIdeDeclaration ed
83−
84
55
85-- | Only keeps Identifiers that are equal to the search string
56-- | Only keeps Identifiers that are equal to the search string
86equalityFilter :: Text -> Filter
57equalityFilter :: Text -> Filter
87equalityFilter = mkFilter . identFilter equality
58equalityFilter = mkFilter . identFilter equality
88 where
59 where
89− equality :: ExternDecl -> Text -> Bool
60+ equality :: IdeDeclaration -> Text -> Bool
90− equality ed search = identifierFromExternDecl ed == search
61+ equality ed search = identifierFromIdeDeclaration ed == search
91
62
92−identFilter :: (ExternDecl -> Text -> Bool ) -> Text -> [Module] -> [Module]
63+identFilter :: (IdeDeclaration -> Text -> Bool) -> Text -> [Module] -> [Module]
93identFilter predicate search =
64identFilter predicate search =
94 filter (not . null . snd) . fmap filterModuleDecls
65 filter (not . null . snd) . fmap filterModuleDecls
95 where
66 where
@@ -105,7 +76,7 @@ applyFilters = runFilter . fold
105
76
106instance FromJSON Filter where
77instance FromJSON Filter where
107 parseJSON = withObject "filter" $ \o -> do
78 parseJSON = withObject "filter" $ \o -> do
108− (filter' :: String) <- o .: "filter"
79+ (filter' :: Text) <- o .: "filter"
109 case filter' of
80 case filter' of
110 "exact" -> do
81 "exact" -> do
111 params <- o .: "params"
82 params <- o .: "params"
@@ -117,10 +88,6 @@ instance FromJSON Filter where
117 return $ prefixFilter search
88 return $ prefixFilter search
118 "modules" -> do
89 "modules" -> do
119 params <- o .: "params"
90 params <- o .: "params"
120− modules <- params .: "modules"
91+ modules <- map P.moduleNameFromString <$> params .: "modules"
121 return $ moduleFilter modules
92 return $ moduleFilter modules
122− "dependencies" -> do
123− params <- o .: "params"
124− deps <- params .: "modules"
125− return $ dependencyFilter deps
126 _ -> mzero
93 _ -> mzero
src/Language/PureScript/Ide/Imports.hs+30−37
@@ -29,17 +29,9 @@ module Language.PureScript.Ide.Imports
29 )
29 )
30 where
30 where
31
31
32−import Prelude.Compat
32+import Protolude
33−import Control.Applicative ((<|>))
34−import Control.Monad.Error.Class
35−import Control.Monad.IO.Class
36−import Data.Bifunctor (first, second)
37−import Data.Function (on)
38−import qualified Data.List as List
39−import Data.Maybe (isNothing)
40−import Data.Monoid ((<>))
41−import Data.Text (Text)
42import qualified Data.Text as T
33import qualified Data.Text as T
34+import Data.List (nubBy, findIndex)
43import qualified Data.Text.IO as TIO
35import qualified Data.Text.IO as TIO
44import qualified Language.PureScript as P
36import qualified Language.PureScript as P
45import Language.PureScript.Ide.Completion
37import Language.PureScript.Ide.Completion
@@ -50,6 +42,7 @@ import Language.PureScript.Ide.Filter
50import Language.PureScript.Ide.State
42import Language.PureScript.Ide.State
51import Language.PureScript.Ide.Types
43import Language.PureScript.Ide.Types
52import Language.PureScript.Ide.Util
44import Language.PureScript.Ide.Util
45+import System.FilePath
53
46
54data Import = Import P.ModuleName P.ImportDeclarationType (Maybe P.ModuleName)
47data Import = Import P.ModuleName P.ImportDeclarationType (Maybe P.ModuleName)
55 deriving (Eq, Show)
48 deriving (Eq, Show)
@@ -85,7 +78,7 @@ parseImportsFromFile fp = do
85 Right res -> pure res
78 Right res -> pure res
86 Left err -> throwError (GeneralError err)
79 Left err -> throwError (GeneralError err)
87
80
88−parseImportsWithModuleName :: [Text] -> Either String (P.ModuleName, [Import])
81+parseImportsWithModuleName :: [Text] -> Either Text (P.ModuleName, [Import])
89parseImportsWithModuleName ls = do
82parseImportsWithModuleName ls = do
90 (P.Module _ _ mn decls _) <- moduleParse ls
83 (P.Module _ _ mn decls _) <- moduleParse ls
91 pure (mn, concatMap mkImport (unwrapPositioned <$> decls))
84 pure (mn, concatMap mkImport (unwrapPositioned <$> decls))
@@ -95,13 +88,13 @@ parseImportsWithModuleName ls = do
95 mkImport (P.ImportDeclaration mn it qual) = [Import mn it qual]
88 mkImport (P.ImportDeclaration mn it qual) = [Import mn it qual]
96 mkImport _ = []
89 mkImport _ = []
97
90
98−sliceImportSection :: [Text] -> Either String (P.ModuleName, [Text], [Import], [Text])
91+sliceImportSection :: [Text] -> Either Text (P.ModuleName, [Text], [Import], [Text])
99sliceImportSection ts =
92sliceImportSection ts =
100 case foldl step (ModuleHeader 0) (zip [0..] ts) of
93 case foldl step (ModuleHeader 0) (zip [0..] ts) of
101 Res start end ->
94 Res start end ->
102 let
95 let
103 (moduleHeader, (importSection, remainingFile)) =
96 (moduleHeader, (importSection, remainingFile)) =
104− List.splitAt (succ (end - start)) `second` List.splitAt start ts
97+ splitAt (succ (end - start)) `second` splitAt start ts
105 in
98 in
106 (\(mn, is) -> (mn, moduleHeader, is, remainingFile)) <$>
99 (\(mn, is) -> (mn, moduleHeader, is, remainingFile)) <$>
107 parseImportsWithModuleName (moduleHeader <> importSection)
100 parseImportsWithModuleName (moduleHeader <> importSection)
@@ -109,7 +102,7 @@ sliceImportSection ts =
109 -- If we don't find any imports, we insert a newline after the module
102 -- If we don't find any imports, we insert a newline after the module
110 -- declaration and begin a new importsection
103 -- declaration and begin a new importsection
111 ModuleHeader ix ->
104 ModuleHeader ix ->
112− let (moduleHeader, remainingFile) = List.splitAt (succ ix) ts
105+ let (moduleHeader, remainingFile) = splitAt (succ ix) ts
113 in
106 in
114 (\(mn, is) -> (mn, moduleHeader ++ [""], is, remainingFile)) <$>
107 (\(mn, is) -> (mn, moduleHeader ++ [""], is, remainingFile)) <$>
115 parseImportsWithModuleName moduleHeader
108 parseImportsWithModuleName moduleHeader
@@ -151,7 +144,7 @@ step (ImportSection start lastImportLine) (ix, l)
151 | otherwise = Res start lastImportLine
144 | otherwise = Res start lastImportLine
152step (Res start end) _ = Res start end
145step (Res start end) _ = Res start end
153
146
154−moduleParse :: [Text] -> Either String P.Module
147+moduleParse :: [Text] -> Either Text P.Module
155moduleParse t = first show $ do
148moduleParse t = first show $ do
156 tokens <- (P.lex "" . T.unpack . T.unlines) t
149 tokens <- (P.lex "" . T.unpack . T.unlines) t
157 P.runTokenParser "<psc-ide>" P.parseModule tokens
150 P.runTokenParser "<psc-ide>" P.parseModule tokens
@@ -181,7 +174,7 @@ addImplicitImport' imports mn =
181-- @import Prelude (bind)@ in the file File.purs returns @["import Prelude
174-- @import Prelude (bind)@ in the file File.purs returns @["import Prelude
182-- (bind, unit)"]@
175-- (bind, unit)"]@
183addExplicitImport :: (MonadIO m, MonadError PscIdeError m) =>
176addExplicitImport :: (MonadIO m, MonadError PscIdeError m) =>
184− FilePath -> ExternDecl -> P.ModuleName -> m [Text]
177+ FilePath -> IdeDeclaration -> P.ModuleName -> m [Text]
185addExplicitImport fp decl moduleName = do
178addExplicitImport fp decl moduleName = do
186 (mn, pre, imports, post) <- parseImportsFromFile fp
179 (mn, pre, imports, post) <- parseImportsFromFile fp
187 let newImportSection =
180 let newImportSection =
@@ -192,7 +185,7 @@ addExplicitImport fp decl moduleName = do
192 else addExplicitImport' decl moduleName imports
185 else addExplicitImport' decl moduleName imports
193 pure (pre ++ prettyPrintImportSection newImportSection ++ post)
186 pure (pre ++ prettyPrintImportSection newImportSection ++ post)
194
187
195−addExplicitImport' :: ExternDecl -> P.ModuleName -> [Import] -> [Import]
188+addExplicitImport' :: IdeDeclaration -> P.ModuleName -> [Import] -> [Import]
196addExplicitImport' decl moduleName imports =
189addExplicitImport' decl moduleName imports =
197 let
190 let
198 isImplicitlyImported =
191 isImplicitlyImported =
@@ -207,37 +200,37 @@ addExplicitImport' decl moduleName imports =
207 then imports
200 then imports
208 else updateAtFirstOrPrepend matches (insertDeclIntoImport decl) freshImport imports
201 else updateAtFirstOrPrepend matches (insertDeclIntoImport decl) freshImport imports
209 where
202 where
210− refFromDeclaration (TypeClassDeclaration n) =
203+ refFromDeclaration (IdeTypeClass n) =
211 P.TypeClassRef n
204 P.TypeClassRef n
212− refFromDeclaration (DataConstructor n tn _) =
205+ refFromDeclaration (IdeDataConstructor n tn _) =
213 P.TypeRef tn (Just [P.ProperName (T.unpack n)])
206 P.TypeRef tn (Just [P.ProperName (T.unpack n)])
214− refFromDeclaration (TypeDeclaration n _) =
207+ refFromDeclaration (IdeType n _) =
215 P.TypeRef n (Just [])
208 P.TypeRef n (Just [])
216− refFromDeclaration (ValueOperator op _ _ _) =
209+ refFromDeclaration (IdeValueOperator op _ _ _) =
217 P.ValueOpRef op
210 P.ValueOpRef op
218− refFromDeclaration (TypeOperator op _ _ _) =
211+ refFromDeclaration (IdeTypeOperator op _ _ _) =
219 P.TypeOpRef op
212 P.TypeOpRef op
220 refFromDeclaration d =
213 refFromDeclaration d =
221− P.ValueRef $ P.Ident $ T.unpack (identifierFromExternDecl d)
214+ P.ValueRef $ P.Ident $ T.unpack (identifierFromIdeDeclaration d)
222
215
223 -- | Adds a declaration to an import:
216 -- | Adds a declaration to an import:
224 -- TypeDeclaration "Maybe" + Data.Maybe (maybe) -> Data.Maybe(Maybe, maybe)
217 -- TypeDeclaration "Maybe" + Data.Maybe (maybe) -> Data.Maybe(Maybe, maybe)
225− insertDeclIntoImport :: ExternDecl -> Import -> Import
218+ insertDeclIntoImport :: IdeDeclaration -> Import -> Import
226 insertDeclIntoImport decl' (Import mn (P.Explicit refs) Nothing) =
219 insertDeclIntoImport decl' (Import mn (P.Explicit refs) Nothing) =
227 Import mn (P.Explicit (insertDeclIntoRefs decl' refs)) Nothing
220 Import mn (P.Explicit (insertDeclIntoRefs decl' refs)) Nothing
228 insertDeclIntoImport _ is = is
221 insertDeclIntoImport _ is = is
229
222
230− insertDeclIntoRefs :: ExternDecl -> [P.DeclarationRef] -> [P.DeclarationRef]
223+ insertDeclIntoRefs :: IdeDeclaration -> [P.DeclarationRef] -> [P.DeclarationRef]
231− insertDeclIntoRefs (DataConstructor dtor tn _) refs =
224+ insertDeclIntoRefs (IdeDataConstructor dtor tn _) refs =
232 let
225 let
233 dtor' = P.ProperName (T.unpack dtor)
226 dtor' = P.ProperName (T.unpack dtor)
234 in
227 in
235 updateAtFirstOrPrepend (matchType tn) (insertDtor dtor') (P.TypeRef tn (Just [dtor'])) refs
228 updateAtFirstOrPrepend (matchType tn) (insertDtor dtor') (P.TypeRef tn (Just [dtor'])) refs
236− insertDeclIntoRefs dr refs = List.nubBy ((==) `on` P.prettyPrintRef) (refFromDeclaration dr : refs)
229+ insertDeclIntoRefs dr refs = nubBy ((==) `on` P.prettyPrintRef) (refFromDeclaration dr : refs)
237
230
238 insertDtor dtor (P.TypeRef tn' dtors) =
231 insertDtor dtor (P.TypeRef tn' dtors) =
239 case dtors of
232 case dtors of
240− Just dtors' -> P.TypeRef tn' (Just (List.nub (dtor : dtors')))
233+ Just dtors' -> P.TypeRef tn' (Just (ordNub (dtor : dtors')))
241 -- This means the import was opened. We don't add anything in this case
234 -- This means the import was opened. We don't add anything in this case
242 -- import Data.Maybe (Maybe(..)) -> import Data.Maybe (Maybe(Just))
235 -- import Data.Maybe (Maybe(..)) -> import Data.Maybe (Maybe(Just))
243 Nothing -> P.TypeRef tn' Nothing
236 Nothing -> P.TypeRef tn' Nothing
@@ -249,10 +242,10 @@ addExplicitImport' decl moduleName imports =
249
242
250updateAtFirstOrPrepend :: (a -> Bool) -> (a -> a) -> a -> [a] -> [a]
243updateAtFirstOrPrepend :: (a -> Bool) -> (a -> a) -> a -> [a] -> [a]
251updateAtFirstOrPrepend p t d l =
244updateAtFirstOrPrepend p t d l =
252− case List.findIndex p l of
245+ case findIndex p l of
253 Nothing -> d : l
246 Nothing -> d : l
254 Just ix ->
247 Just ix ->
255− let (x, a : y) = List.splitAt ix l
248+ let (x, a : y) = splitAt ix l
256 in x ++ [t a] ++ y
249 in x ++ [t a] ++ y
257
250
258-- | Looks up the given identifier in the currently loaded modules.
251-- | Looks up the given identifier in the currently loaded modules.
@@ -263,14 +256,14 @@ updateAtFirstOrPrepend p t d l =
263--
256--
264-- * If more than one possible imports are found, reports the possibilities as a
257-- * If more than one possible imports are found, reports the possibilities as a
265-- list of completions.
258-- list of completions.
266−addImportForIdentifier :: (PscIde m, MonadError PscIdeError m)
259+addImportForIdentifier :: (Ide m, MonadError PscIdeError m)
267 => FilePath -- ^ The Sourcefile to read from
260 => FilePath -- ^ The Sourcefile to read from
268 -> Text -- ^ The identifier to import
261 -> Text -- ^ The identifier to import
269 -> [Filter] -- ^ Filters to apply before searching for
262 -> [Filter] -- ^ Filters to apply before searching for
270 -- the identifier
263 -- the identifier
271 -> m (Either [Match] [Text])
264 -> m (Either [Match] [Text])
272addImportForIdentifier fp ident filters = do
265addImportForIdentifier fp ident filters = do
273− modules <- getAllModulesWithReexports
266+ modules <- getAllModules2 Nothing
274 case getExactMatches ident filters modules of
267 case getExactMatches ident filters modules of
275 [] ->
268 [] ->
276 throwError (NotFound "Couldn't find the given identifier. \
269 throwError (NotFound "Couldn't find the given identifier. \
@@ -279,7 +272,7 @@ addImportForIdentifier fp ident filters = do
279 -- Only one match was found for the given identifier, so we can insert it
272 -- Only one match was found for the given identifier, so we can insert it
280 -- right away
273 -- right away
281 [Match m decl] ->
274 [Match m decl] ->
282− Right <$> addExplicitImport fp decl (P.moduleNameFromString (T.unpack m))
275+ Right <$> addExplicitImport fp decl m
283
276
284 -- This case comes up for newtypes and dataconstructors. Because values and
277 -- This case comes up for newtypes and dataconstructors. Because values and
285 -- types don't share a namespace we can get multiple matches from the same
278 -- types don't share a namespace we can get multiple matches from the same
@@ -296,7 +289,7 @@ addImportForIdentifier fp ident filters = do
296 -- dataconstructor as that will give us an unnecessary import warning at
289 -- dataconstructor as that will give us an unnecessary import warning at
297 -- worst
290 -- worst
298 Just decl ->
291 Just decl ->
299− Right <$> addExplicitImport fp decl (P.moduleNameFromString (T.unpack m1))
292+ Right <$> addExplicitImport fp decl m1
300 -- Here we need the user to specify whether he wanted a dataconstructor
293 -- Here we need the user to specify whether he wanted a dataconstructor
301 -- or a type
294 -- or a type
302 Nothing ->
295 Nothing ->
@@ -307,9 +300,9 @@ addImportForIdentifier fp ident filters = do
307 xs ->
300 xs ->
308 pure $ Left xs
301 pure $ Left xs
309 where
302 where
310− decideRedundantCase dtor@(DataConstructor _ t _) (TypeDeclaration t' _) =
303+ decideRedundantCase dtor@(IdeDataConstructor _ t _) (IdeType t' _) =
311 if t == t' then Just dtor else Nothing
304 if t == t' then Just dtor else Nothing
312− decideRedundantCase TypeDeclaration{} ts@TypeSynonymDeclaration{} =
305+ decideRedundantCase IdeType{} ts@IdeTypeSynonym{} =
313 Just ts
306 Just ts
314 decideRedundantCase _ _ = Nothing
307 decideRedundantCase _ _ = Nothing
315
308
@@ -321,7 +314,7 @@ prettyPrintImport' (Import mn idt qual) =
321 T.pack $ "import " ++ P.prettyPrintImport mn idt qual
314 T.pack $ "import " ++ P.prettyPrintImport mn idt qual
322
315
323prettyPrintImportSection :: [Import] -> [Text]
316prettyPrintImportSection :: [Import] -> [Text]
324−prettyPrintImportSection imports = map prettyPrintImport' (List.sort imports)
317+prettyPrintImportSection imports = map prettyPrintImport' (sort imports)
325
318
326-- | Writes a list of lines to @Just filepath@ and responds with a @TextResult@,
319-- | Writes a list of lines to @Just filepath@ and responds with a @TextResult@,
327-- or returns the lines as a @MultilineTextResult@ if @Nothing@ was given as the
320-- or returns the lines as a @MultilineTextResult@ if @Nothing@ was given as the
src/Language/PureScript/Ide/Matcher.hs+7−14
@@ -21,16 +21,9 @@ module Language.PureScript.Ide.Matcher
21 , runMatcher
21 , runMatcher
22 ) where
22 ) where
23
23
24−import Prelude ()
24+import Protolude
25−import Prelude.Compat
26
25
27−import Control.Monad
28import Data.Aeson
26import Data.Aeson
29−import Data.Function (on)
30−import Data.List (sortBy)
31−import Data.Maybe (mapMaybe)
32−import Data.Monoid
33−import Data.Text (Text)
34import qualified Data.Text as T
27import qualified Data.Text as T
35import qualified Data.Text.Encoding as TE
28import qualified Data.Text.Encoding as TE
36import Language.PureScript.Ide.Types
29import Language.PureScript.Ide.Types
@@ -41,11 +34,11 @@ import Text.Regex.TDFA ((=~))
41
34
42type ScoredMatch = (Match, Double)
35type ScoredMatch = (Match, Double)
43
36
44−newtype Matcher = Matcher (Endo [Match]) deriving(Monoid)
37+newtype Matcher = Matcher (Endo [Match]) deriving (Monoid)
45
38
46instance FromJSON Matcher where
39instance FromJSON Matcher where
47 parseJSON = withObject "matcher" $ \o -> do
40 parseJSON = withObject "matcher" $ \o -> do
48− (matcher :: Maybe String) <- o .:? "matcher"
41+ (matcher :: Maybe Text) <- o .:? "matcher"
49 case matcher of
42 case matcher of
50 Just "flex" -> do
43 Just "flex" -> do
51 params <- o .: "params"
44 params <- o .: "params"
@@ -105,11 +98,11 @@ flexRate p c = do
105-- By string =~ pattern we'll get the start of the match and the length of
98-- By string =~ pattern we'll get the start of the match and the length of
106-- the matchas a (start, length) tuple if there's a match.
99-- the matchas a (start, length) tuple if there's a match.
107-- If match fails then it would be (-1,0)
100-- If match fails then it would be (-1,0)
108−flexScore :: Text -> DeclIdent -> Maybe Double
101+flexScore :: Text -> Text -> Maybe Double
109flexScore pat str =
102flexScore pat str =
110 case T.uncons pat of
103 case T.uncons pat of
111 Nothing -> Nothing
104 Nothing -> Nothing
112− Just (first, p) ->
105+ Just (first', p) ->
113 case TE.encodeUtf8 str =~ TE.encodeUtf8 pat' :: (Int, Int) of
106 case TE.encodeUtf8 str =~ TE.encodeUtf8 pat' :: (Int, Int) of
114 (-1,0) -> Nothing
107 (-1,0) -> Nothing
115 (start,len) -> Just $ calcScore start (start + len)
108 (start,len) -> Just $ calcScore start (start + len)
@@ -120,11 +113,11 @@ flexScore pat str =
120 -- escape prepends a backslash to "regexy" characters to prevent the
113 -- escape prepends a backslash to "regexy" characters to prevent the
121 -- matcher from crashing when trying to build the regex
114 -- matcher from crashing when trying to build the regex
122 escape :: Char -> Text
115 escape :: Char -> Text
123− escape c = if c `elem` ("[\\^$.|?*+(){}" :: String)
116+ escape c = if c `elem` T.unpack "[\\^$.|?*+(){}"
124 then T.pack ['\\', c]
117 then T.pack ['\\', c]
125 else T.singleton c
118 else T.singleton c
126 -- This just interleaves the search pattern with .*
119 -- This just interleaves the search pattern with .*
127 -- abcd[*] -> a.*b.*c.*d.*[*]
120 -- abcd[*] -> a.*b.*c.*d.*[*]
128− pat' = escape first <> foldMap (<> ".*") escapedPattern
121+ pat' = escape first' <> foldMap (<> ".*") escapedPattern
129 calcScore start end =
122 calcScore start end =
130 100.0 / fromIntegral ((1 + start) * (end - start + 1))
123 100.0 / fromIntegral ((1 + start) * (end - start + 1))
src/Language/PureScript/Ide/Pursuit.hs+5−11
@@ -16,18 +16,12 @@
16
16
17module Language.PureScript.Ide.Pursuit where
17module Language.PureScript.Ide.Pursuit where
18
18
19−import Prelude ()
19+import Protolude
20−import Prelude.Compat
21
20
22import qualified Control.Exception as E
21import qualified Control.Exception as E
23import Data.Aeson
22import Data.Aeson
24−import Data.ByteString (ByteString)
25import Data.ByteString.Lazy (fromStrict)
23import Data.ByteString.Lazy (fromStrict)
26−import Data.Foldable (toList)
27−import Data.Maybe (mapMaybe)
28−import Data.Monoid ((<>))
29import Data.String
24import Data.String
30−import Data.Text (Text)
31import qualified Data.Text as T
25import qualified Data.Text as T
32import Language.PureScript.Ide.Types
26import Language.PureScript.Ide.Types
33import Network.HTTP.Types.Header (hAccept)
27import Network.HTTP.Types.Header (hAccept)
@@ -41,12 +35,12 @@ queryPursuit q = do
41 let qClean = T.dropWhileEnd (== '.') q
35 let qClean = T.dropWhileEnd (== '.') q
42 req' <- parseUrl "http://pursuit.purescript.org/search"
36 req' <- parseUrl "http://pursuit.purescript.org/search"
43 let req = req'
37 let req = req'
44− { queryString=("q=" <> (fromString . T.unpack) qClean)
38+ { queryString= "q=" <> (fromString . T.unpack) qClean
45 , requestHeaders=[(hAccept, "application/json")]
39 , requestHeaders=[(hAccept, "application/json")]
46 }
40 }
47 m <- newManager tlsManagerSettings
41 m <- newManager tlsManagerSettings
48 withHTTP req m $ \resp ->
42 withHTTP req m $ \resp ->
49− P.fold (<>) "" id $ responseBody resp
43+ P.fold (<>) "" identity (responseBody resp)
50
44
51
45
52handler :: HttpException -> IO [a]
46handler :: HttpException -> IO [a]
@@ -59,7 +53,7 @@ searchPursuitForDeclarations query =
59 let results' = decode (fromStrict r) :: Maybe Array
53 let results' = decode (fromStrict r) :: Maybe Array
60 case results' of
54 case results' of
61 Nothing -> pure []
55 Nothing -> pure []
62− Just results -> pure (mapMaybe isDeclarationResponse (map fromJSON (toList results)))) `E.catch`
56+ Just results -> pure (mapMaybe (isDeclarationResponse . fromJSON) (toList results))) `E.catch`
63 handler
57 handler
64 where
58 where
65 isDeclarationResponse (Success a@DeclarationResponse{}) = Just a
59 isDeclarationResponse (Success a@DeclarationResponse{}) = Just a
@@ -71,7 +65,7 @@ findPackagesForModuleIdent query =
71 let results' = decode (fromStrict r) :: Maybe Array
65 let results' = decode (fromStrict r) :: Maybe Array
72 case results' of
66 case results' of
73 Nothing -> pure []
67 Nothing -> pure []
74− Just results -> pure (mapMaybe isModuleResponse (map fromJSON (toList results)))) `E.catch`
68+ Just results -> pure (mapMaybe (isModuleResponse . fromJSON) (toList results))) `E.catch`
75 handler
69 handler
76 where
70 where
77 isModuleResponse (Success a@ModuleResponse{}) = Just a
71 isModuleResponse (Success a@ModuleResponse{}) = Just a
src/Language/PureScript/Ide/Rebuild.hs+16−18
@@ -8,14 +8,12 @@ module Language.PureScript.Ide.Rebuild
8 ( rebuildFile
8 ( rebuildFile
9 ) where
9 ) where
10
10
11−import Control.Monad.Error.Class
11+import Protolude
12−import Control.Monad.IO.Class
12+
13import "monad-logger" Control.Monad.Logger
13import "monad-logger" Control.Monad.Logger
14−import Control.Monad.Reader
14+import qualified Data.List as List
15−import Control.Monad.Trans.Except
16import qualified Data.Map.Lazy as M
15import qualified Data.Map.Lazy as M
17−import Data.Maybe (fromJust, mapMaybe)
16+import Data.Maybe (fromJust)
18−import Data.Monoid ((<>))
19import qualified Data.Set as S
17import qualified Data.Set as S
20import qualified Language.PureScript as P
18import qualified Language.PureScript as P
21import Language.PureScript.Errors.JSON
19import Language.PureScript.Errors.JSON
@@ -23,8 +21,8 @@ import Language.PureScript.Ide.Error
23import Language.PureScript.Ide.State
21import Language.PureScript.Ide.State
24import Language.PureScript.Ide.Types
22import Language.PureScript.Ide.Types
25import Language.PureScript.Ide.Util
23import Language.PureScript.Ide.Util
26−import Prelude.Compat
27import System.IO.UTF8 (readUTF8File)
24import System.IO.UTF8 (readUTF8File)
25+import System.FilePath
28
26
29-- | Given a filepath performs the following steps:
27-- | Given a filepath performs the following steps:
30--
28--
@@ -42,14 +40,14 @@ import System.IO.UTF8 (readUTF8File)
42-- warnings, and if rebuilding fails, returns a @RebuildError@ with the
40-- warnings, and if rebuilding fails, returns a @RebuildError@ with the
43-- generated errors.
41-- generated errors.
44rebuildFile
42rebuildFile
45− :: (PscIde m, MonadLogger m, MonadError PscIdeError m)
43+ :: (Ide m, MonadLogger m, MonadError PscIdeError m)
46 => FilePath
44 => FilePath
47 -> m Success
45 -> m Success
48rebuildFile path = do
46rebuildFile path = do
49
47
50 input <- liftIO (readUTF8File path)
48 input <- liftIO (readUTF8File path)
51
49
52− m <- case snd <$> P.parseModuleFromFile id (path, input) of
50+ m <- case snd <$> P.parseModuleFromFile identity (path, input) of
53 Left parseError -> throwError
51 Left parseError -> throwError
54 . RebuildError
52 . RebuildError
55 . toJSONErrors False P.Error
53 . toJSONErrors False P.Error
@@ -60,7 +58,7 @@ rebuildFile path = do
60 -- correctly to the 'Environment'.
58 -- correctly to the 'Environment'.
61 externs <- sortExterns m =<< getExternFiles
59 externs <- sortExterns m =<< getExternFiles
62
60
63− outputDirectory <- confOutputPath . envConfiguration <$> ask
61+ outputDirectory <- confOutputPath . ideConfiguration <$> ask
64
62
65 -- For rebuilding, we want to 'RebuildAlways', but for inferring foreign
63 -- For rebuilding, we want to 'RebuildAlways', but for inferring foreign
66 -- modules using their file paths, we need to specify the path in the 'Map'.
64 -- modules using their file paths, we need to specify the path in the 'Map'.
@@ -82,7 +80,7 @@ rebuildFile path = do
82-- | Rebuilds a module but opens up its export list first and stores the result
80-- | Rebuilds a module but opens up its export list first and stores the result
83-- inside the rebuild cache
81-- inside the rebuild cache
84rebuildModuleOpen
82rebuildModuleOpen
85− :: (PscIde m, MonadLogger m, MonadError PscIdeError m)
83+ :: (Ide m, MonadLogger m, MonadError PscIdeError m)
86 => MakeActionsEnv
84 => MakeActionsEnv
87 -> [P.ExternsFile]
85 -> [P.ExternsFile]
88 -> P.Module
86 -> P.Module
@@ -100,14 +98,14 @@ rebuildModuleOpen makeEnv externs m = do
100 Right result -> do
98 Right result -> do
101 $(logDebug)
99 $(logDebug)
102 ("Setting Rebuild cache: " <> runModuleNameT (P.efModuleName result))
100 ("Setting Rebuild cache: " <> runModuleNameT (P.efModuleName result))
103− setCachedRebuild result
101+ cacheRebuild result
104
102
105-- | Parameters we can access while building our @MakeActions@
103-- | Parameters we can access while building our @MakeActions@
106data MakeActionsEnv =
104data MakeActionsEnv =
107 MakeActionsEnv
105 MakeActionsEnv
108 { maeOutputDirectory :: FilePath
106 { maeOutputDirectory :: FilePath
109− , maeFilePathMap :: M.Map P.ModuleName (Either P.RebuildPolicy FilePath)
107+ , maeFilePathMap :: Map P.ModuleName (Either P.RebuildPolicy FilePath)
110− , maeForeignPathMap :: M.Map P.ModuleName FilePath
108+ , maeForeignPathMap :: Map P.ModuleName FilePath
111 , maePrefixComment :: Bool
109 , maePrefixComment :: Bool
112 }
110 }
113
111
@@ -135,9 +133,9 @@ shushCodegen ma MakeActionsEnv{..} =
135-- module. Throws an error if there is a cyclic dependency within the
133-- module. Throws an error if there is a cyclic dependency within the
136-- ExternsFiles
134-- ExternsFiles
137sortExterns
135sortExterns
138− :: (PscIde m, MonadError PscIdeError m)
136+ :: (Ide m, MonadError PscIdeError m)
139 => P.Module
137 => P.Module
140− -> M.Map P.ModuleName P.ExternsFile
138+ -> Map P.ModuleName P.ExternsFile
141 -> m [P.ExternsFile]
139 -> m [P.ExternsFile]
142sortExterns m ex = do
140sortExterns m ex = do
143 sorted' <- runExceptT
141 sorted' <- runExceptT
@@ -149,11 +147,11 @@ sortExterns m ex = do
149 case sorted' of
147 case sorted' of
150 Left _ -> throwError (GeneralError "There was a cycle in the dependencies")
148 Left _ -> throwError (GeneralError "There was a cycle in the dependencies")
151 Right (sorted, graph) -> do
149 Right (sorted, graph) -> do
152− let deps = fromJust (lookup (P.getModuleName m) graph)
150+ let deps = fromJust (List.lookup (P.getModuleName m) graph)
153 pure $ mapMaybe getExtern (deps `inOrderOf` map P.getModuleName sorted)
151 pure $ mapMaybe getExtern (deps `inOrderOf` map P.getModuleName sorted)
154 where
152 where
155 mkShallowModule P.ExternsFile{..} =
153 mkShallowModule P.ExternsFile{..} =
156− P.Module undefined [] efModuleName (map mkImport efImports) Nothing
154+ P.Module (P.internalModuleSourceSpan "<rebuild>") [] efModuleName (map mkImport efImports) Nothing
157 mkImport (P.ExternsImport mn it iq) =
155 mkImport (P.ExternsImport mn it iq) =
158 P.ImportDeclaration mn it iq
156 P.ImportDeclaration mn it iq
159 getExtern mn = M.lookup mn ex
157 getExtern mn = M.lookup mn ex
src/Language/PureScript/Ide/Reexports.hs+23−15
@@ -15,19 +15,24 @@
15
15
16{-# LANGUAGE OverloadedStrings #-}
16{-# LANGUAGE OverloadedStrings #-}
17
17
18−module Language.PureScript.Ide.Reexports where
18+module Language.PureScript.Ide.Reexports
19+ ( resolveReexports2
20+ -- for tests
21+ , getReexports
22+ , replaceReexport
23+ , replaceReexports
24+ ) where
19
25
20
26
21−import Prelude ()
27+import Protolude
22−import Prelude.Compat
23
28
24import Data.List (union)
29import Data.List (union)
25−import Data.Map (Map)
26import qualified Data.Map as Map
30import qualified Data.Map as Map
27−import Data.Maybe
28import Language.PureScript.Ide.Types
31import Language.PureScript.Ide.Types
32+import Language.PureScript.Ide.Externs
33+import qualified Language.PureScript as P
29
34
30−getReexports :: Module -> [ExternDecl]
35+getReexports :: ModuleOld -> [ExternDecl]
31getReexports (mn, decls)= concatMap getExport decls
36getReexports (mn, decls)= concatMap getExport decls
32 where getExport d
37 where getExport d
33 | (Export mn') <- d
38 | (Export mn') <- d
@@ -48,32 +53,32 @@ replaceExportWithAliases decls ident =
48 , alias == ident = True
53 , alias == ident = True
49 | otherwise = False
54 | otherwise = False
50
55
51−replaceReexport :: ExternDecl -> Module -> Module -> Module
56+replaceReexport :: ExternDecl -> ModuleOld -> ModuleOld -> ModuleOld
52replaceReexport e@(Export _) (m, decls) (_, newDecls) =
57replaceReexport e@(Export _) (m, decls) (_, newDecls) =
53 (m, filter (/= e) decls `union` newDecls)
58 (m, filter (/= e) decls `union` newDecls)
54−replaceReexport _ _ _ = error "Should only get Exports here."
59+replaceReexport _ _ _ = P.internalError "Should only get Exports here"
55
60
56−emptyModule :: Module
61+emptyModule :: ModuleOld
57emptyModule = ("Empty", [])
62emptyModule = ("Empty", [])
58
63
59isExport :: ExternDecl -> Bool
64isExport :: ExternDecl -> Bool
60isExport (Export _) = True
65isExport (Export _) = True
61isExport _ = False
66isExport _ = False
62
67
63−removeExportDecls :: Module -> Module
68+removeExportDecls :: ModuleOld -> ModuleOld
64removeExportDecls = fmap (filter (not . isExport))
69removeExportDecls = fmap (filter (not . isExport))
65
70
66−replaceReexports :: Module -> Map ModuleIdent [ExternDecl] -> Module
71+replaceReexports :: ModuleOld -> Map ModuleIdent [ExternDecl] -> ModuleOld
67replaceReexports m db = result
72replaceReexports m db = result
68 where
73 where
69 reexports = getReexports m
74 reexports = getReexports m
70 result = foldl go (removeExportDecls m) reexports
75 result = foldl go (removeExportDecls m) reexports
71
76
72− go :: Module -> ExternDecl -> Module
77+ go :: ModuleOld -> ExternDecl -> ModuleOld
73 go m' re@(Export name) = replaceReexport re m' (getModule name)
78 go m' re@(Export name) = replaceReexport re m' (getModule name)
74− go _ _ = error "partiality! woohoo"
79+ go _ _ = P.internalError "Should only get Exports here"
75
80
76− getModule :: ModuleIdent -> Module
81+ getModule :: ModuleIdent -> ModuleOld
77 getModule name = clean res
82 getModule name = clean res
78 where
83 where
79 res = fromMaybe emptyModule $ (name , ) <$> Map.lookup name db
84 res = fromMaybe emptyModule $ (name , ) <$> Map.lookup name db
@@ -81,9 +86,12 @@ replaceReexports m db = result
81 -- infinite loops
86 -- infinite loops
82 clean (mn, decls) = (mn,) (filter (/= Export mn) decls)
87 clean (mn, decls) = (mn,) (filter (/= Export mn) decls)
83
88
84−resolveReexports :: Map ModuleIdent [ExternDecl] -> Module -> Module
89+resolveReexports :: Map ModuleIdent [ExternDecl] -> ModuleOld -> ModuleOld
85resolveReexports modules m =
90resolveReexports modules m =
86 let replaced = replaceReexports m modules
91 let replaced = replaceReexports m modules
87 in if null (getReexports replaced)
92 in if null (getReexports replaced)
88 then replaced
93 then replaced
89 else resolveReexports modules replaced
94 else resolveReexports modules replaced
95+
96+resolveReexports2 :: Map Text [ExternDecl] -> ModuleOld -> Module
97+resolveReexports2 decls = convertModule . resolveReexports decls
src/Language/PureScript/Ide/SourceFile.hs+52−74
@@ -14,107 +14,85 @@
14
14
15{-# LANGUAGE OverloadedStrings #-}
15{-# LANGUAGE OverloadedStrings #-}
16
16
17−module Language.PureScript.Ide.SourceFile where
17+module Language.PureScript.Ide.SourceFile
18+ ( parseModule
19+ , getImportsForFile
20+ -- SOON...
21+ , getDeclPosition
22+ ) where
18
23
19−import Prelude
24+import Protolude
20
25
21−import Control.Monad.Error.Class
22−import Control.Monad.IO.Class
23−import Control.Monad.Trans.Except
24−import Data.Maybe (mapMaybe)
25−import Data.Monoid
26−import qualified Data.Text as T
27−import qualified Language.PureScript.AST.Declarations as D
26+import qualified Language.PureScript as P
28−import qualified Language.PureScript.AST.SourcePos as SP
29import Language.PureScript.Ide.Error
27import Language.PureScript.Ide.Error
28+import Language.PureScript.Ide.Util
30import Language.PureScript.Ide.Externs (unwrapPositioned,
29import Language.PureScript.Ide.Externs (unwrapPositioned,
31 unwrapPositionedRef)
30 unwrapPositionedRef)
32import Language.PureScript.Ide.Types
31import Language.PureScript.Ide.Types
33−import qualified Language.PureScript.Names as N
32+import System.FilePath
34−import qualified Language.PureScript.Parser as P
35−import System.Directory
36import System.IO.UTF8 (readUTF8File)
33import System.IO.UTF8 (readUTF8File)
37
34
38−parseModuleFromFile :: (MonadIO m, MonadError PscIdeError m) =>
35+parseModule
39− FilePath -> m D.Module
36+ :: (MonadIO m)
40−parseModuleFromFile fp = do
37+ => FilePath
41− exists <- liftIO (doesFileExist fp)
38+ -> m (Either FilePath (FilePath, P.Module) )
42− if exists
39+parseModule path = do
43− then do
44− content <- liftIO (readUTF8File fp)
40+ contents <- liftIO (readUTF8File path)
45− let m = do tokens <- P.lex fp content
41+ case P.parseModuleFromFile identity (path, contents) of
46− P.runTokenParser "" P.parseModule tokens
42+ Left _ -> pure (Left path)
47− either (throwError . (`ParseError` "File could not be parsed.")) pure m
43+ Right m -> pure (Right m)
48− else throwError (NotFound "File does not exist.")
49
44
50−-- data Module = Module SourceSpan [Comment] ModuleName [Declaration] (Maybe [DeclarationRef])
45+getImports :: P.Module -> [(P.ModuleName, P.ImportDeclarationType, Maybe P.ModuleName)]
51−
52−getDeclarations :: D.Module -> [D.Declaration]
53−getDeclarations (D.Module _ _ _ declarations _) = declarations
54−
55−getImports :: D.Module -> [D.Declaration]
56−getImports (D.Module _ _ _ declarations _) =
46+getImports (P.Module _ _ _ declarations _) =
57 mapMaybe isImport declarations
47 mapMaybe isImport declarations
58 where
48 where
59− isImport (D.PositionedDeclaration _ _ (i@D.ImportDeclaration{})) = Just i
49+ isImport (P.PositionedDeclaration _ _ (P.ImportDeclaration a b c)) = Just (a, b, c)
60 isImport _ = Nothing
50 isImport _ = Nothing
61
51
62getImportsForFile :: (MonadIO m, MonadError PscIdeError m) =>
52getImportsForFile :: (MonadIO m, MonadError PscIdeError m) =>
63 FilePath -> m [ModuleImport]
53 FilePath -> m [ModuleImport]
64getImportsForFile fp = do
54getImportsForFile fp = do
65− module' <- parseModuleFromFile fp
55+ moduleE <- parseModule fp
66− let imports = getImports module'
56+ case moduleE of
57+ Left _ -> throwError (GeneralError "Failed to parse sourcefile.")
58+ Right (_, module') ->
67− pure (mkModuleImport . unwrapPositionedImport <$> imports)
59+ pure (mkModuleImport . unwrapPositionedImport <$> getImports module')
68− where
60+ where
69− mkModuleImport (D.ImportDeclaration mn importType' qualifier) =
61+ mkModuleImport (mn, importType', qualifier) =
70− ModuleImport
62+ ModuleImport
71− (T.pack (N.runModuleName mn))
63+ (runModuleNameT mn)
72− importType'
64+ importType'
73− (T.pack . N.runModuleName <$> qualifier)
65+ (runModuleNameT <$> qualifier)
74− mkModuleImport _ = error "Shouldn't have gotten anything but Imports here"
75− unwrapPositionedImport (D.ImportDeclaration mn importType' qualifier) =
66+ unwrapPositionedImport (mn, it, q) = (mn, unwrapImportType it, q)
76− D.ImportDeclaration mn (unwrapImportType importType') qualifier
77− unwrapPositionedImport x = x
78− unwrapImportType (D.Explicit decls) = D.Explicit (map unwrapPositionedRef decls)
67+ unwrapImportType (P.Explicit decls) = P.Explicit (map unwrapPositionedRef decls)
79− unwrapImportType (D.Hiding decls) = D.Hiding (map unwrapPositionedRef decls)
68+ unwrapImportType (P.Hiding decls) = P.Hiding (map unwrapPositionedRef decls)
80− unwrapImportType D.Implicit = D.Implicit
69+ unwrapImportType P.Implicit = P.Implicit
81−
82−getPositionedImports :: D.Module -> [D.Declaration]
83−getPositionedImports (D.Module _ _ _ declarations _) =
84− mapMaybe isImport declarations
85− where
86− isImport i@(D.PositionedDeclaration _ _ D.ImportDeclaration{}) = Just i
87− isImport _ = Nothing
88
70
89−getDeclPosition :: D.Module -> String -> Maybe SP.SourceSpan
71+getDeclPosition :: P.Module -> Text -> Maybe P.SourceSpan
90getDeclPosition m ident = getFirst (foldMap (match ident) decls)
72getDeclPosition m ident = getFirst (foldMap (match ident) decls)
91 where
73 where
92 decls = getDeclarations m
74 decls = getDeclarations m
93− match q (D.PositionedDeclaration ss _ decl) = First (if go q decl
75+ match q (P.PositionedDeclaration ss _ decl) = First (if go q decl
94 then Just ss
76 then Just ss
95 else Nothing)
77 else Nothing)
96 match _ _ = First Nothing
78 match _ _ = First Nothing
97
79
98− go q (D.DataDeclaration _ name _ constructors) =
80+ go q (P.DataDeclaration _ name _ constructors) =
99 properEqual name q || any (\(x,_) -> properEqual x q) constructors
81 properEqual name q || any (\(x,_) -> properEqual x q) constructors
100− go q (D.DataBindingGroupDeclaration decls') = any (go q) decls'
82+ go q (P.DataBindingGroupDeclaration decls') = any (go q) decls'
101− go q (D.TypeSynonymDeclaration name _ _) = properEqual name q
83+ go q (P.TypeSynonymDeclaration name _ _) = properEqual name q
102− go q (D.TypeDeclaration ident' _) = identEqual ident' q
84+ go q (P.TypeDeclaration ident' _) = identEqual ident' q
103− go q (D.ValueDeclaration ident' _ _ _) = identEqual ident' q
85+ go q (P.ValueDeclaration ident' _ _ _) = identEqual ident' q
104− go q (D.ExternDeclaration ident' _) = identEqual ident' q
86+ go q (P.ExternDeclaration ident' _) = identEqual ident' q
105− go q (D.ExternDataDeclaration name _) = properEqual name q
87+ go q (P.ExternDataDeclaration name _) = properEqual name q
106− go q (D.TypeClassDeclaration name _ _ members) =
88+ go q (P.TypeClassDeclaration name _ _ members) =
107 properEqual name q || any (go q . unwrapPositioned) members
89 properEqual name q || any (go q . unwrapPositioned) members
108− go q (D.TypeInstanceDeclaration ident' _ _ _ _) =
90+ go q (P.TypeInstanceDeclaration ident' _ _ _ _) =
109 identEqual ident' q
91 identEqual ident' q
110 go _ _ = False
92 go _ _ = False
111
93
112− properEqual x q = N.runProperName x == q
94+ properEqual x q = runProperNameT x == q
113− identEqual x q = N.runIdent x == q
95+ identEqual x q = runIdentT x == q
114
96
115−goToDefinition :: String -> FilePath -> IO (Maybe SP.SourceSpan)
97+ getDeclarations :: P.Module -> [P.Declaration]
116−goToDefinition q fp = do
98+ getDeclarations (P.Module _ _ _ declarations _) = declarations
117− m <- runExceptT (parseModuleFromFile fp)
118− case m of
119− Right module' -> pure (getDeclPosition module' q)
120− Left _ -> pure Nothing
src/Language/PureScript/Ide/State.hs+156−88
@@ -17,127 +17,195 @@
17{-# LANGUAGE TemplateHaskell #-}
17{-# LANGUAGE TemplateHaskell #-}
18
18
19module Language.PureScript.Ide.State
19module Language.PureScript.Ide.State
20− ( getPscIdeState
20+ ( getLoadedModulenames
21 , getExternFiles
21 , getExternFiles
22− , getModule
22+ , insertModuleOld
23− , getModuleWithReexports
23+ , resetIdeState
24− , getAllModulesWithReexports
24+ , cacheRebuild
25− , getAllModulesWithReexportsAndCache
25+ , insertExterns
26 , insertModule
26 , insertModule
27 , insertModuleSTM
27 , insertModuleSTM
28− , getCachedRebuild
28+ , insertExternsSTM
29− , resetPscIdeState
29+ , getAllModules2
30− , setCachedRebuild
30+ , getStage1
31+ , setStage1
32+ , getStage2
33+ , setStage2
34+ , populateStage2
35+ , populateStage2STM
31 ) where
36 ) where
32
37
33−import Prelude ()
38+import Protolude
34−import Prelude.Compat
39+import qualified Prelude
35
40
36import Control.Concurrent.STM
41import Control.Concurrent.STM
37−import Control.Monad.IO.Class
38import "monad-logger" Control.Monad.Logger
42import "monad-logger" Control.Monad.Logger
39−import Control.Monad.Reader.Class
40import qualified Data.Map.Lazy as M
43import qualified Data.Map.Lazy as M
41−import Data.Maybe (mapMaybe)
42−import Data.Monoid
43import Language.PureScript.Externs
44import Language.PureScript.Externs
44import Language.PureScript.Ide.Externs
45import Language.PureScript.Ide.Externs
45import Language.PureScript.Ide.Reexports
46import Language.PureScript.Ide.Reexports
46import Language.PureScript.Ide.Types
47import Language.PureScript.Ide.Types
47import Language.PureScript.Ide.Util
48import Language.PureScript.Ide.Util
48import qualified Language.PureScript as P
49import qualified Language.PureScript as P
50+import System.Clock
51+import System.FilePath
49
52
50−-- | Resets the PscIdeState to emptyPscIdeState
53+-- | Resets all State inside psc-ide
51−resetPscIdeState :: PscIde m => m ()
54+resetIdeState :: Ide m => m ()
52−resetPscIdeState = do
55+resetIdeState = do
53 stateVar <- envStateVar <$> ask
56 stateVar <- envStateVar <$> ask
57+ ideVar <- ideStateVar <$> ask
58+ liftIO . atomically $ do
54− liftIO $ atomically (writeTVar stateVar emptyPscIdeState)
59+ writeTVar stateVar emptyPscIdeState
60+ writeTVar ideVar emptyIdeState
61+ setStage2STM ideVar emptyStage2
55
62
56−-- | Gets the entire PscIdeState
63+-- | Gets the loaded Modulenames
57−getPscIdeState :: PscIde m => m PscIdeState
64+getLoadedModulenames :: Ide m => m [P.ModuleName]
58−getPscIdeState = do
65+getLoadedModulenames = M.keys <$> getExternFiles
59− stateVar <- envStateVar <$> ask
60− liftIO (readTVarIO stateVar)
61
66
62-- | Gets all loaded ExternFiles
67-- | Gets all loaded ExternFiles
63−getExternFiles :: (PscIde m) => m (M.Map P.ModuleName ExternsFile)
68+getExternFiles :: Ide m => m (M.Map P.ModuleName ExternsFile)
64−getExternFiles = do
69+getExternFiles = s1Externs <$> getStage1
65− stateVar <- envStateVar <$> ask
66− liftIO (pscIdeStateExternsFiles <$> readTVarIO stateVar)
67−
68−-- | Gets all loaded Modules and resolves Reexports
69−getAllModulesWithReexports :: (PscIde m) => m [Module]
70−getAllModulesWithReexports = getAllModulesWithReexports' <$> getPscIdeState
71−
72−-- | Pure version of @getAllModulesWithReexports@
73−getAllModulesWithReexports' :: PscIdeState -> [Module]
74−getAllModulesWithReexports' state =
75− mapMaybe (getModuleWithReexports' state) (M.keys (pscIdeStateModules state))
76−
77−-- | Checks if the given ModuleName matches the last rebuild cache and if it
78−-- does, runs @getAllModulesWithReexports@ with the cached module replacing the
79−-- loaded module
80−getAllModulesWithReexportsAndCache
81− :: (PscIde m)
82− => Maybe P.ModuleName
83− -> m [Module]
84−getAllModulesWithReexportsAndCache Nothing = getAllModulesWithReexports
85−getAllModulesWithReexportsAndCache (Just mn) = do
86− state <- getPscIdeState
87− cachedRebuild <- getCachedRebuild
88− case cachedRebuild of
89− Just (cachedIdent, ef) | cachedIdent == mn ->
90− pure (getAllModulesWithReexports' (insertModule' ef state))
91− _ -> getAllModulesWithReexports
92−
93−-- | Looks up a single Module inside the loaded Modules
94−getModule :: (PscIde m) => ModuleIdent -> m (Maybe Module)
95−getModule m = getModule' <$> getPscIdeState <*> pure m
96−
97−-- | Pure version of @getModule@
98−getModule' :: PscIdeState -> ModuleIdent -> Maybe Module
99−getModule' ps mi = (mi,) <$> M.lookup mi (pscIdeStateModules ps)
100−
101−-- | Looks up a single Module and resolves its Reexports
102−getModuleWithReexports :: PscIde m => ModuleIdent -> m (Maybe Module)
103−getModuleWithReexports i = getModuleWithReexports' <$> getPscIdeState <*> pure i
104−
105−-- | Pure version of @getModuleWithReexports@
106−getModuleWithReexports' :: PscIdeState -> ModuleIdent -> Maybe Module
107−getModuleWithReexports' ps mi =
108− resolveReexports (pscIdeStateModules ps) <$> getModule' ps mi
109
70
110-- | Inserts an @ExternsFile@ into the PscIdeState. Also converts the
71-- | Inserts an @ExternsFile@ into the PscIdeState. Also converts the
111-- ExternsFile into psc-ide's internal Declaration format
72-- ExternsFile into psc-ide's internal Declaration format
112−insertModule :: (PscIde m, MonadLogger m) =>
73+-- TODO: should be removed when the "old" Declaration format gets removed
113− ExternsFile -> m ()
74+insertModuleOld :: Ide m => ExternsFile -> m ()
114−insertModule externsFile = do
75+insertModuleOld externsFile = do
115 stateVar <- envStateVar <$> ask
76 stateVar <- envStateVar <$> ask
116− let moduleName = efModuleName externsFile
117− $(logDebug) $ "Inserting Module: " <> runModuleNameT moduleName
118− liftIO . atomically $ insertModuleSTM stateVar externsFile
77+ liftIO . atomically $ insertModuleOldSTM stateVar externsFile
119
78
120−-- | STM version of insertModule
79+-- | STM version of insertModuleOld
121−insertModuleSTM :: TVar PscIdeState -> ExternsFile -> STM ()
80+insertModuleOldSTM :: TVar PscIdeState -> ExternsFile -> STM ()
122−insertModuleSTM st ef = modifyTVar st (insertModule' ef)
81+insertModuleOldSTM st ef = modifyTVar st (insertModule' ef)
123
82
124−-- | Pure version of insertModule
83+-- | Pure version of insertModuleOld
125insertModule' :: ExternsFile -> PscIdeState -> PscIdeState
84insertModule' :: ExternsFile -> PscIdeState -> PscIdeState
126insertModule' ef state =
85insertModule' ef state =
127 state
86 state
128− { pscIdeStateExternsFiles =
129− M.insert (efModuleName ef) ef (pscIdeStateExternsFiles state)
130− , pscIdeStateModules = let (mn, decls) = convertExterns ef
87+ { pscIdeStateModules = let (mn, decls) = convertExterns ef
131 in M.insert mn decls (pscIdeStateModules state)
88 in M.insert mn decls (pscIdeStateModules state)
132 }
89 }
133
90
91+-- | Insert a Module into Stage1 of the State
92+insertModule :: Ide m => (FilePath, P.Module) -> m ()
93+insertModule module' = do
94+ stateVar <- ideStateVar <$> ask
95+ liftIO . atomically $ insertModuleSTM stateVar module'
96+
97+-- | STM version of insertModule
98+insertModuleSTM :: TVar IdeState -> (FilePath, P.Module) -> STM ()
99+insertModuleSTM ref (fp, module') =
100+ modifyTVar ref $ \x ->
101+ x { ideStage1 = (ideStage1 x) {
102+ s1Modules = M.insert
103+ (P.getModuleName module')
104+ (module', fp)
105+ (s1Modules (ideStage1 x))}}
106+
107+-- | Retrieves Stage1 from the State.
108+-- This includes loaded Externfiles
109+-- (TODO: as soon as we actually parse the modules) aswell as the parsed modules
110+getStage1 :: Ide m => m Stage1
111+getStage1 = do
112+ st <- ideStateVar <$> ask
113+ fmap ideStage1 . liftIO . readTVarIO $ st
114+
115+-- | STM version of getStage1
116+getStage1STM :: TVar IdeState -> STM Stage1
117+getStage1STM ref = ideStage1 <$> readTVar ref
118+
119+-- | Sets Stage1 inside the compiler
120+setStage1 :: Ide m => Stage1 -> m ()
121+setStage1 s1 = do
122+ st <- ideStateVar <$> ask
123+ liftIO . atomically . modifyTVar st $ \x ->
124+ x {ideStage1 = s1}
125+ pure ()
126+
127+-- TODO: Soon to be Stage3
128+-- | Retrieves Stage2 from the State.
129+-- This includes the denormalized Declarations and cached rebuilds
130+getStage2 :: Ide m => m Stage2
131+getStage2 = do
132+ st <- ideStateVar <$> ask
133+ fmap ideStage2 . liftIO . readTVarIO $ st
134+
135+-- | Sets Stage2 inside the compiler
136+setStage2 :: Ide m => Stage2 -> m ()
137+setStage2 s2 = do
138+ st <- ideStateVar <$> ask
139+ liftIO . atomically $ setStage2STM st s2
140+
141+-- | STM version of setStage2
142+setStage2STM :: TVar IdeState -> Stage2 -> STM ()
143+setStage2STM ref s2 = do
144+ modifyTVar ref $ \x ->
145+ x {ideStage2 = s2}
146+ pure ()
147+
148+-- | Checks if the given ModuleName matches the last rebuild cache and if it
149+-- does returns all loaded definitions + the definitions inside the rebuild
150+-- cache
151+getAllModules2 :: Ide m => Maybe P.ModuleName -> m [(P.ModuleName, [IdeDeclaration])]
152+getAllModules2 mmoduleName = do
153+ declarations <- s2Declarations <$> getStage2
154+ rebuild <- cachedRebuild
155+ case mmoduleName of
156+ Nothing -> pure (M.toList declarations)
157+ Just moduleName ->
158+ case rebuild of
159+ Just (cachedModulename, ef)
160+ | cachedModulename == moduleName ->
161+ pure . M.toList $
162+ M.insert moduleName (snd . convertModule . convertExterns $ ef) declarations
163+ _ -> pure (M.toList declarations)
164+
165+-- | Adds an ExternsFile into psc-ide's State Stage1. This does not populate the
166+-- following Stages, which needs to be done after all the necessary Exterms have
167+-- been loaded.
168+insertExterns :: Ide m => ExternsFile -> m ()
169+insertExterns ef = do
170+ st <- ideStateVar <$> ask
171+ liftIO (atomically (insertExternsSTM st ef))
172+
173+-- | STM version of insertExterns
174+insertExternsSTM :: TVar IdeState -> ExternsFile -> STM ()
175+insertExternsSTM ref ef =
176+ modifyTVar ref $ \x ->
177+ x { ideStage1 = (ideStage1 x) {
178+ s1Externs = M.insert (efModuleName ef) ef (s1Externs (ideStage1 x))}}
179+
134-- | Sets rebuild cache to the given ExternsFile
180-- | Sets rebuild cache to the given ExternsFile
135−setCachedRebuild :: PscIde m => ExternsFile -> m ()
181+cacheRebuild :: Ide m => ExternsFile -> m ()
136−setCachedRebuild ef = do
182+cacheRebuild ef = do
137− st <- envStateVar <$> ask
183+ st <- ideStateVar <$> ask
138 liftIO . atomically . modifyTVar st $ \x ->
184 liftIO . atomically . modifyTVar st $ \x ->
185+ x { ideStage2 = (ideStage2 x) {
139− x { pscIdeStateCachedRebuild = Just (efModuleName ef, ef) }
186+ s2CachedRebuild = Just (efModuleName ef, ef)}}
140
187
141-- | Retrieves the rebuild cache
188-- | Retrieves the rebuild cache
142−getCachedRebuild :: PscIde m => m (Maybe (P.ModuleName, ExternsFile))
189+cachedRebuild :: Ide m => m (Maybe (P.ModuleName, ExternsFile))
143−getCachedRebuild = pscIdeStateCachedRebuild <$> getPscIdeState
190+cachedRebuild = s2CachedRebuild <$> getStage2
191+
192+-- | Resolves reexports and populates Stage2 with data to be used in queries.
193+populateStage2 :: (Ide m, MonadLogger m) => m ()
194+populateStage2 = do
195+ st <- ideStateVar <$> ask
196+ duration <- liftIO $ do
197+ start <- getTime Monotonic
198+ atomically (populateStage2STM st)
199+ end <- getTime Monotonic
200+ pure (Prelude.show (diffTimeSpec start end))
201+ $(logDebug) $ "Finished populating Stage2 in " <> toS duration
202+
203+-- | STM version of populateStage2
204+populateStage2STM :: TVar IdeState -> STM ()
205+populateStage2STM ref = do
206+ externs <- s1Externs <$> getStage1STM ref
207+ -- Build the "old" ExternDecl format
208+ let modules = M.mapKeys runModuleNameT (M.map (snd . convertExterns) externs)
209+ -- Convert ExternDecl into IdeDeclaration
210+ declarations = resolveReexports2 modules <$> M.toList modules
211+ setStage2STM ref (Stage2 (M.fromList declarations) Nothing)
src/Language/PureScript/Ide/Types.hs+69−43
@@ -12,32 +12,23 @@
12-- Type definitions for psc-ide
12-- Type definitions for psc-ide
13-----------------------------------------------------------------------------
13-----------------------------------------------------------------------------
14
14
15−{-# LANGUAGE OverloadedStrings #-}
15+{-# LANGUAGE OverloadedStrings #-}
16
16
17module Language.PureScript.Ide.Types where
17module Language.PureScript.Ide.Types where
18
18
19−import Prelude ()
19+import Protolude
20−import Prelude.Compat
21
20
22import Control.Concurrent.STM
21import Control.Concurrent.STM
23−import Control.Monad
24−import Control.Monad.Reader.Class
25−import Control.Monad.Trans
26import Data.Aeson
22import Data.Aeson
27import Data.Map.Lazy as M
23import Data.Map.Lazy as M
28−import Data.Maybe (maybeToList)
29−import Data.Text (Text (), pack, unpack)
30−import qualified Language.PureScript.AST.Declarations as D
31−import Language.PureScript.Externs
32import qualified Language.PureScript.Errors.JSON as P
24import qualified Language.PureScript.Errors.JSON as P
33−import qualified Language.PureScript.Names as N
34import qualified Language.PureScript as P
25import qualified Language.PureScript as P
35−
26+import Language.PureScript.Ide.Conversions
27+import System.FilePath
36−import Text.Parsec
28+import Text.Parsec as Parsec
37import Text.Parsec.Text
29import Text.Parsec.Text
38
30
39type Ident = Text
31type Ident = Text
40−type DeclIdent = Text
41type ModuleIdent = Text
32type ModuleIdent = Text
42
33
43data ExternDecl
34data ExternDecl
@@ -53,10 +44,10 @@ data ExternDecl
53 -- | A module declaration
44 -- | A module declaration
54 | ModuleDecl
45 | ModuleDecl
55 ModuleIdent -- The modules name
46 ModuleIdent -- The modules name
56− [DeclIdent] -- The exported identifiers
47+ [Ident] -- The exported identifiers
57 -- | A data/newtype declaration
48 -- | A data/newtype declaration
58 | DataConstructor
49 | DataConstructor
59− DeclIdent -- The type name
50+ Ident -- The type name
60 (P.ProperName 'P.TypeName)
51 (P.ProperName 'P.TypeName)
61 P.Type -- The "type"
52 P.Type -- The "type"
62 -- | An exported module
53 -- | An exported module
@@ -66,37 +57,72 @@ data ExternDecl
66 | Export ModuleIdent -- The exported Modules name
57 | Export ModuleIdent -- The exported Modules name
67 deriving (Show,Eq,Ord)
58 deriving (Show,Eq,Ord)
68
59
69−type Module = (ModuleIdent, [ExternDecl])
60+data IdeDeclaration
61+ = IdeValue Ident P.Type
62+ | IdeType (P.ProperName 'P.TypeName) P.Kind
63+ | IdeTypeSynonym (P.ProperName 'P.TypeName) P.Type
64+ | IdeDataConstructor Ident (P.ProperName 'P.TypeName) P.Type
65+ | IdeTypeClass (P.ProperName 'P.ClassName)
66+ | IdeValueOperator (P.OpName 'P.ValueOpName) Ident P.Precedence P.Associativity
67+ | IdeTypeOperator (P.OpName 'P.TypeOpName) Ident P.Precedence P.Associativity
68+ deriving (Show, Eq, Ord)
69+
70+type Module = (P.ModuleName, [IdeDeclaration])
71+type ModuleOld = (Text, [ExternDecl])
70
72
71data Configuration =
73data Configuration =
72 Configuration
74 Configuration
73 { confOutputPath :: FilePath
75 { confOutputPath :: FilePath
74 , confDebug :: Bool
76 , confDebug :: Bool
77+ , confGlobs :: [FilePath]
75 }
78 }
76
79
77−data PscIdeEnvironment =
80+data IdeEnvironment =
78− PscIdeEnvironment
81+ IdeEnvironment
79 { envStateVar :: TVar PscIdeState
82 { envStateVar :: TVar PscIdeState
83+ , ideStateVar :: TVar IdeState
80− , envConfiguration :: Configuration
84+ , ideConfiguration :: Configuration
81 }
85 }
82
86
83−type PscIde m = (MonadIO m, MonadReader PscIdeEnvironment m)
87+type Ide m = (MonadIO m, MonadReader IdeEnvironment m)
84
88
85data PscIdeState =
89data PscIdeState =
86 PscIdeState
90 PscIdeState
87 { pscIdeStateModules :: M.Map Text [ExternDecl]
91 { pscIdeStateModules :: M.Map Text [ExternDecl]
88− , pscIdeStateExternsFiles :: M.Map P.ModuleName ExternsFile
89− , pscIdeStateCachedRebuild :: Maybe (P.ModuleName, ExternsFile)
90 } deriving Show
92 } deriving Show
91
93
92emptyPscIdeState :: PscIdeState
94emptyPscIdeState :: PscIdeState
93−emptyPscIdeState = PscIdeState M.empty M.empty Nothing
95+emptyPscIdeState = PscIdeState M.empty
96+
97+data IdeState = IdeState
98+ { ideStage1 :: Stage1
99+ , ideStage2 :: Stage2
100+ }
101+
102+emptyIdeState :: IdeState
103+emptyIdeState = IdeState emptyStage1 emptyStage2
104+
105+emptyStage1 :: Stage1
106+emptyStage1 = Stage1 M.empty M.empty
107+
108+emptyStage2 :: Stage2
109+emptyStage2 = Stage2 M.empty Nothing
110+
111+data Stage1 = Stage1
112+ { s1Externs :: M.Map P.ModuleName P.ExternsFile
113+ , s1Modules :: M.Map P.ModuleName (P.Module, FilePath)
114+ }
115+
116+data Stage2 = Stage2
117+ { s2Declarations :: M.Map P.ModuleName [IdeDeclaration]
118+ , s2CachedRebuild :: Maybe (P.ModuleName, P.ExternsFile)
119+ }
94
120
95−data Match = Match ModuleIdent ExternDecl
121+data Match = Match P.ModuleName IdeDeclaration
96− deriving (Show, Eq)
122+ deriving (Show, Eq)
97
123
98newtype Completion =
124newtype Completion =
99− Completion (ModuleIdent, DeclIdent, Text)
125+ Completion (ModuleIdent, Ident, Text)
100 deriving (Show,Eq)
126 deriving (Show,Eq)
101
127
102instance ToJSON Completion where
128instance ToJSON Completion where
@@ -106,7 +132,7 @@ instance ToJSON Completion where
106data ModuleImport =
132data ModuleImport =
107 ModuleImport
133 ModuleImport
108 { importModuleName :: ModuleIdent
134 { importModuleName :: ModuleIdent
109− , importType :: D.ImportDeclarationType
135+ , importType :: P.ImportDeclarationType
110 , importQualifier :: Maybe Text
136 , importQualifier :: Maybe Text
111 } deriving(Show)
137 } deriving(Show)
112
138
@@ -116,25 +142,25 @@ instance Eq ModuleImport where
116 && importQualifier mi1 == importQualifier mi2
142 && importQualifier mi1 == importQualifier mi2
117
143
118instance ToJSON ModuleImport where
144instance ToJSON ModuleImport where
119− toJSON (ModuleImport mn D.Implicit qualifier) =
145+ toJSON (ModuleImport mn P.Implicit qualifier) =
120 object $ [ "module" .= mn
146 object $ [ "module" .= mn
121 , "importType" .= ("implicit" :: Text)
147 , "importType" .= ("implicit" :: Text)
122 ] ++ fmap (\x -> "qualifier" .= x) (maybeToList qualifier)
148 ] ++ fmap (\x -> "qualifier" .= x) (maybeToList qualifier)
123− toJSON (ModuleImport mn (D.Explicit refs) _) =
149+ toJSON (ModuleImport mn (P.Explicit refs) _) =
124 object [ "module" .= mn
150 object [ "module" .= mn
125 , "importType" .= ("explicit" :: Text)
151 , "importType" .= ("explicit" :: Text)
126 , "identifiers" .= (identifierFromDeclarationRef <$> refs)
152 , "identifiers" .= (identifierFromDeclarationRef <$> refs)
127 ]
153 ]
128− toJSON (ModuleImport mn (D.Hiding refs) _) =
154+ toJSON (ModuleImport mn (P.Hiding refs) _) =
129 object [ "module" .= mn
155 object [ "module" .= mn
130 , "importType" .= ("hiding" :: Text)
156 , "importType" .= ("hiding" :: Text)
131 , "identifiers" .= (identifierFromDeclarationRef <$> refs)
157 , "identifiers" .= (identifierFromDeclarationRef <$> refs)
132 ]
158 ]
133
159
134−identifierFromDeclarationRef :: D.DeclarationRef -> String
160+identifierFromDeclarationRef :: P.DeclarationRef -> Text
135−identifierFromDeclarationRef (D.TypeRef name _) = N.runProperName name
161+identifierFromDeclarationRef (P.TypeRef name _) = runProperNameT name
136−identifierFromDeclarationRef (D.ValueRef ident) = N.runIdent ident
162+identifierFromDeclarationRef (P.ValueRef ident) = runIdentT ident
137−identifierFromDeclarationRef (D.TypeClassRef name) = N.runProperName name
163+identifierFromDeclarationRef (P.TypeClassRef name) = runProperNameT name
138identifierFromDeclarationRef _ = ""
164identifierFromDeclarationRef _ = ""
139
165
140data Success =
166data Success =
@@ -182,14 +208,14 @@ data PursuitResponse =
182 ModuleResponse ModuleIdent Text
208 ModuleResponse ModuleIdent Text
183 -- | A Pursuit Response for a declaration. Consist of the declarations type,
209 -- | A Pursuit Response for a declaration. Consist of the declarations type,
184 -- module, name and package
210 -- module, name and package
185− | DeclarationResponse Text ModuleIdent DeclIdent Text
211+ | DeclarationResponse Text ModuleIdent Ident Text
186 deriving (Show,Eq)
212 deriving (Show,Eq)
187
213
188instance FromJSON PursuitResponse where
214instance FromJSON PursuitResponse where
189 parseJSON (Object o) = do
215 parseJSON (Object o) = do
190 package <- o .: "package"
216 package <- o .: "package"
191 info <- o .: "info"
217 info <- o .: "info"
192− (type' :: String) <- info .: "type"
218+ (type' :: Text) <- info .: "type"
193 case type' of
219 case type' of
194 "module" -> do
220 "module" -> do
195 name <- info .: "module"
221 name <- info .: "module"
@@ -204,26 +230,26 @@ instance FromJSON PursuitResponse where
204
230
205typeParse :: Text -> Either Text (Text, Text)
231typeParse :: Text -> Either Text (Text, Text)
206typeParse t = case parse parseType "" t of
232typeParse t = case parse parseType "" t of
207− Right (x,y) -> Right (pack x, pack y)
233+ Right (x,y) -> Right (x, y)
208− Left err -> Left (pack (show err))
234+ Left err -> Left (show err)
209 where
235 where
210− parseType :: Parser (String, String)
236+ parseType :: Parser (Text, Text)
211 parseType = do
237 parseType = do
212 name <- identifier
238 name <- identifier
213 _ <- string "::"
239 _ <- string "::"
214 spaces
240 spaces
215 type' <- many1 anyChar
241 type' <- many1 anyChar
216− pure (unpack name, type')
242+ pure (name, toS type')
217
243
218 identifier :: Parser Text
244 identifier :: Parser Text
219 identifier = do
245 identifier = do
220 spaces
246 spaces
221 ident <-
247 ident <-
222 -- necessary for being able to parse the following ((++), concat)
248 -- necessary for being able to parse the following ((++), concat)
223− between (char '(') (char ')') (many1 (noneOf ", )")) <|>
249+ between (char '(') (char ')') (many1 (noneOf ", )")) Parsec.<|>
224 many1 (noneOf ", )")
250 many1 (noneOf ", )")
225 spaces
251 spaces
226− pure (pack ident)
252+ pure (toS ident)
227
253
228instance ToJSON PursuitResponse where
254instance ToJSON PursuitResponse where
229 toJSON (ModuleResponse name package) =
255 toJSON (ModuleResponse name package) =
src/Language/PureScript/Ide/Util.hs+34−48
@@ -9,75 +9,61 @@
9-- Stability : experimental
9-- Stability : experimental
10--
10--
11-- |
11-- |
12−-- Generally useful functions and conversions
12+-- Generally useful functions
13-----------------------------------------------------------------------------
13-----------------------------------------------------------------------------
14
14
15{-# LANGUAGE OverloadedStrings #-}
15{-# LANGUAGE OverloadedStrings #-}
16
16
17−module Language.PureScript.Ide.Util where
17+module Language.PureScript.Ide.Util
18+ ( identifierFromIdeDeclaration
19+ , identifierFromMatch
20+ , completionFromMatch
21+ , encodeT
22+ , decodeT
23+ , module Language.PureScript.Ide.Conversions
24+ ) where
18
25
19−import Prelude.Compat
26+import Protolude
20import Data.Aeson
27import Data.Aeson
21−import Data.Text (Text)
22import qualified Data.Text as T
28import qualified Data.Text as T
23−import Data.Text.Lazy (fromStrict, toStrict)
24import Data.Text.Lazy.Encoding (decodeUtf8, encodeUtf8)
29import Data.Text.Lazy.Encoding (decodeUtf8, encodeUtf8)
25import qualified Language.PureScript as P
30import qualified Language.PureScript as P
26import Language.PureScript.Ide.Types
31import Language.PureScript.Ide.Types
32+import Language.PureScript.Ide.Conversions
27
33
28−runProperNameT :: P.ProperName a -> Text
34+identifierFromIdeDeclaration :: IdeDeclaration -> Text
29−runProperNameT = T.pack . P.runProperName
35+identifierFromIdeDeclaration d = case d of
30−
36+ IdeValue name _ -> name
31−runIdentT :: P.Ident -> Text
32−runIdentT = T.pack . P.runIdent
33−
34−runOpNameT :: P.OpName a -> Text
35−runOpNameT = T.pack . P.runOpName
36−
37−runModuleNameT :: P.ModuleName -> Text
38−runModuleNameT = T.pack . P.runModuleName
39−
40−prettyTypeT :: P.Type -> Text
41−prettyTypeT = T.unwords . fmap T.strip . T.lines . T.pack . P.prettyPrintType
42−
43−identifierFromExternDecl :: ExternDecl -> Text
44−identifierFromExternDecl (ValueDeclaration name _) = name
45−identifierFromExternDecl (TypeDeclaration name _) = runProperNameT name
37+ IdeType name _ -> runProperNameT name
46−identifierFromExternDecl (TypeSynonymDeclaration name _) = runProperNameT name
38+ IdeTypeSynonym name _ -> runProperNameT name
47−identifierFromExternDecl (DataConstructor name _ _) = name
39+ IdeDataConstructor name _ _ -> name
48−identifierFromExternDecl (TypeClassDeclaration name) = runProperNameT name
40+ IdeTypeClass name -> runProperNameT name
49−identifierFromExternDecl (ModuleDecl name _) = name
41+ IdeValueOperator op _ _ _ -> runOpNameT op
50−identifierFromExternDecl (ValueOperator op _ _ _) = runOpNameT op
51−identifierFromExternDecl (TypeOperator op _ _ _) = runOpNameT op
42+ IdeTypeOperator op _ _ _ -> runOpNameT op
52−identifierFromExternDecl Dependency{} = "~Dependency~"
53−identifierFromExternDecl Export{} = "~Export~"
54
43
55identifierFromMatch :: Match -> Text
44identifierFromMatch :: Match -> Text
56−identifierFromMatch (Match _ ed) = identifierFromExternDecl ed
45+identifierFromMatch (Match _ ed) = identifierFromIdeDeclaration ed
57
46
58−completionFromMatch :: Match -> Maybe Completion
47+completionFromMatch :: Match -> Completion
59−completionFromMatch (Match m d) = case d of
48+completionFromMatch (Match m' d) = case d of
60− ValueDeclaration name type' -> Just $ Completion (m, name, prettyTypeT type')
49+ IdeValue name type' -> Completion (m, name, prettyTypeT type')
61− TypeDeclaration name kind -> Just $ Completion (m, runProperNameT name, T.pack $ P.prettyPrintKind kind)
50+ IdeType name kind -> Completion (m, runProperNameT name, toS (P.prettyPrintKind kind))
62− TypeSynonymDeclaration name kind -> Just $ Completion (m, runProperNameT name, prettyTypeT kind)
51+ IdeTypeSynonym name kind -> Completion (m, runProperNameT name, prettyTypeT kind)
63− DataConstructor name _ type' -> Just $ Completion (m, name, prettyTypeT type')
52+ IdeDataConstructor name _ type' -> Completion (m, name, prettyTypeT type')
64− TypeClassDeclaration name -> Just $ Completion (m, runProperNameT name, "class")
53+ IdeTypeClass name -> Completion (m, runProperNameT name, "class")
65− ModuleDecl name _ -> Just $ Completion ("module", name, "module")
66− ValueOperator op ref precedence associativity -> Just $ Completion (m, runOpNameT op, showFixity precedence associativity ref op)
54+ IdeValueOperator op ref precedence associativity -> Completion (m, runOpNameT op, showFixity precedence associativity ref op)
67− TypeOperator op ref precedence associativity -> Just $ Completion (m, runOpNameT op, showFixity precedence associativity ref op)
55+ IdeTypeOperator op ref precedence associativity -> Completion (m, runOpNameT op, showFixity precedence associativity ref op)
68− Dependency{} -> Nothing
69− Export{} -> Nothing
70 where
56 where
57+ m = runModuleNameT m'
71 showFixity p a r o =
58 showFixity p a r o =
72 let asso = case a of
59 let asso = case a of
73 P.Infix -> "infix"
60 P.Infix -> "infix"
74 P.Infixl -> "infixl"
61 P.Infixl -> "infixl"
75 P.Infixr -> "infixr"
62 P.Infixr -> "infixr"
76− in T.unwords [asso, T.pack (show p), r, "as", runOpNameT o]
63+ in T.unwords [asso, show p, r, "as", runOpNameT o]
77−
78
64
79encodeT :: (ToJSON a) => a -> Text
65encodeT :: (ToJSON a) => a -> Text
80−encodeT = toStrict . decodeUtf8 . encode
66+encodeT = toS . decodeUtf8 . encode
81
67
82decodeT :: (FromJSON a) => Text -> Maybe a
68decodeT :: (FromJSON a) => Text -> Maybe a
83−decodeT = decode . encodeUtf8 . fromStrict
69+decodeT = decode . encodeUtf8 . toS
src/Language/PureScript/Ide/Watcher.hs+6−8
@@ -14,33 +14,31 @@
14
14
15module Language.PureScript.Ide.Watcher where
15module Language.PureScript.Ide.Watcher where
16
16
17−import Control.Concurrent (threadDelay)
17+import Protolude
18+
18import Control.Concurrent.STM
19import Control.Concurrent.STM
19−import Control.Monad
20−import Control.Monad.Trans.Except
21import Language.PureScript.Ide.Externs
20import Language.PureScript.Ide.Externs
22import Language.PureScript.Ide.State
21import Language.PureScript.Ide.State
23import Language.PureScript.Ide.Types
22import Language.PureScript.Ide.Types
24−import Prelude
25import System.FilePath
23import System.FilePath
26import System.FSNotify
24import System.FSNotify
27
25
28-- | Reloads an ExternsFile from Disc. If the Event indicates the ExternsFile
26-- | Reloads an ExternsFile from Disc. If the Event indicates the ExternsFile
29-- was deleted we don't do anything.
27-- was deleted we don't do anything.
30−reloadFile :: TVar PscIdeState -> Event -> IO ()
28+reloadFile :: TVar IdeState -> Event -> IO ()
31reloadFile _ Removed{} = pure ()
29reloadFile _ Removed{} = pure ()
32−reloadFile stateVar ev = do
30+reloadFile ref ev = do
33 let fp = eventPath ev
31 let fp = eventPath ev
34 ef' <- runExceptT (readExternFile fp)
32 ef' <- runExceptT (readExternFile fp)
35 case ef' of
33 case ef' of
36 Left _ -> pure ()
34 Left _ -> pure ()
37 Right ef -> do
35 Right ef -> do
38− atomically (insertModuleSTM stateVar ef)
36+ atomically (insertExternsSTM ref ef *> populateStage2STM ref)
39 putStrLn ("Reloaded File at: " ++ fp)
37 putStrLn ("Reloaded File at: " ++ fp)
40
38
41-- | Installs filewatchers for the given directory and reloads ExternsFiles when
39-- | Installs filewatchers for the given directory and reloads ExternsFiles when
42-- they change on disc
40-- they change on disc
43−watcher :: TVar PscIdeState -> FilePath -> IO ()
41+watcher :: TVar IdeState -> FilePath -> IO ()
44watcher stateVar fp =
42watcher stateVar fp =
45 withManagerConf (defaultConfig { confDebounce = NoDebounce }) $ \mgr -> do
43 withManagerConf (defaultConfig { confDebounce = NoDebounce }) $ \mgr -> do
46 _ <- watchTree mgr fp
44 _ <- watchTree mgr fp
src/Language/PureScript/Publish.hs+1
@@ -21,6 +21,7 @@ module Language.PureScript.Publish
21 , getResolvedDependencies
21 , getResolvedDependencies
22 ) where
22 ) where
23
23
24+import Prelude ()
24import Prelude.Compat hiding (userError)
25import Prelude.Compat hiding (userError)
25
26
26import Control.Arrow ((***))
27import Control.Arrow ((***))
tests/Language/PureScript/Ide/FilterSpec.hs+18−29
@@ -1,32 +1,31 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
2module Language.PureScript.Ide.FilterSpec where
3module Language.PureScript.Ide.FilterSpec where
3
4
4−import Data.Text (Text)
5+import Protolude
5import Language.PureScript.Ide.Filter
6import Language.PureScript.Ide.Filter
6import Language.PureScript.Ide.Types
7import Language.PureScript.Ide.Types
7import qualified Language.PureScript as P
8import qualified Language.PureScript as P
8import Test.Hspec
9import Test.Hspec
9
10
10−value :: Text -> ExternDecl
11+value :: Text -> IdeDeclaration
11−value s = ValueDeclaration s $ P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0)
12+value s = IdeValue s $ P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0)
13+
14+moduleA, moduleB :: Module
15+moduleA = (P.moduleNameFromString "Module.A", [value "function1"])
16+moduleB = (P.moduleNameFromString "Module.B", [value "data1"])
12
17
13modules :: [Module]
18modules :: [Module]
14−modules =
19+modules = [moduleA, moduleB]
15− [
16− ("Module.A", [value "function1"]),
17− ("Module.B", [value "data1"]),
18− ("Module.C", [ModuleDecl "Module.C" []]),
19− ("Module.D", [Dependency "Module.C" [] Nothing, value "asd"])
20− ]
21
20
22runEq :: Text -> [Module]
21runEq :: Text -> [Module]
23runEq s = runFilter (equalityFilter s) modules
22runEq s = runFilter (equalityFilter s) modules
23+
24runPrefix :: Text -> [Module]
24runPrefix :: Text -> [Module]
25runPrefix s = runFilter (prefixFilter s) modules
25runPrefix s = runFilter (prefixFilter s) modules
26+
26−runModule :: [ModuleIdent] -> [Module]
27+runModule :: [P.ModuleName] -> [Module]
27runModule ms = runFilter (moduleFilter ms) modules
28runModule ms = runFilter (moduleFilter ms) modules
28−runDependency :: [ModuleIdent] -> [Module]
29−runDependency ms = runFilter (dependencyFilter ms) modules
30
29
31spec :: Spec
30spec :: Spec
32spec = do
31spec = do
@@ -34,30 +33,20 @@ spec = do
34 it "removes empty modules" $
33 it "removes empty modules" $
35 runEq "test" `shouldBe` []
34 runEq "test" `shouldBe` []
36 it "keeps function declarations that are equal" $
35 it "keeps function declarations that are equal" $
37− runEq "function1" `shouldBe` [head modules]
36+ runEq "function1" `shouldBe` [moduleA]
38− -- TODO: It would be more sensible to match Constructors
39 it "keeps data declarations that are equal" $
37 it "keeps data declarations that are equal" $
40− runEq "data1" `shouldBe` [modules !! 1]
38+ runEq "data1" `shouldBe` [moduleB]
41 describe "prefixFilter" $ do
39 describe "prefixFilter" $ do
42 it "keeps everything on empty string" $
40 it "keeps everything on empty string" $
43 runPrefix "" `shouldBe` modules
41 runPrefix "" `shouldBe` modules
44 it "keeps functionname prefix matches" $
42 it "keeps functionname prefix matches" $
45− runPrefix "fun" `shouldBe` [head modules]
43+ runPrefix "fun" `shouldBe` [moduleA]
46 it "keeps data decls prefix matches" $
44 it "keeps data decls prefix matches" $
47− runPrefix "dat" `shouldBe` [modules !! 1]
45+ runPrefix "dat" `shouldBe` [moduleB]
48− it "keeps module decl prefix matches" $
49− runPrefix "Mod" `shouldBe` [modules !! 2]
50 describe "moduleFilter" $ do
46 describe "moduleFilter" $ do
51 it "removes everything on empty input" $
47 it "removes everything on empty input" $
52 runModule [] `shouldBe` []
48 runModule [] `shouldBe` []
53 it "only keeps the specified modules" $
49 it "only keeps the specified modules" $
54− runModule ["Module.A", "Module.C"] `shouldBe` [head modules, modules !! 2]
50+ runModule [P.moduleNameFromString "Module.A"] `shouldBe` [moduleA]
55 it "ignores modules that are not in scope" $
51 it "ignores modules that are not in scope" $
56− runModule ["Module.A", "Module.C", "Unknown"] `shouldBe` [head modules, modules !! 2]
52+ runModule (P.moduleNameFromString <$> ["Module.A", "Unknown"]) `shouldBe` [moduleA]
57− describe "dependencyFilter" $ do
58− it "removes everything on empty input" $
59− runDependency [] `shouldBe` []
60− it "only keeps the specified modules if they have no imports" $
61− runDependency ["Module.A", "Module.B"] `shouldBe` [head modules, modules !! 1]
62− it "keeps the specified modules and their imports" $
63− runDependency ["Module.A", "Module.D"] `shouldBe` [head modules, modules !! 2, modules !! 3]
tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs+14−25
@@ -1,8 +1,10 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
2module Language.PureScript.Ide.Imports.IntegrationSpec where
3module Language.PureScript.Ide.Imports.IntegrationSpec where
3
4
4−import Control.Monad (void)
5+
5−import Data.Text (Text)
6+import Protolude
7+
6import qualified Data.Text as T
8import qualified Data.Text as T
7import qualified Data.Text.IO as TIO
9import qualified Data.Text.IO as TIO
8import qualified Language.PureScript.Ide.Integration as Integration
10import qualified Language.PureScript.Ide.Integration as Integration
@@ -12,9 +14,7 @@ import System.Directory
12import System.FilePath
14import System.FilePath
13
15
14setup :: IO ()
16setup :: IO ()
15−setup = do
16− Integration.reset
17+setup = void (Integration.reset *> Integration.loadAll)
17− mapM_ Integration.loadModuleWithDeps ["ImportsSpec", "ImportsSpec1"]
18
18
19withSupportFiles :: (FilePath -> FilePath -> IO a) -> IO ()
19withSupportFiles :: (FilePath -> FilePath -> IO a) -> IO ()
20withSupportFiles test = do
20withSupportFiles test = do
@@ -35,52 +35,41 @@ spec = beforeAll_ setup . describe "Adding imports" $ do
35 let
35 let
36 sourceFileSkeleton :: [Text] -> [Text]
36 sourceFileSkeleton :: [Text] -> [Text]
37 sourceFileSkeleton importSection =
37 sourceFileSkeleton importSection =
38− [ "module ImportsSpec where" , ""] ++ importSection ++ [ "" , "myId = id"]
38+ [ "module ImportsSpec where" , ""] ++ importSection ++ [ "" , "myId x = x"]
39 it "adds an implicit import" $ do
39 it "adds an implicit import" $ do
40 withSupportFiles (Integration.addImplicitImport "ImportsSpec1")
40 withSupportFiles (Integration.addImplicitImport "ImportsSpec1")
41 outputFileShouldBe (sourceFileSkeleton
41 outputFileShouldBe (sourceFileSkeleton
42 [ "import ImportsSpec1"
42 [ "import ImportsSpec1"
43− , "import Main (id)"
44 ])
43 ])
45 it "adds an explicit unqualified import" $ do
44 it "adds an explicit unqualified import" $ do
46 withSupportFiles (Integration.addImport "exportedFunction")
45 withSupportFiles (Integration.addImport "exportedFunction")
47 outputFileShouldBe (sourceFileSkeleton
46 outputFileShouldBe (sourceFileSkeleton
48 [ "import ImportsSpec1 (exportedFunction)"
47 [ "import ImportsSpec1 (exportedFunction)"
49− , "import Main (id)"
50 ])
48 ])
51 it "adds an explicit unqualified import (type)" $ do
49 it "adds an explicit unqualified import (type)" $ do
52 withSupportFiles (Integration.addImport "MyType")
50 withSupportFiles (Integration.addImport "MyType")
53− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyType)"
51+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyType)"])
54− , "import Main (id)"
55− ])
56 it "adds an explicit unqualified import (parameterized type)" $ do
52 it "adds an explicit unqualified import (parameterized type)" $ do
57 withSupportFiles (Integration.addImport "MyParamType")
53 withSupportFiles (Integration.addImport "MyParamType")
58− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyParamType)"
54+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyParamType)"])
59− , "import Main (id)"
60− ])
61 it "adds an explicit unqualified import (typeclass)" $ do
55 it "adds an explicit unqualified import (typeclass)" $ do
62 withSupportFiles (Integration.addImport "ATypeClass")
56 withSupportFiles (Integration.addImport "ATypeClass")
63− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (class ATypeClass)"
57+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (class ATypeClass)"])
64− , "import Main (id)"])
65 it "adds an explicit unqualified import (dataconstructor)" $ do
58 it "adds an explicit unqualified import (dataconstructor)" $ do
66 withSupportFiles (Integration.addImport "MyJust")
59 withSupportFiles (Integration.addImport "MyJust")
67− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyMaybe(MyJust))"
60+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyMaybe(MyJust))"])
68− , "import Main (id)"])
69 it "adds an explicit unqualified import (newtype)" $ do
61 it "adds an explicit unqualified import (newtype)" $ do
70 withSupportFiles (Integration.addImport "MyNewtype")
62 withSupportFiles (Integration.addImport "MyNewtype")
71− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (MyNewtype(MyNewtype))"
63+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (MyNewtype(MyNewtype))"])
72− , "import Main (id)"])
73 it "adds an explicit unqualified import (typeclass member function)" $ do
64 it "adds an explicit unqualified import (typeclass member function)" $ do
74 withSupportFiles (Integration.addImport "typeClassFun")
65 withSupportFiles (Integration.addImport "typeClassFun")
75− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (typeClassFun)"
66+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (typeClassFun)"])
76− , "import Main (id)"])
77 it "doesn't add a newtypes constructor if only the type is exported" $ do
67 it "doesn't add a newtypes constructor if only the type is exported" $ do
78 withSupportFiles (Integration.addImport "OnlyTypeExported")
68 withSupportFiles (Integration.addImport "OnlyTypeExported")
79− outputFileShouldBe (sourceFileSkeleton [ "import ImportsSpec1 (OnlyTypeExported)"
69+ outputFileShouldBe (sourceFileSkeleton ["import ImportsSpec1 (OnlyTypeExported)"])
80− , "import Main (id)"])
81 it "doesn't add an import if the identifier is defined in the module itself" $ do
70 it "doesn't add an import if the identifier is defined in the module itself" $ do
82 withSupportFiles (Integration.addImport "myId")
71 withSupportFiles (Integration.addImport "myId")
83− outputFileShouldBe (sourceFileSkeleton [ "import Main (id)"])
72+ outputFileShouldBe (sourceFileSkeleton [])
84 it "responds with an error if it's undecidable whether we want a type or constructor" $
73 it "responds with an error if it's undecidable whether we want a type or constructor" $
85 withSupportFiles (\sourceFp outFp -> do
74 withSupportFiles (\sourceFp outFp -> do
86 r <- Integration.addImport "SpecialCase" sourceFp outFp
75 r <- Integration.addImport "SpecialCase" sourceFp outFp
tests/Language/PureScript/Ide/ImportsSpec.hs+9−9
@@ -1,8 +1,10 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
2module Language.PureScript.Ide.ImportsSpec where
3module Language.PureScript.Ide.ImportsSpec where
3
4
4−import Data.Maybe (fromJust)
5+import Protolude
5−import Data.Text (Text)
6+import Unsafe (fromJust)
7+
6import qualified Language.PureScript as P
8import qualified Language.PureScript as P
7import Language.PureScript.Ide.Imports
9import Language.PureScript.Ide.Imports
8import Language.PureScript.Ide.Types
10import Language.PureScript.Ide.Types
@@ -17,11 +19,9 @@ simpleFile =
17 ]
19 ]
18
20
19splitSimpleFile :: (P.ModuleName, [Text], [Import], [Text])
21splitSimpleFile :: (P.ModuleName, [Text], [Import], [Text])
20−splitSimpleFile = fromRight $ sliceImportSection simpleFile
22+splitSimpleFile = fromRight (sliceImportSection simpleFile)
21 where
23 where
22− fromRight (Right r) = r
24+ fromRight = fromJust . rightToMaybe
23− fromRight (Left _) = error "fromRight"
24−
25withImports :: [Text] -> [Text]
25withImports :: [Text] -> [Text]
26withImports is =
26withImports is =
27 take 2 simpleFile ++ is ++ drop 2 simpleFile
27 take 2 simpleFile ++ is ++ drop 2 simpleFile
@@ -68,11 +68,11 @@ spec = do
68 describe "import commands" $ do
68 describe "import commands" $ do
69 let simpleFileImports = let (_, _, i, _) = splitSimpleFile in i
69 let simpleFileImports = let (_, _, i, _) = splitSimpleFile in i
70 addValueImport i mn is =
70 addValueImport i mn is =
71− prettyPrintImportSection (addExplicitImport' (ValueDeclaration i wildcard) mn is)
71+ prettyPrintImportSection (addExplicitImport' (IdeValue i wildcard) mn is)
72 addOpImport op mn is =
72 addOpImport op mn is =
73− prettyPrintImportSection (addExplicitImport' (ValueOperator op "" 2 P.Infix) mn is)
73+ prettyPrintImportSection (addExplicitImport' (IdeValueOperator op "" 2 P.Infix) mn is)
74 addDtorImport i t mn is =
74 addDtorImport i t mn is =
75− prettyPrintImportSection (addExplicitImport' (DataConstructor i t wildcard) mn is)
75+ prettyPrintImportSection (addExplicitImport' (IdeDataConstructor i t wildcard) mn is)
76 it "adds an implicit unqualified import" $
76 it "adds an implicit unqualified import" $
77 shouldBe
77 shouldBe
78 (addImplicitImport' simpleFileImports (P.moduleNameFromString "Data.Map"))
78 (addImplicitImport' simpleFileImports (P.moduleNameFromString "Data.Map"))
tests/Language/PureScript/Ide/Integration.hs+60−75
@@ -14,6 +14,7 @@
14
14
15{-# LANGUAGE OverloadedStrings #-}
15{-# LANGUAGE OverloadedStrings #-}
16{-# LANGUAGE ScopedTypeVariables #-}
16{-# LANGUAGE ScopedTypeVariables #-}
17+{-# LANGUAGE NoImplicitPrelude #-}
17module Language.PureScript.Ide.Integration
18module Language.PureScript.Ide.Integration
18 (
19 (
19 -- managing the server process
20 -- managing the server process
@@ -29,8 +30,9 @@ module Language.PureScript.Ide.Integration
29 -- sending commands
30 -- sending commands
30 , addImport
31 , addImport
31 , addImplicitImport
32 , addImplicitImport
33+ , loadAll
32 , loadModule
34 , loadModule
33− , loadModuleWithDeps
35+ , loadModules
34 , getCwd
36 , getCwd
35 , getFlexCompletions
37 , getFlexCompletions
36 , getFlexCompletionsInModule
38 , getFlexCompletionsInModule
@@ -43,19 +45,15 @@ module Language.PureScript.Ide.Integration
43 , parseTextResult
45 , parseTextResult
44 ) where
46 ) where
45
47
46−import Control.Concurrent (threadDelay)
48+import Protolude
47−import Control.Exception
49+import Unsafe (fromJust)
48−import Control.Monad (join, when)
50+
49import Data.Aeson
51import Data.Aeson
50import Data.Aeson.Types
52import Data.Aeson.Types
51−import qualified Data.ByteString.Lazy.UTF8 as BSL
52−import Data.Either (isRight)
53−import Data.Maybe (fromJust, isNothing, fromMaybe)
54import qualified Data.Text as T
53import qualified Data.Text as T
55import qualified Data.Vector as V
54import qualified Data.Vector as V
56import Language.PureScript.Ide.Util
55import Language.PureScript.Ide.Util
57import System.Directory
56import System.Directory
58−import System.Exit
59import System.FilePath
57import System.FilePath
60import System.IO.Error (mkIOError, userErrorType)
58import System.IO.Error (mkIOError, userErrorType)
61import System.Process
59import System.Process
@@ -80,26 +78,23 @@ stopServer = terminateProcess
80withServer :: IO a -> IO a
78withServer :: IO a -> IO a
81withServer s = do
79withServer s = do
82 _ <- startServer
80 _ <- startServer
83− started <- tryNTimes 5 (shush <$> (try getCwd :: IO (Either SomeException String)))
81+ started <- tryNTimes 5 (rightToMaybe <$> (try getCwd :: IO (Either SomeException Text)))
84 when (isNothing started) $
82 when (isNothing started) $
85 throwIO (mkIOError userErrorType "psc-ide-server didn't start in time" Nothing Nothing)
83 throwIO (mkIOError userErrorType "psc-ide-server didn't start in time" Nothing Nothing)
86 r <- s
84 r <- s
87 quitServer
85 quitServer
88 pure r
86 pure r
89
87
90−shush :: Either a b -> Maybe b
91−shush = either (const Nothing) Just
92−
93-- project management utils
88-- project management utils
94
89
95compileTestProject :: IO Bool
90compileTestProject :: IO Bool
96compileTestProject = do
91compileTestProject = do
97 pdir <- projectDirectory
92 pdir <- projectDirectory
98 (_, _, _, procHandle) <- createProcess $
93 (_, _, _, procHandle) <- createProcess $
99− (shell $ "psc " ++ fileGlob) { cwd = Just pdir
94+ (shell . toS $ "psc " <> fileGlob) { cwd = Just pdir
100− , std_out = CreatePipe
95+ , std_out = CreatePipe
101− , std_err = CreatePipe
96+ , std_err = CreatePipe
102− }
97+ }
103 r <- tryNTimes 5 (getProcessExitCode procHandle)
98 r <- tryNTimes 5 (getProcessExitCode procHandle)
104 pure (fromMaybe False (isSuccess <$> r))
99 pure (fromMaybe False (isSuccess <$> r))
105
100
@@ -121,24 +116,17 @@ deleteOutputFolder = do
121deleteFileIfExists :: FilePath -> IO ()
116deleteFileIfExists :: FilePath -> IO ()
122deleteFileIfExists fp = whenM (doesFileExist fp) (removeFile fp)
117deleteFileIfExists fp = whenM (doesFileExist fp) (removeFile fp)
123
118
124−whenM :: Monad m => m Bool -> m () -> m ()
125−whenM p f = do
126− x <- p
127− when x f
128−
129isSuccess :: ExitCode -> Bool
119isSuccess :: ExitCode -> Bool
130isSuccess ExitSuccess = True
120isSuccess ExitSuccess = True
131isSuccess (ExitFailure _) = False
121isSuccess (ExitFailure _) = False
132
122
133−fileGlob :: String
123+fileGlob :: Text
134−fileGlob = unwords
135− [ "\"src/**/*.purs\""
124+fileGlob = "\"src/**/*.purs\""
136− ]
137
125
138-- Integration Testing API
126-- Integration Testing API
139
127
140−sendCommand :: Value -> IO String
128+sendCommand :: Value -> IO Text
141−sendCommand v = readCreateProcess
129+sendCommand v = toS <$> readCreateProcess
142 ((shell "psc-ide-client") { std_out=CreatePipe
130 ((shell "psc-ide-client") { std_out=CreatePipe
143 , std_err=CreatePipe
131 , std_err=CreatePipe
144 })
132 })
@@ -146,65 +134,68 @@ sendCommand v = readCreateProcess
146
134
147quitServer :: IO ()
135quitServer :: IO ()
148quitServer = do
136quitServer = do
149− let quitCommand = object ["command" .= ("quit" :: String)]
137+ let quitCommand = object ["command" .= ("quit" :: Text)]
150− _ <- try $ sendCommand quitCommand :: IO (Either SomeException String)
138+ _ <- try $ sendCommand quitCommand :: IO (Either SomeException Text)
151 return ()
139 return ()
152
140
153reset :: IO ()
141reset :: IO ()
154reset = do
142reset = do
155− let resetCommand = object ["command" .= ("reset" :: String)]
143+ let resetCommand = object ["command" .= ("reset" :: Text)]
156− _ <- try $ sendCommand resetCommand :: IO (Either SomeException String)
144+ _ <- try $ sendCommand resetCommand :: IO (Either SomeException Text)
157 return ()
145 return ()
158
146
159−getCwd :: IO String
147+getCwd :: IO Text
160getCwd = do
148getCwd = do
161− let cwdCommand = object ["command" .= ("cwd" :: String)]
149+ let cwdCommand = object ["command" .= ("cwd" :: Text)]
162 sendCommand cwdCommand
150 sendCommand cwdCommand
163
151
164−loadModuleWithDeps :: String -> IO String
152+loadModule :: Text -> IO Text
165−loadModuleWithDeps m = sendCommand $ load [] [m]
153+loadModule m = loadModules [m]
166
154
167−loadModule :: String -> IO String
155+loadModules :: [Text] -> IO Text
168−loadModule m = sendCommand $ load [m] []
156+loadModules = sendCommand . load
169
157
158+loadAll :: IO Text
159+loadAll = sendCommand (load [])
160+
170−getFlexCompletions :: String -> IO [(String, String, String)]
161+getFlexCompletions :: Text -> IO [(Text, Text, Text)]
171getFlexCompletions q = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) Nothing)
162getFlexCompletions q = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) Nothing)
172
163
173−getFlexCompletionsInModule :: String -> String -> IO [(String, String, String)]
164+getFlexCompletionsInModule :: Text -> Text -> IO [(Text, Text, Text)]
174getFlexCompletionsInModule q m = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) (Just m))
165getFlexCompletionsInModule q m = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) (Just m))
175
166
176−getType :: String -> IO [(String, String, String)]
167+getType :: Text -> IO [(Text, Text, Text)]
177getType q = parseCompletions <$> sendCommand (typeC q [])
168getType q = parseCompletions <$> sendCommand (typeC q [])
178
169
179−addImport :: String -> FilePath -> FilePath -> IO String
170+addImport :: Text -> FilePath -> FilePath -> IO Text
180addImport identifier fp outfp = sendCommand (addImportC identifier fp outfp)
171addImport identifier fp outfp = sendCommand (addImportC identifier fp outfp)
181
172
182−addImplicitImport :: String -> FilePath -> FilePath -> IO String
173+addImplicitImport :: Text -> FilePath -> FilePath -> IO Text
183addImplicitImport mn fp outfp = sendCommand (addImplicitImportC mn fp outfp)
174addImplicitImport mn fp outfp = sendCommand (addImplicitImportC mn fp outfp)
184
175
185−rebuildModule :: FilePath -> IO String
176+rebuildModule :: FilePath -> IO Text
186rebuildModule m = sendCommand (rebuildC m Nothing)
177rebuildModule m = sendCommand (rebuildC m Nothing)
187
178
188-- Command Encoding
179-- Command Encoding
189
180
190−commandWrapper :: String -> Value -> Value
181+commandWrapper :: Text -> Value -> Value
191commandWrapper c p = object ["command" .= c, "params" .= p]
182commandWrapper c p = object ["command" .= c, "params" .= p]
192
183
193−load :: [String] -> [String] -> Value
184+load :: [Text] -> Value
194−load ms ds = commandWrapper "load" (object ["modules" .= ms, "dependencies" .= ds])
185+load ms = commandWrapper "load" (object ["modules" .= ms])
195
186
196−typeC :: String -> [Value] -> Value
187+typeC :: Text -> [Value] -> Value
197typeC q filters = commandWrapper "type" (object ["search" .= q, "filters" .= filters])
188typeC q filters = commandWrapper "type" (object ["search" .= q, "filters" .= filters])
198
189
199−addImportC :: String -> FilePath -> FilePath -> Value
190+addImportC :: Text -> FilePath -> FilePath -> Value
200addImportC identifier = addImportW $
191addImportC identifier = addImportW $
201− object [ "importCommand" .= ("addImport" :: String)
192+ object [ "importCommand" .= ("addImport" :: Text)
202 , "identifier" .= identifier
193 , "identifier" .= identifier
203 ]
194 ]
204
195
205−addImplicitImportC :: String -> FilePath -> FilePath -> Value
196+addImplicitImportC :: Text -> FilePath -> FilePath -> Value
206addImplicitImportC mn = addImportW $
197addImplicitImportC mn = addImportW $
207− object [ "importCommand" .= ("addImplicitImport" :: String)
198+ object [ "importCommand" .= ("addImplicitImport" :: Text)
208 , "module" .= mn
199 , "module" .= mn
209 ]
200 ]
210
201
@@ -222,7 +213,7 @@ addImportW importCommand fp outfp =
222 ])
213 ])
223
214
224
215
225−completion :: [Value] -> Maybe Value -> Maybe String -> Value
216+completion :: [Value] -> Maybe Value -> Maybe Text -> Value
226completion filters matcher currentModule =
217completion filters matcher currentModule =
227 let
218 let
228 matcher' = case matcher of
219 matcher' = case matcher of
@@ -234,16 +225,16 @@ completion filters matcher currentModule =
234 in
225 in
235 commandWrapper "complete" (object $ "filters" .= filters : matcher' ++ currentModule' )
226 commandWrapper "complete" (object $ "filters" .= filters : matcher' ++ currentModule' )
236
227
237−flexMatcher :: String -> Value
228+flexMatcher :: Text -> Value
238−flexMatcher q = object [ "matcher" .= ("flex" :: String)
229+flexMatcher q = object [ "matcher" .= ("flex" :: Text)
239 , "params" .= object ["search" .= q]
230 , "params" .= object ["search" .= q]
240 ]
231 ]
241
232
242-- Result parsing
233-- Result parsing
243
234
244−unwrapResult :: Value -> Parser (Either String Value)
235+unwrapResult :: Value -> Parser (Either Text Value)
245unwrapResult = withObject "result" $ \o -> do
236unwrapResult = withObject "result" $ \o -> do
246− (rt :: String) <- o .: "resultType"
237+ (rt :: Text) <- o .: "resultType"
247 case rt of
238 case rt of
248 "error" -> do
239 "error" -> do
249 res <- o .: "result"
240 res <- o .: "result"
@@ -251,16 +242,16 @@ unwrapResult = withObject "result" $ \o -> do
251 "success" -> do
242 "success" -> do
252 res <- o .: "result"
243 res <- o .: "result"
253 pure (Right res)
244 pure (Right res)
254− _ -> fail "lol"
245+ _ -> mzero
255
246
256−withResult :: (Value -> Parser a) -> Value -> Parser (Either String a)
247+withResult :: (Value -> Parser a) -> Value -> Parser (Either Text a)
257withResult p v = do
248withResult p v = do
258 r <- unwrapResult v
249 r <- unwrapResult v
259 case r of
250 case r of
260 Left err -> pure (Left err)
251 Left err -> pure (Left err)
261 Right res -> Right <$> p res
252 Right res -> Right <$> p res
262
253
263−completionParser :: Value -> Parser [(String, String, String)]
254+completionParser :: Value -> Parser [(Text, Text, Text)]
264completionParser = withArray "res" $ \cs ->
255completionParser = withArray "res" $ \cs ->
265 mapM (withObject "completion" $ \o -> do
256 mapM (withObject "completion" $ \o -> do
266 ident <- o .: "identifier"
257 ident <- o .: "identifier"
@@ -268,22 +259,16 @@ completionParser = withArray "res" $ \cs ->
268 ty <- o .: "type"
259 ty <- o .: "type"
269 pure (module', ident, ty)) (V.toList cs)
260 pure (module', ident, ty)) (V.toList cs)
270
261
271−valueFromString :: String -> Value
262+valueFromText :: Text -> Value
272−valueFromString = fromJust . decode . BSL.fromString
263+valueFromText = fromJust . decode . toS
273
264
274−resultIsSuccess :: String -> Bool
265+resultIsSuccess :: Text -> Bool
275−resultIsSuccess = isRight . join . parseEither unwrapResult . valueFromString
266+resultIsSuccess = isRight . join . first toS . parseEither unwrapResult . valueFromText
276
267
277−parseCompletions :: String -> [(String, String, String)]
268+parseCompletions :: Text -> [(Text, Text, Text)]
278−parseCompletions s = fromJust $ do
269+parseCompletions s =
279− cs <- parseMaybe (withResult completionParser) (valueFromString s)
270+ fromJust $ join (rightToMaybe <$> parseMaybe (withResult completionParser) (valueFromText s))
280− case cs of
281− Left _ -> error "Failed to parse completions"
282− Right cs' -> pure cs'
283
271
284−parseTextResult :: String -> String
272+parseTextResult :: Text -> Text
285−parseTextResult s = fromJust $ do
273+parseTextResult s =
286− r <- parseMaybe (withResult (withText "tr" pure)) (valueFromString s)
274+ fromJust $ join (rightToMaybe <$> parseMaybe (withResult (withText "tr" pure)) (valueFromText s))
287− case r of
288− Left _ -> error "Failed to parse textResult"
289− Right r' -> pure (T.unpack r')
tests/Language/PureScript/Ide/MatcherSpec.hs+15−16
@@ -1,33 +1,32 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
2
3
3module Language.PureScript.Ide.MatcherSpec where
4module Language.PureScript.Ide.MatcherSpec where
4
5
5−import Control.Monad (void)
6+import Protolude
6−import Data.Text (Text)
7+
7import qualified Language.PureScript as P
8import qualified Language.PureScript as P
8import Language.PureScript.Ide.Integration
9import Language.PureScript.Ide.Integration
9import Language.PureScript.Ide.Matcher
10import Language.PureScript.Ide.Matcher
10import Language.PureScript.Ide.Types
11import Language.PureScript.Ide.Types
11import Test.Hspec
12import Test.Hspec
12
13
13−value :: Text -> ExternDecl
14+value :: Text -> IdeDeclaration
14−value s = ValueDeclaration s $ P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0)
15+value s = IdeValue s $ P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0)
15
16
16−completions :: [Match]
17+firstResult, secondResult, fiult :: Match
17−completions =
18− [ Match "" (value "firstResult")
18+firstResult = Match (P.moduleNameFromString "Match") (value "firstResult")
19− , Match "" (value "secondResult")
19+secondResult = Match (P.moduleNameFromString "Match") (value "secondResult")
20− , Match "" (value "fiult")
20+fiult = Match (P.moduleNameFromString "Match") (value "fiult")
21− ]
22
21
23−mkResult :: [Int] -> [Match]
22+completions :: [Match]
24−mkResult = map (completions !!)
23+completions = [firstResult, secondResult, fiult]
25
24
26runFlex :: Text -> [Match]
25runFlex :: Text -> [Match]
27runFlex s = runMatcher (flexMatcher s) completions
26runFlex s = runMatcher (flexMatcher s) completions
28
27
29setup :: IO ()
28setup :: IO ()
30−setup = reset *> void (loadModuleWithDeps "Main")
29+setup = reset *> void loadAll
31
30
32spec :: Spec
31spec :: Spec
33spec = do
32spec = do
@@ -35,9 +34,9 @@ spec = do
35 it "doesn't match on an empty string" $
34 it "doesn't match on an empty string" $
36 runFlex "" `shouldBe` []
35 runFlex "" `shouldBe` []
37 it "matches on equality" $
36 it "matches on equality" $
38− runFlex "firstResult" `shouldBe` mkResult [0]
37+ runFlex "firstResult" `shouldBe` [firstResult]
39 it "scores short matches higher and sorts accordingly" $
38 it "scores short matches higher and sorts accordingly" $
40− runFlex "filt" `shouldBe` mkResult [2, 0]
39+ runFlex "filt" `shouldBe` [fiult, firstResult]
41
40
42 beforeAll_ setup . describe "Integration Tests: Flex Matcher" $ do
41 beforeAll_ setup . describe "Integration Tests: Flex Matcher" $ do
43 it "doesn't match on an empty string" $ do
42 it "doesn't match on an empty string" $ do
@@ -45,4 +44,4 @@ spec = do
45 cs `shouldBe` []
44 cs `shouldBe` []
46 it "matches on equality" $ do
45 it "matches on equality" $ do
47 cs <- getFlexCompletions "const"
46 cs <- getFlexCompletions "const"
48− cs `shouldBe` [("Main", "const", "forall a b. a -> b -> a")]
47+ cs `shouldBe` [("MatcherSpec", "const", "forall a b. a -> b -> a")]
tests/Language/PureScript/Ide/RebuildSpec.hs+10−6
@@ -1,19 +1,23 @@
1+{-# LANGUAGE NoImplicitPrelude #-}
2+{-# LANGUAGE OverloadedStrings #-}
1module Language.PureScript.Ide.RebuildSpec where
3module Language.PureScript.Ide.RebuildSpec where
2
4
5+import Protolude
6+
3import qualified Language.PureScript.Ide.Integration as Integration
7import qualified Language.PureScript.Ide.Integration as Integration
4import System.FilePath
8import System.FilePath
5import Test.Hspec
9import Test.Hspec
6
10
7−shouldBeSuccess :: String -> IO ()
11+shouldBeSuccess :: Text -> IO ()
8shouldBeSuccess = shouldBe True . Integration.resultIsSuccess
12shouldBeSuccess = shouldBe True . Integration.resultIsSuccess
9
13
10−shouldBeFailure :: String -> IO ()
14+shouldBeFailure :: Text -> IO ()
11shouldBeFailure = shouldBe False . Integration.resultIsSuccess
15shouldBeFailure = shouldBe False . Integration.resultIsSuccess
12
16
13spec :: Spec
17spec :: Spec
14spec = before_ Integration.reset . describe "Rebuilding single modules" $ do
18spec = before_ Integration.reset . describe "Rebuilding single modules" $ do
15 it "rebuilds a correct module without dependencies successfully" $ do
19 it "rebuilds a correct module without dependencies successfully" $ do
16− _ <- Integration.loadModuleWithDeps "RebuildSpecSingleModule"
20+ _ <- Integration.loadModule "RebuildSpecSingleModule"
17 pdir <- Integration.projectDirectory
21 pdir <- Integration.projectDirectory
18 let file = pdir </> "src" </> "RebuildSpecSingleModule.purs"
22 let file = pdir </> "src" </> "RebuildSpecSingleModule.purs"
19 Integration.rebuildModule file >>= shouldBeSuccess
23 Integration.rebuildModule file >>= shouldBeSuccess
@@ -22,12 +26,12 @@ spec = before_ Integration.reset . describe "Rebuilding single modules" $ do
22 let file = pdir </> "src" </> "RebuildSpecSingleModule.fail"
26 let file = pdir </> "src" </> "RebuildSpecSingleModule.fail"
23 Integration.rebuildModule file >>= shouldBeFailure
27 Integration.rebuildModule file >>= shouldBeFailure
24 it "rebuilds a correct module with its dependencies successfully" $ do
28 it "rebuilds a correct module with its dependencies successfully" $ do
25− _ <- Integration.loadModuleWithDeps "RebuildSpecWithDeps"
29+ _ <- Integration.loadModules ["RebuildSpecWithDeps", "RebuildSpecDep"]
26 pdir <- Integration.projectDirectory
30 pdir <- Integration.projectDirectory
27 let file = pdir </> "src" </> "RebuildSpecWithDeps.purs"
31 let file = pdir </> "src" </> "RebuildSpecWithDeps.purs"
28 Integration.rebuildModule file >>= shouldBeSuccess
32 Integration.rebuildModule file >>= shouldBeSuccess
29 it "rebuilds a correct module that has reverse dependencies" $ do
33 it "rebuilds a correct module that has reverse dependencies" $ do
30− _ <- Integration.loadModuleWithDeps "RebuildSpecWithDeps"
34+ _ <- Integration.loadModule "RebuildSpecWithDeps"
31 pdir <- Integration.projectDirectory
35 pdir <- Integration.projectDirectory
32 let file = pdir </> "src" </> "RebuildSpecDep.purs"
36 let file = pdir </> "src" </> "RebuildSpecDep.purs"
33 Integration.rebuildModule file >>= shouldBeSuccess
37 Integration.rebuildModule file >>= shouldBeSuccess
@@ -37,7 +41,7 @@ spec = before_ Integration.reset . describe "Rebuilding single modules" $ do
37 let file = pdir </> "src" </> "RebuildSpecWithDeps.purs"
41 let file = pdir </> "src" </> "RebuildSpecWithDeps.purs"
38 Integration.rebuildModule file >>= shouldBeFailure
42 Integration.rebuildModule file >>= shouldBeFailure
39 it "rebuilds a correct module with a foreign file" $ do
43 it "rebuilds a correct module with a foreign file" $ do
40− _ <- Integration.loadModuleWithDeps "RebuildSpecWithForeign"
44+ _ <- Integration.loadModule "RebuildSpecWithForeign"
41 pdir <- Integration.projectDirectory
45 pdir <- Integration.projectDirectory
42 let file = pdir </> "src" </> "RebuildSpecWithForeign.purs"
46 let file = pdir </> "src" </> "RebuildSpecWithForeign.purs"
43 Integration.rebuildModule file >>= shouldBeSuccess
47 Integration.rebuildModule file >>= shouldBeSuccess
tests/Language/PureScript/Ide/ReexportsSpec.hs+11−13
@@ -1,8 +1,9 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
2module Language.PureScript.Ide.ReexportsSpec where
3module Language.PureScript.Ide.ReexportsSpec where
3
4
4−import Control.Exception (evaluate)
5+import Protolude
5−import Data.List (sort)
6+
6import qualified Data.Map as Map
7import qualified Data.Map as Map
7import Language.PureScript.Ide.Reexports
8import Language.PureScript.Ide.Reexports
8import Language.PureScript.Ide.Types
9import Language.PureScript.Ide.Types
@@ -23,28 +24,28 @@ dep1 = Dependency "Test.Foo" [] (Just "T")
23dep2 :: ExternDecl
24dep2 :: ExternDecl
24dep2 = Dependency "Test.Bar" [] (Just "T")
25dep2 = Dependency "Test.Bar" [] (Just "T")
25
26
26−circularModule :: Module
27+circularModule :: ModuleOld
27circularModule = ("Circular", [Export "Circular"])
28circularModule = ("Circular", [Export "Circular"])
28
29
29−module1 :: Module
30+module1 :: ModuleOld
30module1 = ("Module1", [Export "Module2", Export "Module3", decl1])
31module1 = ("Module1", [Export "Module2", Export "Module3", decl1])
31
32
32−module2 :: Module
33+module2 :: ModuleOld
33module2 = ("Module2", [decl2])
34module2 = ("Module2", [decl2])
34
35
35−module3 :: Module
36+module3 :: ModuleOld
36module3 = ("Module3", [decl3])
37module3 = ("Module3", [decl3])
37
38
38−module4 :: Module
39+module4 :: ModuleOld
39module4 = ("Module4", [Export "T", decl1, dep1, dep2])
40module4 = ("Module4", [Export "T", decl1, dep1, dep2])
40
41
41−result :: Module
42+result :: ModuleOld
42result = ("Module1", [decl1, decl2, Export "Module3"])
43result = ("Module1", [decl1, decl2, Export "Module3"])
43
44
44−db :: Map.Map ModuleIdent [ExternDecl]
45+db :: Map ModuleIdent [ExternDecl]
45db = Map.fromList [module1, module2, module3]
46db = Map.fromList [module1, module2, module3]
46
47
47−shouldBeEqualSorted :: Module -> Module -> Expectation
48+shouldBeEqualSorted :: ModuleOld -> ModuleOld -> Expectation
48shouldBeEqualSorted (n1, d1) (n2, d2) = (n1, sort d1) `shouldBe` (n2, sort d2)
49shouldBeEqualSorted (n1, d1) (n2, d2) = (n1, sort d1) `shouldBe` (n2, sort d2)
49
50
50spec :: Spec
51spec :: Spec
@@ -64,9 +65,6 @@ spec =
64 let replaced = replaceReexport (Export "Module2") module1 module2
65 let replaced = replaceReexport (Export "Module2") module1 module2
65 in replaceReexport (Export "Module2") replaced module2 `shouldBeEqualSorted` result
66 in replaceReexport (Export "Module2") replaced module2 `shouldBeEqualSorted` result
66
67
67− it "should error when given a non-Export to replace" $
68− evaluate (replaceReexport decl1 module1 module2)
69− `shouldThrow` errorCall "Should only get Exports here."
70 it "replaces all Exports with their corresponding declarations" $
68 it "replaces all Exports with their corresponding declarations" $
71 replaceReexports module1 db `shouldBe` ("Module1", [decl1, decl2, decl3])
69 replaceReexports module1 db `shouldBe` ("Module1", [decl1, decl2, decl3])
72
70
tests/Language/PureScript/IdeSpec.hsdeleted−35
@@ -1,35 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−module Language.PureScript.IdeSpec where
4−
5−import Control.Concurrent.STM
6−import Control.Monad.Reader
7−import Data.List
8−import qualified Data.Map as Map
9−import Language.PureScript.Ide
10−import Language.PureScript.Ide.Types
11−import Test.Hspec
12−
13−testState :: PscIdeState
14−testState = PscIdeState (Map.fromList [("Data.Array", []), ("Control.Monad.Eff", [])]) Map.empty Nothing
15−
16−defaultConfig :: Configuration
17−defaultConfig =
18− Configuration
19− {
20− confOutputPath = "output/"
21− , confDebug = False
22− }
23−
24−spec :: SpecWith ()
25−spec =
26− describe "list" $
27− describe "loadedModules" $ do
28− it "returns an empty list when no modules are loaded" $ do
29− st <- newTVarIO emptyPscIdeState
30− result <- runReaderT printModules (PscIdeEnvironment st defaultConfig)
31− result `shouldBe` ModuleList []
32− it "returns the list of loaded modules" $ do
33− st <- newTVarIO testState
34− ModuleList result <- runReaderT printModules (PscIdeEnvironment st defaultConfig)
35− sort result `shouldBe` sort ["Data.Array", "Control.Monad.Eff"]
tests/support/pscide/src/ImportsSpec.purs+1−3
@@ -1,5 +1,3 @@
1module ImportsSpec where
1module ImportsSpec where
2
2
3−import Main (id)
4−
5−myId = id
3+myId x = x
tests/support/pscide/src/Main.purs → tests/support/pscide/src/MatcherSpec.pursrenamed+1−1
@@ -1,4 +1,4 @@
1−module Main where
1+module MatcherSpec where
2
2
3id :: forall a. a -> a
3id :: forall a. a -> a
4id x = x
4id x = x
tests/support/pscide/src/RebuildSpecSingleModule.purs+1−1
@@ -1,4 +1,4 @@
1module RebuildSpecSingleModule where
1module RebuildSpecSingleModule where
2
2
3id x = x
3id x = x
4−const x y = x
4+lulz x y = x