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

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


0

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

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

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

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

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

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.