fix(query): code-routed unused quickfixes

- Emit Diagnostic.code for unused diagnostics and avoid message matching

- Route dead-code code actions exclusively by Diagnostic.code

- Update fixtures and snapshots (incl exported-mode)
This commit is contained in:
Hong Jiarong 2025-12-15 21:29:33 +08:00
parent 9d0308febc
commit ec4cce5475
85 changed files with 314 additions and 102 deletions

View file

@ -629,7 +629,11 @@ mod call_info_tests {
mod lint_tests {
use std::collections::BTreeMap;
use tinymist_lint::KnownIssues;
use tinymist_analysis::{
adt::interner::Interned,
syntax::{Decl, Expr},
};
use tinymist_lint::{DeadCodeConfig, KnownIssues};
use crate::tests::*;
@ -662,4 +666,54 @@ mod lint_tests {
assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
});
}
#[test]
fn test_dead_code_exported() {
snapshot_testing("dead_code_exported", &|ctx, path| {
let source = ctx.source_by_path(&path).unwrap();
let ei = ctx.expr_stage(&source);
let ti = ctx.type_check(&source);
let has_references = |decl: &Interned<Decl>| -> bool {
if matches!(decl.as_ref(), Decl::PathStem(_)) {
if ei.resolves.values().any(|r| {
matches!(
r.step.as_ref(),
Some(Expr::Decl(step_decl)) if step_decl == decl
)
}) {
return true;
}
} else if ei
.get_refs(decl.clone())
.any(|(_, r)| r.as_ref().decl != *decl)
{
return true;
}
false
};
let dead_code_config = DeadCodeConfig {
check_exported: true,
..DeadCodeConfig::default()
};
let result = tinymist_lint::lint_file_with_dead_code_config(
ctx.world(),
&ei,
ti,
KnownIssues::default(),
has_references,
&dead_code_config,
)
.diagnostics;
let result = crate::diagnostics::DiagWorker::new(ctx).convert_all(result.iter());
let result = result
.into_iter()
.map(|(k, v)| (file_uri_(&k), v))
.collect::<BTreeMap<_, _>>();
assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
});
}
}

View file

