Skip to content

Commit a2bc1f5

Browse files
authored
Merge pull request #109 from kevv87/feature/73-line-breaking
Implement line length and breaking rules
2 parents 4ffa670 + 4a12a53 commit a2bc1f5

20 files changed

+1255
-78
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
# Change Log
66

77
# 0.9.15
8-
8+
- Added support for line length and breaking rules regarding line-breaks after opening parentheses, method output arguments, conditional expressions and binary operands.
9+
- Added support for indendation rule indent_continuation_line.
910

1011
## 0.9.14
1112
- Slight optimization to the memory usage of device-level analysis which

example_files/example_lint_cfg.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@
1818
"indent_paren_expr": {},
1919
"indent_switch_case": {},
2020
"indent_empty_loop": {},
21+
"indent_continuation_line": {},
22+
"break_func_call_open_paren": {},
23+
"break_method_output": {},
24+
"break_conditional_expression": {},
25+
"break_before_binary_op": {},
2126
"annotate_lints": true
2227
}

src/analysis/parsing/expression.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use crate::lint::{DMLStyleError,
2626
SpPunctArgs},
2727
CurrentRules},
2828
AuxParams};
29-
use crate::lint::rules::indentation::{IndentParenExprArgs};
29+
use crate::lint::rules::indentation::IndentParenExprArgs;
30+
use crate::lint::rules::linelength::{BreakBeforeBinaryOpArgs,
31+
BreakConditionalExpression,
32+
BreakFuncCallOpenParenArgs};
3033

3134
#[derive(Debug, Clone, PartialEq)]
3235
pub struct UnaryExpressionContent {
@@ -96,6 +99,7 @@ impl TreeElement for BinaryExpressionContent {
9699
}
97100
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
98101
rules.sp_binop.check(SpBinopArgs::from_binary_expression_content(self), acc);
102+
rules.break_before_binary_op.check(BreakBeforeBinaryOpArgs::from_binary_expression(self), acc);
99103
}
100104
}
101105

@@ -158,6 +162,8 @@ impl TreeElement for TertiaryExpressionContent {
158162
}
159163
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
160164
rules.sp_ternary.check(SpTernaryArgs::from_tertiary_expression_content(self), acc);
165+
rules.break_conditional_expression
166+
.check(BreakConditionalExpression::from_tertiary_expression(self), acc);
161167
}
162168
}
163169

@@ -175,8 +181,10 @@ impl TreeElement for ParenExpressionContent {
175181
fn subs(&self) -> TreeElements<'_> {
176182
create_subs!(&self.lparen, &self.expr, &self.rparen)
177183
}
178-
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
184+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
179185
rules.indent_paren_expr.check(IndentParenExprArgs::from_paren_expression(self), acc);
186+
rules.break_func_call_open_paren.check(
187+
BreakFuncCallOpenParenArgs::from_paren_expression(self, aux.depth), acc);
180188
}
181189
}
182190

@@ -222,11 +230,13 @@ impl TreeElement for FunctionCallContent {
222230
noderef, ReferenceKind::Callable));
223231
}
224232
}
225-
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
233+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
226234
rules.nsp_funpar.check(NspFunparArgs::from_function_call(self), acc);
227235
rules.nsp_inparen.check(NspInparenArgs::from_function_call(self), acc);
228236
rules.sp_punct.check(SpPunctArgs::from_function_call(self), acc);
229237
rules.indent_paren_expr.check(IndentParenExprArgs::from_function_call(self), acc);
238+
rules.break_func_call_open_paren
239+
.check(BreakFuncCallOpenParenArgs::from_function_call(self, aux.depth), acc);
230240
}
231241
}
232242

@@ -340,8 +350,10 @@ impl TreeElement for CastContent {
340350
create_subs!(&self.cast, &self.lparen, &self.from,
341351
&self.comma, &self.to, &self.rparen)
342352
}
343-
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
353+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
344354
rules.indent_paren_expr.check(IndentParenExprArgs::from_cast(self), acc);
355+
rules.break_func_call_open_paren
356+
.check(BreakFuncCallOpenParenArgs::from_cast(self, aux.depth), acc);
345357
}
346358
}
347359

src/analysis/parsing/statement.rs

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

5-
use crate::lint::rules::indentation::IndentEmptyLoopArgs;
5+
use crate::lint::rules::indentation::{IndentEmptyLoopArgs,
6+
IndentContinuationLineArgs};
67
use crate::lint::rules::spacing::SpReservedArgs;
78
use crate::span::Range;
89
use crate::analysis::parsing::lexer::TokenKind;
@@ -26,7 +27,10 @@ use crate::analysis::parsing::structure::{parse_vardecl, VarDecl};
2627
use crate::analysis::LocalDMLError;
2728
use crate::lint::{DMLStyleError,
2829
rules::{CurrentRules,
29-
indentation::{IndentCodeBlockArgs, IndentClosingBraceArgs, IndentParenExprArgs, IndentSwitchCaseArgs},
30+
indentation::{IndentCodeBlockArgs,
31+
IndentClosingBraceArgs,
32+
IndentParenExprArgs,
33+
IndentSwitchCaseArgs},
3034
spacing::{NspInparenArgs,
3135
SpBracesArgs,
3236
SpPunctArgs}},
@@ -1847,6 +1851,9 @@ impl TreeElement for StatementContent {
18471851
Self::Return(content) => create_subs![content],
18481852
}
18491853
}
1854+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
1855+
rules.indent_continuation_line.check(acc, IndentContinuationLineArgs::from_statement_content(self, aux.depth));
1856+
}
18501857
}
18511858

