diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index d3dd36ee138d..ecb0250d4b75 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1292,7 +1292,7 @@ literal.as.arg.to.string.equals.problem.descriptor=Literal #ref is
literal.as.arg.to.string.equals.flip.quickfix=Flip ''{0}()''
c.style.array.declaration.replace.quickfix=Replace with Java-style array declaration
chained.method.call.ignore.option=Ignore chained method calls in field initializers
-chained.method.call.ignore.this.super.option=Ignore chained method calls in 'this()' and 'super()' calls
+chained.method.call.ignore.self.types.option=Ignore calls to methods returning the same type as their enclosing class
introduce.variable.quickfix=Introduce variable
introduce.variable.may.change.semantics.quickfix=Introduce variable (may change semantics)
flip.comparison.quickfix=Flip comparison
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/ChainedMethodCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/ChainedMethodCallInspection.java
index 73795d618855..54803e41a129 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/ChainedMethodCallInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/ChainedMethodCallInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2016 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2019 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.
@@ -18,6 +18,7 @@ package com.siyeh.ig.style;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.util.JavaPsiConstructorUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -25,6 +26,7 @@ import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.IntroduceVariableFix;
import com.siyeh.ig.psiutils.ParenthesesUtils;
+import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -32,14 +34,24 @@ import javax.swing.*;
public class ChainedMethodCallInspection extends BaseInspection {
@SuppressWarnings("PublicField")
public boolean m_ignoreFieldInitializations = true;
+
+ @SuppressWarnings({"PublicField", "unused"})
+ public boolean m_ignoreThisSuperCalls = true; // keep for compatibility
+
@SuppressWarnings("PublicField")
- public boolean m_ignoreThisSuperCalls = true;
+ public boolean ignoreSelfTypes = true;
+
+ @Override
+ public void writeSettings(@NotNull Element node) {
+ defaultWriteSettings(node, "ignoreSelfTypes");
+ writeBooleanOption(node, "ignoreSelfTypes", true);
+ }
@Override
public JComponent createOptionsPanel() {
final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
panel.addCheckbox(InspectionGadgetsBundle.message("chained.method.call.ignore.option"), "m_ignoreFieldInitializations");
- panel.addCheckbox(InspectionGadgetsBundle.message("chained.method.call.ignore.this.super.option"), "m_ignoreThisSuperCalls");
+ panel.addCheckbox(InspectionGadgetsBundle.message("chained.method.call.ignore.self.types.option"), "ignoreSelfTypes");
return panel;
}
@@ -76,11 +88,11 @@ public class ChainedMethodCallInspection extends BaseInspection {
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression reference = expression.getMethodExpression();
- final PsiExpression qualifier = reference.getQualifierExpression();
+ final PsiExpression qualifier = ParenthesesUtils.stripParentheses(reference.getQualifierExpression());
if (qualifier == null) {
return;
}
- if (!isCallExpression(qualifier)) {
+ if (!(qualifier instanceof PsiCallExpression)) {
return;
}
if (m_ignoreFieldInitializations) {
@@ -89,21 +101,35 @@ public class ChainedMethodCallInspection extends BaseInspection {
return;
}
}
- if (m_ignoreThisSuperCalls) {
- final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class);
- if (expressionList != null) {
- final PsiElement parent = expressionList.getParent();
- if (JavaPsiConstructorUtil.isConstructorCall(parent)) {
+ final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class);
+ if (expressionList != null) {
+ final PsiElement parent = expressionList.getParent();
+ if (JavaPsiConstructorUtil.isConstructorCall(parent)) {
+ return;
+ }
+ }
+ if (ignoreSelfTypes) {
+ if (qualifier instanceof PsiMethodCallExpression) {
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)qualifier;
+ final PsiMethod qualifierMethod = methodCallExpression.resolveMethod();
+ if (qualifierMethod == null) {
+ return;
+ }
+ PsiClass containingClass = qualifierMethod.getContainingClass();
+ PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(qualifierMethod.getReturnType());
+ if (containingClass == null || containingClass.equals(aClass)) {
+ return;
+ }
+ }
+ else {
+ PsiClass callClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType());
+ PsiClass qualifierClass = PsiUtil.resolveClassInClassTypeOnly(qualifier.getType());
+ if (qualifierClass == null || qualifierClass.equals(callClass)) {
return;
}
}
}
registerMethodCallError(expression);
}
-
- private boolean isCallExpression(PsiExpression expression) {
- expression = ParenthesesUtils.stripParentheses(expression);
- return expression instanceof PsiMethodCallExpression || expression instanceof PsiNewExpression;
- }
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ChainedMethodInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ChainedMethodInspection.java
deleted file mode 100644
index 584be27c5304..000000000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/ChainedMethodInspection.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.siyeh.igtest.bugs;
-
-public class ChainedMethodInspection{
- private ChainedMethodInspection baz = foo().bar();
- public void baz(){
- foo().bar();
- (foo()).bar();
- }
-
- public ChainedMethodInspection foo()
- {
- return this;
- }
-
- public ChainedMethodInspection bar()
- {
- return this;
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/chained_method_call/ChainedMethodCall.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/chained_method_call/ChainedMethodCall.java
new file mode 100644
index 000000000000..be1b3906ab37
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/chained_method_call/ChainedMethodCall.java
@@ -0,0 +1,22 @@
+package com.siyeh.igtest.bugs;
+
+public class ChainedMethodCall {
+ private X baz = new X().foo().bar();
+ public void baz(){
+ new X().foo().bar();
+ (new X().foo()).bar();
+ String s = new StringBuilder().append("x: ").append(new X()).append("y: ").append(new Y()).toString();
+ }
+
+ class X {
+ public Y foo() {
+ return new Y();
+ }
+ }
+
+ class Y {
+ public X bar() {
+ return new X();
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/ChainedMethodCallInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/ChainedMethodCallInspectionTest.java
new file mode 100644
index 000000000000..dc6b29eddb9f
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/ChainedMethodCallInspectionTest.java
@@ -0,0 +1,22 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.siyeh.ig.style;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ChainedMethodCallInspectionTest extends LightInspectionTestCase {
+
+ public void testChainedMethodCall() {
+ doTest();
+ }
+
+ @Nullable
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ChainedMethodCallInspection();
+ }
+}