![JAR search and dependency download from the Maven repository](/logo.png)
com.siyeh.ig.abstraction.InstanceofChainInspection Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-analysis-impl Show documentation
Show all versions of java-analysis-impl Show documentation
A packaging of the IntelliJ Community Edition java-analysis-impl library.
This is release number 1 of trunk branch 142.
The newest version!
/*
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.abstraction;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class InstanceofChainInspection extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean ignoreInstanceofOnLibraryClasses = false;
@Override
@NotNull
public String getID() {
return "ChainOfInstanceofChecks";
}
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message("chain.of.instanceof.checks.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final Check check = (Check)infos[0];
if (check == Check.CLASS_EQUALITY) {
return InspectionGadgetsBundle.message("chain.of.class.equality.checks.problem.descriptor");
}
return InspectionGadgetsBundle.message("chain.of.instanceof.checks.problem.descriptor");
}
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("ignore.instanceof.on.library.classes"), this,
"ignoreInstanceofOnLibraryClasses");
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new InstanceofChainVisitor();
}
private enum Check {
CLASS_EQUALITY, INSTANCEOF, NEITHER
}
private class InstanceofChainVisitor extends BaseInspectionVisitor {
@Override
public void visitIfStatement(@NotNull PsiIfStatement ifStatement) {
super.visitIfStatement(ifStatement);
if (ControlFlowUtils.isElseIf(ifStatement)) {
return;
}
final PsiStatement previousStatement = PsiTreeUtil.getPrevSiblingOfType(ifStatement, PsiStatement.class);
if (previousStatement instanceof PsiIfStatement) {
final PsiIfStatement previousIfStatement = (PsiIfStatement)previousStatement;
final PsiExpression condition = previousIfStatement.getCondition();
if (chainCheck(condition, null) != Check.NEITHER) {
return;
}
}
int numChecks = 0;
PsiIfStatement branch = ifStatement;
Check check = null;
while (true) {
final PsiExpression condition = branch.getCondition();
final Check chainCheck = chainCheck(condition, check);
if (chainCheck == Check.NEITHER) {
if (numChecks > 1) {
break;
}
return;
}
else {
check = chainCheck;
}
numChecks++;
final PsiStatement elseBranch = branch.getElseBranch();
if (elseBranch instanceof PsiIfStatement) {
branch = (PsiIfStatement)elseBranch;
}
else if (elseBranch == null) {
final PsiStatement nextStatement = PsiTreeUtil.getNextSiblingOfType(branch, PsiStatement.class);
if (!(nextStatement instanceof PsiIfStatement)) {
break;
}
branch = (PsiIfStatement)nextStatement;
}
else {
break;
}
}
if (numChecks < 2) {
return;
}
registerStatementError(ifStatement, check);
}
private Check chainCheck(PsiExpression condition, Check check) {
while (true) {
if (condition == null) {
return Check.NEITHER;
}
else if (check != Check.CLASS_EQUALITY && isInstanceofExpression(condition)) {
return Check.INSTANCEOF;
}
else if (condition instanceof PsiPolyadicExpression) {
if (check != Check.INSTANCEOF && isClassEqualityExpression(condition)) {
return Check.CLASS_EQUALITY;
}
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)condition;
final PsiExpression[] operands = polyadicExpression.getOperands();
for (PsiExpression operand : operands) {
final Check chainCheck = chainCheck(operand, check);
if (chainCheck != Check.NEITHER) {
return chainCheck;
}
}
return Check.NEITHER;
}
else if (condition instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)condition;
condition = parenthesizedExpression.getExpression();
continue;
}
else if (condition instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)condition;
condition = prefixExpression.getOperand();
continue;
}
else if (condition instanceof PsiPostfixExpression) {
final PsiPostfixExpression postfixExpression = (PsiPostfixExpression)condition;
condition = postfixExpression.getOperand();
continue;
}
return Check.NEITHER;
}
}
private boolean isClassEqualityExpression(PsiExpression expression) {
if (!(expression instanceof PsiBinaryExpression)) {
return false;
}
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
if (binaryExpression.getOperationTokenType() != JavaTokenType.EQEQ) {
return false;
}
return isClassObjectAccessExpression(binaryExpression.getLOperand()) ||
isClassObjectAccessExpression(binaryExpression.getROperand());
}
private boolean isClassObjectAccessExpression(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiClassObjectAccessExpression)) {
return false;
}
final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression)expression;
final PsiTypeElement typeElement = classObjectAccessExpression.getOperand();
return !ignoreInstanceofOnLibraryClasses || !LibraryUtil.isTypeInLibrary(typeElement.getType());
}
private boolean isInstanceofExpression(PsiExpression expression) {
if (!(expression instanceof PsiInstanceOfExpression)) {
return false;
}
final PsiInstanceOfExpression instanceOfExpression = (PsiInstanceOfExpression)expression;
final PsiTypeElement typeElement = instanceOfExpression.getCheckType();
return !ignoreInstanceofOnLibraryClasses || typeElement == null || !LibraryUtil.isTypeInLibrary(typeElement.getType());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy