PsiReferences and code completion

Hi,

I'm bit stuck and do not grock it properly. I provide refenreces through reference providers
( XML language with  custom DomElement provider )

In case of PolyReference  there no error highlighting if  reference is not resolvable,  but code completion proposal
pop up on ctrl-space ( proposals delieverd as string  from getVariants() )

Class in question ( I used  Poly  because resolve cache likes it )

public class LinkInNameReference extends PsiReferenceBase.Poly<XmlAttributeValue> implements EmptyResolveMessageProvider {


    private final ResolveCache cache;

    public LinkInNameReference(@NotNull XmlAttributeValue element, ResolveCache cache) {
        super(element);
        this.cache = cache;
    }


    @Nullable
    @Override
    public PsiElement resolve() {
        // out variants are psi elements
        String text = getElement().getText();
        for (ResolveResult resolveResult : multiResolve(false)) {
            XmlAttributeValue psiElement = (XmlAttributeValue) resolveResult.getElement();

            if (text.equals(psiElement.getText())) {

                return (PsiElement) psiElement;
            }
        }

        System.err.println(".......... no mathch for " + text);
        return null;
    }

    /**
     * provide list of suitable variants.     this is for presentation purposes only
     *
     * @return
     */
    @NotNull
    @Override
    public Object[] getVariants() {
        ArrayList<String> variants = new ArrayListModel<String>();
        for (ResolveResult resolveResult : multiResolve(false)) {
            XmlAttributeValue psiElement = (XmlAttributeValue) resolveResult.getElement();
            variants.add(psiElement.getValue());
        }
        return variants.toArray();
    }

    @NotNull
    @Override
    public String getUnresolvedMessagePattern() {
        return "receiver attribute shall correspond to in_message name attribute";
    }

    /**
     * resolve multiple candidates for caching
     *
     * @param incompleteCode
     * @return
     */
    @NotNull
    @Override
    public ResolveResult[] multiResolve(boolean incompleteCode) {

        return cache.resolveWithCaching(this, new ResolveCache.PolyVariantResolver<LinkInNameReference>() {
            /**
             * actual resolution is performed here
             * @param linkInNameReference
             * @param incompleteCode
             * @return
             */
            @NotNull
            @Override
            public ResolveResult[] resolve(@NotNull LinkInNameReference linkInNameReference, boolean incompleteCode) {
                final DomElement domElement = DomUtil.getDomElement(linkInNameReference.getElement());
                Communication_link communicationLink = DomUtil.getParentOfType(domElement, Communication_link.class, true);
                final String processName = communicationLink.getProcess().getStringValue();
                DomElement root = DomUtil.getParentOfType(communicationLink, Module.class, true);
                List<Process> processes = DomUtil.getChildrenOfType(root, Process.class);
                for (Process process : processes) {
                    if (processName.equals(process.getName().getStringValue())) {
                        Workflow workflow = process.getWorkflow();
                        if (null != workflow) {
                            return workflow.inMessageNames();
                        }
                    }
                }


                return ResolveResult.EMPTY_ARRAY;
            }
        }, true, incompleteCode);

    }
}



And when I do not use poly, I get error highlighting but now completion chouces:

/**
* provides references to activity names defined in wirkflow
*/
public class ActivityNameReference extends PsiReferenceBase<XmlAttributeValue> {
    final ResolveCache resolveCache;

    public ActivityNameReference(@NotNull XmlAttributeValue element, ResolveCache resolveCache) {
        super(element);
        this.resolveCache = resolveCache;
    }

    @Nullable
    @Override
    public PsiElement resolve() {
        // out variants are psi elements
        for (Object resolveResult : resolveReferences()) {
            XmlAttributeValue psiElement = (XmlAttributeValue) ((ResolveResult) resolveResult).getElement();
            if (getElement().getText().equals(psiElement.getText())) { 
                return (PsiElement) psiElement;
            }
        }

        return null;
    }

    @NotNull
    @Override
    public Object[] getVariants() {
        ResolveResult[] resolveResults = resolveReferences();
        ArrayList<String> strings = new ArrayList<String>();
        for (ResolveResult resolveResult : resolveResults) {
            strings.add(resolveResult.getElement().getText());
        }
        return resolveResults;
    }

    /**
     * resolve references, possibly with caching
     *
     * @return
     */
    private ResolveResult[] resolveReferences() {
        Workflow workflow = EbiModuleUtils.getParentWorkflow(getElement());
        return workflow.activityNames();
    }

}




So not I'm bit of stuck -  shall I return PSI elements as variants or  extracted string values?  What is difference between poly and normal references?  Is there better way to do this?
I will have code completion,   being able to choose from different kind of references (maybe with icons) , being able to navigate both ways etc.

I'm sure there are services to implemente, but I did notfound which ones
1 comment

OK got it.  PolyReference seems to be wrong for this ( or I do not grok it completely )

Problem with second class was retrieval of lookup values.  XMLAttributeValue is not suitable as lookup  item asit does not provide name
( my own bug )

0

Please sign in to leave a comment.