aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/conv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server/src/conv.rs')
-rw-r--r--crates/ra_lsp_server/src/conv.rs86
1 files changed, 66 insertions, 20 deletions
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 32e67838e..82c7e757f 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -384,27 +384,53 @@ impl TryConvWith for &NavigationTarget {
384 } 384 }
385} 385}
386 386
387pub fn to_location_link( 387impl TryConvWith for (FileId, RangeInfo<NavigationTarget>) {
388 target: &RangeInfo<NavigationTarget>, 388 type Ctx = WorldSnapshot;
389 world: &WorldSnapshot, 389 type Output = LocationLink;
390 // line index for original range file 390 fn try_conv_with(self, world: &WorldSnapshot) -> Result<LocationLink> {
391 line_index: &LineIndex, 391 let (src_file_id, target) = self;
392) -> Result<LocationLink> { 392
393 let target_uri = target.info.file_id().try_conv_with(world)?; 393 let target_uri = target.info.file_id().try_conv_with(world)?;
394 let tgt_line_index = world.analysis().file_line_index(target.info.file_id()); 394 let src_line_index = world.analysis().file_line_index(src_file_id);
395 395 let tgt_line_index = world.analysis().file_line_index(target.info.file_id());
396 let target_range = target.info.full_range().conv_with(&tgt_line_index); 396
397 397 let target_range = target.info.full_range().conv_with(&tgt_line_index);
398 let target_selection_range = 398
399 target.info.focus_range().map(|it| it.conv_with(&tgt_line_index)).unwrap_or(target_range); 399 let target_selection_range = target
400 .info
401 .focus_range()
402 .map(|it| it.conv_with(&tgt_line_index))
403 .unwrap_or(target_range);
404
405 let res = LocationLink {
406 origin_selection_range: Some(target.range.conv_with(&src_line_index)),
407 target_uri,
408 target_range,
409 target_selection_range,
410 };
411 Ok(res)
412 }
413}
400 414
401 let res = LocationLink { 415impl TryConvWith for (FileId, RangeInfo<Vec<NavigationTarget>>) {
402 origin_selection_range: Some(target.range.conv_with(line_index)), 416 type Ctx = WorldSnapshot;
403 target_uri, 417 type Output = req::GotoDefinitionResponse;
404 target_range, 418 fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::GotoTypeDefinitionResponse> {
405 target_selection_range, 419 let (file_id, RangeInfo { range, info: navs }) = self;
406 }; 420 let links = navs
407 Ok(res) 421 .into_iter()
422 .map(|nav| (file_id, RangeInfo::new(range, nav)))
423 .try_conv_with_to_vec(world)?;
424 if world.options.supports_location_link {
425 Ok(links.into())
426 } else {
427 let locations: Vec<Location> = links
428 .into_iter()
429 .map(|link| Location { uri: link.target_uri, range: link.target_selection_range })
430 .collect();
431 Ok(locations.into())
432 }
433 }
408} 434}
409 435
410pub fn to_location( 436pub fn to_location(
@@ -452,3 +478,23 @@ where
452 self.iter.next().map(|item| item.conv_with(self.ctx)) 478 self.iter.next().map(|item| item.conv_with(self.ctx))
453 } 479 }
454} 480}
481
482pub trait TryConvWithToVec<'a>: Sized + 'a {
483 type Ctx;
484 type Output;
485
486 fn try_conv_with_to_vec(self, ctx: &'a Self::Ctx) -> Result<Vec<Self::Output>>;
487}
488
489impl<'a, I> TryConvWithToVec<'a> for I
490where
491 I: Iterator + 'a,
492 I::Item: TryConvWith,
493{
494 type Ctx = <I::Item as TryConvWith>::Ctx;
495 type Output = <I::Item as TryConvWith>::Output;
496
497 fn try_conv_with_to_vec(self, ctx: &'a Self::Ctx) -> Result<Vec<Self::Output>> {
498 self.map(|it| it.try_conv_with(ctx)).collect()
499 }
500}