summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/args/flags.rs48
-rw-r--r--cli/tests/integration/doc_tests.rs11
-rw-r--r--cli/tests/testdata/doc/referenced_private_types_fixed.out16
-rw-r--r--cli/tests/testdata/doc/referenced_private_types_fixed.ts11
-rw-r--r--cli/tests/testdata/doc/referenced_private_types_lint.out10
-rw-r--r--cli/tools/doc.rs51
6 files changed, 145 insertions, 2 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 271a56ac3..0e4621d67 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -109,6 +109,7 @@ impl Default for DocSourceFileFlag {
pub struct DocFlags {
pub private: bool,
pub json: bool,
+ pub lint: bool,
pub source_files: DocSourceFileFlag,
pub filter: Option<String>,
}
@@ -1329,6 +1330,10 @@ Output documentation in JSON format:
deno doc --json ./path/to/module.ts
+Lint a module for documentation diagnostics:
+
+ deno doc --lint ./path/to/module.ts
+
Target a specific symbol:
deno doc ./path/to/module.ts MyClass.someField
@@ -1363,7 +1368,14 @@ Show documentation for runtime built-ins:
.long("filter")
.help("Dot separated path to symbol")
.required(false)
- .conflicts_with("json"),
+ .conflicts_with("json")
+ .conflicts_with("lint"),
+ )
+ .arg(
+ Arg::new("lint")
+ .long("lint")
+ .help("Output documentation diagnostics.")
+ .action(ArgAction::SetTrue),
)
// TODO(nayeemrmn): Make `--builtin` a proper option. Blocked by
// https://github.com/clap-rs/clap/issues/1794. Currently `--builtin` is
@@ -3145,11 +3157,13 @@ fn doc_parse(flags: &mut Flags, matches: &mut ArgMatches) {
DocSourceFileFlag::Builtin
};
let private = matches.get_flag("private");
+ let lint = matches.get_flag("lint");
let json = matches.get_flag("json");
let filter = matches.remove_one::<String>("filter");
flags.subcommand = DenoSubcommand::Doc(DocFlags {
source_files,
json,
+ lint,
filter,
private,
});
@@ -6044,6 +6058,7 @@ mod tests {
source_files: DocSourceFileFlag::Paths(vec!["script.ts".to_owned()]),
private: false,
json: false,
+ lint: false,
filter: None,
}),
import_map_path: Some("import_map.json".to_owned()),
@@ -7298,6 +7313,7 @@ mod tests {
subcommand: DenoSubcommand::Doc(DocFlags {
private: false,
json: true,
+ lint: false,
source_files: DocSourceFileFlag::Paths(vec![
"path/to/module.ts".to_string()
]),
@@ -7320,6 +7336,7 @@ mod tests {
subcommand: DenoSubcommand::Doc(DocFlags {
private: false,
json: false,
+ lint: false,
source_files: DocSourceFileFlag::Paths(vec![
"path/to/module.ts".to_string()
]),
@@ -7336,6 +7353,7 @@ mod tests {
subcommand: DenoSubcommand::Doc(DocFlags {
private: false,
json: false,
+ lint: false,
source_files: Default::default(),
filter: None,
}),
@@ -7355,6 +7373,7 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Doc(DocFlags {
private: false,
+ lint: false,
json: false,
source_files: DocSourceFileFlag::Builtin,
filter: Some("Deno.Listener".to_string()),
@@ -7376,6 +7395,7 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Doc(DocFlags {
private: true,
+ lint: false,
json: false,
source_files: DocSourceFileFlag::Paths(vec![
"path/to/module.js".to_string()
@@ -7399,6 +7419,7 @@ mod tests {
Flags {
subcommand: DenoSubcommand::Doc(DocFlags {
private: false,
+ lint: false,
json: false,
source_files: DocSourceFileFlag::Paths(vec![
"path/to/module.js".to_string(),
@@ -7423,6 +7444,31 @@ mod tests {
subcommand: DenoSubcommand::Doc(DocFlags {
private: false,
json: false,
+ lint: false,
+ source_files: DocSourceFileFlag::Paths(vec![
+ "path/to/module.js".to_string(),
+ "path/to/module2.js".to_string()
+ ]),
+ filter: None,
+ }),
+ ..Flags::default()
+ }
+ );
+
+ let r = flags_from_vec(svec![
+ "deno",
+ "doc",
+ "--lint",
+ "path/to/module.js",
+ "path/to/module2.js"
+ ]);
+ assert_eq!(
+ r.unwrap(),
+ Flags {
+ subcommand: DenoSubcommand::Doc(DocFlags {
+ private: false,
+ lint: true,
+ json: false,
source_files: DocSourceFileFlag::Paths(vec![
"path/to/module.js".to_string(),
"path/to/module2.js".to_string()
diff --git a/cli/tests/integration/doc_tests.rs b/cli/tests/integration/doc_tests.rs
index 2afa8ca92..a16f99dd9 100644
--- a/cli/tests/integration/doc_tests.rs
+++ b/cli/tests/integration/doc_tests.rs
@@ -53,6 +53,17 @@ itest!(deno_doc_referenced_private_types {
output: "doc/referenced_private_types.out",
});
+itest!(deno_doc_lint_referenced_private_types_error {
+ args: "doc --lint doc/referenced_private_types.ts",
+ exit_code: 1,
+ output: "doc/referenced_private_types_lint.out",
+});
+
+itest!(deno_doc_lint_referenced_private_types_fixed {
+ args: "doc --lint doc/referenced_private_types_fixed.ts",
+ output: "doc/referenced_private_types_fixed.out",
+});
+
itest!(_060_deno_doc_displays_all_overloads_in_details_view {
args:
"doc --filter NS.test doc/060_deno_doc_displays_all_overloads_in_details_view.ts",
diff --git a/cli/tests/testdata/doc/referenced_private_types_fixed.out b/cli/tests/testdata/doc/referenced_private_types_fixed.out
new file mode 100644
index 000000000..4621c6371
--- /dev/null
+++ b/cli/tests/testdata/doc/referenced_private_types_fixed.out
@@ -0,0 +1,16 @@
+Defined in file:///[WILDCARD]/referenced_private_types_fixed.ts:8:1
+
+class MyClass
+ Doc comment
+
+ prop: MyInterface
+ Doc comment
+
+Defined in file:///[WILDCARD]/referenced_private_types_fixed.ts:2:1
+
+interface MyInterface
+ Doc comment
+
+ prop?: string
+ Doc comment
+
diff --git a/cli/tests/testdata/doc/referenced_private_types_fixed.ts b/cli/tests/testdata/doc/referenced_private_types_fixed.ts
new file mode 100644
index 000000000..cd99bc76e
--- /dev/null
+++ b/cli/tests/testdata/doc/referenced_private_types_fixed.ts
@@ -0,0 +1,11 @@
+/** Doc comment */
+export interface MyInterface {
+ /** Doc comment */
+ prop?: string;
+}
+
+/** Doc comment */
+export class MyClass {
+ /** Doc comment */
+ prop: MyInterface = {};
+}
diff --git a/cli/tests/testdata/doc/referenced_private_types_lint.out b/cli/tests/testdata/doc/referenced_private_types_lint.out
new file mode 100644
index 000000000..bb8c599f4
--- /dev/null
+++ b/cli/tests/testdata/doc/referenced_private_types_lint.out
@@ -0,0 +1,10 @@
+Type is not exported, but referenced by an exported type.
+ at file:///[WILDCARD]/referenced_private_types.ts:1:1
+
+Missing JS documentation comment.
+ at file:///[WILDCARD]/referenced_private_types.ts:5:1
+
+Missing JS documentation comment.
+ at file:///[WILDCARD]/referenced_private_types.ts:6:3
+
+error: Found 3 documentation diagnostics.
diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs
index 193362267..4028c412f 100644
--- a/cli/tools/doc.rs
+++ b/cli/tools/doc.rs
@@ -1,5 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+use std::collections::BTreeMap;
+
use crate::args::DocFlags;
use crate::args::DocSourceFileFlag;
use crate::args::Flags;
@@ -18,6 +20,8 @@ use deno_graph::CapturingModuleParser;
use deno_graph::DefaultParsedSourceStore;
use deno_graph::GraphKind;
use deno_graph::ModuleSpecifier;
+use doc::DocDiagnostic;
+use indexmap::IndexMap;
pub async fn print_docs(
flags: Flags,
@@ -101,7 +105,7 @@ pub async fn print_docs(
capturing_parser,
doc::DocParserOptions {
private: doc_flags.private,
- diagnostics: false,
+ diagnostics: doc_flags.lint,
},
)?;
@@ -112,6 +116,11 @@ pub async fn print_docs(
doc_nodes.extend_from_slice(&nodes);
}
+ if doc_flags.lint {
+ let diagnostics = doc_parser.take_diagnostics();
+ check_diagnostics(&diagnostics)?;
+ }
+
doc_nodes
}
};
@@ -144,3 +153,43 @@ pub async fn print_docs(
write_to_stdout_ignore_sigpipe(details.as_bytes()).map_err(AnyError::from)
}
}
+
+fn check_diagnostics(diagnostics: &[DocDiagnostic]) -> Result<(), AnyError> {
+ if diagnostics.is_empty() {
+ return Ok(());
+ }
+
+ // group by location then by line (sorted) then column (sorted)
+ let mut diagnostic_groups = IndexMap::new();
+ for diagnostic in diagnostics {
+ diagnostic_groups
+ .entry(diagnostic.location.filename.clone())
+ .or_insert_with(BTreeMap::new)
+ .entry(diagnostic.location.line)
+ .or_insert_with(BTreeMap::new)
+ .entry(diagnostic.location.col)
+ .or_insert_with(Vec::new)
+ .push(diagnostic);
+ }
+
+ for (filename, diagnostics_by_lc) in diagnostic_groups {
+ for (line, diagnostics_by_col) in diagnostics_by_lc {
+ for (col, diagnostics) in diagnostics_by_col {
+ for diagnostic in diagnostics {
+ log::warn!("{}", diagnostic.kind);
+ }
+ log::warn!(
+ " at {}:{}:{}\n",
+ colors::cyan(filename.as_str()),
+ colors::yellow(&line.to_string()),
+ colors::yellow(&(col + 1).to_string())
+ )
+ }
+ }
+ }
+ bail!(
+ "Found {} documentation diagnostic{}.",
+ colors::bold(diagnostics.len().to_string()),
+ if diagnostics.len() == 1 { "" } else { "s" }
+ );
+}