feat: client-side control to whether issue completion callback (#744)

* feat: client-side control to whether issue completion callback

* fix: bad changes
This commit is contained in:
Myriad-Dreamin 2024-10-29 13:00:57 +08:00 committed by GitHub
parent 5dd1226cdc
commit 9c87fe2fb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 87 additions and 15 deletions

View file

@ -45,6 +45,12 @@ pub struct CompletionRequest {
pub position: LspPosition,
/// Whether the completion is triggered explicitly.
pub explicit: bool,
/// Whether to trigger suggest completion, a.k.a. auto-completion.
pub trigger_suggest: bool,
/// Whether to trigger named parameter completion.
pub trigger_named_completion: bool,
/// Whether to trigger parameter hint, a.k.a. signature help.
pub trigger_parameter_hints: bool,
}
impl StatefulRequest for CompletionRequest {
@ -131,7 +137,16 @@ impl StatefulRequest for CompletionRequest {
let is_incomplete = false;
let mut items = completion_result.or_else(|| {
let mut cc_ctx = CompletionContext::new(ctx, doc, &source, cursor, explicit)?;
let mut cc_ctx = CompletionContext::new(
ctx,
doc,
&source,
cursor,
explicit,
self.trigger_suggest,
self.trigger_parameter_hints,
self.trigger_named_completion,
)?;
// Exclude it self from auto completion
// e.g. `#let x = (1.);`
@ -372,6 +387,9 @@ mod tests {
path: ctx.path_for_id(id).unwrap(),
position: ctx.to_lsp_pos(s, &source),
explicit: false,
trigger_suggest: true,
trigger_parameter_hints: true,
trigger_named_completion: true,
};
results.push(request.request(ctx, doc.clone()).map(|resp| match resp {
CompletionResponse::List(l) => CompletionResponse::List(CompletionList {

View file

@ -959,6 +959,9 @@ pub struct CompletionContext<'a, 'b> {
pub leaf: LinkedNode<'a>,
pub cursor: usize,
pub explicit: bool,
pub trigger_suggest: bool,
pub trigger_parameter_hints: bool,
pub trigger_named_completion: bool,
pub from: usize,
pub completions: Vec<Completion>,
pub completions2: Vec<lsp_types::CompletionItem>,
@ -970,12 +973,16 @@ pub struct CompletionContext<'a, 'b> {
impl<'a, 'w> CompletionContext<'a, 'w> {
/// Create a new autocompletion context.
#[allow(clippy::too_many_arguments)]
pub fn new(
ctx: &'a mut AnalysisContext<'w>,
document: Option<&'a Document>,
source: &'a Source,
cursor: usize,
explicit: bool,
trigger_suggest: bool,
trigger_parameter_hints: bool,
trigger_named_completion: bool,
) -> Option<Self> {
let text = source.text();
let root = LinkedNode::new(source.root());
@ -989,6 +996,9 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
root,
leaf,
cursor,
trigger_suggest,
trigger_parameter_hints,
trigger_named_completion,
explicit,
from: cursor,
incomplete: true,
@ -1032,10 +1042,7 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
// VS Code doesn't do that... Auto triggering suggestion only happens on typing (word
// starts or trigger characters). However, you can use editor.action.triggerSuggest as
// command on a suggestion to "manually" retrigger suggest after inserting one
//
// todo: only vscode and neovim (0.9.1) support this
command: snippet
.contains("${")
command: (self.trigger_suggest && snippet.contains("${"))
.then_some("editor.action.triggerSuggest"),
..Completion::default()
});
@ -1231,7 +1238,9 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
let mut command = None;
if parens && matches!(value, Value::Func(_)) {
if let Value::Func(func) = value {
command = Some("editor.action.triggerParameterHints");
command = self
.trigger_parameter_hints
.then_some("editor.action.triggerParameterHints");
if func
.params()
.is_some_and(|params| params.iter().all(|param| param.name == "self"))

View file

@ -308,8 +308,9 @@ impl<'a, 'w> CompletionContext<'a, 'w> {
let base = Completion {
kind: kind.clone(),
label_detail: ty_detail,
// todo: only vscode and neovim (0.9.1) support this
command: Some("editor.action.triggerParameterHints"),
command: self
.trigger_parameter_hints
.then_some("editor.action.triggerParameterHints"),
..Default::default()
};
@ -648,7 +649,9 @@ pub fn param_completions<'a>(
apply: Some(eco_format!("{}: ${{}}", param.name)),
detail: docs(),
label_detail: None,
command: Some("tinymist.triggerNamedCompletion"),
command: ctx
.trigger_named_completion
.then_some("tinymist.triggerNamedCompletion"),
..Completion::default()
};
match param.ty {
@ -734,7 +737,9 @@ fn type_completion(
label: f.into(),
apply: Some(eco_format!("{}: ${{}}", f)),
detail: docs.map(Into::into),
command: Some("tinymist.triggerNamedCompletion"),
command: ctx
.trigger_named_completion
.then_some("tinymist.triggerNamedCompletion"),
..Completion::default()
});
}

View file

@ -301,6 +301,12 @@ pub struct Config {
pub formatter_mode: FormatterMode,
/// Dynamic configuration for the experimental formatter.
pub formatter_print_width: Option<u32>,
/// Whether to trigger suggest completion, a.k.a. auto-completion.
pub trigger_suggest: bool,
/// Whether to trigger named parameter completion.
pub trigger_named_completion: bool,
/// Whether to trigger parameter hint, a.k.a. signature help.
pub trigger_parameter_hints: bool,
}
impl Config {
@ -349,12 +355,21 @@ impl Config {
/// # Errors
/// Errors if the update is invalid.
pub fn update_by_map(&mut self, update: &Map<String, JsonValue>) -> anyhow::Result<()> {
macro_rules! deser_or_default {
($key:expr, $ty:ty) => {
try_or_default(|| <$ty>::deserialize(update.get($key)?).ok())
};
}
try_(|| SemanticTokensMode::deserialize(update.get("semanticTokens")?).ok())
.inspect(|v| self.semantic_tokens = *v);
try_(|| FormatterMode::deserialize(update.get("formatterMode")?).ok())
.inspect(|v| self.formatter_mode = *v);
try_(|| u32::deserialize(update.get("formatterPrintWidth")?).ok())
.inspect(|v| self.formatter_print_width = Some(*v));
self.trigger_suggest = deser_or_default!("triggerSuggest", bool);
self.trigger_parameter_hints = deser_or_default!("triggerParameterHints", bool);
self.trigger_named_completion = deser_or_default!("triggerNamedCompletion", bool);
self.compile.update_by_map(update)?;
self.compile.validate()
}
@ -479,9 +494,14 @@ impl CompileConfig {
/// Updates the configuration with a map.
pub fn update_by_map(&mut self, update: &Map<String, JsonValue>) -> anyhow::Result<()> {
self.output_path =
try_or_default(|| PathPattern::deserialize(update.get("outputPath")?).ok());
self.export_pdf = try_or_default(|| ExportMode::deserialize(update.get("exportPdf")?).ok());
macro_rules! deser_or_default {
($key:expr, $ty:ty) => {
try_or_default(|| <$ty>::deserialize(update.get($key)?).ok())
};
}
self.output_path = deser_or_default!("outputPath", PathPattern);
self.export_pdf = deser_or_default!("exportPdf", ExportMode);
self.root_path = try_(|| Some(update.get("rootPath")?.as_str()?.into()));
self.notify_status = match try_(|| update.get("compileStatus")?.as_str()) {
Some("enable") => true,

View file

@ -750,8 +750,21 @@ impl LanguageState {
.context
.map(|context| context.trigger_kind == CompletionTriggerKind::INVOKED)
.unwrap_or(false);
let trigger_suggest = self.config.trigger_suggest;
let trigger_parameter_hints = self.config.trigger_parameter_hints;
let trigger_named_completion = self.config.trigger_named_completion;
run_query!(req_id, self.Completion(path, position, explicit))
run_query!(
req_id,
self.Completion(
path,
position,
explicit,
trigger_suggest,
trigger_parameter_hints,
trigger_named_completion
)
)
}
fn signature_help(