diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/InnerClasses.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/InnerClasses.java
new file mode 100644
index 000000000000..5c465b31df5b
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/InnerClasses.java
@@ -0,0 +1,16 @@
+package xxx;
+
+public class InnerClasses {
+ static class PackagePrivateInnerClass {
+ }
+
+ static class PackagePrivateInnerClassWithConstructor {
+ PackagePrivateInnerClassWithConstructor() {
+ }
+ }
+
+ public static class ClassWithPackagePrivateConstructor {
+ ClassWithPackagePrivateConstructor() {
+ }
+ }
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PackagePrivateClass.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PackagePrivateClass.java
new file mode 100644
index 000000000000..afd175aa6cd6
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PackagePrivateClass.java
@@ -0,0 +1,4 @@
+package xxx;
+
+class PackagePrivateClass {
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/ProtectedConstructors.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/ProtectedConstructors.java
new file mode 100644
index 000000000000..5d30de8de61a
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/ProtectedConstructors.java
@@ -0,0 +1,9 @@
+package xxx;
+
+public class ProtectedConstructors {
+ protected ProtectedConstructors() {
+ }
+
+ protected ProtectedConstructors(int i) {
+ }
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/ProtectedMembers.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/ProtectedMembers.java
new file mode 100644
index 000000000000..3bae60a51cf9
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/ProtectedMembers.java
@@ -0,0 +1,12 @@
+package xxx;
+
+public class ProtectedMembers {
+ protected void method() {
+ }
+
+ static protected void staticMethod() {
+ }
+
+ protected static class StaticInner {
+ }
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PublicClass.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PublicClass.java
new file mode 100644
index 000000000000..02fdb18bc7f3
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PublicClass.java
@@ -0,0 +1,16 @@
+// Copyright 2000-2018 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 xxx;
+
+public class PublicClass {
+ public String publicField;
+ String packagePrivateField;
+ static public String PUBLIC_STATIC_FIELD;
+ static String PACKAGE_PRIVATE_STATIC_FIELD;
+
+ public void publicMethod() {}
+ void packagePrivateMethod() {}
+
+ PublicClass() {}
+ public PublicClass(int i) {}
+ PublicClass(boolean b) {}
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PublicClassWithDefaultConstructor.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PublicClassWithDefaultConstructor.java
new file mode 100644
index 000000000000..c71e3139f08c
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/PublicClassWithDefaultConstructor.java
@@ -0,0 +1,5 @@
+// Copyright 2000-2018 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 xxx;
+
+public class PublicClassWithDefaultConstructor {
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/StaticMembers.java b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/StaticMembers.java
new file mode 100644
index 000000000000..75b10e0e5008
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/dep/xxx/StaticMembers.java
@@ -0,0 +1,7 @@
+package xxx;
+
+public class StaticMembers {
+ static String IMPORTED_FIELD = "";
+ static void importedMethod() {
+ }
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/src/AccessingPackagePrivateMembers.kt b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/src/AccessingPackagePrivateMembers.kt
new file mode 100644
index 000000000000..befe8347739c
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/src/AccessingPackagePrivateMembers.kt
@@ -0,0 +1,41 @@
+package xxx
+
+import xxx.StaticMembers.*
+
+/**
+ * @see PackagePrivateClass
+ * @see PublicClass.packagePrivateField
+ */
+@Suppress("UNUSED_VARIABLE")
+class AccessingPackagePrivateMembers {
+ private val property = PackagePrivateClass()
+
+ fun main() {
+ PackagePrivateClass()
+ var variable: PackagePrivateClass
+
+ val aClass: PublicClass = PublicClass(1);
+ val aClass2: PublicClassWithDefaultConstructor = PublicClassWithDefaultConstructor();
+ PublicClass()
+ PublicClass(true)
+
+ System.out.println(aClass.publicField)
+ System.out.println(aClass.packagePrivateField)
+ System.out.println(PublicClass.PUBLIC_STATIC_FIELD)
+ System.out.println(PublicClass.PACKAGE_PRIVATE_STATIC_FIELD)
+
+ aClass.publicMethod()
+ aClass.packagePrivateMethod()
+
+ System.out.println(IMPORTED_FIELD)
+ importedMethod()
+
+ InnerClasses.PackagePrivateInnerClass()
+ InnerClasses.PackagePrivateInnerClassWithConstructor()
+ InnerClasses.ClassWithPackagePrivateConstructor()
+ }
+
+ companion object {
+ private val staticProperty = PackagePrivateClass()
+ }
+}
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/src/AccessingProtectedMembers.kt b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/src/AccessingProtectedMembers.kt
new file mode 100644
index 000000000000..4fc4709420a9
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testData/codeInspection/suspiciousPackagePrivateAccess/src/AccessingProtectedMembers.kt
@@ -0,0 +1,36 @@
+package xxx
+
+class AccessingProtectedMembersNotFromSubclass {
+ fun foo() {
+ val aClass: ProtectedMembers = ProtectedMembers()
+ aClass.method()
+ ProtectedMembers.staticMethod()
+ ProtectedConstructors()
+ ProtectedConstructors(1)
+ }
+}
+
+@Suppress("UNUSED_VARIABLE")
+class AccessingProtectedMembersFromSubclass : ProtectedMembers() {
+ fun foo() {
+ method()
+ staticMethod()
+ ProtectedMembers.staticMethod()
+
+ val aClass = ProtectedMembers()
+ aClass.method()
+ val myInstance = AccessingProtectedMembersFromSubclass()
+ myInstance.method()
+
+ var inner1: ProtectedMembers.StaticInner
+ var inner2: StaticInner
+ }
+
+ private class StaticInnerImpl1 : ProtectedMembers.StaticInner()
+
+ private class StaticInnerImpl2 : StaticInner()
+}
+
+class AccessingDefaultProtectedConstructorFromSubclass : ProtectedConstructors()
+
+class AccessingProtectedConstructorFromSubclass : ProtectedConstructors(1)
\ No newline at end of file
diff --git a/jvm/jvm-analysis-kotlin-tests/testSrc/com/intellij/codeInspection/tests/kotlin/KtSuspiciousPackagePrivateAccessInspectionTest.kt b/jvm/jvm-analysis-kotlin-tests/testSrc/com/intellij/codeInspection/tests/kotlin/KtSuspiciousPackagePrivateAccessInspectionTest.kt
new file mode 100644
index 000000000000..837a5bb49182
--- /dev/null
+++ b/jvm/jvm-analysis-kotlin-tests/testSrc/com/intellij/codeInspection/tests/kotlin/KtSuspiciousPackagePrivateAccessInspectionTest.kt
@@ -0,0 +1,18 @@
+package com.intellij.codeInspection.tests.kotlin
+
+import com.intellij.jvm.analysis.JvmAnalysisKtTestsUtil
+import com.intellij.testFramework.TestDataPath
+import com.siyeh.ig.dependency.SuspiciousPackagePrivateAccessInspectionTestCase
+
+@TestDataPath("/testData/codeInspection/suspiciousPackagePrivateAccess")
+class KtSuspiciousPackagePrivateAccessInspectionTest : SuspiciousPackagePrivateAccessInspectionTestCase("kt") {
+ fun testAccessingPackagePrivateMembers() {
+ doTestWithDependency()
+ }
+
+ fun testAccessingProtectedMembers() {
+ doTestWithDependency()
+ }
+
+ override fun getBasePath() = "${JvmAnalysisKtTestsUtil.TEST_DATA_PROJECT_RELATIVE_BASE_PATH}/codeInspection/suspiciousPackagePrivateAccess"
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspection.java
index 03103ec3d6f7..e8c411826e41 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspection.java
@@ -15,6 +15,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.uast.UastVisitorAdapter;
import com.intellij.ui.ContextHelpLabel;
@@ -65,20 +66,49 @@ public class SuspiciousPackagePrivateAccessInspection extends AbstractBaseUastLo
}
PsiElement resolved = node.resolve();
if (resolved instanceof PsiMember) {
- checkAccess(node.getSelector(), (PsiMember)resolved, receiver);
+ checkAccess(node.getSelector(), (PsiMember)resolved, getAccessObjectType(receiver));
}
return true;
}
@Override
public boolean visitSimpleNameReferenceExpression(@NotNull USimpleNameReferenceExpression node) {
- PsiElement resolved = node.resolve();
- if (resolved instanceof PsiMember) {
- checkAccess(node, (PsiMember)resolved, null);
+ UElement uastParent = node.getUastParent();
+ //we should skip 'checkAccess' here if node is part of UQualifiedReferenceExpression or UCallExpression node,
+ // otherwise the same problem will be reported twice
+ if (!isSelectorOfQualifiedReference(node)
+ && !(uastParent instanceof UCallExpression && isMethodReferenceOfCallExpression(node, (UCallExpression)uastParent)
+ && (((UCallExpression)uastParent).getKind() == UastCallKind.CONSTRUCTOR_CALL || isSelectorOfQualifiedReference((UExpression)uastParent)))) {
+ PsiElement resolved = node.resolve();
+ if (resolved instanceof PsiMember) {
+ checkAccess(node, (PsiMember)resolved, null);
+ }
}
return true;
}
+ private boolean isSelectorOfQualifiedReference(@Nullable UExpression expression) {
+ if (expression == null) return false;
+ UElement parent = expression.getUastParent();
+ return parent instanceof UQualifiedReferenceExpression
+ && referToSameSourceElement(expression, ((UQualifiedReferenceExpression)parent).getSelector());
+ }
+
+ private boolean isMethodReferenceOfCallExpression(@NotNull USimpleNameReferenceExpression expression, @NotNull UCallExpression parent) {
+ UElement methodIdentifier = parent.getMethodIdentifier();
+ UReferenceExpression classReference = parent.getClassReference();
+ if (methodIdentifier == null && classReference != null) {
+ methodIdentifier = classReference.getReferenceNameElement();
+ }
+ return referToSameSourceElement(expression.getReferenceNameElement(), methodIdentifier);
+ }
+
+ private boolean referToSameSourceElement(@Nullable UElement element1, @Nullable UElement element2) {
+ if (element1 == null || element2 == null) return false;
+ PsiElement sourcePsi1 = element1.getSourcePsi();
+ return sourcePsi1 != null && sourcePsi1.equals(element2.getSourcePsi());
+ }
+
@Override
public boolean visitCallableReferenceExpression(@NotNull UCallableReferenceExpression node) {
PsiElement resolve = node.resolve();
@@ -86,18 +116,50 @@ public class SuspiciousPackagePrivateAccessInspection extends AbstractBaseUastLo
PsiMember member = (PsiMember)resolve;
UElement sourceNode = getReferenceNameElement(node);
if (sourceNode != null) {
- checkAccess(sourceNode, member, node.getQualifierExpression());
+ checkAccess(sourceNode, member, getAccessObjectType(node.getQualifierExpression()));
}
}
return true;
}
- private void checkAccess(@NotNull UElement sourceNode, @NotNull PsiMember target, @Nullable UExpression receiver) {
+ @Override
+ public boolean visitTypeReferenceExpression(@NotNull UTypeReferenceExpression node) {
+ //in Kotlin implementation of UAST USimpleNameReferenceExpression::resolve returns null for reference to type in local variable declaration,
+ // so we need to have this case specifically
+ if (!(node.getSourcePsi() instanceof PsiTypeElement)) {
+ PsiClass resolved = PsiTypesUtil.getPsiClass(node.getType());
+ if (resolved != null) {
+ checkAccess(node, resolved, null);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean visitCallExpression(@NotNull UCallExpression node) {
+ //regular method calls are handled by visitSimpleNameReferenceExpression or visitQualifiedReferenceExpression, but we need to handle
+ // constructor calls in a special way because they may refer to classes
+ if (!isSelectorOfQualifiedReference(node) && node.getKind() == UastCallKind.CONSTRUCTOR_CALL) {
+ PsiMethod resolved = node.resolve();
+ if (resolved != null) {
+ checkAccess(node, resolved, null);
+ }
+ else {
+ UReferenceExpression classReference = node.getClassReference();
+ PsiElement resolvedClass = classReference != null ? classReference.resolve() : null;
+ if (resolvedClass instanceof PsiClass) {
+ checkAccess(node, (PsiClass)resolvedClass, null);
+ }
+ }
+ }
+ return true;
+ }
+
+ private void checkAccess(@NotNull UElement sourceNode, @NotNull PsiMember target, @Nullable PsiClass accessObjectType) {
if (target.hasModifier(JvmModifier.PACKAGE_LOCAL)) {
checkPackageLocalAccess(sourceNode, target, "package-private");
}
- else if (target.hasModifier(JvmModifier.PROTECTED) && receiver != null
- && !(receiver instanceof UThisExpression) && !(receiver instanceof USuperExpression) && !canAccessProtectedMember(receiver, sourceNode, target)) {
+ else if (target.hasModifier(JvmModifier.PROTECTED) && !canAccessProtectedMember(sourceNode, target, accessObjectType)) {
checkPackageLocalAccess(sourceNode, target, "protected and used not through a subclass here");
}
}
@@ -132,22 +194,26 @@ public class SuspiciousPackagePrivateAccessInspection extends AbstractBaseUastLo
return node;
}
- private static boolean canAccessProtectedMember(UExpression receiver, UElement sourceNode, PsiMember member) {
- PsiClass memberClass = member.getContainingClass();
- if (memberClass == null) return false;
+ @Nullable
+ private static PsiClass getAccessObjectType(@Nullable UExpression receiver) {
+ if (receiver == null || receiver instanceof UThisExpression || receiver instanceof USuperExpression) {
+ return null;
+ }
- PsiClass accessObjectType;
PsiType type = receiver.getExpressionType();
if (type != null) {
- if (!(type instanceof PsiClassType)) return false;
- accessObjectType = ((PsiClassType)type).resolve();
- if (accessObjectType == null) return false;
+ if (!(type instanceof PsiClassType)) return null;
+ return ((PsiClassType)type).resolve();
}
else {
PsiElement element = ((UReferenceExpression)receiver).resolve();
- if (!(element instanceof PsiClass)) return false;
- accessObjectType = (PsiClass)element;
+ return element instanceof PsiClass ? (PsiClass)element : null;
}
+ }
+
+ private static boolean canAccessProtectedMember(UElement sourceNode, PsiMember member, PsiClass accessObjectType) {
+ PsiClass memberClass = member.getContainingClass();
+ if (memberClass == null) return false;
PsiElement sourcePsi = sourceNode.getSourcePsi();
UClass sourceClass = UastUtils.findContaining(sourcePsi, UClass.class);
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/InnerClasses.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/InnerClasses.java
new file mode 100644
index 000000000000..5c465b31df5b
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/InnerClasses.java
@@ -0,0 +1,16 @@
+package xxx;
+
+public class InnerClasses {
+ static class PackagePrivateInnerClass {
+ }
+
+ static class PackagePrivateInnerClassWithConstructor {
+ PackagePrivateInnerClassWithConstructor() {
+ }
+ }
+
+ public static class ClassWithPackagePrivateConstructor {
+ ClassWithPackagePrivateConstructor() {
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/ProtectedConstructors.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/ProtectedConstructors.java
new file mode 100644
index 000000000000..5d30de8de61a
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/ProtectedConstructors.java
@@ -0,0 +1,9 @@
+package xxx;
+
+public class ProtectedConstructors {
+ protected ProtectedConstructors() {
+ }
+
+ protected ProtectedConstructors(int i) {
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClass.java
index 22012cd714b6..02fdb18bc7f3 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClass.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClass.java
@@ -9,4 +9,8 @@ public class PublicClass {
public void publicMethod() {}
void packagePrivateMethod() {}
+
+ PublicClass() {}
+ public PublicClass(int i) {}
+ PublicClass(boolean b) {}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClassWithDefaultConstructor.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClassWithDefaultConstructor.java
new file mode 100644
index 000000000000..c71e3139f08c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/dep/xxx/PublicClassWithDefaultConstructor.java
@@ -0,0 +1,5 @@
+// Copyright 2000-2018 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 xxx;
+
+public class PublicClassWithDefaultConstructor {
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingPackagePrivateMembers.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingPackagePrivateMembers.java
index 097d61e795cf..5c609bca49dd 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingPackagePrivateMembers.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingPackagePrivateMembers.java
@@ -7,19 +7,23 @@ import static xxx.StaticMembers.*;
* @see PublicClass#packagePrivateField
*/
public class AccessingPackagePrivateMembers {
- Object field = new PackagePrivateClass();
+ static Object staticField = new PackagePrivateClass();
+ Object field = new PackagePrivateClass();
{
- new PackagePrivateClass();
+ new PackagePrivateClass();
}
static {
- new PackagePrivateClass();
+ new PackagePrivateClass();
}
public void main() {
- new PackagePrivateClass();
+ new PackagePrivateClass();
PackagePrivateClass variable;
- PublicClass aClass = new PublicClass();
+ PublicClass aClass = new PublicClass(1);
+ PublicClassWithDefaultConstructor aClass2 = new PublicClassWithDefaultConstructor();
+ new PublicClass();
+ new PublicClass(true);
System.out.println(aClass.publicField);
System.out.println(aClass.packagePrivateField);
@@ -32,5 +36,9 @@ public class AccessingPackagePrivateMembers {
System.out.println(IMPORTED_FIELD);
importedMethod();
+
+ new InnerClasses.PackagePrivateInnerClass();
+ new InnerClasses.PackagePrivateInnerClassWithConstructor();
+ new InnerClasses.ClassWithPackagePrivateConstructor();
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingProtectedMembers.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingProtectedMembers.java
index 09d2a28d15d4..bc20f0d11cef 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingProtectedMembers.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/suspicious_package_private_access/src/AccessingProtectedMembers.java
@@ -5,6 +5,10 @@ class AccessingProtectedMembersNotFromSubclass {
ProtectedMembers aClass = new ProtectedMembers();
aClass.method();
ProtectedMembers.staticMethod();
+ new ProtectedConstructors();
+ new ProtectedConstructors(1);
+ new ProtectedConstructors() {};
+ new ProtectedConstructors(1) {};
}
}
@@ -21,6 +25,13 @@ class AccessingProtectedMembersFromSubclass extends ProtectedMembers {
ProtectedMembers.StaticInner inner1;
StaticInner inner2;
+
+ new Runnable() {
+ public void run() {
+ method();
+ staticMethod();
+ }
+ };
}
public static class StaticInnerImpl1 extends ProtectedMembers.StaticInner {
@@ -28,4 +39,26 @@ class AccessingProtectedMembersFromSubclass extends ProtectedMembers {
public static class StaticInnerImpl2 extends StaticInner {
}
+
+ public class OwnInner {
+ void bar() {
+ method();
+ staticMethod();
+ }
+ }
+
+ public static class OwnStaticInner {
+ void bar() {
+ staticMethod();
+ }
+ }
+}
+
+class AccessingDefaultProtectedConstructorFromSubclass extends ProtectedConstructors {
+}
+
+class AccessingProtectedConstructorFromSubclass extends ProtectedConstructors {
+ AccessingProtectedConstructorFromSubclass() {
+ super(1);
+ }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTest.java
index fed29d115f44..126d372e89d3 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTest.java
@@ -1,27 +1,8 @@
// Copyright 2000-2018 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.dependency;
-import com.intellij.codeInspection.InspectionProfileEntry;
-import com.intellij.openapi.application.WriteAction;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.LanguageLevelModuleExtension;
-import com.intellij.openapi.roots.ModuleRootModificationUtil;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.pom.java.LanguageLevel;
-import com.intellij.testFramework.LightProjectDescriptor;
-import com.siyeh.ig.LightInspectionTestCase;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.model.java.JavaSourceRootType;
-
-import java.io.File;
-import java.io.IOException;
-
-public class SuspiciousPackagePrivateAccessInspectionTest extends LightInspectionTestCase {
- private final ProjectWithDepModuleDescriptor myProjectDescriptor = new ProjectWithDepModuleDescriptor(LanguageLevel.HIGHEST);
+public class SuspiciousPackagePrivateAccessInspectionTest extends SuspiciousPackagePrivateAccessInspectionTestCase {
+ public SuspiciousPackagePrivateAccessInspectionTest() {super("java");}
public void testAccessingPackagePrivateMembers() {
doTestWithDependency();
@@ -30,77 +11,4 @@ public class SuspiciousPackagePrivateAccessInspectionTest extends LightInspectio
public void testAccessingProtectedMembers() {
doTestWithDependency();
}
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- myFixture.copyDirectoryToProject("dep", ProjectWithDepModuleDescriptor.getDepModuleSourceRoot());
- }
-
- @Override
- protected void tearDown() throws Exception {
- try {
- myProjectDescriptor.cleanUpSources();
- }
- catch (Throwable e) {
- addSuppressedException(e);
- }
- finally {
- super.tearDown();
- }
- }
-
- private void doTestWithDependency() {
- myFixture.configureByFile("src/" + getTestName(false) + ".java");
- myFixture.testHighlighting(true, false, false);
- }
-
- @NotNull
- @Override
- protected LightProjectDescriptor getProjectDescriptor() {
- return myProjectDescriptor;
- }
-
- @Nullable
- @Override
- protected InspectionProfileEntry getInspection() {
- return new SuspiciousPackagePrivateAccessInspection();
- }
-
- private static class ProjectWithDepModuleDescriptor extends ProjectDescriptor {
- private static final String DEP_MODULE_SOURCE_ROOT = "dep-module-src";
- private VirtualFile mySourceRoot;
-
- ProjectWithDepModuleDescriptor(@NotNull LanguageLevel languageLevel) {
- super(languageLevel);
- }
-
- @Override
- public void setUpProject(@NotNull Project project, @NotNull SetupHandler handler) throws Exception {
- super.setUpProject(project, handler);
- WriteAction.run(() -> {
- Module mainModule = ModuleManager.getInstance(project).findModuleByName(TEST_MODULE_NAME);
- File depModuleDir = FileUtil.createTempDirectory("dep-module-", null);
- Module depModule = createModule(project, depModuleDir + "/dep.iml");
- ModuleRootModificationUtil.updateModel(depModule, model -> {
- model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLanguageLevel);
- model.setSdk(getSdk());
- mySourceRoot = createSourceRoot(depModule, DEP_MODULE_SOURCE_ROOT);
- model.addContentEntry(mySourceRoot).addSourceFolder(mySourceRoot, JavaSourceRootType.SOURCE);
- });
- ModuleRootModificationUtil.addDependency(mainModule, depModule);
- });
- }
-
- public void cleanUpSources() throws IOException {
- if (mySourceRoot != null) {
- WriteAction.run(() -> mySourceRoot.delete(this));
- }
- }
-
- @NotNull
- private static String getDepModuleSourceRoot() {
- return "../" + DEP_MODULE_SOURCE_ROOT;
- }
- }
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTestCase.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTestCase.java
new file mode 100644
index 000000000000..53b9164c761c
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/SuspiciousPackagePrivateAccessInspectionTestCase.java
@@ -0,0 +1,103 @@
+// 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.dependency;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.LanguageLevelModuleExtension;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+
+import java.io.File;
+import java.io.IOException;
+
+public class SuspiciousPackagePrivateAccessInspectionTestCase extends LightInspectionTestCase {
+ private final ProjectWithDepModuleDescriptor myProjectDescriptor = new ProjectWithDepModuleDescriptor(LanguageLevel.HIGHEST);
+ private final String myExtension;
+
+ public SuspiciousPackagePrivateAccessInspectionTestCase(String extension) {
+ myExtension = extension;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.copyDirectoryToProject("dep", ProjectWithDepModuleDescriptor.getDepModuleSourceRoot());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ myProjectDescriptor.cleanUpSources();
+ }
+ catch (Throwable e) {
+ addSuppressedException(e);
+ }
+ finally {
+ super.tearDown();
+ }
+ }
+
+ protected void doTestWithDependency() {
+ myFixture.configureByFile("src/" + getTestName(false) + "." + myExtension);
+ myFixture.testHighlighting(true, false, false);
+ }
+
+ @NotNull
+ @Override
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return myProjectDescriptor;
+ }
+
+ @Nullable
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new SuspiciousPackagePrivateAccessInspection();
+ }
+
+ private static class ProjectWithDepModuleDescriptor extends ProjectDescriptor {
+ private static final String DEP_MODULE_SOURCE_ROOT = "dep-module-src";
+ private VirtualFile mySourceRoot;
+
+ ProjectWithDepModuleDescriptor(@NotNull LanguageLevel languageLevel) {
+ super(languageLevel);
+ }
+
+ @Override
+ public void setUpProject(@NotNull Project project, @NotNull SetupHandler handler) throws Exception {
+ super.setUpProject(project, handler);
+ WriteAction.run(() -> {
+ Module mainModule = ModuleManager.getInstance(project).findModuleByName(TEST_MODULE_NAME);
+ File depModuleDir = FileUtil.createTempDirectory("dep-module-", null);
+ Module depModule = createModule(project, depModuleDir + "/dep.iml");
+ ModuleRootModificationUtil.updateModel(depModule, model -> {
+ model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(myLanguageLevel);
+ model.setSdk(getSdk());
+ mySourceRoot = createSourceRoot(depModule, DEP_MODULE_SOURCE_ROOT);
+ model.addContentEntry(mySourceRoot).addSourceFolder(mySourceRoot, JavaSourceRootType.SOURCE);
+ });
+ ModuleRootModificationUtil.addDependency(mainModule, depModule);
+ });
+ }
+
+ public void cleanUpSources() throws IOException {
+ if (mySourceRoot != null) {
+ WriteAction.run(() -> mySourceRoot.delete(this));
+ }
+ }
+
+ @NotNull
+ private static String getDepModuleSourceRoot() {
+ return "../" + DEP_MODULE_SOURCE_ROOT;
+ }
+ }
+}