Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rust-checks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.sonarsource.analyzer-commons</groupId>
<artifactId>sonar-analyzer-test-commons</artifactId>
</dependency>

<!-- test dependencies -->
<dependency>
Expand Down
18 changes: 11 additions & 7 deletions rust-checks/src/main/java/org/elegoff/rust/checks/CheckList.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,24 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.elegoff.rust.checks;

import java.util.*;

public class CheckList {
public static final String REPOSITORY_KEY = "rust";
public static final String REPOSITORY_KEY = "community-rust";

private CheckList() { }
private CheckList() {
}

public static List<Class<? extends RustCheck>> getRustChecks() {
//empty array so far, until a first rule is defined
return new ArrayList<>();
public static List<Class<?>> getRustChecks() {
return Arrays.asList(
LineLengthCheck.class,
FunctionParametersCountCheck.class,
EmptyEnumCheck.class
);
}
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Sonar Rust Plugin (Community)
* Copyright (C) 2021 Eric Le Goff
* http://github.com/elegoff/sonar-rust
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.elegoff.rust.checks;

import com.sonar.sslr.api.AstNode;
import com.sonar.sslr.api.AstNodeType;
import org.sonar.check.Rule;
import org.sonar.rust.RustGrammar;

import java.util.Collections;
import java.util.Set;

@Rule(key = "EmptyEnum")
public class EmptyEnumCheck extends RustCheck {
@Override
public Set<AstNodeType> subscribedKinds() {
return Collections.singleton(RustGrammar.ENUMERATION);
}

@Override
public void visitNode(AstNode node) {
AstNode enumItems = node.getFirstChild(RustGrammar.ENUM_ITEMS);

if (enumItems == null) {
raiseIssue(node);
}
}

private void raiseIssue(AstNode node) {
addIssue("Either remove or fill this empty enumeration.", node);
}

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Sonar Rust Plugin (Community)
* Copyright (C) 2021 Eric Le Goff
* http://github.com/elegoff/sonar-rust
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.elegoff.rust.checks;

import com.sonar.sslr.api.AstNode;
import com.sonar.sslr.api.AstNodeType;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.rust.RustGrammar;

import java.util.Collections;
import java.util.Set;

@Rule(key = "FunctionParametersCount")
public class FunctionParametersCountCheck extends RustCheck {

private static final int DEFAULT_MAXIMUM_PARAMETER_COUNT = 8;

@RuleProperty(
key = "maximumParameterCount",
description = " Maximum authorized number of parameters",
defaultValue = "" + DEFAULT_MAXIMUM_PARAMETER_COUNT)
public int maximumParameterCount = DEFAULT_MAXIMUM_PARAMETER_COUNT;

@Override
public Set<AstNodeType> subscribedKinds() {
return Collections.singleton(RustGrammar.FUNCTION);
}

@Override
public void visitNode(AstNode node) {
int numberOfParameters = getNumberOfParameters(node);

if (numberOfParameters > maximumParameterCount) {
addIssue(
"Reduce the number of parameters that this function takes from " + numberOfParameters + " to at most " + maximumParameterCount + ".",
node);
}
}

private static int getNumberOfParameters(AstNode node) {
AstNode parameterNameList = node.getFirstChild(RustGrammar.FUNCTION_PARAMETERS);

return parameterNameList == null ? 0 : parameterNameList.getChildren(RustGrammar.FUNCTION_PARAM).size();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Sonar Rust Plugin (Community)
* Copyright (C) 2021 Eric Le Goff
* http://github.com/elegoff/sonar-rust
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.elegoff.rust.checks;

import com.sonar.sslr.api.AstNode;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;

@Rule(key = "LineLength")
public class LineLengthCheck extends RustCheck {

private static final int DEFAULT_MAXIMUM_LINE_LENHGTH = 120;

@RuleProperty(
key = "maximumLineLength",
description = "The maximum authorized line length.",
defaultValue = "" + DEFAULT_MAXIMUM_LINE_LENHGTH)
public int maximumLineLength = DEFAULT_MAXIMUM_LINE_LENHGTH;

@Override
public void visitFile(AstNode astNode) {
String[] lines = getContext().file().content().split("\\r?\\n");
for (int i = 0; i < lines.length; i++) {
int length = lines[i].length();
if (length > maximumLineLength) {
addLineIssue(
"Split this " + length + " characters long line (which is greater than " + maximumLineLength + " authorized).",
i + 1);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@

import com.sonar.sslr.api.AstNode;
import com.sonar.sslr.api.Token;
import org.sonar.api.internal.google.common.collect.ImmutableList;
import org.sonar.rust.RustVisitor;
import org.sonar.rust.RustVisitorContext;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RustCheck extends RustVisitor {
Expand All @@ -34,17 +34,15 @@ public class RustCheck extends RustVisitor {
public List<Issue> scanFileForIssues(RustVisitorContext context) {
issues.clear();
scanFile(context);
return ImmutableList.copyOf(issues);
return Collections.unmodifiableList(new ArrayList<>(issues));
}

public void addIssue(String message, AstNode node) {
addIssue(message, node.getToken());
}

public void addIssue(String message, Token token) {
if (token.getURI().equals(getContext().file().uri())) {
addLineIssue(message, token.getLine());
}
addLineIssue(message, token.getLine());
}

public void addLineIssue(String message, int line) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<p>Empty enums should be avoided. Use a never_type instead.</p>
<h2>Noncompliant Code Example</h2>
<pre>
enum Foo {}
</pre>
<h2>Compliant Code Example</h2>
<pre>
#![feature(never_type)]

struct Foo(!);
</pre>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

{
"title": "Enum should not be left empty",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "5min"
},
"tags": [
"suspicious"
],
"defaultSeverity": "Major",
"sqKey": "EmptyEnum",
"scope": "All"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<p>Functions with excessive parameters are difficult to use, as one needs to figure out what each parameter is.</p>
<p>In many cases, the procedure can either be split into several smaller ones, or a better data structure can be found.</p>
<p>This rule verifies that each function has at most the given number of parameters.</p>
<h2>Noncompliant Code Example</h2>
<pre>
fn nine_params_sum(p1 : i32, p2 : i32,p3 : i32,p4 : i32,p5 : i32,p6 : i32,p7 : i32,p8 : i32,p9 : i32) -> i32 {/* Non-Compliant - too many parameters */
return p1 + p2 + p3 + p4 +p5 + p6 + p7 + p8 +p9;
}
</pre>
<h2>Compliant Solution</h2>
<pre>
fn single_params_sum(a : &[i32] )-> i32{
a.iter().sum()
}
</pre>

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"title": "Functions should not have too many parameters",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "20min"
},
"tags": [
"brain-overload"
],
"defaultSeverity": "Major",
"scope": "All"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Having to scroll horizontally makes it harder to get a quick overview and understanding of any piece of code.</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "Lines should not be too long",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "1min"
},
"tags": [
"convention"
],
"defaultSeverity": "Major",
"sqKey": "LineLength",
"scope": "All"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "Community Rust",
"ruleKeys": [
"LineLength",
"FunctionParametersCount",
"EmptyEnum"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ public class CheckListTest {

@Test
public void testSize(){
assertThat(CheckList.getRustChecks().isEmpty()).isTrue();
assertThat(CheckList.getRustChecks().size()).isEqualTo(3);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Sonar Rust Plugin (Community)
* Copyright (C) 2021 Eric Le Goff
* http://github.com/elegoff/sonar-rust
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.elegoff.rust.checks;

import org.junit.Test;

import java.io.File;

public class EmptyEnumCheckTest {

@Test
public void test() {
RustCheckVerifier.verify(new File("src/test/resources/checks/empty_enum.rs"), new EmptyEnumCheck());
}
}
Loading