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
Please sign in to leave a 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 )