@ -15,6 +15,13 @@ use crate::analysis::LinkTarget;
use crate::prelude::*;
use crate::syntax::{InterpretMode, interpret_mode_at};
const UNUSED_CODE_IMPORTED_ITEM: &str = "tinymist.unused.import";
const UNUSED_CODE_MODULE_IMPORT: &str = "tinymist.unused.module_import";
const UNUSED_CODE_MODULE: &str = "tinymist.unused.module";
const UNUSED_CODE_SYMBOL: &str = "tinymist.unused.symbol";
const UNUSED_CODE_EXPORTED_DOCUMENTED_FUNCTION: &str =
"tinymist.unused.exported_documented_function";
/// Analyzes the document and provides code actions.
pub struct CodeActionWorker<'a> {
/// The local analysis context to work with.
@ -75,11 +82,32 @@ impl<'a> CodeActionWorker<'a> {
}
for diag in &context.diagnostics {
let Some(source) = diag.source.as_deref() else {
let Some(diag_range) = self.ctx.to_typst_range(diag.range, &self.source) else {
continue;
};
let Some(diag_range) = self.ctx.to_typst_range(diag.range, &self.source) else {
if let Some(unused_code) = unused_code(diag) {
if unused_code == UNUSED_CODE_IMPORTED_ITEM {
self.autofix_remove_unused_import(root, &diag_range);
} else if unused_code == UNUSED_CODE_MODULE_IMPORT
|| unused_code == UNUSED_CODE_MODULE
{
self.autofix_remove_declaration(root, &diag_range);
} else {
let Some(binding_range) = self.binding_range_for_diag(root, &diag_range, diag)
else {
continue;
};
self.autofix_unused_symbol(&binding_range);
self.autofix_replace_with_placeholder(root, &binding_range);
self.autofix_remove_declaration(root, &binding_range);
}
continue;
}
let Some(source) = diag.source.as_deref() else {
continue;
};
@ -90,23 +118,6 @@ impl<'a> CodeActionWorker<'a> {
Some(AutofixKind::FileNotFound) => {
self.autofix_file_not_found(root, &diag_range);
}
Some(AutofixKind::MarkUnusedSymbol) => {
if diag.message.starts_with("unused import:") {
self.autofix_remove_unused_import(root, &diag_range);
} else if diag.message.starts_with("unused module") {
self.autofix_remove_declaration(root, &diag_range);
} else {
let Some(binding_range) =
self.binding_range_for_diag(root, &diag_range, diag)
else {
continue;
};
self.autofix_unused_symbol(&binding_range);
self.autofix_replace_with_placeholder(root, &binding_range);
self.autofix_remove_declaration(root, &binding_range);
}
}
_ => {}
}
}
@ -521,33 +532,12 @@ impl<'a> CodeActionWorker<'a> {
diag_range: &Range<usize>,
diag: &lsp_types::Diagnostic,
) -> Option<Range<usize>> {
let _ = (root, diag);
if diag_range.is_empty() {
return None;
}
if let Some(text) = self.source.text().get(diag_range.clone()) {
if is_plain_identifier(text) {
return Some(diag_range.clone());
}
}
let name = extract_backticked_name(&diag.message)?;
let cursor = (diag_range.start + 1).min(self.source.text().len());
let node = root.leaf_at_compat(cursor)?;
let decl_node = self.find_declaration_ancestor(&node)?;
if decl_node.kind() == SyntaxKind::LetBinding {
let let_binding = decl_node.cast::<ast::LetBinding>()?;
for binding in let_binding.kind().bindings() {
let binding_node = decl_node.find(binding.span())?;
let range = binding_node.range();
if self.source.text().get(range.clone())? == name {
return Some(range);
}
}
}
None
Some(diag_range.clone())
}
fn expand_import_item_range(&self, mut range: Range<usize>) -> Range<usize> {
@ -1013,14 +1003,9 @@ impl<'a> CodeActionWorker<'a> {
enum AutofixKind {
UnknownVariable,
FileNotFound,
MarkUnusedSymbol,
}
fn match_autofix_kind(source: &str, msg: &str) -> Option<AutofixKind> {
if msg.starts_with("unused ") {
return Some(AutofixKind::MarkUnusedSymbol);
}
if source == "typst" {
static PATTERNS: &[(&str, AutofixKind)] = &[
("unknown variable", AutofixKind::UnknownVariable),
@ -1037,15 +1022,8 @@ fn match_autofix_kind(source: &str, msg: &str) -> Option<AutofixKind> {
None
}
fn extract_backticked_name(message: &str) -> Option<&str> {
let start = message.find('`')?;
let rest = &message[start + 1..];
let end = rest.find('`')?;
Some(&rest[..end])
}
fn is_ascii_ident(ch: u8) -> bool {
matches!(ch, b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9')
matches!(ch, b'_' | b'-' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9')
}
fn is_plain_identifier(name: &str) -> bool {
@ -1060,3 +1038,17 @@ fn is_plain_identifier(name: &str) -> bool {
chars.all(|ch| ch == '_' || ch.is_ascii_alphanumeric())
}
fn unused_code(diag: &lsp_types::Diagnostic) -> Option<&str> {
match diag.code.as_ref()? {
lsp_types::NumberOrString::String(s) => match s.as_str() {
UNUSED_CODE_IMPORTED_ITEM
| UNUSED_CODE_MODULE_IMPORT
| UNUSED_CODE_MODULE
| UNUSED_CODE_SYMBOL
| UNUSED_CODE_EXPORTED_DOCUMENTED_FUNCTION => Some(s.as_str()),
_ => None,
},
_ => None,
}
}

View file

@ -1,6 +1,6 @@
use std::borrow::Cow;
use tinymist_lint::KnownIssues;
use tinymist_lint::{DOCUMENTED_EXPORTED_FUNCTION_HINT, KnownIssues};
use tinymist_world::vfs::WorkspaceResolver;
use typst::syntax::Span;
@ -14,6 +14,13 @@ pub type DiagnosticsMap = HashMap<Url, EcoVec<Diagnostic>>;
type TypstDiagnostic = typst::diag::SourceDiagnostic;
type TypstSeverity = typst::diag::Severity;
const UNUSED_CODE_IMPORTED_ITEM: &str = "tinymist.unused.import";
const UNUSED_CODE_MODULE_IMPORT: &str = "tinymist.unused.module_import";
const UNUSED_CODE_MODULE: &str = "tinymist.unused.module";
const UNUSED_CODE_SYMBOL: &str = "tinymist.unused.symbol";
const UNUSED_CODE_EXPORTED_DOCUMENTED_FUNCTION: &str =
"tinymist.unused.exported_documented_function";
/// Converts a list of Typst diagnostics to LSP diagnostics,
/// with potential refinements on the error messages.
pub fn convert_diagnostics<'a>(
@ -122,13 +129,20 @@ impl<'w> DiagWorker<'w> {
let lsp_severity = diagnostic_severity(&typst_diagnostic);
let lsp_message = diagnostic_message(&typst_diagnostic);
let is_unused = typst_diagnostic.message.starts_with("unused ");
let unused_code = is_unused
.then(|| self.unused_code(&typst_diagnostic))
.flatten();
let is_documented_exported_function =
unused_code.is_some_and(|code| code == UNUSED_CODE_EXPORTED_DOCUMENTED_FUNCTION);
let diagnostic = Diagnostic {
range: lsp_range,
severity: Some(lsp_severity),
message: lsp_message,
source: Some(self.source.to_owned()),
tags: is_unused.then(|| vec![DiagnosticTag::UNNECESSARY]),
code: unused_code.map(|code| lsp_types::NumberOrString::String(code.to_string())),
tags: (is_unused && !is_documented_exported_function)
.then(|| vec![DiagnosticTag::UNNECESSARY]),
related_information: (!typst_diagnostic.trace.is_empty()).then(|| {
typst_diagnostic
.trace
@ -182,6 +196,31 @@ impl<'w> DiagWorker<'w> {
None => LspRange::new(LspPosition::new(0, 0), LspPosition::new(0, 0)),
}
}
fn unused_code(&self, diag: &TypstDiagnostic) -> Option<&'static str> {
let msg = diag.message.as_str();
if msg.starts_with("unused import:") {
return Some(UNUSED_CODE_IMPORTED_ITEM);
}
if msg.starts_with("unused module import") {
return Some(UNUSED_CODE_MODULE_IMPORT);
}
if msg.starts_with("unused module:") {
return Some(UNUSED_CODE_MODULE);
}
if msg.starts_with("unused function:")
&& diag
.hints
.iter()
.any(|hint| hint.as_str() == DOCUMENTED_EXPORTED_FUNCTION_HINT)
{
return Some(UNUSED_CODE_EXPORTED_DOCUMENTED_FUNCTION);
}
if msg.starts_with("unused ") {
return Some(UNUSED_CODE_SYMBOL);
}
None
}
}
fn diagnostic_severity(typst_diagnostic: &TypstDiagnostic) -> DiagnosticSeverity {

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/array_dict_usage.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused`\nHint: consider removing this variable or prefixing with underscore: `_unused`",
"range": "3:1:3:15",
"range": "3:5:3:11",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/closure_capture.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_not_captured`\nHint: consider removing this variable or prefixing with underscore: `_unused_not_captured`",
"range": "2:1:2:30",
"range": "2:5:2:24",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/conditional_usage.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused`\nHint: consider removing this variable or prefixing with underscore: `_unused`",
"range": "4:1:4:16",
"range": "4:5:4:11",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/contextual_usage.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_ctx`\nHint: consider removing this variable or prefixing with underscore: `_unused_ctx`",
"range": "2:1:2:20",
"range": "2:5:2:15",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_array.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_x`\nHint: consider removing this variable or prefixing with underscore: `_unused_x`",
"range": "6:1:6:46",
"range": "6:15:6:23",
"severity": 4,
"source": "typst",
"tags": [
@ -15,8 +16,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_array.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `c2`\nHint: consider removing this variable or prefixing with underscore: `_c2`",
"range": "6:1:6:46",
"range": "6:31:6:33",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_dict.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_x`\nHint: consider removing this variable or prefixing with underscore: `_unused_x`",
"range": "6:1:6:52",
"range": "6:18:6:26",
"severity": 4,
"source": "typst",
"tags": [
@ -15,8 +16,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_dict.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `c2`\nHint: consider removing this variable or prefixing with underscore: `_c2`",
"range": "6:1:6:52",
"range": "6:37:6:39",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_spread.ty
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_rest`\nHint: consider removing this variable or prefixing with underscore: `_unused_rest`",
"range": "4:1:4:30",
"range": "4:11:4:22",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/duplicate_module_alias_
{
"main.typ": [
{
"code": "tinymist.unused.import",
"message": "unused import: `b`\nHint: consider removing this unused import",
"range": "3:19:3:20",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/duplicate_module_alias_
{
"main.typ": [
{
"code": "tinymist.unused.import",
"message": "unused import: `b`\nHint: consider removing this unused import",
"range": "3:19:3:20",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/duplicate_module_wildca
{
"main.typ": [
{
"code": "tinymist.unused.module_import",
"message": "unused module import\nHint: imported modules should be used or the import should be removed",
"range": "3:1:3:18",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/function_as_value.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `unused_callback`\nHint: consider removing this function or prefixing with underscore: `_unused_callback`",
"range": "6:5:6:20",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/import_module_alias_unu
{
"main.typ": [
{
"code": "tinymist.unused.import",
"message": "unused import: `util`\nHint: consider removing this unused import",
"range": "2:19:2:23",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/import_module_unused.ty
{
"main.typ": [
{
"code": "tinymist.unused.module",
"message": "unused module: `u`\nHint: imported modules should be used or the import should be removed",
"range": "2:8:2:15",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/imported_unused.typ
{
"main.typ": [
{
"code": "tinymist.unused.import",
"message": "unused import: `Bbar`\nHint: consider removing this unused import",
"range": "2:24:2:28",
"severity": 4,
@ -15,6 +16,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/imported_unused.typ
]
},
{
"code": "tinymist.unused.import",
"message": "unused import: `foo`\nHint: consider removing this unused import",
"range": "2:30:2:33",
"severity": 4,
@ -24,6 +26,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/imported_unused.typ
]
},
{
"code": "tinymist.unused.module_import",
"message": "unused module import\nHint: imported modules should be used or the import should be removed",
"range": "2:1:2:33",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/imported_used.typ
{
"main.typ": [
{
"code": "tinymist.unused.import",
"message": "unused import: `foo`\nHint: consider removing this unused import",
"range": "2:31:2:34",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/loop_variables.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_item`\nHint: consider removing this variable or prefixing with underscore: `_unused_item`",
"range": "1:5:1:16",
"severity": 4,

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/method_chain.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_obj`\nHint: consider removing this variable or prefixing with underscore: `_unused_obj`",
"range": "8:1:8:24",
"range": "8:5:8:15",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/module_item_wildcard_un
{
"main.typ": [
{
"code": "tinymist.unused.module_import",
"message": "unused module import\nHint: imported modules should be used or the import should be removed",
"range": "2:1:2:18",
"severity": 4,

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused1`\nHint: consider removing this variable or prefixing with underscore: `_unused1`",
"range": "1:1:1:16",
"range": "1:5:1:12",
"severity": 4,
"source": "typst",
"tags": [
@ -15,8 +16,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused2`\nHint: consider removing this variable or prefixing with underscore: `_unused2`",
"range": "2:1:2:16",
"range": "2:5:2:12",
"severity": 4,
"source": "typst",
"tags": [
@ -24,8 +26,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused3`\nHint: consider removing this variable or prefixing with underscore: `_unused3`",
"range": "4:1:4:16",
"range": "4:5:4:12",
"severity": 4,
"source": "typst",
"tags": [
@ -33,6 +36,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `unused_func1`\nHint: consider removing this function or prefixing with underscore: `_unused_func1`",
"range": "6:5:6:17",
"severity": 4,
@ -42,6 +46,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `unused_func2`\nHint: consider removing this function or prefixing with underscore: `_unused_func2`",
"range": "8:5:8:17",
"severity": 4,

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/nested_scope.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `inner_unused`\nHint: consider removing this variable or prefixing with underscore: `_inner_unused`",
"range": "4:2:4:22",
"range": "4:6:4:18",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/pattern_destructure.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_b`\nHint: consider removing this variable or prefixing with underscore: `_unused_b`",
"range": "1:1:1:43",
"range": "1:14:1:22",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/shadowing.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `x`\nHint: consider removing this variable or prefixing with underscore: `_x`",
"range": "1:1:1:10",
"range": "1:5:1:6",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/show_set_rules.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_style`\nHint: consider removing this variable or prefixing with underscore: `_unused_style`",
"range": "1:1:1:23",
"range": "1:5:1:17",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/underscore_prefix.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `normal_unused`\nHint: consider removing this variable or prefixing with underscore: `_normal_unused`",
"range": "4:1:4:24",
"range": "4:5:4:18",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/unused_function.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `unused_func`\nHint: consider removing this function or prefixing with underscore: `_unused_func`",
"range": "1:5:1:16",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/unused_parameter.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_param`\nHint: if this parameter is intentionally unused, prefix it with underscore: `_unused_param`",
"range": "1:22:1:34",
"severity": 4,

View file

@ -6,8 +6,9 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/unused_variable.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `unused_var`\nHint: consider removing this variable or prefixing with underscore: `_unused_var`",
"range": "1:1:1:20",
"range": "1:5:1:15",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/array_dict_usage.typ
}
],
"message": "unused variable: `unused`\nHint: consider removing this variable or prefixing with underscore: `_unused`",
"range": "3:1:3:15"
"range": "3:5:3:11"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/closure_capture.typ
}
],
"message": "unused variable: `unused_not_captured`\nHint: consider removing this variable or prefixing with underscore: `_unused_not_captured`",
"range": "2:1:2:30"
"range": "2:5:2:24"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/conditional_usage.typ
}
],
"message": "unused variable: `unused`\nHint: consider removing this variable or prefixing with underscore: `_unused`",
"range": "4:1:4:16"
"range": "4:5:4:11"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/contextual_usage.typ
}
],
"message": "unused variable: `unused_ctx`\nHint: consider removing this variable or prefixing with underscore: `_unused_ctx`",
"range": "2:1:2:20"
"range": "2:5:2:15"
}
]

View file

@ -39,7 +39,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_array.typ
}
],
"message": "unused variable: `unused_x`\nHint: consider removing this variable or prefixing with underscore: `_unused_x`",
"range": "6:1:6:46"
"range": "6:15:6:23"
},
{
"actions": [
@ -75,6 +75,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_array.typ
}
],
"message": "unused variable: `c2`\nHint: consider removing this variable or prefixing with underscore: `_c2`",
"range": "6:1:6:46"
"range": "6:31:6:33"
}
]

View file

@ -39,7 +39,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_dict.typ
}
],
"message": "unused variable: `unused_x`\nHint: consider removing this variable or prefixing with underscore: `_unused_x`",
"range": "6:1:6:52"
"range": "6:18:6:26"
},
{
"actions": [
@ -75,6 +75,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_dict.typ
}
],
"message": "unused variable: `c2`\nHint: consider removing this variable or prefixing with underscore: `_c2`",
"range": "6:1:6:52"
"range": "6:37:6:39"
}
]

View file

@ -24,6 +24,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/destructuring_spread.ty
}
],
"message": "unused variable: `unused_rest`\nHint: consider removing this variable or prefixing with underscore: `_unused_rest`",
"range": "4:1:4:30"
"range": "4:11:4:22"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/method_chain.typ
}
],
"message": "unused variable: `unused_obj`\nHint: consider removing this variable or prefixing with underscore: `_unused_obj`",
"range": "8:1:8:24"
"range": "8:5:8:15"
}
]

View file

@ -54,7 +54,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
}
],
"message": "unused variable: `unused1`\nHint: consider removing this variable or prefixing with underscore: `_unused1`",
"range": "1:1:1:16"
"range": "1:5:1:12"
},
{
"actions": [
@ -105,7 +105,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
}
],
"message": "unused variable: `unused2`\nHint: consider removing this variable or prefixing with underscore: `_unused2`",
"range": "2:1:2:16"
"range": "2:5:2:12"
},
{
"actions": [
@ -156,7 +156,7 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/multiple_unused.typ
}
],
"message": "unused variable: `unused3`\nHint: consider removing this variable or prefixing with underscore: `_unused3`",
"range": "4:1:4:16"
"range": "4:5:4:12"
},
{
"actions": [

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/nested_scope.typ
}
],
"message": "unused variable: `inner_unused`\nHint: consider removing this variable or prefixing with underscore: `_inner_unused`",
"range": "4:2:4:22"
"range": "4:6:4:18"
}
]

View file

@ -39,6 +39,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/pattern_destructure.typ
}
],
"message": "unused variable: `unused_b`\nHint: consider removing this variable or prefixing with underscore: `_unused_b`",
"range": "1:1:1:43"
"range": "1:14:1:22"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/shadowing.typ
}
],
"message": "unused variable: `x`\nHint: consider removing this variable or prefixing with underscore: `_x`",
"range": "1:1:1:10"
"range": "1:5:1:6"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/show_set_rules.typ
}
],
"message": "unused variable: `unused_style`\nHint: consider removing this variable or prefixing with underscore: `_unused_style`",
"range": "1:1:1:23"
"range": "1:5:1:17"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/underscore_prefix.typ
}
],
"message": "unused variable: `normal_unused`\nHint: consider removing this variable or prefixing with underscore: `_normal_unused`",
"range": "4:1:4:24"
"range": "4:5:4:18"
}
]

View file

@ -54,6 +54,6 @@ input_file: crates/tinymist-query/src/fixtures/dead_code/unused_variable.typ
}
],
"message": "unused variable: `unused_var`\nHint: consider removing this variable or prefixing with underscore: `_unused_var`",
"range": "1:1:1:20"
"range": "1:5:1:15"
}
]

View file

@ -0,0 +1,7 @@
/// path: main.typ
/// compile: true
#let api(x) = x
#let value = 1
#value

View file

@ -0,0 +1,8 @@
/// path: main.typ
/// compile: true
/// Public API documentation.
#let api(x) = x
#let value = 1
#value

View file

@ -0,0 +1,19 @@
---
source: crates/tinymist-query/src/analysis.rs
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
input_file: crates/tinymist-query/src/fixtures/dead_code_exported/exported_unused.typ
---
{
"main.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `api`\nHint: this function is exported but never used",
"range": "2:5:2:8",
"severity": 4,
"source": "typst",
"tags": [
1
]
}
]
}

View file

@ -0,0 +1,16 @@
---
source: crates/tinymist-query/src/analysis.rs
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
input_file: crates/tinymist-query/src/fixtures/dead_code_exported/exported_unused_docstring.typ
---
{
"main.typ": [
{
"code": "tinymist.unused.exported_documented_function",
"message": "unused function: `api`\nHint: this function is exported but never used\nHint: this function is exported and documented; it may be part of the public API\nHint: if this is intended public API, you can ignore this diagnostic; otherwise consider removing it",
"range": "3:5:3:8",
"severity": 4,
"source": "typst"
}
]
}

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/assign_ok.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/binary.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/binary_type_compare_str.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/binary_type_compare_str_inpu
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/binary_type_compare_str_let.
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/break_for.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `value`\nHint: consider removing this variable or prefixing with underscore: `_value`",
"range": "0:5:0:10",
"severity": 4,

View file

@ -20,6 +20,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/break_func_for.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `value`\nHint: consider removing this variable or prefixing with underscore: `_value`",
"range": "0:5:0:10",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_array.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -18,6 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_common.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_common_break.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_common_break2.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_equation.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,
@ -21,8 +22,9 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `i`\nHint: consider removing this variable or prefixing with underscore: `_i`",
"range": "0:1:3:1",
"range": "0:15:0:16",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for2.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,
@ -21,8 +22,9 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for2.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `i`\nHint: consider removing this variable or prefixing with underscore: `_i`",
"range": "0:1:3:1",
"range": "0:15:0:16",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for3.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,
@ -21,8 +22,9 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for3.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `i`\nHint: consider removing this variable or prefixing with underscore: `_i`",
"range": "0:1:2:1",
"range": "0:15:0:16",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for4.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,
@ -21,8 +22,9 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for4.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `i`\nHint: consider removing this variable or prefixing with underscore: `_i`",
"range": "0:1:3:1",
"range": "0:15:0:16",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for5.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,
@ -21,8 +22,9 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_for5.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `i`\nHint: consider removing this variable or prefixing with underscore: `_i`",
"range": "0:1:3:1",
"range": "0:15:0:16",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_hello.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_if.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -18,6 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_if2.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -18,6 +18,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_join.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_join_partial.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_join_partial2.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_set.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_show.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -12,6 +12,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/discard_show_content.typ
"source": "typst"
},
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_loop2.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_loop3.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `mul-mat`\nHint: consider removing this function or prefixing with underscore: `_mul-mat`",
"range": "0:5:0:12",
"severity": 4,
@ -15,8 +16,9 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_loop3.typ
]
},
{
"code": "tinymist.unused.symbol",
"message": "unused variable: `matrix`\nHint: consider removing this variable or prefixing with underscore: `_matrix`",
"range": "0:1:9:1",
"range": "3:6:3:12",
"severity": 4,
"source": "typst",
"tags": [

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_partial.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_partial2.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `as-padding-dict`\nHint: consider removing this function or prefixing with underscore: `_as-padding-dict`",
"range": "0:5:0:20",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_partial_if.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `get-op`\nHint: consider removing this function or prefixing with underscore: `_get-op`",
"range": "0:5:0:11",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/return_regular.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/show_good.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/show_good2.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/while_good.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,

View file

@ -6,6 +6,7 @@ input_file: crates/tinymist-query/src/fixtures/lint/while_good2.typ
{
"s0.typ": [
{
"code": "tinymist.unused.symbol",
"message": "unused function: `f`\nHint: consider removing this function or prefixing with underscore: `_f`",
"range": "0:5:0:6",
"severity": 4,