Skip to content

Commit b1ed0eb

Browse files
committed
Add major CLI mode for printing the cradle type
Adds test-case for proving that wrapper and hls report the same cradle type for a project.
1 parent c2a998a commit b1ed0eb

File tree

9 files changed

+103
-22
lines changed

9 files changed

+103
-22
lines changed

exe/Wrapper.hs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Control.Monad.Extra
77
import Data.Default
88
import Data.Foldable
99
import Data.List
10+
import Data.Void
1011
import qualified Development.IDE.Session as Session
1112
import qualified HIE.Bios.Environment as HieBios
1213
import HIE.Bios.Types
@@ -42,6 +43,9 @@ main = do
4243
VersionMode PrintNumericVersion ->
4344
putStrLn haskellLanguageServerNumericVersion
4445

46+
BiosMode PrintCradleType ->
47+
print =<< findProjectCradle
48+
4549
_ -> launchHaskellLanguageServer args
4650

4751
launchHaskellLanguageServer :: Arguments -> IO ()
@@ -51,18 +55,11 @@ launchHaskellLanguageServer parsedArgs = do
5155
_ -> pure ()
5256

5357
d <- getCurrentDirectory
58+
59+
-- search for the project cradle type
60+
cradle <- findProjectCradle
5461

55-
let initialFp = (d </> "a")
56-
-- Get the cabal directory from the cradle
57-
hieYaml <- Session.findCradle def initialFp
58-
59-
-- Some log messages
60-
case hieYaml of
61-
Just yaml -> hPutStrLn stderr $ "Found \"" ++ yaml ++ "\" for \"" ++ initialFp ++ "\""
62-
Nothing -> hPutStrLn stderr "No 'hie.yaml' found. Try to discover the project type!"
63-
64-
cradle <- Session.loadCradle def hieYaml d
65-
62+
-- Get the root directory from the cradle
6663
setCurrentDirectory $ cradleRootDir cradle
6764

6865
case parsedArgs of
@@ -135,3 +132,17 @@ getRuntimeGhcVersion' cradle = do
135132
Nothing ->
136133
die $ "Cradle requires " ++ exe ++ " but couldn't find it" ++ "\n"
137134
++ show cradle
135+
136+
findProjectCradle :: IO (Cradle Void)
137+
findProjectCradle = do
138+
d <- getCurrentDirectory
139+
140+
let initialFp = (d </> "a")
141+
hieYaml <- Session.findCradle def initialFp
142+
143+
-- Some log messages
144+
case hieYaml of
145+
Just yaml -> hPutStrLn stderr $ "Found \"" ++ yaml ++ "\" for \"" ++ initialFp ++ "\""
146+
Nothing -> hPutStrLn stderr "No 'hie.yaml' found. Try to discover the project type!"
147+
148+
Session.loadCradle def hieYaml d

haskell-language-server.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,8 @@ test-suite func-test
440440
test-suite wrapper-test
441441
type: exitcode-stdio-1.0
442442
build-tool-depends:
443-
haskell-language-server:haskell-language-server-wrapper -any
443+
haskell-language-server:haskell-language-server-wrapper -any,
444+
haskell-language-server:haskell-language-server -any
444445

445446
default-language: Haskell2010
446447
build-depends:

hls-test-utils/src/Test/Hls/Util.hs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ module Test.Hls.Util
2929
, waitForDiagnosticsFromSource
3030
, waitForDiagnosticsFromSourceWithTimeout
3131
, withCurrentDirectoryInTmp
32+
, withCurrentDirectoryInTmp'
3233
)
3334
where
3435

@@ -269,30 +270,54 @@ flushStackEnvironment = do
269270

