mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
kotlin: fix false positives for 'suspicious package-private access' inspection nested object literal expressions in Kotlin
This is an improvement for cdd6055 which also fixes IDEA-210253. JavaResolveUtil.canAccessProtectedMember doesn't work properly for Kotlin because of KT-30759 and KT-30752, so its code is rewritten to use UAST to find outer class.
This commit is contained in:
+7
@@ -0,0 +1,7 @@
|
||||
package xxx
|
||||
|
||||
open class ProtectedMembersKotlin {
|
||||
protected val property: String = ""
|
||||
|
||||
protected fun foo() {}
|
||||
}
|
||||
+14
@@ -61,3 +61,17 @@ class AccessingProtectedConstructorFromSubclass : ProtectedConstructors(1)
|
||||
val objectAccessingDefaultProtectedConstructorFromSubclass = object : ProtectedConstructors() {}
|
||||
|
||||
val objectAccessingProtectedConstructorFromSubclass = object : ProtectedConstructors(1) {}
|
||||
|
||||
class AccessingProtectedMembersFromObjectLiteral {
|
||||
fun bar1() {
|
||||
object : ProtectedMembers() {
|
||||
fun bar2() {
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
method()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package xxx
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
class AccessingProtectedKotlinMembersFromObjectLiteral {
|
||||
fun bar1() {
|
||||
object : ProtectedMembersKotlin() {
|
||||
fun bar2() {
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
foo()
|
||||
val s2 = property
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
class AccessingProtectedMembersFromKotlin : ProtectedMembersKotlin() {
|
||||
fun bar() {
|
||||
foo()
|
||||
val s = property
|
||||
object : Runnable {
|
||||
override fun run() {
|
||||
foo()
|
||||
val s2 = property
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -14,5 +14,9 @@ class KtSuspiciousPackagePrivateAccessInspectionTest : SuspiciousPackagePrivateA
|
||||
doTestWithDependency()
|
||||
}
|
||||
|
||||
fun testAccessingProtectedMembersFromKotlin() {
|
||||
doTestWithDependency()
|
||||
}
|
||||
|
||||
override fun getBasePath() = "${JvmAnalysisKtTestsUtil.TEST_DATA_PROJECT_RELATIVE_BASE_PATH}/codeInspection/suspiciousPackagePrivateAccess"
|
||||
}
|
||||
+27
-13
@@ -15,7 +15,7 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiTypesUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
@@ -232,24 +232,38 @@ public class SuspiciousPackagePrivateAccessInspection extends AbstractBaseUastLo
|
||||
sourceClass);
|
||||
}
|
||||
|
||||
private static boolean canAccessProtectedMember(PsiMember member, PsiClass memberClass, PsiClass accessObjectType,
|
||||
boolean isMemberStatic, UClass sourceClass) {
|
||||
if (JavaResolveUtil.canAccessProtectedMember(member, memberClass, accessObjectType, sourceClass.getJavaPsi(), isMemberStatic)) {
|
||||
return true;
|
||||
}
|
||||
if (sourceClass instanceof UAnonymousClass && sourceClass.getJavaPsi().getContext() == null) {
|
||||
//workaround for KT-30752: KtLightClassForAnonymousDeclaration::getContext returns null for object literal expressions in some member initializers
|
||||
UElement uastParent = sourceClass.getUastParent();
|
||||
if (uastParent != null) {
|
||||
UClass parentClass = UastUtils.findContaining(uastParent.getSourcePsi(), UClass.class);
|
||||
if (parentClass != null) {
|
||||
return canAccessProtectedMember(member, memberClass, accessObjectType, isMemberStatic, parentClass);
|
||||
/**
|
||||
* The implementation was copied from {@link com.intellij.psi.impl.source.resolve.JavaResolveUtil#canAccessProtectedMember} but uses UAST
|
||||
* to find outer class as a workaround for bugs in Kotlin Light PSI (KT-30759, KT-30752)
|
||||
*/
|
||||
private static boolean canAccessProtectedMember(@NotNull PsiMember member, @NotNull PsiClass memberClass,
|
||||
@Nullable PsiClass accessObjectClass, boolean isStatic, @Nullable UClass contextClass) {
|
||||
while (contextClass != null) {
|
||||
PsiClass javaPsiClass = contextClass.getJavaPsi();
|
||||
if (InheritanceUtil.isInheritorOrSelf(javaPsiClass, memberClass, true)) {
|
||||
if (member instanceof PsiClass || isStatic || accessObjectClass == null
|
||||
|| InheritanceUtil.isInheritorOrSelf(accessObjectClass, javaPsiClass, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
contextClass = getOuterClass(contextClass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static UClass getOuterClass(@NotNull UClass aClass) {
|
||||
UElement uastParent = aClass.getUastParent();
|
||||
if (uastParent == null) return null;
|
||||
PsiElement sourcePsi = uastParent.getSourcePsi();
|
||||
while (sourcePsi == null) {
|
||||
uastParent = uastParent.getUastParent();
|
||||
if (uastParent == null) return null;
|
||||
sourcePsi = uastParent.getSourcePsi();
|
||||
}
|
||||
return UastUtils.findContaining(sourcePsi, UClass.class);
|
||||
}
|
||||
|
||||
private boolean isPackageLocalAccessSuspicious(Module sourceModule, Module targetModule) {
|
||||
if (targetModule == null || sourceModule == null || targetModule.equals(sourceModule)) {
|
||||
return false;
|
||||
|
||||
+16
@@ -10,6 +10,15 @@ class AccessingProtectedMembersNotFromSubclass {
|
||||
new ProtectedConstructors() {};
|
||||
new ProtectedConstructors(1) {};
|
||||
}
|
||||
|
||||
void baz() {
|
||||
class LocalSubclass extends ProtectedMembers {
|
||||
void bar() {
|
||||
method();
|
||||
staticMethod();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AccessingProtectedMembersFromSubclass extends ProtectedMembers {
|
||||
@@ -32,6 +41,13 @@ class AccessingProtectedMembersFromSubclass extends ProtectedMembers {
|
||||
staticMethod();
|
||||
}
|
||||
};
|
||||
|
||||
class LocalClass {
|
||||
void baz() {
|
||||
method();
|
||||
staticMethod();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class StaticInnerImpl1 extends ProtectedMembers.StaticInner {
|
||||
|
||||
Reference in New Issue
Block a user