Skip to content

Commit 965d40c

Browse files
committed
refactor goto defination, and support string references search
1 parent ae61381 commit 965d40c

File tree

12 files changed

+210
-53
lines changed

12 files changed

+210
-53
lines changed

crates/code_analysis/src/compilation/analyzer/decl/exprs.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use emmylua_parser::{
2-
LuaAstNode, LuaAstToken, LuaClosureExpr, LuaIndexExpr, LuaIndexKey, LuaNameExpr, LuaTableExpr,
2+
LuaAstNode, LuaAstToken, LuaClosureExpr, LuaIndexExpr, LuaIndexKey, LuaLiteralExpr,
3+
LuaLiteralToken, LuaNameExpr, LuaTableExpr,
34
};
5+
use internment::ArcIntern;
46

57
use crate::{
68
db_index::{LuaDecl, LuaMember, LuaMemberKey, LuaMemberOwner},
@@ -162,3 +164,20 @@ pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, expr: LuaTableExpr) -> Op
162164

163165
Some(())
164166
}
167+
168+
pub fn analyze_literal_expr(analyzer: &mut DeclAnalyzer, expr: LuaLiteralExpr) -> Option<()> {
169+
if let LuaLiteralToken::String(string_token) = expr.get_literal()? {
170+
let file_id = analyzer.get_file_id();
171+
let value = string_token.get_value();
172+
if value.len() > 64 {
173+
return Some(());
174+
}
175+
176+
analyzer
177+
.db
178+
.get_reference_index_mut()
179+
.add_string_reference(file_id, ArcIntern::new(value), string_token.get_range());
180+
}
181+
182+
Some(())
183+
}