270271
-- | Like 'withCurrentDirectory', but will copy the directory over to the system
271272
-- temporary directory first to avoid haskell-language-server's source tree from
272-
-- interfering with the cradle
273+
-- interfering with the cradle.
274+
--
275+
-- Ignores directories containing build artefacts to avoid interference and
276+
-- provide reproducible test-behaviour.
273277
withCurrentDirectoryInTmp :: FilePath -> IO a -> IO a
274278
withCurrentDirectoryInTmp dir f =
275-
withTempCopy dir $ \newDir ->
279+
withTempCopy ignored dir $ \newDir ->
280+
withCurrentDirectory newDir f
281+
where
282+
ignored = ["dist", "dist-newstyle", ".stack-work"]
283+
284+
285+
-- | Like 'withCurrentDirectory', but will copy the directory over to the system
286+
-- temporary directory first to avoid haskell-language-server's source tree from
287+
-- interfering with the cradle.
288+
--
289+
-- You may specify directories to ignore, but should be careful to maintain reproducibility.
290+
withCurrentDirectoryInTmp' :: [FilePath] -> FilePath -> IO a -> IO a
291+
withCurrentDirectoryInTmp' ignored dir f =
292+
withTempCopy ignored dir $ \newDir ->
276293
withCurrentDirectory newDir f
277294

278-
withTempCopy :: FilePath -> (FilePath -> IO a) -> IO a
279-
withTempCopy srcDir f = do
295+
-- | Example call: @withTempCopy ignored src f@
296+
--
297+
-- Copy directory 'src' to into a temporary directory ignoring any directories
298+
-- (and files) that are listed in 'ignored'. Pass the temporary directory
299+
-- containing the copied sources to the continuation.
300+
withTempCopy :: [FilePath] -> FilePath -> (FilePath -> IO a) -> IO a
301+
withTempCopy ignored srcDir f = do
280302
withSystemTempDirectory "hls-test" $ \newDir -> do
281-
copyDir srcDir newDir
303+
copyDir ignored srcDir newDir
282304
f newDir
283305

284-
copyDir :: FilePath -> FilePath -> IO ()
285-
copyDir src dst = do
306+
-- | Example call: @copyDir ignored src dst@
307+
--
308+
-- Copy directory 'src' to 'dst' ignoring any directories (and files)
309+
-- that are listed in 'ignored'.
310+
copyDir :: [FilePath] -> FilePath -> FilePath -> IO ()
311+
copyDir ignored src dst = do
286312
cnts <- listDirectory src
287313
forM_ cnts $ \file -> do
288314
unless (file `elem` ignored) $ do
289315
let srcFp = src </> file
290316
dstFp = dst </> file
291317
isDir <- doesDirectoryExist srcFp
292318
if isDir
293-
then createDirectory dstFp >> copyDir srcFp dstFp
319+
then createDirectory dstFp >> copyDir ignored srcFp dstFp
294320
else copyFile srcFp dstFp
295-
where ignored = ["dist", "dist-newstyle", ".stack-work"]
296321

297322
fromAction :: (Command |? CodeAction) -> CodeAction
298323
fromAction (InR action) = action

