Skip to content

Commit

Permalink
Merge pull request #10 from green-code-initiative/EC34-replace
Browse files Browse the repository at this point in the history
EC34 replaced by EC35 : PHP implementation
  • Loading branch information
dedece35 authored Dec 10, 2023
2 parents a638d44 + a9bee71 commit daacdb2
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 84 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- [#9](https://github.com/green-code-initiative/ecoCode-php/pull/9) Upgrade licence system and licence headers of Java files
- [#10](https://github.com/green-code-initiative/ecoCode-php/pull/10) Adding EC35 rule : EC35 rule replaces EC34 with a specific use case ("file not found" specific)
- [#13](https://github.com/green-code-initiative/ecoCode-php/issues/13) Add build number to manifest
- Update ecocode-rules-specifications to 0.0.9

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public List<Class<?>> checkClasses() {
AvoidDoubleQuoteCheck.class,
AvoidFullSQLRequestCheck.class,
AvoidSQLRequestInLoopCheck.class,
AvoidTryCatchFinallyCheck_NOK_failsAllTryStatements.class,
AvoidTryCatchWithFileOpenedCheck.class,
AvoidUsingGlobalVariablesCheck.class,
IncrementCheck.class,
NoFunctionCallWhenDeclaringForLoop.class,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* ecoCode - PHP language - Provides rules to reduce the environmental footprint of your PHP programs
* Copyright © 2023 Green Code Initiative (https://www.ecocode.io)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.greencodeinitiative.php.checks;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.sonar.check.Rule;
import org.sonar.plugins.php.api.tree.Tree;
import org.sonar.plugins.php.api.tree.declaration.NamespaceNameTree;
import org.sonar.plugins.php.api.tree.expression.AssignmentExpressionTree;
import org.sonar.plugins.php.api.tree.expression.ExpressionTree;
import org.sonar.plugins.php.api.tree.expression.FunctionCallTree;
import org.sonar.plugins.php.api.tree.statement.*;
import org.sonar.plugins.php.api.visitors.PHPSubscriptionCheck;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;

@Rule(key = "EC35")
@DeprecatedRuleKey(repositoryKey = "gci-php", ruleKey = "S34")
@DeprecatedRuleKey(repositoryKey = "gci-php", ruleKey = "EC34")

public class AvoidTryCatchWithFileOpenedCheck extends PHPSubscriptionCheck {

public static final String ERROR_MESSAGE = "Avoid the use of try-catch with a file open in try block";

@Override
public List<Tree.Kind> nodesToVisit() {
return Collections.singletonList(Tree.Kind.TRY_STATEMENT);
}

@Override
public void visitNode(Tree tree) {

TryStatementTree tryStatement = (TryStatementTree) tree;

// parcours des statements du bloc try
visitStatementsList(tryStatement.block().statements());

}

private void visitStatementsList(List<StatementTree> lstStmts) {
for (StatementTree stmt : lstStmts){
Tree.Kind kind = stmt.getKind();
switch (kind) {
case EXPRESSION_STATEMENT:
visitExpressionStatement(((ExpressionStatementTree) stmt).expression());
break;
case BLOCK:
visitStatementsList(((BlockTree) stmt).statements());
break;
case IF_STATEMENT:
case ALTERNATIVE_IF_STATEMENT:
visitIfStatement((IfStatementTree) stmt);
break;
case FOR_STATEMENT:
case ALTERNATIVE_FOR_STATEMENT:
visitStatementsList(((ForStatementTree) stmt).statements());
break;
case WHILE_STATEMENT:
case ALTERNATIVE_WHILE_STATEMENT:
visitStatementsList(((WhileStatementTree) stmt).statements());
break;
case DO_WHILE_STATEMENT:
visitStatementsList(Arrays.asList(((DoWhileStatementTree) stmt).statement()));
break;
case FOREACH_STATEMENT:
case ALTERNATIVE_FOREACH_STATEMENT:
visitStatementsList(((ForEachStatementTree) stmt).statements());
break;
case CASE_CLAUSE:
visitStatementsList(((CaseClauseTree) stmt).statements());
break;
case SWITCH_STATEMENT:
visitSwitchStatement((SwitchStatementTree) stmt);
break;
case DEFAULT_CLAUSE:
visitStatementsList(((DefaultClauseTree) stmt).statements());
break;
case TRY_STATEMENT:
visitTryStatement((TryStatementTree) stmt);
break;
default:
}
}
}

private void visitIfStatement(IfStatementTree ifStatement) {
visitStatementsList(ifStatement.statements());

if (ifStatement.elseClause() != null) {
visitStatementsList(ifStatement.elseClause().statements());
}

if (ifStatement.elseifClauses() != null) {
for (ElseifClauseTree stmtElseIf : ifStatement.elseifClauses()) {
visitStatementsList(stmtElseIf.statements());
}
}
}

private void visitTryStatement(TryStatementTree tryStatement) {
for (CatchBlockTree stmtCatch : tryStatement.catchBlocks()) {
visitStatementsList(stmtCatch.block().statements());
}

if (tryStatement.finallyBlock() != null) {
visitStatementsList(tryStatement.finallyBlock().statements());
}
}

private void visitSwitchStatement(SwitchStatementTree switchStatement) {
for (SwitchCaseClauseTree switchCaseStmt : switchStatement.cases()) {
visitStatementsList(switchCaseStmt.statements());
}
}

private void visitExpressionStatement(ExpressionTree exprTree){
if (exprTree.is(Tree.Kind.FUNCTION_CALL)) { // si directement "function call"
visitCallExpression((FunctionCallTree) exprTree);
} else if (exprTree.is(Tree.Kind.ASSIGNMENT)) { // ou si assignment
AssignmentExpressionTree assignTree = (AssignmentExpressionTree) exprTree;
if (assignTree.value().is(Tree.Kind.FUNCTION_CALL)) { // et si "function call"
visitCallExpression((FunctionCallTree) assignTree.value());
}
}
}

private void visitCallExpression(FunctionCallTree functionCall){
String funcName = getFunctionNameFromCallExpression(functionCall);
if (funcName.toUpperCase().startsWith("PDF_OPEN")
|| "fopen".equalsIgnoreCase(funcName)
|| "readfile".equalsIgnoreCase(funcName)) {
context().newIssue(this, functionCall, ERROR_MESSAGE);
}
}

private String getFunctionNameFromCallExpression(FunctionCallTree functionCall) {
NamespaceNameTree nspTree = (NamespaceNameTree)functionCall.callee();
return nspTree != null && nspTree.fullName() != null ? nspTree.fullName() : "";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import org.sonar.plugins.php.api.tests.PHPCheckTest;
import org.sonar.plugins.php.api.tests.PhpTestFile;

public class AvoidTryCatchFinallyCheckNOKfailsAllTryStatementsTest {
public class AvoidTryCatchWithFileOpenedCheckTest {

@Test
public void test() throws Exception {
PHPCheckTest.check(new AvoidTryCatchFinallyCheck_NOK_failsAllTryStatements(), new PhpTestFile(new File("src/test/resources/checks/AvoidTryCatchFinallyCheck_NOK_FailsAllTryStatements.php")));
PHPCheckTest.check(new AvoidTryCatchWithFileOpenedCheck(), new PhpTestFile(new File("src/test/resources/checks/AvoidTryCatchWithFileOpenedCheck.php")));
}

}

This file was deleted.

Loading

0 comments on commit daacdb2

Please sign in to comment.