package org.jetbrains.android; import com.intellij.codeInsight.daemon.ImplicitUsageProvider; import com.intellij.psi.*; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.android.dom.converters.OnClickConverter; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; /** * @author Eugene.Kudelevsky */ public class AndroidImplicitUsagesProvider implements ImplicitUsageProvider { @Override public boolean isImplicitUsage(PsiElement element) { if (element instanceof PsiField) { return isImplicitFieldUsage((PsiField)element); } else if (element instanceof PsiParameter) { return isImplicitParameterUsage((PsiParameter)element); } return false; } private static boolean isImplicitParameterUsage(@NotNull PsiParameter parameter) { if (AndroidFacet.getInstance(parameter) == null) { return false; } final PsiMethod method = PsiTreeUtil.getParentOfType(parameter, PsiMethod.class); if (method == null || !OnClickConverter.CONVERTER_FOR_LAYOUT.checkSignature(method) && !OnClickConverter.CONVERTER_FOR_MENU.checkSignature(method)) { return false; } final PsiClass aClass = PsiTreeUtil.getParentOfType(method, PsiClass.class); if (aClass == null) { return false; } final PsiClass activityBaseClass = JavaPsiFacade.getInstance(aClass.getProject()). findClass(AndroidUtils.ACTIVITY_BASE_CLASS_NAME, parameter.getResolveScope()); if (activityBaseClass == null) { return false; } return aClass.isInheritor(activityBaseClass, true); } private static boolean isImplicitFieldUsage(@NotNull PsiField field) { if (!"CREATOR".equals(field.getName())) { return false; } final PsiModifierList modifierList = field.getModifierList(); if (modifierList == null || !modifierList.hasModifierProperty(PsiModifier.STATIC)) { return false; } final PsiClass aClass = field.getContainingClass(); return aClass != null && InheritanceUtil.isInheritor(aClass, "android.os.Parcelable"); } @Override public boolean isImplicitRead(PsiElement element) { return false; } @Override public boolean isImplicitWrite(PsiElement element) { if (!(element instanceof PsiField)) { return false; } final AndroidFacet facet = AndroidFacet.getInstance(element); if (facet == null) { return false; } final PsiField field = (PsiField)element; final PsiModifierList modifierList = field.getModifierList(); if (modifierList == null) { return false; } for (PsiAnnotation annotation : modifierList.getAnnotations()) { for (PsiNameValuePair pair : annotation.getParameterList().getAttributes()) { final PsiAnnotationMemberValue value = pair.getValue(); if (isResourceReference(value)) { return true; } } } return false; } private static boolean isResourceReference(PsiAnnotationMemberValue value) { if (!(value instanceof PsiReferenceExpression)) { return false; } PsiReferenceExpression exp = (PsiReferenceExpression)value; String refName = exp.getReferenceName(); if (refName == null || refName.length() == 0) { return false; } PsiExpression qExp = exp.getQualifierExpression(); if (!(qExp instanceof PsiReferenceExpression)) { return false; } exp = (PsiReferenceExpression)qExp; refName = exp.getReferenceName(); if (refName == null || refName.length() == 0) { return false; } qExp = exp.getQualifierExpression(); if (!(qExp instanceof PsiReferenceExpression)) { return false; } exp = (PsiReferenceExpression)qExp; return AndroidUtils.R_CLASS_NAME.equals(exp.getReferenceName()); } }