use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class StrStrUsedAsStrPosInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName != null && mapping.containsKey(functionName)) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length >= 2) {
/* checks implicit boolean comparison pattern */
final PsiElement parent = reference.getParent();
if (parent instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) parent;
if (OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(binary.getOperationType())) {
final PsiElement secondOperand = OpenapiElementsUtil.getSecondOperand(binary, reference);
if (PhpLanguageUtil.isFalse(secondOperand)) {
final PsiElement operationNode = binary.getOperation();
if (operationNode != null) {
String operation = operationNode.getText();
operation = operation.length() == 2 ? operation + '=' : operation;
final String call = String.format("%s%s(%s, %s)", reference.getImmediateNamespaceName(), mapping.get(functionName), arguments[0].getText(), arguments[1].getText());
final boolean isRegular = ComparisonStyle.isRegular();
final String replacement = String.format("%s %s %s", isRegular ? call : "false", operation, isRegular ? "false" : call);
holder.registerProblem(binary, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new UseStrposFix(replacement));
return;
}
}
}
}
/* checks non-implicit boolean comparison patternS */
if (ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
final String operation = parent instanceof UnaryExpression ? "===" : "!==";
final String call = String.format("%s%s(%s, %s)", reference.getImmediateNamespaceName(), mapping.get(functionName), arguments[0].getText(), arguments[1].getText());
final boolean isRegular = ComparisonStyle.isRegular();
final String replacement = String.format("%s %s %s", isRegular ? call : "false", operation, isRegular ? "false" : call);
holder.registerProblem(parent instanceof UnaryExpression ? parent : reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new UseStrposFix(replacement));
}
}
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class SubStrShortHandUsageInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName != null && substringFunctions.contains(functionName)) {
final PsiElement[] arguments = reference.getParameters();
if ((arguments.length == 3 || arguments.length == 4) && arguments[2] instanceof BinaryExpression) {
/* check if 3rd argument is "strlen($search) - strlen(...)": "strlen($search)" is not needed */
final BinaryExpression binary = (BinaryExpression) arguments[2];
if (binary.getOperationType() == PhpTokenTypes.opMINUS) {
final PsiElement left = binary.getLeftOperand();
final PsiElement right = binary.getRightOperand();
if (right != null && OpenapiTypesUtil.isFunctionReference(left)) {
final FunctionReference leftCall = (FunctionReference) left;
final String leftName = leftCall.getName();
if (leftName != null && lengthFunctions.contains(leftName)) {
final PsiElement[] leftArguments = leftCall.getParameters();
if (leftArguments.length == 1 && OpenapiEquivalenceUtil.areEqual(leftArguments[0], arguments[0])) {
final PsiElement startOffset = arguments[1];
if (OpenapiEquivalenceUtil.areEqual(right, startOffset)) {
/* case: third parameter is not needed at all */
holder.registerProblem(arguments[2], String.format(MessagesPresentationUtil.prefixWithEa(patternDropLength), arguments[2].getText()), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropThirdParameterFix(holder.getProject(), reference));
} else if (OpenapiTypesUtil.isNumber(startOffset) && OpenapiTypesUtil.isNumber(right)) {
try {
int offset = Integer.parseInt(startOffset.getText()) - Integer.parseInt(right.getText());
if (offset < 0) {
/* case: third parameter can be simplified */
holder.registerProblem(binary, String.format(MessagesPresentationUtil.prefixWithEa(patternSimplifyLength), offset), new SimplifyFix(String.valueOf(offset)));
} else {
/* case: third parameter is not needed at all */
holder.registerProblem(arguments[2], String.format(MessagesPresentationUtil.prefixWithEa(patternDropLength), arguments[2].getText()), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropThirdParameterFix(holder.getProject(), reference));
}
} catch (final NumberFormatException expected) {
// return;
}
}
}
}
}
}
}
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class ArrayIsListCanBeUsedInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName != null && (functionName.equals("array_keys") || functionName.equals("array_values"))) {
final boolean isTargetVersion = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP800);
if (isTargetVersion) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 1) {
final PsiElement context = reference.getParent();
if (context instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) context;
final IElementType operator = binary.getOperationType();
if (OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operator)) {
final PsiElement second = OpenapiElementsUtil.getSecondOperand(binary, reference);
if (functionName.equals("array_values")) {
if (second != null && OpenapiEquivalenceUtil.areEqual(arguments[0], second)) {
this.report(reference, operator, arguments[0]);
}
} else if (functionName.equals("array_keys")) {
if (OpenapiTypesUtil.isFunctionReference(second)) {
final FunctionReference rightReference = (FunctionReference) second;
final String rightFunctionName = rightReference.getName();
final PsiElement[] rightArguments = rightReference.getParameters();
if ((rightFunctionName != null && rightFunctionName.equals("range")) && rightArguments.length == 2) {
final boolean rangeFromZero = OpenapiTypesUtil.isNumber(rightArguments[0]) && rightArguments[0].getText().equals("0");
if (rangeFromZero && rightArguments[1] instanceof BinaryExpression) {
final BinaryExpression rangeToBinary = (BinaryExpression) rightArguments[1];
if (rangeToBinary.getOperationType() == PhpTokenTypes.opMINUS) {
final PsiElement right = rangeToBinary.getRightOperand();
final PsiElement left = rangeToBinary.getLeftOperand();
if (OpenapiTypesUtil.isNumber(right) && right.getText().equals("1") && OpenapiTypesUtil.isFunctionReference(left)) {
final FunctionReference leftReference = (FunctionReference) left;
final String leftName = leftReference.getName();
final PsiElement[] leftArguments = leftReference.getParameters();
if (leftName != null && leftName.equals("count") && leftArguments.length == 1) {
if (OpenapiEquivalenceUtil.areEqual(arguments[0], leftArguments[0])) {
this.report(reference, operator, arguments[0]);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
private void report(@NotNull FunctionReference reference, @NotNull IElementType operator, @NotNull PsiElement argument) {
final boolean listExpected = operator == PhpTokenTypes.opIDENTICAL || operator == PhpTokenTypes.opEQUAL;
final String replacement = String.format("%s%sarray_is_list(%s)", listExpected ? "" : "!", reference.getImmediateNamespaceName(), argument.getText());
holder.registerProblem(reference.getParent(), String.format(MessagesPresentationUtil.prefixWithEa(message), replacement), new UseArrayIsListFix(replacement));
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class TypeUnsafeArraySearchInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName != null && targetFunctions.contains(functionName)) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 2) {
/* false-positives: array of string literals */
if (arguments[1] instanceof ArrayCreationExpression) {
final PsiElement[] elements = arguments[1].getChildren();
if (elements.length > 0) {
final long validElementsCount = Arrays.stream(elements).filter(element -> OpenapiTypesUtil.is(element, PhpElementTypes.ARRAY_VALUE)).map(PsiElement::getFirstChild).filter(element -> element instanceof StringLiteralExpression).map(literal -> ((StringLiteralExpression) literal).getContents().trim()).filter(content -> !content.isEmpty() && !content.matches("^\\d+$")).count();
if (validElementsCount == elements.length) {
return;
}
}
}
/* false-positives: array and item types are complimentary */
if (arguments[0] instanceof PhpTypedElement && arguments[1] instanceof PhpTypedElement) {
final Project project = holder.getProject();
final PhpType arrayType = OpenapiResolveUtil.resolveType((PhpTypedElement) arguments[1], project);
final Set<String> arrayTypes = arrayType == null ? null : arrayType.filterUnknown().getTypes();
if (arrayTypes != null && arrayTypes.size() == 1) {
final PhpType itemType = OpenapiResolveUtil.resolveType((PhpTypedElement) arguments[0], project);
final Set<String> itemTypes = itemType == null ? null : itemType.filterUnknown().getTypes();
if (itemTypes != null && itemTypes.size() == 1) {
final boolean matching = this.areTypesMatching(itemTypes.iterator().next(), arrayTypes.iterator().next());
if (matching) {
return;
}
}
}
}
/* general case: we need the third argument */
final String replacement = String.format("%s%s(%s, %s, true)", reference.getImmediateNamespaceName(), functionName, arguments[0].getText(), arguments[1].getText());
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message), new MakeSearchTypeSensitiveFix(replacement));
}
}
}
private boolean areTypesMatching(@NotNull String itemType, @NotNull String arrayType) {
boolean result = false;
if (!itemType.isEmpty()) {
result = arrayType.equals((itemType.charAt(0) == '\\' ? itemType : '\\' + itemType) + "[]");
}
return result;
}
};
}
use of com.jetbrains.php.lang.psi.elements.FunctionReference in project phpinspectionsea by kalessil.
the class DateUsageInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName != null && functionName.equals("date")) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 2) {
final PsiElement candidate = arguments[1];
if (OpenapiTypesUtil.isFunctionReference(candidate)) {
final FunctionReference inner = (FunctionReference) candidate;
final String innerName = inner.getName();
if (innerName != null && innerName.equals("time") && inner.getParameters().length == 0) {
holder.registerProblem(inner, MessagesPresentationUtil.prefixWithEa(messageDropTime), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropTimeFunctionCallLocalFix(holder.getProject(), arguments[0], arguments[1]));
}
}
}
}
}
};
}
Aggregations