Why is it that a Java String ending with "." cannot enter the getVariants method in Reference?
Answered
As shown in the image below, if a string ends with "." or other special characters, it will not autocomplete. Normal English characters will autocomplete automatically.
my Reference
/**
* Returns the array of String, {@link PsiElement} and/or {@link LookupElement}
* instances representing all identifiers that are visible at the location of the reference. The contents
* of the returned array are used to build the lookup list for basic code completion. (The list
* of visible identifiers may not be filtered by the completion prefix string - the
* filtering is performed later by the IDE.)
* <p>
* This method is default since 2018.3.
*
* @return the array of available identifiers.
*/
@Override
public Object @NotNull [] getVariants() {
if (StringUtils.isNotBlank(rqlxKey) && rqlxKey.contains(".")) {
Module module = ModuleUtil.findModuleForPsiElement(myElement);
if (module == null) {
return super.getVariants();
}
String beforeRqlxKey = StringUtils.substringBeforeLast(rqlxKey, CompletionUtil.DUMMY_IDENTIFIER);
String prefixKey = StringUtils.substringBeforeLast(beforeRqlxKey, ".");
Optional<PsiPackage> aPackage = SnowJavaUtils.findPackage(module.getProject(), prefixKey);
List<PsiFile> rqlxFiles = RqlxUtils.findFilesByPath(prefixKey, module.getModuleScope());
ArrayList<SnowLookUpElement> appendElement = new ArrayList<>();
if (aPackage.isPresent()) {
PsiPackage psiPackage = aPackage.get();
PsiPackage[] subPackages = psiPackage.getSubPackages(module.getModuleScope());
PsiFile[] files = psiPackage.getFiles(module.getModuleScope());
for (PsiPackage subPackage : subPackages) {
appendElement.add(new SnowLookUpElement(subPackage.getName(), subPackage));
}
for (PsiFile file : files) {
if (RqlxUtils.isRqlxFile(file)) {
appendElement.add(new SnowLookUpElement(FilenameUtils.getBaseName(file.getName()), file));
}
}
}
if (CollectionUtils.isNotEmpty(rqlxFiles)) {
DomManager domManager = DomManager.getDomManager(module.getProject());
for (PsiFile file : rqlxFiles) {
XmlFile xmlFile = (XmlFile) file;
DomFileElement<Mapper> mapperDomFileElement = domManager.getFileElement(xmlFile, Mapper.class);
if (mapperDomFileElement != null) {
Mapper mapper = mapperDomFileElement.getRootElement();
List<Rql> rqls = mapper.getRqls();
for (Rql rql : rqls) {
XmlAttribute xmlAttribute = rql.getId().getXmlAttribute();
GenericAttributeValue<String> paramType = rql.getParamType();
String resultType = null;
if (rql instanceof Select) {
Select select = (Select) rql;
resultType = select.getResultType().getValue();
if (StringUtils.isNotBlank(resultType)) {
resultType = StringUtils.substringAfterLast(resultType, ".");
}
}
if (xmlAttribute != null) {
appendElement.add(
new SnowLookUpElement(xmlAttribute.getValue(), xmlAttribute, paramType.getValue(),
resultType));
}
}
}
}
}
String s = StringUtils.substringBeforeLast(myElement.getText(), CompletionUtil.DUMMY_IDENTIFIER);
String text = StringUtils.removeQuot(s);
ArrayList<LookupElement> result = new ArrayList<>();
if (text.contains(".")) {
String prefix = StringUtils.substringBeforeLast(text, ".");
for (SnowLookUpElement snowLookUpElement : appendElement) {
snowLookUpElement.setLookUpText(prefix + "." + snowLookUpElement.getLookupString());
result.add(snowLookUpElement);
}
} else {
result.addAll(appendElement);
}
return result.toArray();
}
return super.getVariants();
}
my plugin.xml
<completion.confidence language="JAVA"
implementationClass="com.ruimin.helper.java.contributor.SnowLiteralCompletionConfidence"
order="before javaSkipAutopopupInStrings"/>
my completion confidence
@NotNull
@Override
public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
if (isInStringLiteral(contextElement)) {
PsiLiteralExpression expression;
if (contextElement instanceof PsiJavaToken) {
expression = (PsiLiteralExpression) contextElement.getParent();
} else if (contextElement instanceof PsiLiteralExpression) {
expression = (PsiLiteralExpression) contextElement;
} else if (contextElement instanceof PsiLiteral) {
expression = (PsiLiteralExpression) contextElement.getParent();
} else {
return ThreeState.YES;
}
PsiMethodCallExpression callExpression = RqlxUtils.getLatestMethodCallExpressionFromParent(expression);
if (callExpression != null) {
PsiElement referenceExpression = callExpression.getFirstChild();
if (RqlxUtils.isRqlxMethodName(referenceExpression.getText()) || RqlxUtils.isSpliceRqlxKey(
referenceExpression)) {
return ThreeState.NO;
}
}
return ThreeState.YES;
}
return ThreeState.UNSURE;
}
public static boolean isInStringLiteral(PsiElement element) {
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(
PsiUtilCore.findLanguageFromElement(element));
return definition != null && (isStringLiteral(element, definition) || isStringLiteral(element.getParent(),
definition));
}
private static boolean isStringLiteral(PsiElement element, ParserDefinition definition) {
return PlatformPatterns.psiElement().withElementType(definition.getStringLiteralElements()).accepts(element);
}
Please sign in to leave a comment.
Hi,
It is hard to follow the implementation. I suggest debugging why it happens. Try to set a breakpoint in:
com.intellij.codeInsight.completion.CompletionData.completeReference(PsiReference, PsiElement, Set, TailType, ElementFilter, CompletionVariant)
If you are not able to find the reason, please simplify it and share the minimal reproducible example and a test project.
Karol Lewandowski
Thank you for your answer, I tracked down the cause of the problem using breakpoints according to your suggestion, but I don't know how to fix it. I've pasted the code below with a line comment
com.intellij.codeInsight.completion.CompletionPhase.CommittingDocuments#scheduleAsyncCompletion
Hi,
This is not the reason but the result of previous computations. I suggest focusing on:
I guess this condition is true, and `completionEditor` in the place you comment is null because of that. Maybe one of `CompletionConfidence` extensions prevents the completion?
Hi,
I found the reason, the "." character is judged in the condition, and the Reference must extend JavaClassReference class
Sorry, forgot to attach the class name of condition
com.intellij.codeInsight.editorActions.JavaTypedHandler
Please share the minimal reproducible plugin and test projects. It's hard to diagnose what is possible in your case without having the full context and without debugging it.
I don't understand the big picture, and analyzing the problem with the information you provided via the forum is just too time-consuming.
Sorry for not providing easy to analyze information, I have now added test project on my github repo. https://github.com/SvenShi/IfsSnowHelper
The path of the test project is sample/
The source code path of the plugin is in src/
Here are some classes that can cause this problem
my Completion Confidence
com.ruimin.helper.java.contributor.SnowLiteralCompletionConfidence
https://github.com/SvenShi/IfsSnowHelper/blob/master/src/main/java/com/ruimin/helper/java/contributor/SnowLiteralCompletionConfidence.java
my Reference Contributor
com.ruimin.helper.java.contributor.JavaReferenceContributor
https://github.com/SvenShi/IfsSnowHelper/blob/master/src/main/java/com/ruimin/helper/java/contributor/JavaReferenceContributor.java
my ReferenceProvider
com.ruimin.helper.java.provider.JavaRqlxKeyReferenceProvider
https://github.com/SvenShi/IfsSnowHelper/blob/master/src/main/java/com/ruimin/helper/java/provider/JavaRqlxKeyReferenceProvider.java
my reference
com.ruimin.helper.java.reference.JavaRqlxKeyReference
https://github.com/SvenShi/IfsSnowHelper/blob/master/src/main/java/com/ruimin/helper/java/reference/JavaRqlxKeyReference.java
How to reproduce the error? I run the sample project, and it doesn't complete anything except Java packages.
Please describe step by step what to do and what is expected/actual result. Which elements do completions reference? And other details.
Hello, thank you for your patience and for following up on my question.
Let me briefly introduce my sample project. In this project, there is a simple method call in the test method in TestService. The method call is dao.selectList("com.ruimin.sample.service.rqlx.test.selectTest",new HashMap<>()), where the first parameter references to an xml tag with the id "selectTest " in the test.rqlx file located under the "com.ruimin.sample.service.rqlx" package.
My expectation is that there should be a completion dialog that pops up after each character is entered, including when entering "." so that the completion dialog should continue to pop up to display all sub-packages. Please note that there is a plugin writing issue that causes the completion dialog to not get triggered when the parameter does not contain the "." symbol. Please disregard this issue.
Currently, I am facing a problem where the completion dialog of all sub-package names of the current package does not pop up when I enter "." after the package name.
Hi,
In the first screenshot, you showed completions with XML icons, and I cannot reproduce this case, so I assume I cannot reproduce the issue you struggle with. My behavior is exactly the opposite. If I have

.
, completions are provided:I can’t spend so much time trying to reproduce the error if you are not providing me precise information on how to reproduce it step by step.
I suggest checking whether the
PrefixMatcher
doesn’t reject your completion variants. As I can see incom.intellij.codeInsight.completion.LegacyCompletionContributor#completeReference
,CompletionResultsSet.prefixMatcher
isCamelHumpMatcher
with the prefix, e.g.,com.ruimin.sample.service.
.If this is the prefix matcher issue, I recommend moving the completion logic to
CompletionContributor
and adjusting thePrefixMatcher
to one that passes your items. Example of completion provider:I’m sorry, but I can’t spend more time on it.
Thank you so much for your patience and helpfulness. I will attempt to troubleshoot the issue on my own.