Skip to content

Commit 90f532b

Browse files
committed
support non standard symbol
Close #679
1 parent 13b8a95 commit 90f532b

File tree

14 files changed

+650
-56
lines changed

14 files changed

+650
-56
lines changed

crates/emmylua_code_analysis/resources/schema.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
},
108108
"extensions": [],
109109
"frameworkVersions": [],
110+
"nonstandardSymbol": [],
110111
"requireLikeFunction": [],
111112
"requirePattern": [],
112113
"version": "LuaLatest"
@@ -754,6 +755,30 @@
754755
}
755756
]
756757
},
758+
"EmmyrcNonStdSymbol": {
759+
"type": "string",
760+
"enum": [
761+
"//",
762+
"/**/",
763+
"`",
764+
"+=",
765+
"-=",
766+
"*=",
767+
"/=",
768+
"%=",
769+
"^=",
770+
"//=",
771+
"|=",
772+
"&=",
773+
"<<=",
774+
">>=",
775+
"||",
776+
"&&",
777+
"!",
778+
"!=",
779+
"continue"
780+
]
781+
},
757782
"EmmyrcReference": {
758783
"type": "object",
759784
"properties": {
@@ -817,6 +842,14 @@
817842
"type": "string"
818843
}
819844
},
845+
"nonstandardSymbol": {
846+
"description": "Non-standard symbols.",
847+
"type": "array",
848+
"default": [],
849+
"items": {
850+
"$ref": "#/$defs/EmmyrcNonStdSymbol"
851+
}
852+
},
820853
"requireLikeFunction": {
821854
"description": "Functions that like require.",
822855
"type": "array",

crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ fn get_local_stat_reference_ranges(
263263
}
264264
} else if parent2.kind() == LuaSyntaxKind::AssignStat.into() {
265265
let stat = LuaAssignStat::cast(parent2)?;
266-
if let Some(assign_token) = stat.token_by_kind(LuaTokenKind::TkAssign) {
266+
if let Some(assign_token) = stat.get_assign_op() {
267267
if assign_token.get_position() > decl_ref.range.start() {
268268
ranges.push(stat.get_range());
269269
for comment in stat.get_comments() {

crates/emmylua_code_analysis/src/config/configs/runtime.rs

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use emmylua_parser::LuaVersionNumber;
1+
use emmylua_parser::{LuaNonStdSymbol, LuaVersionNumber};
22
use schemars::JsonSchema;
33
use serde::{Deserialize, Serialize};
44

@@ -23,6 +23,9 @@ pub struct EmmyrcRuntime {
2323
#[serde(default)]
2424
/// class default overload function.
2525
pub class_default_call: ClassDefaultCall,
26+
/// Non-standard symbols.
27+
#[serde(default)]
28+
pub nonstandard_symbol: Vec<EmmyrcNonStdSymbol>,
2629
}
2730

2831
impl Default for EmmyrcRuntime {
@@ -34,6 +37,7 @@ impl Default for EmmyrcRuntime {
3437
extensions: Default::default(),
3538
require_pattern: Default::default(),
3639
class_default_call: Default::default(),
40+
nonstandard_symbol: Default::default(),
3741
}
3842
}
3943
}
@@ -101,6 +105,74 @@ fn default_true() -> bool {
101105
true
102106
}
103107

108+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
109+
pub enum EmmyrcNonStdSymbol {
110+
#[serde(rename = "//")]
111+
DoubleSlash = 1, // "//"
112+
#[serde(rename = "/**/")]
113+
SlashStar, // "/**/"
114+
#[serde(rename = "`")]
115+
Backtick, // "`"
116+
#[serde(rename = "+=")]
117+
PlusAssign, // "+="
118+
#[serde(rename = "-=")]
119+
MinusAssign, // "-="
120+
#[serde(rename = "*=")]
121+
StarAssign, // "*="
122+
#[serde(rename = "/=")]
123+
SlashAssign, // "/="
124+
#[serde(rename = "%=")]
125+
PercentAssign, // "%="
126+
#[serde(rename = "^=")]
127+
CaretAssign, // "^="
128+
#[serde(rename = "//=")]
129+
DoubleSlashAssign, // "//="
130+
#[serde(rename = "|=")]
131+
PipeAssign, // "|="
132+
#[serde(rename = "&=")]
133+
AmpAssign, // "&="
134+
#[serde(rename = "<<=")]
135+
ShiftLeftAssign, // "<<="
136+
#[serde(rename = ">>=")]
137+
ShiftRightAssign, // ">>="
138+
#[serde(rename = "||")]
139+
DoublePipe, // "||"
140+
#[serde(rename = "&&")]
141+
DoubleAmp, // "&&"
142+
#[serde(rename = "!")]
143+
Exclamation, // "!"
144+
#[serde(rename = "!=")]
145+
NotEqual, // "!="
146+
#[serde(rename = "continue")]
147+
Continue, // "continue"
148+
}
149+
150+
impl From<EmmyrcNonStdSymbol> for LuaNonStdSymbol {
151+
fn from(symbol: EmmyrcNonStdSymbol) -> Self {
152+
match symbol {
153+
EmmyrcNonStdSymbol::DoubleSlash => LuaNonStdSymbol::DoubleSlash,
154+
EmmyrcNonStdSymbol::SlashStar => LuaNonStdSymbol::SlashStar,
155+
EmmyrcNonStdSymbol::Backtick => LuaNonStdSymbol::Backtick,
156+
EmmyrcNonStdSymbol::PlusAssign => LuaNonStdSymbol::PlusAssign,
157+
EmmyrcNonStdSymbol::MinusAssign => LuaNonStdSymbol::MinusAssign,
158+
EmmyrcNonStdSymbol::StarAssign => LuaNonStdSymbol::StarAssign,
159+
EmmyrcNonStdSymbol::SlashAssign => LuaNonStdSymbol::SlashAssign,
160+
EmmyrcNonStdSymbol::PercentAssign => LuaNonStdSymbol::PercentAssign,
161+
EmmyrcNonStdSymbol::CaretAssign => LuaNonStdSymbol::CaretAssign,
162+
EmmyrcNonStdSymbol::DoubleSlashAssign => LuaNonStdSymbol::DoubleSlashAssign,
163+
EmmyrcNonStdSymbol::PipeAssign => LuaNonStdSymbol::PipeAssign,
164+
EmmyrcNonStdSymbol::AmpAssign => LuaNonStdSymbol::AmpAssign,
165+
EmmyrcNonStdSymbol::ShiftLeftAssign => LuaNonStdSymbol::ShiftLeftAssign,
166+
EmmyrcNonStdSymbol::ShiftRightAssign => LuaNonStdSymbol::ShiftRightAssign,
167+
EmmyrcNonStdSymbol::DoublePipe => LuaNonStdSymbol::DoublePipe,
168+
EmmyrcNonStdSymbol::DoubleAmp => LuaNonStdSymbol::DoubleAmp,
169+
EmmyrcNonStdSymbol::Exclamation => LuaNonStdSymbol::Exclamation,
170+
EmmyrcNonStdSymbol::NotEqual => LuaNonStdSymbol::NotEqual,
171+
EmmyrcNonStdSymbol::Continue => LuaNonStdSymbol::Continue,
172+
}
173+
}
174+
}
175+
104176
#[cfg(test)]
105177
mod tests {
106178
use super::*;

crates/emmylua_code_analysis/src/config/mod.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use configs::{
1515
EmmyrcWorkspace,
1616
};
1717
pub use configs::{EmmyrcFilenameConvention, EmmyrcLuaVersion};
18-
use emmylua_parser::{LuaLanguageLevel, ParserConfig, SpecialFunction};
18+
use emmylua_parser::{LuaLanguageLevel, LuaNonStdSymbolSet, ParserConfig, SpecialFunction};
1919
use regex::Regex;
2020
use rowan::NodeCache;
2121
use schemars::JsonSchema;
@@ -71,7 +71,17 @@ impl Emmyrc {
7171
for name in self.runtime.require_like_function.iter() {
7272
special_like.insert(name.clone(), SpecialFunction::Require);
7373
}
74-
ParserConfig::new(lua_language_level, Some(node_cache), special_like)
74+
let mut non_std_symbols = LuaNonStdSymbolSet::new();
75+
for symbol in self.runtime.nonstandard_symbol.iter() {
76+
non_std_symbols.add(symbol.clone().into());
77+
}
78+
79+
ParserConfig::new(
80+
lua_language_level,
81+
Some(node_cache),
82+
special_like,
83+
non_std_symbols,
84+
)
7585
}
7686

7787
pub fn get_language_level(&self) -> LuaLanguageLevel {

crates/emmylua_parser/src/grammar/lua/stat.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ fn parse_local(p: &mut LuaParser) -> ParseResult {
221221
parse_local_name(p, true)?;
222222
}
223223

224-
if p.current_token() == LuaTokenKind::TkAssign {
224+
if p.current_token().is_assign_op() {
225225
p.bump();
226226
parse_expr(p)?;
227227
while p.current_token() == LuaTokenKind::TkComma {
@@ -239,7 +239,7 @@ fn parse_local(p: &mut LuaParser) -> ParseResult {
239239
parse_local_name(p, true)?;
240240
}
241241

242-
if p.current_token() == LuaTokenKind::TkAssign {
242+
if p.current_token().is_assign_op() {
243243
p.bump();
244244
parse_expr(p)?;
245245
while p.current_token() == LuaTokenKind::TkComma {
@@ -423,7 +423,7 @@ fn parse_assign_or_expr_or_global_stat(p: &mut LuaParser) -> ParseResult {
423423
}
424424
}
425425

426-
if p.current_token() == LuaTokenKind::TkAssign {
426+
if p.current_token().is_assign_op() {
427427
p.bump();
428428
parse_expr(p)?;
429429
while p.current_token() == LuaTokenKind::TkComma {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2+
#[repr(u64)]
3+
pub enum LuaNonStdSymbol {
4+
DoubleSlash = 1, // "//"
5+
SlashStar, // "/**/"
6+
Backtick, // "`"
7+
PlusAssign, // "+="
8+
MinusAssign, // "-="
9+
StarAssign, // "*="
10+
SlashAssign, // "/="
11+
PercentAssign, // "%="
12+
CaretAssign, // "^="
13+
DoubleSlashAssign, // "//="
14+
PipeAssign, // "|="
15+
AmpAssign, // "&="
16+
ShiftLeftAssign, // "<<="
17+
ShiftRightAssign, // ">>="
18+
DoublePipe, // "||"
19+
DoubleAmp, // "&&"
20+
Exclamation, // "!"
21+
NotEqual, // "!="
22+
Continue, // "continue"
23+
}
24+
25+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26+
pub struct LuaNonStdSymbolSet(u64);
27+
28+
impl LuaNonStdSymbolSet {
29+
pub fn new() -> Self {
30+
LuaNonStdSymbolSet(0)
31+
}
32+
33+
pub fn add(&mut self, symbol: LuaNonStdSymbol) {
34+
self.0 |= 1 << (symbol as u64);
35+
}
36+
37+
pub fn extends(&mut self, other: Vec<LuaNonStdSymbol>) {
38+
for symbol in other {
39+
self.add(symbol);
40+
}
41+
}
42+
43+
pub fn support(&self, symbol: LuaNonStdSymbol) -> bool {
44+
self.0 & (1 << (symbol as u64)) != 0
45+
}
46+
}

crates/emmylua_parser/src/kind/lua_token_kind.rs

Lines changed: 91 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,35 +29,49 @@ pub enum LuaTokenKind {
2929
TkWhile,
3030
TkGlobal, // global *
3131

32-
TkWhitespace, // whitespace
33-
TkEndOfLine, // end of line
34-
TkPlus, // +
35-
TkMinus, // -
36-
TkMul, // *
37-
TkDiv, // /
38-
TkIDiv, // //
39-
TkDot, // .
40-
TkConcat, // ..
41-
TkDots, // ...
42-
TkComma, // ,
43-
TkAssign, // =
44-
TkEq, // ==
45-
TkGe, // >=
46-
TkLe, // <=
47-
TkNe, // ~=
48-
TkShl, // <<
49-
TkShr, // >>
50-
TkLt, // <
51-
TkGt, // >
52-
TkMod, // %
53-
TkPow, // ^
54-
TkLen, // #
55-
TkBitAnd, // &
56-
TkBitOr, // |
57-
TkBitXor, // ~
58-
TkColon, // :
59-
TkDbColon, // ::
60-
TkSemicolon, // ;
32+
TkWhitespace, // whitespace
33+
TkEndOfLine, // end of line
34+
TkPlus, // +
35+
TkMinus, // -
36+
TkMul, // *
37+
TkDiv, // /
38+
TkIDiv, // //
39+
TkDot, // .
40+
TkConcat, // ..
41+
TkDots, // ...
42+
TkComma, // ,
43+
TkAssign, // =
44+
TkEq, // ==
45+
TkGe, // >=
46+
TkLe, // <=
47+
TkNe, // ~=
48+
TkShl, // <<
49+
TkShr, // >>
50+
TkLt, // <
51+
TkGt, // >
52+
TkMod, // %
53+
TkPow, // ^
54+
TkLen, // #
55+
TkBitAnd, // &
56+
TkBitOr, // |
57+
TkBitXor, // ~
58+
TkColon, // :
59+
TkDbColon, // ::
60+
TkSemicolon, // ;
61+
62+
// Non-standard assignment operators
63+
TkPlusAssign, // +=
64+
TkMinusAssign, // -=
65+
TkStarAssign, // *=
66+
TkSlashAssign, // /=
67+
TkPercentAssign, // %=
68+
TkCaretAssign, // ^=
69+
TkDoubleSlashAssign, // //=
70+
TkPipeAssign, // |=
71+
TkAmpAssign, // &=
72+
TkShiftLeftAssign, // <<=
73+
TkShiftRightAssign, // >>=
74+
6175
TkLeftBracket, // [
6276
TkRightBracket, // ]
6377
TkLeftParen, // (
@@ -148,3 +162,51 @@ impl fmt::Display for LuaTokenKind {
148162
write!(f, "{:?}", self)
149163
}
150164
}
165+
166+
impl LuaTokenKind {
167+
pub fn is_keyword(self) -> bool {
168+
matches!(
169+
self,
170+
LuaTokenKind::TkAnd
171+
| LuaTokenKind::TkBreak
172+
| LuaTokenKind::TkDo
173+
| LuaTokenKind::TkElse
174+
| LuaTokenKind::TkElseIf
175+
| LuaTokenKind::TkEnd
176+
| LuaTokenKind::TkFalse
177+
| LuaTokenKind::TkFor
178+
| LuaTokenKind::TkFunction
179+
| LuaTokenKind::TkGoto
180+
| LuaTokenKind::TkIf
181+
| LuaTokenKind::TkIn
182+
| LuaTokenKind::TkLocal
183+
| LuaTokenKind::TkNil
184+
| LuaTokenKind::TkNot
185+
| LuaTokenKind::TkOr
186+
| LuaTokenKind::TkRepeat
187+
| LuaTokenKind::TkReturn
188+
| LuaTokenKind::TkThen
189+
| LuaTokenKind::TkTrue
190+
| LuaTokenKind::TkUntil
191+
| LuaTokenKind::TkWhile
192+
)
193+
}
194+
195+
pub fn is_assign_op(self) -> bool {
196+
matches!(
197+
self,
198+
LuaTokenKind::TkAssign
199+
| LuaTokenKind::TkPlusAssign
200+
| LuaTokenKind::TkMinusAssign
201+
| LuaTokenKind::TkStarAssign
202+
| LuaTokenKind::TkSlashAssign
203+
| LuaTokenKind::TkPercentAssign
204+
| LuaTokenKind::TkCaretAssign
205+
| LuaTokenKind::TkDoubleSlashAssign
206+
| LuaTokenKind::TkPipeAssign
207+
| LuaTokenKind::TkAmpAssign
208+
| LuaTokenKind::TkShiftLeftAssign
209+
| LuaTokenKind::TkShiftRightAssign
210+
)
211+
}
212+
}

0 commit comments

Comments
 (0)