summaryrefslogtreecommitdiff
path: root/cli/tools/doc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/doc.rs')
-rw-r--r--cli/tools/doc.rs143
1 files changed, 131 insertions, 12 deletions
diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs
index 4a59ec986..2cb9ddfba 100644
--- a/cli/tools/doc.rs
+++ b/cli/tools/doc.rs
@@ -5,6 +5,16 @@ use crate::args::DocHtmlFlag;
use crate::args::DocSourceFileFlag;
use crate::args::Flags;
use crate::colors;
+use crate::diagnostics::Diagnostic;
+use crate::diagnostics::DiagnosticLevel;
+use crate::diagnostics::DiagnosticLocation;
+use crate::diagnostics::DiagnosticSnippet;
+use crate::diagnostics::DiagnosticSnippetHighlight;
+use crate::diagnostics::DiagnosticSnippetHighlightStyle;
+use crate::diagnostics::DiagnosticSnippetSource;
+use crate::diagnostics::DiagnosticSourcePos;
+use crate::diagnostics::DiagnosticSourceRange;
+use crate::diagnostics::SourceTextParsedSourceStore;
use crate::display::write_json_to_stdout;
use crate::display::write_to_stdout_ignore_sigpipe;
use crate::factory::CliFactory;
@@ -23,7 +33,10 @@ use deno_graph::ModuleAnalyzer;
use deno_graph::ModuleParser;
use deno_graph::ModuleSpecifier;
use doc::DocDiagnostic;
+use doc::DocDiagnosticKind;
use indexmap::IndexMap;
+use lsp_types::Url;
+use std::borrow::Cow;
use std::collections::BTreeMap;
use std::rc::Rc;
@@ -129,7 +142,7 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> {
if doc_flags.lint {
let diagnostics = doc_parser.take_diagnostics();
- check_diagnostics(&diagnostics)?;
+ check_diagnostics(&**parsed_source_cache, &diagnostics)?;
}
doc_nodes_by_url
@@ -291,7 +304,118 @@ fn print_docs_to_stdout(
write_to_stdout_ignore_sigpipe(details.as_bytes()).map_err(AnyError::from)
}
-fn check_diagnostics(diagnostics: &[DocDiagnostic]) -> Result<(), AnyError> {
+impl Diagnostic for DocDiagnostic {
+ fn level(&self) -> DiagnosticLevel {
+ DiagnosticLevel::Error
+ }
+
+ fn code(&self) -> impl std::fmt::Display + '_ {
+ match self.kind {
+ DocDiagnosticKind::MissingJsDoc => "missing-jsdoc",
+ DocDiagnosticKind::MissingExplicitType => "missing-explicit-type",
+ DocDiagnosticKind::MissingReturnType => "missing-return-type",
+ DocDiagnosticKind::PrivateTypeRef { .. } => "private-type-ref",
+ }
+ }
+
+ fn message(&self) -> impl std::fmt::Display + '_ {
+ match &self.kind {
+ DocDiagnosticKind::MissingJsDoc => {
+ Cow::Borrowed("exported symbol is missing JSDoc documentation")
+ }
+ DocDiagnosticKind::MissingExplicitType => {
+ Cow::Borrowed("exported symbol is missing an explicit type annotation")
+ }
+ DocDiagnosticKind::MissingReturnType => Cow::Borrowed(
+ "exported function is missing an explicit return type annotation",
+ ),
+ DocDiagnosticKind::PrivateTypeRef {
+ reference, name, ..
+ } => Cow::Owned(format!(
+ "public type '{name}' references private type '{reference}'",
+ )),
+ }
+ }
+
+ fn location(&self) -> DiagnosticLocation {
+ let specifier = Url::parse(&self.location.filename).unwrap();
+ DiagnosticLocation::PositionInFile {
+ specifier: Cow::Owned(specifier),
+ source_pos: DiagnosticSourcePos::ByteIndex(self.location.byte_index),
+ }
+ }
+
+ fn snippet(&self) -> Option<DiagnosticSnippet<'_>> {
+ let specifier = Url::parse(&self.location.filename).unwrap();
+ Some(DiagnosticSnippet {
+ source: DiagnosticSnippetSource::Specifier(Cow::Owned(specifier)),
+ highlight: DiagnosticSnippetHighlight {
+ style: DiagnosticSnippetHighlightStyle::Error,
+ range: DiagnosticSourceRange {
+ start: DiagnosticSourcePos::ByteIndex(self.location.byte_index),
+ end: DiagnosticSourcePos::ByteIndex(self.location.byte_index + 1),
+ },
+ description: None,
+ },
+ })
+ }
+
+ fn hint(&self) -> Option<impl std::fmt::Display + '_> {
+ match &self.kind {
+ DocDiagnosticKind::PrivateTypeRef { .. } => {
+ Some("make the referenced type public or remove the reference")
+ }
+ _ => None,
+ }
+ }
+ fn snippet_fixed(&self) -> Option<DiagnosticSnippet<'_>> {
+ match &self.kind {
+ DocDiagnosticKind::PrivateTypeRef {
+ reference_location, ..
+ } => {
+ let specifier = Url::parse(&reference_location.filename).unwrap();
+ Some(DiagnosticSnippet {
+ source: DiagnosticSnippetSource::Specifier(Cow::Owned(specifier)),
+ highlight: DiagnosticSnippetHighlight {
+ style: DiagnosticSnippetHighlightStyle::Hint,
+ range: DiagnosticSourceRange {
+ start: DiagnosticSourcePos::ByteIndex(
+ reference_location.byte_index,
+ ),
+ end: DiagnosticSourcePos::ByteIndex(
+ reference_location.byte_index + 1,
+ ),
+ },
+ description: Some(Cow::Borrowed("this is the referenced type")),
+ },
+ })
+ }
+ _ => None,
+ }
+ }
+
+ fn info(&self) -> std::borrow::Cow<'_, [std::borrow::Cow<'_, str>]> {
+ match &self.kind {
+ DocDiagnosticKind::MissingJsDoc => Cow::Borrowed(&[]),
+ DocDiagnosticKind::MissingExplicitType => Cow::Borrowed(&[]),
+ DocDiagnosticKind::MissingReturnType => Cow::Borrowed(&[]),
+ DocDiagnosticKind::PrivateTypeRef { .. } => {
+ Cow::Borrowed(&[Cow::Borrowed(
+ "to ensure documentation is complete all types that are exposed in the public API must be public",
+ )])
+ }
+ }
+ }
+
+ fn docs_url(&self) -> Option<impl std::fmt::Display + '_> {
+ None::<&str>
+ }
+}
+
+fn check_diagnostics(
+ parsed_source_cache: &dyn deno_graph::ParsedSourceStore,
+ diagnostics: &[DocDiagnostic],
+) -> Result<(), AnyError> {
if diagnostics.is_empty() {
return Ok(());
}
@@ -309,18 +433,13 @@ fn check_diagnostics(diagnostics: &[DocDiagnostic]) -> Result<(), AnyError> {
.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 (_, diagnostics_by_lc) in diagnostic_groups {
+ for (_, diagnostics_by_col) in diagnostics_by_lc {
+ for (_, diagnostics) in diagnostics_by_col {
for diagnostic in diagnostics {
- log::warn!("{}", diagnostic.message());
+ let sources = SourceTextParsedSourceStore(parsed_source_cache);
+ eprintln!("{}", diagnostic.display(&sources));
}
- log::warn!(
- " at {}:{}:{}\n",
- colors::cyan(filename.as_str()),
- colors::yellow(&line.to_string()),
- colors::yellow(&(col + 1).to_string())
- )
}
}
}