Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/patterns.rs')
| -rw-r--r-- | crates/ide-completion/src/patterns.rs | 89 |
1 files changed, 1 insertions, 88 deletions
diff --git a/crates/ide-completion/src/patterns.rs b/crates/ide-completion/src/patterns.rs index 88cb486f5d..9efb42c4de 100644 --- a/crates/ide-completion/src/patterns.rs +++ b/crates/ide-completion/src/patterns.rs @@ -4,103 +4,16 @@ //! This means we for example expand a NameRef token to its outermost Path node, as semantically these act in the same location //! and the completions usually query for path specific things on the Path context instead. This simplifies some location handling. -use hir::Semantics; -use ide_db::RootDatabase; use syntax::{ ast::{self, HasLoopBody}, match_ast, AstNode, SyntaxElement, SyntaxKind::*, - SyntaxNode, SyntaxToken, TextSize, + SyntaxNode, SyntaxToken, }; #[cfg(test)] use crate::tests::check_pattern_is_applicable; -/// Direct parent "thing" of what we are currently completing. -/// -/// This may contain nodes of the fake file as well as the original, comments on the variants specify -/// from which file the nodes are. -#[derive(Clone, Debug, PartialEq, Eq)] -pub(crate) enum ImmediateLocation { - TypeBound, - // Only set from a type arg - /// Original file ast node - GenericArgList(ast::GenericArgList), -} - -pub(crate) fn determine_location( - sema: &Semantics<RootDatabase>, - original_file: &SyntaxNode, - offset: TextSize, - name_like: &ast::NameLike, -) -> Option<ImmediateLocation> { - let node = match name_like { - ast::NameLike::NameRef(name_ref) => maximize_name_ref(name_ref), - ast::NameLike::Name(name) => name.syntax().clone(), - ast::NameLike::Lifetime(lt) => lt.syntax().clone(), - }; - - match_ast! { - match node { - ast::TypeBoundList(_it) => return Some(ImmediateLocation::TypeBound), - _ => (), - } - }; - - let parent = match node.parent() { - Some(parent) => match ast::MacroCall::cast(parent.clone()) { - // When a path is being typed in an (Assoc)ItemList the parser will always emit a macro_call. - // This is usually fine as the node expansion code above already accounts for that with - // the ancestors call, but there is one exception to this which is that when an attribute - // precedes it the code above will not walk the Path to the parent MacroCall as their ranges differ. - // FIXME path expr and statement have a similar problem - Some(call) - if call.excl_token().is_none() - && call.token_tree().is_none() - && call.semicolon_token().is_none() => - { - call.syntax().parent()? - } - _ => parent, - }, - // SourceFile - None => return None, - }; - - let res = match_ast! { - match parent { - ast::TypeBound(_) => ImmediateLocation::TypeBound, - ast::TypeBoundList(_) => ImmediateLocation::TypeBound, - ast::GenericArgList(_) => sema - .find_node_at_offset_with_macros(original_file, offset) - .map(ImmediateLocation::GenericArgList)?, - _ => return None, - } - }; - Some(res) -} - -/// Maximize a nameref to its enclosing path if its the last segment of said path. -/// That is, when completing a [`NameRef`] we actually handle it as the path it is part of when determining -/// its location. -fn maximize_name_ref(name_ref: &ast::NameRef) -> SyntaxNode { - if let Some(segment) = name_ref.syntax().parent().and_then(ast::PathSegment::cast) { - let p = segment.parent_path(); - if p.parent_path().is_none() { - // Get rid of PathExpr, PathType, etc... - let path = p - .syntax() - .ancestors() - .take_while(|it| it.text_range() == p.syntax().text_range()) - .last(); - if let Some(it) = path { - return it; - } - } - } - name_ref.syntax().clone() -} - pub(crate) fn previous_token(element: SyntaxElement) -> Option<SyntaxToken> { element.into_token().and_then(previous_non_trivia_token) } |