Skip to content

Commit 8bea617

Browse files
committed
Improve variableName proposals for collections
1 parent 787ca9f commit 8bea617

File tree

3 files changed

+51
-26
lines changed

3 files changed

+51
-26
lines changed

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/codeassist/DOMCompletionContext.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,28 +71,38 @@ class DOMCompletionContext extends CompletionContext {
7171
this.modelUnit = modelUnit;
7272
this.textContent = textContent;
7373
this.offset = offset;
74-
// Use the raw text to walk back the offset to the first non-whitespace spot
7574
int adjustedOffset = this.offset;
75+
if (adjustedOffset > 0 && Character.isJavaIdentifierPart(textContent.charAt(adjustedOffset - 1))) {
76+
// workaround for cases where right node is empty and reported (wrongly) as starting at same offset
77+
adjustedOffset--;
78+
}
79+
ASTNode currentNode = NodeFinder.perform(domUnit, adjustedOffset, 0);
80+
// Use the raw text to walk back the offset to the first non-whitespace spot
81+
adjustedOffset = this.offset;
7682
if (adjustedOffset >= textContent.length()) {
7783
adjustedOffset = textContent.length() - 1;
7884
}
85+
if (adjustedOffset > 0 && Character.isJavaIdentifierPart(textContent.charAt(adjustedOffset - 1))) {
86+
// workaround for cases where right node is empty and reported (wrongly) as starting at same offset
87+
adjustedOffset--;
88+
}
7989
if (adjustedOffset + 1 >= textContent.length()
8090
|| !Character.isJavaIdentifierStart(textContent.charAt(adjustedOffset))) {
8191
while (adjustedOffset > 0 && Character.isWhitespace(textContent.charAt(adjustedOffset - 1)) ) {
8292
adjustedOffset--;
8393
}
8494
}
8595
ASTNode previousNodeBeforeWhitespaces = NodeFinder.perform(domUnit, adjustedOffset, 0);
86-
// if (cuBuffer.getChar(adjustedOffset - 1) == ',' && Character.isWhitespace(cuBuffer.getChar(adjustedOffset))) {
87-
// // probably an empty parameter
88-
// adjustedOffset = this.offset;
89-
// while (adjustedOffset < cuBuffer.getLength() && Character.isWhitespace(cuBuffer.getChar(adjustedOffset))) {
90-
// adjustedOffset++;
91-
// }
92-
// }
93-
this.node = previousNodeBeforeWhitespaces instanceof SimpleName || previousNodeBeforeWhitespaces instanceof StringLiteral || previousNodeBeforeWhitespaces instanceof CharacterLiteral || previousNodeBeforeWhitespaces instanceof NumberLiteral
94-
? NodeFinder.perform(domUnit, this.offset, 0) // keep default node from initial offset
95-
: previousNodeBeforeWhitespaces; // use previous node
96+
adjustedOffset = this.offset;
97+
if (adjustedOffset < textContent.length() - 1 && Character.isWhitespace(textContent.charAt(adjustedOffset)) ) {
98+
adjustedOffset++;
99+
}
100+
ASTNode nextNodeAfterWhitespaces = NodeFinder.perform(domUnit, adjustedOffset, 0);
101+
this.node = (nextNodeAfterWhitespaces.getLength() == 0 && nextNodeAfterWhitespaces.getParent() == currentNode)
102+
? nextNodeAfterWhitespaces
103+
: (previousNodeBeforeWhitespaces instanceof SimpleName || previousNodeBeforeWhitespaces instanceof StringLiteral || previousNodeBeforeWhitespaces instanceof CharacterLiteral || previousNodeBeforeWhitespaces instanceof NumberLiteral)
104+
? currentNode
105+
: previousNodeBeforeWhitespaces;
96106
this.expectedTypes = new ExpectedTypes(assistOptions, this.node, offset);
97107
this.token = tokenBefore(this.textContent).toCharArray();
98108
this.bindingsAcquirer = bindings::all;
@@ -329,6 +339,9 @@ public int getTokenEnd() {
329339
if (this.isJustAfterStringLiteral) {
330340
return -1;
331341
}
342+
if (this.node.getLength() == 0) { // recovered
343+
return this.offset - 1;
344+
}
332345
if (this.node instanceof SimpleName || this.node instanceof StringLiteral) {
333346
return this.node.getStartPosition() + this.node.getLength() - 1;
334347
}

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/codeassist/DOMCompletionEngine.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Deque;
2121
import java.util.HashMap;
2222
import java.util.HashSet;
23+
import java.util.LinkedHashSet;
2324
import java.util.LinkedList;
2425
import java.util.List;
2526
import java.util.Map;
@@ -1786,7 +1787,8 @@ public void complete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sour
17861787
}
17871788
}
17881789
if (context instanceof VariableDeclarationFragment vdf) {
1789-
if (this.toComplete.equals(vdf.getName())) {
1790+
if (this.toComplete.equals(vdf.getName())
1791+
|| this.toComplete.getLength() == 0 /* recovered */) {
17901792
ITypeBinding typeBinding = null;
17911793
if (vdf.getParent() instanceof VariableDeclarationStatement vds) {
17921794
typeBinding = vds.getType().resolveBinding();
@@ -2211,16 +2213,35 @@ private void suggestUndeclaredVariableNames(Block block, ITypeBinding typeBindin
22112213
}
22122214
}
22132215

2216+
private static boolean isCollection(ITypeBinding type) {
2217+
if (type == null) {
2218+
return false;
2219+
}
2220+
if (Collection.class.getName().equals(type.getErasure().getQualifiedName())) {
2221+
return true;
2222+
}
2223+
return isCollection(type.getSuperclass()) || Arrays.stream(type.getInterfaces()).anyMatch(DOMCompletionEngine::isCollection);
2224+
}
2225+
22142226
private void suggestVariableNamesForType(ITypeBinding typeBinding, Set<String> alreadySuggestedNames) {
22152227
if (typeBinding.isPrimitive() || typeBinding.isRecovered()) {
22162228
return;
22172229
}
2230+
Set<String> possibleNames = new LinkedHashSet<>();
22182231

2219-
String simpleName;
2232+
String simpleName = "";
2233+
boolean multiple = false;
22202234
if (typeBinding.isArray()) {
22212235
simpleName = typeBinding.getElementType().getName();
2236+
multiple = true;
2237+
} else if (typeBinding.isParameterizedType() && isCollection(typeBinding)) {
2238+
possibleNames.add(typeBinding.getErasure().getName().toLowerCase());
2239+
multiple = true;
2240+
if (typeBinding.getTypeArguments().length > 0) {
2241+
simpleName = typeBinding.getTypeArguments()[0].getErasure().getName();
2242+
}
22222243
} else {
2223-
simpleName = typeBinding.getName();
2244+
simpleName = typeBinding.getErasure().getName();
22242245
}
22252246

22262247
List<String> nameSegments = Stream.of(simpleName.split("(?=_)|(?<=_)")).flatMap(nameSegment -> Stream.of(nameSegment.split("(?<=[a-z0-9])(?=[A-Z])"))).filter(str -> !str.isEmpty()).toList();
@@ -2241,7 +2262,7 @@ private void suggestVariableNamesForType(ITypeBinding typeBinding, Set<String> a
22412262
for (int j = i + 1; j < nameSegments.size(); j++) {
22422263
variablePortionOfName.append(nameSegments.get(j));
22432264
}
2244-
if (typeBinding.isArray()) {
2265+
if (multiple) {
22452266
if (variablePortionOfName.toString().endsWith("s")) {
22462267
variablePortionOfName.append("es");
22472268
} else {
@@ -2265,7 +2286,6 @@ private void suggestVariableNamesForType(ITypeBinding typeBinding, Set<String> a
22652286
}
22662287
// there is always the implicit suffix of ""
22672288
suffixes.add("");
2268-
Set<String> possibleNames = new HashSet<>();
22692289
Map<String, Integer> additionalRelevances = new HashMap<>();
22702290
boolean firstPrefix = true;
22712291
boolean firstSuffix = true;
@@ -2374,7 +2394,7 @@ private void suggestVariableNamesForType(ITypeBinding typeBinding, Set<String> a
23742394
alreadySuggestedNames.add(possibleName);
23752395
CompletionProposal res = createProposal(CompletionProposal.VARIABLE_DECLARATION);
23762396

2377-
int additionalRelevance = additionalRelevances.get(possibleName);
2397+
int additionalRelevance = additionalRelevances.getOrDefault(possibleName, 0);
23782398
if (SourceVersion.isKeyword(possibleName)) {
23792399
possibleName += "1";
23802400
}
@@ -4075,14 +4095,6 @@ private boolean staticOnly() {
40754095
return false;
40764096
}
40774097

4078-
private String qualifiedTypeName(ITypeBinding typeBinding) {
4079-
if (typeBinding.isTypeVariable()) {
4080-
return typeBinding.getName();
4081-
} else {
4082-
return typeBinding.getQualifiedName();
4083-
}
4084-
}
4085-
40864098
private CompletionProposal toProposal(TypeNameMatch typeNameMatch) {
40874099
return toProposal(typeNameMatch.getType(), typeNameMatch.getAccessibility());
40884100
}

org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/codeassist/ExpectedTypes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ private LinkedHashSet<IMethodBinding> avaiableMethods(ITypeBinding typeBinding)
749749
public List<ITypeBinding> getExpectedTypes() {
750750
if (!this.isReady) {
751751
computeExpectedTypes();
752-
this.expectedTypes.removeIf(binding -> binding.isNullType());
752+
this.expectedTypes.removeIf(ITypeBinding::isNullType);
753753
this.isReady = true;
754754
}
755755
return new ArrayList<>(this.expectedTypes);

0 commit comments

Comments
 (0)