Make documentation on hover configurable
This commit is contained in:
parent
388a91c8a8
commit
a93d166f0f
@ -1,8 +1,5 @@
|
|||||||
use either::Either;
|
use either::Either;
|
||||||
use hir::{
|
use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay};
|
||||||
AsAssocItem, AssocItemContainer, GenericParam, HasAttrs, HasSource, HirDisplay, InFile, Module,
|
|
||||||
ModuleDef, Semantics,
|
|
||||||
};
|
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
base_db::SourceDatabase,
|
base_db::SourceDatabase,
|
||||||
defs::{Definition, NameClass, NameRefClass},
|
defs::{Definition, NameClass, NameRefClass},
|
||||||
@ -40,6 +37,7 @@ pub struct HoverConfig {
|
|||||||
pub goto_type_def: bool,
|
pub goto_type_def: bool,
|
||||||
pub links_in_hover: bool,
|
pub links_in_hover: bool,
|
||||||
pub markdown: bool,
|
pub markdown: bool,
|
||||||
|
pub documentation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HoverConfig {
|
impl HoverConfig {
|
||||||
@ -51,14 +49,15 @@ impl HoverConfig {
|
|||||||
goto_type_def: false,
|
goto_type_def: false,
|
||||||
links_in_hover: true,
|
links_in_hover: true,
|
||||||
markdown: true,
|
markdown: true,
|
||||||
|
documentation: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn any(&self) -> bool {
|
pub fn any_actions(&self) -> bool {
|
||||||
self.implementations || self.references || self.runnable() || self.goto_type_def
|
self.implementations || self.references || self.runnable() || self.goto_type_def
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn none(&self) -> bool {
|
pub fn no_actions(&self) -> bool {
|
||||||
!self.any()
|
!self.any_actions()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runnable(&self) -> bool {
|
pub fn runnable(&self) -> bool {
|
||||||
@ -97,9 +96,10 @@ pub(crate) fn hover(
|
|||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
links_in_hover: bool,
|
links_in_hover: bool,
|
||||||
|
documentation: bool,
|
||||||
markdown: bool,
|
markdown: bool,
|
||||||
) -> Option<RangeInfo<HoverResult>> {
|
) -> Option<RangeInfo<HoverResult>> {
|
||||||
let sema = Semantics::new(db);
|
let sema = hir::Semantics::new(db);
|
||||||
let file = sema.parse(position.file_id).syntax().clone();
|
let file = sema.parse(position.file_id).syntax().clone();
|
||||||
let token = pick_best(file.token_at_offset(position.offset))?;
|
let token = pick_best(file.token_at_offset(position.offset))?;
|
||||||
let token = sema.descend_into_macros(token);
|
let token = sema.descend_into_macros(token);
|
||||||
@ -131,7 +131,7 @@ pub(crate) fn hover(
|
|||||||
let (docs, doc_mapping) = attributes.docs_with_rangemap(db)?;
|
let (docs, doc_mapping) = attributes.docs_with_rangemap(db)?;
|
||||||
let (idl_range, link, ns) =
|
let (idl_range, link, ns) =
|
||||||
extract_definitions_from_markdown(docs.as_str()).into_iter().find_map(|(range, link, ns)| {
|
extract_definitions_from_markdown(docs.as_str()).into_iter().find_map(|(range, link, ns)| {
|
||||||
let InFile { file_id, value: range } = doc_mapping.map(range)?;
|
let hir::InFile { file_id, value: range } = doc_mapping.map(range)?;
|
||||||
if file_id == position.file_id.into() && range.contains(position.offset) {
|
if file_id == position.file_id.into() && range.contains(position.offset) {
|
||||||
Some((range, link, ns))
|
Some((range, link, ns))
|
||||||
} else {
|
} else {
|
||||||
@ -151,12 +151,14 @@ pub(crate) fn hover(
|
|||||||
|
|
||||||
if let Some(definition) = definition {
|
if let Some(definition) = definition {
|
||||||
let famous_defs = match &definition {
|
let famous_defs = match &definition {
|
||||||
Definition::ModuleDef(ModuleDef::BuiltinType(_)) => {
|
Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => {
|
||||||
Some(FamousDefs(&sema, sema.scope(&node).krate()))
|
Some(FamousDefs(&sema, sema.scope(&node).krate()))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(markup) = hover_for_definition(db, definition, famous_defs.as_ref()) {
|
if let Some(markup) =
|
||||||
|
hover_for_definition(db, definition, famous_defs.as_ref(), documentation)
|
||||||
|
{
|
||||||
res.markup = process_markup(sema.db, definition, &markup, links_in_hover, markdown);
|
res.markup = process_markup(sema.db, definition, &markup, links_in_hover, markdown);
|
||||||
if let Some(action) = show_implementations_action(db, definition) {
|
if let Some(action) = show_implementations_action(db, definition) {
|
||||||
res.actions.push(action);
|
res.actions.push(action);
|
||||||
@ -261,8 +263,10 @@ fn to_action(nav_target: NavigationTarget) -> HoverAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let adt = match def {
|
let adt = match def {
|
||||||
Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action),
|
Definition::ModuleDef(hir::ModuleDef::Trait(it)) => {
|
||||||
Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it),
|
return it.try_to_nav(db).map(to_action)
|
||||||
|
}
|
||||||
|
Definition::ModuleDef(hir::ModuleDef::Adt(it)) => Some(it),
|
||||||
Definition::SelfType(it) => it.self_ty(db).as_adt(),
|
Definition::SelfType(it) => it.self_ty(db).as_adt(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}?;
|
}?;
|
||||||
@ -271,25 +275,27 @@ fn to_action(nav_target: NavigationTarget) -> HoverAction {
|
|||||||
|
|
||||||
fn show_fn_references_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
fn show_fn_references_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
||||||
match def {
|
match def {
|
||||||
Definition::ModuleDef(ModuleDef::Function(it)) => it.try_to_nav(db).map(|nav_target| {
|
Definition::ModuleDef(hir::ModuleDef::Function(it)) => {
|
||||||
|
it.try_to_nav(db).map(|nav_target| {
|
||||||
HoverAction::Reference(FilePosition {
|
HoverAction::Reference(FilePosition {
|
||||||
file_id: nav_target.file_id,
|
file_id: nav_target.file_id,
|
||||||
offset: nav_target.focus_or_full_range().start(),
|
offset: nav_target.focus_or_full_range().start(),
|
||||||
})
|
})
|
||||||
}),
|
})
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runnable_action(
|
fn runnable_action(
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &hir::Semantics<RootDatabase>,
|
||||||
def: Definition,
|
def: Definition,
|
||||||
file_id: FileId,
|
file_id: FileId,
|
||||||
) -> Option<HoverAction> {
|
) -> Option<HoverAction> {
|
||||||
match def {
|
match def {
|
||||||
Definition::ModuleDef(it) => match it {
|
Definition::ModuleDef(it) => match it {
|
||||||
ModuleDef::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable),
|
hir::ModuleDef::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable),
|
||||||
ModuleDef::Function(func) => {
|
hir::ModuleDef::Function(func) => {
|
||||||
let src = func.source(sema.db)?;
|
let src = func.source(sema.db)?;
|
||||||
if src.file_id != file_id.into() {
|
if src.file_id != file_id.into() {
|
||||||
cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment);
|
cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment);
|
||||||
@ -306,19 +312,19 @@ fn runnable_action(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
||||||
let mut targets: Vec<ModuleDef> = Vec::new();
|
let mut targets: Vec<hir::ModuleDef> = Vec::new();
|
||||||
let mut push_new_def = |item: ModuleDef| {
|
let mut push_new_def = |item: hir::ModuleDef| {
|
||||||
if !targets.contains(&item) {
|
if !targets.contains(&item) {
|
||||||
targets.push(item);
|
targets.push(item);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Definition::GenericParam(GenericParam::TypeParam(it)) = def {
|
if let Definition::GenericParam(hir::GenericParam::TypeParam(it)) = def {
|
||||||
it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into()));
|
it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into()));
|
||||||
} else {
|
} else {
|
||||||
let ty = match def {
|
let ty = match def {
|
||||||
Definition::Local(it) => it.ty(db),
|
Definition::Local(it) => it.ty(db),
|
||||||
Definition::GenericParam(GenericParam::ConstParam(it)) => it.ty(db),
|
Definition::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db),
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -348,13 +354,7 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
|
|||||||
Some(HoverAction::GoToType(targets))
|
Some(HoverAction::GoToType(targets))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hover_markup(
|
fn hover_markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Option<Markup> {
|
||||||
docs: Option<String>,
|
|
||||||
desc: Option<String>,
|
|
||||||
mod_path: Option<String>,
|
|
||||||
) -> Option<Markup> {
|
|
||||||
match desc {
|
|
||||||
Some(desc) => {
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
if let Some(mod_path) = mod_path {
|
if let Some(mod_path) = mod_path {
|
||||||
@ -368,9 +368,6 @@ fn hover_markup(
|
|||||||
format_to!(buf, "\n___\n\n{}", doc);
|
format_to!(buf, "\n___\n\n{}", doc);
|
||||||
}
|
}
|
||||||
Some(buf.into())
|
Some(buf.into())
|
||||||
}
|
|
||||||
None => docs.map(Markup::from),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_markup(
|
fn process_markup(
|
||||||
@ -396,11 +393,11 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
|
|||||||
Definition::Field(f) => Some(f.parent_def(db).name(db)),
|
Definition::Field(f) => Some(f.parent_def(db).name(db)),
|
||||||
Definition::Local(l) => l.parent(db).name(db),
|
Definition::Local(l) => l.parent(db).name(db),
|
||||||
Definition::ModuleDef(md) => match md {
|
Definition::ModuleDef(md) => match md {
|
||||||
ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
|
hir::ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) {
|
||||||
AssocItemContainer::Trait(t) => Some(t.name(db)),
|
hir::AssocItemContainer::Trait(t) => Some(t.name(db)),
|
||||||
AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)),
|
hir::AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)),
|
||||||
},
|
},
|
||||||
ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
|
hir::ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -408,7 +405,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
|
|||||||
.map(|name| name.to_string())
|
.map(|name| name.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
|
fn render_path(db: &RootDatabase, module: hir::Module, item_name: Option<String>) -> String {
|
||||||
let crate_name =
|
let crate_name =
|
||||||
db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
|
db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
|
||||||
let module_path = module
|
let module_path = module
|
||||||
@ -420,6 +417,9 @@ fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
|
fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
|
||||||
|
if let Definition::GenericParam(_) = def {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
|
def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,60 +427,53 @@ fn hover_for_definition(
|
|||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
def: Definition,
|
def: Definition,
|
||||||
famous_defs: Option<&FamousDefs>,
|
famous_defs: Option<&FamousDefs>,
|
||||||
|
documentation: bool,
|
||||||
) -> Option<Markup> {
|
) -> Option<Markup> {
|
||||||
let mod_path = definition_mod_path(db, &def);
|
let mod_path = definition_mod_path(db, &def);
|
||||||
return match def {
|
let (label, docs) = match def {
|
||||||
Definition::Macro(it) => match &it.source(db)?.value {
|
Definition::Macro(it) => match &it.source(db)?.value {
|
||||||
Either::Left(mac) => {
|
Either::Left(mac) => {
|
||||||
let label = macro_label(mac);
|
let label = macro_label(mac);
|
||||||
from_def_source_labeled(db, it, Some(label), mod_path)
|
(label, it.attrs(db).docs())
|
||||||
}
|
}
|
||||||
Either::Right(_) => {
|
Either::Right(_) => {
|
||||||
// FIXME
|
// FIXME
|
||||||
None
|
return None;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Definition::Field(def) => from_hir_fmt(db, def, mod_path),
|
Definition::Field(def) => label_and_docs(db, def),
|
||||||
Definition::ModuleDef(it) => match it {
|
Definition::ModuleDef(it) => match it {
|
||||||
ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Module(it) => label_and_docs(db, it),
|
||||||
ModuleDef::Function(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Function(it) => label_and_docs(db, it),
|
||||||
ModuleDef::Adt(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Adt(it) => label_and_docs(db, it),
|
||||||
ModuleDef::Variant(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Variant(it) => label_and_docs(db, it),
|
||||||
ModuleDef::Const(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Const(it) => label_and_docs(db, it),
|
||||||
ModuleDef::Static(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Static(it) => label_and_docs(db, it),
|
||||||
ModuleDef::Trait(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::Trait(it) => label_and_docs(db, it),
|
||||||
ModuleDef::TypeAlias(it) => from_hir_fmt(db, it, mod_path),
|
hir::ModuleDef::TypeAlias(it) => label_and_docs(db, it),
|
||||||
ModuleDef::BuiltinType(it) => famous_defs
|
hir::ModuleDef::BuiltinType(it) => {
|
||||||
|
return famous_defs
|
||||||
.and_then(|fd| hover_for_builtin(fd, it))
|
.and_then(|fd| hover_for_builtin(fd, it))
|
||||||
.or_else(|| Some(Markup::fenced_block(&it.name()))),
|
.or_else(|| Some(Markup::fenced_block(&it.name())))
|
||||||
},
|
|
||||||
Definition::Local(it) => hover_for_local(it, db),
|
|
||||||
Definition::SelfType(impl_def) => {
|
|
||||||
impl_def.self_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path))
|
|
||||||
}
|
}
|
||||||
Definition::GenericParam(it) => from_hir_fmt(db, it, None),
|
},
|
||||||
Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))),
|
Definition::Local(it) => return hover_for_local(it, db),
|
||||||
|
Definition::SelfType(impl_def) => {
|
||||||
|
impl_def.self_ty(db).as_adt().map(|adt| label_and_docs(db, adt))?
|
||||||
|
}
|
||||||
|
Definition::GenericParam(it) => label_and_docs(db, it),
|
||||||
|
Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db))),
|
||||||
};
|
};
|
||||||
|
|
||||||
fn from_hir_fmt<D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup>
|
return hover_markup(docs.filter(|_| documentation).map(Into::into), label, mod_path);
|
||||||
|
|
||||||
|
fn label_and_docs<D>(db: &RootDatabase, def: D) -> (String, Option<hir::Documentation>)
|
||||||
where
|
where
|
||||||
D: HasAttrs + HirDisplay,
|
D: HasAttrs + HirDisplay,
|
||||||
{
|
{
|
||||||
let label = def.display(db).to_string();
|
let label = def.display(db).to_string();
|
||||||
from_def_source_labeled(db, def, Some(label), mod_path)
|
let docs = def.attrs(db).docs();
|
||||||
}
|
(label, docs)
|
||||||
|
|
||||||
fn from_def_source_labeled<D>(
|
|
||||||
db: &RootDatabase,
|
|
||||||
def: D,
|
|
||||||
short_label: Option<String>,
|
|
||||||
mod_path: Option<String>,
|
|
||||||
) -> Option<Markup>
|
|
||||||
where
|
|
||||||
D: HasAttrs,
|
|
||||||
{
|
|
||||||
let docs = def.attrs(db).docs().map(Into::into);
|
|
||||||
hover_markup(docs, short_label, mod_path)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,11 +497,11 @@ fn hover_for_local(it: hir::Local, db: &RootDatabase) -> Option<Markup> {
|
|||||||
}
|
}
|
||||||
Either::Right(_) => format!("{}self: {}", is_mut, ty),
|
Either::Right(_) => format!("{}self: {}", is_mut, ty),
|
||||||
};
|
};
|
||||||
hover_markup(None, Some(desc), None)
|
hover_markup(None, desc, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hover_for_keyword(
|
fn hover_for_keyword(
|
||||||
sema: &Semantics<RootDatabase>,
|
sema: &hir::Semantics<RootDatabase>,
|
||||||
links_in_hover: bool,
|
links_in_hover: bool,
|
||||||
markdown: bool,
|
markdown: bool,
|
||||||
token: &SyntaxToken,
|
token: &SyntaxToken,
|
||||||
@ -524,7 +517,7 @@ fn hover_for_keyword(
|
|||||||
let markup = process_markup(
|
let markup = process_markup(
|
||||||
sema.db,
|
sema.db,
|
||||||
Definition::ModuleDef(doc_owner.into()),
|
Definition::ModuleDef(doc_owner.into()),
|
||||||
&hover_markup(Some(docs.into()), Some(token.text().into()), None)?,
|
&hover_markup(Some(docs.into()), token.text().into(), None)?,
|
||||||
links_in_hover,
|
links_in_hover,
|
||||||
markdown,
|
markdown,
|
||||||
);
|
);
|
||||||
@ -536,7 +529,7 @@ fn hover_for_builtin(famous_defs: &FamousDefs, builtin: hir::BuiltinType) -> Opt
|
|||||||
let primitive_mod = format!("prim_{}", builtin.name());
|
let primitive_mod = format!("prim_{}", builtin.name());
|
||||||
let doc_owner = find_std_module(famous_defs, &primitive_mod)?;
|
let doc_owner = find_std_module(famous_defs, &primitive_mod)?;
|
||||||
let docs = doc_owner.attrs(famous_defs.0.db).docs()?;
|
let docs = doc_owner.attrs(famous_defs.0.db).docs()?;
|
||||||
hover_markup(Some(docs.into()), Some(builtin.name().to_string()), None)
|
hover_markup(Some(docs.into()), builtin.name().to_string(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option<hir::Module> {
|
fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option<hir::Module> {
|
||||||
@ -572,12 +565,12 @@ mod tests {
|
|||||||
|
|
||||||
fn check_hover_no_result(ra_fixture: &str) {
|
fn check_hover_no_result(ra_fixture: &str) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (analysis, position) = fixture::position(ra_fixture);
|
||||||
assert!(analysis.hover(position, true, true).unwrap().is_none());
|
assert!(analysis.hover(position, true, true, true).unwrap().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(ra_fixture: &str, expect: Expect) {
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (analysis, position) = fixture::position(ra_fixture);
|
||||||
let hover = analysis.hover(position, true, true).unwrap().unwrap();
|
let hover = analysis.hover(position, true, true, true).unwrap().unwrap();
|
||||||
|
|
||||||
let content = analysis.db.file_text(position.file_id);
|
let content = analysis.db.file_text(position.file_id);
|
||||||
let hovered_element = &content[hover.range];
|
let hovered_element = &content[hover.range];
|
||||||
@ -588,7 +581,7 @@ fn check(ra_fixture: &str, expect: Expect) {
|
|||||||
|
|
||||||
fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
|
fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (analysis, position) = fixture::position(ra_fixture);
|
||||||
let hover = analysis.hover(position, false, true).unwrap().unwrap();
|
let hover = analysis.hover(position, false, true, true).unwrap().unwrap();
|
||||||
|
|
||||||
let content = analysis.db.file_text(position.file_id);
|
let content = analysis.db.file_text(position.file_id);
|
||||||
let hovered_element = &content[hover.range];
|
let hovered_element = &content[hover.range];
|
||||||
@ -599,7 +592,7 @@ fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
|
|||||||
|
|
||||||
fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
|
fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (analysis, position) = fixture::position(ra_fixture);
|
||||||
let hover = analysis.hover(position, true, false).unwrap().unwrap();
|
let hover = analysis.hover(position, true, true, false).unwrap().unwrap();
|
||||||
|
|
||||||
let content = analysis.db.file_text(position.file_id);
|
let content = analysis.db.file_text(position.file_id);
|
||||||
let hovered_element = &content[hover.range];
|
let hovered_element = &content[hover.range];
|
||||||
@ -610,7 +603,7 @@ fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) {
|
|||||||
|
|
||||||
fn check_actions(ra_fixture: &str, expect: Expect) {
|
fn check_actions(ra_fixture: &str, expect: Expect) {
|
||||||
let (analysis, position) = fixture::position(ra_fixture);
|
let (analysis, position) = fixture::position(ra_fixture);
|
||||||
let hover = analysis.hover(position, true, true).unwrap().unwrap();
|
let hover = analysis.hover(position, true, true, true).unwrap().unwrap();
|
||||||
expect.assert_debug_eq(&hover.info.actions)
|
expect.assert_debug_eq(&hover.info.actions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,9 +407,10 @@ pub fn hover(
|
|||||||
&self,
|
&self,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
links_in_hover: bool,
|
links_in_hover: bool,
|
||||||
|
documentation: bool,
|
||||||
markdown: bool,
|
markdown: bool,
|
||||||
) -> Cancellable<Option<RangeInfo<HoverResult>>> {
|
) -> Cancellable<Option<RangeInfo<HoverResult>>> {
|
||||||
self.with_db(|db| hover::hover(db, position, links_in_hover, markdown))
|
self.with_db(|db| hover::hover(db, position, links_in_hover, documentation, markdown))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return URL(s) for the documentation of the symbol under the cursor.
|
/// Return URL(s) for the documentation of the symbol under the cursor.
|
||||||
|
@ -141,6 +141,11 @@ struct ConfigData {
|
|||||||
/// their contents.
|
/// their contents.
|
||||||
highlighting_strings: bool = "true",
|
highlighting_strings: bool = "true",
|
||||||
|
|
||||||
|
/// Whether to show documentation on hover.
|
||||||
|
hover_documentation: bool = "true",
|
||||||
|
/// Use markdown syntax for links in hover.
|
||||||
|
hover_linksInHover: bool = "true",
|
||||||
|
|
||||||
/// Whether to show `Debug` action. Only applies when
|
/// Whether to show `Debug` action. Only applies when
|
||||||
/// `#rust-analyzer.hoverActions.enable#` is set.
|
/// `#rust-analyzer.hoverActions.enable#` is set.
|
||||||
hoverActions_debug: bool = "true",
|
hoverActions_debug: bool = "true",
|
||||||
@ -158,8 +163,6 @@ struct ConfigData {
|
|||||||
/// Whether to show `Run` action. Only applies when
|
/// Whether to show `Run` action. Only applies when
|
||||||
/// `#rust-analyzer.hoverActions.enable#` is set.
|
/// `#rust-analyzer.hoverActions.enable#` is set.
|
||||||
hoverActions_run: bool = "true",
|
hoverActions_run: bool = "true",
|
||||||
/// Use markdown syntax for links in hover.
|
|
||||||
hoverActions_linksInHover: bool = "true",
|
|
||||||
|
|
||||||
/// Whether to show inlay type hints for method chains.
|
/// Whether to show inlay type hints for method chains.
|
||||||
inlayHints_chainingHints: bool = "true",
|
inlayHints_chainingHints: bool = "true",
|
||||||
@ -726,7 +729,7 @@ pub fn hover(&self) -> HoverConfig {
|
|||||||
run: self.data.hoverActions_enable && self.data.hoverActions_run,
|
run: self.data.hoverActions_enable && self.data.hoverActions_run,
|
||||||
debug: self.data.hoverActions_enable && self.data.hoverActions_debug,
|
debug: self.data.hoverActions_enable && self.data.hoverActions_debug,
|
||||||
goto_type_def: self.data.hoverActions_enable && self.data.hoverActions_gotoTypeDef,
|
goto_type_def: self.data.hoverActions_enable && self.data.hoverActions_gotoTypeDef,
|
||||||
links_in_hover: self.data.hoverActions_linksInHover,
|
links_in_hover: self.data.hover_linksInHover,
|
||||||
markdown: try_or!(
|
markdown: try_or!(
|
||||||
self.caps
|
self.caps
|
||||||
.text_document
|
.text_document
|
||||||
@ -739,6 +742,7 @@ pub fn hover(&self) -> HoverConfig {
|
|||||||
&[]
|
&[]
|
||||||
)
|
)
|
||||||
.contains(&MarkupKind::Markdown),
|
.contains(&MarkupKind::Markdown),
|
||||||
|
documentation: self.data.hover_documentation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,8 +862,12 @@ pub(crate) fn handle_hover(
|
|||||||
let _p = profile::span("handle_hover");
|
let _p = profile::span("handle_hover");
|
||||||
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
let position = from_proto::file_position(&snap, params.text_document_position_params)?;
|
||||||
let hover_config = snap.config.hover();
|
let hover_config = snap.config.hover();
|
||||||
let info =
|
let info = match snap.analysis.hover(
|
||||||
match snap.analysis.hover(position, hover_config.links_in_hover, hover_config.markdown)? {
|
position,
|
||||||
|
hover_config.links_in_hover,
|
||||||
|
hover_config.documentation,
|
||||||
|
hover_config.markdown,
|
||||||
|
)? {
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(info) => info,
|
Some(info) => info,
|
||||||
};
|
};
|
||||||
@ -1587,7 +1591,7 @@ fn prepare_hover_actions(
|
|||||||
snap: &GlobalStateSnapshot,
|
snap: &GlobalStateSnapshot,
|
||||||
actions: &[HoverAction],
|
actions: &[HoverAction],
|
||||||
) -> Vec<lsp_ext::CommandLinkGroup> {
|
) -> Vec<lsp_ext::CommandLinkGroup> {
|
||||||
if snap.config.hover().none() || !snap.config.hover_actions() {
|
if snap.config.hover().no_actions() || !snap.config.hover_actions() {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +205,16 @@ In some editors (e.g. vscode) semantic tokens override other highlighting gramma
|
|||||||
By disabling semantic tokens for strings, other grammars can be used to highlight
|
By disabling semantic tokens for strings, other grammars can be used to highlight
|
||||||
their contents.
|
their contents.
|
||||||
--
|
--
|
||||||
|
[[rust-analyzer.hover.documentation]]rust-analyzer.hover.documentation (default: `true`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Whether to show documentation on hover.
|
||||||
|
--
|
||||||
|
[[rust-analyzer.hover.linksInHover]]rust-analyzer.hover.linksInHover (default: `true`)::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
Use markdown syntax for links in hover.
|
||||||
|
--
|
||||||
[[rust-analyzer.hoverActions.debug]]rust-analyzer.hoverActions.debug (default: `true`)::
|
[[rust-analyzer.hoverActions.debug]]rust-analyzer.hoverActions.debug (default: `true`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
@ -240,11 +250,6 @@ Whether to show `References` action. Only applies when
|
|||||||
Whether to show `Run` action. Only applies when
|
Whether to show `Run` action. Only applies when
|
||||||
`#rust-analyzer.hoverActions.enable#` is set.
|
`#rust-analyzer.hoverActions.enable#` is set.
|
||||||
--
|
--
|
||||||
[[rust-analyzer.hoverActions.linksInHover]]rust-analyzer.hoverActions.linksInHover (default: `true`)::
|
|
||||||
+
|
|
||||||
--
|
|
||||||
Use markdown syntax for links in hover.
|
|
||||||
--
|
|
||||||
[[rust-analyzer.inlayHints.chainingHints]]rust-analyzer.inlayHints.chainingHints (default: `true`)::
|
[[rust-analyzer.inlayHints.chainingHints]]rust-analyzer.inlayHints.chainingHints (default: `true`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
@ -640,6 +640,16 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"rust-analyzer.hover.documentation": {
|
||||||
|
"markdownDescription": "Whether to show documentation on hover.",
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"rust-analyzer.hover.linksInHover": {
|
||||||
|
"markdownDescription": "Use markdown syntax for links in hover.",
|
||||||
|
"default": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"rust-analyzer.hoverActions.debug": {
|
"rust-analyzer.hoverActions.debug": {
|
||||||
"markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.",
|
"markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.",
|
||||||
"default": true,
|
"default": true,
|
||||||
@ -670,11 +680,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"rust-analyzer.hoverActions.linksInHover": {
|
|
||||||
"markdownDescription": "Use markdown syntax for links in hover.",
|
|
||||||
"default": true,
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"rust-analyzer.inlayHints.chainingHints": {
|
"rust-analyzer.inlayHints.chainingHints": {
|
||||||
"markdownDescription": "Whether to show inlay type hints for method chains.",
|
"markdownDescription": "Whether to show inlay type hints for method chains.",
|
||||||
"default": true,
|
"default": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user