use of com.jetbrains.php.lang.psi.elements.PhpIsset in project phpinspectionsea by kalessil.
the class IssetAndNullComparisonStrategy method apply.
public static boolean apply(@NotNull List<PsiElement> conditions, @NotNull ProblemsHolder holder) {
/* first ensure that we have null identity checks at all */
final Map<PsiElement, PsiElement> nullTestSubjects = new HashMap<>();
for (final PsiElement oneCondition : conditions) {
if (oneCondition instanceof BinaryExpression) {
final BinaryExpression expression = (BinaryExpression) oneCondition;
/* we need only !== and === operations */
final IElementType operator = expression.getOperationType();
if (operator != PhpTokenTypes.opIDENTICAL && operator != PhpTokenTypes.opNOT_IDENTICAL) {
continue;
}
/* quickly check if any operands is a constant */
final PsiElement left = expression.getLeftOperand();
final PsiElement right = expression.getRightOperand();
if (!(left instanceof ConstantReference) && !(right instanceof ConstantReference)) {
continue;
}
/* store null test subjects */
if (PhpLanguageUtil.isNull(right)) {
if (null != left) {
nullTestSubjects.put(expression, left);
}
continue;
}
if (PhpLanguageUtil.isNull(left)) {
if (null != right) {
nullTestSubjects.put(expression, right);
}
// continue;
}
}
}
if (0 == nullTestSubjects.size()) {
return false;
}
boolean hasReportedExpressions = false;
for (final PsiElement oneCondition : conditions) {
/* do not process null identity checks */
if (nullTestSubjects.containsKey(oneCondition)) {
continue;
}
/* unwrap ! and () */
PsiElement issetCandidate = oneCondition;
if (issetCandidate instanceof UnaryExpression) {
final PsiElement notOperatorCandidate = ((UnaryExpression) issetCandidate).getOperation();
if (null != notOperatorCandidate && notOperatorCandidate.getNode().getElementType() == PhpTokenTypes.opNOT) {
PsiElement invertedValue = ((UnaryExpression) issetCandidate).getValue();
invertedValue = ExpressionSemanticUtil.getExpressionTroughParenthesis(invertedValue);
if (null == invertedValue) {
continue;
}
issetCandidate = invertedValue;
}
}
if (!(issetCandidate instanceof PhpIsset) || 0 == ((PhpIsset) issetCandidate).getVariables().length) {
continue;
}
/* process isset constructions */
for (final PsiElement issetArgument : ((PhpIsset) issetCandidate).getVariables()) {
/* compare with know null identity checked subjects */
for (final Map.Entry<PsiElement, PsiElement> nullTestPair : nullTestSubjects.entrySet()) {
if (!OpeanapiEquivalenceUtil.areEqual(nullTestPair.getValue(), issetArgument)) {
continue;
}
hasReportedExpressions = true;
final PsiElement nullTestExpression = nullTestPair.getKey();
final String message = messagePattern.replace("%e%", nullTestExpression.getText());
holder.registerProblem(nullTestExpression, message, ProblemHighlightType.WEAK_WARNING);
}
}
}
nullTestSubjects.clear();
return hasReportedExpressions;
}
use of com.jetbrains.php.lang.psi.elements.PhpIsset in project phpinspectionsea by kalessil.
the class NotEmptyCanBeUsedStrategy method apply.
public static boolean apply(@NotNull List<PsiElement> conditions, @Nullable IElementType operation, @NotNull ProblemsHolder holder) {
boolean result = false;
if (conditions.size() > 1 && PhpTokenTypes.tsSHORT_CIRCUIT_AND_OPS.contains(operation)) {
for (final PsiElement issetCandidate : conditions) {
if (issetCandidate instanceof PhpIsset) {
final PhpIsset isset = (PhpIsset) issetCandidate;
final PsiElement[] arguments = isset.getVariables();
for (final PsiElement argument : arguments) {
final Class clazz = argument.getClass();
for (final PsiElement match : conditions) {
if (match == issetCandidate || match.getClass() != clazz) {
continue;
}
if (OpeanapiEquivalenceUtil.areEqual(argument, match)) {
result = true;
final String argumentAsText = argument.getText();
final String message = String.format(messagePattern, argumentAsText, argumentAsText, argumentAsText);
final PsiElement target = arguments.length == 1 ? isset : argument;
holder.registerProblem(target, message, ProblemHighlightType.WEAK_WARNING);
break;
}
}
}
}
}
}
return result;
}
use of com.jetbrains.php.lang.psi.elements.PhpIsset in project phpinspectionsea by kalessil.
the class IssetConstructsCanBeMergedInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpBinaryExpression(@NotNull BinaryExpression expression) {
final IElementType operator = expression.getOperationType();
if (operator != null && (operator == PhpTokenTypes.opAND || operator == PhpTokenTypes.opOR)) {
/* false-positives: part of another condition */
final PsiElement parent = expression.getParent();
final PsiElement context = parent instanceof ParenthesizedExpression ? parent.getParent() : parent;
if (context instanceof BinaryExpression && ((BinaryExpression) context).getOperationType() == operator) {
return;
}
final List<PsiElement> fragments = this.extract(expression, operator);
if (fragments.size() > 1) {
if (operator == PhpTokenTypes.opAND) {
/* handle isset && isset ... */
PsiElement firstHit = null;
int hitsCount = 0;
for (final PsiElement fragment : fragments) {
if (fragment instanceof PhpIsset) {
if (++hitsCount > 1 && firstHit != null) {
fragments.remove(firstHit);
fragments.remove(fragment);
holder.registerProblem(fragment, MessagesPresentationUtil.prefixWithEa(messageIsset), new MergeConstructsFix(holder.getProject(), expression, fragments, (PhpIsset) firstHit, (PhpIsset) fragment, operator));
break;
}
firstHit = firstHit == null ? fragment : firstHit;
}
}
} else {
/* handle !isset || !isset ... */
PsiElement firstHit = null;
int hitsCount = 0;
for (final PsiElement fragment : fragments) {
if (fragment instanceof UnaryExpression) {
final PsiElement candidate = ((UnaryExpression) fragment).getValue();
if (candidate instanceof PhpIsset) {
if (++hitsCount > 1 && firstHit != null) {
fragments.remove(firstHit.getParent());
fragments.remove(fragment);
holder.registerProblem(candidate, MessagesPresentationUtil.prefixWithEa(messageIvertedIsset), new MergeConstructsFix(holder.getProject(), expression, fragments, (PhpIsset) firstHit, (PhpIsset) candidate, operator));
break;
}
firstHit = firstHit == null ? candidate : firstHit;
}
}
}
}
}
fragments.clear();
}
}
@NotNull
private List<PsiElement> extract(@NotNull BinaryExpression binary, @Nullable IElementType operator) {
final List<PsiElement> result = new ArrayList<>();
if (binary.getOperationType() == operator) {
Stream.of(binary.getLeftOperand(), binary.getRightOperand()).filter(Objects::nonNull).map(ExpressionSemanticUtil::getExpressionTroughParenthesis).forEach(expression -> {
if (expression instanceof BinaryExpression) {
result.addAll(this.extract((BinaryExpression) expression, operator));
} else {
result.add(expression);
}
});
} else {
result.add(binary);
}
return result;
}
};
}
use of com.jetbrains.php.lang.psi.elements.PhpIsset in project phpinspectionsea by kalessil.
the class UnnecessaryIssetArgumentsInspector method buildVisitor.
@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
return new BasePhpElementVisitor() {
@Override
public void visitPhpIsset(@NotNull PhpIsset issetExpression) {
final PsiElement[] arguments = issetExpression.getVariables();
if (arguments.length > 1) {
final Set<PsiElement> reported = new HashSet<>();
for (final PsiElement current : arguments) {
if (current instanceof ArrayAccessExpression && !reported.contains(current)) {
/* collect current element bases */
final List<PsiElement> bases = new ArrayList<>();
PsiElement base = current;
while (base instanceof ArrayAccessExpression) {
base = ((ArrayAccessExpression) base).getValue();
if (base != null) {
bases.add(base);
}
}
/* iterate arguments once more to match */
if (!bases.isEmpty()) {
for (final PsiElement discoveredBase : bases) {
for (final PsiElement match : arguments) {
if (match != current && !reported.contains(match) && OpenapiEquivalenceUtil.areEqual(discoveredBase, match)) {
holder.registerProblem(match, MessagesPresentationUtil.prefixWithEa(message), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropArgumentFix());
reported.add(match);
}
}
}
bases.clear();
}
}
}
reported.clear();
}
}
};
}
use of com.jetbrains.php.lang.psi.elements.PhpIsset in project phpinspectionsea by kalessil.
the class GenerateAlternativeFromIssetStrategy method generate.
@Nullable
public static String generate(@NotNull TernaryExpression expression) {
/* handle inverted cases */
PsiElement issetCandidate = ExpressionSemanticUtil.getExpressionTroughParenthesis(expression.getCondition());
boolean isInverted = false;
if (issetCandidate instanceof UnaryExpression) {
final PsiElement operator = ((UnaryExpression) issetCandidate).getOperation();
if (null != operator && PhpTokenTypes.opNOT == operator.getNode().getElementType()) {
isInverted = true;
issetCandidate = ((UnaryExpression) issetCandidate).getValue();
}
}
/* verify condition structure */
final PhpIsset isset = issetCandidate instanceof PhpIsset ? (PhpIsset) issetCandidate : null;
if (null == isset || 1 != isset.getVariables().length) {
return null;
}
/* verify subject match and alternative availability */
final PsiElement subject = ExpressionSemanticUtil.getExpressionTroughParenthesis(isset.getVariables()[0]);
final PsiElement value = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getFalseVariant() : expression.getTrueVariant());
final PsiElement alternative = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getTrueVariant() : expression.getFalseVariant());
if (null == subject || null == value || null == alternative || !OpenapiEquivalenceUtil.areEqual(subject, value)) {
return null;
}
return subject.getText() + " ?? " + alternative.getText();
}
Aggregations