summaryrefslogtreecommitdiff
path: root/cli/tools
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools')
-rw-r--r--cli/tools/doc.rs137
-rw-r--r--cli/tools/lint.rs181
-rw-r--r--cli/tools/registry/diagnostics.rs175
-rw-r--r--cli/tools/registry/graph.rs25
-rw-r--r--cli/tools/registry/mod.rs11
-rw-r--r--cli/tools/registry/tar.rs2
-rw-r--r--cli/tools/repl/session.rs15
-rw-r--r--cli/tools/test/mod.rs2
-rw-r--r--cli/tools/test/reporters/pretty.rs2
-rw-r--r--cli/tools/vendor/analyze.rs3
10 files changed, 187 insertions, 366 deletions
diff --git a/cli/tools/doc.rs b/cli/tools/doc.rs
index 729ee05fc..d2cd0c2a2 100644
--- a/cli/tools/doc.rs
+++ b/cli/tools/doc.rs
@@ -4,24 +4,14 @@ use crate::args::DocFlags;
use crate::args::DocHtmlFlag;
use crate::args::DocSourceFileFlag;
use crate::args::Flags;
-use crate::cache::LazyGraphSourceParser;
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;
use crate::graph_util::graph_lock_or_exit;
use crate::tsc::get_types_declaration_file_text;
use crate::util::fs::collect_specifiers;
+use deno_ast::diagnostics::Diagnostic;
use deno_config::glob::FilePatterns;
use deno_config::glob::PathOrPatternSet;
use deno_core::anyhow::bail;
@@ -34,10 +24,7 @@ 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;
@@ -143,10 +130,7 @@ pub async fn doc(flags: Flags, doc_flags: DocFlags) -> Result<(), AnyError> {
if doc_flags.lint {
let diagnostics = doc_parser.take_diagnostics();
- check_diagnostics(
- LazyGraphSourceParser::new(parsed_source_cache, &graph),
- &diagnostics,
- )?;
+ check_diagnostics(&diagnostics)?;
}
doc_nodes_by_url
@@ -252,6 +236,7 @@ async fn generate_docs_directory(
hide_module_doc_title: false,
href_resolver: Rc::new(DocResolver { deno_ns }),
sidebar_flatten_namespaces: false,
+ usage_composer: None,
};
let files = deno_doc::html::generate(options, doc_nodes_by_url)
@@ -308,118 +293,7 @@ fn print_docs_to_stdout(
write_to_stdout_ignore_sigpipe(details.as_bytes()).map_err(AnyError::from)
}
-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::ModulePosition {
- 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(
- source_parser: LazyGraphSourceParser,
- diagnostics: &[DocDiagnostic],
-) -> Result<(), AnyError> {
+fn check_diagnostics(diagnostics: &[DocDiagnostic]) -> Result<(), AnyError> {
if diagnostics.is_empty() {
return Ok(());
}
@@ -441,8 +315,7 @@ fn check_diagnostics(
for (_, diagnostics_by_col) in diagnostics_by_lc {
for (_, diagnostics) in diagnostics_by_col {
for diagnostic in diagnostics {
- let sources = SourceTextParsedSourceStore(source_parser);
- log::error!("{}", diagnostic.display(&sources));
+ log::error!("{}", diagnostic.display());
}
}
}
diff --git a/cli/tools/lint.rs b/cli/tools/lint.rs
index e9f84fd77..32b47e453 100644
--- a/cli/tools/lint.rs
+++ b/cli/tools/lint.rs
@@ -8,33 +8,22 @@ use crate::args::LintOptions;
use crate::args::LintReporterKind;
use crate::args::LintRulesConfig;
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::SourceTextStore;
use crate::factory::CliFactory;
use crate::tools::fmt::run_parallelized;
use crate::util::file_watcher;
use crate::util::fs::canonicalize_path;
+use crate::util::fs::specifier_from_file_path;
use crate::util::fs::FileCollector;
use crate::util::path::is_script_ext;
use crate::util::sync::AtomicFlag;
+use deno_ast::diagnostics::Diagnostic;
use deno_ast::MediaType;
-use deno_ast::ModuleSpecifier;
use deno_ast::ParsedSource;
-use deno_ast::SourceTextInfo;
use deno_config::glob::FilePatterns;
use deno_core::anyhow::bail;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
use deno_core::serde_json;
-use deno_core::url;
use deno_lint::diagnostic::LintDiagnostic;
use deno_lint::linter::LintFileOptions;
use deno_lint::linter::Linter;
@@ -44,7 +33,6 @@ use deno_lint::rules::LintRule;
use log::debug;
use log::info;
use serde::Serialize;
-use std::borrow::Cow;
use std::fs;
use std::io::stdin;
use std::io::Read;
@@ -124,9 +112,12 @@ pub async fn lint(flags: Flags, lint_flags: LintFlags) -> Result<(), AnyError> {
let reporter_lock = Arc::new(Mutex::new(create_reporter(reporter_kind)));
let lint_rules = get_config_rules_err_empty(lint_options.rules)?;
let file_path = cli_options.initial_cwd().join(STDIN_FILE_NAME);
- let file_path = file_path.to_string_lossy();
let r = lint_stdin(&file_path, lint_rules);
- let success = handle_lint_result(&file_path, r, reporter_lock.clone());
+ let success = handle_lint_result(
+ &file_path.to_string_lossy(),
+ r,
+ reporter_lock.clone(),
+ );
reporter_lock.lock().unwrap().close(1);
success
} else {
@@ -278,13 +269,13 @@ fn lint_file(
source_code: String,
lint_rules: Vec<&'static dyn LintRule>,
) -> Result<(Vec<LintDiagnostic>, ParsedSource), AnyError> {
- let filename = file_path.to_string_lossy().to_string();
- let media_type = MediaType::from_path(file_path);
+ let specifier = specifier_from_file_path(file_path)?;
+ let media_type = MediaType::from_specifier(&specifier);
let linter = create_linter(lint_rules);
let (source, file_diagnostics) = linter.lint_file(LintFileOptions {
- filename,
+ specifier,
media_type,
source_code: source_code.clone(),
})?;
@@ -296,7 +287,7 @@ fn lint_file(
/// Treats input as TypeScript.
/// Compatible with `--json` flag.
fn lint_stdin(
- file_path: &str,
+ file_path: &Path,
lint_rules: Vec<&'static dyn LintRule>,
) -> Result<(Vec<LintDiagnostic>, ParsedSource), AnyError> {
let mut source_code = String::new();
@@ -307,7 +298,7 @@ fn lint_stdin(
let linter = create_linter(lint_rules);
let (source, file_diagnostics) = linter.lint_file(LintFileOptions {
- filename: file_path.to_string(),
+ specifier: specifier_from_file_path(file_path)?,
source_code: source_code.clone(),
media_type: MediaType::TypeScript,
})?;
@@ -324,7 +315,10 @@ fn handle_lint_result(
match result {
Ok((mut file_diagnostics, source)) => {
- sort_diagnostics(&mut file_diagnostics);
+ file_diagnostics.sort_by(|a, b| match a.specifier.cmp(&b.specifier) {
+ std::cmp::Ordering::Equal => a.range.start.cmp(&b.range.start),
+ file_order => file_order,
+ });
for d in file_diagnostics.iter() {
reporter.visit_diagnostic(d, &source);
}
@@ -359,77 +353,11 @@ impl PrettyLintReporter {
}
}
-impl Diagnostic for LintDiagnostic {
- fn level(&self) -> DiagnosticLevel {
- DiagnosticLevel::Error
- }
-
- fn code(&self) -> impl std::fmt::Display + '_ {
- &self.code
- }
-
- fn message(&self) -> impl std::fmt::Display + '_ {
- &self.message
- }
-
- fn location(&self) -> DiagnosticLocation {
- let specifier = url::Url::from_file_path(&self.filename).unwrap();
- DiagnosticLocation::ModulePosition {
- specifier: Cow::Owned(specifier),
- source_pos: DiagnosticSourcePos::ByteIndex(self.range.start.byte_index),
- }
- }
-
- fn snippet(&self) -> Option<DiagnosticSnippet<'_>> {
- let specifier = url::Url::from_file_path(&self.filename).unwrap();
- let range = DiagnosticSourceRange {
- start: DiagnosticSourcePos::ByteIndex(self.range.start.byte_index),
- end: DiagnosticSourcePos::ByteIndex(self.range.end.byte_index),
- };
- Some(DiagnosticSnippet {
- source: DiagnosticSnippetSource::Specifier(Cow::Owned(specifier)),
- highlight: DiagnosticSnippetHighlight {
- range,
- style: DiagnosticSnippetHighlightStyle::Error,
- description: None,
- },
- })
- }
-
- fn hint(&self) -> Option<impl std::fmt::Display + '_> {
- self.hint.as_ref().map(|h| h as &dyn std::fmt::Display)
- }
-
- fn snippet_fixed(&self) -> Option<DiagnosticSnippet<'_>> {
- None // todo
- }
-
- fn info(&self) -> Cow<'_, [std::borrow::Cow<'_, str>]> {
- Cow::Borrowed(&[])
- }
-
- fn docs_url(&self) -> Option<impl std::fmt::Display + '_> {
- Some(format!("https://lint.deno.land/#{}", &self.code))
- }
-}
-
-struct OneSource<'a>(&'a ParsedSource);
-
-impl SourceTextStore for OneSource<'_> {
- fn get_source_text<'a>(
- &'a self,
- _specifier: &ModuleSpecifier,
- ) -> Option<Cow<'a, SourceTextInfo>> {
- Some(Cow::Borrowed(self.0.text_info()))
- }
-}
-
impl LintReporter for PrettyLintReporter {
- fn visit_diagnostic(&mut self, d: &LintDiagnostic, source: &ParsedSource) {
+ fn visit_diagnostic(&mut self, d: &LintDiagnostic, _source: &ParsedSource) {
self.lint_count += 1;
- let sources = OneSource(source);
- eprintln!("{}", d.display(&sources));
+ eprintln!("{}", d.display());
}
fn visit_error(&mut self, file_path: &str, err: &AnyError) {
@@ -466,11 +394,12 @@ impl LintReporter for CompactLintReporter {
fn visit_diagnostic(&mut self, d: &LintDiagnostic, _source: &ParsedSource) {
self.lint_count += 1;
+ let line_and_column = d.text_info.line_and_column_display(d.range.start);
eprintln!(
"{}: line {}, col {} - {} ({})",
- d.filename,
- d.range.start.line_index + 1,
- d.range.start.column_index + 1,
+ d.specifier,
+ line_and_column.line_number,
+ line_and_column.column_number,
d.message,
d.code
)
@@ -496,9 +425,47 @@ impl LintReporter for CompactLintReporter {
}
}
+// WARNING: Ensure doesn't change because it's used in the JSON output
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct JsonDiagnosticLintPosition {
+ /// The 1-indexed line number.
+ pub line: usize,
+ /// The 0-indexed column index.
+ pub col: usize,
+ pub byte_pos: usize,
+}
+
+impl JsonDiagnosticLintPosition {
+ pub fn new(byte_index: usize, loc: deno_ast::LineAndColumnIndex) -> Self {
+ JsonDiagnosticLintPosition {
+ line: loc.line_index + 1,
+ col: loc.column_index,
+ byte_pos: byte_index,
+ }
+ }
+}
+
+// WARNING: Ensure doesn't change because it's used in the JSON output
+#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
+struct JsonLintDiagnosticRange {
+ pub start: JsonDiagnosticLintPosition,
+ pub end: JsonDiagnosticLintPosition,
+}
+
+// WARNING: Ensure doesn't change because it's used in the JSON output
+#[derive(Clone, Serialize)]
+struct JsonLintDiagnostic {
+ pub filename: String,
+ pub range: JsonLintDiagnosticRange,
+ pub message: String,
+ pub code: String,
+ pub hint: Option<String>,
+}
+
#[derive(Serialize)]
struct JsonLintReporter {
- diagnostics: Vec<LintDiagnostic>,
+ diagnostics: Vec<JsonLintDiagnostic>,
errors: Vec<LintError>,
}
@@ -513,7 +480,22 @@ impl JsonLintReporter {
impl LintReporter for JsonLintReporter {
fn visit_diagnostic(&mut self, d: &LintDiagnostic, _source: &ParsedSource) {
- self.diagnostics.push(d.clone());
+ self.diagnostics.push(JsonLintDiagnostic {
+ filename: d.specifier.to_string(),
+ range: JsonLintDiagnosticRange {
+ start: JsonDiagnosticLintPosition::new(
+ d.range.start.as_byte_index(d.text_info.range().start),
+ d.text_info.line_and_column_index(d.range.start),
+ ),
+ end: JsonDiagnosticLintPosition::new(
+ d.range.end.as_byte_index(d.text_info.range().start),
+ d.text_info.line_and_column_index(d.range.end),
+ ),
+ },
+ message: d.message.clone(),
+ code: d.code.clone(),
+ hint: d.hint.clone(),
+ });
}
fn visit_error(&mut self, file_path: &str, err: &AnyError) {
@@ -530,19 +512,16 @@ impl LintReporter for JsonLintReporter {
}
}
-fn sort_diagnostics(diagnostics: &mut [LintDiagnostic]) {
+fn sort_diagnostics(diagnostics: &mut [JsonLintDiagnostic]) {
// Sort so that we guarantee a deterministic output which is useful for tests
diagnostics.sort_by(|a, b| {
use std::cmp::Ordering;
let file_order = a.filename.cmp(&b.filename);
match file_order {
Ordering::Equal => {
- let line_order =
- a.range.start.line_index.cmp(&b.range.start.line_index);
+ let line_order = a.range.start.line.cmp(&b.range.start.line);
match line_order {
- Ordering::Equal => {
- a.range.start.column_index.cmp(&b.range.start.column_index)
- }
+ Ordering::Equal => a.range.start.col.cmp(&b.range.start.col),
_ => line_order,
}
}
diff --git a/cli/tools/registry/diagnostics.rs b/cli/tools/registry/diagnostics.rs
index e7f947303..aeb5d61e2 100644
--- a/cli/tools/registry/diagnostics.rs
+++ b/cli/tools/registry/diagnostics.rs
@@ -1,28 +1,25 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use std::borrow::Cow;
-use std::fmt::Display;
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::Mutex;
+use deno_ast::diagnostics::Diagnostic;
+use deno_ast::diagnostics::DiagnosticLevel;
+use deno_ast::diagnostics::DiagnosticLocation;
+use deno_ast::diagnostics::DiagnosticSnippet;
+use deno_ast::diagnostics::DiagnosticSnippetHighlight;
+use deno_ast::diagnostics::DiagnosticSnippetHighlightStyle;
+use deno_ast::diagnostics::DiagnosticSourcePos;
+use deno_ast::diagnostics::DiagnosticSourceRange;
use deno_ast::swc::common::util::take::Take;
+use deno_ast::SourceTextInfo;
use deno_core::anyhow::anyhow;
use deno_core::error::AnyError;
use deno_graph::FastCheckDiagnostic;
use lsp_types::Url;
-use crate::cache::LazyGraphSourceParser;
-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::util::import_map::ImportMapUnfurlDiagnostic;
#[derive(Clone, Default)]
@@ -31,16 +28,12 @@ pub struct PublishDiagnosticsCollector {
}
impl PublishDiagnosticsCollector {
- pub fn print_and_error(
- &self,
- sources: LazyGraphSourceParser,
- ) -> Result<(), AnyError> {
+ pub fn print_and_error(&self) -> Result<(), AnyError> {
let mut errors = 0;
let mut has_zap_errors = false;
let diagnostics = self.diagnostics.lock().unwrap().take();
- let sources = SourceTextParsedSourceStore(sources);
for diagnostic in diagnostics {
- eprint!("{}", diagnostic.display(&sources));
+ eprint!("{}", diagnostic.display());
if matches!(diagnostic.level(), DiagnosticLevel::Error) {
errors += 1;
}
@@ -90,6 +83,7 @@ pub enum PublishDiagnostic {
InvalidExternalImport {
kind: String,
imported: Url,
+ text_info: SourceTextInfo,
referrer: deno_graph::Range,
},
}
@@ -110,22 +104,22 @@ impl Diagnostic for PublishDiagnostic {
}
}
- fn code(&self) -> impl Display + '_ {
+ fn code(&self) -> Cow<'_, str> {
use PublishDiagnostic::*;
match &self {
FastCheck(diagnostic) => diagnostic.code(),
- ImportMapUnfurl(diagnostic) => diagnostic.code(),
- InvalidPath { .. } => "invalid-path",
- DuplicatePath { .. } => "case-insensitive-duplicate-path",
- UnsupportedFileType { .. } => "unsupported-file-type",
- InvalidExternalImport { .. } => "invalid-external-import",
+ ImportMapUnfurl(diagnostic) => Cow::Borrowed(diagnostic.code()),
+ InvalidPath { .. } => Cow::Borrowed("invalid-path"),
+ DuplicatePath { .. } => Cow::Borrowed("case-insensitive-duplicate-path"),
+ UnsupportedFileType { .. } => Cow::Borrowed("unsupported-file-type"),
+ InvalidExternalImport { .. } => Cow::Borrowed("invalid-external-import"),
}
}
- fn message(&self) -> impl Display + '_ {
+ fn message(&self) -> Cow<'_, str> {
use PublishDiagnostic::*;
match &self {
- FastCheck(diagnostic) => Cow::Owned(diagnostic.to_string()) ,
+ FastCheck(diagnostic) => diagnostic.message(),
ImportMapUnfurl(diagnostic) => Cow::Borrowed(diagnostic.message()),
InvalidPath { message, .. } => Cow::Borrowed(message.as_str()),
DuplicatePath { .. } => {
@@ -141,21 +135,15 @@ impl Diagnostic for PublishDiagnostic {
fn location(&self) -> DiagnosticLocation {
use PublishDiagnostic::*;
match &self {
- FastCheck(diagnostic) => match diagnostic.range() {
- Some(range) => DiagnosticLocation::ModulePosition {
- specifier: Cow::Borrowed(diagnostic.specifier()),
- source_pos: DiagnosticSourcePos::SourcePos(range.range.start),
- },
- None => DiagnosticLocation::Module {
- specifier: Cow::Borrowed(diagnostic.specifier()),
- },
- },
+ FastCheck(diagnostic) => diagnostic.location(),
ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport {
specifier,
+ text_info,
range,
} => DiagnosticLocation::ModulePosition {
specifier: Cow::Borrowed(specifier),
+ text_info: Cow::Borrowed(text_info),
source_pos: DiagnosticSourcePos::SourcePos(range.start),
},
},
@@ -168,41 +156,31 @@ impl Diagnostic for PublishDiagnostic {
UnsupportedFileType { specifier, .. } => DiagnosticLocation::Module {
specifier: Cow::Borrowed(specifier),
},
- InvalidExternalImport { referrer, .. } => {
- DiagnosticLocation::ModulePosition {
- specifier: Cow::Borrowed(&referrer.specifier),
- source_pos: DiagnosticSourcePos::LineAndCol {
- line: referrer.start.line,
- column: referrer.start.character,
- },
- }
- }
+ InvalidExternalImport {
+ referrer,
+ text_info,
+ ..
+ } => DiagnosticLocation::ModulePosition {
+ specifier: Cow::Borrowed(&referrer.specifier),
+ text_info: Cow::Borrowed(text_info),
+ source_pos: DiagnosticSourcePos::LineAndCol {
+ line: referrer.start.line,
+ column: referrer.start.character,
+ },
+ },
}
}
fn snippet(&self) -> Option<DiagnosticSnippet<'_>> {
match &self {
- PublishDiagnostic::FastCheck(diagnostic) => {
- diagnostic.range().map(|range| DiagnosticSnippet {
- source: DiagnosticSnippetSource::Specifier(Cow::Borrowed(
- diagnostic.specifier(),
- )),
- highlight: DiagnosticSnippetHighlight {
- style: DiagnosticSnippetHighlightStyle::Error,
- range: DiagnosticSourceRange {
- start: DiagnosticSourcePos::SourcePos(range.range.start),
- end: DiagnosticSourcePos::SourcePos(range.range.end),
- },
- description: diagnostic.range_description().map(Cow::Borrowed),
- },
- })
- }
+ PublishDiagnostic::FastCheck(diagnostic) => diagnostic.snippet(),
PublishDiagnostic::ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport {
- specifier,
+ text_info,
range,
+ ..
} => Some(DiagnosticSnippet {
- source: DiagnosticSnippetSource::Specifier(Cow::Borrowed(specifier)),
+ source: Cow::Borrowed(text_info),
highlight: DiagnosticSnippetHighlight {
style: DiagnosticSnippetHighlightStyle::Warning,
range: DiagnosticSourceRange {
@@ -216,44 +194,44 @@ impl Diagnostic for PublishDiagnostic {
PublishDiagnostic::InvalidPath { .. } => None,
PublishDiagnostic::DuplicatePath { .. } => None,
PublishDiagnostic::UnsupportedFileType { .. } => None,
- PublishDiagnostic::InvalidExternalImport { referrer, .. } => {
- Some(DiagnosticSnippet {
- source: DiagnosticSnippetSource::Specifier(Cow::Borrowed(
- &referrer.specifier,
- )),
- highlight: DiagnosticSnippetHighlight {
- style: DiagnosticSnippetHighlightStyle::Error,
- range: DiagnosticSourceRange {
- start: DiagnosticSourcePos::LineAndCol {
- line: referrer.start.line,
- column: referrer.start.character,
- },
- end: DiagnosticSourcePos::LineAndCol {
- line: referrer.end.line,
- column: referrer.end.character,
- },
+ PublishDiagnostic::InvalidExternalImport {
+ referrer,
+ text_info,
+ ..
+ } => Some(DiagnosticSnippet {
+ source: Cow::Borrowed(text_info),
+ highlight: DiagnosticSnippetHighlight {
+ style: DiagnosticSnippetHighlightStyle::Error,
+ range: DiagnosticSourceRange {
+ start: DiagnosticSourcePos::LineAndCol {
+ line: referrer.start.line,
+ column: referrer.start.character,
+ },
+ end: DiagnosticSourcePos::LineAndCol {
+ line: referrer.end.line,
+ column: referrer.end.character,
},
- description: Some("the specifier".into()),
},
- })
- }
+ description: Some("the specifier".into()),
+ },
+ }),
}
}
- fn hint(&self) -> Option<impl Display + '_> {
+ fn hint(&self) -> Option<Cow<'_, str>> {
match &self {
- PublishDiagnostic::FastCheck(diagnostic) => Some(diagnostic.fix_hint()),
+ PublishDiagnostic::FastCheck(diagnostic) => diagnostic.hint(),
PublishDiagnostic::ImportMapUnfurl(_) => None,
PublishDiagnostic::InvalidPath { .. } => Some(
- "rename or remove the file, or add it to 'publish.exclude' in the config file",
+ Cow::Borrowed("rename or remove the file, or add it to 'publish.exclude' in the config file"),
),
PublishDiagnostic::DuplicatePath { .. } => Some(
- "rename or remove the file",
+ Cow::Borrowed("rename or remove the file"),
),
PublishDiagnostic::UnsupportedFileType { .. } => Some(
- "remove the file, or add it to 'publish.exclude' in the config file",
+ Cow::Borrowed("remove the file, or add it to 'publish.exclude' in the config file"),
),
- PublishDiagnostic::InvalidExternalImport { .. } => Some("replace this import with one from jsr or npm, or vendor the dependency into your package")
+ PublishDiagnostic::InvalidExternalImport { .. } => Some(Cow::Borrowed("replace this import with one from jsr or npm, or vendor the dependency into your package"))
}
}
@@ -264,12 +242,7 @@ impl Diagnostic for PublishDiagnostic {
fn info(&self) -> Cow<'_, [Cow<'_, str>]> {
match &self {
PublishDiagnostic::FastCheck(diagnostic) => {
- let infos = diagnostic
- .additional_info()
- .iter()
- .map(|s| Cow::Borrowed(*s))
- .collect();
- Cow::Owned(infos)
+ diagnostic.info()
}
PublishDiagnostic::ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport { .. } => Cow::Borrowed(&[
@@ -296,25 +269,23 @@ impl Diagnostic for PublishDiagnostic {
}
}
- fn docs_url(&self) -> Option<impl Display + '_> {
+ fn docs_url(&self) -> Option<Cow<'_, str>> {
match &self {
- PublishDiagnostic::FastCheck(diagnostic) => {
- Some(format!("https://jsr.io/go/{}", diagnostic.code()))
- }
+ PublishDiagnostic::FastCheck(diagnostic) => diagnostic.docs_url(),
PublishDiagnostic::ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport { .. } => None,
},
PublishDiagnostic::InvalidPath { .. } => {
- Some("https://jsr.io/go/invalid-path".to_owned())
- }
- PublishDiagnostic::DuplicatePath { .. } => {
- Some("https://jsr.io/go/case-insensitive-duplicate-path".to_owned())
+ Some(Cow::Borrowed("https://jsr.io/go/invalid-path"))
}
+ PublishDiagnostic::DuplicatePath { .. } => Some(Cow::Borrowed(
+ "https://jsr.io/go/case-insensitive-duplicate-path",
+ )),
PublishDiagnostic::UnsupportedFileType { .. } => {
- Some("https://jsr.io/go/unsupported-file-type".to_owned())
+ Some(Cow::Borrowed("https://jsr.io/go/unsupported-file-type"))
}
PublishDiagnostic::InvalidExternalImport { .. } => {
- Some("https://jsr.io/go/invalid-external-import".to_owned())
+ Some(Cow::Borrowed("https://jsr.io/go/invalid-external-import"))
}
}
}
diff --git a/cli/tools/registry/graph.rs b/cli/tools/registry/graph.rs
index d9fb665c4..3445d55e7 100644
--- a/cli/tools/registry/graph.rs
+++ b/cli/tools/registry/graph.rs
@@ -2,8 +2,10 @@
use std::collections::HashSet;
use std::collections::VecDeque;
+use std::sync::Arc;
use deno_ast::ModuleSpecifier;
+use deno_ast::SourceTextInfo;
use deno_config::ConfigFile;
use deno_config::WorkspaceConfig;
use deno_core::anyhow::bail;
@@ -76,7 +78,9 @@ pub fn collect_invalid_external_imports(
let mut skip_specifiers: HashSet<Url> = HashSet::new();
let mut collect_if_invalid =
- |skip_specifiers: &mut HashSet<Url>, resolution: &ResolutionResolved| {
+ |skip_specifiers: &mut HashSet<Url>,
+ text: &Arc<str>,
+ resolution: &ResolutionResolved| {
if visited.insert(resolution.specifier.clone()) {
match resolution.specifier.scheme() {
"file" | "data" | "node" => {}
@@ -88,6 +92,7 @@ pub fn collect_invalid_external_imports(
diagnostics_collector.push(
PublishDiagnostic::InvalidExternalImport {
kind: format!("non-JSR '{}'", resolution.specifier.scheme()),
+ text_info: SourceTextInfo::new(text.clone()),
imported: resolution.specifier.clone(),
referrer: resolution.range.clone(),
},
@@ -98,6 +103,7 @@ pub fn collect_invalid_external_imports(
diagnostics_collector.push(
PublishDiagnostic::InvalidExternalImport {
kind: format!("'{}'", resolution.specifier.scheme()),
+ text_info: SourceTextInfo::new(text.clone()),
imported: resolution.specifier.clone(),
referrer: resolution.range.clone(),
},
@@ -128,10 +134,10 @@ pub fn collect_invalid_external_imports(
for (_, dep) in &module.dependencies {
if let Some(resolved) = dep.maybe_code.ok() {
- collect_if_invalid(&mut skip_specifiers, resolved);
+ collect_if_invalid(&mut skip_specifiers, &module.source, resolved);
}
if let Some(resolved) = dep.maybe_type.ok() {
- collect_if_invalid(&mut skip_specifiers, resolved);
+ collect_if_invalid(&mut skip_specifiers, &module.source, resolved);
}
}
}
@@ -144,7 +150,7 @@ pub fn collect_fast_check_type_graph_diagnostics(
packages: &[MemberRoots],
diagnostics_collector: &PublishDiagnosticsCollector,
) -> bool {
- let mut seen_diagnostics = HashSet::new();
+ let mut had_diagnostic = false;
let mut seen_modules = HashSet::with_capacity(graph.specifiers_count());
for package in packages {
let mut pending = VecDeque::new();
@@ -161,12 +167,9 @@ pub fn collect_fast_check_type_graph_diagnostics(
let Some(es_module) = module.js() else {
continue;
};
- if let Some(diagnostic) = es_module.fast_check_diagnostic() {
- for diagnostic in diagnostic.flatten_multiple() {
- if !seen_diagnostics.insert(diagnostic.message_with_range_for_test())
- {
- continue;
- }
+ if let Some(diagnostics) = es_module.fast_check_diagnostics() {
+ for diagnostic in diagnostics {
+ had_diagnostic = true;
diagnostics_collector
.push(PublishDiagnostic::FastCheck(diagnostic.clone()));
if matches!(
@@ -197,5 +200,5 @@ pub fn collect_fast_check_type_graph_diagnostics(
}
}
- !seen_diagnostics.is_empty()
+ had_diagnostic
}
diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs
index 5f03fa6fd..cfdec04c5 100644
--- a/cli/tools/registry/mod.rs
+++ b/cli/tools/registry/mod.rs
@@ -643,7 +643,6 @@ async fn publish_package(
struct PreparePackagesData {
publish_order_graph: PublishOrderGraph,
- graph: Arc<deno_graph::ModuleGraph>,
package_by_name: HashMap<String, Rc<PreparedPublishPackage>>,
}
@@ -678,7 +677,7 @@ async fn prepare_packages_for_publishing(
let package = prepare_publish(
&deno_json,
source_cache.clone(),
- graph.clone(),
+ graph,
import_map,
diagnostics_collector,
)
@@ -689,7 +688,6 @@ async fn prepare_packages_for_publishing(
let package_by_name = HashMap::from([(package_name, package)]);
return Ok(PreparePackagesData {
publish_order_graph,
- graph,
package_by_name,
});
};
@@ -743,7 +741,6 @@ async fn prepare_packages_for_publishing(
}
Ok(PreparePackagesData {
publish_order_graph,
- graph,
package_by_name,
})
}
@@ -849,11 +846,7 @@ pub async fn publish(
)
.await?;
- let source_parser = LazyGraphSourceParser::new(
- cli_factory.parsed_source_cache(),
- &prepared_data.graph,
- );
- diagnostics_collector.print_and_error(source_parser)?;
+ diagnostics_collector.print_and_error()?;
if prepared_data.package_by_name.is_empty() {
bail!("No packages to publish");
diff --git a/cli/tools/registry/tar.rs b/cli/tools/registry/tar.rs
index e63a76516..6543fbf2e 100644
--- a/cli/tools/registry/tar.rs
+++ b/cli/tools/registry/tar.rs
@@ -206,7 +206,7 @@ fn resolve_content_maybe_unfurling(
let text = String::from_utf8(data)?;
deno_ast::parse_module(deno_ast::ParseParams {
- specifier: specifier.to_string(),
+ specifier: specifier.clone(),
text_info: deno_ast::SourceTextInfo::from_string(text),
media_type,
capture_tokens: false,
diff --git a/cli/tools/repl/session.rs b/cli/tools/repl/session.rs
index e98f4b430..a52eb095f 100644
--- a/cli/tools/repl/session.rs
+++ b/cli/tools/repl/session.rs
@@ -16,14 +16,15 @@ use crate::tools::test::worker_has_tests;
use crate::tools::test::TestEvent;
use crate::tools::test::TestEventSender;
+use deno_ast::diagnostics::Diagnostic;
use deno_ast::swc::ast as swc_ast;
use deno_ast::swc::common::comments::CommentKind;
use deno_ast::swc::visit::noop_visit_type;
use deno_ast::swc::visit::Visit;
use deno_ast::swc::visit::VisitWith;
-use deno_ast::DiagnosticsError;
use deno_ast::ImportsNotUsedAsValues;
use deno_ast::ModuleSpecifier;
+use deno_ast::ParseDiagnosticsError;
use deno_ast::ParsedSource;
use deno_ast::SourcePos;
use deno_ast::SourceRangedForSpanned;
@@ -324,7 +325,7 @@ impl ReplSession {
&mut self,
line: &str,
) -> EvaluationOutput {
- fn format_diagnostic(diagnostic: &deno_ast::Diagnostic) -> String {
+ fn format_diagnostic(diagnostic: &deno_ast::ParseDiagnostic) -> String {
let display_position = diagnostic.display_position();
format!(
"{}: {} at {}:{}",
@@ -377,11 +378,11 @@ impl ReplSession {
}
Err(err) => {
// handle a parsing diagnostic
- match err.downcast_ref::<deno_ast::Diagnostic>() {
+ match err.downcast_ref::<deno_ast::ParseDiagnostic>() {
Some(diagnostic) => {
Ok(EvaluationOutput::Error(format_diagnostic(diagnostic)))
}
- None => match err.downcast_ref::<DiagnosticsError>() {
+ None => match err.downcast_ref::<ParseDiagnosticsError>() {
Some(diagnostics) => Ok(EvaluationOutput::Error(
diagnostics
.0
@@ -786,13 +787,13 @@ fn parse_source_as(
media_type: deno_ast::MediaType,
) -> Result<deno_ast::ParsedSource, AnyError> {
let specifier = if media_type == deno_ast::MediaType::Tsx {
- "repl.tsx"
+ ModuleSpecifier::parse("file:///repl.tsx").unwrap()
} else {
- "repl.ts"
+ ModuleSpecifier::parse("file:///repl.ts").unwrap()
};
let parsed = deno_ast::parse_module(deno_ast::ParseParams {
- specifier: specifier.to_string(),
+ specifier,
text_info: deno_ast::SourceTextInfo::from_string(source),
media_type,
capture_tokens: true,
diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs
index 332bfa8c8..c138abec2 100644
--- a/cli/tools/test/mod.rs
+++ b/cli/tools/test/mod.rs
@@ -752,7 +752,7 @@ fn extract_files_from_source_comments(
media_type: MediaType,
) -> Result<Vec<File>, AnyError> {
let parsed_source = deno_ast::parse_module(deno_ast::ParseParams {
- specifier: specifier.to_string(),
+ specifier: specifier.clone(),
text_info: deno_ast::SourceTextInfo::new(source),
media_type,
capture_tokens: false,
diff --git a/cli/tools/test/reporters/pretty.rs b/cli/tools/test/reporters/pretty.rs
index c49081dd6..4e8a1f402 100644
--- a/cli/tools/test/reporters/pretty.rs
+++ b/cli/tools/test/reporters/pretty.rs
@@ -141,7 +141,7 @@ impl PrettyTestReporter {
.child_results_buffer
.entry(description.parent_id)
.or_default()
- .remove(&description.id);
+ .shift_remove(&description.id);
}
fn write_output_end(&mut self) {
diff --git a/cli/tools/vendor/analyze.rs b/cli/tools/vendor/analyze.rs
index c804fa1ce..2b00f6bf4 100644
--- a/cli/tools/vendor/analyze.rs
+++ b/cli/tools/vendor/analyze.rs
@@ -61,6 +61,7 @@ fn export_specifier_has_default(s: &ExportSpecifier) -> bool {
#[cfg(test)]
mod test {
use deno_ast::MediaType;
+ use deno_ast::ModuleSpecifier;
use deno_ast::ParseParams;
use deno_ast::ParsedSource;
use deno_ast::SourceTextInfo;
@@ -101,7 +102,7 @@ mod test {
fn parse_module(text: &str) -> ParsedSource {
deno_ast::parse_module(ParseParams {
- specifier: "file:///mod.ts".to_string(),
+ specifier: ModuleSpecifier::parse("file:///mod.ts").unwrap(),
capture_tokens: false,
maybe_syntax: None,
media_type: MediaType::TypeScript,