Skip to content

Commit 1b158f3

Browse files
committed
feat: add no-runtime-private-fields rule
1 parent 2fcb88c commit 1b158f3

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed

src/rules.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub mod no_process_global;
9393
pub mod no_prototype_builtins;
9494
pub mod no_redeclare;
9595
pub mod no_regex_spaces;
96+
pub mod no_runtime_private_fields;
9697
pub mod no_self_assign;
9798
pub mod no_self_compare;
9899
pub mod no_setter_return;
@@ -340,6 +341,7 @@ fn get_all_rules_raw() -> Vec<Box<dyn LintRule>> {
340341
Box::new(no_prototype_builtins::NoPrototypeBuiltins),
341342
Box::new(no_redeclare::NoRedeclare),
342343
Box::new(no_regex_spaces::NoRegexSpaces),
344+
Box::new(no_runtime_private_fields::NoRuntimePrivateFields),
343345
Box::new(no_self_assign::NoSelfAssign),
344346
Box::new(no_self_compare::NoSelfCompare),
345347
Box::new(no_setter_return::NoSetterReturn),
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
use super::program_ref;
2+
use super::{Context, LintRule};
3+
use crate::tags::Tags;
4+
use crate::Program;
5+
use crate::ProgramRef;
6+
use deno_ast::swc::ast::{PrivateMethod, PrivateProp};
7+
use deno_ast::swc::ecma_visit::{Visit, VisitWith};
8+
use deno_ast::SourceRangedForSpanned;
9+
use derive_more::Display;
10+
11+
#[derive(Debug)]
12+
pub struct NoRuntimePrivateFields;
13+
14+
const CODE: &str = "no-runtime-private-fields";
15+
16+
#[derive(Display)]
17+
enum NoRuntimePrivateFieldsMessage {
18+
#[display(fmt = "Avoid prefixing fields with `#`")]
19+
Default,
20+
}
21+
22+
#[derive(Display)]
23+
enum NoRuntimePrivateFieldsHint {
24+
#[display(fmt = "Use `private {}`", _0)]
25+
Default(String),
26+
#[display(fmt = "Use `static {}`", _0)]
27+
Static(String),
28+
}
29+
30+
impl LintRule for NoRuntimePrivateFields {
31+
fn tags(&self) -> Tags {
32+
&[]
33+
}
34+
35+
fn code(&self) -> &'static str {
36+
CODE
37+
}
38+
39+
fn lint_program_with_ast_view<'view>(
40+
&self,
41+
context: &mut Context<'view>,
42+
program: Program<'view>,
43+
) {
44+
let program = program_ref(program);
45+
let mut visitor = NoRuntimePrivateFieldsVisitor::new(context);
46+
match program {
47+
ProgramRef::Module(m) => m.visit_with(&mut visitor),
48+
ProgramRef::Script(s) => s.visit_with(&mut visitor),
49+
}
50+
}
51+
}
52+
53+
struct NoRuntimePrivateFieldsVisitor<'c, 'view> {
54+
context: &'c mut Context<'view>,
55+
}
56+
57+
impl<'c, 'view> NoRuntimePrivateFieldsVisitor<'c, 'view> {
58+
fn new(context: &'c mut Context<'view>) -> Self {
59+
Self { context }
60+
}
61+
}
62+
63+
impl Visit for NoRuntimePrivateFieldsVisitor<'_, '_> {
64+
fn visit_private_method(&mut self, method: &PrivateMethod) {
65+
self.context.add_diagnostic_with_hint(
66+
method.range(),
67+
CODE,
68+
NoRuntimePrivateFieldsMessage::Default,
69+
NoRuntimePrivateFieldsHint::Default(method.key.name.to_string()),
70+
);
71+
}
72+
73+
fn visit_private_prop(&mut self, prop: &PrivateProp) {
74+
if prop.is_static {
75+
self.context.add_diagnostic_with_hint(
76+
prop.range(),
77+
CODE,
78+
NoRuntimePrivateFieldsMessage::Default,
79+
NoRuntimePrivateFieldsHint::Static(prop.key.name.to_string()),
80+
);
81+
return;
82+
}
83+
84+
self.context.add_diagnostic_with_hint(
85+
prop.range(),
86+
CODE,
87+
NoRuntimePrivateFieldsMessage::Default,
88+
NoRuntimePrivateFieldsHint::Default(prop.key.name.to_string()),
89+
);
90+
}
91+
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use super::*;
96+
97+
#[test]
98+
fn no_runtime_private_fields_valid() {
99+
assert_lint_ok! {
100+
NoRuntimePrivateFields,
101+
"class Test { testField = 0; }",
102+
"class Test { _testField = 1; }",
103+
"class Test { private testField = 2; }",
104+
"class Test { public testField = 3; }",
105+
"class Test { protected testField = 4; }",
106+
"class Test { static staticField = 5; }",
107+
};
108+
}
109+
110+
#[test]
111+
fn no_runtime_private_fields_invalid() {
112+
assert_lint_err! {
113+
NoRuntimePrivateFields,
114+
"class Test {
115+
#runtimePrivate = 2;}":
116+
[
117+
{
118+
line: 2,
119+
col: 4,
120+
message: variant!(NoRuntimePrivateFieldsMessage, Default),
121+
hint: variant!(NoRuntimePrivateFieldsHint, Default, "runtimePrivate"),
122+
}
123+
],
124+
"class Test {
125+
private #keywordAndRuntimePrivate = 3;}":
126+
[
127+
{
128+
line: 2,
129+
col: 4,
130+
message: variant!(NoRuntimePrivateFieldsMessage, Default),
131+
hint: variant!(NoRuntimePrivateFieldsHint, Default, "keywordAndRuntimePrivate"),
132+
}
133+
],
134+
"class Test {
135+
static #STATIC_FIELD = 3;}":
136+
[
137+
{
138+
line: 2,
139+
col: 4,
140+
message: variant!(NoRuntimePrivateFieldsMessage, Default),
141+
hint: variant!(NoRuntimePrivateFieldsHint, Static, "STATIC_FIELD"),
142+
}
143+
]
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)