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() } }



0
1 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?

0

Please sign in to leave a comment.