refactor: refactor hover, analysis/global, and docs crates (#755)

* dev: refactor hover.rs

* refactor refactor AnalysisContext

* refactor: refactor docs crate
This commit is contained in:
Myriad-Dreamin 2024-10-31 10:07:31 +08:00 committed by GitHub
parent 1c1bc19caf
commit 8f3566366e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 694 additions and 790 deletions

View file

@ -13,12 +13,12 @@ use typst::syntax::FileId;
use crate::docs::file_id_repr;
use crate::syntax::{Decl, DefKind, Expr, ExprInfo};
use crate::ty::Interned;
use crate::AnalysisContext;
use crate::LocalContext;
use super::{get_manifest_id, DefDocs, PackageInfo};
/// Get documentation of symbols in a package.
pub fn package_module_docs(ctx: &mut AnalysisContext, pkg: &PackageInfo) -> StrResult<SymbolsInfo> {
/// Get documentation of definitions in a package.
pub fn package_module_docs(ctx: &mut LocalContext, pkg: &PackageInfo) -> StrResult<PackageDefInfo> {
let toml_id = get_manifest_id(pkg)?;
let manifest = ctx.get_manifest(toml_id)?;
@ -26,12 +26,12 @@ pub fn package_module_docs(ctx: &mut AnalysisContext, pkg: &PackageInfo) -> StrR
module_docs(ctx, entry_point)
}
/// Get documentation of symbols in a module.
pub fn module_docs(ctx: &mut AnalysisContext, entry_point: FileId) -> StrResult<SymbolsInfo> {
/// Get documentation of definitions in a module.
pub fn module_docs(ctx: &mut LocalContext, entry_point: FileId) -> StrResult<PackageDefInfo> {
let mut aliases = HashMap::new();
let mut extras = vec![];
let mut scan_ctx = ScanSymbolCtx {
let mut scan_ctx = ScanDefCtx {
ctx,
root: entry_point,
for_spec: entry_point.package(),
@ -43,7 +43,7 @@ pub fn module_docs(ctx: &mut AnalysisContext, entry_point: FileId) -> StrResult<
.ctx
.expr_stage_by_id(entry_point)
.ok_or("entry point not found")?;
let mut symbols = scan_ctx.module_sym(eco_vec![], ei);
let mut defs = scan_ctx.defs(eco_vec![], ei);
let module_uses = aliases
.into_iter()
@ -55,72 +55,64 @@ pub fn module_docs(ctx: &mut AnalysisContext, entry_point: FileId) -> StrResult<
log::debug!("module_uses: {module_uses:#?}",);
symbols.children.extend(extras);
defs.children.extend(extras);
Ok(SymbolsInfo {
root: symbols,
Ok(PackageDefInfo {
root: defs,
module_uses,
})
}
/// Information about a symbol.
/// Information about a definition.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SymbolInfoHead {
/// The name of the symbol.
pub struct DefInfo {
/// The name of the definition.
pub name: EcoString,
/// The kind of the symbol.
/// The kind of the definition.
pub kind: DefKind,
/// The location (file, start, end) of the symbol.
/// The location (file, start, end) of the definition.
pub loc: Option<(usize, usize, usize)>,
/// Is the symbol reexport
pub export_again: bool,
/// Is the symbol reexport
/// Whether the definition external to the module.
pub is_external: bool,
/// The link to the definition if it is external.
pub external_link: Option<String>,
/// The one-line documentation of the symbol.
/// The one-line documentation of the definition.
pub oneliner: Option<String>,
/// The raw documentation of the symbol.
/// The raw documentation of the definition.
pub docs: Option<EcoString>,
/// The parsed documentation of the symbol.
/// The parsed documentation of the definition.
pub parsed_docs: Option<DefDocs>,
/// The value of the symbol.
/// The value of the definition.
#[serde(skip)]
pub constant: Option<EcoString>,
/// The name range of the symbol.
/// The value of the symbol.
/// The name range of the definition.
/// The value of the definition.
#[serde(skip)]
pub decl: Option<Interned<Decl>>,
/// The children of the definition.
pub children: EcoVec<DefInfo>,
}
/// Information about a symbol.
/// Information about the definitions in a package.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolInfo {
/// The primary information about the symbol.
#[serde(flatten)]
pub head: SymbolInfoHead,
/// The children of the symbol.
pub children: EcoVec<SymbolInfo>,
}
/// Information about the symbols in a package.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolsInfo {
pub struct PackageDefInfo {
/// The root module information.
#[serde(flatten)]
pub root: SymbolInfo,
pub root: DefInfo,
/// The module accessible paths.
pub module_uses: HashMap<String, EcoVec<String>>,
}
struct ScanSymbolCtx<'a, 'w> {
ctx: &'a mut AnalysisContext<'w>,
struct ScanDefCtx<'a> {
ctx: &'a mut LocalContext,
for_spec: Option<&'a PackageSpec>,
aliases: &'a mut HashMap<FileId, Vec<String>>,
extras: &'a mut Vec<SymbolInfo>,
extras: &'a mut Vec<DefInfo>,
root: FileId,
}
impl ScanSymbolCtx<'_, '_> {
fn module_sym(&mut self, path: EcoVec<&str>, ei: Arc<ExprInfo>) -> SymbolInfo {
impl ScanDefCtx<'_> {
fn defs(&mut self, path: EcoVec<&str>, ei: Arc<ExprInfo>) -> DefInfo {
let name = {
let stem = ei.fid.vpath().as_rooted_path().file_stem();
stem.and_then(|s| Some(Interned::new_str(s.to_str()?)))
@ -129,7 +121,7 @@ impl ScanSymbolCtx<'_, '_> {
let module_decl = Decl::module(name.clone(), ei.fid).into();
let site = Some(self.root);
let p = path.clone();
self.sym(&name, p, site.as_ref(), &module_decl, None)
self.def(&name, p, site.as_ref(), &module_decl, None)
}
fn expr(
@ -138,9 +130,9 @@ impl ScanSymbolCtx<'_, '_> {
path: EcoVec<&str>,
site: Option<&FileId>,
val: &Expr,
) -> SymbolInfo {
) -> DefInfo {
match val {
Expr::Decl(d) => self.sym(key, path, site, d, Some(val)),
Expr::Decl(d) => self.def(key, path, site, d, Some(val)),
Expr::Ref(r) if r.root.is_some() => {
self.expr(key, path, site, r.root.as_ref().unwrap())
}
@ -148,55 +140,38 @@ impl ScanSymbolCtx<'_, '_> {
Expr::Select(..) => {
let mut path = path.clone();
path.push(key);
let head = SymbolInfoHead {
DefInfo {
name: key.to_string().into(),
kind: DefKind::Module,
..Default::default()
};
SymbolInfo {
head,
children: eco_vec![],
}
}
// v => panic!("unexpected export: {key} -> {v}"),
_ => {
let mut path = path.clone();
path.push(key);
let head = SymbolInfoHead {
DefInfo {
name: key.to_string().into(),
kind: DefKind::Constant,
..Default::default()
};
SymbolInfo {
head,
children: eco_vec![],
}
}
}
}
fn sym(
fn def(
&mut self,
key: &str,
path: EcoVec<&str>,
site: Option<&FileId>,
val: &Interned<Decl>,
decl: &Interned<Decl>,
expr: Option<&Expr>,
) -> SymbolInfo {
let mut head = create_head(self.ctx, key, val, expr);
if !matches!(val.as_ref(), Decl::Module(..)) {
if let Some((span, mod_fid)) = head.decl.as_ref().and_then(|d| d.file_id()).zip(site) {
if span != *mod_fid {
head.export_again = true;
head.oneliner = head.docs.as_deref().map(oneliner).map(|e| e.to_owned());
head.docs = None;
}
}
}
let children = match val.as_ref() {
Decl::Module(..) => val.file_id().and_then(|fid| {
) -> DefInfo {
let def = self.ctx.def_of_decl(decl);
let def_docs = def.and_then(|def| self.ctx.def_docs(&def));
let docs = def_docs.as_ref().map(|d| d.docs().clone());
let children = match decl.as_ref() {
Decl::Module(..) => decl.file_id().and_then(|fid| {
// only generate docs for the same package
if fid.package() != self.for_spec {
return None;
@ -230,6 +205,28 @@ impl ScanSymbolCtx<'_, '_> {
_ => None,
};
let mut head = DefInfo {
name: key.to_string().into(),
kind: decl.kind(),
constant: expr.map(|e| e.repr()),
docs,
parsed_docs: def_docs,
decl: Some(decl.clone()),
children: children.unwrap_or_default(),
loc: None,
is_external: false,
external_link: None,
oneliner: None,
};
if let Some((span, mod_fid)) = head.decl.as_ref().and_then(|d| d.file_id()).zip(site) {
if span != *mod_fid {
head.is_external = true;
head.oneliner = head.docs.as_deref().map(oneliner).map(|e| e.to_owned());
head.docs = None;
}
}
// Insert module that is not exported
if let Some(fid) = head.decl.as_ref().and_then(|d| d.file_id()) {
// only generate docs for the same package
@ -243,37 +240,14 @@ impl ScanSymbolCtx<'_, '_> {
log::debug!("found internal module: {path:?}");
if let Some(m) = src {
let msym = self.module_sym(path, m);
let msym = self.defs(path, m);
self.extras.push(msym)
}
}
}
}
let children = children.unwrap_or_default();
SymbolInfo { head, children }
}
}
fn create_head(
ctx: &mut AnalysisContext,
k: &str,
decl: &Interned<Decl>,
expr: Option<&Expr>,
) -> SymbolInfoHead {
let kind = decl.kind();
let parsed_docs = ctx.def_of_decl(decl).and_then(|def| ctx.def_docs(&def));
let docs = parsed_docs.as_ref().map(|d| d.docs().clone());
SymbolInfoHead {
name: k.to_string().into(),
kind,
constant: expr.map(|e| e.repr()),
docs,
parsed_docs,
decl: Some(decl.clone()),
..Default::default()
head
}
}