Skip to content

Commit 2971653

Browse files
committed
Refactor a little
1 parent 484ad55 commit 2971653

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

lsp/src/Language/LSP/VFS.hs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -388,48 +388,66 @@ extractLine rope l = do
388388
(prefix, _) = Rope.splitAtLine 1 suffix
389389
pure $ prefix
390390

391+
-- | Translate a code-point offset into a code-unit offset.
392+
-- Linear in the length of the rope.
393+
codePointOffsetToCodeUnitOffset :: URope.Rope -> Word -> Maybe Word
394+
codePointOffsetToCodeUnitOffset rope offset = do
395+
-- Check for the position being out of bounds
396+
guard $ offset <= URope.length rope
397+
-- Split at the given position in *code points*
398+
let (prefix, _) = URope.splitAt offset rope
399+
-- Convert the prefix to a rope using *code units*
400+
utf16Prefix = Rope.fromText $ URope.toText prefix
401+
-- Get the length of the prefix in *code units*
402+
pure $ Rope.length utf16Prefix
403+
404+
-- | Translate a code-unit offset into a code-point offset.
405+
-- Linear in the length of the rope.
406+
codeUnitOffsetToCodePointOffset :: Rope.Rope -> Word -> Maybe Word
407+
codeUnitOffsetToCodePointOffset rope offset = do
408+
-- Check for the position being out of bounds
409+
guard $ offset <= Rope.length rope
410+
-- Split at the given position in *code units*
411+
(prefix, _) <- Rope.splitAt offset rope
412+
-- Convert the prefixto a rope using *code points*
413+
let utfPrefix = URope.fromText $ Rope.toText prefix
414+
-- Get the length of the prefix in *code points*
415+
pure $ URope.length utfPrefix
416+
391417
-- | Given a virtual file, translate a 'CodePointPosition' in that file into a 'J.Position' in that file.
392418
--
393419
-- Will return 'Nothing' if the requested position is out of bounds of the document.
394420
--
395421
-- We need the file itself because this requires translating between code points and code units.
422+
--
423+
-- Logarithmic in the number of lines in the document, and linear in the length of the line containing
424+
-- the position.
396425
codePointPositionToPosition :: VirtualFile -> CodePointPosition -> Maybe J.Position
397426
codePointPositionToPosition vFile (CodePointPosition l cpc) = do
398427
-- See Note [Converting between code points and code units]
399428
let text = _file_text vFile
400429
utf16Line <- extractLine text (fromIntegral l)
401-
402430
-- Convert the line a rope using *code points*
403431
let utfLine = URope.fromText $ Rope.toText utf16Line
404-
-- Check for the position being out of bounds
405-
guard $ (fromIntegral cpc) <= URope.length utfLine
406-
-- Split at the given position in *code points*
407-
let (utfLinePrefix, _) = URope.splitAt (fromIntegral cpc) utfLine
408-
-- Convert the prefix to a rope using *code units*
409-
utf16LinePrefix = Rope.fromText $ URope.toText utfLinePrefix
410-
-- Get the length of the prefix in *code units*
411-
cuc = Rope.length utf16LinePrefix
432+
433+
cuc <- codePointOffsetToCodeUnitOffset utfLine (fromIntegral cpc)
412434
pure $ J.Position l (fromIntegral cuc)
413435

414436
-- | Given a virtual file, translate a 'J.Position' in that file into a 'CodePointPosition' in that file.
415437
--
416438
-- Will return 'Nothing' if the requested position lies inside a code point, or if it is out of bounds of the document.
417439
--
418440
-- We need the file itself because this requires translating between code unit and code points.
441+
--
442+
-- Logarithmic in the number of lines in the document, and linear in the length of the line containing
443+
-- the position.
419444
positionToCodePointPosition :: VirtualFile -> J.Position -> Maybe CodePointPosition
420445
positionToCodePointPosition vFile (J.Position l cuc) = do
421446
-- See Note [Converting between code points and code units]
422447
let text = _file_text vFile
423448
utf16Line <- extractLine text (fromIntegral l)
424449

425-
-- Check for the position being out of bounds
426-
guard $ (fromIntegral cuc) <= Rope.length utf16Line
427-
-- Split at the given position in *code units*
428-
(utf16LinePrefix, _) <- Rope.splitAt (fromIntegral cuc) utf16Line
429-
-- Convert the prefixto a rope using *code points*
430-
let utfLinePrefix = URope.fromText $ Rope.toText utf16LinePrefix
431-
-- Get the length of the prefix in *code points*
432-
cpc = URope.length utfLinePrefix
450+
cpc <- codeUnitOffsetToCodePointOffset utf16Line (fromIntegral cuc)
433451
pure $ CodePointPosition l (fromIntegral cpc)
434452

435453
-- ---------------------------------------------------------------------

0 commit comments

Comments
 (0)