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



1 comment
Comment actions Permalink

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.