mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 09:52:27 +00:00
feat: fledge diagnostic hint patterns by updating 2 refiners (#1544)
* feat: support more diagnostic hint patterns about typst v0.13 deprecation
* feat: add out of root hint diagnostic refiner
* optimize multi-pattern search with `RegexSet`
* add "cannot spread content"
* fix test
* Revert "add "cannot spread content""
This reverts commit 7d6c981413
.
This commit is contained in:
parent
766a41f4d5
commit
8d9a8f8bed
5 changed files with 103 additions and 8 deletions
|
@ -5,6 +5,9 @@ use typst::syntax::Span;
|
|||
|
||||
use crate::{prelude::*, LspWorldExt};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::RegexSet;
|
||||
|
||||
/// Stores diagnostics for files.
|
||||
pub type DiagnosticsMap = HashMap<Url, EcoVec<Diagnostic>>;
|
||||
|
||||
|
@ -64,7 +67,8 @@ fn convert_diagnostic(
|
|||
let mut diag = Cow::Borrowed(typst_diagnostic);
|
||||
|
||||
// Extend more refiners here by adding their instances.
|
||||
let refiners = &[&DeprecationRefiner::<13> {}];
|
||||
let refiners: &[&dyn DiagnosticRefiner] =
|
||||
&[&DeprecationRefiner::<13> {}, &OutOfRootHintRefiner {}];
|
||||
|
||||
// NOTE: It would be nice to have caching here.
|
||||
for refiner in refiners {
|
||||
|
@ -195,9 +199,19 @@ trait DiagnosticRefiner {
|
|||
|
||||
struct DeprecationRefiner<const MINOR: usize>();
|
||||
|
||||
static DEPRECATION_PATTERNS: Lazy<RegexSet> = Lazy::new(|| {
|
||||
RegexSet::new([
|
||||
r"unknown variable: style",
|
||||
r"unexpected argument: fill",
|
||||
r"type state has no method `display`",
|
||||
r"only element functions can be used as selectors",
|
||||
])
|
||||
.expect("Invalid regular expressions")
|
||||
});
|
||||
|
||||
impl DiagnosticRefiner for DeprecationRefiner<13> {
|
||||
fn matches(&self, raw: &TypstDiagnostic) -> bool {
|
||||
raw.message.contains("unknown variable: style")
|
||||
DEPRECATION_PATTERNS.is_match(&raw.message)
|
||||
}
|
||||
|
||||
fn refine(&self, raw: TypstDiagnostic) -> TypstDiagnostic {
|
||||
|
@ -209,3 +223,20 @@ impl DiagnosticRefiner for DeprecationRefiner<13> {
|
|||
))
|
||||
}
|
||||
}
|
||||
|
||||
struct OutOfRootHintRefiner();
|
||||
|
||||
impl DiagnosticRefiner for OutOfRootHintRefiner {
|
||||
fn matches(&self, raw: &TypstDiagnostic) -> bool {
|
||||
raw.message.contains("failed to load file (access denied)")
|
||||
&& raw
|
||||
.hints
|
||||
.iter()
|
||||
.any(|hint| hint.contains("cannot read file outside of project root"))
|
||||
}
|
||||
|
||||
fn refine(&self, mut raw: TypstDiagnostic) -> TypstDiagnostic {
|
||||
raw.hints.clear();
|
||||
raw.with_hint("Cannot read file outside of project root.")
|
||||
}
|
||||
}
|
||||
|
|
1
editors/vscode/e2e-workspaces/diag/out-of-root.typ
Normal file
1
editors/vscode/e2e-workspaces/diag/out-of-root.typ
Normal file
|
@ -0,0 +1 @@
|
|||
#import "../out-of-root/library.typ": item
|
|
@ -1,2 +1,17 @@
|
|||
#style(styles => {
|
||||
})
|
||||
// Test Typst v0.13 deprecated diagnostics.
|
||||
|
||||
--- style-function ---
|
||||
|
||||
#style(styles => {})
|
||||
|
||||
--- outline-fill-argument ---
|
||||
|
||||
#set outline(fill: white)
|
||||
|
||||
--- state-display-method ---
|
||||
|
||||
#state("ok").display()
|
||||
|
||||
--- locate-function ---
|
||||
|
||||
#locate((loc) => {})
|
||||
|
|
1
editors/vscode/e2e-workspaces/out-of-root/library.typ
Normal file
1
editors/vscode/e2e-workspaces/out-of-root/library.typ
Normal file
|
@ -0,0 +1 @@
|
|||
#let item = 1
|
|
@ -4,6 +4,23 @@ import * as vscode from "vscode";
|
|||
import type { Context } from ".";
|
||||
|
||||
export async function getTests(ctx: Context) {
|
||||
function parseTestFile(content: string): Record<string, string> {
|
||||
// 初始化结果对象
|
||||
const result: Record<string, string> = {};
|
||||
const sectionRegex = /---\s*(\S+)\s*---\r?\n([\s\S]*?)(?=\r?\n---|$)/g;
|
||||
let match;
|
||||
while ((match = sectionRegex.exec(content)) !== null) {
|
||||
const sectionName = match[1];
|
||||
const sectionContent = match[2].trim();
|
||||
result[sectionName] = sectionContent;
|
||||
}
|
||||
|
||||
if (Object.keys(result).length === 0)
|
||||
return { "default": content };
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
await ctx.suite("diagnostics", (suite) => {
|
||||
vscode.window.showInformationMessage("Start all tests.");
|
||||
const workspaceUri = ctx.getWorkspace("diag");
|
||||
|
@ -52,14 +69,44 @@ export async function getTests(ctx: Context) {
|
|||
suite.addTest("typst0.13 diag hints", async () => {
|
||||
const mainUrl = vscode.Uri.joinPath(workspaceUri, "typst013.typ");
|
||||
|
||||
const [_1, _2, diags] = await ctx.diagnostics(1, async () => {
|
||||
const editor = await ctx.openDocument(mainUrl);
|
||||
const testCases = parseTestFile(editor.document.getText());
|
||||
|
||||
const checkTypstHint = (diags: vscode.Diagnostic[]) => {
|
||||
ctx.expect(diags).to.have.lengthOf(1);
|
||||
const diag = diags[0];
|
||||
ctx.expect(diag.message).contains("Hint: Typst 0.13");
|
||||
};
|
||||
|
||||
for (const [name, content] of Object.entries(testCases)) {
|
||||
console.log(`Running test case ${name}`);
|
||||
const stats = await ctx.diagnostics(1, async () => {
|
||||
await editor.edit((edit) => {
|
||||
edit.replace(new vscode.Range(0, 0, editor.document.lineCount, 0), content);
|
||||
});
|
||||
});
|
||||
checkTypstHint(stats[2]);
|
||||
await ctx.diagnostics(0, async () => {
|
||||
await editor.edit((edit) => {
|
||||
edit.delete(new vscode.Range(0, 0, editor.document.lineCount, 0));
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
suite.addTest("out of root diag hints", async () => {
|
||||
const mainUrl = vscode.Uri.joinPath(workspaceUri, "out-of-root.typ");
|
||||
|
||||
const stats = await ctx.diagnostics(1, async () => {
|
||||
await ctx.openDocument(mainUrl);
|
||||
ctx.timeout(400);
|
||||
});
|
||||
|
||||
const diags = stats[2];
|
||||
|
||||
ctx.expect(diags).to.have.lengthOf(1);
|
||||
const diag = diags[0];
|
||||
ctx.expect(diag.message).contains("Hint: Typst 0.13");
|
||||
ctx.expect(diag.message).contains("Hint: Cannot read file outside of project root");
|
||||
ctx.expect(diag.message).not.contains("Hint: you can adjust the project root with the --root argument");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue