Introduce CompletionOptions

This commit is contained in:
Aleksey Kladov 2020-03-10 18:39:17 +01:00
parent 6b9d66bbee
commit 2347c03dcd
6 changed files with 48 additions and 18 deletions

View file

@ -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();

View file

@ -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;
} }

View file

@ -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,

View file

@ -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();

View file

@ -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(

View file

@ -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