Skip to content

Commit 5d00903

Browse files
authored
Merge pull request #56 from kevv87/feature/55-indentation-rules
Implement DML indentation rules tracking
2 parents 39454ee + 61aa750 commit 5d00903

File tree

24 files changed

+2453
-400
lines changed

24 files changed

+2453
-400
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# Change Log
66

77
## 0.9.10
8+
- Added indentation-style rules to the lint module with configurable indent size as specified in [example_lint_cfg.json](./example_files/example_lint_cfg.README)
89

910
## 0.9.9
1011
- Fixed an issue that could cause analysis thread crash when an object was declared both

example_files/example_lint_cfg.README

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,12 @@
1717
// "nsp_unary": {}
1818
// or assign it to null
1919
"nsp_unary": null
20+
// indentation rules can be configured by setting
21+
// "indentation_spaces" field for "indent_size" rule
22+
// to the desired integer value (defaults to 4).
23+
// all other indentation rules will use this size
24+
"indent_size": { "indentation_spaces": 4 },
25+
"indent_tabs": {},
26+
"indent_code_block": {}
27+
2028
}

example_files/example_lint_cfg.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,12 @@
55
"nsp_inparen": {},
66
"nsp_unary": {},
77
"nsp_trailing": {},
8-
"long_lines": { "max_length": 80 }
8+
"long_lines": { "max_length": 80 },
9+
"indent_size": { "indentation_spaces": 4 },
10+
"indent_no_tabs": {},
11+
"indent_code_block": {},
12+
"indent_closing_brace": {},
13+
"indent_paren_expr": {},
14+
"indent_switch_case": {},
15+
"indent_empty_loop": {}
916
}

src/analysis/parsing/expression.rs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ use crate::analysis::structure::expressions::DMLString;
1717
use crate::analysis::{DeclarationSpan, LocalDMLError};
1818

1919

20-
use crate::lint::rules::spacing::{NspFunparArgs,
21-
NspInparenArgs,
22-
NspUnaryArgs,
23-
SpPunctArgs};
24-
use crate::lint::rules::CurrentRules;
20+
use crate::lint::{DMLStyleError,
21+
rules::{spacing::{NspFunparArgs,
22+
NspInparenArgs,
23+
NspUnaryArgs,
24+
SpPunctArgs},
25+
CurrentRules},
26+
AuxParams};
27+
use crate::lint::rules::indentation::{IndentParenExprArgs};
2528

2629
#[derive(Debug, Clone, PartialEq)]
2730
pub struct UnaryExpressionContent {
@@ -36,7 +39,7 @@ impl TreeElement for UnaryExpressionContent {
3639
fn subs(&self) -> TreeElements<'_> {
3740
create_subs!(&self.operation, &self.expr)
3841
}
39-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
42+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
4043
rules.nsp_unary.check(acc, NspUnaryArgs::from_unary_expr(self));
4144
}
4245
}
@@ -70,7 +73,7 @@ impl TreeElement for PostUnaryExpressionContent {
7073
fn subs(&self) -> TreeElements<'_> {
7174
create_subs!(&self.expr, &self.operation)
7275
}
73-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
76+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
7477
rules.nsp_unary.check(acc, NspUnaryArgs::from_postunary_expr(self));
7578
}
7679
}
@@ -164,6 +167,9 @@ impl TreeElement for ParenExpressionContent {
164167
fn subs(&self) -> TreeElements<'_> {
165168
create_subs!(&self.lparen, &self.expr, &self.rparen)
166169
}
170+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
171+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_paren_expression(self));
172+
}
167173
}
168174

169175
impl Parse<ExpressionContent> for ParenExpressionContent{
@@ -208,10 +214,11 @@ impl TreeElement for FunctionCallContent {
208214
noderef, ReferenceKind::Callable));
209215
}
210216
}
211-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
217+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
212218
rules.nsp_funpar.check(acc, NspFunparArgs::from_function_call(self));
213219
rules.nsp_inparen.check(acc, NspInparenArgs::from_function_call(self));
214220
rules.sp_punct.check(acc, SpPunctArgs::from_function_call(self));
221+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_function_call(self));
215222
}
216223
}
217224

