Skip to content

Commit 4ed8568

Browse files
alecalvopjvsqzj
authored andcommitted
Add MethodOutputBreak (LL5) Rule (#24)
* Add MethodOutputBreak (LL5) Rule
1 parent 868fb9d commit 4ed8568

File tree

8 files changed

+133
-4
lines changed

8 files changed

+133
-4
lines changed

example_files/example_lint_cfg.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020
"indent_empty_loop": {},
2121
"indent_continuation_line": {},
2222
"func_call_break_on_open_paren": {},
23+
"method_output_break": {},
2324
"annotate_lints": true
2425
}

src/analysis/parsing/structure.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::analysis::parsing::parser::{doesnt_understand_tokens,
1616
FileParser, Parse, ParseContext,
1717
FileInfo};
1818
use crate::analysis::LocalDMLError;
19-
use crate::lint::rules::linebreaking::FuncCallBreakOnOpenParenArgs;
19+
use crate::lint::rules::linebreaking::{FuncCallBreakOnOpenParenArgs, MethodOutputBreakArgs};
2020
use crate::lint::rules::spacing::{SpBracesArgs,
2121
NspInparenArgs,
2222
NspFunparArgs,
@@ -245,6 +245,7 @@ impl TreeElement for MethodContent {
245245
rules.sp_punct.check(SpPunctArgs::from_method(self), acc);
246246
rules.indent_paren_expr.check(IndentParenExprArgs::from_method(self), acc);
247247
rules.func_call_break_on_open_paren.check(FuncCallBreakOnOpenParenArgs::from_method(self, aux.depth), acc);
248+
rules.method_output_break.check(MethodOutputBreakArgs::from_method(self), acc);
248249
}
249250
}
250251

src/lint/features.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,12 @@ Below are listed the currently supported rules for linting:
4747

4848
## Line Length
4949
- **LL1**, `long_lines`: Lines should be kept shorter than 80 characters. This limit can be set to a custom value
50+
- **LL5**, `method_output_break`: Break long method declarations with output parameters before the arrow.
51+
```
52+
method inquiry_status(uint64 physical_address)
53+
-> (uint16 status) {
54+
...
55+
}
56+
```
5057

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

src/lint/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
55
use std::str::FromStr;
66
use lazy_static::lazy_static;
77
use log::{debug, error, trace};
8-
use rules::linebreaking::FuncCallBreakOnOpenParenOptions;
8+
use rules::linebreaking::{FuncCallBreakOnOpenParenOptions, MethodOutputBreakOptions};
99
use serde::{Deserialize, Serialize};
1010
use regex::Regex;
1111
use rules::{instantiate_rules, CurrentRules, RuleType};
@@ -116,6 +116,8 @@ pub struct LintCfg {
116116
pub indent_continuation_line: Option<IndentContinuationLineOptions>,
117117
#[serde(default)]
118118
pub func_call_break_on_open_paren: Option<FuncCallBreakOnOpenParenOptions>,
119+
#[serde(default)]
120+
pub method_output_break: Option<MethodOutputBreakOptions>,
119121
#[serde(default = "get_true")]
120122
pub annotate_lints: bool,
121123
}
@@ -163,6 +165,7 @@ impl Default for LintCfg {
163165
indent_empty_loop: Some(IndentEmptyLoopOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
164166
indent_continuation_line: Some(IndentContinuationLineOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
165167
func_call_break_on_open_paren: Some(FuncCallBreakOnOpenParenOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
168+
method_output_break: Some(MethodOutputBreakOptions{}),
166169
annotate_lints: true,
167170
}
168171
}

src/lint/rules/linebreaking.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,58 @@ fn default_indentation_spaces() -> u32 {
1414
INDENTATION_LEVEL_DEFAULT
1515
}
1616

17+
pub struct MethodOutputBreakRule {
18+
pub enabled: bool
19+
}
20+
21+
pub struct MethodOutputBreakArgs {
22+
pub before_arrow_range: ZeroRange,
23+
pub arrow_range: ZeroRange,
24+
pub after_arrow_range: ZeroRange,
25+
}
26+
27+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
28+
pub struct MethodOutputBreakOptions{
29+
}
30+
31+
impl Rule for MethodOutputBreakRule {
32+
fn name() -> &'static str {
33+
"method_output_break"
34+
}
35+
fn description() -> &'static str {
36+
"Break long method declarations with output parameters before the arrow."
37+
}
38+
fn get_rule_type() -> RuleType {
39+
RuleType::LL5
40+
}
41+
}
42+
43+
impl MethodOutputBreakArgs {
44+
pub fn from_method(node: &MethodContent) -> Option<MethodOutputBreakArgs> {
45+
let Some(returns) = &node.returns else { return None; };
46+
Some(MethodOutputBreakArgs {
47+
before_arrow_range: node.rparen.range(),
48+
arrow_range: returns.0.range(),
49+
after_arrow_range: returns.1.range(),
50+
})
51+
}
52+
}
53+
54+
impl MethodOutputBreakRule {
55+
pub fn check(&self, args: Option<MethodOutputBreakArgs>, acc: &mut Vec<DMLStyleError>) {
56+
if !self.enabled { return; }
57+
let Some(args) = args else { return; };
58+
if args.before_arrow_range.row_end.0 == args.after_arrow_range.row_start.0 {
59+
// If all parts are on the same line, we don't need to check it.
60+
return;
61+
}
62+
// If the arrow and the return type are not on the same line, report an error.
63+
if args.arrow_range.row_start.0 != args.after_arrow_range.row_start.0 {
64+
acc.push(self.create_err(args.arrow_range));
65+
}
66+
}
67+
}
68+
1769
pub struct FuncCallBreakOnOpenParenRule {
1870
pub enabled: bool,
1971
indentation_spaces: u32

src/lint/rules/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use indentation::{LongLinesRule,
2424
IndentSwitchCaseRule,
2525
IndentEmptyLoopRule,
2626
IndentContinuationLineRule};
27-
use linebreaking::FuncCallBreakOnOpenParenRule;
27+
use linebreaking::{FuncCallBreakOnOpenParenRule,
28+
MethodOutputBreakRule};
2829
use crate::lint::{LintCfg, DMLStyleError};
2930
use crate::analysis::{LocalDMLError, parsing::tree::ZeroRange};
3031

@@ -49,6 +50,7 @@ pub struct CurrentRules {
4950
pub indent_empty_loop: IndentEmptyLoopRule,
5051
pub indent_continuation_line: IndentContinuationLineRule,
5152
pub func_call_break_on_open_paren: FuncCallBreakOnOpenParenRule,
53+
pub method_output_break: MethodOutputBreakRule,
5254
}
5355

5456
pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
@@ -73,6 +75,7 @@ pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
7375
indent_empty_loop: IndentEmptyLoopRule::from_options(&cfg.indent_empty_loop),
7476
indent_continuation_line: IndentContinuationLineRule::from_options(&cfg.indent_continuation_line),
7577
func_call_break_on_open_paren: FuncCallBreakOnOpenParenRule::from_options(&cfg.func_call_break_on_open_paren),
78+
method_output_break: MethodOutputBreakRule { enabled: cfg.method_output_break.is_some() },
7679
}
7780
}
7881

@@ -107,6 +110,7 @@ pub enum RuleType {
107110
NspUnary,
108111
NspTrailing,
109112
LL1,
113+
LL5,
110114
LL6,
111115
IN2,
112116
IN3,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use crate::lint::rules::tests::common::{set_up, assert_snippet};
2+
use crate::lint::rules::RuleType;
3+
4+
// LL5: Break long method declarations with output parameters before the arrow.
5+
6+
static METHOD_OUTPUT_BREAK_CORRECT: &str = "
7+
method inquiry_status(uint64 physical_address)
8+
-> (uint16 status) {
9+
return 0;
10+
}
11+
12+
method inquiry_status(uint64 physical_address)
13+
-> (uint16 status) {
14+
return 0;
15+
}
16+
17+
method inquiry_status(uint64 physical_address) -> (uint16 status) {
18+
return 0;
19+
}
20+
21+
method other_method(uint64 arg1,
22+
uint64 arg2)
23+
-> (uint16 status) {
24+
return 0;
25+
}
26+
";
27+
#[test]
28+
fn method_output_break_correct() {
29+
let rules = set_up();
30+
assert_snippet(METHOD_OUTPUT_BREAK_CORRECT, vec![], &rules);
31+
}
32+
33+
static METHOD_OUTPUT_BREAK_INCORRECT: &str = "
34+
method inquiry_status(uint64 physical_address) ->
35+
(uint16 status) {
36+
return 0;
37+
}
38+
39+
method inquiry_status(uint64 physical_address) ->
40+
(uint16 status) {
41+
return 0;
42+
}
43+
44+
method other_method(uint64 arg1,
45+
uint64 arg2) ->
46+
(uint16 status) {
47+
return 0;
48+
}
49+
";
50+
#[test]
51+
fn method_output_break_incorrect() {
52+
let rules = set_up();
53+
let expected_errors = define_expected_errors!(
54+
RuleType::LL5,
55+
(1, 1, 47, 49),
56+
(6, 6, 47, 49),
57+
(12, 12, 33, 35),
58+
);
59+
assert_snippet(METHOD_OUTPUT_BREAK_INCORRECT, expected_errors, &rules);
60+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
mod func_call_break_open_paren;
1+
mod func_call_break_open_paren;
2+
mod method_output_break;

0 commit comments

Comments
 (0)