TextRange,
};
-use crate::{FileRange, FileSymbol};
+use crate::FileSymbol;
use super::short_label::ShortLabel;
pub fn range(&self) -> TextRange {
self.focus_range.unwrap_or(self.full_range)
}
+ /// A "most interesting" range withing the `full_range`.
+ ///
+ /// Typically, `full_range` is the whole syntax node,
+ /// including doc comments, and `focus_range` is the range of the identifier.
+ pub fn focus_range(&self) -> Option<TextRange> {
+ self.focus_range
+ }
+ pub fn full_range(&self) -> TextRange {
+ self.full_range
+ }
+ pub fn file_id(&self) -> FileId {
+ self.file_id
+ }
pub fn name(&self) -> &SmolStr {
&self.name
self.kind
}
- pub fn file_id(&self) -> FileId {
- self.file_id
- }
-
- // TODO: inconsistent
- pub fn file_range(&self) -> FileRange {
- FileRange { file_id: self.file_id, range: self.full_range }
- }
-
- pub fn full_range(&self) -> TextRange {
- self.full_range
- }
-
pub fn docs(&self) -> Option<&str> {
self.docs.as_deref()
}
self.description.as_deref()
}
- /// A "most interesting" range withing the `full_range`.
- ///
- /// Typically, `full_range` is the whole syntax node,
- /// including doc comments, and `focus_range` is the range of the identifier.
- pub fn focus_range(&self) -> Option<TextRange> {
- self.focus_range
- }
-
pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
if let Some(src) = module.declaration_source(db) {
mod tests {
use ra_db::FileRange;
- use crate::mock_analysis::{analysis_and_position, MockAnalysis};
+ use crate::mock_analysis::MockAnalysis;
fn check(ra_fixture: &str) {
let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture);
fn exec_query(snap: &GlobalStateSnapshot, query: Query) -> Result<Vec<SymbolInformation>> {
let mut res = Vec::new();
for nav in snap.analysis.symbol_search(query)? {
+ let container_name = nav.container_name().map(|v| v.to_string());
let info = SymbolInformation {
name: nav.name().to_string(),
kind: to_proto::symbol_kind(nav.kind()),
- location: to_proto::location(snap, nav.file_range())?,
- container_name: nav.container_name().map(|v| v.to_string()),
+ location: to_proto::location_from_nav(snap, nav)?,
+ container_name,
deprecated: None,
};
res.push(info);
let position = to_proto::position(&line_index, position.offset);
let locations: Vec<_> = nav_data
.info
- .iter()
- .filter_map(|it| to_proto::location(snap, it.file_range()).ok())
+ .into_iter()
+ .filter_map(|nav| to_proto::location_from_nav(snap, nav).ok())
.collect();
let title = implementation_title(locations.len());
let command = show_references_command(title, &uri, position, locations);
Ok(loc)
}
+/// Perefer using `location_link`, if the client has the cap.
+pub(crate) fn location_from_nav(
+ snap: &GlobalStateSnapshot,
+ nav: NavigationTarget,
+) -> Result<lsp_types::Location> {
+ let url = url(snap, nav.file_id());
+ let line_index = snap.analysis.file_line_index(nav.file_id())?;
+ let range = range(&line_index, nav.full_range());
+ let loc = lsp_types::Location::new(url, range);
+ Ok(loc)
+}
+
pub(crate) fn location_link(
snap: &GlobalStateSnapshot,
src: Option<FileRange>,