Skip to content

Commit 4b171f2

Browse files
committed
refactor: Introducing new Visitor pattern in linter
1 parent 64d1030 commit 4b171f2

3 files changed

Lines changed: 144 additions & 99 deletions

File tree

rusty_linter/src/core/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod traits;
88
mod type_resolver;
99
mod type_resolver_impl;
1010
mod types;
11+
mod visitor;
1112

1213
pub use self::casting::*;
1314
pub use self::const_value_resolver::*;
@@ -19,3 +20,4 @@ pub use self::traits::*;
1920
pub use self::type_resolver::*;
2021
pub use self::type_resolver_impl::*;
2122
pub use self::types::*;
23+
pub use self::visitor::*;

rusty_linter/src/core/visitor.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use rusty_common::{Position, Positioned};
2+
use rusty_parser::*;
3+
4+
use crate::LintErrorPos;
5+
6+
pub type VisitResult = Result<(), LintErrorPos>;
7+
8+
pub trait Visitor<T> {
9+
fn visit(&mut self, element: &T) -> VisitResult;
10+
}
11+
12+
pub trait PosVisitor {
13+
fn set_pos(&mut self, pos: Position);
14+
}
15+
16+
impl<P, T> Visitor<Vec<T>> for P
17+
where
18+
P: Visitor<T>,
19+
{
20+
fn visit(&mut self, elements: &Vec<T>) -> VisitResult {
21+
for element in elements {
22+
self.visit(element)?;
23+
}
24+
Ok(())
25+
}
26+
}
27+
28+
impl<P, T> Visitor<Positioned<T>> for P
29+
where
30+
P: Visitor<T> + PosVisitor,
31+
{
32+
fn visit(&mut self, element: &Positioned<T>) -> VisitResult {
33+
let Positioned { element, pos } = element;
34+
self.set_pos(*pos);
35+
self.visit(element)
36+
}
37+
}
38+
39+
impl<P> Visitor<GlobalStatement> for P
40+
where
41+
P: Visitor<DefType>
42+
+ Visitor<FunctionDeclaration>
43+
+ Visitor<FunctionImplementation>
44+
+ Visitor<Statement>
45+
+ Visitor<SubDeclaration>
46+
+ Visitor<SubImplementation>
47+
+ Visitor<UserDefinedType>,
48+
{
49+
fn visit(&mut self, element: &GlobalStatement) -> VisitResult {
50+
match element {
51+
GlobalStatement::DefType(def_type) => self.visit(def_type),
52+
GlobalStatement::FunctionDeclaration(f) => self.visit(f),
53+
GlobalStatement::FunctionImplementation(f) => self.visit(f),
54+
GlobalStatement::Statement(statement) => self.visit(statement),
55+
GlobalStatement::SubDeclaration(s) => self.visit(s),
56+
GlobalStatement::SubImplementation(s) => self.visit(s),
57+
GlobalStatement::UserDefinedType(user_defined_type) => self.visit(user_defined_type),
58+
}
59+
}
60+
}
Lines changed: 82 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use crate::core::IntoTypeQualifier;
2+
use crate::core::PosVisitor;
23
use crate::core::TypeResolverImpl;
4+
use crate::core::VisitResult;
5+
use crate::core::Visitor;
36
use crate::core::{LintError, LintErrorPos};
47
use crate::core::{LintResult, ResolvedParamType};
58
use crate::pre_linter::const_rules::global_const;
@@ -26,7 +29,7 @@ pub fn pre_lint_program(program: &Program) -> Result<PreLinterResult, LintErrorP
2629
global_constants: Default::default(),
2730
declaration_pos: Position::start(),
2831
};
29-
ctx.on_program(program)?;
32+
<MainContext as Visitor<Program>>::visit(&mut ctx, program)?;
3033
ctx.functions.post_visit()?;
3134
ctx.subs.post_visit()?;
3235
Ok(PreLinterResult::new(
@@ -42,41 +45,70 @@ pub fn pre_lint_program(program: &Program) -> Result<PreLinterResult, LintErrorP
4245
// FUNCTION/SUB -> depends on resolver for resolving bare names and on user_defined_types to ensure types exist
4346

4447
impl MainContext {
45-
fn on_program(&mut self, program: &Program) -> Result<(), LintErrorPos> {
46-
for Positioned { element, pos } in program {
47-
self.declaration_pos = *pos;
48-
match element {
49-
GlobalStatement::DefType(def_type) => {
50-
self.on_def_type(def_type);
51-
}
52-
GlobalStatement::FunctionDeclaration(f) => {
53-
self.on_function_declaration(f)?;
54-
}
55-
GlobalStatement::FunctionImplementation(f) => {
56-
self.on_function_implementation(f)?;
57-
}
58-
GlobalStatement::Statement(s) => {
59-
self.on_statement(s)?;
60-
}
61-
GlobalStatement::SubDeclaration(s) => {
62-
self.on_sub_declaration(s)?;
63-
}
64-
GlobalStatement::SubImplementation(s) => {
65-
self.on_sub_implementation(s)?;
66-
}
67-
GlobalStatement::UserDefinedType(user_defined_type) => {
68-
self.on_user_defined_type(user_defined_type, *pos)?;
48+
fn on_parameters(&self, parameters: &Parameters) -> Result<ResolvedParamTypes, LintErrorPos> {
49+
parameters
50+
.iter()
51+
.map(|p| self.on_parameter_pos(p))
52+
.collect()
53+
}
54+
55+
fn on_parameter_pos(
56+
&self,
57+
parameter_pos: &ParameterPos,
58+
) -> Result<ResolvedParamType, LintErrorPos> {
59+
self.on_parameter(&parameter_pos.element)
60+
.with_err_at(parameter_pos)
61+
}
62+
63+
fn on_parameter(&self, parameter: &Parameter) -> Result<ResolvedParamType, LintError> {
64+
self.resolve_param_type(&parameter.bare_name, &parameter.var_type)
65+
}
66+
67+
fn resolve_param_type(
68+
&self,
69+
bare_name: &BareName,
70+
param_type: &ParamType,
71+
) -> Result<ResolvedParamType, LintError> {
72+
match param_type {
73+
ParamType::Bare => {
74+
let q = bare_name.qualify(&self.resolver);
75+
Ok(ResolvedParamType::BuiltIn(q, BuiltInStyle::Compact))
76+
}
77+
ParamType::BuiltIn(q, built_in_style) => {
78+
Ok(ResolvedParamType::BuiltIn(*q, *built_in_style))
79+
}
80+
ParamType::UserDefined(u) => {
81+
let type_name: &BareName = &u.element;
82+
if self.user_defined_types.contains_key(type_name) {
83+
Ok(ResolvedParamType::UserDefined(type_name.clone()))
84+
} else {
85+
Err(LintError::TypeNotDefined)
6986
}
7087
}
88+
ParamType::Array(element_type) => {
89+
let element_param_type =
90+
self.resolve_param_type(bare_name, element_type.as_ref())?;
91+
Ok(ResolvedParamType::Array(Box::new(element_param_type)))
92+
}
7193
}
72-
Ok(())
7394
}
95+
}
96+
97+
impl PosVisitor for MainContext {
98+
fn set_pos(&mut self, pos: Position) {
99+
self.declaration_pos = pos;
100+
}
101+
}
74102

75-
fn on_def_type(&mut self, def_type: &DefType) {
103+
impl Visitor<DefType> for MainContext {
104+
fn visit(&mut self, def_type: &DefType) -> VisitResult {
76105
self.resolver.set(def_type);
106+
Ok(())
77107
}
108+
}
78109

79-
fn on_function_declaration(&mut self, f: &FunctionDeclaration) -> Result<(), LintErrorPos> {
110+
impl Visitor<FunctionDeclaration> for MainContext {
111+
fn visit(&mut self, f: &FunctionDeclaration) -> VisitResult {
80112
let FunctionDeclaration {
81113
name,
82114
parameters: params,
@@ -88,11 +120,10 @@ impl MainContext {
88120
.add_declaration(bare_name, signature, self.declaration_pos)
89121
.with_err_at(name)
90122
}
123+
}
91124

92-
fn on_function_implementation(
93-
&mut self,
94-
f: &FunctionImplementation,
95-
) -> Result<(), LintErrorPos> {
125+
impl Visitor<FunctionImplementation> for MainContext {
126+
fn visit(&mut self, f: &FunctionImplementation) -> VisitResult {
96127
let FunctionImplementation { name, params, .. } = f;
97128
let param_types: ResolvedParamTypes = self.on_parameters(params)?;
98129
let bare_name = name.element.bare_name();
@@ -101,15 +132,10 @@ impl MainContext {
101132
.add_implementation(bare_name, signature, self.declaration_pos)
102133
.with_err_at(name)
103134
}
135+
}
104136

105-
fn on_statement(&mut self, s: &Statement) -> Result<(), LintErrorPos> {
106-
match s {
107-
Statement::Const(name, expr) => self.on_const(name, expr),
108-
_ => Ok(()),
109-
}
110-
}
111-
112-
fn on_sub_declaration(&mut self, s: &SubDeclaration) -> Result<(), LintErrorPos> {
137+
impl Visitor<SubDeclaration> for MainContext {
138+
fn visit(&mut self, s: &SubDeclaration) -> VisitResult {
113139
let SubDeclaration {
114140
name,
115141
parameters: params,
@@ -121,8 +147,10 @@ impl MainContext {
121147
.add_declaration(bare_name, signature, self.declaration_pos)
122148
.with_err_at(name)
123149
}
150+
}
124151

125-
fn on_sub_implementation(&mut self, s: &SubImplementation) -> Result<(), LintErrorPos> {
152+
impl Visitor<SubImplementation> for MainContext {
153+
fn visit(&mut self, s: &SubImplementation) -> VisitResult {
126154
let SubImplementation { name, params, .. } = s;
127155
let param_types: ResolvedParamTypes = self.on_parameters(params)?;
128156
let bare_name = &name.element;
@@ -131,69 +159,24 @@ impl MainContext {
131159
.add_implementation(bare_name, signature, self.declaration_pos)
132160
.with_err_at(name)
133161
}
162+
}
134163

135-
fn on_user_defined_type(
136-
&mut self,
137-
user_defined_type: &UserDefinedType,
138-
pos: Position,
139-
) -> Result<(), LintErrorPos> {
164+
impl Visitor<Statement> for MainContext {
165+
fn visit(&mut self, s: &Statement) -> VisitResult {
166+
match s {
167+
Statement::Const(name, expr) => global_const(&mut self.global_constants, name, expr),
168+
_ => Ok(()),
169+
}
170+
}
171+
}
172+
173+
impl Visitor<UserDefinedType> for MainContext {
174+
fn visit(&mut self, user_defined_type: &UserDefinedType) -> VisitResult {
140175
super::user_defined_type_rules::user_defined_type(
141176
&mut self.user_defined_types,
142177
&self.global_constants,
143178
user_defined_type,
144-
pos,
179+
self.declaration_pos,
145180
)
146181
}
147-
148-
fn on_const(&mut self, name: &NamePos, expr: &ExpressionPos) -> Result<(), LintErrorPos> {
149-
global_const(&mut self.global_constants, name, expr)
150-
}
151-
152-
fn on_parameters(&self, parameters: &Parameters) -> Result<ResolvedParamTypes, LintErrorPos> {
153-
parameters
154-
.iter()
155-
.map(|p| self.on_parameter_pos(p))
156-
.collect()
157-
}
158-
159-
fn on_parameter_pos(
160-
&self,
161-
parameter_pos: &ParameterPos,
162-
) -> Result<ResolvedParamType, LintErrorPos> {
163-
self.on_parameter(&parameter_pos.element)
164-
.with_err_at(parameter_pos)
165-
}
166-
167-
fn on_parameter(&self, parameter: &Parameter) -> Result<ResolvedParamType, LintError> {
168-
self.resolve_param_type(&parameter.bare_name, &parameter.var_type)
169-
}
170-
171-
fn resolve_param_type(
172-
&self,
173-
bare_name: &BareName,
174-
param_type: &ParamType,
175-
) -> Result<ResolvedParamType, LintError> {
176-
match param_type {
177-
ParamType::Bare => {
178-
let q = bare_name.qualify(&self.resolver);
179-
Ok(ResolvedParamType::BuiltIn(q, BuiltInStyle::Compact))
180-
}
181-
ParamType::BuiltIn(q, built_in_style) => {
182-
Ok(ResolvedParamType::BuiltIn(*q, *built_in_style))
183-
}
184-
ParamType::UserDefined(u) => {
185-
let type_name: &BareName = &u.element;
186-
if self.user_defined_types.contains_key(type_name) {
187-
Ok(ResolvedParamType::UserDefined(type_name.clone()))
188-
} else {
189-
Err(LintError::TypeNotDefined)
190-
}
191-
}
192-
ParamType::Array(element_type) => {
193-
let element_param_type =
194-
self.resolve_param_type(bare_name, element_type.as_ref())?;
195-
Ok(ResolvedParamType::Array(Box::new(element_param_type)))
196-
}
197-
}
198-
}
199182
}

0 commit comments

Comments
 (0)