Tidy up
This commit is contained in:
parent
68ee033762
commit
f497f6b4e0
@ -1,8 +1,10 @@
|
|||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir::{
|
use hir::{
|
||||||
Adt, AsAssocItem, AssocItemContainer, FieldSource, HasSource, HirDisplay, ModuleDef,
|
Adt, AsAssocItem, AssocItemContainer, FieldSource, HasSource, HirDisplay, ModuleDef,
|
||||||
ModuleSource, Semantics, Module, Documentation, AttrDef, Crate
|
ModuleSource, Semantics, Documentation, AttrDef, Crate
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
@ -12,8 +14,12 @@ use ra_ide_db::{
|
|||||||
};
|
};
|
||||||
use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset};
|
use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset};
|
||||||
use ra_project_model::ProjectWorkspace;
|
use ra_project_model::ProjectWorkspace;
|
||||||
use ra_hir_def::{item_scope::ItemInNs, db::DefDatabase, ModuleDefId};
|
use ra_hir_def::{item_scope::ItemInNs, db::DefDatabase};
|
||||||
use ra_tt::{Literal, Ident, Punct, TokenTree, Leaf, Subtree, SmolStr};
|
use ra_tt::{Literal, Ident, Punct, TokenTree, Leaf};
|
||||||
|
|
||||||
|
use comrak::{parse_document,format_commonmark, ComrakOptions, Arena};
|
||||||
|
use comrak::nodes::NodeValue;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
display::{
|
display::{
|
||||||
@ -68,13 +74,6 @@ pub struct HoverGotoTypeData {
|
|||||||
pub nav: NavigationTarget,
|
pub nav: NavigationTarget,
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use comrak::{parse_document,format_commonmark, ComrakOptions, Arena};
|
|
||||||
use comrak::nodes::NodeValue;
|
|
||||||
use url::Url;
|
|
||||||
use ra_ide_db::imports_locator::ImportsLocator;
|
|
||||||
|
|
||||||
/// Contains the results when hovering over an item
|
/// Contains the results when hovering over an item
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct HoverResult {
|
pub struct HoverResult {
|
||||||
@ -392,50 +391,42 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
|
|||||||
|
|
||||||
/// Rewrite documentation links in markdown to point to local documentation/docs.rs
|
/// Rewrite documentation links in markdown to point to local documentation/docs.rs
|
||||||
fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition, workspaces: Arc<Vec<ProjectWorkspace>>) -> Option<String> {
|
fn rewrite_links(db: &RootDatabase, markdown: &str, definition: &Definition, workspaces: Arc<Vec<ProjectWorkspace>>) -> Option<String> {
|
||||||
// FIXME: Fail early
|
let arena = Arena::new();
|
||||||
if let (Some(name), Some(module)) = (definition.name(db), definition.module(db)) {
|
let doc = parse_document(&arena, markdown, &ComrakOptions::default());
|
||||||
let krate_name = module.krate().display_name(db)?;
|
let doc_target_dirs = workspaces
|
||||||
let arena = Arena::new();
|
.iter()
|
||||||
let doc = parse_document(&arena, markdown, &ComrakOptions::default());
|
.filter_map(|workspace| if let ProjectWorkspace::Cargo{cargo: cargo_workspace, ..} = workspace {Some(cargo_workspace)} else {None})
|
||||||
let path = module.path_to_root(db);
|
.map(|workspace| workspace.workspace_root())
|
||||||
let mut doc_target_dirs = workspaces
|
// TODO: `target` is configurable in cargo config, we should respect it
|
||||||
.iter()
|
.map(|root| root.join("target/doc"));
|
||||||
.filter_map(|workspace| if let ProjectWorkspace::Cargo{cargo: cargo_workspace, ..} = workspace {Some(cargo_workspace)} else {None})
|
|
||||||
.map(|workspace| workspace.workspace_root())
|
|
||||||
// TODO: `target` is configurable in cargo config, we should respect it
|
|
||||||
.map(|root| root.join("target/doc"));
|
|
||||||
|
|
||||||
iter_nodes(doc, &|node| {
|
iter_nodes(doc, &|node| {
|
||||||
match &mut node.data.borrow_mut().value {
|
match &mut node.data.borrow_mut().value {
|
||||||
&mut NodeValue::Link(ref mut link) => {
|
&mut NodeValue::Link(ref mut link) => {
|
||||||
match Url::parse(&String::from_utf8(link.url.clone()).unwrap()) {
|
match Url::parse(&String::from_utf8(link.url.clone()).unwrap()) {
|
||||||
// If this is a valid absolute URL don't touch it
|
// If this is a valid absolute URL don't touch it
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
// If contains .html file-based link to new page
|
// If contains .html file-based link to new page
|
||||||
// If starts with #fragment file-based link to fragment on current page
|
// If starts with #fragment file-based link to fragment on current page
|
||||||
// If contains :: module-based link
|
// If contains :: module-based link
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let link_str = String::from_utf8(link.url.clone()).unwrap();
|
let link_str = String::from_utf8(link.url.clone()).unwrap();
|
||||||
let resolved = try_resolve_path(db, &mut doc_target_dirs.clone(), definition, &link_str, UrlMode::Url)
|
let resolved = try_resolve_path(db, &mut doc_target_dirs.clone(), definition, &link_str, UrlMode::Url)
|
||||||
.or_else(|| try_resolve_intra(db, &mut doc_target_dirs.clone(), definition, &link_str));
|
.or_else(|| try_resolve_intra(db, &mut doc_target_dirs.clone(), definition, &link_str));
|
||||||
|
|
||||||
if let Some(resolved) = resolved {
|
|
||||||
link.url = resolved.as_bytes().to_vec();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if let Some(resolved) = resolved {
|
||||||
|
link.url = resolved.as_bytes().to_vec();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => ()
|
},
|
||||||
}
|
_ => ()
|
||||||
});
|
}
|
||||||
let mut out = Vec::new();
|
});
|
||||||
format_commonmark(doc, &ComrakOptions::default(), &mut out);
|
let mut out = Vec::new();
|
||||||
Some(String::from_utf8(out).unwrap())
|
format_commonmark(doc, &ComrakOptions::default(), &mut out).ok()?;
|
||||||
} else {
|
Some(String::from_utf8(out).unwrap())
|
||||||
// eprintln!("WARN: Unable to determine name or module for hover; link rewriting disabled.");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to resolve path to local documentation via intra-doc-links (i.e. `super::gateway::Shard`)
|
/// Try to resolve path to local documentation via intra-doc-links (i.e. `super::gateway::Shard`)
|
||||||
@ -467,13 +458,10 @@ fn try_resolve_path(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = Pat
|
|||||||
UrlMode::Url => {
|
UrlMode::Url => {
|
||||||
let root = get_doc_url(db, &krate);
|
let root = get_doc_url(db, &krate);
|
||||||
let mut base = base.join("/");
|
let mut base = base.join("/");
|
||||||
if let Some(url) = root {
|
if link.starts_with("#") {
|
||||||
eprintln!("root: {:?} base: {:?} link: {} root&base: {} root&base&link: {}", url, &base, link, url.join(&base).unwrap(), url.join(&base).unwrap().join(link).unwrap());
|
base = base + "/"
|
||||||
if link.starts_with("#") {
|
};
|
||||||
base = base + "/"
|
root.and_then(|url| url.join(&base).ok()).and_then(|url| url.join(link).ok()).map(|url| url.into_string())
|
||||||
};
|
|
||||||
Some(url.join(&base)?.join(link)?.into_string())
|
|
||||||
} else {None}
|
|
||||||
},
|
},
|
||||||
UrlMode::File => {
|
UrlMode::File => {
|
||||||
let base = base.collect::<PathBuf>();
|
let base = base.collect::<PathBuf>();
|
||||||
@ -491,7 +479,7 @@ fn try_resolve_path(db: &RootDatabase, doc_target_dirs: impl Iterator<Item = Pat
|
|||||||
|
|
||||||
/// Try to get the root URL of the documentation of a crate.
|
/// Try to get the root URL of the documentation of a crate.
|
||||||
fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
|
fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
|
||||||
// Look for #![doc(html_root_url = "https://docs.rs/...")]
|
// Look for #![doc(html_root_url = "...")]
|
||||||
let attrs = db.attrs(AttrDef::from(krate.root_module(db)?).into());
|
let attrs = db.attrs(AttrDef::from(krate.root_module(db)?).into());
|
||||||
let doc_attr_q = attrs.by_key("doc");
|
let doc_attr_q = attrs.by_key("doc");
|
||||||
let doc_url = if doc_attr_q.exists() {
|
let doc_url = if doc_attr_q.exists() {
|
||||||
@ -500,20 +488,18 @@ fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
|
|||||||
TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident_text, ..})),
|
TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident_text, ..})),
|
||||||
TokenTree::Leaf(Leaf::Punct(Punct{r#char: '=', ..})),
|
TokenTree::Leaf(Leaf::Punct(Punct{r#char: '=', ..})),
|
||||||
TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))
|
TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))
|
||||||
] if ident_text == "html_root_url" => Some(text),
|
] if ident_text == "html_root_url" => Some(text.to_string()),
|
||||||
_ => {
|
_ => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}).next()
|
}).next()
|
||||||
} else {
|
} else {
|
||||||
None
|
// Fallback to docs.rs
|
||||||
|
// TODO: Specify an exact version here (from Cargo.lock)
|
||||||
|
Some(format!("https://docs.rs/{}/*", krate.display_name(db)?))
|
||||||
};
|
};
|
||||||
eprintln!("url {:?}", doc_url);
|
|
||||||
|
|
||||||
// TODO: It should be possible to fallback to `format!("https://docs.rs/{}/*", crate_name, *)`
|
doc_url.map(|s| s.trim_matches('"').to_owned() + "/").and_then(|s| Url::parse(&s).ok())
|
||||||
let url = doc_url.map(|s| s.trim_matches('"').to_owned() + "/").and_then(|s| Url::parse(&s).ok());
|
|
||||||
eprintln!("url {:?}", url);
|
|
||||||
url
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_nodes<'a, F>(node: &'a comrak::nodes::AstNode<'a>, f: &F)
|
fn iter_nodes<'a, F>(node: &'a comrak::nodes::AstNode<'a>, f: &F)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user