From 8ae56fa6d0e8a03d6ad75919d6be953f5fc27083 Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Mon, 13 Aug 2018 16:35:17 +0300
Subject: Stupid goto definition

---
 crates/libanalysis/src/lib.rs | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

(limited to 'crates/libanalysis/src')

diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index b2f4bdbb3..97b6dfca6 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -18,10 +18,14 @@ use std::{
     path::{PathBuf, Path},
 };
 
-use libsyntax2::ast;
+use libsyntax2::{
+    TextUnit,
+    ast::{self, AstNode},
+    algo::{find_leaf_at_offset, ancestors},
+};
 use libeditor::{LineIndex, FileSymbol};
 
-use self::symbol_index::{FileSymbols};
+use self::symbol_index::FileSymbols;
 pub use self::symbol_index::Query;
 
 pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
@@ -90,8 +94,7 @@ impl World {
         Ok(index.clone())
     }
 
-    pub fn world_symbols<'a>(&'a self, query: Query) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a
-    {
+    pub fn world_symbols<'a>(&'a self, query: Query) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a {
         self.data.file_map.iter()
             .flat_map(move |(path, data)| {
                 let path: &'a Path = path.as_path();
@@ -100,6 +103,31 @@ impl World {
             })
     }
 
+    pub fn approximately_resolve_symbol<'a>(
+        &'a self,
+        path: &Path,
+        offset: TextUnit,
+    ) -> Result<Vec<(&'a Path, &'a FileSymbol)>> {
+        let file = self.file_syntax(path)?;
+        let syntax = file.syntax();
+        let syntax = syntax.as_ref();
+        let name_ref =
+            find_leaf_at_offset(syntax, offset)
+                .left_biased()
+                .into_iter()
+                .flat_map(|node| ancestors(node))
+                .flat_map(ast::NameRef::cast)
+                .next();
+        let name = match name_ref {
+            None => return Ok(vec![]),
+            Some(name_ref) => name_ref.text(),
+        };
+
+        let mut query = Query::new(name.to_string());
+        query.exact();
+        Ok(self.world_symbols(query).take(4).collect())
+    }
+
     fn file_data(&self, path: &Path) -> Result<Arc<FileData>> {
         match self.data.file_map.get(path) {
             Some(data) => Ok(data.clone()),
-- 
cgit v1.2.3