Bug 575631 - [content assist] missing static method proposals in conditional, before variable declaration
Summary: [content assist] missing static method proposals in conditional, before varia...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 4.20   Edit
Hardware: All All
: P3 normal with 1 vote (vote)
Target Milestone: 4.22 M2   Edit
Assignee: Stephan Herrmann CLA
QA Contact:
URL:
Whiteboard:
Keywords: regression
: 575422 576088 576573 (view as bug list)
Depends on:
Blocks: 575919 576781 576823
  Show dependency tree
 
Reported: 2021-08-26 03:02 EDT by Julian Honnen CLA
Modified: 2021-11-11 05:55 EST (History)
6 users (show)

See Also:


Attachments
code completion in a lambda initialized field works ok in 2021-03 (273.83 KB, image/png)
2021-10-18 00:35 EDT, Morgwai Kotarbinski CLA
no flags Details
code completion in a lambda initialized field works ok in 2021-03 (275.54 KB, image/png)
2021-10-18 00:42 EDT, Morgwai Kotarbinski CLA
no flags Details
code completion does not work in methods of anonymous classes in 2021-09 (206.48 KB, image/png)
2021-10-18 01:02 EDT, Morgwai Kotarbinski CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Julian Honnen CLA 2021-08-26 03:02:11 EDT
In the following example no proposals are shown:

	public static void staticMethod() {
		if (true) {
			LocalDateTime.now|
			Calendar calendar = Calendar.getInstance();
		}
	}

Tested in Version: 2021-09 (4.21)
Build id: I20210825-1800

worked in 4.19
Comment 1 Holger Voormann CLA 2021-09-19 08:20:34 EDT
I can reproduce this also in I20210917-1800 and also in the "else" branch (see 576088):

class missing_proposals_for_static_fields_and_methods {
	void sample(String foo) {
		if (foo == null) {
			System. // <- missing: "out", "getenv()", etc. (similar to bug 574267)
			System.out.println();
		} else {
			System. // <- missing: "out", "getenv()", etc. (similar to bug 574215)
			System.out.println();
		}
		System. // <- here content assist works fine
	}
}

The first location is the same location as in bug 574267 (missing templates), and the second location is as in bug 574215 (missing proposals for given parameter). Like the two mentioned bugs, it works as expected if the next token is a semicolon.
Comment 2 Holger Voormann CLA 2021-09-19 08:20:42 EDT
*** Bug 576088 has been marked as a duplicate of this bug. ***
Comment 3 Morgwai Kotarbinski CLA 2021-10-12 04:47:23 EDT
it fails in several types of blocks, not just IFs:
loops:


```
	public static void main(String[] args) {
		for (int i = 0; i < 32; i++) {
			System.out.
			System.out.println();
		}
	}
```
lambdas:


```
		Runnable r = () -> {
			System.out.
			System.out.println();
		}
```
and probably others...
Comment 4 Holger Voormann CLA 2021-10-12 05:00:33 EDT
(In reply to Piotr Morgwai Kotarbinski from comment #3)
> it fails in several types of blocks, not just IFs:
> ...
To my understanding, conditional blocks includes if block, for/while loops, etc., but lambdas have not yet mentioned. Good catch! Thanks.

As workaround, you can put a ";" after the position where you want to get the proposals.
Comment 5 Morgwai Kotarbinski CLA 2021-10-12 14:11:21 EDT
@Holger is there any additional info that I could possibly provide to help with this bug? In particular, it was suggested in bug 574338 comment 21 to provide some screenshots and debug info, but not sure if this is relevant to this one.
Please advise and I will be happy to help.
Comment 6 Stephan Herrmann CLA 2021-10-12 16:55:12 EDT
I can reproduce now, not sure what happened in bug 574338 comment 13.

I see now that the work done in bug 574215 and then bug 575032 is incomplete.

We need to do the full combinatorics of type & variable segments of a given qualified name.
Comment 7 Eclipse Genie CLA 2021-10-17 17:48:04 EDT
New Gerrit change created: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/186576
Comment 8 Stephan Herrmann CLA 2021-10-17 17:49:54 EDT
(In reply to Eclipse Genie from comment #7)
> New Gerrit change created:
> https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/186576

Covers comment 0 and comment 1 and the lambda case of comment 3, but the latter works only inside a method, not if 'r' is a field. But that's a completely different problem (technically) and very likely it has never worked before.
Comment 9 Morgwai Kotarbinski CLA 2021-10-18 00:35:43 EDT
Created attachment 287321 [details]
code completion in a lambda initialized field works ok in 2021-03

(In reply to Stephan Herrmann from comment #8)

the attached screenshot shows that code completion in a lambda initialized field works ok in 2021-03.
Comment 10 Morgwai Kotarbinski CLA 2021-10-18 00:36:18 EDT
(In reply to Stephan Herrmann from comment #8)
(...)
> latter works only inside a method, not if 'r' is a field. But that's a
> completely different problem (technically) and very likely it has never
> worked before.

so could we please have a link here to the issue that tracks this different problem?
Comment 11 Morgwai Kotarbinski CLA 2021-10-18 00:42:32 EDT
Created attachment 287322 [details]
code completion in a lambda initialized field works ok in 2021-03

one more screenshot showing lambda field initialization works ok in 2021-03, this time with another statement below just like in the original report and some indentation to make the whole code visible when taking a shot.
Comment 12 Morgwai Kotarbinski CLA 2021-10-18 01:02:02 EDT
Created attachment 287323 [details]
code completion does not work in methods of anonymous classes in 2021-09

also, please make sure to check *all* possible other block types before declaring it fixed. I've just noticed it doesn't work in methods of anonymous classes: see screenshot.
So far only try-catch-finally blocks seem to work correctly.
Comment 13 yong ma CLA 2021-10-20 02:19:19 EDT
*** Bug 576573 has been marked as a duplicate of this bug. ***
Comment 14 Stephan Herrmann CLA 2021-10-20 18:53:45 EDT
(In reply to Piotr Morgwai Kotarbinski from comment #11)
> Created attachment 287322 [details]
> code completion in a lambda initialized field works ok in 2021-03
> 
> one more screenshot showing lambda field initialization works ok in 2021-03,
> this time with another statement below just like in the original report and
> some indentation to make the whole code visible when taking a shot.

Thanks, I stand corrected.

Unfortunately that was another hard nut to crack, but I think I have a viable solution in https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/186576/1..2

Up until 2021-03 we stopped parsing at the cursor, which then required a bunch of tricks to still complete parsing of the lambda, otherwise the parse tree would remain utterly incomplete. Those tricks introduced infinite loops for certain code patterns, which obviously was an unacceptable state.

Since 2021-06 we continue parsing until the end of the method body (for methods) with yet a slightly different strategy for field initializers. As this was a huge change of strategy, it caused some regressions.

After 2021-09 cleaned up a bunch of regressions, we still had issues when the cursor (internally creating an empty identifier as the completion token) was immediately followed by another identifier, i.e., the current line and the next line would be combined into some illegal stuff. It seems inside method bodies we could cope with this but not inside a field initializer.

Patch set #2 of the gerrit now detects this situation and synthesizes either ';' or ',' to separate the construct left of the cursor from possibly unrelated stuff to the right, selecting the suitable among the two separators.

Working on this cluster of bugs revealed some more problems. One has been outsourced to bug 576781.

Also, in some cases things like "Thread.this", "Thread.super" were proposed even if no such instance is in scope. that parts is fixed by new method CompletionEngine.hasCompatibleEnclosing(Scope, ReferenceBinding). See also the change in CompletionTests.testStaticMembers1().

Conversely, in some tests we now get one more proposal, see change in CompletionTest3.testBug575397a and testBug575397c, viz. "Thread.class" etc. This is a consequence of the main fix from patch set #1 (to be documented soon).
Comment 15 Stephan Herrmann CLA 2021-10-20 19:06:02 EDT
(In reply to Piotr Morgwai Kotarbinski from comment #12)
> Created attachment 287323 [details]
> code completion does not work in methods of anonymous classes in 2021-09
> 
> also, please make sure to check *all* possible other block types before
> declaring it fixed. I've just noticed it doesn't work in methods of
> anonymous classes: see screenshot.
> So far only try-catch-finally blocks seem to work correctly.

I'm trying my best, by looking at things from a syntactical point of view, where all block *statements* are equal, only *expressions* containing a block have additional problems (anonymous classes & lambdas, perhaps switch-expressions?). I'll add your example with an anonymous class to our test suite.

It would be highly welcome if you pick up the proposed change and provide test cases for all situations that are not yet covered.

I *will* declare this bug fixed very soon (even if more problems will be found), for the simple reason to ship the bag of fixes we already have, so users can get them in the upcoming milestone 2 build. Remaining issues will be managed via the umbrella bug 575919.
Comment 16 Stephan Herrmann CLA 2021-10-21 10:42:16 EDT
@Gayan, since you are working on related topics, may I ask you for some quick comments?

I'll have to adjust some completion parser tests, I made these changes for one test class as you can see in https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/186576/2..3/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/AllocationExpressionCompletionTest.java

Do you see any interference with your ongoing work? The common theme in those tests is to complete in "somewords(1, 2,| i);". Previously it would count as completing the enclosing invocation, whereas with may changes the parser will see a synthetic ',' and simply try to complete the empty identifier in "somewords(1, 2, <CompleteOnName:>, i);". I believe the old behavior was a result of a spurious syntax error (when completion identifier and constant '1' clash with no separator) and way of parsing will result in better proposals (see also comment 14).

In order to preserve existing tests as much as possible, I duplicated tests into (a) a variant completing right after '(' which comes close to the original expectation, and another variant where only test expectations have been updated.

If you see no objections here, I would update remaining tests and merge this later today in order to include the fixes in M2.

Other explanations & questions to follow in separate comments :)
Comment 17 Stephan Herrmann CLA 2021-10-21 10:54:45 EDT
Explaining the initial fix from patch set #1 (https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/186576/1/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java):

In the presence of syntax errors (the norm during comletion) and for technical reasons the parser has a bias towards creating a CompletionOnQualifiedTypeReference (as start of an assumed local variable declaration), where in some cases the user actually wants to create an expression (otherwise represented as CompletionOnQualifiedNameReference, which can swing both ways).

Rather than bloating handling of CompletionOnQualifiedTypeReference, I extracted the general part of QualifiedNameReference-completion and made completionOnQualifiedTypeReference() conditionally branch into the extracted method. Thus we are adding all proposals that would be given for a CompletionOnQualifiedNameReference.

This comparably small change allowed me to discard tweaks from Bug 574215, Bug 575032 and Bug 575397 :) while achieving more completeness.
Comment 18 Gayan Perera CLA 2021-10-21 13:24:49 EDT
(In reply to Stephan Herrmann from comment #16)
> @Gayan, since you are working on related topics, may I ask you for some
> quick comments?
> 
@Stephan currently i have no remaining patches on something similar to this. There is one at https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/184001. But i think we found a quick fix and we open a different issue to improve it further. So i think the mentioned gerrit can be removed.

You can go ahead Stephan. The lambda completion support patches are already in master.
Comment 19 Stephan Herrmann CLA 2021-10-21 14:36:36 EDT
(In reply to Gayan Perera from comment #18)
> (In reply to Stephan Herrmann from comment #16)
> > @Gayan, since you are working on related topics, may I ask you for some
> > quick comments?
> > 
> @Stephan currently i have no remaining patches on something similar to this.
> There is one at https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/184001.
> But i think we found a quick fix and we open a different issue to improve it
> further. So i think the mentioned gerrit can be removed.

Thanks for reminding me. Looking again at bug 575397 I found one more trace that is no longer needed with this new patch :)
Comment 20 Stephan Herrmann CLA 2021-10-21 14:45:54 EDT
*** Bug 575422 has been marked as a duplicate of this bug. ***
Comment 22 Stephan Herrmann CLA 2021-10-21 15:16:22 EDT
(In reply to Eclipse Genie from comment #21)
> Gerrit change https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/186576 was
> merged to [master].
> Commit:
> http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/
> ?id=ce59f244f3c0c78d1953b77e8d3652368d985c3a

This is a combined fix for comment 0, comment 1 and comment 3.

The fix will be available in 4.22 M2.

If problems in similar situations can still be observed with that fix, please file a new bug. Thanks.

Some additional problems are already recorded as bug 576781 and bug 576823.
Comment 23 Jay Arthanareeswaran CLA 2021-11-11 05:55:57 EST
Verified for 4.22 M3 using build I20211110-1800