@@ -325,6 +332,9 @@ impl TreeElement for CastContent {
325332
create_subs!(&self.cast, &self.lparen, &self.from,
326333
&self.comma, &self.to, &self.rparen)
327334
}
335+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
336+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_cast(self));
337+
}
328338
}
329339

330340
impl Parse<ExpressionContent> for CastContent {
@@ -419,7 +429,7 @@ impl TreeElement for IndexContent {
419429
fn subs(&self) -> TreeElements<'_> {
420430
create_subs!(&self.array, &self.lbracket, &self.index, &self.rbracket)
421431
}
422-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
432+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
423433
rules.nsp_inparen.check(acc, NspInparenArgs::from_index(self));
424434
}
425435
}

src/analysis/parsing/statement.rs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
// SPDX-License-Identifier: Apache-2.0 and MIT
33
use log::error;
44

5+
use crate::lint::rules::indentation::IndentEmptyLoopArgs;
56
use crate::span::Range;
67
use crate::analysis::parsing::lexer::TokenKind;
8+
use crate::analysis::parsing::statement;
79
use crate::analysis::parsing::parser::{Token, doesnt_understand_tokens,
810
FileParser, Parse, ParseContext,
911
FileInfo};
@@ -21,10 +23,13 @@ use crate::analysis::parsing::misc::{Initializer, InitializerContent, CDecl,
2123
ident_filter, objident_filter};
2224
use crate::analysis::parsing::structure::{parse_vardecl, VarDecl};
2325
use crate::analysis::LocalDMLError;
24-
use crate::lint::rules::spacing::{NspInparenArgs,
25-
SpBracesArgs,
26-
SpPunctArgs};
27-
use crate::lint::rules::CurrentRules;
26+
use crate::lint::{DMLStyleError,
27+
rules::{CurrentRules,
28+
indentation::{IndentCodeBlockArgs, IndentClosingBraceArgs, IndentParenExprArgs, IndentSwitchCaseArgs},
29+
spacing::{NspInparenArgs,
30+
SpBracesArgs,
31+
SpPunctArgs}},
32+
AuxParams};
2833
use crate::vfs::TextFile;
2934

3035
fn statement_contexts(context: &ParseContext)
@@ -139,8 +144,13 @@ impl TreeElement for CompoundContent {
139144
fn subs(&self) -> TreeElements<'_> {
140145
create_subs!(&self.lbrace, &self.statements, &self.rbrace)
141146
}
142-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
147+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
143148
rules.sp_brace.check(acc, SpBracesArgs::from_compound(self));
149+
rules.indent_code_block.check(acc, IndentCodeBlockArgs::from_compound_content(self, aux.depth));
150+
rules.indent_closing_brace.check(acc, IndentClosingBraceArgs::from_compound_content(self, aux.depth));
151+
}
152+
fn should_increment_depth(&self) -> bool {
153+
true
144154
}
145155
}
146156

@@ -192,7 +202,7 @@ impl TreeElement for VariableDeclContent {
192202
fn post_parse_sanity(&self, _file: &TextFile) -> Vec<LocalDMLError> {
193203
self.decls.ensure_named()
194204
}
195-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
205+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
196206
rules.sp_punct.check(acc, SpPunctArgs::from_variable_decl(self));
197207
}
198208
}
@@ -424,8 +434,9 @@ impl TreeElement for IfContent {
424434
&self.truebranch,
425435
&self.elsebranch)
426436
}
427-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
437+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
428438
rules.nsp_inparen.check(acc, NspInparenArgs::from_if(self));
439+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_if(self));
429440
}
430441
}
431442

@@ -536,6 +547,10 @@ impl TreeElement for WhileContent {
536547
&self.rparen,
537548
&self.statement)
538549
}
550+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
551+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_while(self));
552+
rules.indent_empty_loop.check(acc, IndentEmptyLoopArgs::from_while_content(self, aux.depth));
553+
}
539554
}
540555