18521859
pub type Statement = AstObject<StatementContent>;

src/analysis/parsing/structure.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ use crate::analysis::parsing::parser::{doesnt_understand_tokens,
1616
FileParser, Parse, ParseContext,
1717
FileInfo};
1818
use crate::analysis::LocalDMLError;
19-
use crate::lint::rules::spacing::{NspFunparArgs, NspInparenArgs, SpBracesArgs, SpPunctArgs};
20-
use crate::lint::rules::indentation::{IndentCodeBlockArgs, IndentClosingBraceArgs, IndentParenExprArgs};
19+
use crate::lint::rules::linelength::{BreakFuncCallOpenParenArgs, BreakMethodOutputArgs};
20+
use crate::lint::rules::spacing::{SpBracesArgs,
21+
NspInparenArgs,
22+
NspFunparArgs,
23+
SpPunctArgs};
24+
use crate::lint::rules::indentation::{IndentCodeBlockArgs,
25+
IndentClosingBraceArgs,
26+
IndentParenExprArgs,
27+
IndentContinuationLineArgs};
2128
use crate::lint::{rules::CurrentRules, AuxParams, DMLStyleError};
2229
use crate::analysis::reference::{Reference, ReferenceKind};
2330
use crate::analysis::FileSpec;
@@ -232,11 +239,13 @@ impl TreeElement for MethodContent {
232239
}
233240
errors
234241
}
235-
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
242+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
236243
rules.nsp_funpar.check(NspFunparArgs::from_method(self), acc);
237244
rules.nsp_inparen.check(NspInparenArgs::from_method(self), acc);
238245
rules.sp_punct.check(SpPunctArgs::from_method(self), acc);
239246
rules.indent_paren_expr.check(IndentParenExprArgs::from_method(self), acc);
247+
rules.break_func_call_open_paren.check(BreakFuncCallOpenParenArgs::from_method(self, aux.depth), acc);
248+
rules.break_method_output.check(BreakMethodOutputArgs::from_method(self), acc);
240249
}
241250
}
242251

@@ -1928,6 +1937,9 @@ impl TreeElement for DMLObjectContent {
19281937
Self::Template(content) => create_subs![content],
19291938
}
19301939
}
1940+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
1941+
rules.indent_continuation_line.check(acc, IndentContinuationLineArgs::from_dml_object_content(self, aux.depth));
1942+
}
19311943
}
19321944

19331945
pub type DMLObject = AstObject<DMLObjectContent>;

src/lint/features.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,24 @@ Below are listed the currently supported rules for linting:
5151

5252
## Line Length
5353
- **LL1**, `long_lines`: Lines should be kept shorter than 80 characters. This limit can be set to a custom value
54+
- **LL2**, `break_before_binary_op`: Break long lines before binary operators, not after
55+
```
56+
x = (a_very_long_expression
57+
+ another_very_long_expression)
58+
* a_third_long_expression;
59+
```
60+
- **LL3**, `break_conditional_expression`: Break conditional expressions before the ?, or both before the ? and before the :.
61+
- **LL5**, `break_method_output`: Break long method declarations with output parameters before the arrow.
62+
```
63+
method inquiry_status(uint64 physical_address)
64+
-> (uint16 status) {
65+
...
66+
}
67+
```
68+
- **LL6**, `break_func_call_open_paren`: Function and method invocations can be broken after the opening parenthesis, with the continuation lines indented one level.
69+
```
70+
signal_interface *my_interface = SIM_get_interface(
71+
other_object, SIGNAL_INTERFACE);
72+
```
5473

5574
##### Check [Issue #76 For remaining and planned checks](https://github.com/intel/dml-language-server/issues/76)

src/lint/mod.rs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,33 @@ use std::path::{Path, PathBuf};
77
use std::str::FromStr;
88
use lazy_static::lazy_static;
99
use log::{debug, error, trace};
10+
use rules::linelength::{BreakBeforeBinaryOpOptions,
11+
BreakFuncCallOpenParenOptions,
12+
BreakMethodOutputOptions,
13+
BreakConditionalExpressionOptions};
1014
use serde::{Deserialize, Serialize};
1115
use regex::Regex;
1216
use rules::{instantiate_rules, CurrentRules, RuleType};
1317
use rules::{spacing::{SpReservedOptions,
14-
SpBraceOptions,
15-
SpPunctOptions,
16-
SpBinopOptions,
17-
NspFunparOptions,
18-
SpTernaryOptions,
19-
SpPtrDeclOptions,
20-
NspPtrDeclOptions,
21-
NspInparenOptions,
22-
NspUnaryOptions,
23-
NspTrailingOptions},
24-
indentation::{LongLineOptions, IndentSizeOptions, IndentCodeBlockOptions,
25-
IndentNoTabOptions, IndentClosingBraceOptions, IndentParenExprOptions,
26-
IndentSwitchCaseOptions, IndentEmptyLoopOptions},
27-
};
18+
SpBraceOptions,
19+
SpPunctOptions,
20+
SpBinopOptions,
21+
NspFunparOptions,
22+
SpTernaryOptions,
23+
SpPtrDeclOptions,
24+
NspPtrDeclOptions,
25+
NspInparenOptions,
26+
NspUnaryOptions,
27+
NspTrailingOptions},
28+
indentation::{LongLineOptions,
29+
IndentSizeOptions,
30+
IndentCodeBlockOptions,
31+
IndentNoTabOptions,
32+
IndentClosingBraceOptions,
33+
IndentParenExprOptions,
34+
IndentSwitchCaseOptions,
35+
IndentEmptyLoopOptions,
36+
IndentContinuationLineOptions}};
2837
use crate::analysis::{DMLError, IsolatedAnalysis, LocalDMLError, ZeroRange};
2938
use crate::analysis::parsing::tree::TreeElement;
3039
use crate::file_management::CanonPath;
@@ -109,6 +118,16 @@ pub struct LintCfg {
109118
pub indent_switch_case: Option<IndentSwitchCaseOptions>,
110119
#[serde(default)]
111120
pub indent_empty_loop: Option<IndentEmptyLoopOptions>,
121+
#[serde(default)]
122+
pub indent_continuation_line: Option<IndentContinuationLineOptions>,
123+
#[serde(default)]
124+
pub break_func_call_open_paren: Option<BreakFuncCallOpenParenOptions>,
125+
#[serde(default)]
126+
pub break_conditional_expression: Option<BreakConditionalExpressionOptions>,
127+
#[serde(default)]
128+
pub break_method_output: Option<BreakMethodOutputOptions>,
129+
#[serde(default)]
130+
pub break_before_binary_op: Option<BreakBeforeBinaryOpOptions>,
112131
#[serde(default = "get_true")]
113132
pub annotate_lints: bool,
114133
}
@@ -154,6 +173,11 @@ impl Default for LintCfg {
154173
indent_paren_expr: Some(IndentParenExprOptions{}),
155174
indent_switch_case: Some(IndentSwitchCaseOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
156175
indent_empty_loop: Some(IndentEmptyLoopOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
176+
indent_continuation_line: Some(IndentContinuationLineOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
177+
break_func_call_open_paren: Some(BreakFuncCallOpenParenOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
178+
break_method_output: Some(BreakMethodOutputOptions{}),
179+
break_conditional_expression: Some(BreakConditionalExpressionOptions{}),
180+
break_before_binary_op: Some(BreakBeforeBinaryOpOptions{}),
157181
annotate_lints: true,
158182
}
159183
}
@@ -218,7 +242,7 @@ impl LinterAnalysis {
218242
}
219243
}
220244

221-
pub fn begin_style_check(ast: TopAst, file: &str, rules: &CurrentRules) -> Result<Vec<DMLStyleError>, Error> {
245+
fn begin_style_check(ast: TopAst, file: &str, rules: &CurrentRules) -> Result<Vec<DMLStyleError>, Error> {
222246
let (mut invalid_lint_annot, lint_annot) = obtain_lint_annotations(file);
223247
let mut linting_errors: Vec<DMLStyleError> = vec![];
224248
ast.style_check(&mut linting_errors, rules, AuxParams { depth: 0 });
@@ -290,8 +314,7 @@ fn obtain_lint_annotations(file: &str) -> (Vec<DMLStyleError>,
290314
last_line = row;
291315
if let Some(capture) = LINT_ANNOTATION.captures(line) {
292316
let has_pre = capture.get(1)
293-
.map_or(false,
294-
|m|!m.is_empty() &&
317+
.is_some_and(|m|!m.is_empty() &&
295318
JUST_WHITESPACE.captures(m.as_str()).is_none());
296319
let op_capture = capture.get(2).unwrap();
297320
let operation = match op_capture.as_str() {
@@ -397,7 +420,7 @@ fn remove_disabled_lints(errors: &mut Vec<DMLStyleError>,
397420
!annotations.whole_file.contains(
398421
&LintAnnotation::Allow(error.rule_type)) &&
399422
!annotations.line_specific.get(&error.error.range.row_start.0)
400-
.map_or(false, |annots|annots.contains(
423+
.is_some_and(|annots|annots.contains(
401424
&LintAnnotation::Allow(error.rule_type)))
402425
}
403426
);
@@ -564,7 +587,7 @@ pub mod tests {
564587
crate::logging::init();
565588

566589
let source =
567-
"
590+
"
568591
dml 1.4;
569592
570593
// dml-lint: allow-file=nsp_unary

0 commit comments

Comments
 (0)