| package org.jetbrains.android.augment; |
| |
| import com.android.resources.ResourceType; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.project.DumbService; |
| import com.intellij.psi.PsiClass; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiField; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.psi.augment.PsiAugmentProvider; |
| import com.intellij.psi.impl.source.PsiExtensibleClass; |
| import com.intellij.util.containers.HashSet; |
| import org.jetbrains.android.dom.converters.ResourceReferenceConverter; |
| import org.jetbrains.android.facet.AndroidFacet; |
| import org.jetbrains.android.util.AndroidResourceUtil; |
| import org.jetbrains.android.util.AndroidUtils; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.*; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class AndroidPsiAugmentProvider extends PsiAugmentProvider { |
| private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.augment.AndroidPsiAugmentProvider"); |
| |
| @SuppressWarnings("unchecked") |
| @NotNull |
| @Override |
| public <Psi extends PsiElement> List<Psi> getAugments(@NotNull PsiElement element, @NotNull Class<Psi> type) { |
| if ((type != PsiClass.class && type != PsiField.class) || |
| !(element instanceof PsiExtensibleClass)) { |
| return Collections.emptyList(); |
| } |
| final PsiExtensibleClass aClass = (PsiExtensibleClass)element; |
| final String className = aClass.getName(); |
| final boolean rClassAugment = AndroidUtils.R_CLASS_NAME.equals(className) |
| && type == PsiClass.class; |
| |
| if (DumbService.isDumb(element.getProject())) { |
| if (rClassAugment) { |
| LOG.debug("R_CLASS_AUGMENT: empty because of dumb mode"); |
| } |
| return Collections.emptyList(); |
| } |
| |
| final AndroidFacet facet = AndroidFacet.getInstance(element); |
| if (facet == null) { |
| if (rClassAugment) { |
| LOG.debug("R_CLASS_AUGMENT: empty because no facet"); |
| } |
| return Collections.emptyList(); |
| } |
| |
| final PsiFile containingFile = element.getContainingFile(); |
| if (containingFile == null) { |
| if (rClassAugment) { |
| LOG.debug("R_CLASS_AUGMENT: empty because of no containing file"); |
| } |
| return Collections.emptyList(); |
| } |
| |
| if (type == PsiClass.class) { |
| if (AndroidUtils.R_CLASS_NAME.equals(className) && |
| AndroidResourceUtil.isRJavaFile(facet, containingFile)) { |
| final Set<String> existingInnerClasses = getOwnInnerClasses(aClass); |
| final Set<String> types = ResourceReferenceConverter.getResourceTypesInCurrentModule(facet); |
| final List<Psi> result = new ArrayList<Psi>(); |
| |
| for (String resType : types) { |
| if (!existingInnerClasses.contains(resType)) { |
| final AndroidLightClass resClass = new ResourceTypeClass(facet, resType, aClass); |
| result.add((Psi)resClass); |
| } |
| } |
| if (rClassAugment) { |
| LOG.debug("R_CLASS_AUGMENT: " + result.size() + " classes added"); |
| } |
| return result; |
| } |
| else if (AndroidUtils.MANIFEST_CLASS_NAME.equals(className) && |
| AndroidResourceUtil.isManifestJavaFile(facet, containingFile)) { |
| return Arrays.asList((Psi)new PermissionClass(facet, aClass), |
| (Psi)new PermissionGroupClass(facet, aClass)); |
| } |
| |
| if (rClassAugment) { |
| LOG.debug("R_CLASS_AUGMENT: empty because containing file is not actual R.java file"); |
| } |
| } |
| else if (type == PsiField.class && !(aClass instanceof AndroidLightClass)) { |
| // extend existing inner classes, not provided by this augment (ex. they can be generated by maven) |
| final PsiClass parentClass = aClass.getContainingClass(); |
| |
| if (parentClass != null && |
| AndroidUtils.R_CLASS_NAME.equals(parentClass.getName()) && |
| AndroidResourceUtil.isRJavaFile(facet, containingFile)) { |
| final String resClassName = aClass.getName(); |
| |
| if (resClassName != null && ResourceType.getEnum(resClassName) != null) { |
| final Set<String> existingFields = getOwnFields(aClass); |
| final PsiField[] newFields = ResourceTypeClass.buildLocalResourceFields(facet, resClassName, aClass); |
| final List<Psi> result = new ArrayList<Psi>(); |
| |
| for (PsiField field : newFields) { |
| if (!existingFields.contains(field.getName())) { |
| result.add((Psi)field); |
| } |
| } |
| return result; |
| } |
| } |
| } |
| return Collections.emptyList(); |
| } |
| |
| @NotNull |
| private static Set<String> getOwnInnerClasses(@NotNull PsiExtensibleClass aClass) { |
| final Set<String> result = new HashSet<String>(); |
| |
| for (PsiClass innerClass : aClass.getOwnInnerClasses()) { |
| result.add(innerClass.getName()); |
| } |
| return result; |
| } |
| |
| @NotNull |
| private static Set<String> getOwnFields(@NotNull PsiExtensibleClass aClass) { |
| final Set<String> result = new HashSet<String>(); |
| |
| for (PsiField field : aClass.getOwnFields()) { |
| result.add(field.getName()); |
| } |
| return result; |
| } |
| } |