Skip to content

Commit b644cb4

Browse files
authored
Merge pull request #56 from xuhuanzy/dev
optimize semantic token
2 parents 99193d8 + 06cbc9d commit b644cb4

File tree

4 files changed

+159
-14
lines changed

4 files changed

+159
-14
lines changed

crates/emmylua_code_analysis/src/semantic/semantic_info/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
mod infer_expr_property_owner;
22

33
use emmylua_parser::{
4-
LuaAstNode, LuaDocNameType, LuaDocTag, LuaExpr, LuaSyntaxKind, LuaSyntaxNode, LuaSyntaxToken,
5-
LuaTableField,
4+
LuaAstNode, LuaAstToken, LuaDocNameType, LuaDocTag, LuaExpr, LuaLocalName, LuaSyntaxKind, LuaSyntaxNode, LuaSyntaxToken, LuaTableField
65
};
76
use infer_expr_property_owner::infer_expr_property_owner;
87

@@ -207,6 +206,11 @@ pub fn infer_node_property_owner(
207206
_ => return None,
208207
}
209208
}
209+
local_name if LuaLocalName::can_cast(local_name.kind().into()) => {
210+
let local_name = LuaLocalName::cast(local_name)?;
211+
let name_token = local_name.get_name_token()?;
212+
infer_token_property_owner(db, infer_config, name_token.syntax().clone())
213+
}
210214
_ => None,
211215
}
212216
}

crates/emmylua_ls/src/handlers/semantic_token/build_semantic_tokens.rs

Lines changed: 144 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use emmylua_code_analysis::SemanticModel;
1+
use std::collections::HashSet;
2+
3+
use emmylua_code_analysis::{LuaMemberKey, LuaPropertyOwnerId, LuaType, SemanticModel};
24
use emmylua_parser::{
35
LuaAst, LuaAstNode, LuaAstToken, LuaDocFieldKey, LuaDocObjectFieldKey, LuaExpr, LuaNameToken,
46
LuaSyntaxNode, LuaSyntaxToken, LuaTokenKind, LuaVarExpr,
57
};
68
use lsp_types::{SemanticToken, SemanticTokenModifier, SemanticTokenType};
7-
use rowan::NodeOrToken;
9+
use rowan::{NodeOrToken, TextRange};
810

911
use crate::context::ClientId;
1012

@@ -26,21 +28,33 @@ pub fn build_semantic_tokens(
2628
SEMANTIC_TOKEN_MODIFIERS.to_vec(),
2729
);
2830

31+
// 用于渲染全局方法/标准库
32+
let mut use_range_set = HashSet::new();
33+
calc_name_expr_ref(semantic_model, &mut use_range_set);
34+
2935
for node_or_token in root.syntax().descendants_with_tokens() {
3036
match node_or_token {
3137
NodeOrToken::Node(node) => {
32-
build_node_semantic_token(&mut builder, node, client_id);
38+
build_node_semantic_token(
39+
semantic_model,
40+
&mut builder,
41+
node,
42+
&mut use_range_set,
43+
client_id,
44+
);
3345
}
3446
NodeOrToken::Token(token) => {
35-
build_tokens_semantic_token(&mut builder, token, client_id);
47+
build_tokens_semantic_token(semantic_model, &mut builder, token, client_id);
3648
}
3749
}
3850
}
3951

4052
Some(builder.build())
4153
}
4254