541556
impl Parse<StatementContent> for WhileContent {
@@ -583,6 +598,9 @@ impl TreeElement for DoContent {
583598
&self.rparen,
584599
&self.semi)
585600
}
601+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
602+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_do_while(self));
603+
}
586604
}
587605

588606
impl Parse<StatementContent> for DoContent {
@@ -844,6 +862,10 @@ impl TreeElement for ForContent {
844862
&self.rparen,
845863
&self.statement)
846864
}
865+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
866+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_for(self));
867+
rules.indent_empty_loop.check(acc, IndentEmptyLoopArgs::from_for_content(self, aux.depth));
868+
}
847869
}
848870

849871
impl Parse<StatementContent> for ForContent {
@@ -1000,6 +1022,14 @@ impl TreeElement for SwitchCase {
10001022
Self::Default(default, colon) => create_subs!(default, colon),
10011023
}
10021024
}
1025+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
1026+
rules.indent_switch_case.check(acc, IndentSwitchCaseArgs::from_switch_case(self, aux.depth));
1027+
}
1028+
fn should_increment_depth(&self) -> bool {
1029+
matches!(self, SwitchCase::Statement(statement)
1030+
if !matches!(*statement.content,
1031+
Content::Some(statement::StatementContent::Compound(_))))
1032+
}
10031033
}
10041034

10051035
fn parse_switchcase(context: &ParseContext, stream: &mut FileParser<'_>, file_info: &FileInfo)
@@ -1080,6 +1110,12 @@ impl TreeElement for SwitchContent {
10801110
&self.cases,
10811111
&self.rbrace)
10821112
}
1113+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>,
1114+
rules: &CurrentRules, aux: AuxParams)
1115+
{
1116+
rules.indent_closing_brace.check(acc, IndentClosingBraceArgs::from_switch_content(self, aux.depth));
1117+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_switch(self));
1118+
}
10831119
}
10841120

10851121
impl Parse<StatementContent> for SwitchContent {
@@ -1573,6 +1609,9 @@ impl TreeElement for ForeachContent {
15731609
&self.rparen,
15741610
&self.statement)
15751611
}
1612+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
1613+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_foreach(self));
1614+
}
15761615
}
15771616

15781617
impl Parse<StatementContent> for ForeachContent {
@@ -1709,7 +1748,7 @@ impl TreeElement for ExpressionStmtContent {
17091748
fn subs(&self) -> TreeElements<'_> {
17101749
create_subs!(&self.expression, &self.semi)
17111750
}
1712-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
1751+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
17131752
rules.sp_punct.check(acc, SpPunctArgs::from_expression_stmt(self));
17141753
}
17151754
}

src/analysis/parsing/structure.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use crate::lint::rules::spacing::{SpBracesArgs,
2020
NspInparenArgs,
2121
NspFunparArgs,
2222
SpPunctArgs};
23-
use crate::lint::rules::CurrentRules;
23+
use crate::lint::rules::indentation::{IndentCodeBlockArgs, IndentClosingBraceArgs, IndentParenExprArgs};
24+
use crate::lint::{rules::CurrentRules, AuxParams, DMLStyleError};
2425
use crate::analysis::reference::{Reference, ReferenceKind};
2526
use crate::analysis::FileSpec;
2627
use crate::span::Range;
@@ -234,10 +235,11 @@ impl TreeElement for MethodContent {
234235
}
235236
errors
236237
}
237-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
238+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
238239
rules.nsp_funpar.check(acc, NspFunparArgs::from_method(self));
239240
rules.nsp_inparen.check(acc, NspInparenArgs::from_method(self));
240241
rules.sp_punct.check(acc, SpPunctArgs::from_method(self));
242+
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_method(self));
241243
}
242244
}
243245

