Skip to content

Commit 27f20b8

Browse files
committed
Generic Glean-based LSP server
1 parent 2942641 commit 27f20b8

File tree

9 files changed

+964
-0
lines changed

9 files changed

+964
-0
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ jobs:
190190
- name: Run tests
191191
run: make test
192192

193+
- name: Build glean-lsp
194+
run: make glean-lsp
195+
193196
# check the vscode extension builds
194197
vscode:
195198
runs-on: ubuntu-latest

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ glean-clang:: gen-schema glean glean.cabal cxx-libraries glean/schema/cpp/schema
325325
glean-hie:: glean.cabal cxx-libraries
326326
$(CABAL) build hie-indexer
327327

328+
.PHONY: glean-lsp
329+
glean-lsp:: glean.cabal
330+
$(CABAL) build glean-lsp
331+
328332
define bash_macros
329333
call_cabal() {
330334
$(CABAL) "$$@"

cabal.project

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ packages:
1111
hsthrift/http/thrift-http.cabal
1212
glean.cabal
1313
glean/lang/clang/glean-clang.cabal
14+
glean/lsp
1415

1516
optional-packages:
1617
hsthrift/folly-clib/folly-clib.cabal
@@ -23,6 +24,8 @@ allow-newer: haskeline:base
2324
-- develop with -Werror on, for consistency with internal Meta CI.
2425
program-options
2526
ghc-options: -Werror
27+
package glean-lsp
28+
ghc-options: -Werror
2629

2730
package fb-util
2831
flags: +folly

glean/lsp/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Revision history for glean-lsp
2+
3+
## 0.1.0.0
4+
5+
* First version. Released on an unsuspecting world.

glean/lsp/Data/Path.hs

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{-
2+
Copyright (c) 2023 Joseph Sumabat
3+
4+
See glean/lsp/LICENSE
5+
-}
6+
7+
module Data.Path (
8+
Path (path, Path, UncheckedPath),
9+
KnownPathKind (sPathKind),
10+
AbsPath,
11+
PathKind (..),
12+
RelPath,
13+
filePathToAbs,
14+
unsafeFilePathToAbs,
15+
filePathToRel,
16+
toFilePath,
17+
(</>),
18+
makeRelative,
19+
absToRel,
20+
(<.>),
21+
(-<.>),
22+
filePathToAbsThrow,
23+
uncheckedCoercePath,
24+
relToAbsThrow,
25+
)
26+
where
27+
28+
import Control.Monad.Catch
29+
import Control.Monad.IO.Class
30+
import Data.Aeson qualified as Aeson
31+
import Data.Coerce (coerce)
32+
import Data.Hashable (Hashable)
33+
import Data.String (IsString (..))
34+
import GHC.Stack (HasCallStack)
35+
import System.Directory qualified as Dir
36+
import System.FilePath qualified as FilePath
37+
import UnliftIO (stringException)
38+
39+
-- | Rel means may be relative or absolute, absolute means must be absolute
40+
data PathKind = Rel | Abs
41+
42+
data SPathKind p where
43+
SRel :: SPathKind Rel
44+
SAbs :: SPathKind Abs
45+
46+
class KnownPathKind p where
47+
sPathKind :: SPathKind p
48+
49+
instance KnownPathKind Abs where
50+
sPathKind = SAbs
51+
52+
instance KnownPathKind Rel where
53+
sPathKind = SRel
54+
55+
newtype Path (p :: PathKind) = UncheckedPath {path :: FilePath}
56+
deriving (Show, Eq, Ord, Hashable, Aeson.FromJSON, Aeson.ToJSON)
57+
58+
uncheckedCoercePath :: Path p -> Path q
59+
uncheckedCoercePath = coerce
60+
61+
instance IsString (Path Rel) where
62+
fromString = UncheckedPath
63+
64+
pattern Path :: FilePath -> Path p
65+
pattern Path p <- UncheckedPath p
66+
67+
type AbsPath = Path Abs
68+
69+
type RelPath = Path Rel
70+
71+
toFilePath :: (HasCallStack) => Path p -> FilePath
72+
toFilePath = (.path)
73+
74+
filePathToRel :: (HasCallStack) => FilePath -> RelPath
75+
filePathToRel = UncheckedPath
76+
77+
filePathToAbs :: (HasCallStack, MonadIO m) => FilePath -> m AbsPath
78+
filePathToAbs p = do
79+
absPath <- liftIO $ Dir.makeAbsolute p
80+
pure $ UncheckedPath absPath
81+
82+
unsafeFilePathToAbs :: (HasCallStack) => FilePath -> AbsPath
83+
unsafeFilePathToAbs p
84+
| FilePath.isAbsolute p = UncheckedPath p
85+
| otherwise = error "unsafeOsPathToAbs: path is not absolute"
86+
87+
relToAbsThrow :: (MonadThrow m, HasCallStack) => RelPath -> m AbsPath
88+
relToAbsThrow (UncheckedPath p) = filePathToAbsThrow p
89+
90+
filePathToAbsThrow :: (MonadThrow m, HasCallStack) => FilePath -> m AbsPath
91+
filePathToAbsThrow p
92+
| FilePath.isAbsolute p = pure $ UncheckedPath p
93+
| otherwise = throwM (stringException $ "filepath was not absolute: " ++ p)
94+
95+
(</>) :: Path p -> Path Rel -> Path p
96+
(UncheckedPath p) </> (UncheckedPath p') = UncheckedPath (p FilePath.</> p')
97+
98+
infixr 5 </>
99+
100+
(<.>) :: Path p -> String -> Path p
101+
(UncheckedPath p) <.> ext = UncheckedPath (p FilePath.<.> ext)
102+
103+
(-<.>) :: Path p -> String -> Path p
104+
(UncheckedPath p) -<.> ext = UncheckedPath (p FilePath.-<.> ext)
105+
106+
absToRel :: AbsPath -> RelPath
107+
absToRel (UncheckedPath p) = UncheckedPath p
108+
109+
makeRelative :: Path p -> Path q -> Path Rel
110+
makeRelative (UncheckedPath p) (UncheckedPath q) = UncheckedPath (FilePath.makeRelative p q)

0 commit comments

Comments
 (0)