au.com.integradev.delphi.checks.VariableNameCheck Maven / Gradle / Ivy
/*
* Sonar Delphi Plugin
* Copyright (C) 2019 Integrated Application Development
*
* 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 02
*/
package au.com.integradev.delphi.checks;
import static au.com.integradev.delphi.utils.VariableUtils.isGeneratedFormVariable;
import au.com.integradev.delphi.utils.InterfaceUtils;
import au.com.integradev.delphi.utils.NameConventionUtils;
import com.google.common.base.Splitter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.sonar.check.Rule;
import org.sonar.check.RuleProperty;
import org.sonar.plugins.communitydelphi.api.ast.ForLoopVarDeclarationNode;
import org.sonar.plugins.communitydelphi.api.ast.FormalParameterListNode;
import org.sonar.plugins.communitydelphi.api.ast.FormalParameterNode.FormalParameterData;
import org.sonar.plugins.communitydelphi.api.ast.NameDeclarationNode;
import org.sonar.plugins.communitydelphi.api.ast.RoutineDeclarationNode;
import org.sonar.plugins.communitydelphi.api.ast.VarDeclarationNode;
import org.sonar.plugins.communitydelphi.api.ast.VarStatementNode;
import org.sonar.plugins.communitydelphi.api.check.DelphiCheck;
import org.sonar.plugins.communitydelphi.api.check.DelphiCheckContext;
import org.sonar.plugins.communitydelphi.api.symbol.declaration.RoutineNameDeclaration;
import org.sonar.plugins.communitydelphi.api.symbol.scope.UnitScope;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
@DeprecatedRuleKey(ruleKey = "VariableNameRule", repositoryKey = "delph")
@Rule(key = "VariableName")
public class VariableNameCheck extends DelphiCheck {
private static final String MESSAGE =
"Rename this variable to match the expected naming convention.";
@RuleProperty(
key = "globalPrefixes",
description =
"Comma-delimited list of prefixes, global variables must begin with one of these.")
public String globalPrefixes = "";
private List globalPrefixesList;
@Override
public void start(DelphiCheckContext context) {
globalPrefixesList = Splitter.on(',').trimResults().splitToList(globalPrefixes);
}
@Override
public DelphiCheckContext visit(VarDeclarationNode varDeclaration, DelphiCheckContext context) {
if (isGeneratedFormVariable(varDeclaration)) {
return context;
}
boolean globalVariable = varDeclaration.getScope() instanceof UnitScope;
varDeclaration.getNameDeclarationList().getDeclarations().stream()
.filter(node -> isViolation(node, globalVariable))
.forEach(node -> reportIssue(context, node, MESSAGE));
return context;
}
@Override
public DelphiCheckContext visit(VarStatementNode varStatement, DelphiCheckContext context) {
varStatement.getNameDeclarationList().getDeclarations().stream()
.filter(node -> isViolation(node, false))
.forEach(node -> reportIssue(context, node, MESSAGE));
return context;
}
@Override
public DelphiCheckContext visit(ForLoopVarDeclarationNode loopVar, DelphiCheckContext context) {
NameDeclarationNode name = loopVar.getNameDeclarationNode();
if (isViolation(name, false)) {
reportIssue(context, name, MESSAGE);
}
return context;
}
@Override
public DelphiCheckContext visit(
FormalParameterListNode parameterListNode, DelphiCheckContext context) {
var parameterNodes =
parameterListNode.getParameters().stream()
.map(FormalParameterData::getNode)
.collect(Collectors.toUnmodifiableList());
var routineNode = parameterListNode.getFirstParentOfType(RoutineDeclarationNode.class);
var routineDeclaration = routineNode == null ? null : routineNode.getRoutineNameDeclaration();
getParametersToCheck(routineDeclaration, parameterNodes).stream()
.filter(parameter -> isViolation(parameter, false))
.forEach(parameter -> reportIssue(context, parameter, MESSAGE));
return context;
}
private static List getParametersToCheck(
RoutineNameDeclaration routineDeclaration, List parameterNodes) {
if (routineDeclaration == null) {
return parameterNodes;
}
List> paramNamesFromInterfaces =
parameterNodes.stream()
.map(x -> new HashSet())
.collect(Collectors.toUnmodifiableList());
InterfaceUtils.findImplementedInterfaceMethodDeclarations(routineDeclaration).stream()
.map(RoutineNameDeclaration::getParameters)
.forEach(
params -> {
assert (params.size() == paramNamesFromInterfaces.size());
for (int i = 0; i < paramNamesFromInterfaces.size(); i++) {
paramNamesFromInterfaces.get(i).add(params.get(i).getImage());
}
});
return IntStream.range(0, parameterNodes.size())
.filter(
index -> {
var actualImage = parameterNodes.get(index).getImage();
return !paramNamesFromInterfaces.get(index).contains(actualImage);
})
.mapToObj(parameterNodes::get)
.collect(Collectors.toUnmodifiableList());
}
private boolean isViolation(NameDeclarationNode name, boolean globalVariable) {
String image = name.getImage();
if (globalVariable) {
return !NameConventionUtils.compliesWithPrefix(image, globalPrefixesList);
}
return !NameConventionUtils.compliesWithPascalCase(image);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy