/* /* * SonarQube PHP Custom Rules Example * Copyright (C) 2016-2016 SonarSource SA * mailto:contact AT sonarsource DOT com * * 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.sonar.samples.php.checks; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.sonar.check.Rule; import org.sonar.check.Priority; import org.sonar.php.tree.symbols.Scope; import org.sonar.plugins.php.api.symbols.Symbol; import org.sonar.plugins.php.api.tree.declaration.FunctionDeclarationTree; import org.sonar.plugins.php.api.tree.declaration.FunctionTree; import org.sonar.plugins.php.api.tree.expression.FunctionExpressionTree; import org.sonar.plugins.php.api.tree.statement.BlockTree; import org.sonar.plugins.php.api.tree.statement.StatementTree; import org.sonar.plugins.php.api.visitors.PHPVisitorCheck; /** * Example of implementation of a check by extending {@link PHPVisitorCheck}. * PHPVisitorCheck provides methods to visit nodes of the Abstract Syntax Tree * that represents the source code. *

* Those methods can be overridden to process information * related to node and issue can be created via the context that can be * accessed through {@link PHPVisitorCheck#context()}. */ @Rule( key = NullValueCheckRule.KEY, priority = Priority.MAJOR, name = "Parameters should be checked for NULL condition before use.", tags = {"convention"}, // Description can either be given in this annotation or through HTML name .html located in package src/resources/org/sonar/l10n/php/rules/ description = "

Parameters should be checked for NULL condition before use.

" ) public class NullValueCheckRule extends PHPVisitorCheck { public static final String KEY = "NullValueCheck"; /** * Overriding script visiting each of the function to create an issue * each time a function parameter is not checked for null value before use. */ @Override public void visitFunctionDeclaration(FunctionDeclarationTree tree) { checkParameters(tree); super.visitFunctionDeclaration(tree); } @Override public void visitFunctionExpression(FunctionExpressionTree tree) { checkParameters(tree); super.visitFunctionExpression(tree); } private void checkParameters(FunctionTree tree) { Scope scope = context().symbolTable().getScopeFor(tree); BlockTree blockTree = (BlockTree)tree.body(); int index_is_null = 0; int index_param = 0; List statementTree = blockTree.statements(); if (scope != null) { for(StatementTree st : statementTree) { for (Symbol symbol : scope.getSymbols(Symbol.Kind.PARAMETER)) { index_is_null = 0; index_param = 0; if(st.toString().contains(symbol.name())) { index_param = st.toString().indexOf(symbol.name()); String str = "is_null(" + symbol.name().toString() + ")"; String str_null_check = symbol.name().toString() + " != null"; String str_null_check2 = "!(" + symbol.name().toString() + " == null)"; Pattern p1 = Pattern.compile(Pattern.quote(str_null_check)); Pattern p = Pattern.compile(Pattern.quote(str)); Pattern p2 = Pattern.compile(Pattern.quote(str_null_check2)); Matcher matcher = p.matcher(st.toString()); Matcher matcher1 = p1.matcher(st.toString()); Matcher matcher2 = p2.matcher(st.toString()); while(matcher.find()) { index_is_null = matcher.start(); } while(matcher1.find()) { index_is_null = matcher1.start(); } while(matcher2.find()) { index_is_null = matcher2.start(); } if(index_is_null == 0 || index_param == 0 || index_param < index_is_null) { context().newIssue(this, tree, "Parameters should be checked for NULL condition before use."); } } } } } } }