Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faulty Content Assist Within Blocks #21

Open
HeikoKlare opened this issue Nov 9, 2023 · 2 comments
Open

Faulty Content Assist Within Blocks #21

HeikoKlare opened this issue Nov 9, 2023 · 2 comments
Labels
Bug A Derivation of Expected Behavior JDT Issues for JDT

Comments

@HeikoKlare
Copy link
Contributor

HeikoKlare commented Nov 9, 2023

Issue: eclipse-jdt/eclipse.jdt.core#1770

Current Behavior

Under specific conditions, content assist provides proposals as expected in the context. Consider the following code:

public boolean doIt() {
	while (true) {
		Integer i = 0;
		i.
		((Object)i).getClass();	
	}
}

Opening auto-completion proposal after the i. does not provide content assist for i but for its context:

Image

The conditions for this problems I found so far are as follows:

  • Be inside a block, such as a condition block or a loop block
  • The line after the incomplete line, in which content assist shall be used, starts with a cast

Expected Behavior

The content assist should provide the methods of i as proposals, same as when one of the conditions above is not fulfilled. For example:

public boolean doIt() {
	Integer i = 0;
	i.
	((Object)i).getClass();	
}

shows:

Image

@HeikoKlare HeikoKlare added Bug A Derivation of Expected Behavior JDT Issues for JDT labels Nov 9, 2023
@amartya4256 amartya4256 self-assigned this Dec 14, 2023
@amartya4256
Copy link

amartya4256 commented Dec 19, 2023

Did a lot of research over this topic. Came across a few interesting things:

  • The vaariable inside a while or if block is parsed as an AST Node of type CompletionOnMessageSendName while the other variable which is not inside any block is computed as a CompletionOnQualifiedNameReference.
  • The difference starts inside the parser (Parser.java) which uses a method consumeRule(act) which creates CompletionOnMessageSendName because of the value of act being 607 while the other has a value of 619.
  • these 2 codes in the switch/case of consumeRule method produce 2 different kinds of nodes.
  • Later, these nodes throw a CompletionNodeFound exception wrapping their scope and the astNode in the exception in CompletionEngine.java, where the information of the scope and the node type is used to generate codeComplete Proposals.

What I tried doing:

  • in the case 607, the changed the method consumeMethodInvocationName to consumePostfixExpression, which is also used for 619.
  • I get the right recommendations for the variable in the block after this change. However, the chnage of the method in the case 607 makes the other part of the code behave differently.
  • Seems like the TypeBinding (SingleVariableBinding) is not present in the ASTNode, which is need for the propsals. I tried adding binding manually but there's some cast checks which doesn't allow this kind of binding for the object of type CompletionOnMessageSendName.

The twist in the plot

  • I realized that if we don't have the line ((Object) i).getClass(); following the line "i.", it gives the right proposals. On debugging, I found out that without the following line, the parse parses i.((Object) i) as CompletionOnQualifiedNameReference<i.()> node.

Conclusion:
Hence we can conclude that there is something wrong with the parser and it should not be parsing it as a CompletionOnMessageSendName but CompletionOnQualifiedNameReference.

@amartya4256
Copy link

amartya4256 commented Dec 19, 2023

Another Observation is that when we have a type cast in the following statement followed by a method call, this issue is specific to that case. On printing the scanner in 2 cases, it looks like this:

  1. When we have a following statement which satisfies the condition mentioned above:
public boolean doItFaulty() {
		while (true) {
			Integer k = 0;
			k.
			((Object)k)
===============================
Starts here -->.<-- Ends here
===============================
getClass();	
		}
  1. When there's no satatement as mentioned:
public boolean doItFaulty() {
		while (true) {
			Integer k = 0;
			k.
//			((Object)k).getClass();	
		
===============================
Starts here -->}<-- Ends here
===============================

In other words, the parser parses for the following statements:

k.
((Integer)k).getClass();

as:

<CompleteOnMessageSendName:k.()>.getClass()

@amartya4256 amartya4256 removed their assignment Dec 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A Derivation of Expected Behavior JDT Issues for JDT
Projects
Status: 🔖 Ready: Atomic
Development

No branches or pull requests

2 participants