rustdoc: Add CrateName
newtype (#13056)
This PR adds a `CrateName` newtype used to represent crate names. This makes the code a bit more self-descriptive and prevents confusing other string values for a crate name. It also changes the internal representation from a `String` to an `Arc<str>` for cheaper clones. Release Notes: - N/A
This commit is contained in:
parent
3b84b106e2
commit
44f66aa426
5 changed files with 35 additions and 20 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -8714,6 +8714,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"collections",
|
"collections",
|
||||||
|
"derive_more",
|
||||||
"fs",
|
"fs",
|
||||||
"futures 0.3.28",
|
"futures 0.3.28",
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
|
|
|
@ -10,8 +10,8 @@ use gpui::{AppContext, Model, Task, WeakView};
|
||||||
use http::{AsyncBody, HttpClient, HttpClientWithUrl};
|
use http::{AsyncBody, HttpClient, HttpClientWithUrl};
|
||||||
use language::LspAdapterDelegate;
|
use language::LspAdapterDelegate;
|
||||||
use project::{Project, ProjectPath};
|
use project::{Project, ProjectPath};
|
||||||
use rustdoc::LocalProvider;
|
|
||||||
use rustdoc::{convert_rustdoc_to_markdown, RustdocStore};
|
use rustdoc::{convert_rustdoc_to_markdown, RustdocStore};
|
||||||
|
use rustdoc::{CrateName, LocalProvider};
|
||||||
use ui::{prelude::*, ButtonLike, ElevationIndex};
|
use ui::{prelude::*, ButtonLike, ElevationIndex};
|
||||||
use util::{maybe, ResultExt};
|
use util::{maybe, ResultExt};
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
@ -30,14 +30,14 @@ impl RustdocSlashCommand {
|
||||||
async fn build_message(
|
async fn build_message(
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
http_client: Arc<HttpClientWithUrl>,
|
http_client: Arc<HttpClientWithUrl>,
|
||||||
crate_name: String,
|
crate_name: CrateName,
|
||||||
module_path: Vec<String>,
|
module_path: Vec<String>,
|
||||||
path_to_cargo_toml: Option<&Path>,
|
path_to_cargo_toml: Option<&Path>,
|
||||||
) -> Result<(RustdocSource, String)> {
|
) -> Result<(RustdocSource, String)> {
|
||||||
let cargo_workspace_root = path_to_cargo_toml.and_then(|path| path.parent());
|
let cargo_workspace_root = path_to_cargo_toml.and_then(|path| path.parent());
|
||||||
if let Some(cargo_workspace_root) = cargo_workspace_root {
|
if let Some(cargo_workspace_root) = cargo_workspace_root {
|
||||||
let mut local_cargo_doc_path = cargo_workspace_root.join("target/doc");
|
let mut local_cargo_doc_path = cargo_workspace_root.join("target/doc");
|
||||||
local_cargo_doc_path.push(&crate_name);
|
local_cargo_doc_path.push(crate_name.as_ref());
|
||||||
if !module_path.is_empty() {
|
if !module_path.is_empty() {
|
||||||
local_cargo_doc_path.push(module_path.join("/"));
|
local_cargo_doc_path.push(module_path.join("/"));
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ impl SlashCommand for RustdocSlashCommand {
|
||||||
let provider = Box::new(LocalProvider::new(fs, cargo_workspace_root));
|
let provider = Box::new(LocalProvider::new(fs, cargo_workspace_root));
|
||||||
// We don't need to hold onto this task, as the `RustdocStore` will hold it
|
// We don't need to hold onto this task, as the `RustdocStore` will hold it
|
||||||
// until it completes.
|
// until it completes.
|
||||||
let _ = store.clone().index(crate_name.to_string(), provider);
|
let _ = store.clone().index(crate_name.into(), provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ impl SlashCommand for RustdocSlashCommand {
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| anyhow!("missing crate name"))
|
.ok_or_else(|| anyhow!("missing crate name"))
|
||||||
{
|
{
|
||||||
Ok(crate_name) => crate_name.to_string(),
|
Ok(crate_name) => CrateName::from(crate_name),
|
||||||
Err(err) => return Task::ready(Err(err)),
|
Err(err) => return Task::ready(Err(err)),
|
||||||
};
|
};
|
||||||
let item_path = path_components.map(ToString::to_string).collect::<Vec<_>>();
|
let item_path = path_components.map(ToString::to_string).collect::<Vec<_>>();
|
||||||
|
@ -207,7 +207,6 @@ impl SlashCommand for RustdocSlashCommand {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let crate_name = SharedString::from(crate_name);
|
|
||||||
let module_path = if item_path.is_empty() {
|
let module_path = if item_path.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,7 +241,7 @@ struct RustdocPlaceholder {
|
||||||
pub id: ElementId,
|
pub id: ElementId,
|
||||||
pub unfold: Arc<dyn Fn(&mut WindowContext)>,
|
pub unfold: Arc<dyn Fn(&mut WindowContext)>,
|
||||||
pub source: RustdocSource,
|
pub source: RustdocSource,
|
||||||
pub crate_name: SharedString,
|
pub crate_name: CrateName,
|
||||||
pub module_path: Option<SharedString>,
|
pub module_path: Option<SharedString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ path = "src/rustdoc.rs"
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
collections.workspace = true
|
collections.workspace = true
|
||||||
|
derive_more.workspace = true
|
||||||
fs.workspace = true
|
fs.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
|
|
|
@ -8,7 +8,9 @@ use fs::Fs;
|
||||||
use futures::AsyncReadExt;
|
use futures::AsyncReadExt;
|
||||||
use http::{AsyncBody, HttpClient, HttpClientWithUrl};
|
use http::{AsyncBody, HttpClient, HttpClientWithUrl};
|
||||||
|
|
||||||
use crate::{convert_rustdoc_to_markdown, RustdocDatabase, RustdocItem, RustdocItemKind};
|
use crate::{
|
||||||
|
convert_rustdoc_to_markdown, CrateName, RustdocDatabase, RustdocItem, RustdocItemKind,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum RustdocSource {
|
pub enum RustdocSource {
|
||||||
|
@ -22,7 +24,7 @@ pub enum RustdocSource {
|
||||||
pub trait RustdocProvider {
|
pub trait RustdocProvider {
|
||||||
async fn fetch_page(
|
async fn fetch_page(
|
||||||
&self,
|
&self,
|
||||||
crate_name: &str,
|
crate_name: &CrateName,
|
||||||
item: Option<&RustdocItem>,
|
item: Option<&RustdocItem>,
|
||||||
) -> Result<Option<String>>;
|
) -> Result<Option<String>>;
|
||||||
}
|
}
|
||||||
|
@ -45,11 +47,11 @@ impl LocalProvider {
|
||||||
impl RustdocProvider for LocalProvider {
|
impl RustdocProvider for LocalProvider {
|
||||||
async fn fetch_page(
|
async fn fetch_page(
|
||||||
&self,
|
&self,
|
||||||
crate_name: &str,
|
crate_name: &CrateName,
|
||||||
item: Option<&RustdocItem>,
|
item: Option<&RustdocItem>,
|
||||||
) -> Result<Option<String>> {
|
) -> Result<Option<String>> {
|
||||||
let mut local_cargo_doc_path = self.cargo_workspace_root.join("target/doc");
|
let mut local_cargo_doc_path = self.cargo_workspace_root.join("target/doc");
|
||||||
local_cargo_doc_path.push(&crate_name);
|
local_cargo_doc_path.push(crate_name.as_ref());
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
local_cargo_doc_path.push(item.url_path());
|
local_cargo_doc_path.push(item.url_path());
|
||||||
} else {
|
} else {
|
||||||
|
@ -78,7 +80,7 @@ impl DocsDotRsProvider {
|
||||||
impl RustdocProvider for DocsDotRsProvider {
|
impl RustdocProvider for DocsDotRsProvider {
|
||||||
async fn fetch_page(
|
async fn fetch_page(
|
||||||
&self,
|
&self,
|
||||||
crate_name: &str,
|
crate_name: &CrateName,
|
||||||
item: Option<&RustdocItem>,
|
item: Option<&RustdocItem>,
|
||||||
) -> Result<Option<String>> {
|
) -> Result<Option<String>> {
|
||||||
let version = "latest";
|
let version = "latest";
|
||||||
|
@ -138,7 +140,7 @@ impl RustdocIndexer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indexes the crate with the given name.
|
/// Indexes the crate with the given name.
|
||||||
pub async fn index(&self, crate_name: String) -> Result<()> {
|
pub async fn index(&self, crate_name: CrateName) -> Result<()> {
|
||||||
let Some(crate_root_content) = self.provider.fetch_page(&crate_name, None).await? else {
|
let Some(crate_root_content) = self.provider.fetch_page(&crate_name, None).await? else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
use derive_more::{Deref, Display};
|
||||||
use futures::future::{self, BoxFuture, Shared};
|
use futures::future::{self, BoxFuture, Shared};
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use fuzzy::StringMatchCandidate;
|
use fuzzy::StringMatchCandidate;
|
||||||
|
@ -18,6 +19,16 @@ use util::ResultExt;
|
||||||
use crate::indexer::{RustdocIndexer, RustdocProvider};
|
use crate::indexer::{RustdocIndexer, RustdocProvider};
|
||||||
use crate::{RustdocItem, RustdocItemKind};
|
use crate::{RustdocItem, RustdocItemKind};
|
||||||
|
|
||||||
|
/// The name of a crate.
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Deref, Display)]
|
||||||
|
pub struct CrateName(Arc<str>);
|
||||||
|
|
||||||
|
impl From<&str> for CrateName {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct GlobalRustdocStore(Arc<RustdocStore>);
|
struct GlobalRustdocStore(Arc<RustdocStore>);
|
||||||
|
|
||||||
impl Global for GlobalRustdocStore {}
|
impl Global for GlobalRustdocStore {}
|
||||||
|
@ -25,7 +36,8 @@ impl Global for GlobalRustdocStore {}
|
||||||
pub struct RustdocStore {
|
pub struct RustdocStore {
|
||||||
executor: BackgroundExecutor,
|
executor: BackgroundExecutor,
|
||||||
database_future: Shared<BoxFuture<'static, Result<Arc<RustdocDatabase>, Arc<anyhow::Error>>>>,
|
database_future: Shared<BoxFuture<'static, Result<Arc<RustdocDatabase>, Arc<anyhow::Error>>>>,
|
||||||
indexing_tasks_by_crate: RwLock<HashMap<String, Shared<Task<Result<(), Arc<anyhow::Error>>>>>>,
|
indexing_tasks_by_crate:
|
||||||
|
RwLock<HashMap<CrateName, Shared<Task<Result<(), Arc<anyhow::Error>>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RustdocStore {
|
impl RustdocStore {
|
||||||
|
@ -61,7 +73,7 @@ impl RustdocStore {
|
||||||
|
|
||||||
pub async fn load(
|
pub async fn load(
|
||||||
&self,
|
&self,
|
||||||
crate_name: String,
|
crate_name: CrateName,
|
||||||
item_path: Option<String>,
|
item_path: Option<String>,
|
||||||
) -> Result<RustdocDatabaseEntry> {
|
) -> Result<RustdocDatabaseEntry> {
|
||||||
self.database_future
|
self.database_future
|
||||||
|
@ -74,7 +86,7 @@ impl RustdocStore {
|
||||||
|
|
||||||
pub fn index(
|
pub fn index(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
crate_name: String,
|
crate_name: CrateName,
|
||||||
provider: Box<dyn RustdocProvider + Send + Sync + 'static>,
|
provider: Box<dyn RustdocProvider + Send + Sync + 'static>,
|
||||||
) -> Shared<Task<Result<(), Arc<anyhow::Error>>>> {
|
) -> Shared<Task<Result<(), Arc<anyhow::Error>>>> {
|
||||||
let indexing_task = self
|
let indexing_task = self
|
||||||
|
@ -215,7 +227,7 @@ impl RustdocDatabase {
|
||||||
|
|
||||||
pub fn load(
|
pub fn load(
|
||||||
&self,
|
&self,
|
||||||
crate_name: String,
|
crate_name: CrateName,
|
||||||
item_path: Option<String>,
|
item_path: Option<String>,
|
||||||
) -> Task<Result<RustdocDatabaseEntry>> {
|
) -> Task<Result<RustdocDatabaseEntry>> {
|
||||||
let env = self.env.clone();
|
let env = self.env.clone();
|
||||||
|
@ -223,7 +235,7 @@ impl RustdocDatabase {
|
||||||
let item_path = if let Some(item_path) = item_path {
|
let item_path = if let Some(item_path) = item_path {
|
||||||
format!("{crate_name}::{item_path}")
|
format!("{crate_name}::{item_path}")
|
||||||
} else {
|
} else {
|
||||||
crate_name
|
crate_name.to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
self.executor.spawn(async move {
|
self.executor.spawn(async move {
|
||||||
|
@ -236,7 +248,7 @@ impl RustdocDatabase {
|
||||||
|
|
||||||
pub fn insert(
|
pub fn insert(
|
||||||
&self,
|
&self,
|
||||||
crate_name: String,
|
crate_name: CrateName,
|
||||||
item: Option<&RustdocItem>,
|
item: Option<&RustdocItem>,
|
||||||
docs: String,
|
docs: String,
|
||||||
) -> Task<Result<()>> {
|
) -> Task<Result<()>> {
|
||||||
|
@ -251,7 +263,7 @@ impl RustdocDatabase {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(crate_name, RustdocDatabaseEntry::Crate { docs })
|
(crate_name.to_string(), RustdocDatabaseEntry::Crate { docs })
|
||||||
};
|
};
|
||||||
|
|
||||||
self.executor.spawn(async move {
|
self.executor.spawn(async move {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue