Skip to content

Commit 716e07f

Browse files
authored
Add pointer declaration spacing rule (SP.ptrdecl) (#20)
* Add pointer declaration spacing rules * Remove NspPtrDecl disable
1 parent 4cc5936 commit 716e07f

File tree

8 files changed

+313
-8
lines changed

8 files changed

+313
-8
lines changed

src/analysis/parsing/misc.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::lint::rules::spacing::{NspPtrDeclArgs, SpPtrDeclArgs};
2+
use crate::lint::{rules::CurrentRules, AuxParams, DMLStyleError};
13
// © 2024 Intel Corporation
24
// SPDX-License-Identifier: Apache-2.0 and MIT
35
use crate::span::Range;
@@ -591,6 +593,10 @@ impl TreeElement for CDeclContent {
591593
create_subs!(&self.consttok, &self.base,
592594
&self.modifiers, &self.decl)
593595
}
596+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
597+
rules.sp_ptrdecl.check(acc, SpPtrDeclArgs::from_cdecl(self));
598+
rules.nsp_ptrdecl.check(acc, NspPtrDeclArgs::from_cdecl(self));
599+
}
594600
}
595601

596602
// corresponds to cdecl in grammar

src/analysis/parsing/structure.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +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::spacing::{SpBracesArgs,
20-
NspInparenArgs,
21-
NspFunparArgs,
22-
SpPunctArgs};
19+
use crate::lint::rules::spacing::{NspFunparArgs, NspInparenArgs, SpBracesArgs, SpPunctArgs};
2320
use crate::lint::rules::indentation::{IndentCodeBlockArgs, IndentClosingBraceArgs, IndentParenExprArgs};
2421
use crate::lint::{rules::CurrentRules, AuxParams, DMLStyleError};
2522
use crate::analysis::reference::{Reference, ReferenceKind};

src/lint/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::fmt;
22
use std::fs;
33
use std::path::{Path, PathBuf};
44
use log::{debug, error, trace};
5+
use rules::spacing::{SpPtrDeclOptions, NspPtrDeclOptions};
56
use serde::{Deserialize, Serialize};
67
use rules::{instantiate_rules, CurrentRules, RuleType};
78
use rules::{spacing::{SpBraceOptions, SpPunctOptions, NspFunparOptions,
@@ -50,6 +51,10 @@ pub struct LintCfg {
5051
#[serde(default)]
5152
pub sp_punct: Option<SpPunctOptions>,
5253
#[serde(default)]
54+
pub sp_ptrdecl: Option<SpPtrDeclOptions>,
55+
#[serde(default)]
56+
pub nsp_ptrdecl: Option<NspPtrDeclOptions>,
57+
#[serde(default)]
5358
pub nsp_funpar: Option<NspFunparOptions>,
5459
#[serde(default)]
5560
pub nsp_inparen: Option<NspInparenOptions>,
@@ -80,6 +85,8 @@ impl Default for LintCfg {
8085
LintCfg {
8186
sp_brace: Some(SpBraceOptions{}),
8287
sp_punct: Some(SpPunctOptions{}),
88+
sp_ptrdecl: Some(SpPtrDeclOptions{}),
89+
nsp_ptrdecl: Some(NspPtrDeclOptions{}),
8390
nsp_funpar: Some(NspFunparOptions{}),
8491
nsp_inparen: Some(NspInparenOptions{}),
8592
nsp_unary: Some(NspUnaryOptions{}),

src/lint/rules/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ pub mod indentation;
44
#[cfg(test)]
55
pub mod tests;
66

7-
use spacing::{SpBracesRule,
8-
SpPunctRule, NspFunparRule, NspInparenRule,
9-
NspUnaryRule, NspTrailingRule};
7+
use spacing::{NspFunparRule, NspInparenRule, NspTrailingRule, NspUnaryRule, SpBracesRule, SpPtrDeclRule, NspPtrDeclRule, SpPunctRule};
108
use indentation::{LongLinesRule, IndentNoTabRule, IndentCodeBlockRule, IndentClosingBraceRule, IndentParenExprRule, IndentSwitchCaseRule, IndentEmptyLoopRule};
119
use crate::lint::{LintCfg, DMLStyleError};
1210
use crate::analysis::{LocalDMLError, parsing::tree::ZeroRange};
1311

1412
pub struct CurrentRules {
1513
pub sp_brace: SpBracesRule,
1614
pub sp_punct: SpPunctRule,
15+
pub sp_ptrdecl: SpPtrDeclRule,
16+
pub nsp_ptrdecl: NspPtrDeclRule,
1717
pub nsp_funpar: NspFunparRule,
1818
pub nsp_inparen: NspInparenRule,
1919
pub nsp_unary: NspUnaryRule,
@@ -31,6 +31,8 @@ pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
3131
CurrentRules {
3232
sp_brace: SpBracesRule { enabled: cfg.sp_brace.is_some() },
3333
sp_punct: SpPunctRule { enabled: cfg.sp_punct.is_some() },
34+
sp_ptrdecl: SpPtrDeclRule { enabled: cfg.sp_ptrdecl.is_some() },
35+
nsp_ptrdecl: NspPtrDeclRule { enabled: cfg.nsp_ptrdecl.is_some() },
3436
nsp_funpar: NspFunparRule { enabled: cfg.nsp_funpar.is_some() },
3537
nsp_inparen: NspInparenRule { enabled: cfg.nsp_inparen.is_some() },
3638
nsp_unary: NspUnaryRule { enabled: cfg.nsp_unary.is_some() },
@@ -65,6 +67,8 @@ pub trait Rule {
6567
pub enum RuleType {
6668
SpBraces,
6769
SpPunct,
70+
SpPtrDecl,
71+
NspPtrDecl,
6872
NspFunpar,
6973
NspInparen,
7074
NspUnary,

src/lint/rules/spacing.rs

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
use itertools::izip;
22
use std::convert::TryInto;
33
use serde::{Deserialize, Serialize};
4+
use crate::analysis::parsing::lexer::TokenKind;
5+
use crate::analysis::parsing::misc::CDeclContent;
46
use crate::analysis::parsing::types::{BitfieldsContent, LayoutContent,
57
StructTypeContent};
68
use crate::lint::{rules::{Rule, RuleType},
79
DMLStyleError};
8-
use crate::analysis::parsing::tree::{TreeElement, ZeroRange};
10+
use crate::analysis::parsing::tree::{LeafToken, TreeElement, ZeroRange};
911
use crate::analysis::parsing::expression::{FunctionCallContent, IndexContent,
1012
PostUnaryExpressionContent,
1113
UnaryExpressionContent};
@@ -501,3 +503,132 @@ impl Rule for NspTrailingRule {
501503
RuleType::NspTrailing
502504
}
503505
}
506+
pub struct SpPtrDeclRule {
507+
pub enabled: bool,
508+
}
509+
510+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
511+
pub struct SpPtrDeclOptions {}
512+
513+
impl Rule for SpPtrDeclRule {
514+
fn name() -> &'static str {
515+
"SP_PTRDECL"
516+
}
517+
fn description() -> &'static str {
518+
"There should be a space between type and * marking a pointer"
519+
}
520+
fn get_rule_type() -> RuleType {
521+
RuleType::SpPtrDecl
522+
}
523+
}
524+
525+
fn has_space_between(range_left: &ZeroRange,
526+
range_right: &ZeroRange) -> bool {
527+
return !((range_left.row_end == range_right.row_start)
528+
&& (range_left.col_end == range_right.col_start))
529+
}
530+
pub struct SpPtrDeclArgs {
531+
type_name_range: ZeroRange,
532+
operator_ranges: Vec<ZeroRange>
533+
}
534+
535+
fn extract_operator_ranges_from_cdecl(node: &CDeclContent) -> Vec<ZeroRange> {
536+
node.modifiers.iter()
537+
.filter_map(|m| {
538+
match m {
539+
LeafToken::Actual(token) => {
540+
match token.kind {
541+
TokenKind::Multiply => Some(m.range()),
542+
_ => None
543+
}
544+
}
545+
LeafToken::Missing(_) => None
546+
}
547+
}).collect()
548+
}
549+
550+
impl SpPtrDeclArgs {
551+
pub fn from_cdecl(node: &CDeclContent) -> Option<SpPtrDeclArgs> {
552+
// Check if node has a multiply token inside its modifiers
553+
let operator_ranges: Vec<ZeroRange> = extract_operator_ranges_from_cdecl(node);
554+
Some(SpPtrDeclArgs {
555+
type_name_range: node.base.range(),
556+
operator_ranges: operator_ranges,
557+
})
558+
}
559+
}
560+
561+
impl SpPtrDeclRule {
562+
pub fn check(&self, acc: &mut Vec<DMLStyleError>,
563+
ranges: Option<SpPtrDeclArgs>) {
564+
if !self.enabled { return; }
565+
match ranges {
566+
None => return,
567+
Some(ranges) => {
568+
if ranges.operator_ranges.iter().any(|op_range| {
569+
!has_space_between(&ranges.type_name_range, op_range)
570+
}) {
571+
self.push_err(acc, ranges.type_name_range);
572+
}
573+
}
574+
}
575+
576+
}
577+
}
578+
579+
pub struct NspPtrDeclRule {
580+
pub enabled: bool,
581+
}
582+
583+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
584+
pub struct NspPtrDeclOptions {}
585+
586+
pub struct NspPtrDeclArgs {
587+
rightmost_multiply: Option<ZeroRange>,
588+
identifier_range: ZeroRange
589+
}
590+
591+
impl NspPtrDeclArgs {
592+
pub fn from_cdecl(node: &CDeclContent) -> Option<NspPtrDeclArgs> {
593+
// Check if node has a multiply token inside its modifiers
594+
let operator_ranges: Vec<ZeroRange> = extract_operator_ranges_from_cdecl(node);
595+
let rightmost_multiply: Option<ZeroRange> = operator_ranges.last().cloned();
596+
Some(NspPtrDeclArgs {
597+
rightmost_multiply: rightmost_multiply,
598+
identifier_range: node.decl.range()
599+
})
600+
}
601+
}
602+
603+
impl Rule for NspPtrDeclRule {
604+
fn name() -> &'static str {
605+
"NSP_PTRDECL"
606+
}
607+
fn description() -> &'static str {
608+
"There should be no space after the * marking a pointer in a declaration"
609+
}
610+
fn get_rule_type() -> RuleType {
611+
RuleType::NspPtrDecl
612+
}
613+
}
614+
615+
impl NspPtrDeclRule {
616+
pub fn check(&self, acc: &mut Vec<DMLStyleError>,
617+
ranges: Option<NspPtrDeclArgs>) {
618+
if !self.enabled { return; }
619+
match ranges {
620+
None => return,
621+
Some(ranges) => {
622+
match ranges.rightmost_multiply{
623+
None => return,
624+
Some(op_range) => {
625+
if has_space_between(&op_range, &ranges.identifier_range) {
626+
self.push_err(acc, ranges.identifier_range);
627+
}
628+
}
629+
}
630+
}
631+
}
632+
633+
}
634+
}

src/lint/rules/tests/spacing/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
use crate::lint::rules::tests::common::assert_snippet;
2+
use crate::lint::rules::instantiate_rules;
3+
use crate::lint::LintCfg;
14
mod nsp_funpar;
25
mod nsp_inparen;
6+
mod nsp_ptrdecl;
37
mod nsp_trailing;
48
mod nsp_unary;
59
mod sp_braces;
10+
mod sp_ptrdecl;
611
mod sp_punct;
712

813
// Put whitespace (space or newline):
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use crate::lint::rules::tests::common::{set_up, assert_snippet};
2+
use crate::lint::rules::RuleType;
3+
4+
#[allow(dead_code)]
5+
static NSP_PTRDECL_CORRECT: &str = "
6+
method this_is_some_method(conf_object_t *dummy_obj) {
7+
if(!dummy_obj) {
8+
return;
9+
}
10+
}";
11+
12+
#[allow(dead_code)]
13+
static NSP_PTRDECL_INCORRECT_PARAM: &str = "
14+
method this_is_some_method(conf_object_t * dummy_obj) {
15+
if(!dummy_obj) {
16+
return;
17+
}
18+
}";
19+
20+
#[allow(dead_code)]
21+
static NSP_PTRDECL_INCORRECT_STATEMENT: &str = "
22+
method this_is_some_method(conf_object_t *dummy_obj) {
23+
local conf_object_t * conf = dummy_obj;
24+
if(!conf) {
25+
return;
26+
}
27+
}";
28+
29+
#[allow(dead_code)]
30+
static NSP_PTRDECL_MULTIPLE_POINTER_SYMBOLS: &str = "
31+
method this_is_some_method(conf_object_t **dummy_obj) {
32+
local conf_object_t ** conf = dummy_obj;
33+
if(!conf) {
34+
return;
35+
}
36+
}";
37+
38+
#[test]
39+
fn nsp_ptrdecl_correct() {
40+
let mut rules = set_up();
41+
assert_snippet(NSP_PTRDECL_CORRECT, vec![], &rules);
42+
// Test rule disable
43+
rules.nsp_ptrdecl.enabled = false;
44+
assert_snippet(NSP_PTRDECL_CORRECT, vec![], &rules);
45+
}
46+
47+
#[test]
48+
fn nsp_ptrdcl_incorrect_param() {
49+
let mut rules = set_up();
50+
let expected_errors = define_expected_errors!(
51+
RuleType::SpPtrDecl,
52+
(1, 1, 43, 52),
53+
);
54+
assert_snippet(NSP_PTRDECL_INCORRECT_PARAM, expected_errors, &rules);
55+
// Test rule disable
56+
rules.nsp_ptrdecl.enabled = false;
57+
assert_snippet(NSP_PTRDECL_INCORRECT_PARAM, vec![], &rules);
58+
}
59+
#[test]
60+
fn nsp_ptrdecl_incorrect_statement() {
61+
let mut rules = set_up();
62+
let expected_errors = define_expected_errors!(
63+
RuleType::NspPtrDecl,
64+
(2, 2, 26, 30),
65+
);
66+
assert_snippet(NSP_PTRDECL_INCORRECT_STATEMENT, expected_errors, &rules);
67+
// Test rule disable
68+
rules.nsp_ptrdecl.enabled = false;
69+
assert_snippet(NSP_PTRDECL_INCORRECT_STATEMENT, vec![], &rules);
70+
}
71+
72+
#[test]
73+
fn nsp_ptrdecl_multiple_symbols() {
74+
let mut rules = set_up();
75+
let expected_errors = define_expected_errors!(
76+
RuleType::NspPtrDecl,
77+
(2, 2, 27, 31),
78+
);
79+
assert_snippet(NSP_PTRDECL_MULTIPLE_POINTER_SYMBOLS, expected_errors, &rules);
80+
// Test rule disable
81+
rules.nsp_ptrdecl.enabled = false;
82+
assert_snippet(NSP_PTRDECL_MULTIPLE_POINTER_SYMBOLS, vec![], &rules);
83+
}

0 commit comments

Comments
 (0)