-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SONARGO-96 Get rid of slang-checks (#77)
- Loading branch information
1 parent
6f092da
commit c57d862
Showing
176 changed files
with
6,487 additions
and
184 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* SonarSource Go | ||
* Copyright (C) 2018-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. | ||
* | ||
* 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 Sonar Source-Available License for more details. | ||
* | ||
* You should have received a copy of the Sonar Source-Available License | ||
* along with this program; if not, see https://sonarsource.com/license/ssal/ | ||
*/ | ||
plugins { | ||
id("org.sonarsource.cloud-native.java-conventions") | ||
id("org.sonarsource.cloud-native.code-style-conventions") | ||
} | ||
|
||
dependencies { | ||
compileOnly(libs.sonar.plugin.api) | ||
|
||
implementation(project(":sonar-go-to-slang", configuration = "goBinaries")) | ||
implementation(libs.sonar.analyzer.commons) | ||
implementation(libs.slang.api) | ||
|
||
testImplementation(libs.assertj.core) | ||
testImplementation(libs.mockito.core) | ||
testImplementation(libs.slang.antlr) | ||
testImplementation(libs.slang.testing) | ||
testImplementation(libs.sonar.analyzer.test.commons) | ||
testImplementation(libs.classgraph) | ||
testImplementation(libs.junit.jupiter.api) | ||
testImplementation(libs.sonar.plugin.api.impl) | ||
testImplementation(libs.sonar.plugin.api.test.fixtures) | ||
testImplementation(testFixtures(project(":sonar-go-commons"))) | ||
|
||
testRuntimeOnly(libs.junit.jupiter.engine) | ||
} |
94 changes: 94 additions & 0 deletions
94
sonar-go-checks/src/main/java/org/sonar/go/checks/AbstractBranchDuplicationCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* SonarSource Go | ||
* Copyright (C) 2018-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. | ||
* | ||
* 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 Sonar Source-Available License for more details. | ||
* | ||
* You should have received a copy of the Sonar Source-Available License | ||
* along with this program; if not, see https://sonarsource.com/license/ssal/ | ||
*/ | ||
package org.sonar.go.checks; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.sonarsource.slang.api.IfTree; | ||
import org.sonarsource.slang.api.MatchCaseTree; | ||
import org.sonarsource.slang.api.MatchTree; | ||
import org.sonarsource.slang.api.Tree; | ||
import org.sonarsource.slang.checks.api.CheckContext; | ||
import org.sonarsource.slang.checks.api.InitContext; | ||
import org.sonarsource.slang.checks.api.SlangCheck; | ||
|
||
import static org.sonarsource.slang.utils.SyntacticEquivalence.areEquivalent; | ||
|
||
public abstract class AbstractBranchDuplicationCheck implements SlangCheck { | ||
|
||
protected abstract void checkDuplicatedBranches(CheckContext ctx, Tree tree, List<Tree> branches); | ||
|
||
protected abstract void onAllIdenticalBranches(CheckContext ctx, Tree tree); | ||
|
||
@Override | ||
public void initialize(InitContext init) { | ||
init.register(IfTree.class, (ctx, tree) -> { | ||
Tree parent = ctx.parent(); | ||
if (!(parent instanceof IfTree ifTree) || tree == ifTree.thenBranch()) { | ||
checkConditionalStructure(ctx, tree, new ConditionalStructure(tree)); | ||
} | ||
}); | ||
init.register(MatchTree.class, (ctx, tree) -> checkConditionalStructure(ctx, tree, new ConditionalStructure(tree))); | ||
} | ||
|
||
protected void checkConditionalStructure(CheckContext ctx, Tree tree, ConditionalStructure conditional) { | ||
if (conditional.allBranchesArePresent && conditional.allBranchesAreIdentical()) { | ||
onAllIdenticalBranches(ctx, tree); | ||
} else { | ||
checkDuplicatedBranches(ctx, tree, conditional.branches); | ||
} | ||
} | ||
|
||
public static class ConditionalStructure { | ||
|
||
private boolean allBranchesArePresent = false; | ||
|
||
private final List<Tree> branches = new ArrayList<>(); | ||
|
||
private ConditionalStructure(IfTree ifTree) { | ||
branches.add(ifTree.thenBranch()); | ||
Tree elseBranch = ifTree.elseBranch(); | ||
while (elseBranch != null) { | ||
if (elseBranch instanceof IfTree elseIf) { | ||
branches.add(elseIf.thenBranch()); | ||
elseBranch = elseIf.elseBranch(); | ||
} else { | ||
branches.add(elseBranch); | ||
allBranchesArePresent = true; | ||
elseBranch = null; | ||
} | ||
} | ||
} | ||
|
||
private ConditionalStructure(MatchTree tree) { | ||
for (MatchCaseTree caseTree : tree.cases()) { | ||
branches.add(caseTree.body()); | ||
if (caseTree.expression() == null) { | ||
allBranchesArePresent = true; | ||
} | ||
} | ||
} | ||
|
||
private boolean allBranchesAreIdentical() { | ||
return branches.size() > 1 && | ||
branches.stream() | ||
.skip(1) | ||
.allMatch(branch -> areEquivalent(branches.get(0), branch)); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
sonar-go-checks/src/main/java/org/sonar/go/checks/BadFunctionNameCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* SonarSource Go | ||
* Copyright (C) 2018-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. | ||
* | ||
* 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 Sonar Source-Available License for more details. | ||
* | ||
* You should have received a copy of the Sonar Source-Available License | ||
* along with this program; if not, see https://sonarsource.com/license/ssal/ | ||
*/ | ||
package org.sonar.go.checks; | ||
|
||
import java.util.regex.Pattern; | ||
import org.sonar.check.Rule; | ||
import org.sonar.check.RuleProperty; | ||
import org.sonarsource.slang.api.FunctionDeclarationTree; | ||
import org.sonarsource.slang.api.IdentifierTree; | ||
import org.sonarsource.slang.checks.api.InitContext; | ||
import org.sonarsource.slang.checks.api.SlangCheck; | ||
|
||
@Rule(key = "S100") | ||
public class BadFunctionNameCheck implements SlangCheck { | ||
|
||
@RuleProperty( | ||
key = "format", | ||
description = "Regular expression used to check the function names against.", | ||
defaultValue = GoChecksConstants.GO_NAMING_DEFAULT) | ||
public String format = GoChecksConstants.GO_NAMING_DEFAULT; | ||
|
||
private String message(String name) { | ||
return "Rename function \"" + name + "\" to match the regular expression " + format; | ||
} | ||
|
||
@Override | ||
public void initialize(InitContext init) { | ||
Pattern pattern = Pattern.compile(format); | ||
init.register(FunctionDeclarationTree.class, (ctx, fnDeclarationTree) -> { | ||
IdentifierTree name = fnDeclarationTree.name(); | ||
if (!fnDeclarationTree.isConstructor() && name != null && !pattern.matcher(name.name()).matches()) { | ||
ctx.reportIssue(fnDeclarationTree.name(), message(name.name())); | ||
} | ||
}); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
sonar-go-checks/src/main/java/org/sonar/go/checks/BooleanInversionCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* SonarSource Go | ||
* Copyright (C) 2018-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. | ||
* | ||
* 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 Sonar Source-Available License for more details. | ||
* | ||
* You should have received a copy of the Sonar Source-Available License | ||
* along with this program; if not, see https://sonarsource.com/license/ssal/ | ||
*/ | ||
package org.sonar.go.checks; | ||
|
||
import java.util.EnumMap; | ||
import java.util.Map; | ||
import org.sonar.check.Rule; | ||
import org.sonarsource.slang.api.BinaryExpressionTree; | ||
import org.sonarsource.slang.api.BinaryExpressionTree.Operator; | ||
import org.sonarsource.slang.api.Tree; | ||
import org.sonarsource.slang.api.UnaryExpressionTree; | ||
import org.sonarsource.slang.checks.api.InitContext; | ||
import org.sonarsource.slang.checks.api.SlangCheck; | ||
|
||
import static org.sonar.go.checks.utils.ExpressionUtils.skipParentheses; | ||
|
||
@Rule(key = "S1940") | ||
public class BooleanInversionCheck implements SlangCheck { | ||
|
||
private static final Map<Operator, String> OPERATORS = createOperatorsMap(); | ||
|
||
private static Map<Operator, String> createOperatorsMap() { | ||
Map<Operator, String> operatorsMap = new EnumMap<>(Operator.class); | ||
operatorsMap.put(Operator.EQUAL_TO, "!="); | ||
operatorsMap.put(Operator.NOT_EQUAL_TO, "=="); | ||
operatorsMap.put(Operator.LESS_THAN, ">="); | ||
operatorsMap.put(Operator.GREATER_THAN, "<="); | ||
operatorsMap.put(Operator.LESS_THAN_OR_EQUAL_TO, ">"); | ||
operatorsMap.put(Operator.GREATER_THAN_OR_EQUAL_TO, "<"); | ||
return operatorsMap; | ||
} | ||
|
||
@Override | ||
public void initialize(InitContext init) { | ||
init.register(UnaryExpressionTree.class, (ctx, tree) -> { | ||
Tree innerExpression = skipParentheses(tree.operand()); | ||
if (tree.operator() == UnaryExpressionTree.Operator.NEGATE && innerExpression instanceof BinaryExpressionTree binaryExpression) { | ||
String oppositeOperator = OPERATORS.get(binaryExpression.operator()); | ||
if (oppositeOperator != null) { | ||
String message = String.format("Use the opposite operator (\"%s\") instead.", oppositeOperator); | ||
ctx.reportIssue(tree, message); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
} |
81 changes: 81 additions & 0 deletions
81
sonar-go-checks/src/main/java/org/sonar/go/checks/BooleanLiteralCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* SonarSource Go | ||
* Copyright (C) 2018-2025 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. | ||
* | ||
* 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 Sonar Source-Available License for more details. | ||
* | ||
* You should have received a copy of the Sonar Source-Available License | ||
* along with this program; if not, see https://sonarsource.com/license/ssal/ | ||
*/ | ||
package org.sonar.go.checks; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import javax.annotation.Nullable; | ||
import org.sonar.check.Rule; | ||
import org.sonar.go.checks.utils.ExpressionUtils; | ||
import org.sonarsource.slang.api.BinaryExpressionTree; | ||
import org.sonarsource.slang.api.BlockTree; | ||
import org.sonarsource.slang.api.IfTree; | ||
import org.sonarsource.slang.api.Tree; | ||
import org.sonarsource.slang.api.UnaryExpressionTree; | ||
import org.sonarsource.slang.checks.api.InitContext; | ||
import org.sonarsource.slang.checks.api.SlangCheck; | ||
|
||
@Rule(key = "S1125") | ||
public class BooleanLiteralCheck implements SlangCheck { | ||
private static final List<BinaryExpressionTree.Operator> CONDITIONAL_BINARY_OPERATORS = Arrays.asList( | ||
BinaryExpressionTree.Operator.CONDITIONAL_AND, | ||
BinaryExpressionTree.Operator.CONDITIONAL_OR); | ||
|
||
private static final String MESSAGE = "Remove the unnecessary Boolean literal."; | ||
|
||
@Override | ||
public void initialize(InitContext init) { | ||
init.register(IfTree.class, (ctx, ifTree) -> { | ||
if (isIfWithMaxTwoBranches(ctx.parent(), ifTree) && !hasBlockBranch(ifTree)) { | ||
getBooleanLiteral(ifTree.thenBranch(), ifTree.elseBranch()) | ||
.ifPresent(booleanLiteral -> ctx.reportIssue(booleanLiteral, MESSAGE)); | ||
} | ||
}); | ||
|
||
init.register(BinaryExpressionTree.class, (ctx, binaryExprTree) -> { | ||
if (CONDITIONAL_BINARY_OPERATORS.contains(binaryExprTree.operator())) { | ||
getBooleanLiteral(binaryExprTree.leftOperand(), binaryExprTree.rightOperand()) | ||
.ifPresent(booleanLiteral -> ctx.reportIssue(booleanLiteral, MESSAGE)); | ||
} | ||
}); | ||
|
||
init.register(UnaryExpressionTree.class, (ctx, unaryExprTree) -> { | ||
if (UnaryExpressionTree.Operator.NEGATE.equals(unaryExprTree.operator())) { | ||
getBooleanLiteral(unaryExprTree.operand()) | ||
.ifPresent(booleanLiteral -> ctx.reportIssue(booleanLiteral, MESSAGE)); | ||
} | ||
}); | ||
} | ||
|
||
private static boolean isIfWithMaxTwoBranches(@Nullable Tree parent, IfTree ifTree) { | ||
boolean isElseIf = parent instanceof IfTree parentIfTree && parentIfTree.elseBranch() == ifTree; | ||
boolean isIfElseIf = ifTree.elseBranch() instanceof IfTree; | ||
return !isElseIf && !isIfElseIf; | ||
} | ||
|
||
private static boolean hasBlockBranch(IfTree ifTree) { | ||
return ifTree.thenBranch() instanceof BlockTree || ifTree.elseBranch() instanceof BlockTree; | ||
} | ||
|
||
private static Optional<Tree> getBooleanLiteral(Tree... trees) { | ||
return Arrays.stream(trees) | ||
.map(ExpressionUtils::skipParentheses) | ||
.filter(ExpressionUtils::isBooleanLiteral) | ||
.findFirst(); | ||
} | ||
} |
Oops, something went wrong.