Proviging PsiReferences to custom xml attributes
I am developing an Android Studio plugin. Because of standardization res-files of the android project are stored separately in ARSC file. Values of this file are available in memory of my plugin as String.
I have custom attributes in my android layout files (@*my_res.common.resources:dimen/*):
<RelativeLayout
android:id="@+id/container_recycler_view_rl"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="@*my_res.common.resources:dimen/scrollable_page_fragment_relative_layout_margin_start"
android:layout_marginTop="@*my_res.common.resources:dimen/scrollable_page_fragment_relative_layout_margin_top"
android:layout_marginEnd="@*my_res.common.resources:dimen/scrollable_page_fragment_relative_layout_margin_end"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/page_fragment_short_reminder">
</RelativeLayout>
When GoToDeclarationAction occurs on these attributes I need a PsiReference to open in memory generated VirtualFile my_res.common.resources:dimen and navigate to appropriate value.
Please advice steps how to implement this. How should I create a virtual file and define passes to each of it’s element?
I have already implemented a PsiReferenceContributor and override getReferencesByElement in MyPsiReferenceProvider
public class MyPsiReferenceConributor extends PsiReferenceContributor {
@Override public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue(), new MyPsiReferenceProvider2()); } }
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> { if(element.text.contains("@*my_res.common.resources:dimen")) { val psiReference: PsiReference = object : PsiReference{ val attributeValue = element as XmlAttributeValue val myFile = PsiFileFactory.getInstance(element.project) .createFileFromText("AChubFile", Language.ANY, "mytext") override fun getElement(): PsiElement { return element } override fun getRangeInElement(): TextRange { return attributeValue.textRange } override fun bindToElement(element: PsiElement): PsiElement { throw UnsupportedOperationException() } override fun isReferenceTo(element: PsiElement): Boolean { return resolve() == element } override fun resolve(): PsiElement? { return myFile } override fun getCanonicalText(): String { return attributeValue.text } override fun handleElementRename(newElementName: String): PsiElement { throw UnsupportedOperationException() } override fun isSoft(): Boolean { return false } } return arrayOf(psiReference) } else { return emptyArray() } }
Please sign in to leave a comment.
What is this generated VirtualFile about? How does it look and why do you need it? Should it contain "fake" declarations for these keys and what would user see?