Skip to content

Commit 1b9ee73

Browse files
committed
Use approrpriate number types
This ensures that we use either: - `Int32` - `Word32` - `Float` In particular, this gets us: - Appropriate `Bounded` instances (see the original issue haskell/haskell-language-server#2169). - More picky `aeson` instances for the bounded types. Rather than use newtypes, we just use the existing appropriate Haskell numeric types for bounded integers. Fixes haskell#354.
1 parent 0f389b5 commit 1b9ee73

24 files changed

+112
-95
lines changed

lsp-test/src/Language/LSP/Test.hs

+3-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ runSessionWithHandles' serverProc serverIn serverOut config' caps rootDir sessio
198198
config <- envOverrideConfig config'
199199

200200
let initializeParams = InitializeParams Nothing
201-
(Just pid)
201+
-- Narowing to Int32 here, but it's unlikely that a pid will
202+
-- be outside the range
203+
(Just $ fromIntegral pid)
202204
(Just lspTestClientInfo)
203205
(Just $ T.pack absRootDir)
204206
(Just $ filePathToUri absRootDir)

lsp-test/src/Language/LSP/Test/Session.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ bumpTimeoutId prev = do
169169

170170
data SessionState = SessionState
171171
{
172-
curReqId :: !Int
172+
curReqId :: !Int32
173173
, vfs :: !VFS
174174
, curDiagnostics :: !(Map.Map NormalizedUri [Diagnostic])
175175
, overridingTimeout :: !Bool
@@ -308,7 +308,7 @@ updateStateC = awaitForever $ \msg -> do
308308
respond (FromServerMess SWindowWorkDoneProgressCreate req) =
309309
sendMessage $ ResponseMessage "2.0" (Just $ req ^. LSP.id) (Right Empty)
310310
respond (FromServerMess SWorkspaceApplyEdit r) = do
311-
sendMessage $ ResponseMessage "2.0" (Just $ r ^. LSP.id) (Right $ ApplyWorkspaceEditResponseBody True Nothing)
311+
sendMessage $ ResponseMessage "2.0" (Just $ r ^. LSP.id) (Right $ ApplyWorkspaceEditResponseBody True Nothing Nothing)
312312
respond _ = pure ()
313313

314314

lsp-types/src/Language/LSP/Types/Common.hs

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,19 @@
44
{-# LANGUAGE TypeOperators #-}
55

66
-- | Common types that aren't in the specification
7-
module Language.LSP.Types.Common where
7+
module Language.LSP.Types.Common (
8+
type (|?) (..)
9+
, toEither
10+
, List (..)
11+
, Empty (..)
12+
, Int32
13+
, Word32 ) where
814

915
import Control.Applicative
1016
import Control.DeepSeq
1117
import Data.Aeson
18+
import Data.Int (Int32)
19+
import Data.Word (Word32)
1220
import GHC.Generics
1321

1422
-- | A terser, isomorphic data type for 'Either', that does not get tagged when

lsp-types/src/Language/LSP/Types/Diagnostic.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ data Diagnostic =
8282
Diagnostic
8383
{ _range :: Range
8484
, _severity :: Maybe DiagnosticSeverity
85-
, _code :: Maybe (Int |? Text)
85+
, _code :: Maybe (Int32 |? Text)
8686
, _source :: Maybe DiagnosticSource
8787
, _message :: Text
8888
, _tags :: Maybe (List DiagnosticTag)
@@ -131,7 +131,7 @@ data PublishDiagnosticsParams =
131131
-- published for.
132132
--
133133
-- Since LSP 3.15.0
134-
, _version :: Maybe Int
134+
, _version :: Maybe Word32
135135
-- | An array of diagnostic information items.
136136
, _diagnostics :: List Diagnostic
137137
} deriving (Read,Show,Eq)

lsp-types/src/Language/LSP/Types/DocumentColor.hs

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ deriveJSON lspOptions ''DocumentColorParams
4545
-- | Represents a color in RGBA space.
4646
data Color =
4747
Color
48-
{ _red :: Int -- ^ The red component of this color in the range [0-1].
49-
, _green :: Int -- ^ The green component of this color in the range [0-1].
50-
, _blue :: Int -- ^ The blue component of this color in the range [0-1].
51-
, _alpha :: Int -- ^ The alpha component of this color in the range [0-1].
48+
{ _red :: Float -- ^ The red component of this color in the range [0-1].
49+
, _green :: Float -- ^ The green component of this color in the range [0-1].
50+
, _blue :: Float -- ^ The blue component of this color in the range [0-1].
51+
, _alpha :: Float -- ^ The alpha component of this color in the range [0-1].
5252
} deriving (Read, Show, Eq)
5353
deriveJSON lspOptions ''Color
5454

lsp-types/src/Language/LSP/Types/FoldingRange.hs

+6-5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Language.LSP.Types.FoldingRange where
66
import qualified Data.Aeson as A
77
import Data.Aeson.TH
88
import Data.Text (Text)
9+
import Language.LSP.Types.Common
910
import Language.LSP.Types.Progress
1011
import Language.LSP.Types.StaticRegistrationOptions
1112
import Language.LSP.Types.TextDocument
@@ -23,7 +24,7 @@ data FoldingRangeClientCapabilities =
2324
_dynamicRegistration :: Maybe Bool
2425
-- | The maximum number of folding ranges that the client prefers to receive
2526
-- per document. The value serves as a hint, servers are free to follow the limit.
26-
, _rangeLimit :: Maybe Int
27+
, _rangeLimit :: Maybe Word32
2728
-- | If set, the client signals that it only supports folding complete lines. If set,
2829
-- client will ignore specified `startCharacter` and `endCharacter` properties in a
2930
-- FoldingRange.
@@ -79,15 +80,15 @@ instance A.FromJSON FoldingRangeKind where
7980
data FoldingRange =
8081
FoldingRange
8182
{ -- | The zero-based line number from where the folded range starts.
82-
_startLine :: Int
83+
_startLine :: Word32
8384
-- | The zero-based character offset from where the folded range
8485
-- starts. If not defined, defaults to the length of the start line.
85-
, _startCharacter :: Maybe Int
86+
, _startCharacter :: Maybe Word32
8687
-- | The zero-based line number where the folded range ends.
87-
, _endLine :: Int
88+
, _endLine :: Word32
8889
-- | The zero-based character offset before the folded range ends.
8990
-- If not defined, defaults to the length of the end line.
90-
, _endCharacter :: Maybe Int
91+
, _endCharacter :: Maybe Word32
9192
-- | Describes the kind of the folding range such as 'comment' or
9293
-- 'region'. The kind is used to categorize folding ranges and used
9394
-- by commands like 'Fold all comments'. See 'FoldingRangeKind' for

lsp-types/src/Language/LSP/Types/Formatting.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Language.LSP.Types.Formatting where
44

55
import Data.Aeson.TH
66
import Data.Text (Text)
7+
import Language.LSP.Types.Common
78
import Language.LSP.Types.Location
89
import Language.LSP.Types.Progress
910
import Language.LSP.Types.TextDocument
@@ -29,7 +30,7 @@ deriveJSON lspOptions ''DocumentFormattingRegistrationOptions
2930
-- | Value-object describing what options formatting should use.
3031
data FormattingOptions = FormattingOptions
3132
{ -- | Size of a tab in spaces.
32-
_tabSize :: Int,
33+
_tabSize :: Word32,
3334
-- | Prefer spaces over tabs
3435
_insertSpaces :: Bool,
3536
-- | Trim trailing whitespace on a line.

lsp-types/src/Language/LSP/Types/Initialize.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ data ClientInfo =
4141
deriveJSON lspOptions ''ClientInfo
4242

4343
makeExtendingDatatype "InitializeParams" [''WorkDoneProgressParams]
44-
[ ("_processId", [t| Maybe Int|])
44+
[ ("_processId", [t| Maybe Int32|])
4545
, ("_clientInfo", [t| Maybe ClientInfo |])
4646
, ("_rootPath", [t| Maybe Text |])
4747
, ("_rootUri", [t| Maybe Uri |])

lsp-types/src/Language/LSP/Types/Location.hs

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ module Language.LSP.Types.Location where
44

55
import Control.DeepSeq
66
import Data.Aeson.TH
7-
import GHC.Generics
7+
import GHC.Generics hiding (UInt)
8+
import Language.LSP.Types.Common
89
import Language.LSP.Types.Uri
910
import Language.LSP.Types.Utils
1011

@@ -13,11 +14,11 @@ import Language.LSP.Types.Utils
1314
data Position =
1415
Position
1516
{ -- | Line position in a document (zero-based).
16-
_line :: Int
17+
_line :: Word32
1718
-- | Character offset on a line in a document (zero-based). Assuming that
1819
-- the line is represented as a string, the @character@ value represents the
1920
-- gap between the @character@ and @character + 1@.
20-
, _character :: Int
21+
, _character :: Word32
2122
} deriving (Show, Read, Eq, Ord, Generic)
2223

2324
instance NFData Position
@@ -72,5 +73,5 @@ deriveJSON lspOptions ''LocationLink
7273

7374
-- | A helper function for creating ranges.
7475
-- prop> mkRange l c l' c' = Range (Position l c) (Position l' c')
75-
mkRange :: Int -> Int -> Int -> Int -> Range
76+
mkRange :: Word32 -> Word32 -> Word32 -> Word32 -> Range
7677
mkRange l c l' c' = Range (Position l c) (Position l' c')

lsp-types/src/Language/LSP/Types/LspId.hs

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ module Language.LSP.Types.LspId where
88

99
import qualified Data.Aeson as A
1010
import Data.Text (Text)
11+
import Data.Int (Int32)
1112
import Data.IxMap
12-
import Language.LSP.Types.Method
13+
14+
import Language.LSP.Types.Method
1315

1416
-- | Id used for a request, Can be either a String or an Int
15-
data LspId (m :: Method f Request) = IdInt !Int | IdString !Text
17+
data LspId (m :: Method f Request) = IdInt !Int32 | IdString !Text
1618
deriving (Show,Read,Eq,Ord)
1719

1820
instance A.ToJSON (LspId m) where

lsp-types/src/Language/LSP/Types/Progress.hs

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import qualified Data.Aeson as A
1111
import Data.Aeson.TH
1212
import Data.Maybe (catMaybes)
1313
import Data.Text (Text)
14+
import Language.LSP.Types.Common
1415
import Language.LSP.Types.Utils
1516

1617
-- | A token used to report progress back or return partial results for a
1718
-- specific request.
1819
-- @since 0.17.0.0
1920
data ProgressToken
20-
= ProgressNumericToken Int
21+
= ProgressNumericToken Int32
2122
| ProgressTextToken Text
2223
deriving (Show, Read, Eq, Ord)
2324

@@ -58,7 +59,7 @@ data WorkDoneProgressBeginParams =
5859
--
5960
-- The value should be steadily rising. Clients are free to ignore values
6061
-- that are not following this rule.
61-
, _percentage :: Maybe Double
62+
, _percentage :: Maybe Word32
6263
} deriving (Show, Read, Eq)
6364

6465
instance A.ToJSON WorkDoneProgressBeginParams where
@@ -103,7 +104,7 @@ data WorkDoneProgressReportParams =
103104
-- If infinite progress was indicated in the start notification client
104105
-- are allowed to ignore the value. In addition the value should be steadily
105106
-- rising. Clients are free to ignore values that are not following this rule.
106-
, _percentage :: Maybe Double
107+
, _percentage :: Maybe Word32
107108
} deriving (Show, Read, Eq)
108109

109110
instance A.ToJSON WorkDoneProgressReportParams where

lsp-types/src/Language/LSP/Types/SemanticTokens.hs

+23-23
Original file line numberDiff line numberDiff line change
@@ -292,12 +292,12 @@ data SemanticTokens = SemanticTokens {
292292
_resultId :: Maybe Text,
293293

294294
-- | The actual tokens.
295-
_xdata :: List Int
295+
_xdata :: List Word32
296296
} deriving (Show, Read, Eq)
297297
deriveJSON lspOptions ''SemanticTokens
298298

299299
data SemanticTokensPartialResult = SemanticTokensPartialResult {
300-
_xdata :: List Int
300+
_xdata :: List Word32
301301
}
302302
deriveJSON lspOptions ''SemanticTokensPartialResult
303303

@@ -311,11 +311,11 @@ deriveJSON lspOptions ''SemanticTokensDeltaParams
311311

312312
data SemanticTokensEdit = SemanticTokensEdit {
313313
-- | The start offset of the edit.
314-
_start :: Int,
314+
_start :: Word32,
315315
-- | The count of elements to remove.
316-
_deleteCount :: Int,
316+
_deleteCount :: Word32,
317317
-- | The elements to insert.
318-
_xdata :: Maybe (List Int)
318+
_xdata :: Maybe (List Word32)
319319
} deriving (Show, Read, Eq)
320320
deriveJSON lspOptions ''SemanticTokensEdit
321321

@@ -359,9 +359,9 @@ deriveJSON lspOptions ''SemanticTokensWorkspaceClientCapabilities
359359
-- | A single 'semantic token' as described in the LSP specification, using absolute positions.
360360
-- This is the kind of token that is usually easiest for editors to produce.
361361
data SemanticTokenAbsolute = SemanticTokenAbsolute {
362-
line :: Int,
363-
startChar :: Int,
364-
length :: Int,
362+
line :: Word32,
363+
startChar :: Word32,
364+
length :: Word32,
365365
tokenType :: SemanticTokenTypes,
366366
tokenModifiers :: [SemanticTokenModifiers]
367367
} deriving (Show, Read, Eq, Ord)
@@ -370,9 +370,9 @@ data SemanticTokenAbsolute = SemanticTokenAbsolute {
370370

371371
-- | A single 'semantic token' as described in the LSP specification, using relative positions.
372372
data SemanticTokenRelative = SemanticTokenRelative {
373-
deltaLine :: Int,
374-
deltaStartChar :: Int,
375-
length :: Int,
373+
deltaLine :: Word32,
374+
deltaStartChar :: Word32,
375+
length :: Word32,
376376
tokenType :: SemanticTokenTypes,
377377
tokenModifiers :: [SemanticTokenModifiers]
378378
} deriving (Show, Read, Eq, Ord)
@@ -385,7 +385,7 @@ relativizeTokens :: [SemanticTokenAbsolute] -> [SemanticTokenRelative]
385385
relativizeTokens xs = DList.toList $ go 0 0 xs mempty
386386
where
387387
-- Pass an accumulator to make this tail-recursive
388-
go :: Int -> Int -> [SemanticTokenAbsolute] -> DList.DList SemanticTokenRelative -> DList.DList SemanticTokenRelative
388+
go :: Word32 -> Word32 -> [SemanticTokenAbsolute] -> DList.DList SemanticTokenRelative -> DList.DList SemanticTokenRelative
389389
go _ _ [] acc = acc
390390
go lastLine lastChar (SemanticTokenAbsolute l c len ty mods:ts) acc =
391391
let
@@ -400,7 +400,7 @@ absolutizeTokens :: [SemanticTokenRelative] -> [SemanticTokenAbsolute]
400400
absolutizeTokens xs = DList.toList $ go 0 0 xs mempty
401401
where
402402
-- Pass an accumulator to make this tail-recursive
403-
go :: Int -> Int -> [SemanticTokenRelative] -> DList.DList SemanticTokenAbsolute -> DList.DList SemanticTokenAbsolute
403+
go :: Word32 -> Word32 -> [SemanticTokenRelative] -> DList.DList SemanticTokenAbsolute -> DList.DList SemanticTokenAbsolute
404404
go _ _ [] acc = acc
405405
go lastLine lastChar (SemanticTokenRelative dl dc len ty mods:ts) acc =
406406
let
@@ -410,18 +410,18 @@ absolutizeTokens xs = DList.toList $ go 0 0 xs mempty
410410
in go l c ts (DList.snoc acc (SemanticTokenAbsolute l c len ty mods))
411411

412412
-- | Encode a series of relatively-positioned semantic tokens into an integer array following the given legend.
413-
encodeTokens :: SemanticTokensLegend -> [SemanticTokenRelative] -> Either Text [Int]
413+
encodeTokens :: SemanticTokensLegend -> [SemanticTokenRelative] -> Either Text [Word32]
414414
encodeTokens SemanticTokensLegend{_tokenTypes=List tts,_tokenModifiers=List tms} sts =
415415
DList.toList . DList.concat <$> traverse encodeToken sts
416416
where
417417
-- Note that there's no "fast" version of these (e.g. backed by an IntMap or similar)
418418
-- in general, due to the possibility of unknown token types which are only identified by strings.
419-
tyMap :: Map.Map SemanticTokenTypes Int
419+
tyMap :: Map.Map SemanticTokenTypes Word32
420420
tyMap = Map.fromList $ zip tts [0..]
421421
modMap :: Map.Map SemanticTokenModifiers Int
422422
modMap = Map.fromList $ zip tms [0..]
423423

424-
lookupTy :: SemanticTokenTypes -> Either Text Int
424+
lookupTy :: SemanticTokenTypes -> Either Text Word32
425425
lookupTy ty = case Map.lookup ty tyMap of
426426
Just tycode -> pure tycode
427427
Nothing -> throwError $ "Semantic token type " <> fromString (show ty) <> " did not appear in the legend"
@@ -431,17 +431,17 @@ encodeTokens SemanticTokensLegend{_tokenTypes=List tts,_tokenModifiers=List tms}
431431
Nothing -> throwError $ "Semantic token modifier " <> fromString (show modifier) <> " did not appear in the legend"
432432

433433
-- Use a DList here for better efficiency when concatenating all these together
434-
encodeToken :: SemanticTokenRelative -> Either Text (DList.DList Int)
434+
encodeToken :: SemanticTokenRelative -> Either Text (DList.DList Word32)
435435
encodeToken (SemanticTokenRelative dl dc len ty mods) = do
436436
tycode <- lookupTy ty
437437
modcodes <- traverse lookupMod mods
438-
let combinedModcode = foldl' Bits.setBit Bits.zeroBits modcodes
438+
let combinedModcode :: Word32 = foldl' Bits.setBit Bits.zeroBits modcodes
439439

440440
pure [dl, dc, len, tycode, combinedModcode ]
441441

442442
-- This is basically 'SemanticTokensEdit', but slightly easier to work with.
443443
-- | An edit to a buffer of items.
444-
data Edit a = Edit { editStart :: Int, editDeleteCount :: Int, editInsertions :: [a] }
444+
data Edit a = Edit { editStart :: Word32, editDeleteCount :: Word32, editInsertions :: [a] }
445445
deriving (Read, Show, Eq, Ord)
446446

447447
-- | Compute a list of edits that will turn the first list into the second list.
@@ -455,15 +455,15 @@ computeEdits l r = DList.toList $ go 0 Nothing (Diff.getGroupedDiff l r) mempty
455455
dump the 'Edit' into the accumulator.
456456
We need the index, because 'Edit's need to say where they start.
457457
-}
458-
go :: Int -> Maybe (Edit a) -> [Diff.Diff [a]] -> DList.DList (Edit a) -> DList.DList (Edit a)
458+
go :: Word32 -> Maybe (Edit a) -> [Diff.Diff [a]] -> DList.DList (Edit a) -> DList.DList (Edit a)
459459
-- No more diffs: append the current edit if there is one and return
460460
go _ e [] acc = acc <> DList.fromList (maybeToList e)
461461

462462
-- Items only on the left (i.e. deletions): increment the current index, and record the count of deletions,
463463
-- starting a new edit if necessary.
464464
go ix e (Diff.First ds : rest) acc =
465465
let
466-
deleteCount = Prelude.length ds
466+
deleteCount = fromIntegral $ Prelude.length ds
467467
edit = fromMaybe (Edit ix 0 []) e
468468
in go (ix + deleteCount) (Just (edit{editDeleteCount=editDeleteCount edit + deleteCount})) rest acc
469469
-- Items only on the right (i.e. insertions): don't increment the current index, and record the insertions,
@@ -475,11 +475,11 @@ computeEdits l r = DList.toList $ go 0 Nothing (Diff.getGroupedDiff l r) mempty
475475
-- Items on both sides: increment the current index appropriately (since the items appear on the left),
476476
-- and append the current edit (if there is one) to our list of edits (since we can't continue it with a break).
477477
go ix e (Diff.Both bs _bs : rest) acc =
478-
let bothCount = Prelude.length bs
478+
let bothCount = fromIntegral $ Prelude.length bs
479479
in go (ix + bothCount) Nothing rest (acc <> DList.fromList (maybeToList e))
480480

481481
-- | Convenience method for making a 'SemanticTokens' from a list of 'SemanticTokenAbsolute's. An error may be returned if
482-
-- the tokens refer to types or modifiers which are not in the legend.
482+
483483
-- The resulting 'SemanticTokens' lacks a result ID, which must be set separately if you are using that.
484484
makeSemanticTokens :: SemanticTokensLegend -> [SemanticTokenAbsolute] -> Either Text SemanticTokens
485485
makeSemanticTokens legend sts = do

0 commit comments

Comments
 (0)