mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-04 05:35:55 +00:00 
			
		
		
		
	Fix import search not discarding rawness
This commit is contained in:
		
							parent
							
								
									20ff27e2ba
								
							
						
					
					
						commit
						a06606c802
					
				
					 8 changed files with 65 additions and 29 deletions
				
			
		| 
						 | 
					@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"]
 | 
				
			||||||
resolver = "2"
 | 
					resolver = "2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[workspace.package]
 | 
					[workspace.package]
 | 
				
			||||||
rust-version = "1.82"
 | 
					rust-version = "1.83"
 | 
				
			||||||
edition = "2021"
 | 
					edition = "2021"
 | 
				
			||||||
license = "MIT OR Apache-2.0"
 | 
					license = "MIT OR Apache-2.0"
 | 
				
			||||||
authors = ["rust-analyzer team"]
 | 
					authors = ["rust-analyzer team"]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ use syntax::utils::is_raw_identifier;
 | 
				
			||||||
/// and declarations. In theory, names should also carry hygiene info, but we are
 | 
					/// and declarations. In theory, names should also carry hygiene info, but we are
 | 
				
			||||||
/// not there yet!
 | 
					/// not there yet!
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Note that the rawness (`r#`) of names does not depend on whether they are written raw.
 | 
					/// Note that the rawness (`r#`) of names is not preserved. Names are always stored without a `r#` prefix.
 | 
				
			||||||
/// This is because we want to show (in completions etc.) names as raw depending on the needs
 | 
					/// This is because we want to show (in completions etc.) names as raw depending on the needs
 | 
				
			||||||
/// of the current crate, for example if it is edition 2021 complete `gen` even if the defining
 | 
					/// of the current crate, for example if it is edition 2021 complete `gen` even if the defining
 | 
				
			||||||
/// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well.
 | 
					/// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well.
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,7 @@ impl Name {
 | 
				
			||||||
    /// Hopefully, this should allow us to integrate hygiene cleaner in the
 | 
					    /// Hopefully, this should allow us to integrate hygiene cleaner in the
 | 
				
			||||||
    /// future, and to switch to interned representation of names.
 | 
					    /// future, and to switch to interned representation of names.
 | 
				
			||||||
    fn new_text(text: &str) -> Name {
 | 
					    fn new_text(text: &str) -> Name {
 | 
				
			||||||
 | 
					        debug_assert!(!text.starts_with("r#"));
 | 
				
			||||||
        Name { symbol: Symbol::intern(text), ctx: () }
 | 
					        Name { symbol: Symbol::intern(text), ctx: () }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,15 +92,34 @@ impl Name {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_root(text: &str) -> Name {
 | 
					    pub fn new_root(text: &str) -> Name {
 | 
				
			||||||
        // The edition doesn't matter for hygiene.
 | 
					        // The edition doesn't matter for hygiene.
 | 
				
			||||||
        Self::new(text, SyntaxContextId::root(Edition::Edition2015))
 | 
					        Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_tuple_field(idx: usize) -> Name {
 | 
					    pub fn new_tuple_field(idx: usize) -> Name {
 | 
				
			||||||
        Name { symbol: Symbol::intern(&idx.to_string()), ctx: () }
 | 
					        let symbol = match idx {
 | 
				
			||||||
 | 
					            0 => sym::INTEGER_0.clone(),
 | 
				
			||||||
 | 
					            1 => sym::INTEGER_1.clone(),
 | 
				
			||||||
 | 
					            2 => sym::INTEGER_2.clone(),
 | 
				
			||||||
 | 
					            3 => sym::INTEGER_3.clone(),
 | 
				
			||||||
 | 
					            4 => sym::INTEGER_4.clone(),
 | 
				
			||||||
 | 
					            5 => sym::INTEGER_5.clone(),
 | 
				
			||||||
 | 
					            6 => sym::INTEGER_6.clone(),
 | 
				
			||||||
 | 
					            7 => sym::INTEGER_7.clone(),
 | 
				
			||||||
 | 
					            8 => sym::INTEGER_8.clone(),
 | 
				
			||||||
 | 
					            9 => sym::INTEGER_9.clone(),
 | 
				
			||||||
 | 
					            10 => sym::INTEGER_10.clone(),
 | 
				
			||||||
 | 
					            11 => sym::INTEGER_11.clone(),
 | 
				
			||||||
 | 
					            12 => sym::INTEGER_12.clone(),
 | 
				
			||||||
 | 
					            13 => sym::INTEGER_13.clone(),
 | 
				
			||||||
 | 
					            14 => sym::INTEGER_14.clone(),
 | 
				
			||||||
 | 
					            15 => sym::INTEGER_15.clone(),
 | 
				
			||||||
 | 
					            _ => Symbol::intern(&idx.to_string()),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        Name { symbol, ctx: () }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
 | 
					    pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
 | 
				
			||||||
        Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () }
 | 
					        Self::new_text(lt.text().as_str().trim_start_matches("r#"))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Resolve a name from the text of token.
 | 
					    /// Resolve a name from the text of token.
 | 
				
			||||||
| 
						 | 
					@ -142,15 +162,18 @@ impl Name {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the text this name represents if it isn't a tuple field.
 | 
					    /// Returns the text this name represents if it isn't a tuple field.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Do not use this for user-facing text, use `display` instead to handle editions properly.
 | 
				
			||||||
    pub fn as_str(&self) -> &str {
 | 
					    pub fn as_str(&self) -> &str {
 | 
				
			||||||
        self.symbol.as_str()
 | 
					        self.symbol.as_str()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // FIXME: Remove this
 | 
				
			||||||
    pub fn unescaped(&self) -> UnescapedName<'_> {
 | 
					    pub fn unescaped(&self) -> UnescapedName<'_> {
 | 
				
			||||||
        UnescapedName(self)
 | 
					        UnescapedName(self)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn is_escaped(&self, edition: Edition) -> bool {
 | 
					    pub fn needs_escape(&self, edition: Edition) -> bool {
 | 
				
			||||||
        is_raw_identifier(self.symbol.as_str(), edition)
 | 
					        is_raw_identifier(self.symbol.as_str(), edition)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,16 +196,19 @@ impl Name {
 | 
				
			||||||
        &self.symbol
 | 
					        &self.symbol
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub const fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
 | 
					    pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self {
 | 
				
			||||||
 | 
					        debug_assert!(!symbol.as_str().starts_with("r#"));
 | 
				
			||||||
        _ = ctx;
 | 
					        _ = ctx;
 | 
				
			||||||
        Self { symbol, ctx: () }
 | 
					        Self { symbol, ctx: () }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // FIXME: This needs to go once we have hygiene
 | 
					    // FIXME: This needs to go once we have hygiene
 | 
				
			||||||
    pub const fn new_symbol_root(sym: Symbol) -> Self {
 | 
					    pub fn new_symbol_root(sym: Symbol) -> Self {
 | 
				
			||||||
 | 
					        debug_assert!(!sym.as_str().starts_with("r#"));
 | 
				
			||||||
        Self { symbol: sym, ctx: () }
 | 
					        Self { symbol: sym, ctx: () }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // FIXME: Remove this
 | 
				
			||||||
    #[inline]
 | 
					    #[inline]
 | 
				
			||||||
    pub fn eq_ident(&self, ident: &str) -> bool {
 | 
					    pub fn eq_ident(&self, ident: &str) -> bool {
 | 
				
			||||||
        self.as_str() == ident.trim_start_matches("r#")
 | 
					        self.as_str() == ident.trim_start_matches("r#")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,8 +39,8 @@ use stdx::TupleExt;
 | 
				
			||||||
use syntax::{
 | 
					use syntax::{
 | 
				
			||||||
    algo::skip_trivia_token,
 | 
					    algo::skip_trivia_token,
 | 
				
			||||||
    ast::{self, HasAttrs as _, HasGenericParams},
 | 
					    ast::{self, HasAttrs as _, HasGenericParams},
 | 
				
			||||||
    AstNode, AstToken, Direction, SmolStr, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken,
 | 
					    AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
 | 
				
			||||||
    TextRange, TextSize,
 | 
					    TextSize,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use triomphe::Arc;
 | 
					use triomphe::Arc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1587,14 +1587,11 @@ impl<'db> SemanticsImpl<'db> {
 | 
				
			||||||
    pub fn resolve_mod_path_relative(
 | 
					    pub fn resolve_mod_path_relative(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        to: Module,
 | 
					        to: Module,
 | 
				
			||||||
        segments: impl IntoIterator<Item = SmolStr>,
 | 
					        segments: impl IntoIterator<Item = Name>,
 | 
				
			||||||
    ) -> Option<impl Iterator<Item = ItemInNs>> {
 | 
					    ) -> Option<impl Iterator<Item = ItemInNs>> {
 | 
				
			||||||
        let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items(
 | 
					        let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items(
 | 
				
			||||||
            self.db.upcast(),
 | 
					            self.db.upcast(),
 | 
				
			||||||
            &ModPath::from_segments(
 | 
					            &ModPath::from_segments(hir_def::path::PathKind::Plain, segments),
 | 
				
			||||||
                hir_def::path::PathKind::Plain,
 | 
					 | 
				
			||||||
                segments.into_iter().map(|it| Name::new_root(&it)),
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        Some(items.iter_items().map(|(item, _)| item.into()))
 | 
					        Some(items.iter_items().map(|(item, _)| item.into()))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@ use ide_db::imports::{
 | 
				
			||||||
    insert_use::ImportScope,
 | 
					    insert_use::ImportScope,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use itertools::Itertools;
 | 
					use itertools::Itertools;
 | 
				
			||||||
use syntax::{ast, AstNode, SyntaxNode, ToSmolStr, T};
 | 
					use syntax::{ast, AstNode, SyntaxNode, ToSmolStr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    config::AutoImportExclusionType,
 | 
					    config::AutoImportExclusionType,
 | 
				
			||||||
| 
						 | 
					@ -403,10 +403,11 @@ fn import_on_the_fly_method(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn import_name(ctx: &CompletionContext<'_>) -> String {
 | 
					fn import_name(ctx: &CompletionContext<'_>) -> String {
 | 
				
			||||||
    let token_kind = ctx.token.kind();
 | 
					    let token_kind = ctx.token.kind();
 | 
				
			||||||
    if matches!(token_kind, T![.] | T![::]) {
 | 
					
 | 
				
			||||||
        String::new()
 | 
					    if token_kind.is_any_identifier() {
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        ctx.token.to_string()
 | 
					        ctx.token.to_string()
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        String::new()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -423,7 +423,7 @@ fn render_resolution_path(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
 | 
					    let name = local_name.display_no_db(ctx.completion.edition).to_smolstr();
 | 
				
			||||||
    let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
 | 
					    let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
 | 
				
			||||||
    if local_name.is_escaped(completion.edition) {
 | 
					    if local_name.needs_escape(completion.edition) {
 | 
				
			||||||
        item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
 | 
					        item.insert_text(local_name.display_no_db(completion.edition).to_smolstr());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Add `<>` for generic types
 | 
					    // Add `<>` for generic types
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,14 +4,14 @@ use std::ops::ControlFlow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use hir::{
 | 
					use hir::{
 | 
				
			||||||
    db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig,
 | 
					    db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig,
 | 
				
			||||||
    ItemInNs, ModPath, Module, ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics,
 | 
					    ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics,
 | 
				
			||||||
    SemanticsScope, Trait, TyFingerprint, Type,
 | 
					    SemanticsScope, Trait, TyFingerprint, Type,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use itertools::Itertools;
 | 
					use itertools::Itertools;
 | 
				
			||||||
use rustc_hash::{FxHashMap, FxHashSet};
 | 
					use rustc_hash::{FxHashMap, FxHashSet};
 | 
				
			||||||
use syntax::{
 | 
					use syntax::{
 | 
				
			||||||
    ast::{self, make, HasName},
 | 
					    ast::{self, make, HasName},
 | 
				
			||||||
    AstNode, SmolStr, SyntaxNode,
 | 
					    AstNode, SyntaxNode,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ pub struct TraitImportCandidate {
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct PathImportCandidate {
 | 
					pub struct PathImportCandidate {
 | 
				
			||||||
    /// Optional qualifier before name.
 | 
					    /// Optional qualifier before name.
 | 
				
			||||||
    pub qualifier: Vec<SmolStr>,
 | 
					    pub qualifier: Vec<Name>,
 | 
				
			||||||
    /// The name the item (struct, trait, enum, etc.) should have.
 | 
					    /// The name the item (struct, trait, enum, etc.) should have.
 | 
				
			||||||
    pub name: NameToImport,
 | 
					    pub name: NameToImport,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -72,10 +72,18 @@ pub enum NameToImport {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl NameToImport {
 | 
					impl NameToImport {
 | 
				
			||||||
    pub fn exact_case_sensitive(s: String) -> NameToImport {
 | 
					    pub fn exact_case_sensitive(s: String) -> NameToImport {
 | 
				
			||||||
 | 
					        let s = match s.strip_prefix("r#") {
 | 
				
			||||||
 | 
					            Some(s) => s.to_owned(),
 | 
				
			||||||
 | 
					            None => s,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        NameToImport::Exact(s, true)
 | 
					        NameToImport::Exact(s, true)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn fuzzy(s: String) -> NameToImport {
 | 
					    pub fn fuzzy(s: String) -> NameToImport {
 | 
				
			||||||
 | 
					        let s = match s.strip_prefix("r#") {
 | 
				
			||||||
 | 
					            Some(s) => s.to_owned(),
 | 
				
			||||||
 | 
					            None => s,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        // unless all chars are lowercase, we do a case sensitive search
 | 
					        // unless all chars are lowercase, we do a case sensitive search
 | 
				
			||||||
        let case_sensitive = s.chars().any(|c| c.is_uppercase());
 | 
					        let case_sensitive = s.chars().any(|c| c.is_uppercase());
 | 
				
			||||||
        NameToImport::Fuzzy(s, case_sensitive)
 | 
					        NameToImport::Fuzzy(s, case_sensitive)
 | 
				
			||||||
| 
						 | 
					@ -359,7 +367,7 @@ fn path_applicable_imports(
 | 
				
			||||||
        [first_qsegment, qualifier_rest @ ..] => items_locator::items_with_name(
 | 
					        [first_qsegment, qualifier_rest @ ..] => items_locator::items_with_name(
 | 
				
			||||||
            sema,
 | 
					            sema,
 | 
				
			||||||
            current_crate,
 | 
					            current_crate,
 | 
				
			||||||
            NameToImport::Exact(first_qsegment.to_string(), true),
 | 
					            NameToImport::Exact(first_qsegment.as_str().to_owned(), true),
 | 
				
			||||||
            AssocSearchMode::Exclude,
 | 
					            AssocSearchMode::Exclude,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .filter_map(|item| {
 | 
					        .filter_map(|item| {
 | 
				
			||||||
| 
						 | 
					@ -389,7 +397,7 @@ fn validate_resolvable(
 | 
				
			||||||
    scope_filter: impl Fn(ItemInNs) -> bool,
 | 
					    scope_filter: impl Fn(ItemInNs) -> bool,
 | 
				
			||||||
    candidate: &NameToImport,
 | 
					    candidate: &NameToImport,
 | 
				
			||||||
    resolved_qualifier: ItemInNs,
 | 
					    resolved_qualifier: ItemInNs,
 | 
				
			||||||
    unresolved_qualifier: &[SmolStr],
 | 
					    unresolved_qualifier: &[Name],
 | 
				
			||||||
) -> Option<LocatedImport> {
 | 
					) -> Option<LocatedImport> {
 | 
				
			||||||
    let _p = tracing::info_span!("ImportAssets::import_for_item").entered();
 | 
					    let _p = tracing::info_span!("ImportAssets::import_for_item").entered();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -722,7 +730,7 @@ fn path_import_candidate(
 | 
				
			||||||
                if qualifier.first_qualifier().is_none_or(|it| sema.resolve_path(&it).is_none()) {
 | 
					                if qualifier.first_qualifier().is_none_or(|it| sema.resolve_path(&it).is_none()) {
 | 
				
			||||||
                    let qualifier = qualifier
 | 
					                    let qualifier = qualifier
 | 
				
			||||||
                        .segments()
 | 
					                        .segments()
 | 
				
			||||||
                        .map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text())))
 | 
					                        .map(|seg| seg.name_ref().map(|name| Name::new_root(&name.text())))
 | 
				
			||||||
                        .collect::<Option<Vec<_>>>()?;
 | 
					                        .collect::<Option<Vec<_>>>()?;
 | 
				
			||||||
                    ImportCandidate::Path(PathImportCandidate { qualifier, name })
 | 
					                    ImportCandidate::Path(PathImportCandidate { qualifier, name })
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,10 +141,11 @@ fn find_items<'a>(
 | 
				
			||||||
    // Query the local crate using the symbol index.
 | 
					    // Query the local crate using the symbol index.
 | 
				
			||||||
    let mut local_results = Vec::new();
 | 
					    let mut local_results = Vec::new();
 | 
				
			||||||
    local_query.search(&symbol_index::crate_symbols(db, krate), |local_candidate| {
 | 
					    local_query.search(&symbol_index::crate_symbols(db, krate), |local_candidate| {
 | 
				
			||||||
        ControlFlow::<()>::Continue(local_results.push(match local_candidate.def {
 | 
					        local_results.push(match local_candidate.def {
 | 
				
			||||||
            hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def),
 | 
					            hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def),
 | 
				
			||||||
            def => ItemInNs::from(def),
 | 
					            def => ItemInNs::from(def),
 | 
				
			||||||
        }))
 | 
					        });
 | 
				
			||||||
 | 
					        ControlFlow::<()>::Continue(())
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    local_results.into_iter().chain(external_importables)
 | 
					    local_results.into_iter().chain(external_importables)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -220,7 +220,10 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut res = vec![];
 | 
					    let mut res = vec![];
 | 
				
			||||||
    query.search::<()>(&indices, |f| ControlFlow::Continue(res.push(f.clone())));
 | 
					    query.search::<()>(&indices, |f| {
 | 
				
			||||||
 | 
					        res.push(f.clone());
 | 
				
			||||||
 | 
					        ControlFlow::Continue(())
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    res
 | 
					    res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue