Skip to content

Commit

Permalink
More fixes for field access
Browse files Browse the repository at this point in the history
- Fix completion issue with `myVariable.|\nMyObj asdf = null;`
- Fix for `myTarget.|` completion

Signed-off-by: David Thompson <[email protected]>
  • Loading branch information
datho7561 committed Nov 4, 2024
1 parent fb63609 commit 7491ef5
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,31 @@ public IJavaElement getEnclosingElement() {
@Override
public IJavaElement[] getVisibleElements(String typeSignature) {
return this.bindingsAcquirer.get() //
.filter(binding -> {
if (typeSignature == null) {
return binding instanceof IVariableBinding || binding instanceof IMethodBinding;
}
if (binding instanceof IVariableBinding variableBinding) {
return castCompatable(variableBinding.getType(),
typeSignature);
} else if (binding instanceof IMethodBinding methodBinding) {
return castCompatable(methodBinding.getReturnType(),
typeSignature);
}
// notably, ITypeBinding is not used to complete values,
// even, for instance, in the case that a `java.lang.Class<?>` is desired.
return false;
}) //
.filter(binding -> matchesSignature(binding, typeSignature)) //
.map(binding -> binding.getJavaElement()) //
.filter(obj -> obj != null) // eg. ArrayList.getFirst() when working with a Java 8 project
.toArray(IJavaElement[]::new);
}

/// Checks if the binding matches the given type signature
/// TODO: this should probably live in a helper method/utils class,
/// along with `castCompatable`
public static boolean matchesSignature(IBinding binding, String typeSignature) {
if (typeSignature == null) {
return binding instanceof IVariableBinding || binding instanceof IMethodBinding;
}
if (binding instanceof IVariableBinding variableBinding) {
return castCompatable(variableBinding.getType(),
typeSignature);
} else if (binding instanceof IMethodBinding methodBinding) {
return castCompatable(methodBinding.getReturnType(),
typeSignature);
}
// notably, ITypeBinding is not used to complete values,
// even, for instance, in the case that a `java.lang.Class<?>` is desired.
return false;
}

@Override
public char[][] getExpectedTypesKeys() {
return this.expectedTypes.getExpectedTypes().stream() //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,20 @@ public void run() {
if (!FAKE_IDENTIFIER.equals(simpleName.getIdentifier())) {
completeAfter = simpleName.getIdentifier().substring(0, simpleName.getIdentifier().length() <= charCount ? simpleName.getIdentifier().length() : charCount);
}
try {
IBuffer cuBuffer = this.modelUnit.getBuffer();
if (cuBuffer.getChar(this.offset - 1) == '.') {
completeAfter = ""; //$NON-NLS-1$
}
} catch (JavaModelException e) {
ILog.get().error("error while trying to read buffer for completion purposes", e); //$NON-NLS-1$
}
if (simpleName.getParent() instanceof FieldAccess || simpleName.getParent() instanceof MethodInvocation
|| simpleName.getParent() instanceof VariableDeclaration || simpleName.getParent() instanceof QualifiedName
|| simpleName.getParent() instanceof SuperFieldAccess) {
context = this.toComplete.getParent();
if (!this.toComplete.getLocationInParent().getId().equals(QualifiedName.QUALIFIER_PROPERTY.getId())) {
context = this.toComplete.getParent();
}
}
if (simpleName.getParent() instanceof SimpleType simpleType && (simpleType.getParent() instanceof ClassInstanceCreation)) {
context = simpleName.getParent().getParent();
Expand All @@ -246,6 +256,8 @@ public void run() {
context = this.toComplete.getParent();
} else if (this.toComplete instanceof FieldAccess fieldAccess) {
completeAfter = fieldAccess.getName().toString();
} else if (this.toComplete instanceof MethodInvocation methodInvocation) {
completeAfter = methodInvocation.getName().toString();
}
this.prefix = completeAfter;
this.qualifiedPrefix = this.prefix;
Expand Down Expand Up @@ -309,7 +321,6 @@ public void run() {
}
suggestDefaultCompletions = false;
}
// else complete parameters, get back to default
}
if (context instanceof VariableDeclaration declaration) {
var binding = declaration.resolveBinding();
Expand Down Expand Up @@ -347,6 +358,30 @@ public void run() {
if (context.getParent() instanceof MethodDeclaration) {
suggestDefaultCompletions = false;
}
if (context.getLocationInParent().getId().equals(QualifiedName.QUALIFIER_PROPERTY.getId()) && context.getParent() instanceof QualifiedName) {
// eg.
// void myMethod() {
// String myVariable = "hello, mom";
// myVariable.|
// Object myObj = null;
// }
// It thinks that our variable is a package or some other type. We know that it's a variable.
// Search the scope for the right binding
IBinding incorrectBinding = ((SimpleName) context).resolveBinding();
Bindings localBindings = new Bindings();
scrapeAccessibleBindings(localBindings);
Optional<IVariableBinding> realBinding = localBindings.stream() //
.filter(IVariableBinding.class::isInstance)
.map(IVariableBinding.class::cast)
.filter(varBind -> varBind.getName().equals(incorrectBinding.getName()))
.findFirst();
if (realBinding.isPresent()) {
processMembers(context, realBinding.get().getType(), specificCompletionBindings, false);
this.prefix = ""; //$NON-NLS-1$
publishFromScope(specificCompletionBindings);
suggestDefaultCompletions = false;
}
}
}
if (context instanceof AbstractTypeDeclaration typeDecl) {
try {
Expand Down Expand Up @@ -991,7 +1026,7 @@ private void processMembers(ASTNode referencedFrom, ITypeBinding typeBinding, Bi
} else {
includeProtected = findInSupers(referencedFromBinding, typeBinding);
}
processMembers(typeBinding, scope, includePrivate, includeProtected, referencedFromBinding.getPackage().getKey(), isStaticContext, false,
processMembers(typeBinding, scope, includePrivate, includeProtected, referencedFromBinding.getPackage().getKey(), isStaticContext, typeBinding.isInterface(),
new HashSet<>(), new HashSet<>());
}

Expand Down Expand Up @@ -1176,7 +1211,7 @@ private CompletionProposal toProposal(IBinding binding, String completion) {
res.setReceiverSignature(new char[] {});
res.setDeclarationSignature(new char[] {});
}
res.setReplaceRange(this.toComplete instanceof SimpleName ? this.toComplete.getStartPosition() : this.offset,
res.setReplaceRange(this.toComplete instanceof SimpleName && !this.toComplete.getLocationInParent().getId().equals(QualifiedName.QUALIFIER_PROPERTY.getId()) && !this.prefix.isEmpty() ? this.toComplete.getStartPosition() : this.offset,
DOMCompletionEngine.this.offset);
var element = binding.getJavaElement();
if (element != null) {
Expand Down

0 comments on commit 7491ef5

Please sign in to comment.