@@ -48,6 +48,9 @@ module Language.LSP.VFS
48
48
, CodePointPosition (.. )
49
49
, codePointPositionToPosition
50
50
, positionToCodePointPosition
51
+ , CodePointRange (.. )
52
+ , codePointRangeToRange
53
+ , rangeToCodePointRange
51
54
52
55
-- * manipulating the file contents
53
56
, rangeLinesFromVfs
@@ -352,8 +355,8 @@ changeChars logger str start finish new = do
352
355
353
356
-- ---------------------------------------------------------------------
354
357
355
- -- | A position, like a 'J.Position', but where the offsets in the line are measured in Unicode code points
356
- -- instead of UTF-16 code units.
358
+ -- | A position, like a 'J.Position', but where the offsets in the line are measured in
359
+ -- Unicode code points instead of UTF-16 code units.
357
360
data CodePointPosition =
358
361
CodePointPosition
359
362
{ -- | Line position in a document (zero-based).
@@ -362,6 +365,14 @@ data CodePointPosition =
362
365
, _character :: J. UInt
363
366
} deriving (Show , Read , Eq , Ord )
364
367
368
+ -- | A range, like a 'J.Range', but where the offsets in the line are measured in
369
+ -- Unicode code points instead of UTF-16 code units.
370
+ data CodePointRange =
371
+ CodePointRange
372
+ { _start :: CodePointPosition -- ^ The range's start position.
373
+ , _end :: CodePointPosition -- ^ The range's end position.
374
+ } deriving (Show , Read , Eq , Ord )
375
+
365
376
{- Note [Converting between code points and code units]
366
377
This is inherently a somewhat expensive operation, but we take some care to minimize the cost.
367
378
In particular, we use the good asymptotics of 'Rope' to our advantage:
@@ -386,7 +397,7 @@ extractLine rope l = do
386
397
387
398
let (_, suffix) = Rope. splitAtLine l rope
388
399
(prefix, _) = Rope. splitAtLine 1 suffix
389
- pure $ prefix
400
+ pure prefix
390
401
391
402
-- | Translate a code-point offset into a code-unit offset.
392
403
-- Linear in the length of the rope.
@@ -401,7 +412,7 @@ codePointOffsetToCodeUnitOffset rope offset = do
401
412
-- Get the length of the prefix in *code units*
402
413
pure $ Rope. length utf16Prefix
403
414
404
- -- | Translate a code-unit offset into a code-point offset.
415
+ -- | Translate a UTF-16 code-unit offset into a code-point offset.
405
416
-- Linear in the length of the rope.
406
417
codeUnitOffsetToCodePointOffset :: Rope. Rope -> Word -> Maybe Word
407
418
codeUnitOffsetToCodePointOffset rope offset = do
@@ -418,8 +429,6 @@ codeUnitOffsetToCodePointOffset rope offset = do
418
429
--
419
430
-- Will return 'Nothing' if the requested position is out of bounds of the document.
420
431
--
421
- -- We need the file itself because this requires translating between code points and code units.
422
- --
423
432
-- Logarithmic in the number of lines in the document, and linear in the length of the line containing
424
433
-- the position.
425
434
codePointPositionToPosition :: VirtualFile -> CodePointPosition -> Maybe J. Position
@@ -433,12 +442,20 @@ codePointPositionToPosition vFile (CodePointPosition l cpc) = do
433
442
cuc <- codePointOffsetToCodeUnitOffset utfLine (fromIntegral cpc)
434
443
pure $ J. Position l (fromIntegral cuc)
435
444
445
+ -- | Given a virtual file, translate a 'CodePointRange' in that file into a 'J.Range' in that file.
446
+ --
447
+ -- Will return 'Nothing' if any of the positions are out of bounds of the document.
448
+ --
449
+ -- Logarithmic in the number of lines in the document, and linear in the length of the lines containing
450
+ -- the positions.
451
+ codePointRangeToRange :: VirtualFile -> CodePointRange -> Maybe J. Range
452
+ codePointRangeToRange vFile (CodePointRange b e) =
453
+ J. Range <$> codePointPositionToPosition vFile b <*> codePointPositionToPosition vFile e
454
+
436
455
-- | Given a virtual file, translate a 'J.Position' in that file into a 'CodePointPosition' in that file.
437
456
--
438
457
-- Will return 'Nothing' if the requested position lies inside a code point, or if it is out of bounds of the document.
439
458
--
440
- -- We need the file itself because this requires translating between code unit and code points.
441
- --
442
459
-- Logarithmic in the number of lines in the document, and linear in the length of the line containing
443
460
-- the position.
444
461
positionToCodePointPosition :: VirtualFile -> J. Position -> Maybe CodePointPosition
@@ -450,6 +467,16 @@ positionToCodePointPosition vFile (J.Position l cuc) = do
450
467
cpc <- codeUnitOffsetToCodePointOffset utf16Line (fromIntegral cuc)
451
468
pure $ CodePointPosition l (fromIntegral cpc)
452
469
470
+ -- | Given a virtual file, translate a 'J.Range' in that file into a 'CodePointRange' in that file.
471
+ --
472
+ -- Will return 'Nothing' if any of the positions are out of bounds of the document.
473
+ --
474
+ -- Logarithmic in the number of lines in the document, and linear in the length of the lines containing
475
+ -- the positions.
476
+ rangeToCodePointRange :: VirtualFile -> J. Range -> Maybe CodePointRange
477
+ rangeToCodePointRange vFile (J. Range b e) =
478
+ CodePointRange <$> positionToCodePointPosition vFile b <*> positionToCodePointPosition vFile e
479
+
453
480
-- ---------------------------------------------------------------------
454
481
455
482
-- TODO:AZ:move this to somewhere sane
0 commit comments