mirror of
https://github.com/denoland/deno.git
synced 2025-01-09 07:39:15 -05:00
feat(doc): handle imports (#6987)
This commit adds additional objects to JSON output of "deno doc" command to facilitate linking between types in different modules.
This commit is contained in:
parent
fdb2dab7cd
commit
6fcf06306e
8 changed files with 127 additions and 6 deletions
|
@ -17,6 +17,7 @@ pub mod variable;
|
||||||
|
|
||||||
pub use node::DocNode;
|
pub use node::DocNode;
|
||||||
pub use node::DocNodeKind;
|
pub use node::DocNodeKind;
|
||||||
|
pub use node::ImportDef;
|
||||||
pub use node::Location;
|
pub use node::Location;
|
||||||
pub use params::ParamDef;
|
pub use params::ParamDef;
|
||||||
pub use parser::DocParser;
|
pub use parser::DocParser;
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Decl::Fn(fn_decl) => {
|
Decl::Fn(fn_decl) => {
|
||||||
|
@ -48,6 +49,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Decl::Var(var_decl) => {
|
Decl::Var(var_decl) => {
|
||||||
|
@ -64,6 +66,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Decl::TsInterface(ts_interface_decl) => {
|
Decl::TsInterface(ts_interface_decl) => {
|
||||||
|
@ -84,6 +87,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
enum_def: None,
|
enum_def: None,
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Decl::TsTypeAlias(ts_type_alias) => {
|
Decl::TsTypeAlias(ts_type_alias) => {
|
||||||
|
@ -104,6 +108,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
class_def: None,
|
class_def: None,
|
||||||
enum_def: None,
|
enum_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Decl::TsEnum(ts_enum) => {
|
Decl::TsEnum(ts_enum) => {
|
||||||
|
@ -121,6 +126,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
function_def: None,
|
function_def: None,
|
||||||
class_def: None,
|
class_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Decl::TsModule(ts_module) => {
|
Decl::TsModule(ts_module) => {
|
||||||
|
@ -138,6 +144,7 @@ pub fn get_doc_node_for_export_decl(
|
||||||
variable_def: None,
|
variable_def: None,
|
||||||
function_def: None,
|
function_def: None,
|
||||||
class_def: None,
|
class_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ pub fn get_doc_for_ts_namespace_decl(
|
||||||
class_def: None,
|
class_def: None,
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub enum DocNodeKind {
|
||||||
Interface,
|
Interface,
|
||||||
TypeAlias,
|
TypeAlias,
|
||||||
Namespace,
|
Namespace,
|
||||||
|
Import,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Clone, PartialEq)]
|
||||||
|
@ -67,6 +68,13 @@ pub struct ModuleDoc {
|
||||||
pub reexports: Vec<Reexport>,
|
pub reexports: Vec<Reexport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ImportDef {
|
||||||
|
pub src: String,
|
||||||
|
pub imported: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Clone)]
|
#[derive(Debug, Serialize, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct DocNode {
|
pub struct DocNode {
|
||||||
|
@ -95,4 +103,7 @@ pub struct DocNode {
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub interface_def: Option<super::interface::InterfaceDef>,
|
pub interface_def: Option<super::interface::InterfaceDef>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub import_def: Option<ImportDef>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
use crate::file_fetcher::map_file_extension;
|
use crate::file_fetcher::map_file_extension;
|
||||||
use crate::op_error::OpError;
|
use crate::op_error::OpError;
|
||||||
use crate::swc_util::AstParser;
|
use crate::swc_util::AstParser;
|
||||||
use crate::swc_util::SwcDiagnosticBuffer;
|
|
||||||
use swc_common::comments::CommentKind;
|
use swc_common::comments::CommentKind;
|
||||||
use swc_common::Span;
|
use swc_common::Span;
|
||||||
use swc_ecmascript::ast::Decl;
|
use swc_ecmascript::ast::Decl;
|
||||||
|
@ -23,6 +22,7 @@ use super::node;
|
||||||
use super::node::ModuleDoc;
|
use super::node::ModuleDoc;
|
||||||
use super::DocNode;
|
use super::DocNode;
|
||||||
use super::DocNodeKind;
|
use super::DocNodeKind;
|
||||||
|
use super::ImportDef;
|
||||||
use super::Location;
|
use super::Location;
|
||||||
|
|
||||||
pub trait DocFileLoader {
|
pub trait DocFileLoader {
|
||||||
|
@ -59,14 +59,18 @@ impl DocParser {
|
||||||
&self,
|
&self,
|
||||||
file_name: &str,
|
file_name: &str,
|
||||||
source_code: &str,
|
source_code: &str,
|
||||||
) -> Result<ModuleDoc, SwcDiagnosticBuffer> {
|
) -> Result<ModuleDoc, ErrBox> {
|
||||||
let media_type = map_file_extension(&PathBuf::from(file_name));
|
let media_type = map_file_extension(&PathBuf::from(file_name));
|
||||||
let parse_result =
|
let parse_result =
|
||||||
self
|
self
|
||||||
.ast_parser
|
.ast_parser
|
||||||
.parse_module(file_name, media_type, source_code);
|
.parse_module(file_name, media_type, source_code);
|
||||||
let module = parse_result?;
|
let module = parse_result?;
|
||||||
let doc_entries = self.get_doc_nodes_for_module_body(module.body.clone());
|
let mut doc_entries =
|
||||||
|
self.get_doc_nodes_for_module_body(module.body.clone());
|
||||||
|
let import_doc_entries =
|
||||||
|
self.get_doc_nodes_for_module_imports(module.body.clone(), file_name)?;
|
||||||
|
doc_entries.extend(import_doc_entries);
|
||||||
let reexports = self.get_reexports_for_module_body(module.body);
|
let reexports = self.get_reexports_for_module_body(module.body);
|
||||||
let module_doc = ModuleDoc {
|
let module_doc = ModuleDoc {
|
||||||
definitions: doc_entries,
|
definitions: doc_entries,
|
||||||
|
@ -138,6 +142,7 @@ impl DocParser {
|
||||||
variable_def: None,
|
variable_def: None,
|
||||||
function_def: None,
|
function_def: None,
|
||||||
class_def: None,
|
class_def: None,
|
||||||
|
import_def: None,
|
||||||
};
|
};
|
||||||
processed_reexports.push(ns_doc_node);
|
processed_reexports.push(ns_doc_node);
|
||||||
}
|
}
|
||||||
|
@ -193,6 +198,72 @@ impl DocParser {
|
||||||
Ok(flattened_docs)
|
Ok(flattened_docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_doc_nodes_for_module_imports(
|
||||||
|
&self,
|
||||||
|
module_body: Vec<swc_ecmascript::ast::ModuleItem>,
|
||||||
|
referrer: &str,
|
||||||
|
) -> Result<Vec<DocNode>, ErrBox> {
|
||||||
|
let mut imports = vec![];
|
||||||
|
|
||||||
|
for node in module_body.iter() {
|
||||||
|
if let swc_ecmascript::ast::ModuleItem::ModuleDecl(module_decl) = node {
|
||||||
|
if let ModuleDecl::Import(import_decl) = module_decl {
|
||||||
|
let (js_doc, location) = self.details_for_span(import_decl.span);
|
||||||
|
for specifier in &import_decl.specifiers {
|
||||||
|
use swc_ecmascript::ast::ImportSpecifier::*;
|
||||||
|
|
||||||
|
let (name, maybe_imported_name, src) = match specifier {
|
||||||
|
Named(named_specifier) => (
|
||||||
|
named_specifier.local.sym.to_string(),
|
||||||
|
named_specifier
|
||||||
|
.imported
|
||||||
|
.as_ref()
|
||||||
|
.map(|ident| ident.sym.to_string())
|
||||||
|
.or_else(|| Some(named_specifier.local.sym.to_string())),
|
||||||
|
import_decl.src.value.to_string(),
|
||||||
|
),
|
||||||
|
Default(default_specifier) => (
|
||||||
|
default_specifier.local.sym.to_string(),
|
||||||
|
Some("default".to_string()),
|
||||||
|
import_decl.src.value.to_string(),
|
||||||
|
),
|
||||||
|
Namespace(namespace_specifier) => (
|
||||||
|
namespace_specifier.local.sym.to_string(),
|
||||||
|
None,
|
||||||
|
import_decl.src.value.to_string(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let resolved_specifier = self.loader.resolve(&src, referrer)?;
|
||||||
|
let import_def = ImportDef {
|
||||||
|
src: resolved_specifier.to_string(),
|
||||||
|
imported: maybe_imported_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
let doc_node = DocNode {
|
||||||
|
kind: DocNodeKind::Import,
|
||||||
|
name,
|
||||||
|
location: location.clone(),
|
||||||
|
js_doc: js_doc.clone(),
|
||||||
|
import_def: Some(import_def),
|
||||||
|
class_def: None,
|
||||||
|
function_def: None,
|
||||||
|
variable_def: None,
|
||||||
|
enum_def: None,
|
||||||
|
type_alias_def: None,
|
||||||
|
namespace_def: None,
|
||||||
|
interface_def: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
imports.push(doc_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(imports)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_doc_nodes_for_module_exports(
|
pub fn get_doc_nodes_for_module_exports(
|
||||||
&self,
|
&self,
|
||||||
module_decl: &ModuleDecl,
|
module_decl: &ModuleDecl,
|
||||||
|
@ -225,6 +296,7 @@ impl DocParser {
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultDecl::Fn(fn_expr) => {
|
DefaultDecl::Fn(fn_expr) => {
|
||||||
|
@ -244,6 +316,7 @@ impl DocParser {
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultDecl::TsInterfaceDecl(interface_decl) => {
|
DefaultDecl::TsInterfaceDecl(interface_decl) => {
|
||||||
|
@ -264,6 +337,7 @@ impl DocParser {
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: Some(interface_def),
|
interface_def: Some(interface_def),
|
||||||
|
import_def: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -309,6 +383,7 @@ impl DocParser {
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Decl::Fn(fn_decl) => {
|
Decl::Fn(fn_decl) => {
|
||||||
|
@ -330,6 +405,7 @@ impl DocParser {
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Decl::Var(var_decl) => {
|
Decl::Var(var_decl) => {
|
||||||
|
@ -350,6 +426,7 @@ impl DocParser {
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
interface_def: None,
|
interface_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Decl::TsInterface(ts_interface_decl) => {
|
Decl::TsInterface(ts_interface_decl) => {
|
||||||
|
@ -374,6 +451,7 @@ impl DocParser {
|
||||||
enum_def: None,
|
enum_def: None,
|
||||||
type_alias_def: None,
|
type_alias_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Decl::TsTypeAlias(ts_type_alias) => {
|
Decl::TsTypeAlias(ts_type_alias) => {
|
||||||
|
@ -398,6 +476,7 @@ impl DocParser {
|
||||||
class_def: None,
|
class_def: None,
|
||||||
enum_def: None,
|
enum_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Decl::TsEnum(ts_enum) => {
|
Decl::TsEnum(ts_enum) => {
|
||||||
|
@ -419,6 +498,7 @@ impl DocParser {
|
||||||
function_def: None,
|
function_def: None,
|
||||||
class_def: None,
|
class_def: None,
|
||||||
namespace_def: None,
|
namespace_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Decl::TsModule(ts_module) => {
|
Decl::TsModule(ts_module) => {
|
||||||
|
@ -440,6 +520,7 @@ impl DocParser {
|
||||||
variable_def: None,
|
variable_def: None,
|
||||||
function_def: None,
|
function_def: None,
|
||||||
class_def: None,
|
class_def: None,
|
||||||
|
import_def: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ impl<'a> DocPrinter<'a> {
|
||||||
DocNodeKind::Interface => 4,
|
DocNodeKind::Interface => 4,
|
||||||
DocNodeKind::TypeAlias => 5,
|
DocNodeKind::TypeAlias => 5,
|
||||||
DocNodeKind::Namespace => 6,
|
DocNodeKind::Namespace => 6,
|
||||||
|
DocNodeKind::Import => 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +153,7 @@ impl<'a> DocPrinter<'a> {
|
||||||
DocNodeKind::Namespace => {
|
DocNodeKind::Namespace => {
|
||||||
self.format_namespace_signature(w, node, indent)
|
self.format_namespace_signature(w, node, indent)
|
||||||
}
|
}
|
||||||
|
DocNodeKind::Import => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,9 +153,12 @@ import { bar } from "./nested_reexport.ts";
|
||||||
* JSDoc for const
|
* JSDoc for const
|
||||||
*/
|
*/
|
||||||
export const foo = "foo";
|
export const foo = "foo";
|
||||||
|
|
||||||
|
export const fizz = "fizz";
|
||||||
"#;
|
"#;
|
||||||
let test_source_code = r#"
|
let test_source_code = r#"
|
||||||
export { default, foo as fooConst } from "./reexport.ts";
|
export { default, foo as fooConst } from "./reexport.ts";
|
||||||
|
import { fizz as buzz } from "./reexport.ts";
|
||||||
|
|
||||||
/** JSDoc for function */
|
/** JSDoc for function */
|
||||||
export function fooFn(a: number) {
|
export function fooFn(a: number) {
|
||||||
|
@ -177,7 +180,7 @@ export function fooFn(a: number) {
|
||||||
.parse_with_reexports("file:///test.ts")
|
.parse_with_reexports("file:///test.ts")
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(entries.len(), 2);
|
assert_eq!(entries.len(), 3);
|
||||||
|
|
||||||
let expected_json = json!([
|
let expected_json = json!([
|
||||||
{
|
{
|
||||||
|
@ -199,7 +202,7 @@ export function fooFn(a: number) {
|
||||||
"name": "fooFn",
|
"name": "fooFn",
|
||||||
"location": {
|
"location": {
|
||||||
"filename": "file:///test.ts",
|
"filename": "file:///test.ts",
|
||||||
"line": 5,
|
"line": 6,
|
||||||
"col": 0
|
"col": 0
|
||||||
},
|
},
|
||||||
"jsDoc": "JSDoc for function",
|
"jsDoc": "JSDoc for function",
|
||||||
|
@ -220,6 +223,20 @@ export function fooFn(a: number) {
|
||||||
"returnType": null,
|
"returnType": null,
|
||||||
"isAsync": false,
|
"isAsync": false,
|
||||||
"isGenerator": false
|
"isGenerator": false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "import",
|
||||||
|
"name": "buzz",
|
||||||
|
"location": {
|
||||||
|
"filename": "file:///test.ts",
|
||||||
|
"line": 3,
|
||||||
|
"col": 0
|
||||||
|
},
|
||||||
|
"jsDoc": null,
|
||||||
|
"importDef": {
|
||||||
|
"src": "file:///reexport.ts",
|
||||||
|
"imported": "fizz",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -532,7 +532,7 @@ async fn doc_command(
|
||||||
.await
|
.await
|
||||||
};
|
};
|
||||||
|
|
||||||
let doc_nodes = match parse_result {
|
let mut doc_nodes = match parse_result {
|
||||||
Ok(nodes) => nodes,
|
Ok(nodes) => nodes,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
|
@ -543,6 +543,7 @@ async fn doc_command(
|
||||||
if json {
|
if json {
|
||||||
write_json_to_stdout(&doc_nodes)
|
write_json_to_stdout(&doc_nodes)
|
||||||
} else {
|
} else {
|
||||||
|
doc_nodes.retain(|doc_node| doc_node.kind != doc::DocNodeKind::Import);
|
||||||
let details = if let Some(filter) = maybe_filter {
|
let details = if let Some(filter) = maybe_filter {
|
||||||
let nodes =
|
let nodes =
|
||||||
doc::find_nodes_by_name_recursively(doc_nodes, filter.clone());
|
doc::find_nodes_by_name_recursively(doc_nodes, filter.clone());
|
||||||
|
|
Loading…
Reference in a new issue