src/Ide/Arguments.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Ide.Arguments
1010
( Arguments(..)
1111
, GhcideArguments(..)
1212
, PrintVersion(..)
13+
, BiosAction(..)
1314
, getArguments
1415
, haskellLanguageServerVersion
1516
, haskellLanguageServerNumericVersion
@@ -27,6 +28,7 @@ import System.Environment
2728
data Arguments
2829
= VersionMode PrintVersion
2930
| ProbeToolsMode
31+
| BiosMode BiosAction
3032
| Ghcide GhcideArguments
3133
| VSCodeExtensionSchemaMode
3234
| DefaultConfigurationMode
@@ -50,12 +52,17 @@ data PrintVersion
5052
| PrintNumericVersion
5153
deriving (Show, Eq, Ord)
5254

55+
data BiosAction
56+
= PrintCradleType
57+
deriving (Show, Eq, Ord)
58+
5359
getArguments :: String -> IO Arguments
5460
getArguments exeName = execParser opts
5561
where
5662
opts = info ((
5763
VersionMode <$> printVersionParser exeName
5864
<|> probeToolsParser exeName
65+
<|> BiosMode <$> biosParser
5966
<|> Ghcide <$> arguments
6067
<|> vsCodeExtensionSchemaModeParser
6168
<|> defaultConfigurationModeParser)
@@ -72,6 +79,11 @@ printVersionParser exeName =
7279
flag' PrintNumericVersion
7380
(long "numeric-version" <> help ("Show numeric version of " ++ exeName))
7481

82+
biosParser :: Parser BiosAction
83+
biosParser =
84+
flag' PrintCradleType
85+
(long "print-cradle" <> help "Print the project cradle type")
86+
7587
probeToolsParser :: String -> Parser Arguments
7688
probeToolsParser exeName =
7789
flag' ProbeToolsMode

src/Ide/Main.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import qualified Data.Text as T
1717
import Development.IDE.Core.Rules
1818
import Development.IDE.Main (isLSP)
1919
import qualified Development.IDE.Main as Main
20+
import qualified Development.IDE.Session as Session
2021
import Development.IDE.Types.Logger as G
2122
import qualified Development.IDE.Types.Options as Ghcide
2223
import Development.IDE.Graph (ShakeOptions (shakeThreads))
@@ -50,6 +51,12 @@ defaultMain args idePlugins = do
5051
VersionMode PrintNumericVersion ->
5152
putStrLn haskellLanguageServerNumericVersion
5253

54+
BiosMode PrintCradleType -> do
55+
dir <- IO.getCurrentDirectory
56+
hieYaml <- Session.findCradle def dir
57+
cradle <- Session.loadCradle def hieYaml dir
58+
print cradle
59+
5360
Ghcide ghcideArgs -> do
5461
{- see WARNING above -}
5562
hPutStrLn stderr hlsVer

test/wrapper/Main.hs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Data.List.Extra (trimEnd)
1+
import Data.List.Extra (trimEnd, isInfixOf)
22
import Data.Maybe
33
import System.Environment
44
import System.Process
@@ -18,6 +18,11 @@ projectGhcVersionTests = testGroup "--project-ghc-version"
1818
, testCase "cabal with global ghc" $ do
1919
ghcVer <- trimEnd <$> readProcess "ghc" ["--numeric-version"] ""
2020
testDir "test/wrapper/testdata/cabal-cur-ver" ghcVer
21+
, testCase "stack with existing cabal build artifact" $ do
22+
-- Should report cabal as existing build artifacts are more important than
23+
-- the existence of 'stack.yaml'
24+
testProjectType "test/wrapper/testdata/stack-with-dist-newstyle"
25+
("cradleOptsProg = CradleAction: Cabal" `isInfixOf`)
2126
]
2227

2328
testDir :: FilePath -> String -> Assertion
@@ -27,3 +32,15 @@ testDir dir expectedVer =
2732
<$> lookupEnv "HLS_WRAPPER_TEST_EXE"
2833
actualVer <- trimEnd <$> readProcess testExe ["--project-ghc-version"] ""
2934
actualVer @?= expectedVer
35+
36+
testProjectType :: FilePath -> (String -> Bool) -> Assertion
37+
testProjectType dir matcher =
38+
withCurrentDirectoryInTmp' [".stack-work", "dist"] dir $ do
39+
wrapperTestExe <- fromMaybe "haskell-language-server-wrapper"
40+
<$> lookupEnv "HLS_WRAPPER_TEST_EXE"
41+
hlsTestExe <- fromMaybe "haskell-language-server"
42+
<$> lookupEnv "HLS_TEST_EXE"
43+
actualWrapperCradle <- trimEnd <$> readProcess wrapperTestExe ["--print-cradle"] ""
44+
actualHlsCradle <- trimEnd <$> readProcess hlsTestExe ["--print-cradle"] ""
45+
matcher actualWrapperCradle @? "Wrapper reported wrong project type: " ++ actualWrapperCradle
46+
matcher actualHlsCradle @? "HLS reported wrong project type: " ++ actualHlsCradle

test/wrapper/testdata/stack-with-dist-newstyle/dist-newstyle/.gitkeep

Whitespace-only changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cabal-version: 2.4
2+
name: stack-with-dist-newstyle
3+
version: 0.1.0.0
4+
5+
library
6+
default-language: Haskell2010
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# specific version does not matter
2+
resolver: ghc-8.10.4

0 commit comments

Comments
 (0)