mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 14:03:35 +00:00
Introduce CompletionOptions
This commit is contained in:
parent
6b9d66bbee
commit
2347c03dcd
6 changed files with 48 additions and 18 deletions
|
@ -33,6 +33,23 @@ pub use crate::completion::completion_item::{
|
||||||
CompletionItem, CompletionItemKind, InsertTextFormat,
|
CompletionItem, CompletionItemKind, InsertTextFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct CompletionOptions {
|
||||||
|
pub enable_postfix_completions: bool,
|
||||||
|
pub add_call_parenthesis: bool,
|
||||||
|
pub add_call_argument_snippets: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CompletionOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
CompletionOptions {
|
||||||
|
enable_postfix_completions: true,
|
||||||
|
add_call_parenthesis: true,
|
||||||
|
add_call_argument_snippets: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Main entry point for completion. We run completion as a two-phase process.
|
/// Main entry point for completion. We run completion as a two-phase process.
|
||||||
///
|
///
|
||||||
/// First, we look at the position and collect a so-called `CompletionContext.
|
/// First, we look at the position and collect a so-called `CompletionContext.
|
||||||
|
@ -55,8 +72,12 @@ pub use crate::completion::completion_item::{
|
||||||
/// `foo` *should* be present among the completion variants. Filtering by
|
/// `foo` *should* be present among the completion variants. Filtering by
|
||||||
/// identifier prefix/fuzzy match should be done higher in the stack, together
|
/// identifier prefix/fuzzy match should be done higher in the stack, together
|
||||||
/// with ordering of completions (currently this is done by the client).
|
/// with ordering of completions (currently this is done by the client).
|
||||||
pub(crate) fn completions(db: &RootDatabase, position: FilePosition) -> Option<Completions> {
|
pub(crate) fn completions(
|
||||||
let ctx = CompletionContext::new(db, position)?;
|
db: &RootDatabase,
|
||||||
|
position: FilePosition,
|
||||||
|
opts: &CompletionOptions,
|
||||||
|
) -> Option<Completions> {
|
||||||
|
let ctx = CompletionContext::new(db, position, opts)?;
|
||||||
|
|
||||||
let mut acc = Completions::default();
|
let mut acc = Completions::default();
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if !ctx.db.feature_flags.get("completion.enable-postfix") {
|
if !ctx.options.enable_postfix_completions {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
use ra_text_edit::AtomTextEdit;
|
use ra_text_edit::AtomTextEdit;
|
||||||
|
|
||||||
use crate::FilePosition;
|
use crate::{completion::CompletionOptions, FilePosition};
|
||||||
|
|
||||||
/// `CompletionContext` is created early during completion to figure out, where
|
/// `CompletionContext` is created early during completion to figure out, where
|
||||||
/// exactly is the cursor, syntax-wise.
|
/// exactly is the cursor, syntax-wise.
|
||||||
|
@ -19,6 +19,7 @@ use crate::FilePosition;
|
||||||
pub(crate) struct CompletionContext<'a> {
|
pub(crate) struct CompletionContext<'a> {
|
||||||
pub(super) sema: Semantics<'a, RootDatabase>,
|
pub(super) sema: Semantics<'a, RootDatabase>,
|
||||||
pub(super) db: &'a RootDatabase,
|
pub(super) db: &'a RootDatabase,
|
||||||
|
pub(super) options: &'a CompletionOptions,
|
||||||
pub(super) offset: TextUnit,
|
pub(super) offset: TextUnit,
|
||||||
/// The token before the cursor, in the original file.
|
/// The token before the cursor, in the original file.
|
||||||
pub(super) original_token: SyntaxToken,
|
pub(super) original_token: SyntaxToken,
|
||||||
|
@ -57,6 +58,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
db: &'a RootDatabase,
|
db: &'a RootDatabase,
|
||||||
position: FilePosition,
|
position: FilePosition,
|
||||||
|
options: &'a CompletionOptions,
|
||||||
) -> Option<CompletionContext<'a>> {
|
) -> Option<CompletionContext<'a>> {
|
||||||
let sema = Semantics::new(db);
|
let sema = Semantics::new(db);
|
||||||
|
|
||||||
|
@ -80,6 +82,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
let mut ctx = CompletionContext {
|
let mut ctx = CompletionContext {
|
||||||
sema,
|
sema,
|
||||||
db,
|
db,
|
||||||
|
options,
|
||||||
original_token,
|
original_token,
|
||||||
token,
|
token,
|
||||||
offset: position.offset,
|
offset: position.offset,
|
||||||
|
|
|
@ -321,14 +321,18 @@ impl Into<Vec<CompletionItem>> for Completions {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
|
||||||
use crate::completion::completions;
|
use crate::{
|
||||||
use crate::mock_analysis::{analysis_and_position, single_file_with_position};
|
completion::{completions, CompletionOptions},
|
||||||
|
mock_analysis::{analysis_and_position, single_file_with_position},
|
||||||
|
};
|
||||||
|
|
||||||
let (analysis, position) = if code.contains("//-") {
|
let (analysis, position) = if code.contains("//-") {
|
||||||
analysis_and_position(code)
|
analysis_and_position(code)
|
||||||
} else {
|
} else {
|
||||||
single_file_with_position(code)
|
single_file_with_position(code)
|
||||||
};
|
};
|
||||||
let completions = completions(&analysis.db, position).unwrap();
|
let options = CompletionOptions::default();
|
||||||
|
let completions = completions(&analysis.db, position, &options).unwrap();
|
||||||
let completion_items: Vec<CompletionItem> = completions.into();
|
let completion_items: Vec<CompletionItem> = completions.into();
|
||||||
let mut kind_completions: Vec<CompletionItem> =
|
let mut kind_completions: Vec<CompletionItem> =
|
||||||
completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
|
completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
|
||||||
|
|
|
@ -212,21 +212,14 @@ impl Completions {
|
||||||
.detail(function_signature.to_string());
|
.detail(function_signature.to_string());
|
||||||
|
|
||||||
// If not an import, add parenthesis automatically.
|
// If not an import, add parenthesis automatically.
|
||||||
if ctx.use_item_syntax.is_none()
|
if ctx.use_item_syntax.is_none() && !ctx.is_call && ctx.options.add_call_parenthesis {
|
||||||
&& !ctx.is_call
|
|
||||||
&& ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
|
|
||||||
{
|
|
||||||
tested_by!(inserts_parens_for_function_calls);
|
tested_by!(inserts_parens_for_function_calls);
|
||||||
|
|
||||||
let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 {
|
let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 {
|
||||||
(format!("{}()$0", name), format!("{}()", name))
|
(format!("{}()$0", name), format!("{}()", name))
|
||||||
} else {
|
} else {
|
||||||
builder = builder.trigger_call_info();
|
builder = builder.trigger_call_info();
|
||||||
let snippet = if ctx
|
let snippet = if ctx.options.add_call_argument_snippets {
|
||||||
.db
|
|
||||||
.feature_flags
|
|
||||||
.get("completion.insertion.add-argument-snippets")
|
|
||||||
{
|
|
||||||
let to_skip = if has_self_param { 1 } else { 0 };
|
let to_skip = if has_self_param { 1 } else { 0 };
|
||||||
let function_params_snippet = join(
|
let function_params_snippet = join(
|
||||||
function_signature.parameter_names.iter().skip(to_skip).enumerate().map(
|
function_signature.parameter_names.iter().skip(to_skip).enumerate().map(
|
||||||
|
|
|
@ -62,7 +62,7 @@ use crate::display::ToNav;
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
assists::{Assist, AssistId},
|
assists::{Assist, AssistId},
|
||||||
call_hierarchy::CallItem,
|
call_hierarchy::CallItem,
|
||||||
completion::{CompletionItem, CompletionItemKind, InsertTextFormat},
|
completion::{CompletionItem, CompletionItemKind, CompletionOptions, InsertTextFormat},
|
||||||
diagnostics::Severity,
|
diagnostics::Severity,
|
||||||
display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
|
display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
|
||||||
expand_macro::ExpandedMacro,
|
expand_macro::ExpandedMacro,
|
||||||
|
@ -451,7 +451,16 @@ impl Analysis {
|
||||||
|
|
||||||
/// Computes completions at the given position.
|
/// Computes completions at the given position.
|
||||||
pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
|
pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
|
||||||
self.with_db(|db| completion::completions(db, position).map(Into::into))
|
let opts = CompletionOptions {
|
||||||
|
enable_postfix_completions: self.feature_flags().get("completion.enable-postfix"),
|
||||||
|
add_call_parenthesis: self
|
||||||
|
.feature_flags()
|
||||||
|
.get("completion.insertion.add-call-parenthesis"),
|
||||||
|
add_call_argument_snippets: self
|
||||||
|
.feature_flags()
|
||||||
|
.get("completion.insertion.add-argument-snippets"),
|
||||||
|
};
|
||||||
|
self.with_db(|db| completion::completions(db, position, &opts).map(Into::into))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes assists (aka code actions aka intentions) for the given
|
/// Computes assists (aka code actions aka intentions) for the given
|
||||||
|
|
Loading…
Reference in a new issue