summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2020-08-10 17:41:19 +0200
committerGitHub <noreply@github.com>2020-08-10 17:41:19 +0200
commit6fcf06306ed2ea52031a97b918f1e929d7209250 (patch)
tree01eaea1836d5ee864aafb57677c9fb4d76e33eba
parentfdb2dab7cd59a70b79704e0a0efca44be2bfc186 (diff)
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.
-rw-r--r--cli/doc/mod.rs1
-rw-r--r--cli/doc/module.rs7
-rw-r--r--cli/doc/namespace.rs1
-rw-r--r--cli/doc/node.rs11
-rw-r--r--cli/doc/parser.rs87
-rw-r--r--cli/doc/printer.rs2
-rw-r--r--cli/doc/tests.rs21
-rw-r--r--cli/main.rs3
8 files changed, 127 insertions, 6 deletions
diff --git a/cli/doc/mod.rs b/cli/doc/mod.rs
index 49f8d7453..d015d9e4c 100644
--- a/cli/doc/mod.rs
+++ b/cli/doc/mod.rs
@@ -17,6 +17,7 @@ pub mod variable;
pub use node::DocNode;
pub use node::DocNodeKind;
+pub use node::ImportDef;
pub use node::Location;
pub use params::ParamDef;
pub use parser::DocParser;
diff --git a/cli/doc/module.rs b/cli/doc/module.rs
index 74d5361eb..cd0fdbd45 100644
--- a/cli/doc/module.rs
+++ b/cli/doc/module.rs
@@ -31,6 +31,7 @@ pub fn get_doc_node_for_export_decl(
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
}
}
Decl::Fn(fn_decl) => {
@@ -48,6 +49,7 @@ pub fn get_doc_node_for_export_decl(
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
}
}
Decl::Var(var_decl) => {
@@ -64,6 +66,7 @@ pub fn get_doc_node_for_export_decl(
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
}
}
Decl::TsInterface(ts_interface_decl) => {
@@ -84,6 +87,7 @@ pub fn get_doc_node_for_export_decl(
enum_def: None,
type_alias_def: None,
namespace_def: None,
+ import_def: None,
}
}
Decl::TsTypeAlias(ts_type_alias) => {
@@ -104,6 +108,7 @@ pub fn get_doc_node_for_export_decl(
class_def: None,
enum_def: None,
namespace_def: None,
+ import_def: None,
}
}
Decl::TsEnum(ts_enum) => {
@@ -121,6 +126,7 @@ pub fn get_doc_node_for_export_decl(
function_def: None,
class_def: None,
namespace_def: None,
+ import_def: None,
}
}
Decl::TsModule(ts_module) => {
@@ -138,6 +144,7 @@ pub fn get_doc_node_for_export_decl(
variable_def: None,
function_def: None,
class_def: None,
+ import_def: None,
}
}
}
diff --git a/cli/doc/namespace.rs b/cli/doc/namespace.rs
index 35f9233fd..17e1d2eb7 100644
--- a/cli/doc/namespace.rs
+++ b/cli/doc/namespace.rs
@@ -46,6 +46,7 @@ pub fn get_doc_for_ts_namespace_decl(
class_def: None,
type_alias_def: None,
interface_def: None,
+ import_def: None,
}
}
diff --git a/cli/doc/node.rs b/cli/doc/node.rs
index 4946924c6..980a5d8b9 100644
--- a/cli/doc/node.rs
+++ b/cli/doc/node.rs
@@ -11,6 +11,7 @@ pub enum DocNodeKind {
Interface,
TypeAlias,
Namespace,
+ Import,
}
#[derive(Debug, Serialize, Clone, PartialEq)]
@@ -69,6 +70,13 @@ pub struct ModuleDoc {
#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
+pub struct ImportDef {
+ pub src: String,
+ pub imported: Option<String>,
+}
+
+#[derive(Debug, Serialize, Clone)]
+#[serde(rename_all = "camelCase")]
pub struct DocNode {
pub kind: DocNodeKind,
pub name: String,
@@ -95,4 +103,7 @@ pub struct DocNode {
#[serde(skip_serializing_if = "Option::is_none")]
pub interface_def: Option<super::interface::InterfaceDef>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub import_def: Option<ImportDef>,
}
diff --git a/cli/doc/parser.rs b/cli/doc/parser.rs
index e185e5bff..2247c6877 100644
--- a/cli/doc/parser.rs
+++ b/cli/doc/parser.rs
@@ -2,7 +2,6 @@
use crate::file_fetcher::map_file_extension;
use crate::op_error::OpError;
use crate::swc_util::AstParser;
-use crate::swc_util::SwcDiagnosticBuffer;
use swc_common::comments::CommentKind;
use swc_common::Span;
use swc_ecmascript::ast::Decl;
@@ -23,6 +22,7 @@ use super::node;
use super::node::ModuleDoc;
use super::DocNode;
use super::DocNodeKind;
+use super::ImportDef;
use super::Location;
pub trait DocFileLoader {
@@ -59,14 +59,18 @@ impl DocParser {
&self,
file_name: &str,
source_code: &str,
- ) -> Result<ModuleDoc, SwcDiagnosticBuffer> {
+ ) -> Result<ModuleDoc, ErrBox> {
let media_type = map_file_extension(&PathBuf::from(file_name));
let parse_result =
self
.ast_parser
.parse_module(file_name, media_type, source_code);
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 module_doc = ModuleDoc {
definitions: doc_entries,
@@ -138,6 +142,7 @@ impl DocParser {
variable_def: None,
function_def: None,
class_def: None,
+ import_def: None,
};
processed_reexports.push(ns_doc_node);
}
@@ -193,6 +198,72 @@ impl DocParser {
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(
&self,
module_decl: &ModuleDecl,
@@ -225,6 +296,7 @@ impl DocParser {
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
}
}
DefaultDecl::Fn(fn_expr) => {
@@ -244,6 +316,7 @@ impl DocParser {
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
}
}
DefaultDecl::TsInterfaceDecl(interface_decl) => {
@@ -264,6 +337,7 @@ impl DocParser {
type_alias_def: None,
namespace_def: None,
interface_def: Some(interface_def),
+ import_def: None,
}
}
};
@@ -309,6 +383,7 @@ impl DocParser {
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
})
}
Decl::Fn(fn_decl) => {
@@ -330,6 +405,7 @@ impl DocParser {
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
})
}
Decl::Var(var_decl) => {
@@ -350,6 +426,7 @@ impl DocParser {
type_alias_def: None,
namespace_def: None,
interface_def: None,
+ import_def: None,
})
}
Decl::TsInterface(ts_interface_decl) => {
@@ -374,6 +451,7 @@ impl DocParser {
enum_def: None,
type_alias_def: None,
namespace_def: None,
+ import_def: None,
})
}
Decl::TsTypeAlias(ts_type_alias) => {
@@ -398,6 +476,7 @@ impl DocParser {
class_def: None,
enum_def: None,
namespace_def: None,
+ import_def: None,
})
}
Decl::TsEnum(ts_enum) => {
@@ -419,6 +498,7 @@ impl DocParser {
function_def: None,
class_def: None,
namespace_def: None,
+ import_def: None,
})
}
Decl::TsModule(ts_module) => {
@@ -440,6 +520,7 @@ impl DocParser {
variable_def: None,
function_def: None,
class_def: None,
+ import_def: None,
})
}
}
diff --git a/cli/doc/printer.rs b/cli/doc/printer.rs
index a3ecd2718..5ba5154c5 100644
--- a/cli/doc/printer.rs
+++ b/cli/doc/printer.rs
@@ -129,6 +129,7 @@ impl<'a> DocPrinter<'a> {
DocNodeKind::Interface => 4,
DocNodeKind::TypeAlias => 5,
DocNodeKind::Namespace => 6,
+ DocNodeKind::Import => 7,
}
}
@@ -152,6 +153,7 @@ impl<'a> DocPrinter<'a> {
DocNodeKind::Namespace => {
self.format_namespace_signature(w, node, indent)
}
+ DocNodeKind::Import => Ok(()),
}
}
diff --git a/cli/doc/tests.rs b/cli/doc/tests.rs
index e46fff621..94d087ea3 100644
--- a/cli/doc/tests.rs
+++ b/cli/doc/tests.rs
@@ -153,9 +153,12 @@ import { bar } from "./nested_reexport.ts";
* JSDoc for const
*/
export const foo = "foo";
+
+export const fizz = "fizz";
"#;
let test_source_code = r#"
export { default, foo as fooConst } from "./reexport.ts";
+import { fizz as buzz } from "./reexport.ts";
/** JSDoc for function */
export function fooFn(a: number) {
@@ -177,7 +180,7 @@ export function fooFn(a: number) {
.parse_with_reexports("file:///test.ts")
.await
.unwrap();
- assert_eq!(entries.len(), 2);
+ assert_eq!(entries.len(), 3);
let expected_json = json!([
{
@@ -199,7 +202,7 @@ export function fooFn(a: number) {
"name": "fooFn",
"location": {
"filename": "file:///test.ts",
- "line": 5,
+ "line": 6,
"col": 0
},
"jsDoc": "JSDoc for function",
@@ -220,6 +223,20 @@ export function fooFn(a: number) {
"returnType": null,
"isAsync": 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",
}
}
]);
diff --git a/cli/main.rs b/cli/main.rs
index 0c84e7b3e..799d47e32 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -532,7 +532,7 @@ async fn doc_command(
.await
};
- let doc_nodes = match parse_result {
+ let mut doc_nodes = match parse_result {
Ok(nodes) => nodes,
Err(e) => {
eprintln!("{}", e);
@@ -543,6 +543,7 @@ async fn doc_command(
if json {
write_json_to_stdout(&doc_nodes)
} else {
+ doc_nodes.retain(|doc_node| doc_node.kind != doc::DocNodeKind::Import);
let details = if let Some(filter) = maybe_filter {
let nodes =
doc::find_nodes_by_name_recursively(doc_nodes, filter.clone());