crates/code_analysis/src/compilation/analyzer/decl/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ fn walk_node_enter(analyzer: &mut DeclAnalyzer, node: LuaAst) {
7272
LuaAst::LuaTableExpr(expr) => {
7373
exprs::analyze_table_expr(analyzer, expr);
7474
}
75+
LuaAst::LuaLiteralExpr(expr) => {
76+
exprs::analyze_literal_expr(analyzer, expr);
77+
}
7578
LuaAst::LuaDocTagClass(doc_tag) => {
7679
docs::analyze_doc_tag_class(analyzer, doc_tag);
7780
}

crates/code_analysis/src/db_index/reference/local_reference.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
use std::collections::HashMap;
2-
32
use rowan::TextRange;
43

54
use crate::db_index::LuaDeclId;
65

76
#[derive(Debug)]
87
pub struct LocalReference {
98
local_references: HashMap<LuaDeclId, Vec<TextRange>>,
10-
references_to_decl: HashMap<TextRange, LuaDeclId>
9+
references_to_decl: HashMap<TextRange, LuaDeclId>,
1110
}
1211

1312
impl LocalReference {

crates/code_analysis/src/db_index/reference/mod.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
mod local_reference;
2+
mod string_reference;
23

34
use std::collections::HashMap;
45

56
use emmylua_parser::{LuaSyntaxId, LuaSyntaxKind};
67
use internment::ArcIntern;
78
use local_reference::LocalReference;
89
use rowan::TextRange;
10+
use string_reference::StringReference;
911

1012
use crate::{FileId, InFiled};
1113

@@ -15,13 +17,15 @@ use super::{traits::LuaIndex, LuaDeclId, LuaMemberKey};
1517
pub struct LuaReferenceIndex {
1618
local_references: HashMap<FileId, LocalReference>,
1719
index_reference: HashMap<LuaMemberKey, HashMap<FileId, Vec<LuaSyntaxId>>>,
20+
string_references: HashMap<FileId, StringReference>,
1821
}
1922

2023
impl LuaReferenceIndex {
2124
pub fn new() -> Self {
2225
Self {
2326
local_references: HashMap::new(),
2427
index_reference: HashMap::new(),
28+
string_references: HashMap::new(),
2529
}
2630
}
2731

@@ -56,6 +60,18 @@ impl LuaReferenceIndex {
5660
.push(syntax_id);
5761
}
5862

63+
pub fn add_string_reference(
64+
&mut self,
65+
file_id: FileId,
66+
string: ArcIntern<String>,
67+
range: TextRange,
68+
) {
69+
self.string_references
70+
.entry(file_id)
71+
.or_insert_with(StringReference::new)
72+
.add_string_reference(string, range);
73+
}
74+
5975
pub fn get_local_reference(&self, file_id: &FileId) -> Option<&LocalReference> {
6076
self.local_references.get(file_id)
6177
}
@@ -142,12 +158,29 @@ impl LuaReferenceIndex {
142158

143159
Some(results)
144160
}
161+
162+
pub fn get_string_references(&self, string_value: &str) -> Vec<InFiled<TextRange>> {
163+
let arc_string = ArcIntern::new(string_value.to_string());
164+
let results = self
165+
.string_references
166+
.iter()
167+
.map(|(file_id, string_reference)| {
168+
string_reference
169+
.get_string_references(&arc_string)
170+
.into_iter()
171+
.map(|range| InFiled::new(*file_id, range))
172+
})
173+
.flatten()
174+
.collect();
175+
176+
results
177+
}
145178
}
146179

147180
impl LuaIndex for LuaReferenceIndex {
148181
fn remove(&mut self, file_id: FileId) {
149182
self.local_references.remove(&file_id);
150-
183+
self.string_references.remove(&file_id);
151184
let mut to_be_remove = Vec::new();
152185
for (key, references) in self.index_reference.iter_mut() {
153186
references.remove(&file_id);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use internment::ArcIntern;
2+
use rowan::TextRange;
3+
use std::collections::HashMap;
4+
5+
#[derive(Debug)]
6+
pub struct StringReference {
7+
string_references: HashMap<ArcIntern<String>, Vec<TextRange>>,
8+
}
9+
10+
impl StringReference {
11+
pub fn new() -> Self {
12+
Self {
13+
string_references: HashMap::new(),
14+
}
15+
}
16+
17+
pub fn add_string_reference(&mut self, string: ArcIntern<String>, range: TextRange) {
18+
self.string_references
19+
.entry(string)
20+
.or_insert_with(Vec::new)
21+
.push(range);
22+
}
23+
24+
pub fn get_string_references(&self, string: &ArcIntern<String>) -> Vec<TextRange> {
25+
self.string_references
26+
.get(string)
27+
.cloned()
28+
.unwrap_or_default()
29+
}
30+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use code_analysis::{LuaPropertyOwnerId, SemanticModel};
2+
use lsp_types::GotoDefinitionResponse;
3+
4+
pub fn goto_def_defination(
5+
semantic_model: &SemanticModel,
6+
property_owner: LuaPropertyOwnerId,
7+
) -> Option<GotoDefinitionResponse> {
8+
match property_owner {
9+
LuaPropertyOwnerId::LuaDecl(decl_id) => {
10+
let decl = semantic_model
11+
.get_db()
12+
.get_decl_index()
13+
.get_decl(&decl_id)?;
14+
let document = semantic_model.get_document_by_file_id(decl_id.file_id)?;
15+
let location = document.to_lsp_location(decl.get_range())?;
16+
return Some(GotoDefinitionResponse::Scalar(location));
17+
}
18+
LuaPropertyOwnerId::Member(member_id) => {
19+
let member = semantic_model
20+
.get_db()
21+
.get_member_index()
22+
.get_member(&member_id)?;
23+
let document = semantic_model.get_document_by_file_id(member_id.file_id)?;
24+
let location = document.to_lsp_location(member.get_range())?;
25+
return Some(GotoDefinitionResponse::Scalar(location));
26+
}
27+
LuaPropertyOwnerId::TypeDecl(type_decl_id) => {
28+
let type_decl = semantic_model
29+
.get_db()
30+
.get_type_index()
31+
.get_type_decl(&type_decl_id)?;
32+
let mut locations = Vec::new();
33+
for lua_location in type_decl.get_locations() {
34+
let document = semantic_model.get_document_by_file_id(lua_location.file_id)?;
35+
let location = document.to_lsp_location(lua_location.range)?;
36+
locations.push(location);
37+
}
38+
39+
return Some(GotoDefinitionResponse::Array(locations));
40+
}
41+
_ => {}
42+
}
43+
44+
None
45+
}

crates/emmylua_ls/src/handlers/defination/goto_doc_see.rs

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use code_analysis::SemanticModel;
2+
use emmylua_parser::LuaStringToken;
3+
use lsp_types::{GotoDefinitionResponse, Location};
4+
5+
use crate::handlers::document_link::is_require_path;
6+
7+
pub fn goto_module_file(
8+
semantic_model: &SemanticModel,
9+
string_token: LuaStringToken,
10+
) -> Option<GotoDefinitionResponse> {
11+
let emmyrc = semantic_model.get_emmyrc();
12+
if !is_require_path(string_token.clone(), &emmyrc).unwrap_or(false) {
13+
return None;
14+
}
15+
16+
let module_path = string_token.get_value();
17+
let module_index = semantic_model.get_db().get_module_index();
18+
let founded_module = module_index.find_module(&module_path)?;
19+
let file_id = founded_module.file_id;
20+
let document = semantic_model.get_document_by_file_id(file_id)?;
21+
let uri = document.get_uri();
22+
let lsp_range = document.get_document_lsp_range();
23+
24+
Some(GotoDefinitionResponse::Scalar(Location {
25+
uri,
26+
range: lsp_range,
27+
}))
28+
}

crates/emmylua_ls/src/handlers/defination/mod.rs

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
use code_analysis::LuaPropertyOwnerId;
2-
use emmylua_parser::{LuaAstNode, LuaTokenKind};
1+
mod goto_def_defination;
2+
mod goto_doc_see;
3+
mod goto_module_file;
4+
5+
use emmylua_parser::{LuaAstNode, LuaAstToken, LuaStringToken, LuaTokenKind};
6+
use goto_def_defination::goto_def_defination;
7+
use goto_module_file::goto_module_file;
38
use lsp_types::{
49
ClientCapabilities, GotoDefinitionParams, GotoDefinitionResponse, OneOf, ServerCapabilities,
510
};
@@ -42,44 +47,13 @@ pub async fn on_goto_defination_handler(
4247
}
4348
};
4449

45-
let semantic_info = semantic_model.get_semantic_info(token.clone().into())?;
46-
match semantic_info.property_owner? {
47-
LuaPropertyOwnerId::LuaDecl(decl_id) => {
48-
let decl = semantic_model
49-
.get_db()
50-
.get_decl_index()
51-
.get_decl(&decl_id)?;
52-
let document = semantic_model.get_document_by_file_id(decl_id.file_id)?;
53-
let location = document.to_lsp_location(decl.get_range())?;
54-
return Some(GotoDefinitionResponse::Scalar(location));
55-
}
56-
LuaPropertyOwnerId::Member(member_id) => {
57-
let member = semantic_model
58-
.get_db()
59-
.get_member_index()
60-
.get_member(&member_id)?;
61-
let document = semantic_model.get_document_by_file_id(member_id.file_id)?;
62-
let location = document.to_lsp_location(member.get_range())?;
63-
return Some(GotoDefinitionResponse::Scalar(location));
64-
}
65-
LuaPropertyOwnerId::TypeDecl(type_decl_id) => {
66-
let type_decl = semantic_model
67-
.get_db()
68-
.get_type_index()
69-
.get_type_decl(&type_decl_id)?;
70-
let mut locations = Vec::new();
71-
for lua_location in type_decl.get_locations() {
72-
let document = semantic_model.get_document_by_file_id(lua_location.file_id)?;
73-
let location = document.to_lsp_location(lua_location.range)?;
74-
locations.push(location);
75-
}
76-
77-
return Some(GotoDefinitionResponse::Array(locations));
78-
}
79-
_ => {}
50+
if let Some(property_owner) = semantic_model.get_property_owner_id(token.clone().into()) {
51+
goto_def_defination(&semantic_model, property_owner);
52+
} else if let Some(string_token) = LuaStringToken::cast(token) {
53+
goto_module_file(&semantic_model, string_token);
8054
}
8155

82-
None
56+
Some(GotoDefinitionResponse::Array(vec![]))
8357
}
8458

8559
pub fn register_capabilities(

crates/emmylua_ls/src/handlers/document_link/build_link.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn try_build_module_link(
103103
Some(())
104104
}
105105

106-
fn is_require_path(token: LuaStringToken, emmyrc: &Emmyrc) -> Option<bool> {
106+
pub fn is_require_path(token: LuaStringToken, emmyrc: &Emmyrc) -> Option<bool> {
107107
let call_expr_prefix = token
108108
.get_parent::<LuaLiteralExpr>()?
109109
.get_parent::<LuaCallArgList>()?

0 commit comments

Comments
 (0)