summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2014-09-08 19:28:21 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-09-08 19:28:22 +0000
commit4a5b724d9fc18eb12aa59ec23c74e39399ab5c03 (patch)
tree525f975af50498b0319435e03bf52d55c9a0a1c3
parent2250e7e055295bee73366d360d15ea0270573ef6 (diff)
parent145ec85b4790ed9ade912d24754b38588998dee1 (diff)
downloadidea-4a5b724d9fc18eb12aa59ec23c74e39399ab5c03.tar.gz
Merge "Don't suggest making activities/fragments private"
-rw-r--r--java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java3
-rw-r--r--java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java13
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java34
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java85
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java5
5 files changed, 136 insertions, 4 deletions
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java
index 3e9044ec5eaf..856285a7bfce 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefClass.java
@@ -62,6 +62,9 @@ public interface RefClass extends RefJavaElement {
boolean isTestCase();
+ /** Returns true if this class extends one of the Android framework classes that must be public */
+ boolean isAndroidPublic();
+
boolean isLocalClass();
boolean isSelfInheritor(PsiClass psiClass);
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java
index 51ea666f59fa..9ce3a61b5222 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaManager.java
@@ -71,6 +71,19 @@ public abstract class RefJavaManager implements RefManagerExtension<RefJavaManag
public abstract PsiClass getServlet();
+ // Android Framework APIs that apps extend and where the subclasses must be public
+ // such that the framework can instantiate them
+
+ public abstract PsiClass getAndroidView();
+ public abstract PsiClass getAndroidActivity();
+ public abstract PsiClass getAndroidService();
+ public abstract PsiClass getAndroidBackupAgent();
+ public abstract PsiClass getAndroidContentProvider();
+ public abstract PsiClass getAndroidReceiver();
+ public abstract PsiClass getAndroidFragment(boolean support);
+ public abstract PsiClass getAndroidActionProvider();
+ public abstract PsiClass getAndroidParcelable();
+
public abstract EntryPointsManager getEntryPointsManager();
@NotNull
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
index 13a18f075aa4..ddaeeb7581b5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java
@@ -56,6 +56,7 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
private static final int IS_SERVLET_MASK = 0x400000;
private static final int IS_TESTCASE_MASK = 0x800000;
private static final int IS_LOCAL_MASK = 0x1000000;
+ private static final int IS_ANDROID_MASK = 0x2000000;
private Set<RefClass> myBases; // singleton (to conserve the memory) or THashSet
private Set<RefClass> mySubClasses; // singleton (to conserve the memory) or THashSet
@@ -139,6 +140,26 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
}
}
+ // The Android framework has a number of classes that it wants to
+ // instantiate so it requires these classes to be public, even if
+ // code analysis suggests that that these are only referenced from
+ // within the same package. Unfortunately these do not all extend the
+ // same set of base classes, so we need to check all these cases
+ // independently.
+ RefJavaManager refManager = getRefJavaManager();
+ if (inheritsFrom(psiClass, refManager.getAndroidActivity())
+ || inheritsFrom(psiClass, refManager.getAndroidService())
+ || inheritsFrom(psiClass, refManager.getAndroidView())
+ || inheritsFrom(psiClass, refManager.getAndroidFragment(false))
+ || inheritsFrom(psiClass, refManager.getAndroidFragment(true))
+ || inheritsFrom(psiClass, refManager.getAndroidReceiver())
+ || inheritsFrom(psiClass, refManager.getAndroidContentProvider())
+ || inheritsFrom(psiClass, refManager.getAndroidParcelable())
+ || inheritsFrom(psiClass, refManager.getAndroidBackupAgent())
+ || inheritsFrom(psiClass, refManager.getAndroidActionProvider())) {
+ setAndroidPublic(true);
+ }
+
for (PsiMethod psiMethod : psiMethods) {
RefMethod refMethod = (RefMethod)getRefManager().getReference(psiMethod);
@@ -187,6 +208,10 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
}
}
+ private static boolean inheritsFrom(@NotNull PsiClass c1, @Nullable PsiClass c2) {
+ return c2 != null && c1.isInheritor(c2, true);
+ }
+
private static ServerPageFile getJspFile(PsiClass psiClass) {
final PsiFile psiFile = PsiUtilCore.getTemplateLanguageFile(psiClass);
return psiFile instanceof ServerPageFile ? (ServerPageFile)psiFile : null;
@@ -491,6 +516,11 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
}
@Override
+ public boolean isAndroidPublic() {
+ return checkFlag(IS_ANDROID_MASK);
+ }
+
+ @Override
public boolean isTestCase() {
return checkFlag(IS_TESTCASE_MASK);
}
@@ -557,6 +587,10 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
setFlag(servlet, IS_SERVLET_MASK);
}
+ private void setAndroidPublic(boolean android) {
+ setFlag(android, IS_ANDROID_MASK);
+ }
+
private void setTestCase(boolean testCase) {
setFlag(testCase, IS_TESTCASE_MASK);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
index d9291660f9be..341f44a2fdf3 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
@@ -46,6 +46,16 @@ public class RefJavaManagerImpl extends RefJavaManager {
private PsiMethod myAppAgentmainPattern;
private PsiClass myApplet;
private PsiClass myServlet;
+ private PsiClass myAndroidActivity;
+ private PsiClass myAndroidService;
+ private PsiClass myAndroidBackupAgent;
+ private PsiClass myAndroidFragment;
+ private PsiClass myAndroidV4Fragment;
+ private PsiClass myAndroidContentProvider;
+ private PsiClass myAndroidReceiver;
+ private PsiClass myAndroidView;
+ private PsiClass myAndroidActionProvider;
+ private PsiClass myAndroidParcelable;
private RefPackage myDefaultPackage;
private THashMap<String, RefPackage> myPackages;
private final RefManagerImpl myRefManager;
@@ -66,9 +76,23 @@ public class RefJavaManagerImpl extends RefJavaManager {
LOG.error(e);
}
- myApplet = JavaPsiFacade.getInstance(psiManager.getProject()).findClass("java.applet.Applet", GlobalSearchScope.allScope(project));
- myServlet = JavaPsiFacade.getInstance(psiManager.getProject()).findClass("javax.servlet.Servlet", GlobalSearchScope.allScope(project));
-
+ GlobalSearchScope scope = GlobalSearchScope.allScope(project);
+ JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(psiManager.getProject());
+ myApplet = psiFacade.findClass("java.applet.Applet", scope);
+ myServlet = psiFacade.findClass("javax.servlet.Servlet", scope);
+
+ // Android Framework APIs that apps extend and where the subclasses must be public
+ // such that the framework can instantiate them
+ myAndroidActivity = psiFacade.findClass("android.app.Activity", scope);
+ myAndroidService = psiFacade.findClass("android.app.Service", scope);
+ myAndroidFragment = psiFacade.findClass("android.app.Fragment", scope);
+ myAndroidV4Fragment = psiFacade.findClass("android.support.v4.app.Fragment", scope);
+ myAndroidContentProvider = psiFacade.findClass("android.content.ContentProvider", scope);
+ myAndroidReceiver = psiFacade.findClass("android.content.BroadcastReceiver", scope);
+ myAndroidView = psiFacade.findClass("android.view.View", scope);
+ myAndroidActionProvider = psiFacade.findClass("android.view.ActionProvider", scope);
+ myAndroidParcelable = psiFacade.findClass("android.os.Parcelable", scope);
+ myAndroidBackupAgent = psiFacade.findClass("android.app.backup.BackupAgent", scope);
}
@Override
@@ -158,6 +182,51 @@ public class RefJavaManagerImpl extends RefJavaManager {
}
@Override
+ public PsiClass getAndroidActivity() {
+ return myAndroidActivity;
+ }
+
+ @Override
+ public PsiClass getAndroidService() {
+ return myAndroidService;
+ }
+
+ @Override
+ public PsiClass getAndroidBackupAgent() {
+ return myAndroidBackupAgent;
+ }
+
+ @Override
+ public PsiClass getAndroidFragment(boolean support) {
+ return support ? myAndroidV4Fragment : myAndroidFragment;
+ }
+
+ @Override
+ public PsiClass getAndroidContentProvider() {
+ return myAndroidContentProvider;
+ }
+
+ @Override
+ public PsiClass getAndroidReceiver() {
+ return myAndroidReceiver;
+ }
+
+ @Override
+ public PsiClass getAndroidView() {
+ return myAndroidView;
+ }
+
+ @Override
+ public PsiClass getAndroidActionProvider() {
+ return myAndroidActionProvider;
+ }
+
+ @Override
+ public PsiClass getAndroidParcelable() {
+ return myAndroidParcelable;
+ }
+
+ @Override
public RefParameter getParameterReference(PsiParameter param, int index) {
LOG.assertTrue(myRefManager.isValidPointForReference(), "References may become invalid after process is finished");
RefElement ref = myRefManager.getFromRefTable(param);
@@ -203,6 +272,16 @@ public class RefJavaManagerImpl extends RefJavaManager {
myAppPremainPattern = null;
myAppAgentmainPattern = null;
myServlet = null;
+ myAndroidActivity = null;
+ myAndroidService = null;
+ myAndroidBackupAgent = null;
+ myAndroidFragment = null;
+ myAndroidV4Fragment = null;
+ myAndroidContentProvider = null;
+ myAndroidReceiver = null;
+ myAndroidView = null;
+ myAndroidActionProvider = null;
+ myAndroidParcelable = null;
myDefaultPackage = null;
myProjectIterator = null;
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
index fd66f2806cb9..aa772f337610 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
@@ -44,7 +44,6 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.usageView.UsageViewTypeLocation;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -179,6 +178,10 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
RefClass refClass = (RefClass) refElement;
if (refClass.isAnonymous() || refClass.isEntry() || refClass.isTestCase() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) return null;
if (isTopLevelClass(refClass) && !SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES) return null;
+
+ if (refClass.isAndroidPublic()) {
+ return null;
+ }
}
//ignore unreferenced code. They could be a potential entry points.