@@ -703,8 +705,15 @@ impl TreeElement for ObjectStatementsContent {
703705
create_subs!(left, vect, right)
704706
}
705707
}
706-
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
708+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
707709
rules.sp_brace.check(acc, SpBracesArgs::from_obj_stmts(self));
710+
rules.indent_code_block.check(acc, IndentCodeBlockArgs::from_obj_stmts_content(self, aux.depth));
711+
rules.indent_closing_brace.check(acc, IndentClosingBraceArgs::from_obj_stmts_content(self, aux.depth));
712+
}
713+
fn should_increment_depth(&self) -> bool {
714+
matches!(self, ObjectStatementsContent::List(lbrace, list, rbrace)
715+
if lbrace.range().row_start != list.range().row_start &&
716+
lbrace.range().row_start != rbrace.range().row_end)
708717
}
709718
}
710719

src/analysis/parsing/tree.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::analysis::reference::{Reference, NodeRef, MaybeIsNodeRef,
77
use crate::analysis::FileSpec;
88
use crate::analysis::structure::expressions::DMLString;
99

10-
use crate::lint::rules::CurrentRules;
11-
use crate::span::{Range, Span, ZeroIndexed, Position, FilePosition};
10+
use crate::lint::{rules::CurrentRules, AuxParams, DMLStyleError};
11+
use crate::span::{FilePosition, Position, Range, Span, ZeroIndexed};
1212
use crate::vfs::{Vfs as GenVfs, TextFile};
1313

1414
pub type ZeroRange = Range::<ZeroIndexed>;
@@ -24,6 +24,7 @@ impl <T: TreeElement + ReferenceContainer + std::fmt::Debug>
2424
TreeElementMember for T {}
2525

2626
pub type TreeElements<'t> = Vec<&'t dyn TreeElementMember>;
27+
pub type TreeElementTokenIterator = Vec<Token>;
2728
// TODO: Might be worth moving this specialization somewhere else
2829
pub type Vfs = GenVfs<()>;
2930

@@ -90,14 +91,32 @@ pub trait TreeElement {
9091
file: FileSpec<'a>) {
9192
self.default_references(accumulator, file);
9293
}
94+
// TODO: This places a hard requirement that subs()
95+
// returns the sub nodes in order, which I _think_
96+
// is true but is not currently tested
97+
fn tokens(&self) -> TreeElementTokenIterator {
98+
let mut coll = vec![];
99+
self.gather_tokens(&mut coll);
100+
coll
101+
}
102+
103+
fn gather_tokens(&self, coll: &mut TreeElementTokenIterator) {
104+
for sub in self.subs() {
105+
sub.gather_tokens(coll);
106+
}
107+
}
93108

94-
fn style_check(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules) {
95-
self.evaluate_rules(acc, rules);
109+
fn style_check(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, mut aux: AuxParams) {
110+
if self.should_increment_depth() {
111+
aux.depth += 1;
112+
}
113+
self.evaluate_rules(acc, rules, aux);
96114
for sub in self.subs() {
97-
sub.style_check(acc, rules);
115+
sub.style_check(acc, rules, aux);
98116
}
99117
}
100-
fn evaluate_rules(&self, _acc: &mut Vec<LocalDMLError>, _rules: &CurrentRules) {} // default NOOP
118+
fn should_increment_depth(&self) -> bool {false} // default don't increment
119+
fn evaluate_rules(&self, _acc: &mut Vec<DMLStyleError>, _rules: &CurrentRules, _aux: AuxParams) {} // default NOOP
101120
}
102121

103122
impl <T: ?Sized + TreeElement> ReferenceContainer for T {
@@ -257,6 +276,11 @@ impl TreeElement for LeafToken {
257276
Self::Missing(missingtok) => vec![missingtok.into()],
258277
}
259278
}
279+
fn gather_tokens(&self, coll: &mut TreeElementTokenIterator) {
280+
if let Self::Actual(t) = self {
281+
coll.push(*t)
282+
}
283+
}
260284
}
261285

262286
impl LeafToken {

0 commit comments

Comments
 (0)