Merging result from multiple reference providers.

Hi all,

I'm in a situation where  reference target can come from multiple classes of destinations, which makes merge result from
reference providers necessary. I came with following solution:

public class CompositeRerefernce extends PsiReferenceBase {

    final PsiReference[] references;


    public CompositeRerefernce(@NotNull PsiElement element, PsiReference... references) {
        super(element);
        this.references = references;
    }


    @Nullable
    @Override
    public PsiElement resolve() {
        for (PsiReference reference : references) {
            PsiElement resolve = reference.resolve();
            if (null != resolve) {
                return resolve;
            }
        }
        return null;
    }

    @NotNull
    @Override
    public Object[] getVariants() {
        ArrayList candidates = new ArrayList();
        for (PsiReference reference : references) {
            candidates.addAll(Arrays.asList(reference.getVariants()));
        }
        return candidates.toArray();
    }
}



Is there better way to do this?

7 comments
Comment actions Permalink

It seems you might replace your class with com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference


0
Comment actions Permalink

I tried poly references, but they seem to behave differenlty.  Somehow they are not marked as errors,  whenr eference is resolved to null
( or I miss something )  obvious.   I have different kinds of objects ( actions, events etc   - yes, I'm developing homegrown BPM )   and they
have to be merged in different contexts ( say, actions can come as sources and destinations,  but certain kinds of events are accetable either as source or destination only )
- and indifuvudual collections can be used as references.    Actually I could use PSI elements  as differences are in presentation only but I did not managed
@Presentation annotation to work in code completionpopup and in gutter.

( tried to steal from struts2 plugin, but did not found where and what;) )

0
Comment actions Permalink

About not highlighting references, please post relevant part of your DOM XML and code of Converter.

For completion, you'll have to build your own variants using LookupElementBuilder. You can obtain @Presentation values via com.intellij.ide.TypePresentationService.

0
Comment actions Permalink

Converter is very easy, nothing special there :

public class SequenceFromReferenceConverter implements CustomReferenceConverter {
    @NotNull
    @Override
    public PsiReference[] createReferences(GenericDomValue value, PsiElement element, ConvertContext context) {
        return new PsiReference[]{new CompositeRerefernce(element, new SourceEventNameReference(element), new ActivityNameReference(element), new GatewayNameReference(element), new ExceptionNameReference(element))};
    }
}


Just combination of references I delegate to.   And I build lookups elements in indivudual references ( for example gateways or events can have different icons based on  types)

And in DOM:
    @NotNull
    @Referencing(SequenceFromReferenceConverter.class)
    GenericAttributeValue<String> getFrom();



I hoped there is some reallly easy to use generic mechanism in DOM saving me some boilerplate code
0
Comment actions Permalink

Do your PsiPolyReferences always return non-empty result from multiResolve?

Do you really need to create custom references here, maybe your possible DOM "target" classes can share a common "ImATarget" interface and you could use plain ResolvingConverter<ImATarget>.

0
Comment actions Permalink

Looking into ResolvingConverter, I could use generic method to retrieve icons / texts  from DOM.

Not sure I will profit from it  -  Events are either source or destination,  based on enum type of yet anoher attribute,
different attributes of same DOM object are used as references in different contexts.

0
Comment actions Permalink

You could use that attribute to decide what converter instance to use via com.intellij.util.xml.ResolvingConverter.WrappedResolvingConverter

0

Please sign in to leave a comment.