mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-04 18:28:02 +00:00
feat: allow to disable lint or lint on save (#1658)
* feat: allow to disable lint or lint on save * fix: description
This commit is contained in:
parent
39d13c83f6
commit
2709aaf429
7 changed files with 140 additions and 33 deletions
|
@ -12,7 +12,7 @@ use tinymist_analysis::stats::AllocStats;
|
|||
use tinymist_analysis::ty::term_value;
|
||||
use tinymist_analysis::{analyze_expr_, analyze_import_};
|
||||
use tinymist_lint::LintInfo;
|
||||
use tinymist_project::{LspComputeGraph, LspWorld};
|
||||
use tinymist_project::{LspComputeGraph, LspWorld, TaskWhen};
|
||||
use tinymist_std::hash::{hash128, FxDashMap};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tinymist_world::debug_loc::DataSource;
|
||||
|
@ -69,6 +69,8 @@ pub struct Analysis {
|
|||
pub completion_feat: CompletionFeat,
|
||||
/// The editor's color theme.
|
||||
pub color_theme: ColorTheme,
|
||||
/// When to trigger the lint.
|
||||
pub lint: TaskWhen,
|
||||
/// The periscope provider.
|
||||
pub periscope: Option<Arc<dyn PeriscopeProvider + Send + Sync>>,
|
||||
/// The global worker resources for analysis.
|
||||
|
|
|
@ -42,21 +42,8 @@ impl ExportTimings {
|
|||
timing: Option<TaskWhen>,
|
||||
docs: Option<&D>,
|
||||
) -> Option<bool> {
|
||||
let s = snap.signal;
|
||||
let when = timing.unwrap_or(TaskWhen::Never);
|
||||
if !matches!(when, TaskWhen::Never) && s.by_entry_update {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
match when {
|
||||
TaskWhen::Never => Some(false),
|
||||
TaskWhen::OnType => Some(s.by_mem_events),
|
||||
TaskWhen::OnSave => Some(s.by_fs_events),
|
||||
TaskWhen::OnDocumentHasTitle if s.by_fs_events => {
|
||||
docs.map(|doc| doc.info().title.is_some())
|
||||
}
|
||||
TaskWhen::OnDocumentHasTitle => Some(false),
|
||||
}
|
||||
snap.signal
|
||||
.should_run_task(timing.unwrap_or_default(), docs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use core::fmt;
|
||||
|
||||
use crate::{CompilerFeat, CompilerWorld, EntryReader, TaskInputs};
|
||||
use crate::{args::TaskWhen, CompilerFeat, CompilerWorld, EntryReader, TaskInputs};
|
||||
use ecow::EcoString;
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
|
||||
|
@ -43,6 +43,38 @@ impl ExportSignal {
|
|||
self.by_fs_events |= other.by_fs_events;
|
||||
self.by_entry_update |= other.by_entry_update;
|
||||
}
|
||||
|
||||
pub fn should_run_task_dyn(
|
||||
&self,
|
||||
when: TaskWhen,
|
||||
docs: Option<&TypstDocument>,
|
||||
) -> Option<bool> {
|
||||
match docs {
|
||||
Some(TypstDocument::Paged(doc)) => self.should_run_task(when, Some(doc.as_ref())),
|
||||
Some(TypstDocument::Html(doc)) => self.should_run_task(when, Some(doc.as_ref())),
|
||||
None => self.should_run_task::<typst::layout::PagedDocument>(when, None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_run_task<D: typst::Document>(
|
||||
&self,
|
||||
when: TaskWhen,
|
||||
docs: Option<&D>,
|
||||
) -> Option<bool> {
|
||||
if !matches!(when, TaskWhen::Never) && self.by_entry_update {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
match when {
|
||||
TaskWhen::Never => Some(false),
|
||||
TaskWhen::OnType => Some(self.by_mem_events),
|
||||
TaskWhen::OnSave => Some(self.by_fs_events),
|
||||
TaskWhen::OnDocumentHasTitle if self.by_fs_events => {
|
||||
docs.map(|doc| doc.info().title.is_some())
|
||||
}
|
||||
TaskWhen::OnDocumentHasTitle => Some(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A snapshot of the project and compilation state.
|
||||
|
|
|
@ -90,6 +90,8 @@ pub struct Config {
|
|||
pub completion: CompletionFeat,
|
||||
/// Tinymist's preview features.
|
||||
pub preview: PreviewFeat,
|
||||
/// When to trigger the lint checks.
|
||||
pub lint: LintFeat,
|
||||
|
||||
/// Specifies the cli font options
|
||||
pub font_opts: CompileFontArgs,
|
||||
|
@ -318,6 +320,7 @@ impl Config {
|
|||
assign_config!(formatter_indent_size := "formatterIndentSize"?: Option<u32>);
|
||||
assign_config!(output_path := "outputPath"?: PathPattern);
|
||||
assign_config!(preview := "preview"?: PreviewFeat);
|
||||
assign_config!(lint := "preview"?: LintFeat);
|
||||
assign_config!(semantic_tokens := "semanticTokens"?: SemanticTokensMode);
|
||||
assign_config!(support_html_in_markdown := "supportHtmlInMarkdown"?: bool);
|
||||
assign_config!(system_fonts := "systemFonts"?: Option<bool>);
|
||||
|
@ -788,6 +791,26 @@ pub struct PreviewFeat {
|
|||
pub background: BackgroundPreviewOpts,
|
||||
}
|
||||
|
||||
/// The lint features.
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
pub struct LintFeat {
|
||||
/// Whether to enable linting.
|
||||
pub enabled: Option<bool>,
|
||||
/// When to trigger the lint checks.
|
||||
pub when: Option<TaskWhen>,
|
||||
}
|
||||
|
||||
impl LintFeat {
|
||||
/// When to trigger the lint checks.
|
||||
pub fn when(&self) -> TaskWhen {
|
||||
if matches!(self.enabled, Some(false)) {
|
||||
return TaskWhen::Never;
|
||||
}
|
||||
|
||||
self.when.unwrap_or(TaskWhen::OnSave)
|
||||
}
|
||||
}
|
||||
|
||||
/// Options for browsing preview.
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
|
@ -161,6 +161,7 @@ impl ServerState {
|
|||
Some("dark") => tinymist_query::ColorTheme::Dark,
|
||||
_ => tinymist_query::ColorTheme::Light,
|
||||
},
|
||||
lint: config.lint.when(),
|
||||
periscope: periscope_args.map(|args| {
|
||||
let r = TypstPeriscopeProvider(PeriscopeRenderer::new(args));
|
||||
Arc::new(r) as Arc<dyn PeriscopeProvider + Send + Sync>
|
||||
|
@ -429,36 +430,54 @@ impl CompileHandlerImpl {
|
|||
.log_error("failed to send diagnostics");
|
||||
}
|
||||
|
||||
fn notify_diagnostics(&self, snap: &LspCompiledArtifact) {
|
||||
fn notify_diagnostics(&self, art: &LspCompiledArtifact) {
|
||||
let dv = ProjVersion {
|
||||
id: snap.id().clone(),
|
||||
revision: snap.world().revision().get(),
|
||||
id: art.id().clone(),
|
||||
revision: art.world().revision().get(),
|
||||
};
|
||||
// todo: better way to remove diagnostics
|
||||
let valid = !snap.world().entry_state().is_inactive();
|
||||
let valid = !art.world().entry_state().is_inactive();
|
||||
if !valid {
|
||||
self.push_diagnostics(dv, None);
|
||||
return;
|
||||
}
|
||||
|
||||
let snap = snap.clone();
|
||||
let editor_tx = self.editor_tx.clone();
|
||||
let analysis = self.analysis.clone();
|
||||
rayon::spawn(move || {
|
||||
let world = snap.world().clone();
|
||||
let mut ctx = analysis.enter(world);
|
||||
let should_lint = art
|
||||
.snap
|
||||
.signal
|
||||
.should_run_task_dyn(self.analysis.lint, art.doc.as_ref())
|
||||
.unwrap_or_default();
|
||||
|
||||
// todo: check all errors in this file
|
||||
let Some(diagnostics) = CheckRequest { snap }.request(&mut ctx) else {
|
||||
return;
|
||||
};
|
||||
if !should_lint {
|
||||
let enc = self.analysis.position_encoding;
|
||||
let diagnostics =
|
||||
tinymist_query::convert_diagnostics(art.world(), art.diagnostics(), enc);
|
||||
|
||||
log::trace!("notify diagnostics({dv:?}): {diagnostics:#?}");
|
||||
|
||||
editor_tx
|
||||
self.editor_tx
|
||||
.send(EditorRequest::Diag(dv, Some(diagnostics)))
|
||||
.log_error("failed to send diagnostics");
|
||||
});
|
||||
} else {
|
||||
let snap = art.clone();
|
||||
let editor_tx = self.editor_tx.clone();
|
||||
let analysis = self.analysis.clone();
|
||||
rayon::spawn(move || {
|
||||
let world = snap.world().clone();
|
||||
let mut ctx = analysis.enter(world);
|
||||
|
||||
// todo: check all errors in this file
|
||||
let Some(diagnostics) = CheckRequest { snap }.request(&mut ctx) else {
|
||||
return;
|
||||
};
|
||||
|
||||
log::trace!("notify diagnostics({dv:?}): {diagnostics:#?}");
|
||||
|
||||
editor_tx
|
||||
.send(EditorRequest::Diag(dv, Some(diagnostics)))
|
||||
.log_error("failed to send diagnostics");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -367,6 +367,26 @@
|
|||
"%extension.tinymist.config.tinymist.semanticTokens.string.enum.disable%"
|
||||
]
|
||||
},
|
||||
"tinymist.lint.enabled": {
|
||||
"title": "%extension.tinymist.config.tinymist.lint.enabled.title%",
|
||||
"markdownDescription": "%extension.tinymist.config.tinymist.lint.enabled.desc%",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"tinymist.lint.when": {
|
||||
"title": "%extension.tinymist.config.tinymist.lint.when.title%",
|
||||
"markdownDescription": "%extension.tinymist.config.tinymist.lint.when.desc%",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"onSave",
|
||||
"onType"
|
||||
],
|
||||
"default": "onSave",
|
||||
"enumDescriptions": [
|
||||
"%extension.tinymist.config.tinymist.lint.when.string.enum.onSave%",
|
||||
"%extension.tinymist.config.tinymist.lint.when.string.enum.onType%"
|
||||
]
|
||||
},
|
||||
"tinymist.typingContinueCommentsOnNewline": {
|
||||
"title": "%extension.tinymist.config.tinymist.typingContinueCommentsOnNewline.title%",
|
||||
"markdownDescription": "%extension.tinymist.config.tinymist.typingContinueCommentsOnNewline.desc%",
|
||||
|
|
|
@ -1538,3 +1538,27 @@ zh = "将当前预览文件声明为 typst-lsp 或 tinymist 的入口点。这
|
|||
[extension.tinymist.config.tinymist.preview.pinPreviewFile.deprecation]
|
||||
en = "This setting is deprecated and no longer needed. The extension will always pin the previewed file as the entrypoint for the language server."
|
||||
zh = "此设置已弃用,不再需要。扩展程序将始终将预览的文件固定为语言服务器的入口点。"
|
||||
|
||||
[extension.tinymist.config.tinymist.lint.enabled.title]
|
||||
en = "Enable Lint Checks"
|
||||
zh = "启用代码检查"
|
||||
|
||||
[extension.tinymist.config.tinymist.lint.enabled.desc]
|
||||
en = "Enable or disable lint checks. Note: restarting the editor is required to change this setting."
|
||||
zh = "启用或禁用代码检查。注意:更改此设置需要重新启动编辑器。"
|
||||
|
||||
[extension.tinymist.config.tinymist.lint.when.title]
|
||||
en = "When to perform lint checks"
|
||||
zh = "何时执行代码检查"
|
||||
|
||||
[extension.tinymist.config.tinymist.lint.when.desc]
|
||||
en = "Configure when to perform lint checks. Note: restarting the editor is required to change this setting."
|
||||
zh = "配置何时执行代码检查。注意:更改此设置需要重新启动编辑器。"
|
||||
|
||||
[extension.tinymist.config.tinymist.lint.when.string.enum.onSave]
|
||||
en = "Perform lint checks on save"
|
||||
zh = "保存文件时执行代码检查"
|
||||
|
||||
[extension.tinymist.config.tinymist.lint.when.string.enum.onType]
|
||||
en = "Perform lint checks on type"
|
||||
zh = "标记文件时执行代码检查"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue