use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class CaseInsensitiveStringFunctionsMissUseInspector 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)) {
return;
}
final PsiElement[] arguments = reference.getParameters();
if (arguments.length != 2 && arguments.length != 3) {
return;
}
// resolve second parameter
final StringLiteralExpression pattern = ExpressionSemanticUtil.resolveAsStringLiteral(arguments[1]);
// might be not available - in another file (PhpStorm limitations)
if (pattern == null || pattern.getContainingFile() != arguments[1].getContainingFile()) {
return;
}
final String patternString = pattern.getContents();
if (!StringUtils.isEmpty(patternString) && !patternString.matches(".*\\p{L}.*")) {
final String replacementFunctionName = mapping.get(functionName);
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%f%", replacementFunctionName)), ProblemHighlightType.WEAK_WARNING, new TheLocalFix(replacementFunctionName));
}
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class StrContainsCanBeUsedInspector 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("strpos") || functionName.equals("mb_strpos"))) {
final boolean isTargetVersion = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP800);
if (isTargetVersion) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 2) {
final PsiElement context = reference.getParent();
if (context instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) context;
final IElementType operation = binary.getOperationType();
final boolean isTarget = (operation == PhpTokenTypes.opNOT_IDENTICAL || operation == PhpTokenTypes.opIDENTICAL) && PhpLanguageUtil.isFalse(OpenapiElementsUtil.getSecondOperand(binary, reference));
if (isTarget) {
final String replacement = String.format("%s%sstr_contains(%s, %s)", operation == PhpTokenTypes.opIDENTICAL ? "! " : "", reference.getImmediateNamespaceName(), arguments[0].getText(), arguments[1].getText());
holder.registerProblem(binary, String.format(MessagesPresentationUtil.prefixWithEa(message), replacement), new UseStrContainsFix(replacement));
}
}
}
}
}
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class ForgottenDebugOutputInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpMethodReference(@NotNull MethodReference reference) {
final String methodName = reference.getName();
if (methodName != null && customMethodsNames.contains(methodName)) {
for (final Couple<String> match : customMethods.values()) {
if (methodName.equals(match.getSecond())) {
final PsiElement resolved = OpenapiResolveUtil.resolveReference(reference);
if (resolved instanceof Method) {
final PhpClass clazz = ((Method) resolved).getContainingClass();
if (clazz != null && match.getFirst().equals(clazz.getFQN()) && !this.isInDebugFunction(reference)) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message));
return;
}
}
}
}
}
}
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final String functionName = reference.getName();
if (functionName != null && customFunctions.contains(functionName) && !(reference.getParent() instanceof PhpUse)) {
final Integer paramsNeeded = functionsRequirements.get(functionName);
if (paramsNeeded == null || reference.getParameters().length != paramsNeeded) {
final boolean isValidContext = this.isBuffered(reference) || this.isInDebugFunction(reference);
if (!isValidContext) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message));
}
}
}
}
private boolean isInDebugFunction(@NotNull PsiElement debugStatement) {
final Function scope = ExpressionSemanticUtil.getScope(debugStatement);
return scope != null && configuration.contains(scope instanceof Method ? scope.getFQN() : scope.getName());
}
private boolean isBuffered(@NotNull PsiElement debugStatement) {
boolean result = false;
PsiElement parent = debugStatement.getParent();
/* statement can be prepended by @ (silence) */
if (parent instanceof UnaryExpression) {
final PsiElement operation = ((UnaryExpression) parent).getOperation();
if (OpenapiTypesUtil.is(operation, PhpTokenTypes.opSILENCE)) {
parent = parent.getParent();
}
}
/* ensure it's not prepended with 'ob_start();' */
if (OpenapiTypesUtil.isStatementImpl(parent)) {
final PsiElement preceding = ((Statement) parent).getPrevPsiSibling();
if (preceding != null && OpenapiTypesUtil.isFunctionReference(preceding.getFirstChild())) {
final String precedingFunctionName = ((FunctionReference) preceding.getFirstChild()).getName();
if (precedingFunctionName != null && precedingFunctionName.equals("ob_start")) {
result = true;
}
}
}
return result;
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class GetClassUsageInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
final Project project = holder.getProject();
if (PhpLanguageLevel.get(project).atLeast(PhpLanguageLevel.PHP710)) {
final String functionName = reference.getName();
if (functionName != null && functionName.equals("get_class")) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 1 && arguments[0] instanceof PhpTypedElement) {
final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) arguments[0], project);
if (resolved != null) {
final boolean hasNull = resolved.filterUnknown().getTypes().stream().anyMatch(t -> Types.getType(t).equals(Types.strNull));
if ((hasNull || isNullableParameter(arguments[0])) && !isNullabilityChecked(arguments[0])) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message));
}
}
}
}
}
}
private boolean isNullabilityChecked(@NotNull PsiElement expression) {
/* workaround for https://youtrack.jetbrains.com/issue/WI-38622 */
boolean result = false;
final Function scope = ExpressionSemanticUtil.getScope(expression);
if (scope != null) {
final GroupStatement body = ExpressionSemanticUtil.getGroupStatement(scope);
final List<PsiElement> allUsages = PsiTreeUtil.findChildrenOfType(body, expression.getClass()).stream().filter(e -> OpenapiEquivalenceUtil.areEqual(e, expression)).collect(Collectors.toList());
for (final PsiElement candidate : allUsages.subList(0, allUsages.indexOf(expression))) {
final PsiElement parent = candidate.getParent();
if (parent instanceof PhpEmpty || parent instanceof PhpIsset) {
result = true;
} else if (parent instanceof BinaryExpression) {
final BinaryExpression binary = (BinaryExpression) parent;
final IElementType operator = binary.getOperationType();
if (operator == PhpTokenTypes.kwINSTANCEOF) {
result = true;
} else if (OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operator)) {
final PsiElement second = OpenapiElementsUtil.getSecondOperand(binary, candidate);
result = PhpLanguageUtil.isNull(second);
}
} else if (ExpressionSemanticUtil.isUsedAsLogicalOperand(candidate)) {
result = true;
}
/* break loop when null check being found */
if (result) {
break;
}
}
allUsages.clear();
}
return result;
}
private boolean isNullableParameter(@NotNull PsiElement expression) {
boolean result = false;
if (expression instanceof Variable) {
final Function scope = ExpressionSemanticUtil.getScope(expression);
if (scope != null) {
final String name = ((Variable) expression).getName();
result = Arrays.stream(scope.getParameters()).anyMatch(parameter -> name.equals(parameter.getName()) && PhpLanguageUtil.isNull(parameter.getDefaultValue()));
}
}
return result;
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class SubStrUsedAsArrayAccessInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
/* check if it's the target function */
final String functionName = reference.getName();
if (functionName != null && functionName.equals("substr")) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 3) {
final PsiElement length = arguments[2];
if (OpenapiTypesUtil.isNumber(length) && length.getText().equals("1")) {
final boolean isValidSource = arguments[0] instanceof Variable || arguments[0] instanceof ArrayAccessExpression || arguments[0] instanceof FieldReference;
if (isValidSource) {
final PhpTypedElement container = (PhpTypedElement) arguments[0];
final PhpType resolvedType = OpenapiResolveUtil.resolveType(container, holder.getProject());
if (resolvedType != null) {
final boolean isValidType = resolvedType.filterUnknown().getTypes().stream().anyMatch(t -> Types.getType(t).equals(Types.strString));
if (isValidType) {
final String source = arguments[0].getText();
final String offset = arguments[1].getText();
final String replacement = offset.startsWith("-") ? String.format("%s[strlen(%s) %s]", source, source, offset.replaceFirst("-", "- ")) : String.format("%s[%s]", source, offset);
holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new TheLocalFix(replacement));
}
}
}
}
}
}
}
};
}
Aggregations