| package org.jetbrains.android; |
| |
| import com.android.resources.ResourceFolderType; |
| import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.xml.XmlFile; |
| import com.intellij.psi.xml.XmlTag; |
| import com.intellij.usages.UsageTarget; |
| import com.intellij.usages.UsageTargetProvider; |
| import org.jetbrains.android.facet.AndroidFacet; |
| import org.jetbrains.android.util.AndroidResourceUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import static com.android.SdkConstants.TAG_RESOURCES; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class AndroidUsagesTargetProvider implements UsageTargetProvider { |
| @Override |
| public UsageTarget[] getTargets(Editor editor, PsiFile file) { |
| if (editor == null || file == null) { |
| return UsageTarget.EMPTY_ARRAY; |
| } |
| |
| final XmlTag tag = findValueResourceTagInContext(editor, file); |
| return tag != null |
| ? new UsageTarget[]{new PsiElement2UsageTargetAdapter(tag)} |
| : UsageTarget.EMPTY_ARRAY; |
| } |
| |
| @Override |
| public UsageTarget[] getTargets(PsiElement psiElement) { |
| return UsageTarget.EMPTY_ARRAY; |
| } |
| |
| @Nullable |
| static XmlTag findValueResourceTagInContext(@NotNull Editor editor, @NotNull PsiFile file) { |
| if (!(file instanceof XmlFile)) { |
| return null; |
| } |
| |
| final AndroidFacet facet = AndroidFacet.getInstance(file); |
| if (facet == null) { |
| return null; |
| } |
| |
| if (!AndroidResourceUtil.isInResourceSubdirectory(file, ResourceFolderType.VALUES.getName())) { |
| return null; |
| } |
| |
| final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); |
| if (element == null) { |
| return null; |
| } |
| |
| final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class); |
| if (tag == null) { |
| return null; |
| } |
| |
| XmlTag current = tag.getParentTag(); |
| if (current == null) { |
| return null; |
| } |
| // Handle nested elements, e.g. <attr> in <declare-styleable> and <item> in <style> |
| while (true) { |
| XmlTag parentTag = current.getParentTag(); |
| if (parentTag == null) { |
| return TAG_RESOURCES.equals(current.getName()) ? tag : null; |
| } else { |
| current = parentTag; |
| } |
| } |
| } |
| } |