Skip to content

Commit f6cb330

Browse files
bors[bot]Veykril
andauthored
Merge #10523
10523: minor: Simplify and add a few doc comments r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 1e9ecb9 + 5ccaff3 commit f6cb330

File tree

7 files changed

+63
-44
lines changed

7 files changed

+63
-44
lines changed

crates/ide_completion/src/completions/postfix.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
context::CompletionContext,
2020
item::{Builder, CompletionKind},
2121
patterns::ImmediateLocation,
22-
CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
22+
CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
2323
};
2424

2525
pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
@@ -231,7 +231,7 @@ fn add_custom_postfix_completions(
231231
) -> Option<()> {
232232
let import_scope =
233233
ImportScope::find_insert_use_container_with_macros(&ctx.token.parent()?, &ctx.sema)?;
234-
ctx.config.postfix_snippets().filter(|(_, snip)| snip.is_expr()).for_each(
234+
ctx.config.postfix_snippets().filter(|(_, snip)| snip.scope == SnippetScope::Expr).for_each(
235235
|(trigger, snippet)| {
236236
let imports = match snippet.imports(ctx, &import_scope) {
237237
Some(imports) => imports,

crates/ide_completion/src/config.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@ pub struct CompletionConfig {
2222

2323
impl CompletionConfig {
2424
pub fn postfix_snippets(&self) -> impl Iterator<Item = (&str, &Snippet)> {
25-
self.snippets.iter().flat_map(|snip| {
26-
snip.postfix_triggers.iter().map(move |trigger| (trigger.as_str(), snip))
27-
})
25+
self.snippets
26+
.iter()
27+
.flat_map(|snip| snip.postfix_triggers.iter().map(move |trigger| (&**trigger, snip)))
2828
}
29+
2930
pub fn prefix_snippets(&self) -> impl Iterator<Item = (&str, &Snippet)> {
30-
self.snippets.iter().flat_map(|snip| {
31-
snip.prefix_triggers.iter().map(move |trigger| (trigger.as_str(), snip))
32-
})
31+
self.snippets
32+
.iter()
33+
.flat_map(|snip| snip.prefix_triggers.iter().map(move |trigger| (&**trigger, snip)))
3334
}
3435
}

crates/ide_completion/src/context.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pub(crate) struct CompletionContext<'a> {
8585
pub(super) original_token: SyntaxToken,
8686
/// The token before the cursor, in the macro-expanded file.
8787
pub(super) token: SyntaxToken,
88+
/// The crate of the current file.
8889
pub(super) krate: Option<hir::Crate>,
8990
pub(super) expected_name: Option<NameOrNameRef>,
9091
pub(super) expected_type: Option<Type>,
@@ -135,11 +136,11 @@ impl<'a> CompletionContext<'a> {
135136
let fake_ident_token =
136137
file_with_fake_ident.syntax().token_at_offset(position.offset).right_biased().unwrap();
137138

138-
let krate = sema.to_module_def(position.file_id).map(|m| m.krate());
139139
let original_token =
140140
original_file.syntax().token_at_offset(position.offset).left_biased()?;
141141
let token = sema.descend_into_macros(original_token.clone());
142142
let scope = sema.scope_at_offset(&token, position.offset);
143+
let krate = scope.krate();
143144
let mut locals = vec![];
144145
scope.process_all_names(&mut |name, scope| {
145146
if let ScopeDef::Local(local) = scope {
@@ -182,6 +183,8 @@ impl<'a> CompletionContext<'a> {
182183
Some(ctx)
183184
}
184185

186+
/// Do the attribute expansion at the current cursor position for both original file and fake file
187+
/// as long as possible. As soon as one of the two expansions fail we stop to stay in sync.
185188
fn expand_and_fill(
186189
&mut self,
187190
mut original_file: SyntaxNode,
@@ -428,6 +431,7 @@ impl<'a> CompletionContext<'a> {
428431
false
429432
}
430433

434+
/// Check if an item is `#[doc(hidden)]`.
431435
pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
432436
let attrs = item.attrs(self.db);
433437
let krate = item.krate(self.db);
@@ -474,11 +478,11 @@ impl<'a> CompletionContext<'a> {
474478
}
475479

476480
fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
477-
let module = match self.scope.module() {
481+
let krate = match self.krate {
478482
Some(it) => it,
479483
None => return true,
480484
};
481-
if module.krate() != defining_crate && attrs.has_doc_hidden() {
485+
if krate != defining_crate && attrs.has_doc_hidden() {
482486
// `doc(hidden)` items are only completed within the defining crate.
483487
return true;
484488
}

crates/ide_completion/src/item.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ impl CompletionRelevance {
218218
}
219219
}
220220

221+
/// The type of the completion item.
221222
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222223
pub enum CompletionItemKind {
223224
SymbolKind(SymbolKind),
@@ -269,6 +270,8 @@ impl CompletionItemKind {
269270
}
270271
}
271272

273+
// FIXME remove this?
274+
/// Like [`CompletionItemKind`] but solely used for filtering test results.
272275
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
273276
pub(crate) enum CompletionKind {
274277
/// Parser-based keyword completion.
@@ -477,9 +480,10 @@ impl Builder {
477480
}
478481
pub(crate) fn insert_snippet(
479482
&mut self,
480-
_cap: SnippetCap,
483+
cap: SnippetCap,
481484
snippet: impl Into<String>,
482485
) -> &mut Builder {
486+
let _ = cap;
483487
self.is_snippet = true;
484488
self.insert_text(snippet)
485489
}

crates/ide_completion/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ pub fn completions(
173173
}
174174

175175
/// Resolves additional completion data at the position given.
176+
/// This is used for import insertion done via completions like flyimport and custom user snippets.
176177
pub fn resolve_completion_edits(
177178
db: &RootDatabase,
178179
config: &CompletionConfig,

crates/ide_completion/src/patterns.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub(crate) enum ImmediatePrevSibling {
2828
}
2929

3030
/// Direct parent "thing" of what we are currently completing.
31+
///
32+
/// This may contain nodes of the fake file as well as the original, comments on the variants specify
33+
/// from which file the nodes are.
3134
#[derive(Clone, Debug, PartialEq, Eq)]
3235
pub(crate) enum ImmediateLocation {
3336
Use,
@@ -42,32 +45,35 @@ pub(crate) enum ImmediateLocation {
4245
StmtList,
4346
ItemList,
4447
TypeBound,
45-
// Fake file ast node
48+
/// Fake file ast node
4649
Attribute(ast::Attr),
47-
// Fake file ast node
50+
/// Fake file ast node
4851
ModDeclaration(ast::Module),
4952
Visibility(ast::Visibility),
50-
// Original file ast node
53+
/// Original file ast node
5154
MethodCall {
5255
receiver: Option<ast::Expr>,
5356
has_parens: bool,
5457
},
55-
// Original file ast node
58+
/// Original file ast node
5659
FieldAccess {
5760
receiver: Option<ast::Expr>,
5861
receiver_is_ambiguous_float_literal: bool,
5962
},
60-
// Original file ast node
6163
// Only set from a type arg
64+
/// Original file ast node
6265
GenericArgList(ast::GenericArgList),
63-
// Original file ast node
6466
/// The record expr of the field name we are completing
67+
///
68+
/// Original file ast node
6569
RecordExpr(ast::RecordExpr),
66-
// Original file ast node
6770
/// The record expr of the functional update syntax we are completing
71+
///
72+
/// Original file ast node
6873
RecordExprUpdate(ast::RecordExpr),
69-
// Original file ast node
7074
/// The record pat of the field name we are completing
75+
///
76+
/// Original file ast node
7177
RecordPat(ast::RecordPat),
7278
}
7379

@@ -268,17 +274,20 @@ pub(crate) fn determine_location(
268274
Some(res)
269275
}
270276

277+
/// Maximize a nameref to its enclosing path if its the last segment of said path.
278+
/// That is, when completing a [`NameRef`] we actually handle it as the path it is part of when determining
279+
/// its location.
271280
fn maximize_name_ref(name_ref: &ast::NameRef) -> SyntaxNode {
272-
// Maximize a nameref to its enclosing path if its the last segment of said path
273281
if let Some(segment) = name_ref.syntax().parent().and_then(ast::PathSegment::cast) {
274282
let p = segment.parent_path();
275283
if p.parent_path().is_none() {
276-
if let Some(it) = p
284+
// Get rid of PathExpr, PathType, etc...
285+
let path = p
277286
.syntax()
278287
.ancestors()
279288
.take_while(|it| it.text_range() == p.syntax().text_range())
280-
.last()
281-
{
289+
.last();
290+
if let Some(it) = path {
282291
return it;
283292
}
284293
}

crates/ide_completion/src/snippet.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! User (postfix)-snippet definitions.
22
//!
3-
//! Actual logic is implemented in [`crate::completions::postfix`] and [`crate::completions::snippet`].
3+
//! Actual logic is implemented in [`crate::completions::postfix`] and [`crate::completions::snippet`] respectively.
4+
5+
use std::ops::Deref;
46

57
// Feature: User Snippet Completions
68
//
@@ -58,21 +60,24 @@ use syntax::ast;
5860

5961
use crate::{context::CompletionContext, ImportEdit};
6062

63+
/// A snippet scope describing where a snippet may apply to.
64+
/// These may differ slightly in meaning depending on the snippet trigger.
6165
#[derive(Clone, Debug, PartialEq, Eq)]
6266
pub enum SnippetScope {
6367
Item,
6468
Expr,
6569
Type,
6670
}
6771

72+
/// A user supplied snippet.
6873
#[derive(Clone, Debug, PartialEq, Eq)]
6974
pub struct Snippet {
70-
pub postfix_triggers: Box<[String]>,
71-
pub prefix_triggers: Box<[String]>,
75+
pub postfix_triggers: Box<[Box<str>]>,
76+
pub prefix_triggers: Box<[Box<str>]>,
7277
pub scope: SnippetScope,
7378
snippet: String,
74-
pub description: Option<String>,
75-
pub requires: Box<[String]>,
79+
pub description: Option<Box<str>>,
80+
pub requires: Box<[Box<str>]>,
7681
}
7782

7883
impl Snippet {
@@ -84,19 +89,22 @@ impl Snippet {
8489
requires: &[String],
8590
scope: SnippetScope,
8691
) -> Option<Self> {
92+
if prefix_triggers.is_empty() && postfix_triggers.is_empty() {
93+
return None;
94+
}
8795
let (snippet, description) = validate_snippet(snippet, description, requires)?;
8896
Some(Snippet {
8997
// Box::into doesn't work as that has a Copy bound 😒
90-
postfix_triggers: postfix_triggers.iter().cloned().collect(),
91-
prefix_triggers: prefix_triggers.iter().cloned().collect(),
98+
postfix_triggers: postfix_triggers.iter().map(Deref::deref).map(Into::into).collect(),
99+
prefix_triggers: prefix_triggers.iter().map(Deref::deref).map(Into::into).collect(),
92100
scope,
93101
snippet,
94102
description,
95-
requires: requires.iter().cloned().collect(),
103+
requires: requires.iter().map(Deref::deref).map(Into::into).collect(),
96104
})
97105
}
98106

99-
/// Returns None if the required items do not resolve.
107+
/// Returns [`None`] if the required items do not resolve.
100108
pub(crate) fn imports(
101109
&self,
102110
ctx: &CompletionContext,
@@ -112,20 +120,12 @@ impl Snippet {
112120
pub fn postfix_snippet(&self, receiver: &str) -> String {
113121
self.snippet.replace("${receiver}", receiver)
114122
}
115-
116-
pub fn is_item(&self) -> bool {
117-
self.scope == SnippetScope::Item
118-
}
119-
120-
pub fn is_expr(&self) -> bool {
121-
self.scope == SnippetScope::Expr
122-
}
123123
}
124124

125125
fn import_edits(
126126
ctx: &CompletionContext,
127127
import_scope: &ImportScope,
128-
requires: &[String],
128+
requires: &[Box<str>],
129129
) -> Option<Vec<ImportEdit>> {
130130
let resolve = |import| {
131131
let path = ast::Path::parse(import).ok()?;
@@ -158,7 +158,7 @@ fn validate_snippet(
158158
snippet: &[String],
159159
description: &str,
160160
requires: &[String],
161-
) -> Option<(String, Option<String>)> {
161+
) -> Option<(String, Option<Box<str>>)> {
162162
// validate that these are indeed simple paths
163163
// we can't save the paths unfortunately due to them not being Send+Sync
164164
if requires.iter().any(|path| match ast::Path::parse(path) {
@@ -171,6 +171,6 @@ fn validate_snippet(
171171
return None;
172172
}
173173
let snippet = snippet.iter().join("\n");
174-
let description = if description.is_empty() { None } else { Some(description.to_owned()) };
174+
let description = if description.is_empty() { None } else { Some(description.into()) };
175175
Some((snippet, description))
176176
}

0 commit comments

Comments
 (0)