use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class StrtotimeUsageInspector 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("strtotime")) {
return;
}
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 0 || arguments.length > 2) {
return;
}
/* handle case: strtotime("now") -> time() */
if (arguments.length == 1) {
if (arguments[0] instanceof StringLiteralExpression) {
final StringLiteralExpression pattern = (StringLiteralExpression) arguments[0];
if (pattern.getContents().equalsIgnoreCase("now")) {
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseTime), new UseTimeFunctionLocalFix());
}
}
} else /* handle case: strtotime(..., time()) -> date(...) */
if (arguments.length == 2) {
if (OpenapiTypesUtil.isFunctionReference(arguments[1])) {
final FunctionReference candidate = (FunctionReference) arguments[1];
final String candidateName = candidate.getName();
if (candidateName != null && candidateName.equals("time") && this.isFromRootNamespace(candidate)) {
final String replacement = "strtotime(%a%)".replace("%a%", arguments[0].getText());
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageDropTime), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropTimeFunctionCallLocalFix(replacement));
}
}
}
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class GetDebugTypeCanBeUsedInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpTernaryExpression(@NotNull TernaryExpression ternary) {
if (!ternary.isShort()) {
final PsiElement condition = ternary.getCondition();
if (OpenapiTypesUtil.isFunctionReference(condition)) {
final FunctionReference reference = (FunctionReference) condition;
final String functionName = reference.getName();
if (functionName != null && functionName.equals("is_object")) {
final boolean isTargetVersion = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP800);
if (isTargetVersion) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 1 && arguments[0] != null) {
final PsiElement positive = ternary.getTrueVariant();
final PsiElement negative = ternary.getFalseVariant();
if (positive != null && negative != null) {
final boolean isTarget = this.is(positive, "get_class", arguments[0]) && this.is(negative, "gettype", arguments[0]);
if (isTarget && this.isFromRootNamespace(reference)) {
final String replacement = String.format("%sget_debug_type(%s)", reference.getImmediateNamespaceName(), arguments[0].getText());
holder.registerProblem(ternary, String.format(MessagesPresentationUtil.prefixWithEa(message), replacement), new UseGetDebugTypeFix(replacement));
}
}
}
}
}
}
}
}
private boolean is(@NotNull PsiElement candidate, @NotNull String targetName, @NotNull PsiElement targetArgument) {
if (OpenapiTypesUtil.isFunctionReference(candidate)) {
final FunctionReference reference = (FunctionReference) candidate;
final String functionName = reference.getName();
if (functionName != null && functionName.equals(targetName)) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length == 1 && arguments[0] != null) {
return OpenapiEquivalenceUtil.areEqual(arguments[0], targetArgument) && this.isFromRootNamespace(reference);
}
}
}
return false;
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class DynamicCallsToScopeIntrospectionInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
if (PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP710)) {
final String functionName = reference.getName();
if (functionName != null) {
/* discover target element */
final PsiElement target;
if (functionName.isEmpty()) {
final PsiElement[] children = reference.getChildren();
target = children.length == 2 ? children[0] : null;
} else if (callbacksPositions.containsKey(functionName)) {
final int callbackPosition = callbacksPositions.get(functionName);
final PsiElement[] arguments = reference.getParameters();
target = arguments.length >= callbackPosition + 1 ? arguments[callbackPosition] : null;
} else {
target = null;
}
/* discover the target function */
if (target != null) {
final StringLiteralExpression literal = ExpressionSemanticUtil.resolveAsStringLiteral(target);
if (literal != null) {
final String raw = PhpStringUtil.unescapeText(literal.getContents(), literal.isSingleQuote());
final String callback = raw.startsWith("\\") ? raw.substring(1) : raw;
if (targetCalls.containsKey(callback)) {
holder.registerProblem(target, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), callback));
}
}
}
}
}
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class CascadingDirnameCallsInspector 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("dirname")) {
return;
}
final PsiElement[] arguments = reference.getParameters();
if (arguments.length != 1 && arguments.length != 2) {
return;
}
/* require PHP7+, where 2nd parameter has been added */
if (PhpLanguageLevel.get(holder.getProject()).below(PhpLanguageLevel.PHP700)) {
return;
}
/* don't report nested calls, we want to report the one on top level */
final PsiElement parent = reference.getParent();
if (parent instanceof ParameterList && parent.getParent() instanceof FunctionReference) {
final FunctionReference parentReference = (FunctionReference) parent.getParent();
final String parentName = parentReference.getName();
if (parentName != null && parentName.equals("dirname")) {
final PsiElement[] parentArguments = parentReference.getParameters();
if (parentArguments.length == 1 || parentArguments.length == 2) {
return;
}
}
}
int directoryLevel = 0;
PsiElement argument = null;
final List<PsiElement> levels = new ArrayList<>();
FunctionReference current = reference;
while (current instanceof FunctionReference) {
final String currentName = current.getName();
if (currentName == null || !currentName.equals("dirname")) {
break;
}
final PsiElement[] currentArguments = current.getParameters();
if (currentArguments.length == 1) {
argument = currentArguments[0];
++directoryLevel;
} else if (currentArguments.length == 2) {
argument = currentArguments[0];
levels.add(currentArguments[1]);
} else {
break;
}
if (!(currentArguments[0] instanceof FunctionReference)) {
break;
}
current = (FunctionReference) currentArguments[0];
}
/* if no nested dirname calls, stop analysis */
if (current == reference) {
levels.clear();
return;
}
/* if we have 1+ nested call (top-level one is not considered) */
if (argument != null && arguments[0] != argument) {
/* process extracted level expressions: numbers to sum-up, expressions to stay */
final List<String> reported = new ArrayList<>();
for (PsiElement levelEntry : levels) {
try {
directoryLevel += Integer.parseInt(levelEntry.getText());
} catch (NumberFormatException fail) {
reported.add(levelEntry.getText());
}
}
levels.clear();
/* do not report cases with one level extraction */
if (1 == directoryLevel && reported.isEmpty()) {
return;
}
/* generate the replacement expression */
reported.add(0, String.valueOf(directoryLevel));
final String replacement = "dirname(%a%, %l%)".replace("%a%", argument.getText()).replace("%l%", String.join(" + ", reported));
reported.clear();
holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%e%", replacement)), new TheLocalFix(replacement));
}
}
};
}
use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.
the class FopenBinaryUnsafeUsageInspector 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("fopen")) {
final PsiElement[] arguments = reference.getParameters();
if (arguments.length >= 2) {
/* verify if mode provided and has no 'b' already */
final StringLiteralExpression mode = ExpressionSemanticUtil.resolveAsStringLiteral(arguments[1]);
final String modeText = mode == null ? null : mode.getContents();
if (modeText != null && !modeText.isEmpty()) {
if (modeText.indexOf('b') != -1) {
final boolean isCorrectlyPlaced = modeText.endsWith("b") || modeText.endsWith("b+");
if (!isCorrectlyPlaced) {
holder.registerProblem(arguments[1], MessagesPresentationUtil.prefixWithEa(messageMisplacedBinaryMode), ProblemHighlightType.GENERIC_ERROR, new TheLocalFix(holder.getProject(), mode));
}
} else if (modeText.indexOf('t') != -1) {
if (ENFORCE_BINARY_MODIFIER_USAGE) {
holder.registerProblem(arguments[1], MessagesPresentationUtil.prefixWithEa(messageReplaceWithBinaryMode), new TheLocalFix(holder.getProject(), mode));
}
} else {
if (ENFORCE_BINARY_MODIFIER_USAGE) {
holder.registerProblem(arguments[1], MessagesPresentationUtil.prefixWithEa(messageUseBinaryMode), new TheLocalFix(holder.getProject(), mode));
}
}
}
}
}
}
};
}
Aggregations