diff --git a/Cargo.lock b/Cargo.lock index e64d40feba7b02..b701073a76db85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2010,9 +2010,9 @@ dependencies = [ [[package]] name = "deno_lint" -version = "0.70.0" +version = "0.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac94db8d8597b96c92d30a68b11d4bec6822dcbb3e8675ab1e0136816a301a34" +checksum = "810d0f4b19cd44061bbe7252ad37cf7a81753540f97f88e1548ac9f03b3a18cc" dependencies = [ "anyhow", "deno_ast", @@ -4187,9 +4187,9 @@ dependencies = [ [[package]] name = "hstr" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9de2bdef6354361892492bab5e316b2d78a0ee9971db4d36da9b1eb0e11999" +checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412" dependencies = [ "hashbrown 0.14.5", "new_debug_unreachable", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index dee17bd34474a2..1e8d75628c2415 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -74,7 +74,7 @@ deno_doc = { version = "=0.164.0", features = ["rust", "comrak"] } deno_error.workspace = true deno_graph = { version = "=0.87.2" } deno_lib.workspace = true -deno_lint = { version = "0.70.0" } +deno_lint = { version = "0.71.0" } deno_lockfile.workspace = true deno_media_type = { workspace = true, features = ["data_url", "decoding", "module_specifier"] } deno_npm.workspace = true diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 7a817486def07f..96adff8696d6d2 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -499,6 +499,7 @@ impl DenoSubcommand { | Self::Jupyter(_) | Self::Repl(_) | Self::Bench(_) + | Self::Lint(_) | Self::Lsp ) } diff --git a/cli/args/mod.rs b/cli/args/mod.rs index f0d59299d0202a..d59a4e4d362c88 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -366,6 +366,7 @@ pub struct LintOptions { pub rules: LintRulesConfig, pub files: FilePatterns, pub fix: bool, + pub plugins: Vec, } impl Default for LintOptions { @@ -380,20 +381,41 @@ impl LintOptions { rules: Default::default(), files: FilePatterns::new_with_base(base), fix: false, + plugins: vec![], } } - pub fn resolve(lint_config: LintConfig, lint_flags: &LintFlags) -> Self { - Self { + pub fn resolve( + dir_path: PathBuf, + lint_config: LintConfig, + lint_flags: &LintFlags, + ) -> Result { + let rules = resolve_lint_rules_options( + lint_config.options.rules, + lint_flags.maybe_rules_tags.clone(), + lint_flags.maybe_rules_include.clone(), + lint_flags.maybe_rules_exclude.clone(), + ); + + let plugins = { + let plugin_specifiers = lint_config.options.plugins; + let mut plugins = Vec::with_capacity(plugin_specifiers.len()); + for plugin in &plugin_specifiers { + // TODO(bartlomieju): handle import-mapped specifiers + let url = resolve_url_or_path(plugin, &dir_path)?; + plugins.push(url); + } + // ensure stability for hasher + plugins.sort_unstable(); + plugins + }; + + Ok(Self { files: lint_config.files, - rules: resolve_lint_rules_options( - lint_config.options.rules, - lint_flags.maybe_rules_tags.clone(), - lint_flags.maybe_rules_include.clone(), - lint_flags.maybe_rules_exclude.clone(), - ), + rules, fix: lint_flags.fix, - } + plugins, + }) } } @@ -759,7 +781,7 @@ impl CliOptions { .resolve_lint_config_for_members(&cli_arg_patterns)?; let mut result = Vec::with_capacity(member_configs.len()); for (ctx, config) in member_configs { - let options = LintOptions::resolve(config, lint_flags); + let options = LintOptions::resolve(ctx.dir_path(), config, lint_flags)?; result.push((ctx, options)); } Ok(result) diff --git a/cli/js/40_lint.js b/cli/js/40_lint.js index 9f85f0871df2ea..d8e99c7b0a9107 100644 --- a/cli/js/40_lint.js +++ b/cli/js/40_lint.js @@ -10,9 +10,14 @@ import { import { core, internals } from "ext:core/mod.js"; const { + op_lint_get_source, + op_lint_report, op_lint_create_serialized_ast, + op_is_cancelled, } = core.ops; +let doReport = op_lint_report; + // Keep these in sync with Rust const AST_IDX_INVALID = 0; const AST_GROUP_TYPE = 1; @@ -72,29 +77,133 @@ const PropFlags = { /** @typedef {import("./40_lint_types.d.ts").VisitorFn} VisitorFn */ /** @typedef {import("./40_lint_types.d.ts").CompiledVisitor} CompiledVisitor */ /** @typedef {import("./40_lint_types.d.ts").LintState} LintState */ -/** @typedef {import("./40_lint_types.d.ts").RuleContext} RuleContext */ -/** @typedef {import("./40_lint_types.d.ts").NodeFacade} NodeFacade */ -/** @typedef {import("./40_lint_types.d.ts").LintPlugin} LintPlugin */ /** @typedef {import("./40_lint_types.d.ts").TransformFn} TransformFn */ /** @typedef {import("./40_lint_types.d.ts").MatchContext} MatchContext */ -/** @typedef {import("./40_lint_types.d.ts").Node} Node */ /** @type {LintState} */ const state = { plugins: [], installedPlugins: new Set(), + ignoredRules: new Set(), }; +function resetState() { + state.plugins = []; + state.installedPlugins.clear(); + state.ignoredRules.clear(); +} + +/** + * This implementation calls into Rust to check if Tokio's cancellation token + * has already been canceled. + */ +class CancellationToken { + isCancellationRequested() { + return op_is_cancelled(); + } +} + +/** @implements {Deno.lint.Fixer} */ +class Fixer { + /** + * @param {Deno.lint.Node} node + * @param {string} text + */ + insertTextAfter(node, text) { + return { + range: /** @type {[number, number]} */ ([node.range[1], node.range[1]]), + text, + }; + } + + /** + * @param {Deno.lint.Node["range"]} range + * @param {string} text + */ + insertTextAfterRange(range, text) { + return { + range: /** @type {[number, number]} */ ([range[1], range[1]]), + text, + }; + } + + /** + * @param {Deno.lint.Node} node + * @param {string} text + */ + insertTextBefore(node, text) { + return { + range: /** @type {[number, number]} */ ([node.range[0], node.range[0]]), + text, + }; + } + + /** + * @param {Deno.lint.Node["range"]} range + * @param {string} text + */ + insertTextBeforeRange(range, text) { + return { + range: /** @type {[number, number]} */ ([range[0], range[0]]), + text, + }; + } + + /** + * @param {Deno.lint.Node} node + */ + remove(node) { + return { + range: node.range, + text: "", + }; + } + + /** + * @param {Deno.lint.Node["range"]} range + */ + removeRange(range) { + return { + range, + text: "", + }; + } + + /** + * @param {Deno.lint.Node} node + * @param {string} text + */ + replaceText(node, text) { + return { + range: node.range, + text, + }; + } + + /** + * @param {Deno.lint.Node["range"]} range + * @param {string} text + */ + replaceTextRange(range, text) { + return { + range, + text, + }; + } +} + /** * Every rule gets their own instance of this class. This is the main * API lint rules interact with. - * @implements {RuleContext} + * @implements {Deno.lint.RuleContext} */ export class Context { id; fileName; + #source = null; + /** * @param {string} id * @param {string} fileName @@ -103,18 +212,85 @@ export class Context { this.id = id; this.fileName = fileName; } + + source() { + if (this.#source === null) { + this.#source = op_lint_get_source(); + } + return /** @type {*} */ (this.#source); + } + + /** + * @param {Deno.lint.ReportData} data + */ + report(data) { + const range = data.node ? data.node.range : data.range ? data.range : null; + if (range == null) { + throw new Error( + "Either `node` or `range` must be provided when reporting an error", + ); + } + + const start = range[0]; + const end = range[1]; + + let fix; + + if (typeof data.fix === "function") { + const fixer = new Fixer(); + fix = data.fix(fixer); + } + + doReport( + this.id, + data.message, + data.hint, + start, + end, + fix, + ); + } } /** - * @param {LintPlugin} plugin + * @param {Deno.lint.Plugin[]} plugins + * @param {string[]} exclude + */ +export function installPlugins(plugins, exclude) { + if (Array.isArray(exclude)) { + for (let i = 0; i < exclude.length; i++) { + state.ignoredRules.add(exclude[i]); + } + } + + return plugins.map((plugin) => installPlugin(plugin)); +} + +/** + * @param {Deno.lint.Plugin} plugin */ -export function installPlugin(plugin) { +function installPlugin(plugin) { if (typeof plugin !== "object") { throw new Error("Linter plugin must be an object"); } if (typeof plugin.name !== "string") { throw new Error("Linter plugin name must be a string"); } + if (!/^[a-z-]+$/.test(plugin.name)) { + throw new Error( + "Linter plugin name must only contain lowercase letters (a-z) or hyphens (-).", + ); + } + if (plugin.name.startsWith("-") || plugin.name.endsWith("-")) { + throw new Error( + "Linter plugin name must start and end with a lowercase letter.", + ); + } + if (plugin.name.includes("--")) { + throw new Error( + "Linter plugin name must not have consequtive hyphens.", + ); + } if (typeof plugin.rules !== "object") { throw new Error("Linter plugin rules must be an object"); } @@ -123,6 +299,11 @@ export function installPlugin(plugin) { } state.plugins.push(plugin); state.installedPlugins.add(plugin.name); + + return { + name: plugin.name, + ruleNames: Object.keys(plugin.rules), + }; } /** @@ -285,7 +466,7 @@ function readType(buf, idx) { /** * @param {AstContext} ctx * @param {number} idx - * @returns {Node["range"]} + * @returns {Deno.lint.Node["range"]} */ function readSpan(ctx, idx) { let offset = ctx.spansOffset + (idx * SPAN_SIZE); @@ -765,6 +946,12 @@ export function runPluginsForFile(fileName, serializedAst) { for (const name of Object.keys(plugin.rules)) { const rule = plugin.rules[name]; const id = `${plugin.name}/${name}`; + + // Check if this rule is excluded + if (state.ignoredRules.has(id)) { + continue; + } + const ctx = new Context(id, fileName); const visitor = rule.create(ctx); @@ -852,10 +1039,11 @@ export function runPluginsForFile(fileName, serializedAst) { visitors.push({ info, matcher }); } + const token = new CancellationToken(); // Traverse ast with all visitors at the same time to avoid traversing // multiple times. try { - traverse(ctx, visitors, ctx.rootOffset); + traverse(ctx, visitors, ctx.rootOffset, token); } finally { ctx.nodes.clear(); @@ -870,9 +1058,11 @@ export function runPluginsForFile(fileName, serializedAst) { * @param {AstContext} ctx * @param {CompiledVisitor[]} visitors * @param {number} idx + * @param {CancellationToken} cancellationToken */ -function traverse(ctx, visitors, idx) { +function traverse(ctx, visitors, idx, cancellationToken) { if (idx === AST_IDX_INVALID) return; + if (cancellationToken.isCancellationRequested()) return; const { buf } = ctx; const nodeType = readType(ctx.buf, idx); @@ -905,12 +1095,12 @@ function traverse(ctx, visitors, idx) { try { const childIdx = readChild(buf, idx); if (childIdx > AST_IDX_INVALID) { - traverse(ctx, visitors, childIdx); + traverse(ctx, visitors, childIdx, cancellationToken); } const nextIdx = readNext(buf, idx); if (nextIdx > AST_IDX_INVALID) { - traverse(ctx, visitors, nextIdx); + traverse(ctx, visitors, nextIdx, cancellationToken); } } finally { if (exits !== null) { @@ -1064,8 +1254,12 @@ function _dump(ctx) { } } -// TODO(bartlomieju): this is temporary, until we get plugins plumbed through -// the CLI linter +// These are captured by Rust and called when plugins need to be loaded +// or run. +internals.installPlugins = installPlugins; +internals.runPluginsForFile = runPluginsForFile; +internals.resetState = resetState; + /** * @param {LintPlugin} plugin * @param {string} fileName @@ -1074,16 +1268,25 @@ function _dump(ctx) { function runLintPlugin(plugin, fileName, sourceText) { installPlugin(plugin); + const diagnostics = []; + doReport = (id, message, hint, start, end, fix) => { + diagnostics.push({ + id, + message, + hint, + range: [start, end], + fix, + }); + }; try { const serializedAst = op_lint_create_serialized_ast(fileName, sourceText); runPluginsForFile(fileName, serializedAst); } finally { - // During testing we don't want to keep plugins around - state.installedPlugins.clear(); + resetState(); } + doReport = op_lint_report; + return diagnostics; } -// TODO(bartlomieju): this is temporary, until we get plugins plumbed through -// the CLI linter -internals.runLintPlugin = runLintPlugin; +Deno.lint.runPlugin = runLintPlugin; diff --git a/cli/js/40_lint_types.d.ts b/cli/js/40_lint_types.d.ts index f07d16581e8e49..662cfc930f7889 100644 --- a/cli/js/40_lint_types.d.ts +++ b/cli/js/40_lint_types.d.ts @@ -1,17 +1,11 @@ // Copyright 2018-2025 the Deno authors. MIT license. -export interface NodeFacade { - type: string; - range: [number, number]; - [key: string]: unknown; -} - export interface AstContext { buf: Uint8Array; strTable: Map; strTableOffset: number; rootOffset: number; - nodes: Map; + nodes: Map; spansOffset: number; propsOffset: number; strByType: number[]; @@ -21,32 +15,11 @@ export interface AstContext { matcher: MatchContext; } -export interface Node { - range: Range; -} - -export type Range = [number, number]; - -// TODO(@marvinhagemeister) Remove once we land "official" types -export interface RuleContext { - id: string; -} - -// TODO(@marvinhagemeister) Remove once we land "official" types -export interface LintRule { - create(ctx: RuleContext): Record void>; - destroy?(ctx: RuleContext): void; -} - -// TODO(@marvinhagemeister) Remove once we land "official" types -export interface LintPlugin { - name: string; - rules: Record; -} - export interface LintState { - plugins: LintPlugin[]; + plugins: Deno.lint.Plugin[]; installedPlugins: Set; + /** format: `/` */ + ignoredRules: Set; } export type VisitorFn = (node: unknown) => void; diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs index fd7337df263dc8..16a815e08ff7bb 100644 --- a/cli/lsp/analysis.rs +++ b/cli/lsp/analysis.rs @@ -38,6 +38,7 @@ use node_resolver::ResolutionMode; use once_cell::sync::Lazy; use regex::Regex; use text_lines::LineAndColumnIndex; +use tokio_util::sync::CancellationToken; use tower_lsp::lsp_types as lsp; use tower_lsp::lsp_types::Position; use tower_lsp::lsp_types::Range; @@ -186,8 +187,9 @@ fn as_lsp_range( pub fn get_lint_references( parsed_source: &deno_ast::ParsedSource, linter: &CliLinter, + token: CancellationToken, ) -> Result, AnyError> { - let lint_diagnostics = linter.lint_with_ast(parsed_source); + let lint_diagnostics = linter.lint_with_ast(parsed_source, token)?; Ok( lint_diagnostics diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index e4570031fb7884..b76c54c7ed6b5f 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -1629,14 +1629,46 @@ impl ConfigData { sloppy_imports_resolver.clone(), Some(resolver.clone()), ); + + let lint_options = LintOptions::resolve( + member_dir.dir_path(), + (*lint_config).clone(), + &LintFlags::default(), + ) + .inspect_err(|err| lsp_warn!(" Failed to resolve linter options: {}", err)) + .ok() + .unwrap_or_default(); + let mut plugin_runner = None; + if !lint_options.plugins.is_empty() { + fn logger_printer(msg: &str, _is_err: bool) { + lsp_log!("pluggin runner - {}", msg); + } + let logger = crate::tools::lint::PluginLogger::new(logger_printer); + let plugin_load_result = + crate::tools::lint::create_runner_and_load_plugins( + lint_options.plugins.clone(), + logger, + lint_options.rules.exclude.clone(), + ) + .await; + match plugin_load_result { + Ok(runner) => { + plugin_runner = Some(Arc::new(runner)); + } + Err(err) => { + lsp_warn!("Failed to load lint plugins: {}", err); + } + } + } + let linter = Arc::new(CliLinter::new(CliLinterOptions { configured_rules: lint_rule_provider.resolve_lint_rules( - LintOptions::resolve((*lint_config).clone(), &LintFlags::default()) - .rules, + lint_options.rules, member_dir.maybe_deno_json().map(|c| c.as_ref()), ), fix: false, deno_lint_config, + maybe_plugin_runner: plugin_runner, })); ConfigData { diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index dee672d17a73a4..7283f2cf8f684a 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -1021,6 +1021,8 @@ fn generate_lint_diagnostics( default_jsx_factory: None, default_jsx_fragment_factory: None, }, + // TODO(bartlomieju): handle linter plugins here before landing + maybe_plugin_runner: None, })), ) }); @@ -1032,6 +1034,7 @@ fn generate_lint_diagnostics( &document, &lint_config, &linter, + token.clone(), ), }, }); @@ -1043,6 +1046,7 @@ fn generate_document_lint_diagnostics( document: &Document, lint_config: &LintConfig, linter: &CliLinter, + token: CancellationToken, ) -> Vec { if !lint_config.files.matches_specifier(document.specifier()) { return Vec::new(); @@ -1050,7 +1054,7 @@ fn generate_document_lint_diagnostics( match document.maybe_parsed_source() { Some(Ok(parsed_source)) => { if let Ok(references) = - analysis::get_lint_references(parsed_source, linter) + analysis::get_lint_references(parsed_source, linter, token) { references .into_iter() diff --git a/cli/ops/lint.rs b/cli/ops/lint.rs index c13cb21a53d43f..820a64db43e670 100644 --- a/cli/ops/lint.rs +++ b/cli/ops/lint.rs @@ -3,11 +3,187 @@ use deno_ast::MediaType; use deno_ast::ModuleSpecifier; use deno_ast::ParseDiagnostic; +use deno_ast::SourceRange; +use deno_ast::SourceTextInfo; +use deno_ast::SourceTextProvider; use deno_core::op2; +use deno_core::OpState; +use deno_lint::diagnostic::LintDiagnostic; +use deno_lint::diagnostic::LintDiagnosticDetails; +use deno_lint::diagnostic::LintDiagnosticRange; +use deno_lint::diagnostic::LintFix; +use deno_lint::diagnostic::LintFixChange; +use tokio_util::sync::CancellationToken; use crate::tools::lint; +use crate::tools::lint::PluginLogger; +use crate::util::text_encoding::Utf16Map; -deno_core::extension!(deno_lint, ops = [op_lint_create_serialized_ast,],); +deno_core::extension!( + deno_lint_ext, + ops = [ + op_lint_create_serialized_ast, + op_lint_report, + op_lint_get_source, + op_is_cancelled + ], + options = { + logger: PluginLogger, + }, + // TODO(bartlomieju): this should only be done, + // if not in the "test worker". + middleware = |op| match op.name { + "op_print" => op_print(), + _ => op, + }, + state = |state, options| { + state.put(options.logger); + state.put(LintPluginContainer::default()); + }, +); + +deno_core::extension!( + deno_lint_ext_for_test, + ops = [op_lint_create_serialized_ast, op_is_cancelled], + state = |state| { + state.put(LintPluginContainer::default()); + }, +); + +#[derive(Default)] +pub struct LintPluginContainer { + pub diagnostics: Vec, + pub source_text_info: Option, + pub utf_16_map: Option, + pub specifier: Option, + pub token: CancellationToken, +} + +impl LintPluginContainer { + pub fn set_cancellation_token( + &mut self, + maybe_token: Option, + ) { + let token = maybe_token.unwrap_or_default(); + self.token = token; + } + + pub fn set_info_for_file( + &mut self, + specifier: ModuleSpecifier, + source_text_info: SourceTextInfo, + utf16_map: Utf16Map, + ) { + self.specifier = Some(specifier); + self.utf_16_map = Some(utf16_map); + self.source_text_info = Some(source_text_info); + } + + fn report( + &mut self, + id: String, + message: String, + hint: Option, + start_utf16: usize, + end_utf16: usize, + fix: Option, + ) -> Result<(), LintReportError> { + fn out_of_range_err( + map: &Utf16Map, + start_utf16: usize, + end_utf16: usize, + ) -> LintReportError { + LintReportError::IncorrectRange { + start: start_utf16, + end: end_utf16, + source_end: map.text_content_length_utf16().into(), + } + } + + fn utf16_to_utf8_range( + utf16_map: &Utf16Map, + source_text_info: &SourceTextInfo, + start_utf16: usize, + end_utf16: usize, + ) -> Result { + let Some(start) = + utf16_map.utf16_to_utf8_offset((start_utf16 as u32).into()) + else { + return Err(out_of_range_err(utf16_map, start_utf16, end_utf16)); + }; + let Some(end) = utf16_map.utf16_to_utf8_offset((end_utf16 as u32).into()) + else { + return Err(out_of_range_err(utf16_map, start_utf16, end_utf16)); + }; + let start_pos = source_text_info.start_pos(); + Ok(SourceRange::new( + start_pos + start.into(), + start_pos + end.into(), + )) + } + + let source_text_info = self.source_text_info.as_ref().unwrap(); + let utf16_map = self.utf_16_map.as_ref().unwrap(); + let specifier = self.specifier.clone().unwrap(); + let diagnostic_range = + utf16_to_utf8_range(utf16_map, source_text_info, start_utf16, end_utf16)?; + let range = LintDiagnosticRange { + range: diagnostic_range, + description: None, + text_info: source_text_info.clone(), + }; + + let mut fixes: Vec = vec![]; + + if let Some(fix) = fix { + let fix_range = utf16_to_utf8_range( + utf16_map, + source_text_info, + fix.range.0, + fix.range.1, + )?; + fixes.push(LintFix { + changes: vec![LintFixChange { + new_text: fix.text.into(), + range: fix_range, + }], + description: format!("Fix this {} problem", id).into(), + }); + } + + let lint_diagnostic = LintDiagnostic { + specifier, + range: Some(range), + details: LintDiagnosticDetails { + message, + code: id, + hint, + fixes, + custom_docs_url: None, + info: vec![], + }, + }; + self.diagnostics.push(lint_diagnostic); + Ok(()) + } +} + +#[op2(fast)] +pub fn op_print(state: &mut OpState, #[string] msg: &str, is_err: bool) { + let logger = state.borrow::(); + + if is_err { + logger.error(msg); + } else { + logger.log(msg); + } +} + +#[op2(fast)] +fn op_is_cancelled(state: &mut OpState) -> bool { + let container = state.borrow::(); + container.token.is_cancelled() +} #[derive(Debug, thiserror::Error, deno_error::JsError)] pub enum LintError { @@ -41,5 +217,50 @@ fn op_lint_create_serialized_ast( scope_analysis: false, maybe_syntax: None, })?; - Ok(lint::serialize_ast_to_buffer(&parsed_source)) + let utf16_map = Utf16Map::new(parsed_source.text().as_ref()); + Ok(lint::serialize_ast_to_buffer(&parsed_source, &utf16_map)) +} + +#[derive(serde::Deserialize)] +struct LintReportFix { + text: String, + range: (usize, usize), +} + +#[derive(Debug, thiserror::Error, deno_error::JsError)] +pub enum LintReportError { + #[class(type)] + #[error("Invalid range [{start}, {end}], the source has a range of [0, {source_end}]")] + IncorrectRange { + start: usize, + end: usize, + source_end: u32, + }, +} + +#[op2] +fn op_lint_report( + state: &mut OpState, + #[string] id: String, + #[string] message: String, + #[string] hint: Option, + #[smi] start_utf16: usize, + #[smi] end_utf16: usize, + #[serde] fix: Option, +) -> Result<(), LintReportError> { + let container = state.borrow_mut::(); + container.report(id, message, hint, start_utf16, end_utf16, fix)?; + Ok(()) +} + +#[op2] +#[string] +fn op_lint_get_source(state: &mut OpState) -> String { + let container = state.borrow_mut::(); + container + .source_text_info + .as_ref() + .unwrap() + .text_str() + .to_string() } diff --git a/cli/schemas/lint-rules.v1.json b/cli/schemas/lint-rules.v1.json index 87bd4e26003ac9..90c1230b410602 100644 --- a/cli/schemas/lint-rules.v1.json +++ b/cli/schemas/lint-rules.v1.json @@ -1,127 +1,135 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "enum": [ - "adjacent-overload-signatures", - "ban-ts-comment", - "ban-types", - "ban-unknown-rule-code", - "ban-untagged-ignore", - "ban-untagged-todo", - "ban-unused-ignore", - "camelcase", - "constructor-super", - "default-param-last", - "eqeqeq", - "explicit-function-return-type", - "explicit-module-boundary-types", - "for-direction", - "fresh-handler-export", - "fresh-server-event-handlers", - "getter-return", - "guard-for-in", - "jsx-boolean-value", - "jsx-button-has-type", - "jsx-curly-braces", - "jsx-key", - "jsx-no-children-prop", - "jsx-no-comment-text-nodes", - "jsx-no-duplicate-props", - "jsx-no-unescaped-entities", - "jsx-no-useless-fragment", - "jsx-props-no-spread-multi", - "jsx-void-dom-elements-no-children", - "no-array-constructor", - "no-async-promise-executor", - "no-await-in-loop", - "no-await-in-sync-fn", - "no-boolean-literal-for-arguments", - "no-case-declarations", - "no-class-assign", - "no-compare-neg-zero", - "no-cond-assign", - "no-console", - "no-const-assign", - "no-constant-condition", - "no-control-regex", - "no-debugger", - "no-delete-var", - "no-deprecated-deno-api", - "no-dupe-args", - "no-dupe-class-members", - "no-dupe-else-if", - "no-dupe-keys", - "no-duplicate-case", - "no-empty", - "no-empty-character-class", - "no-empty-enum", - "no-empty-interface", - "no-empty-pattern", - "no-eval", - "no-ex-assign", - "no-explicit-any", - "no-external-import", - "no-extra-boolean-cast", - "no-extra-non-null-assertion", - "no-fallthrough", - "no-func-assign", - "no-global-assign", - "no-implicit-declare-namespace-export", - "no-import-assertions", - "no-import-assign", - "no-inferrable-types", - "no-inner-declarations", - "no-invalid-regexp", - "no-invalid-triple-slash-reference", - "no-irregular-whitespace", - "no-misused-new", - "no-namespace", - "no-new-symbol", - "no-node-globals", - "no-non-null-asserted-optional-chain", - "no-non-null-assertion", - "no-obj-calls", - "no-octal", - "no-process-global", - "no-prototype-builtins", - "no-redeclare", - "no-regex-spaces", - "no-self-assign", - "no-self-compare", - "no-setter-return", - "no-shadow-restricted-names", - "no-sloppy-imports", - "no-slow-types", - "no-sparse-arrays", - "no-sync-fn-in-async-fn", - "no-this-alias", - "no-this-before-super", - "no-throw-literal", - "no-top-level-await", - "no-undef", - "no-unreachable", - "no-unsafe-finally", - "no-unsafe-negation", - "no-unused-labels", - "no-unused-vars", - "no-useless-rename", - "no-var", - "no-window", - "no-window-prefix", - "no-with", - "prefer-as-const", - "prefer-ascii", - "prefer-const", - "prefer-namespace-keyword", - "prefer-primordials", - "react-no-danger", - "react-no-danger-with-children", - "react-rules-of-hooks", - "require-await", - "require-yield", - "single-var-declarator", - "triple-slash-reference", - "use-isnan", - "valid-typeof", - "verbatim-module-syntax" + "oneOf": [ + { + "type": "string", + "pattern": "^[a-z0-9-]+\\/[a-z0-9-]+$" + }, + { + "enum": [ + "adjacent-overload-signatures", + "ban-ts-comment", + "ban-types", + "ban-unknown-rule-code", + "ban-untagged-ignore", + "ban-untagged-todo", + "ban-unused-ignore", + "camelcase", + "constructor-super", + "default-param-last", + "eqeqeq", + "explicit-function-return-type", + "explicit-module-boundary-types", + "for-direction", + "fresh-handler-export", + "fresh-server-event-handlers", + "getter-return", + "guard-for-in", + "jsx-boolean-value", + "jsx-button-has-type", + "jsx-curly-braces", + "jsx-key", + "jsx-no-children-prop", + "jsx-no-comment-text-nodes", + "jsx-no-duplicate-props", + "jsx-no-unescaped-entities", + "jsx-no-useless-fragment", + "jsx-props-no-spread-multi", + "jsx-void-dom-elements-no-children", + "no-array-constructor", + "no-async-promise-executor", + "no-await-in-loop", + "no-await-in-sync-fn", + "no-boolean-literal-for-arguments", + "no-case-declarations", + "no-class-assign", + "no-compare-neg-zero", + "no-cond-assign", + "no-console", + "no-const-assign", + "no-constant-condition", + "no-control-regex", + "no-debugger", + "no-delete-var", + "no-deprecated-deno-api", + "no-dupe-args", + "no-dupe-class-members", + "no-dupe-else-if", + "no-dupe-keys", + "no-duplicate-case", + "no-empty", + "no-empty-character-class", + "no-empty-enum", + "no-empty-interface", + "no-empty-pattern", + "no-eval", + "no-ex-assign", + "no-explicit-any", + "no-external-import", + "no-extra-boolean-cast", + "no-extra-non-null-assertion", + "no-fallthrough", + "no-func-assign", + "no-global-assign", + "no-implicit-declare-namespace-export", + "no-import-assertions", + "no-import-assign", + "no-inferrable-types", + "no-inner-declarations", + "no-invalid-regexp", + "no-invalid-triple-slash-reference", + "no-irregular-whitespace", + "no-misused-new", + "no-namespace", + "no-new-symbol", + "no-node-globals", + "no-non-null-asserted-optional-chain", + "no-non-null-assertion", + "no-obj-calls", + "no-octal", + "no-process-global", + "no-prototype-builtins", + "no-redeclare", + "no-regex-spaces", + "no-self-assign", + "no-self-compare", + "no-setter-return", + "no-shadow-restricted-names", + "no-sloppy-imports", + "no-slow-types", + "no-sparse-arrays", + "no-sync-fn-in-async-fn", + "no-this-alias", + "no-this-before-super", + "no-throw-literal", + "no-top-level-await", + "no-undef", + "no-unreachable", + "no-unsafe-finally", + "no-unsafe-negation", + "no-unused-labels", + "no-unused-vars", + "no-useless-rename", + "no-var", + "no-window", + "no-window-prefix", + "no-with", + "prefer-as-const", + "prefer-ascii", + "prefer-const", + "prefer-namespace-keyword", + "prefer-primordials", + "react-no-danger", + "react-no-danger-with-children", + "react-rules-of-hooks", + "require-await", + "require-yield", + "single-var-declarator", + "triple-slash-reference", + "use-isnan", + "valid-typeof", + "verbatim-module-syntax" + ] + } ] } diff --git a/cli/tools/lint/ast_buffer/buffer.rs b/cli/tools/lint/ast_buffer/buffer.rs index a884ee24f9e535..b3e4926f241918 100644 --- a/cli/tools/lint/ast_buffer/buffer.rs +++ b/cli/tools/lint/ast_buffer/buffer.rs @@ -6,6 +6,8 @@ use deno_ast::swc::common::Span; use deno_ast::swc::common::DUMMY_SP; use indexmap::IndexMap; +use crate::util::text_encoding::Utf16Map; + /// Each property has this flag to mark what kind of value it holds- /// Plain objects and arrays are not supported yet, but could be easily /// added if needed. @@ -212,6 +214,15 @@ impl SerializeCtx { self.root_idx = idx; } + pub fn map_utf8_spans_to_utf16(&mut self, map: &Utf16Map) { + for value in &mut self.spans { + *value = map + .utf8_to_utf16_offset((*value).into()) + .unwrap_or_else(|| panic!("Failed converting '{value}' to utf16.")) + .into(); + } + } + /// Allocate a node's header fn field_header

(&mut self, prop: P, prop_flags: PropFlags) where @@ -274,7 +285,13 @@ impl SerializeCtx { where K: Into + Display + Clone, { - self.append_inner(kind, span.lo.0, span.hi.0) + let (start, end) = if *span == DUMMY_SP { + (0, 0) + } else { + // -1 is because swc stores spans 1-indexed + (span.lo.0 - 1, span.hi.0 - 1) + }; + self.append_inner(kind, start, end) } pub fn append_inner( diff --git a/cli/tools/lint/ast_buffer/mod.rs b/cli/tools/lint/ast_buffer/mod.rs index fc4045fb60cc8a..b5611af2288f1b 100644 --- a/cli/tools/lint/ast_buffer/mod.rs +++ b/cli/tools/lint/ast_buffer/mod.rs @@ -3,11 +3,16 @@ use deno_ast::ParsedSource; use swc::serialize_swc_to_buffer; +use crate::util::text_encoding::Utf16Map; + mod buffer; mod swc; mod ts_estree; -pub fn serialize_ast_to_buffer(parsed_source: &ParsedSource) -> Vec { +pub fn serialize_ast_to_buffer( + parsed_source: &ParsedSource, + utf16_map: &Utf16Map, +) -> Vec { // TODO: We could support multiple languages here - serialize_swc_to_buffer(parsed_source) + serialize_swc_to_buffer(parsed_source, utf16_map) } diff --git a/cli/tools/lint/ast_buffer/swc.rs b/cli/tools/lint/ast_buffer/swc.rs index 925d1bcd17c032..385035d023ea1c 100644 --- a/cli/tools/lint/ast_buffer/swc.rs +++ b/cli/tools/lint/ast_buffer/swc.rs @@ -93,8 +93,12 @@ use super::buffer::NodeRef; use super::ts_estree::AstNode; use super::ts_estree::TsEsTreeBuilder; use super::ts_estree::TsKeywordKind; +use crate::util::text_encoding::Utf16Map; -pub fn serialize_swc_to_buffer(parsed_source: &ParsedSource) -> Vec { +pub fn serialize_swc_to_buffer( + parsed_source: &ParsedSource, + utf16_map: &Utf16Map, +) -> Vec { let mut ctx = TsEsTreeBuilder::new(); let program = &parsed_source.program(); @@ -125,6 +129,7 @@ pub fn serialize_swc_to_buffer(parsed_source: &ParsedSource) -> Vec { } } + ctx.map_utf8_spans_to_utf16(utf16_map); ctx.serialize() } diff --git a/cli/tools/lint/ast_buffer/ts_estree.rs b/cli/tools/lint/ast_buffer/ts_estree.rs index 340f9f3225510f..f5e89a2bede37d 100644 --- a/cli/tools/lint/ast_buffer/ts_estree.rs +++ b/cli/tools/lint/ast_buffer/ts_estree.rs @@ -10,6 +10,7 @@ use deno_ast::view::TruePlusMinus; use super::buffer::AstBufSerializer; use super::buffer::NodeRef; use super::buffer::SerializeCtx; +use crate::util::text_encoding::Utf16Map; #[derive(Debug, Clone, PartialEq)] pub enum AstNode { @@ -488,6 +489,10 @@ impl TsEsTreeBuilder { } } + pub fn map_utf8_spans_to_utf16(&mut self, map: &Utf16Map) { + self.ctx.map_utf8_spans_to_utf16(map); + } + pub fn write_program( &mut self, span: &Span, diff --git a/cli/tools/lint/linter.rs b/cli/tools/lint/linter.rs index 5d6f8452744847..1b7b999594a13e 100644 --- a/cli/tools/lint/linter.rs +++ b/cli/tools/lint/linter.rs @@ -1,32 +1,45 @@ // Copyright 2018-2025 the Deno authors. MIT license. +use std::borrow::Cow; use std::collections::HashSet; use std::path::Path; +use std::path::PathBuf; +use std::sync::Arc; +use ::tokio_util::sync::CancellationToken; use deno_ast::MediaType; use deno_ast::ModuleSpecifier; use deno_ast::ParsedSource; use deno_ast::SourceTextInfo; use deno_core::anyhow::Context; use deno_core::error::AnyError; +use deno_core::futures::FutureExt as _; +use deno_core::parking_lot::Mutex; use deno_graph::ModuleGraph; use deno_lint::diagnostic::LintDiagnostic; +use deno_lint::linter::ExternalLinterCb; +use deno_lint::linter::ExternalLinterResult; use deno_lint::linter::LintConfig as DenoLintConfig; use deno_lint::linter::LintFileOptions; use deno_lint::linter::Linter as DenoLintLinter; use deno_lint::linter::LinterOptions; use deno_path_util::fs::atomic_write_file_with_retries; +use deno_runtime::tokio_util; +use super::plugins; +use super::plugins::PluginHostProxy; use super::rules::FileOrPackageLintRule; use super::rules::PackageLintRule; use super::ConfiguredRules; use crate::sys::CliSys; use crate::util::fs::specifier_from_file_path; +use crate::util::text_encoding::Utf16Map; pub struct CliLinterOptions { pub configured_rules: ConfiguredRules, pub fix: bool, pub deno_lint_config: DenoLintConfig, + pub maybe_plugin_runner: Option>, } #[derive(Debug)] @@ -35,6 +48,7 @@ pub struct CliLinter { package_rules: Vec>, linter: DenoLintLinter, deno_lint_config: DenoLintConfig, + maybe_plugin_runner: Option>, } impl CliLinter { @@ -62,6 +76,7 @@ impl CliLinter { custom_ignore_diagnostic_directive: None, }), deno_lint_config: options.deno_lint_config, + maybe_plugin_runner: options.maybe_plugin_runner, } } @@ -84,10 +99,22 @@ impl CliLinter { pub fn lint_with_ast( &self, parsed_source: &ParsedSource, - ) -> Vec { - self - .linter - .lint_with_ast(parsed_source, self.deno_lint_config.clone()) + token: CancellationToken, + ) -> Result, AnyError> { + let external_linter_container = ExternalLinterContainer::new( + self.maybe_plugin_runner.clone(), + Some(token), + ); + + let d = self.linter.lint_with_ast( + parsed_source, + self.deno_lint_config.clone(), + external_linter_container.get_callback(), + ); + if let Some(err) = external_linter_container.take_error() { + return Err(err); + } + Ok(d) } pub fn lint_file( @@ -105,18 +132,34 @@ impl CliLinter { MediaType::from_specifier(&specifier) }; + let external_linter_container = + ExternalLinterContainer::new(self.maybe_plugin_runner.clone(), None); + if self.fix { - self.lint_file_and_fix(&specifier, media_type, source_code, file_path) + self.lint_file_and_fix( + &specifier, + media_type, + source_code, + file_path, + external_linter_container, + ) } else { - self + let (source, diagnostics) = self .linter .lint_file(LintFileOptions { specifier, media_type, source_code, config: self.deno_lint_config.clone(), + external_linter: external_linter_container.get_callback(), }) - .map_err(AnyError::from) + .map_err(AnyError::from)?; + + if let Some(err) = external_linter_container.take_error() { + return Err(err); + } + + Ok((source, diagnostics)) } } @@ -126,6 +169,7 @@ impl CliLinter { media_type: MediaType, source_code: String, file_path: &Path, + external_linter_container: ExternalLinterContainer, ) -> Result<(ParsedSource, Vec), deno_core::anyhow::Error> { // initial lint let (source, diagnostics) = self.linter.lint_file(LintFileOptions { @@ -133,8 +177,13 @@ impl CliLinter { media_type, source_code, config: self.deno_lint_config.clone(), + external_linter: external_linter_container.get_callback(), })?; + if let Some(err) = external_linter_container.take_error() { + return Err(err); + } + // Try applying fixes repeatedly until the file has none left or // a maximum number of iterations is reached. This is necessary // because lint fixes may overlap and so we can't always apply @@ -148,8 +197,9 @@ impl CliLinter { media_type, &self.linter, self.deno_lint_config.clone(), - source.text_info_lazy(), + &source, &diagnostics, + &external_linter_container, )?; match change { Some(change) => { @@ -165,7 +215,7 @@ impl CliLinter { log::warn!( concat!( "Reached maximum number of fix iterations for '{}'. There's ", - "probably a bug in Deno. Please fix this file manually.", + "probably a bug in the lint rule. Please fix this file manually.", ), specifier, ); @@ -193,23 +243,81 @@ fn apply_lint_fixes_and_relint( media_type: MediaType, linter: &DenoLintLinter, config: DenoLintConfig, - text_info: &SourceTextInfo, + original_source: &ParsedSource, diagnostics: &[LintDiagnostic], + external_linter_container: &ExternalLinterContainer, ) -> Result)>, AnyError> { + let text_info = original_source.text_info_lazy(); let Some(new_text) = apply_lint_fixes(text_info, diagnostics) else { return Ok(None); }; - linter - .lint_file(LintFileOptions { + + let lint_with_text = |new_text: String| { + let (source, diagnostics) = linter.lint_file(LintFileOptions { specifier: specifier.clone(), source_code: new_text, media_type, - config, - }) - .map(Some) - .context( - "An applied lint fix caused a syntax error. Please report this bug.", - ) + config: config.clone(), + external_linter: external_linter_container.get_callback(), + })?; + let mut new_diagnostics = source.diagnostics().clone(); + new_diagnostics.retain(|d| !original_source.diagnostics().contains(d)); + if let Some(diagnostic) = new_diagnostics.pop() { + return Err(AnyError::from(diagnostic)); + } + Ok((source, diagnostics)) + }; + + let (source, diagnostics) = match lint_with_text(new_text) { + Ok(result) => result, + Err(err) => { + let utf16_map = Utf16Map::new(text_info.text_str()); + // figure out which diagnostic caused a syntax error + let mut diagnostics = diagnostics.to_vec(); + while let Some(last_diagnostic) = diagnostics.pop() { + let Some(lint_fix) = last_diagnostic.details.fixes.first() else { + continue; + }; + let success = match apply_lint_fixes(text_info, &diagnostics) { + Some(new_text) => lint_with_text(new_text).is_ok(), + None => true, + }; + if success { + let mut changes_text = String::new(); + for change in &lint_fix.changes { + let utf8_start = + (change.range.start - text_info.range().start) as u32; + let utf8_end = (change.range.end - text_info.range().start) as u32; + let utf16_start = utf16_map + .utf8_to_utf16_offset(utf8_start.into()) + .unwrap_or(utf8_start.into()); + let utf16_end = utf16_map + .utf8_to_utf16_offset(utf8_end.into()) + .unwrap_or(utf8_end.into()); + changes_text.push_str(&format!( + "Range: [{}, {}]\n", + u32::from(utf16_start), + u32::from(utf16_end) + )); + changes_text.push_str(&format!("Text: {:?}\n\n", &change.new_text)); + } + return Err(err).context(format!( + "The '{}' rule caused a syntax error applying '{}'.\n\n{}", + last_diagnostic.details.code, lint_fix.description, changes_text + )); + } + } + return Err(err).context( + "A lint fix caused a syntax error. This is a bug in a lint rule.", + ); + } + }; + + if let Some(err) = external_linter_container.take_error() { + return Err(err); + } + + Ok(Some((source, diagnostics))) } fn apply_lint_fixes( @@ -258,3 +366,94 @@ fn apply_lint_fixes( deno_ast::apply_text_changes(text_info.text_str(), quick_fixes); Some(new_text) } + +fn run_plugins( + plugin_runner: Arc, + parsed_source: ParsedSource, + file_path: PathBuf, + maybe_token: Option, +) -> Result { + let source_text_info = parsed_source.text_info_lazy().clone(); + let plugin_info = plugin_runner + .get_plugin_rules() + .into_iter() + .map(Cow::from) + .collect(); + + let fut = async move { + let utf16_map = Utf16Map::new(parsed_source.text().as_ref()); + let serialized_ast = + plugin_runner.serialize_ast(&parsed_source, &utf16_map)?; + + plugins::run_rules_for_ast( + &plugin_runner, + &file_path, + serialized_ast, + source_text_info, + utf16_map, + maybe_token, + ) + .await + } + .boxed_local(); + + let plugin_diagnostics = tokio_util::create_and_run_current_thread(fut)?; + + Ok(ExternalLinterResult { + diagnostics: plugin_diagnostics, + rules: plugin_info, + }) +} + +struct ExternalLinterContainer { + cb: Option, + error: Option>>>, +} + +impl ExternalLinterContainer { + pub fn new( + maybe_plugin_runner: Option>, + maybe_token: Option, + ) -> Self { + let mut s = Self { + cb: None, + error: None, + }; + if let Some(plugin_runner) = maybe_plugin_runner { + s.error = Some(Arc::new(Mutex::new(None))); + let error_ = s.error.clone(); + let cb = Arc::new(move |parsed_source: ParsedSource| { + let token_ = maybe_token.clone(); + let file_path = + match deno_path_util::url_to_file_path(parsed_source.specifier()) { + Ok(path) => path, + Err(err) => { + *error_.as_ref().unwrap().lock() = Some(err.into()); + return None; + } + }; + + let r = + run_plugins(plugin_runner.clone(), parsed_source, file_path, token_); + + match r { + Ok(d) => Some(d), + Err(err) => { + *error_.as_ref().unwrap().lock() = Some(err); + None + } + } + }); + s.cb = Some(cb); + } + s + } + + pub fn get_callback(&self) -> Option { + self.cb.clone() + } + + pub fn take_error(&self) -> Option { + self.error.as_ref().and_then(|e| e.lock().take()) + } +} diff --git a/cli/tools/lint/mod.rs b/cli/tools/lint/mod.rs index 49a5c6896bb081..74c46d4c189112 100644 --- a/cli/tools/lint/mod.rs +++ b/cli/tools/lint/mod.rs @@ -26,6 +26,7 @@ use deno_core::serde_json; use deno_core::unsync::future::LocalFutureExt; use deno_core::unsync::future::SharedLocal; use deno_graph::ModuleGraph; +use deno_lib::util::hash::FastInsecureHasher; use deno_lint::diagnostic::LintDiagnostic; use log::debug; use reporters::create_reporter; @@ -55,6 +56,7 @@ use crate::util::sync::AtomicFlag; mod ast_buffer; mod linter; +mod plugins; mod reporters; mod rules; @@ -62,6 +64,8 @@ mod rules; pub use ast_buffer::serialize_ast_to_buffer; pub use linter::CliLinter; pub use linter::CliLinterOptions; +pub use plugins::create_runner_and_load_plugins; +pub use plugins::PluginLogger; pub use rules::collect_no_slow_type_diagnostics; pub use rules::ConfiguredRules; pub use rules::LintRuleProvider; @@ -282,18 +286,52 @@ impl WorkspaceLinter { ) -> Result<(), AnyError> { self.file_count += paths.len(); + let exclude = lint_options.rules.exclude.clone(); + + let plugin_specifiers = lint_options.plugins.clone(); let lint_rules = self.lint_rule_provider.resolve_lint_rules_err_empty( lint_options.rules, member_dir.maybe_deno_json().map(|c| c.as_ref()), )?; - let maybe_incremental_cache = - lint_rules.incremental_cache_state().map(|state| { - Arc::new(IncrementalCache::new( - self.caches.lint_incremental_cache_db(), - CacheDBHash::from_hashable(&state), - &paths, - )) - }); + let mut maybe_incremental_cache = None; + + // TODO(bartlomieju): how do we decide if plugins support incremental cache? + if lint_rules.supports_incremental_cache() { + let mut hasher = FastInsecureHasher::new_deno_versioned(); + hasher.write_hashable(lint_rules.incremental_cache_state()); + if !plugin_specifiers.is_empty() { + hasher.write_hashable(&plugin_specifiers); + } + let state_hash = hasher.finish(); + + maybe_incremental_cache = Some(Arc::new(IncrementalCache::new( + self.caches.lint_incremental_cache_db(), + CacheDBHash::new(state_hash), + &paths, + ))); + } + + #[allow(clippy::print_stdout)] + #[allow(clippy::print_stderr)] + fn logger_printer(msg: &str, is_err: bool) { + if is_err { + eprint!("{}", msg); + } else { + print!("{}", msg); + } + } + + let mut plugin_runner = None; + if !plugin_specifiers.is_empty() { + let logger = plugins::PluginLogger::new(logger_printer); + let runner = plugins::create_runner_and_load_plugins( + plugin_specifiers, + logger, + exclude, + ) + .await?; + plugin_runner = Some(Arc::new(runner)); + } let linter = Arc::new(CliLinter::new(CliLinterOptions { configured_rules: lint_rules, @@ -301,6 +339,7 @@ impl WorkspaceLinter { deno_lint_config: self .tsconfig_resolver .deno_lint_config(member_dir.dir_url())?, + maybe_plugin_runner: plugin_runner, })); let has_error = self.has_error.clone(); @@ -543,7 +582,8 @@ fn lint_stdin( .to_lint_config(FilePatterns::new_with_base(start_dir.dir_path()))?; let deno_lint_config = tsconfig_resolver.deno_lint_config(start_dir.dir_url())?; - let lint_options = LintOptions::resolve(lint_config, &lint_flags); + let lint_options = + LintOptions::resolve(start_dir.dir_path(), lint_config, &lint_flags)?; let configured_rules = lint_rule_provider.resolve_lint_rules_err_empty( lint_options.rules, start_dir.maybe_deno_json().map(|c| c.as_ref()), @@ -561,6 +601,7 @@ fn lint_stdin( fix: false, configured_rules, deno_lint_config, + maybe_plugin_runner: None, }); let r = linter @@ -624,13 +665,24 @@ mod tests { use super::*; + #[derive(Serialize, Deserialize)] + struct RulesPattern { + r#type: String, + pattern: String, + } + + #[derive(Serialize, Deserialize)] + struct RulesEnum { + r#enum: Vec, + } + #[derive(Serialize, Deserialize)] struct RulesSchema { #[serde(rename = "$schema")] schema: String, - #[serde(rename = "enum")] - rules: Vec, + #[serde(rename = "oneOf")] + one_of: (RulesPattern, RulesEnum), } fn get_all_rules() -> Vec { @@ -661,25 +713,25 @@ mod tests { const UPDATE_ENV_VAR_NAME: &str = "UPDATE_EXPECTED"; + let rules_list = schema.one_of.1.r#enum; + if std::env::var(UPDATE_ENV_VAR_NAME).ok().is_none() { assert_eq!( - schema.rules, all_rules, + rules_list, all_rules, "Lint rules schema file not up to date. Run again with {}=1 to update the expected output", UPDATE_ENV_VAR_NAME ); return; } + let new_schema = RulesSchema { + schema: schema.schema, + one_of: (schema.one_of.0, RulesEnum { r#enum: all_rules }), + }; + std::fs::write( &rules_schema_path, - format!( - "{}\n", - serde_json::to_string_pretty(&RulesSchema { - schema: schema.schema, - rules: all_rules, - }) - .unwrap(), - ), + format!("{}\n", serde_json::to_string_pretty(&new_schema).unwrap(),), ) .unwrap(); } diff --git a/cli/tools/lint/plugins.rs b/cli/tools/lint/plugins.rs new file mode 100644 index 00000000000000..3d7acf4f242f04 --- /dev/null +++ b/cli/tools/lint/plugins.rs @@ -0,0 +1,543 @@ +// Copyright 2018-2025 the Deno authors. MIT license. + +use std::path::Path; +use std::path::PathBuf; +use std::rc::Rc; +use std::sync::Arc; + +use ::tokio_util::sync::CancellationToken; +use deno_ast::ModuleSpecifier; +use deno_ast::ParsedSource; +use deno_ast::SourceTextInfo; +use deno_core::anyhow::bail; +use deno_core::error::AnyError; +use deno_core::error::CoreError; +use deno_core::error::JsError; +use deno_core::futures::FutureExt; +use deno_core::parking_lot::Mutex; +use deno_core::resolve_url_or_path; +use deno_core::v8; +use deno_core::PollEventLoopOptions; +use deno_lint::diagnostic::LintDiagnostic; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; +use deno_runtime::tokio_util; +use deno_runtime::worker::MainWorker; +use deno_runtime::WorkerExecutionMode; +use tokio::sync::mpsc::channel; +use tokio::sync::mpsc::Receiver; +use tokio::sync::mpsc::Sender; + +use crate::args::DenoSubcommand; +use crate::args::Flags; +use crate::args::LintFlags; +use crate::factory::CliFactory; +use crate::ops::lint::LintPluginContainer; +use crate::tools::lint::serialize_ast_to_buffer; +use crate::util::text_encoding::Utf16Map; + +#[derive(Debug)] +pub enum PluginHostRequest { + LoadPlugins { + specifiers: Vec, + exclude_rules: Option>, + }, + Run { + serialized_ast: Vec, + file_path: PathBuf, + source_text_info: SourceTextInfo, + utf16_map: Utf16Map, + maybe_token: Option, + }, +} + +pub enum PluginHostResponse { + // TODO: write to structs + LoadPlugin(Result, AnyError>), + Run(Result, AnyError>), +} + +impl std::fmt::Debug for PluginHostResponse { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::LoadPlugin(_arg0) => f.debug_tuple("LoadPlugin").finish(), + Self::Run(_arg0) => f.debug_tuple("Run").finish(), + } + } +} + +#[derive(Clone, Debug)] +pub struct PluginLogger { + print: fn(&str, bool), +} + +impl PluginLogger { + pub fn new(print: fn(&str, bool)) -> Self { + Self { print } + } + + pub fn log(&self, msg: &str) { + (self.print)(msg, false); + } + + pub fn error(&self, msg: &str) { + (self.print)(msg, true); + } +} + +macro_rules! v8_static_strings { + ($($ident:ident = $str:literal),* $(,)?) => { + $( + pub static $ident: deno_core::FastStaticString = deno_core::ascii_str!($str); + )* + }; +} + +v8_static_strings! { + DEFAULT = "default", + INSTALL_PLUGINS = "installPlugins", + RUN_PLUGINS_FOR_FILE = "runPluginsForFile", +} + +#[derive(Debug)] +pub struct PluginHostProxy { + tx: Sender, + rx: Arc>>, + pub(crate) plugin_info: Arc>>, + #[allow(unused)] + join_handle: std::thread::JoinHandle>, +} + +impl PluginHostProxy { + pub fn get_plugin_rules(&self) -> Vec { + let infos = self.plugin_info.lock(); + + let mut all_names = vec![]; + + for info in infos.iter() { + all_names.extend_from_slice(&info.get_rules()); + } + + all_names + } +} + +pub struct PluginHost { + worker: MainWorker, + install_plugins_fn: Rc>, + run_plugins_for_file_fn: Rc>, + tx: Sender, + rx: Receiver, +} + +async fn create_plugin_runner_inner( + logger: PluginLogger, + rx_req: Receiver, + tx_res: Sender, +) -> Result { + let flags = Flags { + subcommand: DenoSubcommand::Lint(LintFlags::default()), + ..Default::default() + }; + let flags = Arc::new(flags); + let factory = CliFactory::from_flags(flags.clone()); + let cli_options = factory.cli_options()?; + let main_module = + resolve_url_or_path("./$deno$lint.mts", cli_options.initial_cwd()).unwrap(); + let perm_parser = factory.permission_desc_parser()?; + let permissions = Permissions::from_options( + perm_parser.as_ref(), + &cli_options.permissions_options(), + )?; + let permissions = PermissionsContainer::new(perm_parser.clone(), permissions); + // let npm_resolver = factory.npm_resolver().await?.clone(); + // let resolver = factory.resolver().await?.clone(); + let worker_factory = factory.create_cli_main_worker_factory().await?; + + let worker = worker_factory + .create_custom_worker( + // TODO(bartlomieju): add "lint" execution mode + WorkerExecutionMode::Run, + main_module.clone(), + permissions, + vec![crate::ops::lint::deno_lint_ext::init_ops(logger.clone())], + Default::default(), + ) + .await?; + + let mut worker = worker.into_main_worker(); + let runtime = &mut worker.js_runtime; + + let obj = runtime.execute_script("lint.js", "Deno[Deno.internal]")?; + + log::debug!("Lint plugins loaded, capturing default exports"); + let (install_plugins_fn, run_plugins_for_file_fn) = { + let scope = &mut runtime.handle_scope(); + let module_exports: v8::Local = + v8::Local::new(scope, obj).try_into().unwrap(); + + let install_plugins_fn_name = INSTALL_PLUGINS.v8_string(scope).unwrap(); + let install_plugins_fn_val = module_exports + .get(scope, install_plugins_fn_name.into()) + .unwrap(); + let install_plugins_fn: v8::Local = + install_plugins_fn_val.try_into().unwrap(); + + let run_plugins_for_file_fn_name = + RUN_PLUGINS_FOR_FILE.v8_string(scope).unwrap(); + let run_plugins_for_file_fn_val = module_exports + .get(scope, run_plugins_for_file_fn_name.into()) + .unwrap(); + let run_plugins_for_file_fn: v8::Local = + run_plugins_for_file_fn_val.try_into().unwrap(); + + ( + Rc::new(v8::Global::new(scope, install_plugins_fn)), + Rc::new(v8::Global::new(scope, run_plugins_for_file_fn)), + ) + }; + + Ok(PluginHost { + worker, + install_plugins_fn, + run_plugins_for_file_fn, + tx: tx_res, + rx: rx_req, + }) +} + +#[derive(Debug, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PluginInfo { + pub name: String, + pub rule_names: Vec, +} + +impl PluginInfo { + pub fn get_rules(&self) -> Vec { + let mut rules = Vec::with_capacity(self.rule_names.len()); + + for rule_name in &self.rule_names { + rules.push(format!("{}/{}", self.name, rule_name)); + } + + rules + } +} + +impl PluginHost { + fn create(logger: PluginLogger) -> Result { + let (tx_req, rx_req) = channel(10); + let (tx_res, rx_res) = channel(10); + + let logger_ = logger.clone(); + let join_handle = std::thread::spawn(move || { + let logger = logger_; + log::debug!("Lint PluginHost thread spawned"); + let start = std::time::Instant::now(); + let fut = async move { + let runner = + create_plugin_runner_inner(logger.clone(), rx_req, tx_res).await?; + log::debug!("Lint PlugibnHost running loop"); + runner.run_loop().await?; + log::debug!( + "Lint PluginHost thread finished, took {:?}", + std::time::Instant::now() - start + ); + Ok(()) + } + .boxed_local(); + tokio_util::create_and_run_current_thread(fut) + }); + + let proxy = PluginHostProxy { + tx: tx_req, + rx: Arc::new(tokio::sync::Mutex::new(rx_res)), + plugin_info: Arc::new(Mutex::new(vec![])), + join_handle, + }; + + Ok(proxy) + } + + async fn run_loop(mut self) -> Result<(), AnyError> { + log::debug!("Lint PluginHost is waiting for message"); + while let Some(req) = self.rx.recv().await { + log::debug!("Lint PluginHost has received a message"); + match req { + PluginHostRequest::LoadPlugins { + specifiers, + exclude_rules, + } => { + let r = self.load_plugins(specifiers, exclude_rules).await; + let _ = self.tx.send(PluginHostResponse::LoadPlugin(r)).await; + } + PluginHostRequest::Run { + serialized_ast, + file_path, + source_text_info, + utf16_map, + maybe_token, + } => { + let start = std::time::Instant::now(); + let r = match self.run_plugins( + &file_path, + serialized_ast, + source_text_info, + utf16_map, + maybe_token, + ) { + Ok(()) => Ok(self.take_diagnostics()), + Err(err) => Err(err), + }; + log::debug!( + "Running plugins lint rules took {:?}", + std::time::Instant::now() - start + ); + let _ = self.tx.send(PluginHostResponse::Run(r)).await; + } + } + } + log::debug!("Lint PluginHost run loop finished"); + Ok(()) + } + + fn take_diagnostics(&mut self) -> Vec { + let op_state = self.worker.js_runtime.op_state(); + let mut state = op_state.borrow_mut(); + let container = state.borrow_mut::(); + std::mem::take(&mut container.diagnostics) + } + + fn run_plugins( + &mut self, + file_path: &Path, + serialized_ast: Vec, + source_text_info: SourceTextInfo, + utf16_map: Utf16Map, + maybe_token: Option, + ) -> Result<(), AnyError> { + { + let state = self.worker.js_runtime.op_state(); + let mut state = state.borrow_mut(); + let container = state.borrow_mut::(); + container.set_info_for_file( + ModuleSpecifier::from_file_path(file_path).unwrap(), + source_text_info, + utf16_map, + ); + container.set_cancellation_token(maybe_token); + } + + let scope = &mut self.worker.js_runtime.handle_scope(); + let file_name_v8: v8::Local = + v8::String::new(scope, &file_path.display().to_string()) + .unwrap() + .into(); + + let store = v8::ArrayBuffer::new_backing_store_from_vec(serialized_ast); + let ast_buf = + v8::ArrayBuffer::with_backing_store(scope, &store.make_shared()); + let ast_bin_v8: v8::Local = + v8::Uint8Array::new(scope, ast_buf, 0, ast_buf.byte_length()) + .unwrap() + .into(); + let run_plugins_for_file = + v8::Local::new(scope, &*self.run_plugins_for_file_fn); + let undefined = v8::undefined(scope); + + let mut tc_scope = v8::TryCatch::new(scope); + let _run_plugins_result = run_plugins_for_file.call( + &mut tc_scope, + undefined.into(), + &[file_name_v8, ast_bin_v8], + ); + + if let Some(exception) = tc_scope.exception() { + let error = JsError::from_v8_exception(&mut tc_scope, exception); + let core_err = CoreError::Js(error); + return Err(core_err.into()); + } + drop(tc_scope); + Ok(()) + } + + async fn load_plugins( + &mut self, + plugin_specifiers: Vec, + exclude: Option>, + ) -> Result, AnyError> { + let mut load_futures = Vec::with_capacity(plugin_specifiers.len()); + for specifier in plugin_specifiers { + let mod_id = self + .worker + .js_runtime + .load_side_es_module(&specifier) + .await?; + let mod_future = + self.worker.js_runtime.mod_evaluate(mod_id).boxed_local(); + load_futures.push((mod_future, mod_id)); + } + + self + .worker + .js_runtime + .run_event_loop(PollEventLoopOptions::default()) + .await?; + + let mut plugin_handles = Vec::with_capacity(load_futures.len()); + + for (fut, mod_id) in load_futures { + fut.await?; + let module = self.worker.js_runtime.get_module_namespace(mod_id).unwrap(); + let scope = &mut self.worker.js_runtime.handle_scope(); + let module_local = v8::Local::new(scope, module); + let default_export_str = DEFAULT.v8_string(scope).unwrap(); + let default_export = + module_local.get(scope, default_export_str.into()).unwrap(); + let default_export_global = v8::Global::new(scope, default_export); + plugin_handles.push(default_export_global); + } + + let scope = &mut self.worker.js_runtime.handle_scope(); + let install_plugins_local = + v8::Local::new(scope, &*self.install_plugins_fn.clone()); + let exclude_v8: v8::Local = + exclude.map_or(v8::null(scope).into(), |v| { + let elems = v + .iter() + .map(|item| v8::String::new(scope, item).unwrap().into()) + .collect::>(); + + v8::Array::new_with_elements(scope, elems.as_slice()).into() + }); + + let undefined = v8::undefined(scope); + + let local_handles = { + let arr = v8::Array::new(scope, plugin_handles.len().try_into().unwrap()); + for (idx, plugin_handle) in plugin_handles.into_iter().enumerate() { + let handle = v8::Local::new(scope, plugin_handle); + arr + .set_index(scope, idx.try_into().unwrap(), handle) + .unwrap(); + } + arr + }; + let args = &[local_handles.into(), exclude_v8]; + + log::debug!("Installing lint plugins..."); + + let mut tc_scope = v8::TryCatch::new(scope); + let plugins_info_result = + install_plugins_local.call(&mut tc_scope, undefined.into(), args); + if let Some(exception) = tc_scope.exception() { + let error = JsError::from_v8_exception(&mut tc_scope, exception); + return Err(error.into()); + } + drop(tc_scope); + let plugins_info = plugins_info_result.unwrap(); + let infos: Vec = + deno_core::serde_v8::from_v8(scope, plugins_info)?; + log::debug!("Plugins installed: {}", infos.len()); + + Ok(infos) + } +} + +impl PluginHostProxy { + pub async fn load_plugins( + &self, + specifiers: Vec, + exclude_rules: Option>, + ) -> Result<(), AnyError> { + self + .tx + .send(PluginHostRequest::LoadPlugins { + specifiers, + exclude_rules, + }) + .await?; + let mut rx = self.rx.lock().await; + + if let Some(val) = rx.recv().await { + let PluginHostResponse::LoadPlugin(result) = val else { + unreachable!() + }; + let infos = result?; + *self.plugin_info.lock() = infos; + return Ok(()); + } + bail!("Plugin host has closed") + } + + pub async fn run_rules( + &self, + specifier: &Path, + serialized_ast: Vec, + source_text_info: SourceTextInfo, + utf16_map: Utf16Map, + maybe_token: Option, + ) -> Result, AnyError> { + self + .tx + .send(PluginHostRequest::Run { + serialized_ast, + file_path: specifier.to_path_buf(), + source_text_info, + utf16_map, + maybe_token, + }) + .await?; + let mut rx = self.rx.lock().await; + + if let Some(PluginHostResponse::Run(diagnostics_result)) = rx.recv().await { + return diagnostics_result; + } + bail!("Plugin host has closed") + } + + pub fn serialize_ast( + &self, + parsed_source: &ParsedSource, + utf16_map: &Utf16Map, + ) -> Result, AnyError> { + let start = std::time::Instant::now(); + let r = serialize_ast_to_buffer(parsed_source, utf16_map); + log::debug!( + "Serializing an AST took {:?}", + std::time::Instant::now() - start + ); + Ok(r) + } +} + +pub async fn create_runner_and_load_plugins( + plugin_specifiers: Vec, + logger: PluginLogger, + exclude: Option>, +) -> Result { + let host_proxy = PluginHost::create(logger)?; + host_proxy.load_plugins(plugin_specifiers, exclude).await?; + Ok(host_proxy) +} + +pub async fn run_rules_for_ast( + host_proxy: &PluginHostProxy, + specifier: &Path, + serialized_ast: Vec, + source_text_info: SourceTextInfo, + utf16_map: Utf16Map, + maybe_token: Option, +) -> Result, AnyError> { + let d = host_proxy + .run_rules( + specifier, + serialized_ast, + source_text_info, + utf16_map, + maybe_token, + ) + .await?; + Ok(d) +} diff --git a/cli/tools/lint/reporters.rs b/cli/tools/lint/reporters.rs index 24e04e840f7dcc..2aa50b6de81262 100644 --- a/cli/tools/lint/reporters.rs +++ b/cli/tools/lint/reporters.rs @@ -2,9 +2,11 @@ use deno_ast::diagnostics::Diagnostic; use deno_core::error::AnyError; +use deno_core::error::CoreError; use deno_core::serde_json; use deno_lint::diagnostic::LintDiagnostic; use deno_runtime::colors; +use deno_runtime::fmt_errors::format_js_error; use log::info; use serde::Serialize; @@ -53,7 +55,19 @@ impl LintReporter for PrettyLintReporter { fn visit_error(&mut self, file_path: &str, err: &AnyError) { log::error!("Error linting: {file_path}"); - log::error!(" {err}"); + let text = + if let Some(CoreError::Js(js_error)) = err.downcast_ref::() { + format_js_error(js_error) + } else { + format!("{err:#}") + }; + for line in text.split('\n') { + if line.is_empty() { + log::error!(""); + } else { + log::error!(" {}", line); + } + } } fn close(&mut self, check_count: usize) { diff --git a/cli/tools/lint/rules/mod.rs b/cli/tools/lint/rules/mod.rs index f8c65428aca6ad..9f2cee24fa9b21 100644 --- a/cli/tools/lint/rules/mod.rs +++ b/cli/tools/lint/rules/mod.rs @@ -122,16 +122,16 @@ impl CliLintRule { #[derive(Debug)] pub struct ConfiguredRules { - pub all_rule_codes: HashSet<&'static str>, + pub all_rule_codes: HashSet>, pub rules: Vec, } impl ConfiguredRules { - pub fn incremental_cache_state(&self) -> Option { - if self.rules.iter().any(|r| !r.supports_incremental_cache()) { - return None; - } + pub fn supports_incremental_cache(&self) -> bool { + self.rules.iter().all(|r| r.supports_incremental_cache()) + } + pub fn incremental_cache_state(&self) -> impl std::hash::Hash { // use a hash of the rule names in order to bust the cache let mut codes = self.rules.iter().map(|r| r.code()).collect::>(); // ensure this is stable by sorting it @@ -195,7 +195,7 @@ impl LintRuleProvider { let all_rules = self.all_rules(); let mut all_rule_names = HashSet::with_capacity(all_rules.len()); for rule in &all_rules { - all_rule_names.insert(rule.code()); + all_rule_names.insert(rule.code().into()); } let rules = filtered_rules( all_rules.into_iter(), diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index cb49a9de95817e..697f99aa175c3f 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -626,7 +626,7 @@ async fn configure_main_worker( permissions_container, vec![ ops::testing::deno_test::init_ops(worker_sender.sender), - ops::lint::deno_lint::init_ops(), + ops::lint::deno_lint_ext_for_test::init_ops(), ], Stdio { stdin: StdioPipe::inherit(), diff --git a/cli/tsc/dts/lib.deno.unstable.d.ts b/cli/tsc/dts/lib.deno.unstable.d.ts index 6c901b864c79fb..8113f75809db0d 100644 --- a/cli/tsc/dts/lib.deno.unstable.d.ts +++ b/cli/tsc/dts/lib.deno.unstable.d.ts @@ -1344,6 +1344,139 @@ declare namespace Deno { export {}; // only export exports } + /** + * @category Linter + * @experimental + */ + export namespace lint { + /** + * @category Linter + * @experimental + */ + export type Range = [number, number]; + + /** + * @category Linter + * @experimental + */ + export interface Node { + type: string; + range: Range; + [key: string]: unknown; + } + + /** + * @category Linter + * @experimental + */ + export interface FixData { + range: Range; + text?: string; + } + + /** + * @category Linter + * @experimental + */ + export interface Fixer { + insertTextAfter(node: Node, text: string): FixData; + insertTextAfterRange(range: Range, text: string): FixData; + insertTextBefore(node: Node, text: string): FixData; + insertTextBeforeRange(range: Range, text: string): FixData; + remove(node: Node): FixData; + removeRange(range: Range): FixData; + replaceText(node: Node, text: string): FixData; + replaceTextRange(range: Range, text: string): FixData; + } + + /** + * @category Linter + * @experimental + */ + export interface ReportData { + node?: Node; + range?: Range; + message: string; + hint?: string; + fix?(fixer: Fixer): FixData; + } + + /** + * @category Linter + * @experimental + */ + export interface RuleContext { + id: string; + report(data: ReportData): void; + } + + /** + * @category Linter + * @experimental + */ + export interface Rule { + create(ctx: RuleContext): Record void>; + destroy?(ctx: RuleContext): void; + } + + /** + * In your plugins file do something like + * + * ```ts + * export default { + * name: "my-plugin", + * rules: { + * "no-foo": { + * create(ctx) { + * return { + * VariableDeclaration(node) {} + * } + * } + * } + * } + * } satisfies Deno.lint.Plugin + * ``` + * @category Linter + * @experimental + */ + export interface Plugin { + name: string; + rules: Record; + } + + /** + * @category Linter + * @experimental + */ + export interface Fix { + range: Range; + text?: string; + } + + /** + * @category Linter + * @experimental + */ + export interface Diagnostic { + id: string; + message: string; + hint?: string; + range: Range; + fix?: Fix; + } + + /** + * This API is a noop in `deno run`... + * @category Linter + * @experimental + */ + export function runPlugin( + plugin: Plugin, + fileName: string, + source: string, + ): Diagnostic[]; + } + export {}; // only export exports } diff --git a/cli/util/text_encoding.rs b/cli/util/text_encoding.rs index 4449202384e6a3..3a8044e13bde36 100644 --- a/cli/util/text_encoding.rs +++ b/cli/util/text_encoding.rs @@ -230,6 +230,52 @@ impl Utf16Map { column_index: col.into(), } } + + /// Convert a UTF-16 byte offset to UTF-8 byte offset + pub fn utf16_to_utf8_offset( + &self, + utf16_offset: TextSize, + ) -> Option { + if utf16_offset > self.text_content_length_utf16() { + return None; + } + let pos = self.position_utf16(utf16_offset); + let line_start_utf8 = self.utf8_offsets[pos.line_index]; + let col_utf8 = + self.utf16_to_utf8_col(pos.line_index as u32, pos.column_index as u32); + Some(line_start_utf8 + col_utf8) + } + + /// Convert a UTF-8 byte offset to UTF-16 byte offset + pub fn utf8_to_utf16_offset( + &self, + utf8_offset: TextSize, + ) -> Option { + if utf8_offset > *self.utf8_offsets.last()? { + return None; + } + let line = partition_point(&self.utf8_offsets, |&it| it <= utf8_offset) - 1; + let line_start_utf8 = self.utf8_offsets[line]; + let col_utf8 = utf8_offset - line_start_utf8; + let col_utf16 = self.utf8_to_utf16_col(line as u32, col_utf8); + Some(self.utf16_offsets[line] + TextSize::from(col_utf16)) + } + + fn utf8_to_utf16_col(&self, line: u32, col: TextSize) -> u32 { + let mut utf16_col = u32::from(col); + + if let Some(utf16_chars) = self.utf16_lines.get(&line) { + for c in utf16_chars { + if col > c.start { + utf16_col -= u32::from(c.len()) - c.len_utf16() as u32; + } else { + break; + } + } + } + + utf16_col + } } fn partition_point(slice: &[T], mut predicate: P) -> usize @@ -490,4 +536,47 @@ const C: char = \"メ メ\"; assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15)); } + + #[test] + fn test_offset_out_of_range() { + let text = "hello"; + let map = Utf16Map::new(text); + assert_eq!(map.utf8_to_utf16_offset(TextSize::from(10)), None); + assert_eq!(map.utf16_to_utf8_offset(TextSize::from(10)), None); + } + + #[test] + fn test_offset_basic_ascii() { + let text = "hello\nworld"; + let map = Utf16Map::new(text); + + let utf8_offset = TextSize::from(7); + let utf16_offset = map.utf8_to_utf16_offset(utf8_offset).unwrap(); + assert_eq!(utf16_offset, TextSize::from(7)); + + let result = map.utf16_to_utf8_offset(utf16_offset).unwrap(); + assert_eq!(result, utf8_offset); + } + + #[test] + fn test_offset_emoji() { + let text = "hi 👋\nbye"; + let map = Utf16Map::new(text); + + let utf8_offset = TextSize::from(3); + let utf16_offset = map.utf8_to_utf16_offset(utf8_offset).unwrap(); + assert_eq!(utf16_offset, TextSize::from(3)); + + let utf8_offset_after = TextSize::from(7); + let utf16_offset_after = + map.utf8_to_utf16_offset(utf8_offset_after).unwrap(); + assert_eq!(utf16_offset_after, TextSize::from(5)); + + for (utf8_offset, _) in text.char_indices() { + let utf8_offset = TextSize::from(utf8_offset as u32); + let utf16_offset = map.utf8_to_utf16_offset(utf8_offset).unwrap(); + let reverse_ut8_offset = map.utf16_to_utf8_offset(utf16_offset).unwrap(); + assert_eq!(reverse_ut8_offset, utf8_offset); + } + } } diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 190de549d1bca0..5c7fab6aecec38 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -94,6 +94,7 @@ import { bootstrap as bootstrapOtel } from "ext:deno_telemetry/telemetry.ts"; if (Symbol.metadata) { throw "V8 supports Symbol.metadata now, no need to shim it"; } + ObjectDefineProperties(Symbol, { dispose: { __proto__: null, @@ -533,7 +534,10 @@ const NOT_IMPORTED_OPS = [ "op_base64_encode", // Used in the lint API + "op_lint_report", + "op_lint_get_source", "op_lint_create_serialized_ast", + "op_is_cancelled", // Related to `Deno.test()` API "op_test_event_step_result_failed", @@ -575,11 +579,14 @@ const finalDenoNs = { internal: internalSymbol, [internalSymbol]: internals, ...denoNs, - // Deno.test and Deno.bench are noops here, but kept for compatibility; so - // that they don't cause errors when used outside of `deno test`/`deno bench` + // Deno.test, Deno.bench, Deno.lint are noops here, but kept for compatibility; so + // that they don't cause errors when used outside of `deno test`/`deno bench`/`deno lint` // contexts. test: () => {}, bench: () => {}, + lint: { + runPlugin: () => {}, + }, }; ObjectDefineProperties(finalDenoNs, { diff --git a/tests/integration/js_unit_tests.rs b/tests/integration/js_unit_tests.rs index 9ecec8b426c844..4a61361837b576 100644 --- a/tests/integration/js_unit_tests.rs +++ b/tests/integration/js_unit_tests.rs @@ -165,10 +165,14 @@ fn js_unit_test(test: String) { let mut deno = deno .arg("-A") - .arg(util::tests_path().join("unit").join(format!("{test}.ts"))) - .piped_output() - .spawn() - .expect("failed to spawn script"); + .arg(util::tests_path().join("unit").join(format!("{test}.ts"))); + + // update the snapshots if when `UPDATE=1` + if std::env::var_os("UPDATE") == Some("1".into()) { + deno = deno.arg("--").arg("--update"); + } + + let mut deno = deno.piped_output().spawn().expect("failed to spawn script"); let now = Instant::now(); let stdout = deno.stdout.take().unwrap(); diff --git a/tests/specs/lint/lint_plugin/__test__.jsonc b/tests/specs/lint/lint_plugin/__test__.jsonc new file mode 100644 index 00000000000000..228923b2ac8c0f --- /dev/null +++ b/tests/specs/lint/lint_plugin/__test__.jsonc @@ -0,0 +1,17 @@ +{ + "steps": [ + { + "args": "lint a.ts", + "output": "lint.out", + "exitCode": 1 + }, + { + "args": "lint -c deno_exclude.json a.ts", + "output": "lint_exclude.out" + }, + { + "args": "lint --fix a.ts", + "output": "lint_fixed.out" + } + ] +} diff --git a/tests/specs/lint/lint_plugin/a.ts b/tests/specs/lint/lint_plugin/a.ts new file mode 100644 index 00000000000000..0366a968a76b74 --- /dev/null +++ b/tests/specs/lint/lint_plugin/a.ts @@ -0,0 +1 @@ +const _a = "foo"; diff --git a/tests/specs/lint/lint_plugin/deno.json b/tests/specs/lint/lint_plugin/deno.json new file mode 100644 index 00000000000000..57b9dcb3647975 --- /dev/null +++ b/tests/specs/lint/lint_plugin/deno.json @@ -0,0 +1,5 @@ +{ + "lint": { + "plugins": ["./plugin.ts"] + } +} diff --git a/tests/specs/lint/lint_plugin/deno_exclude.json b/tests/specs/lint/lint_plugin/deno_exclude.json new file mode 100644 index 00000000000000..cce33a873602fe --- /dev/null +++ b/tests/specs/lint/lint_plugin/deno_exclude.json @@ -0,0 +1,10 @@ +{ + "lint": { + "plugins": ["./plugin.ts"], + "rules": { + "exclude": [ + "test-plugin/my-rule" + ] + } + } +} diff --git a/tests/specs/lint/lint_plugin/lint.out b/tests/specs/lint/lint_plugin/lint.out new file mode 100644 index 00000000000000..56166426a7fb2b --- /dev/null +++ b/tests/specs/lint/lint_plugin/lint.out @@ -0,0 +1,2 @@ +[WILDCARD]Found 1 problem (1 fixable via --fix) +Checked 1 file diff --git a/tests/specs/lint/lint_plugin/lint_exclude.out b/tests/specs/lint/lint_plugin/lint_exclude.out new file mode 100644 index 00000000000000..c05ac45a1e7e51 --- /dev/null +++ b/tests/specs/lint/lint_plugin/lint_exclude.out @@ -0,0 +1 @@ +Checked 1 file diff --git a/tests/specs/lint/lint_plugin/lint_fixed.out b/tests/specs/lint/lint_plugin/lint_fixed.out new file mode 100644 index 00000000000000..c05ac45a1e7e51 --- /dev/null +++ b/tests/specs/lint/lint_plugin/lint_fixed.out @@ -0,0 +1 @@ +Checked 1 file diff --git a/tests/specs/lint/lint_plugin/plugin.ts b/tests/specs/lint/lint_plugin/plugin.ts new file mode 100644 index 00000000000000..0a54d73212438a --- /dev/null +++ b/tests/specs/lint/lint_plugin/plugin.ts @@ -0,0 +1,22 @@ +export default { + name: "test-plugin", + rules: { + "my-rule": { + create(context) { + return { + Identifier(node) { + if (node.name === "_a") { + context.report({ + node, + message: "should be _b", + fix(fixer) { + return fixer.replaceText(node, "_b"); + }, + }); + } + }, + }; + }, + }, + }, +}; diff --git a/tests/specs/lint/lint_plugin_fix_error/__test__.jsonc b/tests/specs/lint/lint_plugin_fix_error/__test__.jsonc new file mode 100644 index 00000000000000..57da106ff691fa --- /dev/null +++ b/tests/specs/lint/lint_plugin_fix_error/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "lint --fix", + "output": "fix.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/lint_plugin_fix_error/deno.json b/tests/specs/lint/lint_plugin_fix_error/deno.json new file mode 100644 index 00000000000000..57b9dcb3647975 --- /dev/null +++ b/tests/specs/lint/lint_plugin_fix_error/deno.json @@ -0,0 +1,5 @@ +{ + "lint": { + "plugins": ["./plugin.ts"] + } +} diff --git a/tests/specs/lint/lint_plugin_fix_error/fix.out b/tests/specs/lint/lint_plugin_fix_error/fix.out new file mode 100644 index 00000000000000..aed9d4df8abcf4 --- /dev/null +++ b/tests/specs/lint/lint_plugin_fix_error/fix.out @@ -0,0 +1,11 @@ +Error linting: [WILDLINE]main.ts + The 'test-plugin/my-rule' rule caused a syntax error applying 'Fix this test-plugin/my-rule problem'. + + Range: [14, 18] + Text: "garbage test test" + + : Expected a semicolon at file:///[WILDLINE]/main.ts:1:23 + + const value = garbage test test; + ~~~~ +Checked 2 files diff --git a/tests/specs/lint/lint_plugin_fix_error/main.ts b/tests/specs/lint/lint_plugin_fix_error/main.ts new file mode 100644 index 00000000000000..5a277eecbbcf4f --- /dev/null +++ b/tests/specs/lint/lint_plugin_fix_error/main.ts @@ -0,0 +1,2 @@ +const value = "𝄞"; +console.log(value); diff --git a/tests/specs/lint/lint_plugin_fix_error/plugin.ts b/tests/specs/lint/lint_plugin_fix_error/plugin.ts new file mode 100644 index 00000000000000..3df9f8655d869d --- /dev/null +++ b/tests/specs/lint/lint_plugin_fix_error/plugin.ts @@ -0,0 +1,20 @@ +export default { + name: "test-plugin", + rules: { + "my-rule": { + create(context) { + return { + VariableDeclarator(node) { + context.report({ + node: node.init, + message: 'should be equal to string "1"', + fix(fixer) { + return fixer.replaceText(node.init, "garbage test test"); + }, + }); + }, + }; + }, + }, + }, +}; diff --git a/tests/specs/lint/lint_plugin_infinite_edits/__test__.jsonc b/tests/specs/lint/lint_plugin_infinite_edits/__test__.jsonc new file mode 100644 index 00000000000000..57da106ff691fa --- /dev/null +++ b/tests/specs/lint/lint_plugin_infinite_edits/__test__.jsonc @@ -0,0 +1,6 @@ +{ + "tempDir": true, + "args": "lint --fix", + "output": "fix.out", + "exitCode": 1 +} diff --git a/tests/specs/lint/lint_plugin_infinite_edits/deno.json b/tests/specs/lint/lint_plugin_infinite_edits/deno.json new file mode 100644 index 00000000000000..57b9dcb3647975 --- /dev/null +++ b/tests/specs/lint/lint_plugin_infinite_edits/deno.json @@ -0,0 +1,5 @@ +{ + "lint": { + "plugins": ["./plugin.ts"] + } +} diff --git a/tests/specs/lint/lint_plugin_infinite_edits/fix.out b/tests/specs/lint/lint_plugin_infinite_edits/fix.out new file mode 100644 index 00000000000000..4dde757781a509 --- /dev/null +++ b/tests/specs/lint/lint_plugin_infinite_edits/fix.out @@ -0,0 +1,12 @@ +Reached maximum number of fix iterations for 'file:///[WILDLINE]/main.ts'. There's probably a bug in the lint rule. Please fix this file manually. +error[test-plugin/my-rule]: should be equal to string "1" + --> [WILDLINE]main.ts:1:15 + | +1 | const value = [WILDLINE]; + | [WILDLINE] + + docs: https://docs.deno.com/lint/rules/test-plugin/my-rule + + +Found 1 problem (1 fixable via --fix) +Checked 2 files diff --git a/tests/specs/lint/lint_plugin_infinite_edits/main.ts b/tests/specs/lint/lint_plugin_infinite_edits/main.ts new file mode 100644 index 00000000000000..5a277eecbbcf4f --- /dev/null +++ b/tests/specs/lint/lint_plugin_infinite_edits/main.ts @@ -0,0 +1,2 @@ +const value = "𝄞"; +console.log(value); diff --git a/tests/specs/lint/lint_plugin_infinite_edits/plugin.ts b/tests/specs/lint/lint_plugin_infinite_edits/plugin.ts new file mode 100644 index 00000000000000..5926fb868c1305 --- /dev/null +++ b/tests/specs/lint/lint_plugin_infinite_edits/plugin.ts @@ -0,0 +1,20 @@ +export default { + name: "test-plugin", + rules: { + "my-rule": { + create(context) { + return { + VariableDeclarator(node) { + context.report({ + node: node.init, + message: 'should be equal to string "1"', + fix(fixer) { + return fixer.replaceText(node.init, Date.now().toString()); + }, + }); + }, + }; + }, + }, + }, +}; diff --git a/tests/specs/lint/lint_plugin_utf16/__test__.jsonc b/tests/specs/lint/lint_plugin_utf16/__test__.jsonc new file mode 100644 index 00000000000000..e04db0eaf0483d --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/__test__.jsonc @@ -0,0 +1,22 @@ +{ + "tests": { + "lint": { + "args": "lint", + "output": "lint.out", + "exitCode": 1 + }, + "fix": { + "tempDir": true, + "steps": [{ + "args": "lint --fix", + "output": "fix.out" + }, { + "args": [ + "eval", + "console.log(Deno.readTextFileSync('main.ts').trim())" + ], + "output": "fixed.out" + }] + } + } +} diff --git a/tests/specs/lint/lint_plugin_utf16/deno.json b/tests/specs/lint/lint_plugin_utf16/deno.json new file mode 100644 index 00000000000000..57b9dcb3647975 --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/deno.json @@ -0,0 +1,5 @@ +{ + "lint": { + "plugins": ["./plugin.ts"] + } +} diff --git a/tests/specs/lint/lint_plugin_utf16/fix.out b/tests/specs/lint/lint_plugin_utf16/fix.out new file mode 100644 index 00000000000000..158c556c2968ff --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/fix.out @@ -0,0 +1 @@ +Checked 2 files diff --git a/tests/specs/lint/lint_plugin_utf16/fixed.out b/tests/specs/lint/lint_plugin_utf16/fixed.out new file mode 100644 index 00000000000000..46538595af2352 --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/fixed.out @@ -0,0 +1,2 @@ +const value = "1"; +console.log(value); diff --git a/tests/specs/lint/lint_plugin_utf16/lint.out b/tests/specs/lint/lint_plugin_utf16/lint.out new file mode 100644 index 00000000000000..cf78dcf9f3b31e --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/lint.out @@ -0,0 +1,11 @@ +error[test-plugin/my-rule]: should be equal to string "1" + --> [WILDLINE]main.ts:1:15 + | +1 | const value = "𝄞"; + | ^^^ + + docs: https://docs.deno.com/lint/rules/test-plugin/my-rule + + +Found 1 problem (1 fixable via --fix) +Checked 2 files diff --git a/tests/specs/lint/lint_plugin_utf16/main.ts b/tests/specs/lint/lint_plugin_utf16/main.ts new file mode 100644 index 00000000000000..5a277eecbbcf4f --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/main.ts @@ -0,0 +1,2 @@ +const value = "𝄞"; +console.log(value); diff --git a/tests/specs/lint/lint_plugin_utf16/plugin.ts b/tests/specs/lint/lint_plugin_utf16/plugin.ts new file mode 100644 index 00000000000000..40894f5e0e67dd --- /dev/null +++ b/tests/specs/lint/lint_plugin_utf16/plugin.ts @@ -0,0 +1,22 @@ +export default { + name: "test-plugin", + rules: { + "my-rule": { + create(context) { + return { + VariableDeclarator(node) { + if (node.init.type !== "Literal" || node.init.value !== "1") { + context.report({ + node: node.init, + message: 'should be equal to string "1"', + fix(fixer) { + return fixer.replaceText(node.init, '"1"'); + }, + }); + } + }, + }; + }, + }, + }, +}; diff --git a/tests/unit/__snapshots__/lint_plugin_test.ts.snap b/tests/unit/__snapshots__/lint_plugin_test.ts.snap index 337fcecc8f1e7d..d2a0d2aa8ce001 100644 --- a/tests/unit/__snapshots__/lint_plugin_test.ts.snap +++ b/tests/unit/__snapshots__/lint_plugin_test.ts.snap @@ -4,8 +4,8 @@ snapshot[`Plugin - Program 1`] = ` { body: [], range: [ - 1, - 1, + 0, + 0, ], sourceType: "script", type: "Program", @@ -17,13 +17,13 @@ snapshot[`Plugin - ImportDeclaration 1`] = ` attributes: [], importKind: "value", range: [ - 1, - 14, + 0, + 13, ], source: { range: [ - 8, - 13, + 7, + 12, ], raw: '"foo"', type: "Literal", @@ -39,13 +39,13 @@ snapshot[`Plugin - ImportDeclaration 2`] = ` attributes: [], importKind: "value", range: [ - 1, - 23, + 0, + 22, ], source: { range: [ - 17, - 22, + 16, + 21, ], raw: '"foo"', type: "Literal", @@ -57,15 +57,15 @@ snapshot[`Plugin - ImportDeclaration 2`] = ` name: "foo", optional: false, range: [ - 8, - 11, + 7, + 10, ], type: "Identifier", typeAnnotation: null, }, range: [ - 8, - 11, + 7, + 10, ], type: "ImportDefaultSpecifier", }, @@ -79,13 +79,13 @@ snapshot[`Plugin - ImportDeclaration 3`] = ` attributes: [], importKind: "value", range: [ - 1, - 28, + 0, + 27, ], source: { range: [ - 22, - 27, + 21, + 26, ], raw: '"foo"', type: "Literal", @@ -97,15 +97,15 @@ snapshot[`Plugin - ImportDeclaration 3`] = ` name: "foo", optional: false, range: [ - 13, - 16, + 12, + 15, ], type: "Identifier", typeAnnotation: null, }, range: [ - 8, - 16, + 7, + 15, ], type: "ImportNamespaceSpecifier", }, @@ -119,13 +119,13 @@ snapshot[`Plugin - ImportDeclaration 4`] = ` attributes: [], importKind: "value", range: [ - 1, - 39, + 0, + 38, ], source: { range: [ - 33, - 38, + 32, + 37, ], raw: '"foo"', type: "Literal", @@ -138,8 +138,8 @@ snapshot[`Plugin - ImportDeclaration 4`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, @@ -148,15 +148,15 @@ snapshot[`Plugin - ImportDeclaration 4`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 10, - 13, + 9, + 12, ], type: "ImportSpecifier", }, @@ -166,8 +166,8 @@ snapshot[`Plugin - ImportDeclaration 4`] = ` name: "bar", optional: false, range: [ - 15, - 18, + 14, + 17, ], type: "Identifier", typeAnnotation: null, @@ -176,15 +176,15 @@ snapshot[`Plugin - ImportDeclaration 4`] = ` name: "baz", optional: false, range: [ - 22, - 25, + 21, + 24, ], type: "Identifier", typeAnnotation: null, }, range: [ - 15, - 25, + 14, + 24, ], type: "ImportSpecifier", }, @@ -201,21 +201,21 @@ snapshot[`Plugin - ImportDeclaration 5`] = ` name: "type", optional: false, range: [ - 30, - 34, + 29, + 33, ], type: "Identifier", typeAnnotation: null, }, range: [ - 30, - 42, + 29, + 41, ], type: "ImportAttribute", value: { range: [ - 36, - 42, + 35, + 41, ], raw: '"json"', type: "Literal", @@ -225,13 +225,13 @@ snapshot[`Plugin - ImportDeclaration 5`] = ` ], importKind: "value", range: [ - 1, - 45, + 0, + 44, ], source: { range: [ - 17, - 22, + 16, + 21, ], raw: '"foo"', type: "Literal", @@ -243,15 +243,15 @@ snapshot[`Plugin - ImportDeclaration 5`] = ` name: "foo", optional: false, range: [ - 8, - 11, + 7, + 10, ], type: "Identifier", typeAnnotation: null, }, range: [ - 8, - 11, + 7, + 10, ], type: "ImportDefaultSpecifier", }, @@ -264,13 +264,13 @@ snapshot[`Plugin - ExportNamedDeclaration 1`] = ` { attributes: [], range: [ - 1, - 27, + 0, + 26, ], source: { range: [ - 21, - 26, + 20, + 25, ], raw: '"foo"', type: "Literal", @@ -283,8 +283,8 @@ snapshot[`Plugin - ExportNamedDeclaration 1`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, @@ -293,15 +293,15 @@ snapshot[`Plugin - ExportNamedDeclaration 1`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 10, - 13, + 9, + 12, ], type: "ExportSpecifier", }, @@ -314,13 +314,13 @@ snapshot[`Plugin - ExportNamedDeclaration 2`] = ` { attributes: [], range: [ - 1, - 34, + 0, + 33, ], source: { range: [ - 28, - 33, + 27, + 32, ], raw: '"foo"', type: "Literal", @@ -333,8 +333,8 @@ snapshot[`Plugin - ExportNamedDeclaration 2`] = ` name: "baz", optional: false, range: [ - 17, - 20, + 16, + 19, ], type: "Identifier", typeAnnotation: null, @@ -343,15 +343,15 @@ snapshot[`Plugin - ExportNamedDeclaration 2`] = ` name: "bar", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 10, - 20, + 9, + 19, ], type: "ExportSpecifier", }, @@ -368,21 +368,21 @@ snapshot[`Plugin - ExportNamedDeclaration 3`] = ` name: "type", optional: false, range: [ - 34, - 38, + 33, + 37, ], type: "Identifier", typeAnnotation: null, }, range: [ - 34, - 46, + 33, + 45, ], type: "ImportAttribute", value: { range: [ - 40, - 46, + 39, + 45, ], raw: '"json"', type: "Literal", @@ -391,13 +391,13 @@ snapshot[`Plugin - ExportNamedDeclaration 3`] = ` }, ], range: [ - 1, - 49, + 0, + 48, ], source: { range: [ - 21, - 26, + 20, + 25, ], raw: '"foo"', type: "Literal", @@ -410,8 +410,8 @@ snapshot[`Plugin - ExportNamedDeclaration 3`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, @@ -420,15 +420,15 @@ snapshot[`Plugin - ExportNamedDeclaration 3`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 10, - 13, + 9, + 12, ], type: "ExportSpecifier", }, @@ -444,8 +444,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 1`] = ` body: { body: [], range: [ - 31, - 33, + 30, + 32, ], type: "BlockStatement", }, @@ -455,16 +455,16 @@ snapshot[`Plugin - ExportDefaultDeclaration 1`] = ` name: "foo", optional: false, range: [ - 25, - 28, + 24, + 27, ], type: "Identifier", typeAnnotation: null, }, params: [], range: [ - 16, - 33, + 15, + 32, ], returnType: null, type: "FunctionDeclaration", @@ -472,8 +472,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 1`] = ` }, exportKind: "value", range: [ - 1, - 33, + 0, + 32, ], type: "ExportDefaultDeclaration", } @@ -486,8 +486,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 2`] = ` body: { body: [], range: [ - 28, - 30, + 27, + 29, ], type: "BlockStatement", }, @@ -496,8 +496,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 2`] = ` id: null, params: [], range: [ - 16, - 30, + 15, + 29, ], returnType: null, type: "FunctionDeclaration", @@ -505,8 +505,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 2`] = ` }, exportKind: "value", range: [ - 1, - 30, + 0, + 29, ], type: "ExportDefaultDeclaration", } @@ -519,8 +519,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 3`] = ` body: { body: [], range: [ - 16, - 28, + 15, + 27, ], type: "ClassBody", }, @@ -529,24 +529,24 @@ snapshot[`Plugin - ExportDefaultDeclaration 3`] = ` name: "Foo", optional: false, range: [ - 22, - 25, + 21, + 24, ], type: "Identifier", typeAnnotation: null, }, implements: [], range: [ - 16, - 28, + 15, + 27, ], superClass: null, type: "ClassDeclaration", }, exportKind: "value", range: [ - 1, - 28, + 0, + 27, ], type: "ExportDefaultDeclaration", } @@ -559,8 +559,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 4`] = ` body: { body: [], range: [ - 16, - 24, + 15, + 23, ], type: "ClassBody", }, @@ -568,16 +568,16 @@ snapshot[`Plugin - ExportDefaultDeclaration 4`] = ` id: null, implements: [], range: [ - 16, - 24, + 15, + 23, ], superClass: null, type: "ClassDeclaration", }, exportKind: "value", range: [ - 1, - 24, + 0, + 23, ], type: "ExportDefaultDeclaration", } @@ -589,16 +589,16 @@ snapshot[`Plugin - ExportDefaultDeclaration 5`] = ` name: "bar", optional: false, range: [ - 16, - 19, + 15, + 18, ], type: "Identifier", typeAnnotation: null, }, exportKind: "value", range: [ - 1, - 20, + 0, + 19, ], type: "ExportDefaultDeclaration", } @@ -610,8 +610,8 @@ snapshot[`Plugin - ExportDefaultDeclaration 6`] = ` body: { body: [], range: [ - 30, - 32, + 29, + 31, ], type: "TSInterfaceBody", }, @@ -621,23 +621,23 @@ snapshot[`Plugin - ExportDefaultDeclaration 6`] = ` name: "Foo", optional: false, range: [ - 26, - 29, + 25, + 28, ], type: "Identifier", typeAnnotation: null, }, range: [ - 16, - 32, + 15, + 31, ], type: "TSInterfaceDeclaration", typeParameters: [], }, exportKind: "type", range: [ - 1, - 32, + 0, + 31, ], type: "ExportDefaultDeclaration", } @@ -649,13 +649,13 @@ snapshot[`Plugin - ExportAllDeclaration 1`] = ` exportKind: "value", exported: null, range: [ - 1, - 21, + 0, + 20, ], source: { range: [ - 15, - 20, + 14, + 19, ], raw: '"foo"', type: "Literal", @@ -671,23 +671,23 @@ snapshot[`Plugin - ExportAllDeclaration 2`] = ` exportKind: "value", exported: { range: [ - 22, - 27, + 21, + 26, ], raw: '"foo"', type: "Literal", value: "foo", }, range: [ - 1, - 28, + 0, + 27, ], source: { name: "foo", optional: false, range: [ - 13, - 16, + 12, + 15, ], type: "Identifier", typeAnnotation: null, @@ -704,21 +704,21 @@ snapshot[`Plugin - ExportAllDeclaration 3`] = ` name: "type", optional: false, range: [ - 28, - 32, + 27, + 31, ], type: "Identifier", typeAnnotation: null, }, range: [ - 28, - 40, + 27, + 39, ], type: "ImportAttribute", value: { range: [ - 34, - 40, + 33, + 39, ], raw: '"json"', type: "Literal", @@ -729,13 +729,13 @@ snapshot[`Plugin - ExportAllDeclaration 3`] = ` exportKind: "value", exported: null, range: [ - 1, - 43, + 0, + 42, ], source: { range: [ - 15, - 20, + 14, + 19, ], raw: '"foo"', type: "Literal", @@ -751,15 +751,15 @@ snapshot[`Plugin - TSExportAssignment 1`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 14, + 0, + 13, ], type: "TSExportAssignment", } @@ -771,15 +771,15 @@ snapshot[`Plugin - TSNamespaceExportDeclaration 1`] = ` name: "A", optional: false, range: [ + 20, 21, - 22, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 23, + 0, + 22, ], type: "TSNamespaceExportDeclaration", } @@ -791,8 +791,8 @@ snapshot[`Plugin - TSImportEqualsDeclaration 1`] = ` name: "a", optional: false, range: [ + 7, 8, - 9, ], type: "Identifier", typeAnnotation: null, @@ -802,15 +802,15 @@ snapshot[`Plugin - TSImportEqualsDeclaration 1`] = ` name: "b", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 13, + 0, + 12, ], type: "TSImportEqualsDeclaration", } @@ -822,8 +822,8 @@ snapshot[`Plugin - TSImportEqualsDeclaration 2`] = ` name: "a", optional: false, range: [ + 7, 8, - 9, ], type: "Identifier", typeAnnotation: null, @@ -832,22 +832,22 @@ snapshot[`Plugin - TSImportEqualsDeclaration 2`] = ` moduleReference: { expression: { range: [ - 20, - 25, + 19, + 24, ], raw: '"foo"', type: "Literal", value: "foo", }, range: [ - 12, - 26, + 11, + 25, ], type: "TSExternalModuleReference", }, range: [ - 1, - 26, + 0, + 25, ], type: "TSImportEqualsDeclaration", } @@ -861,22 +861,22 @@ snapshot[`Plugin - BlockStatement 1`] = ` name: "foo", optional: false, range: [ - 3, - 6, + 2, + 5, ], type: "Identifier", typeAnnotation: null, }, range: [ - 3, - 7, + 2, + 6, ], type: "ExpressionStatement", }, ], range: [ - 1, - 9, + 0, + 8, ], type: "BlockStatement", } @@ -886,8 +886,8 @@ snapshot[`Plugin - BreakStatement 1`] = ` { label: null, range: [ - 15, - 21, + 14, + 20, ], type: "BreakStatement", } @@ -899,15 +899,15 @@ snapshot[`Plugin - BreakStatement 2`] = ` name: "foo", optional: false, range: [ - 26, - 29, + 25, + 28, ], type: "Identifier", typeAnnotation: null, }, range: [ - 20, - 30, + 19, + 29, ], type: "BreakStatement", } @@ -917,8 +917,8 @@ snapshot[`Plugin - ContinueStatement 1`] = ` { label: null, range: [ - 1, - 10, + 0, + 9, ], type: "ContinueStatement", } @@ -930,15 +930,15 @@ snapshot[`Plugin - ContinueStatement 2`] = ` name: "foo", optional: false, range: [ - 10, - 13, + 9, + 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 14, + 0, + 13, ], type: "ContinueStatement", } @@ -947,8 +947,8 @@ snapshot[`Plugin - ContinueStatement 2`] = ` snapshot[`Plugin - DebuggerStatement 1`] = ` { range: [ - 1, - 10, + 0, + 9, ], type: "DebuggerStatement", } @@ -959,21 +959,21 @@ snapshot[`Plugin - DoWhileStatement 1`] = ` body: { body: [], range: [ - 4, - 6, + 3, + 5, ], type: "BlockStatement", }, range: [ - 1, - 19, + 0, + 18, ], test: { name: "foo", optional: false, range: [ - 14, - 17, + 13, + 16, ], type: "Identifier", typeAnnotation: null, @@ -988,15 +988,15 @@ snapshot[`Plugin - ExpressionStatement 1`] = ` name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 5, + 0, + 4, ], type: "ExpressionStatement", } @@ -1007,8 +1007,8 @@ snapshot[`Plugin - ForInStatement 1`] = ` body: { body: [], range: [ - 14, - 16, + 13, + 15, ], type: "BlockStatement", }, @@ -1016,22 +1016,22 @@ snapshot[`Plugin - ForInStatement 1`] = ` name: "a", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 16, + 0, + 15, ], right: { name: "b", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, @@ -1046,8 +1046,8 @@ snapshot[`Plugin - ForOfStatement 1`] = ` body: { body: [], range: [ - 14, - 16, + 13, + 15, ], type: "BlockStatement", }, @@ -1055,22 +1055,22 @@ snapshot[`Plugin - ForOfStatement 1`] = ` name: "a", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 16, + 0, + 15, ], right: { name: "b", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, @@ -1085,8 +1085,8 @@ snapshot[`Plugin - ForOfStatement 2`] = ` body: { body: [], range: [ - 20, - 22, + 19, + 21, ], type: "BlockStatement", }, @@ -1094,22 +1094,22 @@ snapshot[`Plugin - ForOfStatement 2`] = ` name: "a", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 22, + 0, + 21, ], right: { name: "b", optional: false, range: [ + 16, 17, - 18, ], type: "Identifier", typeAnnotation: null, @@ -1123,15 +1123,15 @@ snapshot[`Plugin - ForStatement 1`] = ` body: { body: [], range: [ - 10, - 12, + 9, + 11, ], type: "BlockStatement", }, init: null, range: [ - 1, - 12, + 0, + 11, ], test: null, type: "ForStatement", @@ -1144,8 +1144,8 @@ snapshot[`Plugin - ForStatement 2`] = ` body: { body: [], range: [ - 15, - 17, + 14, + 16, ], type: "BlockStatement", }, @@ -1153,22 +1153,22 @@ snapshot[`Plugin - ForStatement 2`] = ` name: "a", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 17, + 0, + 16, ], test: { name: "b", optional: false, range: [ + 8, 9, - 10, ], type: "Identifier", typeAnnotation: null, @@ -1178,8 +1178,8 @@ snapshot[`Plugin - ForStatement 2`] = ` name: "c", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, @@ -1193,21 +1193,21 @@ snapshot[`Plugin - IfStatement 1`] = ` consequent: { body: [], range: [ - 10, - 12, + 9, + 11, ], type: "BlockStatement", }, range: [ - 1, - 12, + 0, + 11, ], test: { name: "foo", optional: false, range: [ - 5, - 8, + 4, + 7, ], type: "Identifier", typeAnnotation: null, @@ -1221,29 +1221,29 @@ snapshot[`Plugin - IfStatement 2`] = ` alternate: { body: [], range: [ - 18, - 20, + 17, + 19, ], type: "BlockStatement", }, consequent: { body: [], range: [ - 10, - 12, + 9, + 11, ], type: "BlockStatement", }, range: [ - 1, - 20, + 0, + 19, ], test: { name: "foo", optional: false, range: [ - 5, - 8, + 4, + 7, ], type: "Identifier", typeAnnotation: null, @@ -1257,8 +1257,8 @@ snapshot[`Plugin - LabeledStatement 1`] = ` body: { body: [], range: [ - 6, - 8, + 5, + 7, ], type: "BlockStatement", }, @@ -1266,15 +1266,15 @@ snapshot[`Plugin - LabeledStatement 1`] = ` name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 8, + 0, + 7, ], type: "LabeledStatement", } @@ -1284,8 +1284,8 @@ snapshot[`Plugin - ReturnStatement 1`] = ` { argument: null, range: [ - 1, - 7, + 0, + 6, ], type: "ReturnStatement", } @@ -1297,15 +1297,15 @@ snapshot[`Plugin - ReturnStatement 2`] = ` name: "foo", optional: false, range: [ - 8, - 11, + 7, + 10, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 12, + 0, + 11, ], type: "ReturnStatement", } @@ -1317,15 +1317,15 @@ snapshot[`Plugin - SwitchStatement 1`] = ` { consequent: [], range: [ - 22, - 31, + 21, + 30, ], test: { name: "foo", optional: false, range: [ - 27, - 30, + 26, + 29, ], type: "Identifier", typeAnnotation: null, @@ -1337,22 +1337,22 @@ snapshot[`Plugin - SwitchStatement 1`] = ` { label: null, range: [ - 56, - 62, + 55, + 61, ], type: "BreakStatement", }, ], range: [ - 38, - 62, + 37, + 61, ], test: { name: "bar", optional: false, range: [ - 43, - 46, + 42, + 45, ], type: "Identifier", typeAnnotation: null, @@ -1364,15 +1364,15 @@ snapshot[`Plugin - SwitchStatement 1`] = ` { body: [], range: [ - 86, - 88, + 85, + 87, ], type: "BlockStatement", }, ], range: [ - 69, - 88, + 68, + 87, ], test: null, type: "SwitchCase", @@ -1382,15 +1382,15 @@ snapshot[`Plugin - SwitchStatement 1`] = ` name: "foo", optional: false, range: [ - 9, - 12, + 8, + 11, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 94, + 0, + 93, ], type: "SwitchStatement", } @@ -1402,15 +1402,15 @@ snapshot[`Plugin - ThrowStatement 1`] = ` name: "foo", optional: false, range: [ - 7, - 10, + 6, + 9, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 11, + 0, + 10, ], type: "ThrowStatement", } @@ -1421,8 +1421,8 @@ snapshot[`Plugin - TryStatement 1`] = ` block: { body: [], range: [ - 5, - 7, + 4, + 6, ], type: "BlockStatement", }, @@ -1431,21 +1431,21 @@ snapshot[`Plugin - TryStatement 1`] = ` body: { body: [], range: [ - 14, - 16, + 13, + 15, ], type: "BlockStatement", }, param: null, range: [ - 8, - 16, + 7, + 15, ], type: "CatchClause", }, range: [ - 1, - 16, + 0, + 15, ], type: "TryStatement", } @@ -1456,8 +1456,8 @@ snapshot[`Plugin - TryStatement 2`] = ` block: { body: [], range: [ - 5, - 7, + 4, + 6, ], type: "BlockStatement", }, @@ -1466,8 +1466,8 @@ snapshot[`Plugin - TryStatement 2`] = ` body: { body: [], range: [ - 18, - 20, + 17, + 19, ], type: "BlockStatement", }, @@ -1475,21 +1475,21 @@ snapshot[`Plugin - TryStatement 2`] = ` name: "e", optional: false, range: [ + 14, 15, - 16, ], type: "Identifier", typeAnnotation: null, }, range: [ - 8, - 20, + 7, + 19, ], type: "CatchClause", }, range: [ - 1, - 20, + 0, + 19, ], type: "TryStatement", } @@ -1500,23 +1500,23 @@ snapshot[`Plugin - TryStatement 3`] = ` block: { body: [], range: [ - 5, - 7, + 4, + 6, ], type: "BlockStatement", }, finalizer: { body: [], range: [ - 16, - 18, + 15, + 17, ], type: "BlockStatement", }, handler: null, range: [ - 1, - 18, + 0, + 17, ], type: "TryStatement", } @@ -1527,21 +1527,21 @@ snapshot[`Plugin - WhileStatement 1`] = ` body: { body: [], range: [ - 13, - 15, + 12, + 14, ], type: "BlockStatement", }, range: [ - 1, - 15, + 0, + 14, ], test: { name: "foo", optional: false, range: [ - 8, - 11, + 7, + 10, ], type: "Identifier", typeAnnotation: null, @@ -1555,22 +1555,22 @@ snapshot[`Plugin - WithStatement 1`] = ` body: { body: [], range: [ - 11, - 13, + 10, + 12, ], type: "BlockStatement", }, object: { elements: [], range: [ - 7, - 9, + 6, + 8, ], type: "ArrayExpression", }, range: [ - 1, - 13, + 0, + 12, ], type: "WithStatement", } @@ -1582,15 +1582,15 @@ snapshot[`Plugin - ArrayExpression 1`] = ` { elements: [], range: [ - 2, - 4, + 1, + 3, ], type: "ArrayExpression", }, ], range: [ - 1, - 9, + 0, + 8, ], type: "ArrayExpression", } @@ -1602,16 +1602,16 @@ snapshot[`Plugin - ArrowFunctionExpression 1`] = ` body: { body: [], range: [ - 7, - 9, + 6, + 8, ], type: "BlockStatement", }, generator: false, params: [], range: [ - 1, - 9, + 0, + 8, ], returnType: null, type: "ArrowFunctionExpression", @@ -1625,16 +1625,16 @@ snapshot[`Plugin - ArrowFunctionExpression 2`] = ` body: { body: [], range: [ - 13, - 15, + 12, + 14, ], type: "BlockStatement", }, generator: false, params: [], range: [ - 1, - 15, + 0, + 14, ], returnType: null, type: "ArrowFunctionExpression", @@ -1648,8 +1648,8 @@ snapshot[`Plugin - ArrowFunctionExpression 3`] = ` body: { body: [], range: [ - 34, - 36, + 33, + 35, ], type: "BlockStatement", }, @@ -1659,20 +1659,20 @@ snapshot[`Plugin - ArrowFunctionExpression 3`] = ` name: "a", optional: false, range: [ - 2, - 11, + 1, + 10, ], type: "Identifier", typeAnnotation: { range: [ - 3, - 11, + 2, + 10, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 5, - 11, + 4, + 10, ], type: "TSNumberKeyword", }, @@ -1683,34 +1683,34 @@ snapshot[`Plugin - ArrowFunctionExpression 3`] = ` name: "b", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, range: [ - 13, - 24, + 12, + 23, ], type: "RestElement", typeAnnotation: { range: [ - 17, - 24, + 16, + 23, ], type: "TSTypeAnnotation", typeAnnotation: { elementType: { range: [ - 19, - 22, + 18, + 21, ], type: "TSAnyKeyword", }, range: [ - 19, - 24, + 18, + 23, ], type: "TSArrayType", }, @@ -1718,19 +1718,19 @@ snapshot[`Plugin - ArrowFunctionExpression 3`] = ` }, ], range: [ - 1, - 36, + 0, + 35, ], returnType: { range: [ - 25, - 30, + 24, + 29, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 27, - 30, + 26, + 29, ], type: "TSAnyKeyword", }, @@ -1746,23 +1746,23 @@ snapshot[`Plugin - AssignmentExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "=", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -1777,39 +1777,39 @@ snapshot[`Plugin - AssignmentExpression 2`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "=", range: [ - 1, - 12, + 0, + 11, ], right: { left: { name: "a", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, }, operator: "??=", range: [ - 5, - 12, + 4, + 11, ], right: { name: "b", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, @@ -1826,15 +1826,15 @@ snapshot[`Plugin - AwaitExpression 1`] = ` name: "foo", optional: false, range: [ - 7, - 10, + 6, + 9, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 10, + 0, + 9, ], type: "AwaitExpression", } @@ -1846,23 +1846,23 @@ snapshot[`Plugin - BinaryExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: ">", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -1877,23 +1877,23 @@ snapshot[`Plugin - BinaryExpression 2`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: ">=", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -1908,23 +1908,23 @@ snapshot[`Plugin - BinaryExpression 3`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "<", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -1939,23 +1939,23 @@ snapshot[`Plugin - BinaryExpression 4`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "<=", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -1970,23 +1970,23 @@ snapshot[`Plugin - BinaryExpression 5`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "==", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -2001,23 +2001,23 @@ snapshot[`Plugin - BinaryExpression 6`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "===", range: [ - 1, - 8, + 0, + 7, ], right: { name: "b", optional: false, range: [ + 6, 7, - 8, ], type: "Identifier", typeAnnotation: null, @@ -2032,23 +2032,23 @@ snapshot[`Plugin - BinaryExpression 7`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "!=", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -2063,23 +2063,23 @@ snapshot[`Plugin - BinaryExpression 8`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "!=", range: [ - 1, - 8, + 0, + 7, ], right: { name: "b", optional: false, range: [ + 6, 7, - 8, ], type: "Identifier", typeAnnotation: null, @@ -2094,23 +2094,23 @@ snapshot[`Plugin - BinaryExpression 9`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "<<", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -2125,23 +2125,23 @@ snapshot[`Plugin - BinaryExpression 10`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: ">>", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -2156,23 +2156,23 @@ snapshot[`Plugin - BinaryExpression 11`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: ">>>", range: [ - 1, - 8, + 0, + 7, ], right: { name: "b", optional: false, range: [ + 6, 7, - 8, ], type: "Identifier", typeAnnotation: null, @@ -2187,23 +2187,23 @@ snapshot[`Plugin - BinaryExpression 12`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "+", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2218,23 +2218,23 @@ snapshot[`Plugin - BinaryExpression 13`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "-", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2249,23 +2249,23 @@ snapshot[`Plugin - BinaryExpression 14`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "*", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2280,23 +2280,23 @@ snapshot[`Plugin - BinaryExpression 15`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "/", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2311,23 +2311,23 @@ snapshot[`Plugin - BinaryExpression 16`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "%", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2342,23 +2342,23 @@ snapshot[`Plugin - BinaryExpression 17`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "|", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2373,23 +2373,23 @@ snapshot[`Plugin - BinaryExpression 18`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "^", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2404,23 +2404,23 @@ snapshot[`Plugin - BinaryExpression 19`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "&", range: [ - 1, - 6, + 0, + 5, ], right: { name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2435,23 +2435,23 @@ snapshot[`Plugin - BinaryExpression 20`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "in", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -2466,23 +2466,23 @@ snapshot[`Plugin - BinaryExpression 21`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "**", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -2498,16 +2498,16 @@ snapshot[`Plugin - CallExpression 1`] = ` name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 1, - 6, + 0, + 5, ], type: "CallExpression", typeArguments: null, @@ -2521,8 +2521,8 @@ snapshot[`Plugin - CallExpression 2`] = ` name: "a", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2532,15 +2532,15 @@ snapshot[`Plugin - CallExpression 2`] = ` name: "b", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 8, - 11, + 7, + 10, ], type: "SpreadElement", }, @@ -2549,16 +2549,16 @@ snapshot[`Plugin - CallExpression 2`] = ` name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 1, - 13, + 0, + 12, ], type: "CallExpression", typeArguments: null, @@ -2572,16 +2572,16 @@ snapshot[`Plugin - CallExpression 3`] = ` name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, }, optional: true, range: [ - 1, - 8, + 0, + 7, ], type: "CallExpression", typeArguments: null, @@ -2595,24 +2595,24 @@ snapshot[`Plugin - CallExpression 4`] = ` name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 1, - 9, + 0, + 8, ], type: "CallExpression", typeArguments: { params: [ { range: [ + 4, 5, - 6, ], type: "TSTypeReference", typeArguments: null, @@ -2620,8 +2620,8 @@ snapshot[`Plugin - CallExpression 4`] = ` name: "T", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, @@ -2629,8 +2629,8 @@ snapshot[`Plugin - CallExpression 4`] = ` }, ], range: [ - 4, - 7, + 3, + 6, ], type: "TSTypeParameterInstantiation", }, @@ -2645,8 +2645,8 @@ snapshot[`Plugin - ChainExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -2656,21 +2656,21 @@ snapshot[`Plugin - ChainExpression 1`] = ` name: "b", optional: false, range: [ + 3, 4, - 5, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 5, + 0, + 4, ], type: "MemberExpression", }, range: [ - 1, - 5, + 0, + 4, ], type: "ChainExpression", } @@ -2682,8 +2682,8 @@ snapshot[`Plugin - ClassExpression 1`] = ` body: { body: [], range: [ - 5, - 13, + 4, + 12, ], type: "ClassBody", }, @@ -2691,8 +2691,8 @@ snapshot[`Plugin - ClassExpression 1`] = ` id: null, implements: [], range: [ - 5, - 13, + 4, + 12, ], superClass: null, type: "ClassExpression", @@ -2705,8 +2705,8 @@ snapshot[`Plugin - ClassExpression 2`] = ` body: { body: [], range: [ - 5, - 17, + 4, + 16, ], type: "ClassBody", }, @@ -2715,16 +2715,16 @@ snapshot[`Plugin - ClassExpression 2`] = ` name: "Foo", optional: false, range: [ - 11, - 14, + 10, + 13, ], type: "Identifier", typeAnnotation: null, }, implements: [], range: [ - 5, - 17, + 4, + 16, ], superClass: null, type: "ClassExpression", @@ -2737,8 +2737,8 @@ snapshot[`Plugin - ClassExpression 3`] = ` body: { body: [], range: [ - 5, - 29, + 4, + 28, ], type: "ClassBody", }, @@ -2747,23 +2747,23 @@ snapshot[`Plugin - ClassExpression 3`] = ` name: "Foo", optional: false, range: [ - 11, - 14, + 10, + 13, ], type: "Identifier", typeAnnotation: null, }, implements: [], range: [ - 5, - 29, + 4, + 28, ], superClass: { name: "Bar", optional: false, range: [ - 23, - 26, + 22, + 25, ], type: "Identifier", typeAnnotation: null, @@ -2778,8 +2778,8 @@ snapshot[`Plugin - ClassExpression 4`] = ` body: { body: [], range: [ - 5, - 50, + 4, + 49, ], type: "ClassBody", }, @@ -2788,8 +2788,8 @@ snapshot[`Plugin - ClassExpression 4`] = ` name: "Foo", optional: false, range: [ - 11, - 14, + 10, + 13, ], type: "Identifier", typeAnnotation: null, @@ -2800,15 +2800,15 @@ snapshot[`Plugin - ClassExpression 4`] = ` name: "Baz", optional: false, range: [ - 38, - 41, + 37, + 40, ], type: "Identifier", typeAnnotation: null, }, range: [ - 38, - 41, + 37, + 40, ], type: "TSClassImplements", typeArguments: null, @@ -2818,30 +2818,30 @@ snapshot[`Plugin - ClassExpression 4`] = ` name: "Baz2", optional: false, range: [ - 43, - 47, + 42, + 46, ], type: "Identifier", typeAnnotation: null, }, range: [ - 43, - 47, + 42, + 46, ], type: "TSClassImplements", typeArguments: null, }, ], range: [ - 5, - 50, + 4, + 49, ], superClass: { name: "Bar", optional: false, range: [ - 23, - 26, + 22, + 25, ], type: "Identifier", typeAnnotation: null, @@ -2856,8 +2856,8 @@ snapshot[`Plugin - ClassExpression 5`] = ` body: { body: [], range: [ - 5, - 20, + 4, + 19, ], type: "ClassBody", }, @@ -2866,16 +2866,16 @@ snapshot[`Plugin - ClassExpression 5`] = ` name: "Foo", optional: false, range: [ - 11, - 14, + 10, + 13, ], type: "Identifier", typeAnnotation: null, }, implements: [], range: [ - 5, - 20, + 4, + 19, ], superClass: null, type: "ClassExpression", @@ -2895,8 +2895,8 @@ snapshot[`Plugin - ClassExpression 6`] = ` name: "foo", optional: false, range: [ - 13, - 16, + 12, + 15, ], type: "Identifier", typeAnnotation: null, @@ -2905,8 +2905,8 @@ snapshot[`Plugin - ClassExpression 6`] = ` optional: false, override: false, range: [ - 13, - 21, + 12, + 20, ], static: false, type: "MethodDefinition", @@ -2915,8 +2915,8 @@ snapshot[`Plugin - ClassExpression 6`] = ` body: { body: [], range: [ - 19, - 21, + 18, + 20, ], type: "BlockStatement", }, @@ -2924,8 +2924,8 @@ snapshot[`Plugin - ClassExpression 6`] = ` id: null, params: [], range: [ - 13, - 21, + 12, + 20, ], returnType: null, type: "FunctionExpression", @@ -2934,8 +2934,8 @@ snapshot[`Plugin - ClassExpression 6`] = ` }, ], range: [ - 5, - 23, + 4, + 22, ], type: "ClassBody", }, @@ -2943,8 +2943,8 @@ snapshot[`Plugin - ClassExpression 6`] = ` id: null, implements: [], range: [ - 5, - 23, + 4, + 22, ], superClass: null, type: "ClassExpression", @@ -2963,8 +2963,8 @@ snapshot[`Plugin - ClassExpression 7`] = ` key: { name: "foo", range: [ - 13, - 17, + 12, + 16, ], type: "PrivateIdentifier", }, @@ -2972,8 +2972,8 @@ snapshot[`Plugin - ClassExpression 7`] = ` optional: false, override: false, range: [ - 13, - 22, + 12, + 21, ], static: false, type: "MethodDefinition", @@ -2982,8 +2982,8 @@ snapshot[`Plugin - ClassExpression 7`] = ` body: { body: [], range: [ - 20, - 22, + 19, + 21, ], type: "BlockStatement", }, @@ -2991,8 +2991,8 @@ snapshot[`Plugin - ClassExpression 7`] = ` id: null, params: [], range: [ - 13, - 22, + 12, + 21, ], returnType: null, type: "FunctionExpression", @@ -3001,8 +3001,8 @@ snapshot[`Plugin - ClassExpression 7`] = ` }, ], range: [ - 5, - 24, + 4, + 23, ], type: "ClassBody", }, @@ -3010,8 +3010,8 @@ snapshot[`Plugin - ClassExpression 7`] = ` id: null, implements: [], range: [ - 5, - 24, + 4, + 23, ], superClass: null, type: "ClassExpression", @@ -3032,8 +3032,8 @@ snapshot[`Plugin - ClassExpression 8`] = ` name: "foo", optional: false, range: [ - 13, - 16, + 12, + 15, ], type: "Identifier", typeAnnotation: null, @@ -3041,8 +3041,8 @@ snapshot[`Plugin - ClassExpression 8`] = ` optional: false, override: false, range: [ - 13, - 24, + 12, + 23, ], readonly: false, static: false, @@ -3051,8 +3051,8 @@ snapshot[`Plugin - ClassExpression 8`] = ` }, ], range: [ - 5, - 26, + 4, + 25, ], type: "ClassBody", }, @@ -3060,8 +3060,8 @@ snapshot[`Plugin - ClassExpression 8`] = ` id: null, implements: [], range: [ - 5, - 26, + 4, + 25, ], superClass: null, type: "ClassExpression", @@ -3082,8 +3082,8 @@ snapshot[`Plugin - ClassExpression 9`] = ` name: "foo", optional: false, range: [ - 13, - 16, + 12, + 15, ], type: "Identifier", typeAnnotation: null, @@ -3091,8 +3091,8 @@ snapshot[`Plugin - ClassExpression 9`] = ` optional: false, override: false, range: [ - 13, - 22, + 12, + 21, ], readonly: false, static: false, @@ -3101,8 +3101,8 @@ snapshot[`Plugin - ClassExpression 9`] = ` name: "bar", optional: false, range: [ - 19, - 22, + 18, + 21, ], type: "Identifier", typeAnnotation: null, @@ -3110,8 +3110,8 @@ snapshot[`Plugin - ClassExpression 9`] = ` }, ], range: [ - 5, - 24, + 4, + 23, ], type: "ClassBody", }, @@ -3119,8 +3119,8 @@ snapshot[`Plugin - ClassExpression 9`] = ` id: null, implements: [], range: [ - 5, - 24, + 4, + 23, ], superClass: null, type: "ClassExpression", @@ -3140,8 +3140,8 @@ snapshot[`Plugin - ClassExpression 10`] = ` name: "constructor", optional: false, range: [ - 13, - 24, + 12, + 23, ], type: "Identifier", typeAnnotation: null, @@ -3150,8 +3150,8 @@ snapshot[`Plugin - ClassExpression 10`] = ` optional: false, override: false, range: [ - 13, - 47, + 12, + 46, ], static: false, type: "MethodDefinition", @@ -3160,8 +3160,8 @@ snapshot[`Plugin - ClassExpression 10`] = ` body: { body: [], range: [ - 45, - 47, + 44, + 46, ], type: "BlockStatement", }, @@ -3176,28 +3176,28 @@ snapshot[`Plugin - ClassExpression 10`] = ` name: "foo", optional: false, range: [ - 32, - 35, + 31, + 34, ], type: "Identifier", typeAnnotation: { range: [ - 35, - 43, + 34, + 42, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 37, - 43, + 36, + 42, ], type: "TSStringKeyword", }, }, }, range: [ - 25, - 43, + 24, + 42, ], readonly: false, static: false, @@ -3205,8 +3205,8 @@ snapshot[`Plugin - ClassExpression 10`] = ` }, ], range: [ - 13, - 47, + 12, + 46, ], returnType: null, type: "FunctionExpression", @@ -3215,8 +3215,8 @@ snapshot[`Plugin - ClassExpression 10`] = ` }, ], range: [ - 5, - 49, + 4, + 48, ], type: "ClassBody", }, @@ -3224,8 +3224,8 @@ snapshot[`Plugin - ClassExpression 10`] = ` id: null, implements: [], range: [ - 5, - 49, + 4, + 48, ], superClass: null, type: "ClassExpression", @@ -3245,16 +3245,16 @@ snapshot[`Plugin - ClassExpression 11`] = ` key: { name: "foo", range: [ - 13, - 17, + 12, + 16, ], type: "PrivateIdentifier", }, optional: false, override: false, range: [ - 13, - 31, + 12, + 30, ], readonly: false, static: false, @@ -3263,8 +3263,8 @@ snapshot[`Plugin - ClassExpression 11`] = ` name: "bar", optional: false, range: [ - 28, - 31, + 27, + 30, ], type: "Identifier", typeAnnotation: null, @@ -3272,8 +3272,8 @@ snapshot[`Plugin - ClassExpression 11`] = ` }, ], range: [ - 5, - 33, + 4, + 32, ], type: "ClassBody", }, @@ -3281,8 +3281,8 @@ snapshot[`Plugin - ClassExpression 11`] = ` id: null, implements: [], range: [ - 5, - 33, + 4, + 32, ], superClass: null, type: "ClassExpression", @@ -3303,8 +3303,8 @@ snapshot[`Plugin - ClassExpression 12`] = ` name: "foo", optional: false, range: [ - 20, - 23, + 19, + 22, ], type: "Identifier", typeAnnotation: null, @@ -3312,8 +3312,8 @@ snapshot[`Plugin - ClassExpression 12`] = ` optional: false, override: false, range: [ - 13, - 29, + 12, + 28, ], readonly: false, static: true, @@ -3322,8 +3322,8 @@ snapshot[`Plugin - ClassExpression 12`] = ` name: "bar", optional: false, range: [ - 26, - 29, + 25, + 28, ], type: "Identifier", typeAnnotation: null, @@ -3331,8 +3331,8 @@ snapshot[`Plugin - ClassExpression 12`] = ` }, ], range: [ - 5, - 31, + 4, + 30, ], type: "ClassBody", }, @@ -3340,8 +3340,8 @@ snapshot[`Plugin - ClassExpression 12`] = ` id: null, implements: [], range: [ - 5, - 31, + 4, + 30, ], superClass: null, type: "ClassExpression", @@ -3362,8 +3362,8 @@ snapshot[`Plugin - ClassExpression 13`] = ` name: "foo", optional: false, range: [ - 20, - 23, + 19, + 22, ], type: "Identifier", typeAnnotation: null, @@ -3371,8 +3371,8 @@ snapshot[`Plugin - ClassExpression 13`] = ` optional: false, override: false, range: [ - 13, - 24, + 12, + 23, ], readonly: false, static: true, @@ -3388,23 +3388,23 @@ snapshot[`Plugin - ClassExpression 13`] = ` name: "foo", optional: false, range: [ - 34, - 37, + 33, + 36, ], type: "Identifier", typeAnnotation: null, }, operator: "=", range: [ - 34, - 43, + 33, + 42, ], right: { name: "bar", optional: false, range: [ - 40, - 43, + 39, + 42, ], type: "Identifier", typeAnnotation: null, @@ -3412,28 +3412,28 @@ snapshot[`Plugin - ClassExpression 13`] = ` type: "AssignmentExpression", }, range: [ - 34, - 43, + 33, + 42, ], type: "ExpressionStatement", }, ], range: [ - 32, - 45, + 31, + 44, ], type: "BlockStatement", }, range: [ - 25, - 45, + 24, + 44, ], type: "StaticBlock", }, ], range: [ - 5, - 47, + 4, + 46, ], type: "ClassBody", }, @@ -3441,8 +3441,8 @@ snapshot[`Plugin - ClassExpression 13`] = ` id: null, implements: [], range: [ - 5, - 47, + 4, + 46, ], superClass: null, type: "ClassExpression", @@ -3455,8 +3455,8 @@ snapshot[`Plugin - ConditionalExpression 1`] = ` name: "c", optional: false, range: [ + 8, 9, - 10, ], type: "Identifier", typeAnnotation: null, @@ -3465,22 +3465,22 @@ snapshot[`Plugin - ConditionalExpression 1`] = ` name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 10, + 0, + 9, ], test: { name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -3495,8 +3495,8 @@ snapshot[`Plugin - FunctionExpression 1`] = ` body: { body: [], range: [ - 17, - 19, + 16, + 18, ], type: "BlockStatement", }, @@ -3504,8 +3504,8 @@ snapshot[`Plugin - FunctionExpression 1`] = ` id: null, params: [], range: [ - 5, - 19, + 4, + 18, ], returnType: null, type: "FunctionExpression", @@ -3519,8 +3519,8 @@ snapshot[`Plugin - FunctionExpression 2`] = ` body: { body: [], range: [ - 20, - 22, + 19, + 21, ], type: "BlockStatement", }, @@ -3529,16 +3529,16 @@ snapshot[`Plugin - FunctionExpression 2`] = ` name: "foo", optional: false, range: [ - 14, - 17, + 13, + 16, ], type: "Identifier", typeAnnotation: null, }, params: [], range: [ - 5, - 22, + 4, + 21, ], returnType: null, type: "FunctionExpression", @@ -3552,8 +3552,8 @@ snapshot[`Plugin - FunctionExpression 3`] = ` body: { body: [], range: [ - 45, - 47, + 44, + 46, ], type: "BlockStatement", }, @@ -3564,20 +3564,20 @@ snapshot[`Plugin - FunctionExpression 3`] = ` name: "a", optional: true, range: [ + 14, 15, - 16, ], type: "Identifier", typeAnnotation: { range: [ - 17, - 25, + 16, + 24, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 19, - 25, + 18, + 24, ], type: "TSNumberKeyword", }, @@ -3588,34 +3588,34 @@ snapshot[`Plugin - FunctionExpression 3`] = ` name: "b", optional: false, range: [ + 29, 30, - 31, ], type: "Identifier", typeAnnotation: null, }, range: [ - 27, - 38, + 26, + 37, ], type: "RestElement", typeAnnotation: { range: [ - 31, - 38, + 30, + 37, ], type: "TSTypeAnnotation", typeAnnotation: { elementType: { range: [ - 33, - 36, + 32, + 35, ], type: "TSAnyKeyword", }, range: [ - 33, - 38, + 32, + 37, ], type: "TSArrayType", }, @@ -3623,19 +3623,19 @@ snapshot[`Plugin - FunctionExpression 3`] = ` }, ], range: [ - 5, - 47, + 4, + 46, ], returnType: { range: [ - 39, - 44, + 38, + 43, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 41, - 44, + 40, + 43, ], type: "TSAnyKeyword", }, @@ -3651,8 +3651,8 @@ snapshot[`Plugin - FunctionExpression 4`] = ` body: { body: [], range: [ - 24, - 26, + 23, + 25, ], type: "BlockStatement", }, @@ -3660,8 +3660,8 @@ snapshot[`Plugin - FunctionExpression 4`] = ` id: null, params: [], range: [ - 5, - 26, + 4, + 25, ], returnType: null, type: "FunctionExpression", @@ -3674,8 +3674,8 @@ snapshot[`Plugin - Identifier 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -3692,8 +3692,8 @@ snapshot[`Plugin - ImportExpression 1`] = ` name: "with", optional: false, range: [ - 17, - 21, + 16, + 20, ], type: "Identifier", typeAnnotation: null, @@ -3701,8 +3701,8 @@ snapshot[`Plugin - ImportExpression 1`] = ` kind: "init", method: false, range: [ - 17, - 39, + 16, + 38, ], shorthand: false, type: "Property", @@ -3714,8 +3714,8 @@ snapshot[`Plugin - ImportExpression 1`] = ` name: "type", optional: false, range: [ - 25, - 29, + 24, + 28, ], type: "Identifier", typeAnnotation: null, @@ -3723,15 +3723,15 @@ snapshot[`Plugin - ImportExpression 1`] = ` kind: "init", method: false, range: [ - 25, - 37, + 24, + 36, ], shorthand: false, type: "Property", value: { range: [ - 31, - 37, + 30, + 36, ], raw: "'json'", type: "Literal", @@ -3740,27 +3740,27 @@ snapshot[`Plugin - ImportExpression 1`] = ` }, ], range: [ - 23, - 39, + 22, + 38, ], type: "ObjectExpression", }, }, ], range: [ - 15, - 41, + 14, + 40, ], type: "ObjectExpression", }, range: [ - 1, - 42, + 0, + 41, ], source: { range: [ - 8, - 13, + 7, + 12, ], raw: "'foo'", type: "Literal", @@ -3776,23 +3776,23 @@ snapshot[`Plugin - LogicalExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "&&", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -3807,23 +3807,23 @@ snapshot[`Plugin - LogicalExpression 2`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "||", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -3838,23 +3838,23 @@ snapshot[`Plugin - LogicalExpression 3`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, operator: "??", range: [ - 1, - 7, + 0, + 6, ], right: { name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -3870,8 +3870,8 @@ snapshot[`Plugin - MemberExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -3881,15 +3881,15 @@ snapshot[`Plugin - MemberExpression 1`] = ` name: "b", optional: false, range: [ + 2, 3, - 4, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 4, + 0, + 3, ], type: "MemberExpression", } @@ -3902,8 +3902,8 @@ snapshot[`Plugin - MemberExpression 2`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -3911,16 +3911,16 @@ snapshot[`Plugin - MemberExpression 2`] = ` optional: false, property: { range: [ - 3, - 6, + 2, + 5, ], raw: "'b'", type: "Literal", value: "b", }, range: [ - 1, - 7, + 0, + 6, ], type: "MemberExpression", } @@ -3932,15 +3932,15 @@ snapshot[`Plugin - MetaProperty 1`] = ` name: "meta", optional: false, range: [ - 1, - 12, + 0, + 11, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 12, + 0, + 11, ], type: "MetaProperty", } @@ -3953,15 +3953,15 @@ snapshot[`Plugin - NewExpression 1`] = ` name: "Foo", optional: false, range: [ - 5, - 8, + 4, + 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 10, + 0, + 9, ], type: "NewExpression", typeArguments: null, @@ -3975,8 +3975,8 @@ snapshot[`Plugin - NewExpression 2`] = ` name: "a", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, @@ -3986,15 +3986,15 @@ snapshot[`Plugin - NewExpression 2`] = ` name: "b", optional: false, range: [ + 17, 18, - 19, ], type: "Identifier", typeAnnotation: null, }, range: [ - 15, - 18, + 14, + 17, ], type: "SpreadElement", }, @@ -4003,23 +4003,23 @@ snapshot[`Plugin - NewExpression 2`] = ` name: "Foo", optional: false, range: [ - 5, - 8, + 4, + 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 20, + 0, + 19, ], type: "NewExpression", typeArguments: { params: [ { range: [ + 8, 9, - 10, ], type: "TSTypeReference", typeArguments: null, @@ -4027,8 +4027,8 @@ snapshot[`Plugin - NewExpression 2`] = ` name: "T", optional: false, range: [ + 8, 9, - 10, ], type: "Identifier", typeAnnotation: null, @@ -4036,8 +4036,8 @@ snapshot[`Plugin - NewExpression 2`] = ` }, ], range: [ - 8, - 11, + 7, + 10, ], type: "TSTypeParameterInstantiation", }, @@ -4048,8 +4048,8 @@ snapshot[`Plugin - ObjectExpression 1`] = ` { properties: [], range: [ - 5, - 7, + 4, + 6, ], type: "ObjectExpression", } @@ -4064,8 +4064,8 @@ snapshot[`Plugin - ObjectExpression 2`] = ` name: "a", optional: false, range: [ + 6, 7, - 8, ], type: "Identifier", typeAnnotation: null, @@ -4073,8 +4073,8 @@ snapshot[`Plugin - ObjectExpression 2`] = ` kind: "init", method: false, range: [ + 6, 7, - 8, ], shorthand: true, type: "Property", @@ -4082,8 +4082,8 @@ snapshot[`Plugin - ObjectExpression 2`] = ` name: "a", optional: false, range: [ + 6, 7, - 8, ], type: "Identifier", typeAnnotation: null, @@ -4091,8 +4091,8 @@ snapshot[`Plugin - ObjectExpression 2`] = ` }, ], range: [ - 5, - 10, + 4, + 9, ], type: "ObjectExpression", } @@ -4107,8 +4107,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` name: "b", optional: false, range: [ + 6, 7, - 8, ], type: "Identifier", typeAnnotation: null, @@ -4116,8 +4116,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` kind: "init", method: false, range: [ - 7, - 11, + 6, + 10, ], shorthand: false, type: "Property", @@ -4125,8 +4125,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` name: "c", optional: false, range: [ + 9, 10, - 11, ], type: "Identifier", typeAnnotation: null, @@ -4138,8 +4138,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` name: "c", optional: false, range: [ + 13, 14, - 15, ], type: "Identifier", typeAnnotation: null, @@ -4147,8 +4147,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` kind: "init", method: false, range: [ - 13, - 19, + 12, + 18, ], shorthand: false, type: "Property", @@ -4156,8 +4156,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` name: "d", optional: false, range: [ + 17, 18, - 19, ], type: "Identifier", typeAnnotation: null, @@ -4165,8 +4165,8 @@ snapshot[`Plugin - ObjectExpression 3`] = ` }, ], range: [ - 5, - 21, + 4, + 20, ], type: "ObjectExpression", } @@ -4176,8 +4176,8 @@ snapshot[`Plugin - PrivateIdentifier 1`] = ` { name: "foo", range: [ - 13, - 17, + 12, + 16, ], type: "PrivateIdentifier", } @@ -4190,8 +4190,8 @@ snapshot[`Plugin - SequenceExpression 1`] = ` name: "a", optional: false, range: [ + 1, 2, - 3, ], type: "Identifier", typeAnnotation: null, @@ -4200,16 +4200,16 @@ snapshot[`Plugin - SequenceExpression 1`] = ` name: "b", optional: false, range: [ + 4, 5, - 6, ], type: "Identifier", typeAnnotation: null, }, ], range: [ - 2, - 6, + 1, + 5, ], type: "SequenceExpression", } @@ -4218,8 +4218,8 @@ snapshot[`Plugin - SequenceExpression 1`] = ` snapshot[`Plugin - Super 1`] = ` { range: [ - 41, - 46, + 40, + 45, ], type: "Super", } @@ -4233,8 +4233,8 @@ snapshot[`Plugin - TaggedTemplateExpression 1`] = ` name: "bar", optional: false, range: [ - 11, - 14, + 10, + 13, ], type: "Identifier", typeAnnotation: null, @@ -4244,8 +4244,8 @@ snapshot[`Plugin - TaggedTemplateExpression 1`] = ` { cooked: "foo ", range: [ - 5, - 9, + 4, + 8, ], raw: "foo ", tail: false, @@ -4254,8 +4254,8 @@ snapshot[`Plugin - TaggedTemplateExpression 1`] = ` { cooked: " baz", range: [ - 15, - 19, + 14, + 18, ], raw: " baz", tail: true, @@ -4263,21 +4263,21 @@ snapshot[`Plugin - TaggedTemplateExpression 1`] = ` }, ], range: [ - 4, - 20, + 3, + 19, ], type: "TemplateLiteral", }, range: [ - 1, - 20, + 0, + 19, ], tag: { name: "foo", optional: false, range: [ - 1, - 4, + 0, + 3, ], type: "Identifier", typeAnnotation: null, @@ -4294,8 +4294,8 @@ snapshot[`Plugin - TemplateLiteral 1`] = ` name: "bar", optional: false, range: [ - 8, - 11, + 7, + 10, ], type: "Identifier", typeAnnotation: null, @@ -4305,8 +4305,8 @@ snapshot[`Plugin - TemplateLiteral 1`] = ` { cooked: "foo ", range: [ - 2, - 6, + 1, + 5, ], raw: "foo ", tail: false, @@ -4315,8 +4315,8 @@ snapshot[`Plugin - TemplateLiteral 1`] = ` { cooked: " baz", range: [ - 12, - 16, + 11, + 15, ], raw: " baz", tail: true, @@ -4324,8 +4324,8 @@ snapshot[`Plugin - TemplateLiteral 1`] = ` }, ], range: [ - 1, - 17, + 0, + 16, ], type: "TemplateLiteral", } @@ -4334,8 +4334,8 @@ snapshot[`Plugin - TemplateLiteral 1`] = ` snapshot[`Plugin - ThisExpression 1`] = ` { range: [ - 1, - 5, + 0, + 4, ], type: "ThisExpression", } @@ -4347,21 +4347,21 @@ snapshot[`Plugin - TSAsExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 7, + 0, + 6, ], type: "TSAsExpression", typeAnnotation: { range: [ + 5, 6, - 7, ], type: "TSTypeReference", typeArguments: null, @@ -4369,8 +4369,8 @@ snapshot[`Plugin - TSAsExpression 1`] = ` name: "b", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -4385,21 +4385,21 @@ snapshot[`Plugin - TSAsExpression 2`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 11, + 0, + 10, ], type: "TSAsExpression", typeAnnotation: { range: [ - 1, - 11, + 0, + 10, ], type: "TSTypeReference", typeArguments: null, @@ -4407,8 +4407,8 @@ snapshot[`Plugin - TSAsExpression 2`] = ` name: "const", optional: false, range: [ - 1, - 11, + 0, + 10, ], type: "Identifier", typeAnnotation: null, @@ -4423,15 +4423,15 @@ snapshot[`Plugin - TSNonNullExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 3, + 0, + 2, ], type: "TSNonNullExpression", } @@ -4443,21 +4443,21 @@ snapshot[`Plugin - TSSatisfiesExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 14, + 0, + 13, ], type: "TSSatisfiesExpression", typeAnnotation: { range: [ + 12, 13, - 14, ], type: "TSTypeReference", typeArguments: null, @@ -4465,8 +4465,8 @@ snapshot[`Plugin - TSSatisfiesExpression 1`] = ` name: "b", optional: false, range: [ + 12, 13, - 14, ], type: "Identifier", typeAnnotation: null, @@ -4481,16 +4481,16 @@ snapshot[`Plugin - UnaryExpression 1`] = ` name: "a", optional: false, range: [ + 7, 8, - 9, ], type: "Identifier", typeAnnotation: null, }, operator: "typeof", range: [ - 1, - 9, + 0, + 8, ], type: "UnaryExpression", } @@ -4500,8 +4500,8 @@ snapshot[`Plugin - UnaryExpression 2`] = ` { argument: { range: [ + 5, 6, - 7, ], raw: "0", type: "Literal", @@ -4509,8 +4509,8 @@ snapshot[`Plugin - UnaryExpression 2`] = ` }, operator: "void", range: [ - 1, - 7, + 0, + 6, ], type: "UnaryExpression", } @@ -4522,16 +4522,16 @@ snapshot[`Plugin - UnaryExpression 3`] = ` name: "a", optional: false, range: [ + 1, 2, - 3, ], type: "Identifier", typeAnnotation: null, }, operator: "-", range: [ - 1, - 3, + 0, + 2, ], type: "UnaryExpression", } @@ -4543,16 +4543,16 @@ snapshot[`Plugin - UnaryExpression 4`] = ` name: "a", optional: false, range: [ + 1, 2, - 3, ], type: "Identifier", typeAnnotation: null, }, operator: "+", range: [ - 1, - 3, + 0, + 2, ], type: "UnaryExpression", } @@ -4564,8 +4564,8 @@ snapshot[`Plugin - UpdateExpression 1`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -4573,8 +4573,8 @@ snapshot[`Plugin - UpdateExpression 1`] = ` operator: "++", prefix: false, range: [ - 1, - 4, + 0, + 3, ], type: "UpdateExpression", } @@ -4586,8 +4586,8 @@ snapshot[`Plugin - UpdateExpression 2`] = ` name: "a", optional: false, range: [ + 2, 3, - 4, ], type: "Identifier", typeAnnotation: null, @@ -4595,8 +4595,8 @@ snapshot[`Plugin - UpdateExpression 2`] = ` operator: "++", prefix: true, range: [ - 1, - 4, + 0, + 3, ], type: "UpdateExpression", } @@ -4608,8 +4608,8 @@ snapshot[`Plugin - UpdateExpression 3`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, @@ -4617,8 +4617,8 @@ snapshot[`Plugin - UpdateExpression 3`] = ` operator: "--", prefix: false, range: [ - 1, - 4, + 0, + 3, ], type: "UpdateExpression", } @@ -4630,8 +4630,8 @@ snapshot[`Plugin - UpdateExpression 4`] = ` name: "a", optional: false, range: [ + 2, 3, - 4, ], type: "Identifier", typeAnnotation: null, @@ -4639,8 +4639,8 @@ snapshot[`Plugin - UpdateExpression 4`] = ` operator: "--", prefix: true, range: [ - 1, - 4, + 0, + 3, ], type: "UpdateExpression", } @@ -4652,16 +4652,16 @@ snapshot[`Plugin - YieldExpression 1`] = ` name: "bar", optional: false, range: [ - 25, - 28, + 24, + 27, ], type: "Identifier", typeAnnotation: null, }, delegate: false, range: [ - 19, - 28, + 18, + 27, ], type: "YieldExpression", } @@ -4670,8 +4670,8 @@ snapshot[`Plugin - YieldExpression 1`] = ` snapshot[`Plugin - Literal 1`] = ` { range: [ + 0, 1, - 2, ], raw: "1", type: "Literal", @@ -4682,8 +4682,8 @@ snapshot[`Plugin - Literal 1`] = ` snapshot[`Plugin - Literal 2`] = ` { range: [ - 1, - 6, + 0, + 5, ], raw: "'foo'", type: "Literal", @@ -4694,8 +4694,8 @@ snapshot[`Plugin - Literal 2`] = ` snapshot[`Plugin - Literal 3`] = ` { range: [ - 1, - 6, + 0, + 5, ], raw: '"foo"', type: "Literal", @@ -4706,8 +4706,8 @@ snapshot[`Plugin - Literal 3`] = ` snapshot[`Plugin - Literal 4`] = ` { range: [ - 1, - 5, + 0, + 4, ], raw: "true", type: "Literal", @@ -4718,8 +4718,8 @@ snapshot[`Plugin - Literal 4`] = ` snapshot[`Plugin - Literal 5`] = ` { range: [ - 1, - 6, + 0, + 5, ], raw: "false", type: "Literal", @@ -4730,8 +4730,8 @@ snapshot[`Plugin - Literal 5`] = ` snapshot[`Plugin - Literal 6`] = ` { range: [ - 1, - 5, + 0, + 4, ], raw: "null", type: "Literal", @@ -4743,8 +4743,8 @@ snapshot[`Plugin - Literal 7`] = ` { bigint: "1", range: [ - 1, - 3, + 0, + 2, ], raw: "1n", type: "Literal", @@ -4755,8 +4755,8 @@ snapshot[`Plugin - Literal 7`] = ` snapshot[`Plugin - Literal 8`] = ` { range: [ - 1, - 7, + 0, + 6, ], raw: "/foo/g", regex: { @@ -4777,22 +4777,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 8, + 0, + 7, ], selfClosing: true, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 8, + 0, + 7, ], type: "JSXElement", } @@ -4805,14 +4805,14 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 8, - 11, + 7, + 10, ], type: "JSXIdentifier", }, range: [ - 6, - 12, + 5, + 11, ], type: "JSXClosingElement", }, @@ -4821,22 +4821,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 6, + 0, + 5, ], selfClosing: false, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 12, + 0, + 11, ], type: "JSXElement", } @@ -4849,14 +4849,14 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 10, - 13, + 9, + 12, ], type: "JSXIdentifier", }, range: [ - 8, - 14, + 7, + 13, ], type: "JSXClosingElement", }, @@ -4866,14 +4866,14 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "a", range: [ + 5, 6, - 7, ], type: "JSXIdentifier", }, range: [ + 5, 6, - 7, ], type: "JSXAttribute", value: null, @@ -4882,22 +4882,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 8, + 0, + 7, ], selfClosing: false, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 14, + 0, + 13, ], type: "JSXElement", } @@ -4913,20 +4913,20 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "a", range: [ + 5, 6, - 7, ], type: "JSXIdentifier", }, range: [ - 6, - 11, + 5, + 10, ], type: "JSXAttribute", value: { range: [ - 8, - 11, + 7, + 10, ], raw: '"b"', type: "Literal", @@ -4937,22 +4937,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 14, + 0, + 13, ], selfClosing: true, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 14, + 0, + 13, ], type: "JSXElement", } @@ -4968,29 +4968,29 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "a", range: [ + 5, 6, - 7, ], type: "JSXIdentifier", }, range: [ - 6, - 11, + 5, + 10, ], type: "JSXAttribute", value: { expression: { range: [ + 8, 9, - 10, ], raw: "2", type: "Literal", value: 2, }, range: [ - 8, - 11, + 7, + 10, ], type: "JSXExpressionContainer", }, @@ -4999,22 +4999,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 14, + 0, + 13, ], selfClosing: true, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 14, + 0, + 13, ], type: "JSXElement", } @@ -5025,8 +5025,8 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr children: [ { range: [ - 6, - 9, + 5, + 8, ], raw: "foo", type: "JSXText", @@ -5035,16 +5035,16 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr { expression: { range: [ + 9, 10, - 11, ], raw: "2", type: "Literal", value: 2, }, range: [ - 9, - 12, + 8, + 11, ], type: "JSXExpressionContainer", }, @@ -5053,14 +5053,14 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 14, - 17, + 13, + 16, ], type: "JSXIdentifier", }, range: [ - 12, - 18, + 11, + 17, ], type: "JSXClosingElement", }, @@ -5069,22 +5069,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 6, + 0, + 5, ], selfClosing: false, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 18, + 0, + 17, ], type: "JSXElement", } @@ -5100,36 +5100,36 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr object: { name: "a", range: [ + 1, 2, - 3, ], type: "JSXIdentifier", }, property: { name: "b", range: [ + 3, 4, - 5, ], type: "JSXIdentifier", }, range: [ - 2, - 5, + 1, + 4, ], type: "JSXMemberExpression", }, range: [ - 1, - 8, + 0, + 7, ], selfClosing: true, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 8, + 0, + 7, ], type: "JSXElement", } @@ -5146,43 +5146,43 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "b", range: [ + 7, 8, - 9, ], type: "JSXIdentifier", }, namespace: { name: "a", range: [ + 5, 6, - 7, ], type: "JSXIdentifier", }, range: [ - 6, - 9, + 5, + 8, ], type: "JSXNamespacedName", }, range: [ - 6, - 13, + 5, + 12, ], type: "JSXAttribute", value: { expression: { range: [ + 10, 11, - 12, ], raw: "2", type: "Literal", value: 2, }, range: [ - 10, - 13, + 9, + 12, ], type: "JSXExpressionContainer", }, @@ -5191,22 +5191,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "div", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 16, + 0, + 15, ], selfClosing: true, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 16, + 0, + 15, ], type: "JSXElement", } @@ -5221,22 +5221,22 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "Foo", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 8, + 0, + 7, ], selfClosing: true, type: "JSXOpeningElement", typeArguments: null, }, range: [ - 1, - 8, + 0, + 7, ], type: "JSXElement", } @@ -5251,14 +5251,14 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: { name: "Foo", range: [ - 2, - 5, + 1, + 4, ], type: "JSXIdentifier", }, range: [ - 1, - 11, + 0, + 10, ], selfClosing: true, type: "JSXOpeningElement", @@ -5266,8 +5266,8 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr params: [ { range: [ + 5, 6, - 7, ], type: "TSTypeReference", typeArguments: null, @@ -5275,8 +5275,8 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr name: "T", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, @@ -5284,15 +5284,15 @@ snapshot[`Plugin - JSXElement + JSXOpeningElement + JSXClosingElement + JSXAttr }, ], range: [ - 5, - 8, + 4, + 7, ], type: "TSTypeParameterInstantiation", }, }, range: [ - 1, - 11, + 0, + 10, ], type: "JSXElement", } @@ -5303,21 +5303,21 @@ snapshot[`Plugin - JSXFragment + JSXOpeningFragment + JSXClosingFragment 1`] = ` children: [], closingFragment: { range: [ - 3, - 6, + 2, + 5, ], type: "JSXClosingFragment", }, openingFragment: { range: [ - 1, - 3, + 0, + 2, ], type: "JSXOpeningFragment", }, range: [ - 1, - 6, + 0, + 5, ], type: "JSXFragment", } @@ -5328,8 +5328,8 @@ snapshot[`Plugin - JSXFragment + JSXOpeningFragment + JSXClosingFragment 2`] = ` children: [ { range: [ - 3, - 6, + 2, + 5, ], raw: "foo", type: "JSXText", @@ -5338,37 +5338,37 @@ snapshot[`Plugin - JSXFragment + JSXOpeningFragment + JSXClosingFragment 2`] = ` { expression: { range: [ + 6, 7, - 8, ], raw: "2", type: "Literal", value: 2, }, range: [ - 6, - 9, + 5, + 8, ], type: "JSXExpressionContainer", }, ], closingFragment: { range: [ - 9, - 12, + 8, + 11, ], type: "JSXClosingFragment", }, openingFragment: { range: [ - 1, - 3, + 0, + 2, ], type: "JSXOpeningFragment", }, range: [ - 1, - 12, + 0, + 11, ], type: "JSXFragment", } @@ -5380,21 +5380,21 @@ snapshot[`Plugin - TSAsExpression 3`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 9, + 0, + 8, ], type: "TSAsExpression", typeAnnotation: { range: [ - 6, - 9, + 5, + 8, ], type: "TSAnyKeyword", }, @@ -5405,22 +5405,22 @@ snapshot[`Plugin - TSAsExpression 4`] = ` { expression: { range: [ - 1, - 6, + 0, + 5, ], raw: '"foo"', type: "Literal", value: "foo", }, range: [ - 1, - 15, + 0, + 14, ], type: "TSAsExpression", typeAnnotation: { range: [ - 1, - 15, + 0, + 14, ], type: "TSTypeReference", typeArguments: null, @@ -5428,8 +5428,8 @@ snapshot[`Plugin - TSAsExpression 4`] = ` name: "const", optional: false, range: [ - 1, - 15, + 0, + 14, ], type: "Identifier", typeAnnotation: null, @@ -5443,8 +5443,8 @@ snapshot[`Plugin - TSEnumDeclaration 1`] = ` body: { members: [], range: [ - 1, - 12, + 0, + 11, ], type: "TSEnumBody", }, @@ -5454,15 +5454,15 @@ snapshot[`Plugin - TSEnumDeclaration 1`] = ` name: "Foo", optional: false, range: [ - 6, - 9, + 5, + 8, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 12, + 0, + 11, ], type: "TSEnumDeclaration", } @@ -5473,8 +5473,8 @@ snapshot[`Plugin - TSEnumDeclaration 2`] = ` body: { members: [], range: [ - 1, - 18, + 0, + 17, ], type: "TSEnumBody", }, @@ -5484,15 +5484,15 @@ snapshot[`Plugin - TSEnumDeclaration 2`] = ` name: "Foo", optional: false, range: [ - 12, - 15, + 11, + 14, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 18, + 0, + 17, ], type: "TSEnumDeclaration", } @@ -5507,16 +5507,16 @@ snapshot[`Plugin - TSEnumDeclaration 3`] = ` name: "A", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, }, initializer: null, range: [ + 11, 12, - 13, ], type: "TSEnumMember", }, @@ -5525,23 +5525,23 @@ snapshot[`Plugin - TSEnumDeclaration 3`] = ` name: "B", optional: false, range: [ + 14, 15, - 16, ], type: "Identifier", typeAnnotation: null, }, initializer: null, range: [ + 14, 15, - 16, ], type: "TSEnumMember", }, ], range: [ - 1, - 18, + 0, + 17, ], type: "TSEnumBody", }, @@ -5551,15 +5551,15 @@ snapshot[`Plugin - TSEnumDeclaration 3`] = ` name: "Foo", optional: false, range: [ - 6, - 9, + 5, + 8, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 18, + 0, + 17, ], type: "TSEnumDeclaration", } @@ -5572,8 +5572,8 @@ snapshot[`Plugin - TSEnumDeclaration 4`] = ` { id: { range: [ - 12, - 17, + 11, + 16, ], raw: '"a-b"', type: "Literal", @@ -5581,15 +5581,15 @@ snapshot[`Plugin - TSEnumDeclaration 4`] = ` }, initializer: null, range: [ - 12, - 17, + 11, + 16, ], type: "TSEnumMember", }, ], range: [ - 1, - 19, + 0, + 18, ], type: "TSEnumBody", }, @@ -5599,15 +5599,15 @@ snapshot[`Plugin - TSEnumDeclaration 4`] = ` name: "Foo", optional: false, range: [ - 6, - 9, + 5, + 8, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 19, + 0, + 18, ], type: "TSEnumDeclaration", } @@ -5622,24 +5622,24 @@ snapshot[`Plugin - TSEnumDeclaration 5`] = ` name: "A", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, }, initializer: { range: [ + 15, 16, - 17, ], raw: "1", type: "Literal", value: 1, }, range: [ - 12, - 17, + 11, + 16, ], type: "TSEnumMember", }, @@ -5648,24 +5648,24 @@ snapshot[`Plugin - TSEnumDeclaration 5`] = ` name: "B", optional: false, range: [ + 18, 19, - 20, ], type: "Identifier", typeAnnotation: null, }, initializer: { range: [ + 22, 23, - 24, ], raw: "2", type: "Literal", value: 2, }, range: [ - 19, - 24, + 18, + 23, ], type: "TSEnumMember", }, @@ -5674,8 +5674,8 @@ snapshot[`Plugin - TSEnumDeclaration 5`] = ` name: "C", optional: false, range: [ + 25, 26, - 27, ], type: "Identifier", typeAnnotation: null, @@ -5685,23 +5685,23 @@ snapshot[`Plugin - TSEnumDeclaration 5`] = ` name: "A", optional: false, range: [ + 29, 30, - 31, ], type: "Identifier", typeAnnotation: null, }, operator: "|", range: [ - 30, - 35, + 29, + 34, ], right: { name: "B", optional: false, range: [ + 33, 34, - 35, ], type: "Identifier", typeAnnotation: null, @@ -5709,15 +5709,15 @@ snapshot[`Plugin - TSEnumDeclaration 5`] = ` type: "BinaryExpression", }, range: [ - 26, - 35, + 25, + 34, ], type: "TSEnumMember", }, ], range: [ - 1, - 37, + 0, + 36, ], type: "TSEnumBody", }, @@ -5727,15 +5727,15 @@ snapshot[`Plugin - TSEnumDeclaration 5`] = ` name: "Foo", optional: false, range: [ - 6, - 9, + 5, + 8, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 37, + 0, + 36, ], type: "TSEnumDeclaration", } @@ -5746,8 +5746,8 @@ snapshot[`Plugin - TSInterface 1`] = ` body: { body: [], range: [ - 13, - 15, + 12, + 14, ], type: "TSInterfaceBody", }, @@ -5757,15 +5757,15 @@ snapshot[`Plugin - TSInterface 1`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 15, + 0, + 14, ], type: "TSInterface", typeParameters: [], @@ -5777,8 +5777,8 @@ snapshot[`Plugin - TSInterface 2`] = ` body: { body: [], range: [ - 16, - 18, + 15, + 17, ], type: "TSInterfaceBody", }, @@ -5794,23 +5794,23 @@ snapshot[`Plugin - TSInterface 2`] = ` name: "T", optional: false, range: [ + 12, 13, - 14, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 12, 13, - 14, ], type: "TSTypeParameter", }, ], range: [ - 12, - 15, + 11, + 14, ], type: "TSTypeParameterDeclaration", }, @@ -5818,15 +5818,15 @@ snapshot[`Plugin - TSInterface 2`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 18, + 0, + 17, ], type: "TSInterface", typeParameters: [], @@ -5838,8 +5838,8 @@ snapshot[`Plugin - TSInterface 3`] = ` body: { body: [], range: [ - 36, - 38, + 35, + 37, ], type: "TSInterfaceBody", }, @@ -5849,15 +5849,15 @@ snapshot[`Plugin - TSInterface 3`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 38, + 0, + 37, ], type: "TSInterface", typeParameters: [ @@ -5866,23 +5866,23 @@ snapshot[`Plugin - TSInterface 3`] = ` name: "Foo", optional: false, range: [ - 21, - 24, + 20, + 23, ], type: "Identifier", typeAnnotation: null, }, range: [ - 21, - 27, + 20, + 26, ], type: "TSInterfaceHeritage", typeArguments: { params: [ { range: [ + 24, 25, - 26, ], type: "TSTypeReference", typeArguments: null, @@ -5890,8 +5890,8 @@ snapshot[`Plugin - TSInterface 3`] = ` name: "T", optional: false, range: [ + 24, 25, - 26, ], type: "Identifier", typeAnnotation: null, @@ -5899,8 +5899,8 @@ snapshot[`Plugin - TSInterface 3`] = ` }, ], range: [ - 24, - 27, + 23, + 26, ], type: "TSTypeParameterInstantiation", }, @@ -5910,23 +5910,23 @@ snapshot[`Plugin - TSInterface 3`] = ` name: "Bar", optional: false, range: [ - 29, - 32, + 28, + 31, ], type: "Identifier", typeAnnotation: null, }, range: [ - 29, - 35, + 28, + 34, ], type: "TSInterfaceHeritage", typeArguments: { params: [ { range: [ + 32, 33, - 34, ], type: "TSTypeReference", typeArguments: null, @@ -5934,8 +5934,8 @@ snapshot[`Plugin - TSInterface 3`] = ` name: "T", optional: false, range: [ + 32, 33, - 34, ], type: "Identifier", typeAnnotation: null, @@ -5943,9 +5943,9 @@ snapshot[`Plugin - TSInterface 3`] = ` }, ], range: [ - 32, - 35, - ], + 31, + 34, + ], type: "TSTypeParameterInstantiation", }, }, @@ -5963,30 +5963,30 @@ snapshot[`Plugin - TSInterface 4`] = ` name: "foo", optional: false, range: [ - 15, - 18, + 14, + 17, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 15, - 24, + 14, + 23, ], readonly: false, static: false, type: "TSPropertySignature", typeAnnotation: { range: [ - 18, - 23, + 17, + 22, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 20, - 23, + 19, + 22, ], type: "TSAnyKeyword", }, @@ -5998,30 +5998,30 @@ snapshot[`Plugin - TSInterface 4`] = ` name: "bar", optional: false, range: [ - 25, - 28, + 24, + 27, ], type: "Identifier", typeAnnotation: null, }, optional: true, range: [ - 25, - 34, + 24, + 33, ], readonly: false, static: false, type: "TSPropertySignature", typeAnnotation: { range: [ - 29, - 34, + 28, + 33, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 31, - 34, + 30, + 33, ], type: "TSAnyKeyword", }, @@ -6029,8 +6029,8 @@ snapshot[`Plugin - TSInterface 4`] = ` }, ], range: [ - 13, - 36, + 12, + 35, ], type: "TSInterfaceBody", }, @@ -6040,15 +6040,15 @@ snapshot[`Plugin - TSInterface 4`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 36, + 0, + 35, ], type: "TSInterface", typeParameters: [], @@ -6065,20 +6065,20 @@ snapshot[`Plugin - TSInterface 5`] = ` name: "key", optional: false, range: [ - 25, - 36, + 24, + 35, ], type: "Identifier", typeAnnotation: { range: [ - 28, - 36, + 27, + 35, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 30, - 36, + 29, + 35, ], type: "TSStringKeyword", }, @@ -6086,21 +6086,21 @@ snapshot[`Plugin - TSInterface 5`] = ` }, ], range: [ - 15, - 42, + 14, + 41, ], readonly: true, type: "TSIndexSignature", typeAnnotation: { range: [ - 37, - 42, + 36, + 41, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 39, - 42, + 38, + 41, ], type: "TSAnyKeyword", }, @@ -6108,8 +6108,8 @@ snapshot[`Plugin - TSInterface 5`] = ` }, ], range: [ - 13, - 44, + 12, + 43, ], type: "TSInterfaceBody", }, @@ -6119,15 +6119,15 @@ snapshot[`Plugin - TSInterface 5`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 44, + 0, + 43, ], type: "TSInterface", typeParameters: [], @@ -6144,30 +6144,30 @@ snapshot[`Plugin - TSInterface 6`] = ` name: "a", optional: false, range: [ + 23, 24, - 25, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 15, - 30, + 14, + 29, ], readonly: true, static: false, type: "TSPropertySignature", typeAnnotation: { range: [ - 25, - 30, + 24, + 29, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 27, - 30, + 26, + 29, ], type: "TSAnyKeyword", }, @@ -6175,8 +6175,8 @@ snapshot[`Plugin - TSInterface 6`] = ` }, ], range: [ - 13, - 32, + 12, + 31, ], type: "TSInterfaceBody", }, @@ -6186,15 +6186,15 @@ snapshot[`Plugin - TSInterface 6`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 32, + 0, + 31, ], type: "TSInterface", typeParameters: [], @@ -6211,20 +6211,20 @@ snapshot[`Plugin - TSInterface 7`] = ` name: "a", optional: false, range: [ + 18, 19, - 20, ], type: "Identifier", typeAnnotation: { range: [ - 20, - 23, + 19, + 22, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ + 21, 22, - 23, ], type: "TSTypeReference", typeArguments: null, @@ -6232,8 +6232,8 @@ snapshot[`Plugin - TSInterface 7`] = ` name: "T", optional: false, range: [ + 21, 22, - 23, ], type: "Identifier", typeAnnotation: null, @@ -6243,19 +6243,19 @@ snapshot[`Plugin - TSInterface 7`] = ` }, ], range: [ - 15, - 27, + 14, + 26, ], returnType: { range: [ - 24, - 27, + 23, + 26, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ + 25, 26, - 27, ], type: "TSTypeReference", typeArguments: null, @@ -6263,8 +6263,8 @@ snapshot[`Plugin - TSInterface 7`] = ` name: "T", optional: false, range: [ + 25, 26, - 27, ], type: "Identifier", typeAnnotation: null, @@ -6283,31 +6283,31 @@ snapshot[`Plugin - TSInterface 7`] = ` name: "T", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 15, 16, - 17, ], type: "TSTypeParameter", }, ], range: [ - 15, - 18, + 14, + 17, ], type: "TSTypeParameterDeclaration", }, }, ], range: [ - 13, - 29, + 12, + 28, ], type: "TSInterfaceBody", }, @@ -6317,15 +6317,15 @@ snapshot[`Plugin - TSInterface 7`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 29, + 0, + 28, ], type: "TSInterface", typeParameters: [], @@ -6342,20 +6342,20 @@ snapshot[`Plugin - TSInterface 8`] = ` name: "a", optional: false, range: [ + 22, 23, - 24, ], type: "Identifier", typeAnnotation: { range: [ - 24, - 27, + 23, + 26, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ + 25, 26, - 27, ], type: "TSTypeReference", typeArguments: null, @@ -6363,8 +6363,8 @@ snapshot[`Plugin - TSInterface 8`] = ` name: "T", optional: false, range: [ + 25, 26, - 27, ], type: "Identifier", typeAnnotation: null, @@ -6374,19 +6374,19 @@ snapshot[`Plugin - TSInterface 8`] = ` }, ], range: [ - 15, - 31, + 14, + 30, ], returnType: { range: [ - 28, - 31, + 27, + 30, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ + 29, 30, - 31, ], type: "TSTypeReference", typeArguments: null, @@ -6394,8 +6394,8 @@ snapshot[`Plugin - TSInterface 8`] = ` name: "T", optional: false, range: [ + 29, 30, - 31, ], type: "Identifier", typeAnnotation: null, @@ -6414,31 +6414,31 @@ snapshot[`Plugin - TSInterface 8`] = ` name: "T", optional: false, range: [ + 19, 20, - 21, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 19, 20, - 21, ], type: "TSTypeParameter", }, ], range: [ - 19, - 22, + 18, + 21, ], type: "TSTypeParameterDeclaration", }, }, ], range: [ - 13, - 33, + 12, + 32, ], type: "TSInterfaceBody", }, @@ -6448,15 +6448,15 @@ snapshot[`Plugin - TSInterface 8`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 33, + 0, + 32, ], type: "TSInterface", typeParameters: [], @@ -6473,24 +6473,24 @@ snapshot[`Plugin - TSInterface 9`] = ` name: "a", optional: false, range: [ + 14, 15, - 16, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 15, - 36, + 14, + 35, ], readonly: false, static: false, type: "TSPropertySignature", typeAnnotation: { range: [ - 16, - 36, + 15, + 35, ], type: "TSTypeAnnotation", typeAnnotation: { @@ -6499,20 +6499,20 @@ snapshot[`Plugin - TSInterface 9`] = ` name: "a", optional: false, range: [ + 25, 26, - 27, ], type: "Identifier", typeAnnotation: { range: [ - 27, - 30, + 26, + 29, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ + 28, 29, - 30, ], type: "TSTypeReference", typeArguments: null, @@ -6520,8 +6520,8 @@ snapshot[`Plugin - TSInterface 9`] = ` name: "T", optional: false, range: [ + 28, 29, - 30, ], type: "Identifier", typeAnnotation: null, @@ -6531,19 +6531,19 @@ snapshot[`Plugin - TSInterface 9`] = ` }, ], range: [ - 18, - 36, + 17, + 35, ], returnType: { range: [ - 32, - 36, + 31, + 35, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ + 34, 35, - 36, ], type: "TSTypeReference", typeArguments: null, @@ -6551,8 +6551,8 @@ snapshot[`Plugin - TSInterface 9`] = ` name: "T", optional: false, range: [ + 34, 35, - 36, ], type: "Identifier", typeAnnotation: null, @@ -6571,23 +6571,23 @@ snapshot[`Plugin - TSInterface 9`] = ` name: "T", optional: false, range: [ + 22, 23, - 24, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 22, 23, - 24, ], type: "TSTypeParameter", }, ], range: [ - 22, - 25, + 21, + 24, ], type: "TSTypeParameterDeclaration", }, @@ -6596,8 +6596,8 @@ snapshot[`Plugin - TSInterface 9`] = ` }, ], range: [ - 13, - 38, + 12, + 37, ], type: "TSInterfaceBody", }, @@ -6607,15 +6607,15 @@ snapshot[`Plugin - TSInterface 9`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 38, + 0, + 37, ], type: "TSInterface", typeParameters: [], @@ -6632,8 +6632,8 @@ snapshot[`Plugin - TSInterface 10`] = ` name: "a", optional: false, range: [ + 18, 19, - 20, ], type: "Identifier", typeAnnotation: null, @@ -6641,20 +6641,20 @@ snapshot[`Plugin - TSInterface 10`] = ` kind: "getter", optional: false, range: [ - 15, - 30, + 14, + 29, ], readonly: false, returnType: { range: [ - 22, - 30, + 21, + 29, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 24, - 30, + 23, + 29, ], type: "TSStringKeyword", }, @@ -6664,8 +6664,8 @@ snapshot[`Plugin - TSInterface 10`] = ` }, ], range: [ - 13, - 32, + 12, + 31, ], type: "TSInterfaceBody", }, @@ -6675,15 +6675,15 @@ snapshot[`Plugin - TSInterface 10`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 32, + 0, + 31, ], type: "TSInterface", typeParameters: [], @@ -6700,8 +6700,8 @@ snapshot[`Plugin - TSInterface 11`] = ` name: "a", optional: false, range: [ + 18, 19, - 20, ], type: "Identifier", typeAnnotation: null, @@ -6713,20 +6713,20 @@ snapshot[`Plugin - TSInterface 11`] = ` name: "v", optional: false, range: [ + 20, 21, - 22, ], type: "Identifier", typeAnnotation: { range: [ - 22, - 30, + 21, + 29, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 24, - 30, + 23, + 29, ], type: "TSStringKeyword", }, @@ -6734,8 +6734,8 @@ snapshot[`Plugin - TSInterface 11`] = ` }, ], range: [ - 15, - 31, + 14, + 30, ], readonly: false, static: false, @@ -6743,8 +6743,8 @@ snapshot[`Plugin - TSInterface 11`] = ` }, ], range: [ - 13, - 33, + 12, + 32, ], type: "TSInterfaceBody", }, @@ -6754,15 +6754,15 @@ snapshot[`Plugin - TSInterface 11`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 33, + 0, + 32, ], type: "TSInterface", typeParameters: [], @@ -6779,8 +6779,8 @@ snapshot[`Plugin - TSInterface 12`] = ` name: "a", optional: false, range: [ + 14, 15, - 16, ], type: "Identifier", typeAnnotation: null, @@ -6792,20 +6792,20 @@ snapshot[`Plugin - TSInterface 12`] = ` name: "arg", optional: true, range: [ - 20, - 23, + 19, + 22, ], type: "Identifier", typeAnnotation: { range: [ - 24, - 29, + 23, + 28, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 26, - 29, + 25, + 28, ], type: "TSAnyKeyword", }, @@ -6816,34 +6816,34 @@ snapshot[`Plugin - TSInterface 12`] = ` name: "args", optional: false, range: [ - 34, - 38, + 33, + 37, ], type: "Identifier", typeAnnotation: null, }, range: [ - 31, - 45, + 30, + 44, ], type: "RestElement", typeAnnotation: { range: [ - 38, - 45, + 37, + 44, ], type: "TSTypeAnnotation", typeAnnotation: { elementType: { range: [ - 40, - 43, + 39, + 42, ], type: "TSAnyKeyword", }, range: [ - 40, - 45, + 39, + 44, ], type: "TSArrayType", }, @@ -6851,20 +6851,20 @@ snapshot[`Plugin - TSInterface 12`] = ` }, ], range: [ - 15, - 51, + 14, + 50, ], readonly: false, returnType: { range: [ - 46, - 51, + 45, + 50, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 48, - 51, + 47, + 50, ], type: "TSAnyKeyword", }, @@ -6882,31 +6882,31 @@ snapshot[`Plugin - TSInterface 12`] = ` name: "T", optional: false, range: [ + 16, 17, - 18, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 16, 17, - 18, ], type: "TSTypeParameter", }, ], range: [ - 16, - 19, + 15, + 18, ], type: "TSTypeParameterDeclaration", }, }, ], range: [ - 13, - 53, + 12, + 52, ], type: "TSInterfaceBody", }, @@ -6916,15 +6916,15 @@ snapshot[`Plugin - TSInterface 12`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 53, + 0, + 52, ], type: "TSInterface", typeParameters: [], @@ -6936,20 +6936,20 @@ snapshot[`Plugin - TSSatisfiesExpression 2`] = ` expression: { properties: [], range: [ - 11, - 13, + 10, + 12, ], type: "ObjectExpression", }, range: [ - 11, - 25, + 10, + 24, ], type: "TSSatisfiesExpression", typeAnnotation: { range: [ + 23, 24, - 25, ], type: "TSTypeReference", typeArguments: null, @@ -6957,8 +6957,8 @@ snapshot[`Plugin - TSSatisfiesExpression 2`] = ` name: "A", optional: false, range: [ + 23, 24, - 25, ], type: "Identifier", typeAnnotation: null, @@ -6974,21 +6974,21 @@ snapshot[`Plugin - TSTypeAliasDeclaration 1`] = ` name: "A", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 13, + 0, + 12, ], type: "TSTypeAliasDeclaration", typeAnnotation: { range: [ - 10, - 13, + 9, + 12, ], type: "TSAnyKeyword", }, @@ -7003,21 +7003,21 @@ snapshot[`Plugin - TSTypeAliasDeclaration 2`] = ` name: "A", optional: false, range: [ + 5, 6, - 7, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 16, + 0, + 15, ], type: "TSTypeAliasDeclaration", typeAnnotation: { range: [ - 13, - 16, + 12, + 15, ], type: "TSAnyKeyword", }, @@ -7032,23 +7032,23 @@ snapshot[`Plugin - TSTypeAliasDeclaration 2`] = ` name: "T", optional: false, range: [ + 7, 8, - 9, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 7, 8, - 9, ], type: "TSTypeParameter", }, ], range: [ - 7, - 10, + 6, + 9, ], type: "TSTypeParameterDeclaration", }, @@ -7062,21 +7062,21 @@ snapshot[`Plugin - TSTypeAliasDeclaration 3`] = ` name: "A", optional: false, range: [ + 13, 14, - 15, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 24, + 0, + 23, ], type: "TSTypeAliasDeclaration", typeAnnotation: { range: [ - 21, - 24, + 20, + 23, ], type: "TSAnyKeyword", }, @@ -7091,23 +7091,23 @@ snapshot[`Plugin - TSTypeAliasDeclaration 3`] = ` name: "T", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ + 15, 16, - 17, ], type: "TSTypeParameter", }, ], range: [ - 15, - 18, + 14, + 17, ], type: "TSTypeParameterDeclaration", }, @@ -7120,15 +7120,15 @@ snapshot[`Plugin - TSNonNullExpression 2`] = ` name: "a", optional: false, range: [ + 0, 1, - 2, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 3, + 0, + 2, ], type: "TSNonNullExpression", } @@ -7137,15 +7137,15 @@ snapshot[`Plugin - TSNonNullExpression 2`] = ` snapshot[`Plugin - TSUnionType 1`] = ` { range: [ - 10, - 15, + 9, + 14, ], type: "TSUnionType", types: [ { range: [ + 9, 10, - 11, ], type: "TSTypeReference", typeArguments: null, @@ -7153,8 +7153,8 @@ snapshot[`Plugin - TSUnionType 1`] = ` name: "B", optional: false, range: [ + 9, 10, - 11, ], type: "Identifier", typeAnnotation: null, @@ -7162,8 +7162,8 @@ snapshot[`Plugin - TSUnionType 1`] = ` }, { range: [ + 13, 14, - 15, ], type: "TSTypeReference", typeArguments: null, @@ -7171,8 +7171,8 @@ snapshot[`Plugin - TSUnionType 1`] = ` name: "C", optional: false, range: [ + 13, 14, - 15, ], type: "Identifier", typeAnnotation: null, @@ -7185,15 +7185,15 @@ snapshot[`Plugin - TSUnionType 1`] = ` snapshot[`Plugin - TSIntersectionType 1`] = ` { range: [ - 10, - 15, + 9, + 14, ], type: "TSIntersectionType", types: [ { range: [ + 9, 10, - 11, ], type: "TSTypeReference", typeArguments: null, @@ -7201,8 +7201,8 @@ snapshot[`Plugin - TSIntersectionType 1`] = ` name: "B", optional: false, range: [ + 9, 10, - 11, ], type: "Identifier", typeAnnotation: null, @@ -7210,8 +7210,8 @@ snapshot[`Plugin - TSIntersectionType 1`] = ` }, { range: [ + 13, 14, - 15, ], type: "TSTypeReference", typeArguments: null, @@ -7219,8 +7219,8 @@ snapshot[`Plugin - TSIntersectionType 1`] = ` name: "C", optional: false, range: [ + 13, 14, - 15, ], type: "Identifier", typeAnnotation: null, @@ -7235,8 +7235,8 @@ snapshot[`Plugin - TSModuleDeclaration 1`] = ` body: { body: [], range: [ - 10, - 12, + 9, + 11, ], type: "TSModuleBlock", }, @@ -7246,15 +7246,15 @@ snapshot[`Plugin - TSModuleDeclaration 1`] = ` name: "A", optional: false, range: [ + 7, 8, - 9, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 12, + 0, + 11, ], type: "TSModuleDeclaration", } @@ -7274,27 +7274,27 @@ snapshot[`Plugin - TSModuleDeclaration 2`] = ` name: "A", optional: false, range: [ + 35, 36, - 37, ], type: "Identifier", typeAnnotation: null, }, params: [], range: [ - 27, - 45, + 26, + 44, ], returnType: { range: [ - 39, - 45, + 38, + 44, ], type: "TSTypeAnnotation", typeAnnotation: { range: [ - 41, - 45, + 40, + 44, ], type: "TSVoidKeyword", }, @@ -7303,15 +7303,15 @@ snapshot[`Plugin - TSModuleDeclaration 2`] = ` typeParameters: null, }, range: [ - 20, - 45, + 19, + 44, ], type: "ExportNamedDeclaration", }, ], range: [ - 18, - 47, + 17, + 46, ], type: "TSModuleBlock", }, @@ -7321,15 +7321,15 @@ snapshot[`Plugin - TSModuleDeclaration 2`] = ` name: "A", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 47, + 0, + 46, ], type: "TSModuleDeclaration", } @@ -7340,8 +7340,8 @@ snapshot[`Plugin - TSModuleDeclaration + TSModuleBlock 1`] = ` body: { body: [], range: [ - 10, - 12, + 9, + 11, ], type: "TSModuleBlock", }, @@ -7351,15 +7351,15 @@ snapshot[`Plugin - TSModuleDeclaration + TSModuleBlock 1`] = ` name: "A", optional: false, range: [ + 7, 8, - 9, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 12, + 0, + 11, ], type: "TSModuleDeclaration", } @@ -7373,8 +7373,8 @@ snapshot[`Plugin - TSModuleDeclaration + TSModuleBlock 2`] = ` body: { body: [], range: [ - 27, - 29, + 26, + 28, ], type: "TSModuleBlock", }, @@ -7384,22 +7384,22 @@ snapshot[`Plugin - TSModuleDeclaration + TSModuleBlock 2`] = ` name: "B", optional: false, range: [ + 24, 25, - 26, ], type: "Identifier", typeAnnotation: null, }, range: [ - 15, - 29, + 14, + 28, ], type: "TSModuleDeclaration", }, ], range: [ - 13, - 31, + 12, + 30, ], type: "TSModuleBlock", }, @@ -7409,15 +7409,15 @@ snapshot[`Plugin - TSModuleDeclaration + TSModuleBlock 2`] = ` name: "A", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 1, - 31, + 0, + 30, ], type: "TSModuleDeclaration", } @@ -7429,22 +7429,22 @@ snapshot[`Plugin - TSQualifiedName 1`] = ` name: "a", optional: false, range: [ + 9, 10, - 11, ], type: "Identifier", typeAnnotation: null, }, range: [ - 10, - 13, + 9, + 12, ], right: { name: "b", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, @@ -7462,39 +7462,39 @@ snapshot[`Plugin - TSTypeLiteral 1`] = ` name: "a", optional: false, range: [ + 11, 12, - 13, ], type: "Identifier", typeAnnotation: null, }, optional: false, range: [ - 12, - 16, + 11, + 15, ], readonly: false, static: false, type: "TSPropertySignature", typeAnnotation: { range: [ - 13, - 16, + 12, + 15, ], type: "TSTypeAnnotation", typeAnnotation: { literal: { range: [ + 14, 15, - 16, ], raw: "1", type: "Literal", value: 1, }, range: [ + 14, 15, - 16, ], type: "TSLiteralType", }, @@ -7502,8 +7502,8 @@ snapshot[`Plugin - TSTypeLiteral 1`] = ` }, ], range: [ - 10, - 18, + 9, + 17, ], type: "TSTypeLiteral", } @@ -7512,14 +7512,14 @@ snapshot[`Plugin - TSTypeLiteral 1`] = ` snapshot[`Plugin - TSOptionalType 1`] = ` { range: [ - 11, - 18, + 10, + 17, ], type: "TSOptionalType", typeAnnotation: { range: [ - 11, - 17, + 10, + 16, ], type: "TSNumberKeyword", }, @@ -7529,21 +7529,21 @@ snapshot[`Plugin - TSOptionalType 1`] = ` snapshot[`Plugin - TSRestType 1`] = ` { range: [ - 11, - 22, + 10, + 21, ], type: "TSRestType", typeAnnotation: { elementType: { range: [ - 14, - 20, + 13, + 19, ], type: "TSNumberKeyword", }, range: [ - 14, - 22, + 13, + 21, ], type: "TSArrayType", }, @@ -7554,8 +7554,8 @@ snapshot[`Plugin - TSConditionalType 1`] = ` { checkType: { range: [ + 9, 10, - 11, ], type: "TSTypeReference", typeArguments: null, @@ -7563,8 +7563,8 @@ snapshot[`Plugin - TSConditionalType 1`] = ` name: "B", optional: false, range: [ + 9, 10, - 11, ], type: "Identifier", typeAnnotation: null, @@ -7572,8 +7572,8 @@ snapshot[`Plugin - TSConditionalType 1`] = ` }, extendsType: { range: [ + 19, 20, - 21, ], type: "TSTypeReference", typeArguments: null, @@ -7581,8 +7581,8 @@ snapshot[`Plugin - TSConditionalType 1`] = ` name: "C", optional: false, range: [ + 19, 20, - 21, ], type: "Identifier", typeAnnotation: null, @@ -7590,19 +7590,19 @@ snapshot[`Plugin - TSConditionalType 1`] = ` }, falseType: { range: [ - 33, - 39, + 32, + 38, ], type: "TSStringKeyword", }, range: [ - 10, - 39, + 9, + 38, ], trueType: { range: [ - 24, - 30, + 23, + 29, ], type: "TSNumberKeyword", }, @@ -7613,8 +7613,8 @@ snapshot[`Plugin - TSConditionalType 1`] = ` snapshot[`Plugin - TSInferType 1`] = ` { range: [ - 29, - 39, + 28, + 38, ], type: "TSInferType", typeParameter: { @@ -7626,16 +7626,16 @@ snapshot[`Plugin - TSInferType 1`] = ` name: "Item", optional: false, range: [ - 35, - 39, + 34, + 38, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 35, - 39, + 34, + 38, ], type: "TSTypeParameter", }, @@ -7646,14 +7646,14 @@ snapshot[`Plugin - TSTypeOperator 1`] = ` { operator: "keyof", range: [ - 10, - 17, + 9, + 16, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 15, 16, - 17, ], type: "TSTypeReference", typeArguments: null, @@ -7661,8 +7661,8 @@ snapshot[`Plugin - TSTypeOperator 1`] = ` name: "B", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, @@ -7675,14 +7675,14 @@ snapshot[`Plugin - TSTypeOperator 2`] = ` { operator: "unique", range: [ - 21, - 34, + 20, + 33, ], type: "TSTypeOperator", typeAnnotation: { range: [ - 28, - 34, + 27, + 33, ], type: "TSSymbolKeyword", }, @@ -7693,15 +7693,15 @@ snapshot[`Plugin - TSTypeOperator 3`] = ` { operator: "readonly", range: [ - 10, - 21, + 9, + 20, ], type: "TSTypeOperator", typeAnnotation: { elementTypes: [], range: [ - 19, - 21, + 18, + 20, ], type: "TSTupleType", }, @@ -7713,15 +7713,15 @@ snapshot[`Plugin - TSMappedType 1`] = ` nameType: null, optional: undefined, range: [ - 13, - 41, + 12, + 40, ], readonly: undefined, type: "TSMappedType", typeAnnotation: { range: [ - 31, - 38, + 30, + 37, ], type: "TSBooleanKeyword", }, @@ -7730,14 +7730,14 @@ snapshot[`Plugin - TSMappedType 1`] = ` constraint: { operator: "keyof", range: [ - 21, - 28, + 20, + 27, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 26, 27, - 28, ], type: "TSTypeReference", typeArguments: null, @@ -7745,8 +7745,8 @@ snapshot[`Plugin - TSMappedType 1`] = ` name: "T", optional: false, range: [ + 26, 27, - 28, ], type: "Identifier", typeAnnotation: null, @@ -7759,16 +7759,16 @@ snapshot[`Plugin - TSMappedType 1`] = ` name: "P", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 16, - 28, + 15, + 27, ], type: "TSTypeParameter", }, @@ -7780,16 +7780,16 @@ snapshot[`Plugin - TSMappedType 2`] = ` nameType: null, optional: undefined, range: [ - 13, - 45, + 12, + 44, ], readonly: true, type: "TSMappedType", typeAnnotation: { elementTypes: [], range: [ - 40, - 42, + 39, + 41, ], type: "TSTupleType", }, @@ -7798,14 +7798,14 @@ snapshot[`Plugin - TSMappedType 2`] = ` constraint: { operator: "keyof", range: [ - 30, - 37, + 29, + 36, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 35, 36, - 37, ], type: "TSTypeReference", typeArguments: null, @@ -7813,8 +7813,8 @@ snapshot[`Plugin - TSMappedType 2`] = ` name: "T", optional: false, range: [ + 35, 36, - 37, ], type: "Identifier", typeAnnotation: null, @@ -7827,16 +7827,16 @@ snapshot[`Plugin - TSMappedType 2`] = ` name: "P", optional: false, range: [ + 24, 25, - 26, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 25, - 37, + 24, + 36, ], type: "TSTypeParameter", }, @@ -7848,16 +7848,16 @@ snapshot[`Plugin - TSMappedType 3`] = ` nameType: null, optional: undefined, range: [ - 13, - 46, + 12, + 45, ], readonly: "-", type: "TSMappedType", typeAnnotation: { elementTypes: [], range: [ - 41, - 43, + 40, + 42, ], type: "TSTupleType", }, @@ -7866,14 +7866,14 @@ snapshot[`Plugin - TSMappedType 3`] = ` constraint: { operator: "keyof", range: [ - 31, - 38, + 30, + 37, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 36, 37, - 38, ], type: "TSTypeReference", typeArguments: null, @@ -7881,8 +7881,8 @@ snapshot[`Plugin - TSMappedType 3`] = ` name: "T", optional: false, range: [ + 36, 37, - 38, ], type: "Identifier", typeAnnotation: null, @@ -7895,16 +7895,16 @@ snapshot[`Plugin - TSMappedType 3`] = ` name: "P", optional: false, range: [ + 25, 26, - 27, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 26, - 38, + 25, + 37, ], type: "TSTypeParameter", }, @@ -7916,16 +7916,16 @@ snapshot[`Plugin - TSMappedType 4`] = ` nameType: null, optional: undefined, range: [ - 13, - 46, + 12, + 45, ], readonly: "+", type: "TSMappedType", typeAnnotation: { elementTypes: [], range: [ - 41, - 43, + 40, + 42, ], type: "TSTupleType", }, @@ -7934,14 +7934,14 @@ snapshot[`Plugin - TSMappedType 4`] = ` constraint: { operator: "keyof", range: [ - 31, - 38, + 30, + 37, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 36, 37, - 38, ], type: "TSTypeReference", typeArguments: null, @@ -7949,8 +7949,8 @@ snapshot[`Plugin - TSMappedType 4`] = ` name: "T", optional: false, range: [ + 36, 37, - 38, ], type: "Identifier", typeAnnotation: null, @@ -7963,16 +7963,16 @@ snapshot[`Plugin - TSMappedType 4`] = ` name: "P", optional: false, range: [ + 25, 26, - 27, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 26, - 38, + 25, + 37, ], type: "TSTypeParameter", }, @@ -7984,15 +7984,15 @@ snapshot[`Plugin - TSMappedType 5`] = ` nameType: null, optional: true, range: [ - 13, - 42, + 12, + 41, ], readonly: undefined, type: "TSMappedType", typeAnnotation: { range: [ - 32, - 39, + 31, + 38, ], type: "TSBooleanKeyword", }, @@ -8001,14 +8001,14 @@ snapshot[`Plugin - TSMappedType 5`] = ` constraint: { operator: "keyof", range: [ - 21, - 28, + 20, + 27, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 26, 27, - 28, ], type: "TSTypeReference", typeArguments: null, @@ -8016,8 +8016,8 @@ snapshot[`Plugin - TSMappedType 5`] = ` name: "T", optional: false, range: [ + 26, 27, - 28, ], type: "Identifier", typeAnnotation: null, @@ -8030,16 +8030,16 @@ snapshot[`Plugin - TSMappedType 5`] = ` name: "P", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 16, - 28, + 15, + 27, ], type: "TSTypeParameter", }, @@ -8051,15 +8051,15 @@ snapshot[`Plugin - TSMappedType 6`] = ` nameType: null, optional: "-", range: [ - 13, - 43, + 12, + 42, ], readonly: undefined, type: "TSMappedType", typeAnnotation: { range: [ - 33, - 40, + 32, + 39, ], type: "TSBooleanKeyword", }, @@ -8068,14 +8068,14 @@ snapshot[`Plugin - TSMappedType 6`] = ` constraint: { operator: "keyof", range: [ - 21, - 28, + 20, + 27, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 26, 27, - 28, ], type: "TSTypeReference", typeArguments: null, @@ -8083,8 +8083,8 @@ snapshot[`Plugin - TSMappedType 6`] = ` name: "T", optional: false, range: [ + 26, 27, - 28, ], type: "Identifier", typeAnnotation: null, @@ -8097,16 +8097,16 @@ snapshot[`Plugin - TSMappedType 6`] = ` name: "P", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 16, - 28, + 15, + 27, ], type: "TSTypeParameter", }, @@ -8118,15 +8118,15 @@ snapshot[`Plugin - TSMappedType 7`] = ` nameType: null, optional: "+", range: [ - 13, - 43, + 12, + 42, ], readonly: undefined, type: "TSMappedType", typeAnnotation: { range: [ - 33, - 40, + 32, + 39, ], type: "TSBooleanKeyword", }, @@ -8135,14 +8135,14 @@ snapshot[`Plugin - TSMappedType 7`] = ` constraint: { operator: "keyof", range: [ - 21, - 28, + 20, + 27, ], type: "TSTypeOperator", typeAnnotation: { range: [ + 26, 27, - 28, ], type: "TSTypeReference", typeArguments: null, @@ -8150,8 +8150,8 @@ snapshot[`Plugin - TSMappedType 7`] = ` name: "T", optional: false, range: [ + 26, 27, - 28, ], type: "Identifier", typeAnnotation: null, @@ -8164,16 +8164,16 @@ snapshot[`Plugin - TSMappedType 7`] = ` name: "P", optional: false, range: [ + 15, 16, - 17, ], type: "Identifier", typeAnnotation: null, }, out: false, range: [ - 16, - 28, + 15, + 27, ], type: "TSTypeParameter", }, @@ -8184,16 +8184,16 @@ snapshot[`Plugin - TSLiteralType 1`] = ` { literal: { range: [ - 10, - 14, + 9, + 13, ], raw: "true", type: "Literal", value: true, }, range: [ - 10, - 14, + 9, + 13, ], type: "TSLiteralType", } @@ -8203,16 +8203,16 @@ snapshot[`Plugin - TSLiteralType 2`] = ` { literal: { range: [ - 10, - 15, + 9, + 14, ], raw: "false", type: "Literal", value: false, }, range: [ - 10, - 15, + 9, + 14, ], type: "TSLiteralType", } @@ -8222,16 +8222,16 @@ snapshot[`Plugin - TSLiteralType 3`] = ` { literal: { range: [ + 9, 10, - 11, ], raw: "1", type: "Literal", value: 1, }, range: [ + 9, 10, - 11, ], type: "TSLiteralType", } @@ -8241,16 +8241,16 @@ snapshot[`Plugin - TSLiteralType 4`] = ` { literal: { range: [ - 10, - 15, + 9, + 14, ], raw: '"foo"', type: "Literal", value: "foo", }, range: [ - 10, - 15, + 9, + 14, ], type: "TSLiteralType", } @@ -8262,8 +8262,8 @@ snapshot[`Plugin - TSTemplateLiteralType 1`] = ` { cooked: "a ", range: [ - 11, - 13, + 10, + 12, ], raw: "a ", tail: false, @@ -8272,8 +8272,8 @@ snapshot[`Plugin - TSTemplateLiteralType 1`] = ` { cooked: "", range: [ - 22, - 22, + 21, + 21, ], raw: "", tail: true, @@ -8281,15 +8281,15 @@ snapshot[`Plugin - TSTemplateLiteralType 1`] = ` }, ], range: [ - 10, - 23, + 9, + 22, ], type: "TSTemplateLiteralType", types: [ { range: [ - 15, - 21, + 14, + 20, ], type: "TSStringKeyword", }, @@ -8302,15 +8302,15 @@ snapshot[`Plugin - TSTupleType + TSArrayType 1`] = ` elementTypes: [ { range: [ - 11, - 17, + 10, + 16, ], type: "TSNumberKeyword", }, ], range: [ - 10, - 18, + 9, + 17, ], type: "TSTupleType", } @@ -8322,8 +8322,8 @@ snapshot[`Plugin - TSTupleType + TSArrayType 2`] = ` { elementType: { range: [ - 14, - 20, + 13, + 19, ], type: "TSNumberKeyword", }, @@ -8331,22 +8331,22 @@ snapshot[`Plugin - TSTupleType + TSArrayType 2`] = ` name: "x", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 11, - 20, + 10, + 19, ], type: "TSNamedTupleMember", }, ], range: [ - 10, - 21, + 9, + 20, ], type: "TSTupleType", } @@ -8358,8 +8358,8 @@ snapshot[`Plugin - TSTupleType + TSArrayType 3`] = ` { elementType: { range: [ - 14, - 20, + 13, + 19, ], type: "TSNumberKeyword", }, @@ -8367,22 +8367,22 @@ snapshot[`Plugin - TSTupleType + TSArrayType 3`] = ` name: "x", optional: false, range: [ + 10, 11, - 12, ], type: "Identifier", typeAnnotation: null, }, range: [ - 11, - 20, + 10, + 19, ], type: "TSNamedTupleMember", }, ], range: [ - 10, - 21, + 9, + 20, ], type: "TSTupleType", } @@ -8395,14 +8395,14 @@ snapshot[`Plugin - TSTupleType + TSArrayType 4`] = ` elementType: { elementType: { range: [ - 17, - 23, + 16, + 22, ], type: "TSNumberKeyword", }, range: [ - 17, - 25, + 16, + 24, ], type: "TSArrayType", }, @@ -8411,29 +8411,29 @@ snapshot[`Plugin - TSTupleType + TSArrayType 4`] = ` name: "x", optional: false, range: [ + 13, 14, - 15, ], type: "Identifier", typeAnnotation: null, }, range: [ - 11, - 16, + 10, + 15, ], type: "RestElement", typeAnnotation: null, }, range: [ - 11, - 25, + 10, + 24, ], type: "TSNamedTupleMember", }, ], range: [ - 10, - 26, + 9, + 25, ], type: "TSTupleType", } @@ -8443,14 +8443,14 @@ snapshot[`Plugin - TSArrayType 1`] = ` { elementType: { range: [ - 10, - 16, + 9, + 15, ], type: "TSNumberKeyword", }, range: [ - 10, - 18, + 9, + 17, ], type: "TSArrayType", } @@ -8462,15 +8462,15 @@ snapshot[`Plugin - TSTypeQuery 1`] = ` name: "B", optional: false, range: [ + 16, 17, - 18, ], type: "Identifier", typeAnnotation: null, }, range: [ - 10, - 18, + 9, + 17, ], type: "TSTypeQuery", typeArguments: null, @@ -8480,8 +8480,8 @@ snapshot[`Plugin - TSTypeQuery 1`] = ` snapshot[`Plugin - TS keywords 1`] = ` { range: [ - 10, - 13, + 9, + 12, ], type: "TSAnyKeyword", } @@ -8490,8 +8490,8 @@ snapshot[`Plugin - TS keywords 1`] = ` snapshot[`Plugin - TS keywords 2`] = ` { range: [ - 10, - 16, + 9, + 15, ], type: "TSBigIntKeyword", } @@ -8500,8 +8500,8 @@ snapshot[`Plugin - TS keywords 2`] = ` snapshot[`Plugin - TS keywords 3`] = ` { range: [ - 10, - 17, + 9, + 16, ], type: "TSBooleanKeyword", } @@ -8510,8 +8510,8 @@ snapshot[`Plugin - TS keywords 3`] = ` snapshot[`Plugin - TS keywords 4`] = ` { range: [ - 10, - 19, + 9, + 18, ], type: "TSIntrinsicKeyword", } @@ -8520,8 +8520,8 @@ snapshot[`Plugin - TS keywords 4`] = ` snapshot[`Plugin - TS keywords 5`] = ` { range: [ - 10, - 15, + 9, + 14, ], type: "TSNeverKeyword", } @@ -8530,8 +8530,8 @@ snapshot[`Plugin - TS keywords 5`] = ` snapshot[`Plugin - TS keywords 6`] = ` { range: [ - 10, - 14, + 9, + 13, ], type: "TSNullKeyword", } @@ -8540,8 +8540,8 @@ snapshot[`Plugin - TS keywords 6`] = ` snapshot[`Plugin - TS keywords 7`] = ` { range: [ - 10, - 16, + 9, + 15, ], type: "TSNumberKeyword", } @@ -8550,8 +8550,8 @@ snapshot[`Plugin - TS keywords 7`] = ` snapshot[`Plugin - TS keywords 8`] = ` { range: [ - 10, - 16, + 9, + 15, ], type: "TSObjectKeyword", } @@ -8560,8 +8560,8 @@ snapshot[`Plugin - TS keywords 8`] = ` snapshot[`Plugin - TS keywords 9`] = ` { range: [ - 10, - 16, + 9, + 15, ], type: "TSStringKeyword", } @@ -8570,8 +8570,8 @@ snapshot[`Plugin - TS keywords 9`] = ` snapshot[`Plugin - TS keywords 10`] = ` { range: [ - 10, - 16, + 9, + 15, ], type: "TSSymbolKeyword", } @@ -8580,8 +8580,8 @@ snapshot[`Plugin - TS keywords 10`] = ` snapshot[`Plugin - TS keywords 11`] = ` { range: [ - 10, - 19, + 9, + 18, ], type: "TSUndefinedKeyword", } @@ -8590,8 +8590,8 @@ snapshot[`Plugin - TS keywords 11`] = ` snapshot[`Plugin - TS keywords 12`] = ` { range: [ - 10, - 17, + 9, + 16, ], type: "TSUnknownKeyword", } @@ -8600,8 +8600,8 @@ snapshot[`Plugin - TS keywords 12`] = ` snapshot[`Plugin - TS keywords 13`] = ` { range: [ - 10, - 14, + 9, + 13, ], type: "TSVoidKeyword", } diff --git a/tests/unit/lint_plugin_test.ts b/tests/unit/lint_plugin_test.ts index 6c71501c461191..4f660be29f7e49 100644 --- a/tests/unit/lint_plugin_test.ts +++ b/tests/unit/lint_plugin_test.ts @@ -3,45 +3,14 @@ import { assertEquals } from "./test_util.ts"; import { assertSnapshot } from "@std/testing/snapshot"; -// TODO(@marvinhagemeister) Remove once we land "official" types -export interface LintReportData { - // deno-lint-ignore no-explicit-any - node: any; - message: string; -} -// TODO(@marvinhagemeister) Remove once we land "official" types -interface LintContext { - id: string; -} // TODO(@marvinhagemeister) Remove once we land "official" types // deno-lint-ignore no-explicit-any type LintVisitor = Record void>; -// TODO(@marvinhagemeister) Remove once we land "official" types -interface LintRule { - create(ctx: LintContext): LintVisitor; - destroy?(): void; -} - -// TODO(@marvinhagemeister) Remove once we land "official" types -interface LintPlugin { - name: string; - rules: Record; -} - -function runLintPlugin(plugin: LintPlugin, fileName: string, source: string) { - // deno-lint-ignore no-explicit-any - return (Deno as any)[(Deno as any).internal].runLintPlugin( - plugin, - fileName, - source, - ); -} - function testPlugin( source: string, - rule: LintRule, -) { + rule: Deno.lint.Rule, +): Deno.lint.Diagnostic[] { const plugin = { name: "test-plugin", rules: { @@ -49,7 +18,11 @@ function testPlugin( }, }; - return runLintPlugin(plugin, "source.tsx", source); + return Deno.lint.runPlugin( + plugin, + "source.tsx", + source, + ); } interface VisitResult { diff --git a/tests/unit/ops_test.ts b/tests/unit/ops_test.ts index 60f67cdca67ae8..9998ad6d80685b 100644 --- a/tests/unit/ops_test.ts +++ b/tests/unit/ops_test.ts @@ -1,6 +1,6 @@ // Copyright 2018-2025 the Deno authors. MIT license. -const EXPECTED_OP_COUNT = 13; +const EXPECTED_OP_COUNT = 14; Deno.test(function checkExposedOps() { // @ts-ignore TS doesn't allow to index with symbol