55+
#[allow(unused)]
4356
fn build_tokens_semantic_token(
57+
semantic_model: &SemanticModel,
4458
builder: &mut SemanticBuilder,
4559
token: LuaSyntaxToken,
4660
client_id: ClientId,
@@ -120,7 +134,6 @@ fn build_tokens_semantic_token(
120134
| LuaTokenKind::TkTagAsync
121135
| LuaTokenKind::TkTagCast
122136
| LuaTokenKind::TkTagOther
123-
| LuaTokenKind::TkTagVisibility
124137
| LuaTokenKind::TkTagReadonly
125138
| LuaTokenKind::TkTagDiagnostic
126139
| LuaTokenKind::TkTagMeta
@@ -151,7 +164,7 @@ fn build_tokens_semantic_token(
151164
LuaTokenKind::TkDocQuestion => {
152165
builder.push(token, SemanticTokenType::OPERATOR);
153166
}
154-
LuaTokenKind::TkDocVisibility => {
167+
LuaTokenKind::TkDocVisibility | LuaTokenKind::TkTagVisibility => {
155168
builder.push_with_modifier(
156169
token,
157170
SemanticTokenType::KEYWORD,
@@ -192,19 +205,45 @@ fn build_tokens_semantic_token(
192205
SemanticTokenModifier::DOCUMENTATION,
193206
);
194207
}
208+
// LuaTokenKind::TkName => {
209+
// let property_owner = semantic_model.get_property_owner_id(token.clone().into());
210+
// match property_owner {
211+
// Some(LuaPropertyOwnerId::LuaDecl(decl_id)) => {
212+
// let decl = semantic_model.get_db().get_decl_index().get_decl(&decl_id);
213+
// if let Some(decl) = decl {
214+
// let decl_type = decl.get_type();
215+
// if let Some(decl_type) = decl_type {
216+
// match decl_type {
217+
// LuaType::Def(def) => {
218+
// builder.push(token, SemanticTokenType::CLASS);
219+
// }
220+
// _ => {}
221+
// }
222+
// }
223+
// }
224+
// }
225+
// _ => {}
226+
// }
227+
// }
195228
_ => {}
196229
}
197230
}
198231

199232
fn build_node_semantic_token(
233+
semantic_model: &SemanticModel,
200234
builder: &mut SemanticBuilder,
201235
node: LuaSyntaxNode,
236+
use_range_set: &mut HashSet<TextRange>,
202237
_: ClientId,
203238
) -> Option<()> {
204239
match LuaAst::cast(node)? {
205240
LuaAst::LuaDocTagClass(doc_class) => {
206241
let name = doc_class.get_name_token()?;
207-
builder.push(name.syntax().clone(), SemanticTokenType::CLASS);
242+
builder.push_with_modifier(
243+
name.syntax().clone(),
244+
SemanticTokenType::CLASS,
245+
SemanticTokenModifier::DECLARATION,
246+
);
208247
if let Some(attribs) = doc_class.get_attrib() {
209248
for attrib_token in attribs.get_attrib_tokens() {
210249
builder.push(attrib_token.syntax().clone(), SemanticTokenType::MODIFIER);
@@ -213,7 +252,11 @@ fn build_node_semantic_token(
213252
if let Some(generic_list) = doc_class.get_generic_decl() {
214253
for generic_decl in generic_list.get_generic_decl() {
215254
if let Some(name) = generic_decl.get_name_token() {
216-
builder.push(name.syntax().clone(), SemanticTokenType::TYPE_PARAMETER);
255+
builder.push_with_modifier(
256+
name.syntax().clone(),
257+
SemanticTokenType::CLASS,
258+
SemanticTokenModifier::DECLARATION,
259+
);
217260
}
218261
}
219262
}
@@ -265,7 +308,11 @@ fn build_node_semantic_token(
265308
let type_parameter_list = doc_generic.get_generic_decl_list()?;
266309
for type_decl in type_parameter_list.get_generic_decl() {
267310
if let Some(name) = type_decl.get_name_token() {
268-
builder.push(name.syntax().clone(), SemanticTokenType::TYPE_PARAMETER);
311+
builder.push_with_modifier(
312+
name.syntax().clone(),
313+
SemanticTokenType::TYPE,
314+
SemanticTokenModifier::DECLARATION,
315+
);
269316
}
270317
}
271318
}
@@ -283,10 +330,18 @@ fn build_node_semantic_token(
283330
}
284331
LuaAst::LuaLocalName(local_name) => {
285332
let name = local_name.get_name_token()?;
333+
if let Some(true) = is_class_def(semantic_model, local_name.syntax().clone()) {
334+
builder.push(name.syntax().clone(), SemanticTokenType::CLASS);
335+
return Some(());
336+
}
286337
builder.push(name.syntax().clone(), SemanticTokenType::VARIABLE);
287338
}
288339
LuaAst::LuaNameExpr(name_expr) => {
289340
let name = name_expr.get_name_token()?;
341+
if let Some(true) = is_class_def(semantic_model, name_expr.syntax().clone()) {
342+
builder.push(name.syntax().clone(), SemanticTokenType::CLASS);
343+
return Some(());
344+
}
290345
builder.push(name.syntax().clone(), SemanticTokenType::VARIABLE);
291346
}
292347
LuaAst::LuaForRangeStat(for_range_stat) => {
@@ -315,15 +370,52 @@ fn build_node_semantic_token(
315370
}
316371
}
317372
}
373+
LuaAst::LuaLocalStat(local_stat) => {
374+
let var_exprs = local_stat.descendants::<LuaVarExpr>();
375+
for var_expr in var_exprs {
376+
match var_expr {
377+
LuaVarExpr::IndexExpr(name_expr) => {
378+
let name = name_expr.get_name_token()?;
379+
builder.push(name.syntax().clone(), SemanticTokenType::PROPERTY);
380+
}
381+
_ => {}
382+
}
383+
}
384+
}
318385
LuaAst::LuaLocalAttribute(local_attribute) => {
319386
let name = local_attribute.get_name_token()?;
320387
builder.push(name.syntax().clone(), SemanticTokenType::KEYWORD);
321388
}
322389
LuaAst::LuaCallExpr(call_expr) => {
323390
let prefix = call_expr.get_prefix_expr()?;
391+
let prefix_type = semantic_model.infer_expr(prefix.clone());
392+
324393
match prefix {
325394
LuaExpr::NameExpr(name_expr) => {
326395
let name = name_expr.get_name_token()?;
396+
397+
if let Some(prefix_type) = prefix_type {
398+
match prefix_type {
399+
LuaType::Signature(_) => {
400+
let name_text = name_expr.get_name_text()?;
401+
let name_range = name_expr.get_range();
402+
if !use_range_set.contains(&name_range) {
403+
let decl_index = semantic_model.get_db().get_decl_index();
404+
let member_key = LuaMemberKey::Name(name_text.clone().into());
405+
if decl_index.get_global_decl_id(&member_key).is_some() {
406+
builder.push_with_modifier(
407+
name.syntax().clone(),
408+
SemanticTokenType::FUNCTION,
409+
SemanticTokenModifier::DEFAULT_LIBRARY,
410+
);
411+
return Some(());
412+
}
413+
}
414+
}
415+
_ => {}
416+
}
417+
}
418+
327419
builder.push(name.syntax().clone(), SemanticTokenType::FUNCTION);
328420
}
329421
LuaExpr::IndexExpr(index_expr) => {
@@ -336,7 +428,11 @@ fn build_node_semantic_token(
336428
LuaAst::LuaDocNameType(doc_name_type) => {
337429
let name = doc_name_type.get_name_token()?;
338430
if name.get_name_text() == "self" {
339-
builder.push(name.syntax().clone(), SemanticTokenType::KEYWORD);
431+
builder.push_with_modifier(
432+
name.syntax().clone(),
433+
SemanticTokenType::TYPE,
434+
SemanticTokenModifier::READONLY,
435+
);
340436
} else {
341437
builder.push(name.syntax().clone(), SemanticTokenType::TYPE);
342438
}
@@ -376,8 +472,46 @@ fn build_node_semantic_token(
376472
builder.push(name.syntax().clone(), SemanticTokenType::PARAMETER);
377473
}
378474
}
475+
LuaAst::LuaIndexExpr(index_expr) => {
476+
let name = index_expr.get_name_token()?;
477+
builder.push(name.syntax().clone(), SemanticTokenType::PROPERTY);
478+
}
379479
_ => {}
380480
}
381481

382482
Some(())
383483
}
484+
485+
fn is_class_def(semantic_model: &SemanticModel, node: LuaSyntaxNode) -> Option<bool> {
486+
let property_owner = semantic_model.get_property_owner_id(node.into())?;
487+
488+
if let LuaPropertyOwnerId::LuaDecl(decl_id) = property_owner {
489+
let decl = semantic_model
490+
.get_db()
491+
.get_decl_index()
492+
.get_decl(&decl_id)?
493+
.get_type()?;
494+
match decl {
495+
LuaType::Def(_) => Some(true),
496+
_ => None,
497+
}
498+
} else {
499+
None
500+
}
501+
}
502+
503+
fn calc_name_expr_ref(
504+
semantic_model: &SemanticModel,
505+
use_range_set: &mut HashSet<TextRange>,
506+
) -> Option<()> {
507+
let file_id = semantic_model.get_file_id();
508+
let db = semantic_model.get_db();
509+
let refs_index = db.get_reference_index().get_local_reference(&file_id)?;
510+
for (_, decl_refs) in refs_index.get_decl_references_map() {
511+
for decl_ref in decl_refs {
512+
use_range_set.insert(decl_ref.range.clone());
513+
}
514+
}
515+
516+
None
517+
}

crates/emmylua_ls/src/handlers/semantic_token/semantic_token_builder.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ pub const SEMANTIC_TOKEN_TYPES: &[SemanticTokenType] = &[
3131
];
3232

3333
pub const SEMANTIC_TOKEN_MODIFIERS: &[SemanticTokenModifier] = &[
34-
SemanticTokenModifier::MODIFICATION,
3534
SemanticTokenModifier::DECLARATION,
3635
SemanticTokenModifier::DEFINITION,
3736
SemanticTokenModifier::READONLY,
3837
SemanticTokenModifier::STATIC,
3938
SemanticTokenModifier::ABSTRACT,
4039
SemanticTokenModifier::DEPRECATED,
41-
SemanticTokenModifier::DOCUMENTATION
40+
SemanticTokenModifier::ASYNC,
41+
SemanticTokenModifier::MODIFICATION,
42+
SemanticTokenModifier::DOCUMENTATION,
43+
SemanticTokenModifier::DEFAULT_LIBRARY,
4244
];
4345

4446
#[derive(Debug)]

crates/emmylua_parser/src/syntax/node/lua/expr.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,13 @@ impl LuaIndexExpr {
314314
let index_token = self.get_index_token()?;
315315
index_token.syntax().next_token()
316316
}
317+
318+
pub fn get_name_token(&self) -> Option<LuaNameToken> {
319+
self.token()
320+
}
317321
}
318322

323+
319324
impl PathTrait for LuaIndexExpr {}
320325

321326
impl From<LuaIndexExpr> for LuaVarExpr {

0 commit comments

Comments
 (0)