Report access of private members between sibling inner classes in "Synthetic method call" inspection (IDEA-163379)

This commit is contained in:
Bas Leijdekkers
2016-11-01 12:32:23 +01:00
parent aef399bfee
commit 2fb544975c
6 changed files with 78 additions and 17 deletions
@@ -1213,7 +1213,8 @@
key="large.initializer.primitive.type.array.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.j2me.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.j2me.OverlyLargePrimitiveArrayInitializerInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="PrivateMemberAccessBetweenOuterAndInnerClass" bundle="com.siyeh.InspectionGadgetsBundle"
<localInspection groupPath="Java" language="JAVA" suppressId="SyntheticMethodCall" alternativeId="PrivateMemberAccessBetweenOuterAndInnerClass"
shortName="PrivateMemberAccessBetweenOuterAndInnerClass" bundle="com.siyeh.InspectionGadgetsBundle"
key="private.member.access.between.outer.and.inner.classes.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.j2me.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.j2me.PrivateMemberAccessBetweenOuterAndInnerClassInspection"/>
@@ -439,8 +439,8 @@ method.call.in.loop.condition.problem.descriptor=Call to method <code>#ref()</co
large.initializer.primitive.type.array.display.name=Overly large initializer for array of primitive type
large.initializer.primitive.type.array.problem.descriptor=Primitive array initializer with too many elements ({0}) #loc
large.initializer.primitive.type.array.maximum.number.of.elements.option=Maximum number of elements:
private.member.access.between.outer.and.inner.classes.display.name=Private member access between outer and inner classes
private.member.access.between.outer.and.inner.classes.problem.descriptor=Access to 'private' member of class ''{0}'' #loc
private.member.access.between.outer.and.inner.classes.display.name=Synthetic method call
private.member.access.between.outer.and.inner.classes.problem.descriptor=Access to 'private' member of class ''{0}'' requires synthetic method call #loc
private.member.access.between.outer.and.inner.classes.make.local.quickfix=Make ''{0}'' package-private
private.member.access.between.outer.and.inner.classes.make.constructor.package.local.quickfix=Make ''{0}'' constructor package-private
recordstore.opened.not.safely.closed.display.name=RecordStore opened but not safely closed
@@ -32,6 +32,18 @@ import org.jetbrains.annotations.Nullable;
public class PrivateMemberAccessBetweenOuterAndInnerClassInspection extends BaseInspection {
@NotNull
@Override
public String getID() {
return "SyntheticMethodCall";
}
@Nullable
@Override
public String getAlternativeID() {
return "PrivateMemberAccessBetweenOuterAndInnerClass";
}
@Override
@NotNull
public String getDisplayName() {
@@ -184,7 +196,11 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection extends Base
if (containingClass == null) {
return;
}
final PsiMethod constructor = expression.resolveConstructor();
final JavaResolveResult resolveResult = expression.resolveMethodGenerics();
if (!resolveResult.isAccessible()) {
return;
}
final PsiMethod constructor = (PsiMethod)resolveResult.getElement();
if (constructor == null) {
final PsiJavaCodeReferenceElement classReference =
expression.getClassOrAnonymousClassReference();
@@ -223,7 +239,11 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection extends Base
if (referenceNameElement == null) {
return;
}
final PsiElement element = expression.resolve();
final JavaResolveResult resolveResult = expression.advancedResolve(false);
if (!resolveResult.isAccessible()) {
return;
}
final PsiElement element = resolveResult.getElement();
if (!(element instanceof PsiMethod || element instanceof PsiField)) {
return;
}
@@ -240,8 +260,7 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection extends Base
return;
}
final PsiClass memberClass = ClassUtils.getContainingClass(member);
if (memberClass == null || memberClass.equals(containingClass) ||
(!PsiTreeUtil.isAncestor(containingClass, memberClass, true) && !PsiTreeUtil.isAncestor(memberClass, containingClass, true))) {
if (memberClass == null || memberClass.equals(containingClass)) {
return;
}
registerError(referenceNameElement, memberClass, member);
@@ -3,15 +3,15 @@
This inspection is intended for J2ME and other highly resource constrained environments.
Applying the results of this inspection without consideration might have negative effects on code clarity and design.
<p>
Reports references to non-constant <b>private</b> members of an outer class from inside an inner class or
to members of an inner class from a containing class.
Reports references to non-constant <b>private</b> members of a different class,
for which javac will generate a package-private synthetic accessor method.
<p>
An inner class and its containing class are compiled to separate
class files. The virtual machine normally prohibits access from a class to private fields and methods of
class files. The Java virtual machine normally prohibits access from a class to private fields and methods of
another class. To enable access from an inner class to private members of a
containing class or the other way around javac and other compilers create package private
synthetic accessor methods. Less use of memory and greater performance may be achieved by making the
member package-private, thus allowing direct access without the creation of synthetic accessor methods.
containing class or the other way around javac creates a package-private
synthetic accessor method. Less use of memory and greater performance may be achieved by making the
member package-private, thus allowing direct access without the creation of a synthetic accessor method.
<!-- tooltip end -->
<p>
@@ -9,7 +9,7 @@ public class PrivateMemberAccessBetweenOuterAndInnerClass {
System.out.println(caption);
Object btn = new Object() {
public void foo() {
System.out.println(<warning descr="Access to private member of class 'PrivateMemberAccessBetweenOuterAndInnerClass'">caption</warning>);
System.out.println(<warning descr="Access to private member of class 'PrivateMemberAccessBetweenOuterAndInnerClass' requires synthetic method call">caption</warning>);
System.out.println(N);
}
};
@@ -17,3 +17,44 @@ public class PrivateMemberAccessBetweenOuterAndInnerClass {
private static class Inner{}
}
class X {
void test() {
Private ref = new Private("access");
System.out.println(ref.<warning descr="Access to private member of class 'Private' requires synthetic method call">field</warning>);
PrivateAccessor.printPrivate(ref);
new PrivateAccessor().print(ref);
}
private static class Private {
private final String field;
Private(String value) {
this.field = value;
}
}
private static class PrivateAccessor {
PrivateAccessor() {
// prevent synthetic constructor
}
void print(Private ref) {
System.out.println(ref.<warning descr="Access to private member of class 'Private' requires synthetic method call">field</warning>);
}
static void printPrivate(Private ref) {
System.out.println(ref.<warning descr="Access to private member of class 'Private' requires synthetic method call">field</warning>);
}
}
}
class Y {
void m() {
String caption = new PrivateMemberAccessBetweenOuterAndInnerClass().<error descr="'caption' has private access in 'com.siyeh.igtest.j2me.private_member_access_between_outer_and_inner_class.PrivateMemberAccessBetweenOuterAndInnerClass'">caption</error>;
//noinspection PrivateMemberAccessBetweenOuterAndInnerClass
System.out.println(X.s);
//noinspection SyntheticMethodCall
System.out.println(X.s);
}
static class X {
private static String s = "";
}
}
@@ -9,9 +9,9 @@ public class Simple {
private void foo() {}
class Inner {{
new <warning descr="Access to private member of class 'Simple'">Simple</warning>();
System.out.println(<warning descr="Access to private member of class 'Simple'">i</warning>);
<warning descr="Access to private member of class 'Simple'">foo</warning>();
new <warning descr="Access to private member of class 'Simple' requires synthetic method call">Simple</warning>();
System.out.println(<warning descr="Access to private member of class 'Simple' requires synthetic method call">i</warning>);
<warning descr="Access to private member of class 'Simple' requires synthetic method call">foo</warning>();
}}
}
class Other {