-
-
Notifications
You must be signed in to change notification settings - Fork 369
/
Wrapper.hs
177 lines (149 loc) · 6.19 KB
/
Wrapper.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE CPP #-}
-- | This module is based on the hie-wrapper.sh script in
-- https://github.com/alanz/vscode-hie-server
module Main where
import Control.Monad.Extra
import Data.Char (isSpace)
import Data.Default
import Data.Foldable
import Data.List
import Data.Void
import qualified Development.IDE.Session as Session
import qualified HIE.Bios.Environment as HieBios
import HIE.Bios.Types
import Ide.Arguments
import Ide.Version
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import System.IO
import System.Info
#ifndef mingw32_HOST_OS
import System.Posix.Process (executeFile)
import qualified Data.Map.Strict as Map
#else
import System.Process
#endif
-- ---------------------------------------------------------------------
main :: IO ()
main = do
-- WARNING: If you write to stdout before runLanguageServer
-- then the language server will not work
args <- getArguments "haskell-language-server-wrapper" mempty
hlsVer <- haskellLanguageServerVersion
case args of
ProbeToolsMode -> do
programsOfInterest <- findProgramVersions
putStrLn hlsVer
putStrLn "Tool versions found on the $PATH"
putStrLn $ showProgramVersionOfInterest programsOfInterest
VersionMode PrintVersion ->
putStrLn hlsVer
VersionMode PrintNumericVersion ->
putStrLn haskellLanguageServerNumericVersion
BiosMode PrintCradleType ->
print =<< findProjectCradle
PrintLibDir -> do
cradle <- findProjectCradle' False
(CradleSuccess libdir) <- HieBios.getRuntimeGhcLibDir cradle
putStr libdir
_ -> launchHaskellLanguageServer args
launchHaskellLanguageServer :: Arguments -> IO ()
launchHaskellLanguageServer parsedArgs = do
case parsedArgs of
Ghcide GhcideArguments{..} -> whenJust argsCwd setCurrentDirectory
_ -> pure ()
d <- getCurrentDirectory
-- search for the project cradle type
cradle <- findProjectCradle
-- Get the root directory from the cradle
setCurrentDirectory $ cradleRootDir cradle
case parsedArgs of
Ghcide GhcideArguments{..} ->
when argsProjectGhcVersion $ getRuntimeGhcVersion' cradle >>= putStrLn >> exitSuccess
_ -> pure ()
progName <- getProgName
hPutStrLn stderr $ "Run entered for haskell-language-server-wrapper(" ++ progName ++ ") "
++ hlsVersion
hPutStrLn stderr $ "Current directory: " ++ d
hPutStrLn stderr $ "Operating system: " ++ os
args <- getArgs
hPutStrLn stderr $ "Arguments: " ++ show args
hPutStrLn stderr $ "Cradle directory: " ++ cradleRootDir cradle
hPutStrLn stderr $ "Cradle type: " ++ show (actionName (cradleOptsProg cradle))
programsOfInterest <- findProgramVersions
hPutStrLn stderr ""
hPutStrLn stderr "Tool versions found on the $PATH"
hPutStrLn stderr $ showProgramVersionOfInterest programsOfInterest
hPutStrLn stderr ""
-- Get the ghc version -- this might fail!
hPutStrLn stderr "Consulting the cradle to get project GHC version..."
ghcVersion <- getRuntimeGhcVersion' cradle
hPutStrLn stderr $ "Project GHC version: " ++ ghcVersion
let
hlsBin = "haskell-language-server-" ++ ghcVersion
candidates' = [hlsBin, "haskell-language-server"]
candidates = map (++ exeExtension) candidates'
hPutStrLn stderr $ "haskell-language-server exe candidates: " ++ show candidates
mexes <- traverse findExecutable candidates
case asum mexes of
Nothing -> die $ "Cannot find any haskell-language-server exe, looked for: " ++ intercalate ", " candidates
Just e -> do
hPutStrLn stderr $ "Launching haskell-language-server exe at:" ++ e
#ifdef mingw32_HOST_OS
callProcess e args
#else
let Cradle { cradleOptsProg = CradleAction { runGhcCmd } } = cradle
-- we need to be compatible with NoImplicitPrelude
ghcBinary <- (fmap trim <$> runGhcCmd ["-v0", "-package-env=-", "-e", "do e <- System.Environment.getExecutablePath ; System.IO.putStr e"])
>>= cradleResult "Failed to get project GHC executable path"
libdir <- HieBios.getRuntimeGhcLibDir cradle
>>= cradleResult "Failed to get project GHC libdir path"
env <- Map.fromList <$> getEnvironment
let newEnv = Map.insert "GHC_BIN" ghcBinary $ Map.insert "GHC_LIBDIR" libdir env
executeFile e True args (Just (Map.toList newEnv))
#endif
cradleResult :: String -> CradleLoadResult a -> IO a
cradleResult _ (CradleSuccess a) = pure a
cradleResult str (CradleFail e) = die $ str ++ ": " ++ show e
cradleResult str CradleNone = die $ str ++ ": no cradle"
-- | Version of 'getRuntimeGhcVersion' that dies if we can't get it, and also
-- checks to see if the tool is missing if it is one of
getRuntimeGhcVersion' :: Show a => Cradle a -> IO String
getRuntimeGhcVersion' cradle = do
-- See if the tool is installed
case actionName (cradleOptsProg cradle) of
Stack -> checkToolExists "stack"
Cabal -> checkToolExists "cabal"
Default -> checkToolExists "ghc"
Direct -> checkToolExists "ghc"
_ -> pure ()
HieBios.getRuntimeGhcVersion cradle >>= cradleResult "Failed to get project GHC version"
where
checkToolExists exe = do
exists <- findExecutable exe
case exists of
Just _ -> pure ()
Nothing ->
die $ "Cradle requires " ++ exe ++ " but couldn't find it" ++ "\n"
++ show cradle
findProjectCradle :: IO (Cradle Void)
findProjectCradle = findProjectCradle' True
findProjectCradle' :: Bool -> IO (Cradle Void)
findProjectCradle' log = do
d <- getCurrentDirectory
let initialFp = d </> "a"
hieYaml <- Session.findCradle def initialFp
-- Some log messages
when log $
case hieYaml of
Just yaml -> hPutStrLn stderr $ "Found \"" ++ yaml ++ "\" for \"" ++ initialFp ++ "\""
Nothing -> hPutStrLn stderr "No 'hie.yaml' found. Try to discover the project type!"
Session.loadCradle def hieYaml d
trim :: String -> String
trim s = case lines s of
[] -> s
ls -> dropWhileEnd isSpace $ last ls