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

ClassCastException when ctrl+hover over a 'case' literal #1764

Open
nlisker opened this issue Nov 2, 2024 · 13 comments · Fixed by #1768
Open

ClassCastException when ctrl+hover over a 'case' literal #1764

nlisker opened this issue Nov 2, 2024 · 13 comments · Fixed by #1768
Assignees
Milestone

Comments

@nlisker
Copy link

nlisker commented Nov 2, 2024

public class Hover {

	void do2() {
		record R(int i, long l) {}

		R r = new R(1, 1);
		switch (r) {
			case R(_, long l) -> {}
			case R r2 -> {}
		}
	}
}

Hold Ctrl and hover over the second case literal. The case will become clickable as if it's a method or parameter, which is wrong. Then, while still holding Ctrl, move the mouse to the first case label. A bunch of these errors will be thrown:

Unhandled event loop exception

java.lang.ClassCastException: class org.eclipse.jdt.core.dom.VariableDeclarationFragment cannot be cast to class org.eclipse.jdt.core.dom.SingleVariableDeclaration (org.eclipse.jdt.core.dom.VariableDeclarationFragment and org.eclipse.jdt.core.dom.SingleVariableDeclaration are in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @17a0846)
	at org.eclipse.jdt.core.dom.TypePattern.getPatternVariable(TypePattern.java:242)
	at org.eclipse.jdt.internal.corext.dom.ASTFlattener.visit(ASTFlattener.java:2021)
	at org.eclipse.jdt.internal.corext.dom.ASTFlattener.visitPattern(ASTFlattener.java:1451)
	at org.eclipse.jdt.internal.corext.dom.ASTFlattener.visit(ASTFlattener.java:1427)
	at org.eclipse.jdt.core.dom.RecordPattern.accept0(RecordPattern.java:231)
	at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:3312)
	at org.eclipse.jdt.internal.corext.dom.ASTFlattener.visit(ASTFlattener.java:1669)
	at org.eclipse.jdt.core.dom.SwitchCase.accept0(SwitchCase.java:212)
	at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:3312)
	at org.eclipse.jdt.internal.corext.dom.ASTNodes.asString(ASTNodes.java:366)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlinkDetector.findSwitchCaseTarget(JavaElementHyperlinkDetector.java:290)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlinkDetector.detectHyperlinksCached(JavaElementHyperlinkDetector.java:116)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlinkDetector.lambda$0(JavaElementHyperlinkDetector.java:84)
	at org.eclipse.jdt.internal.core.JavaModelManager.cacheZipFiles(JavaModelManager.java:5694)
	at org.eclipse.jdt.internal.core.JavaModelManager.callReadOnly(JavaModelManager.java:5683)
	at org.eclipse.jdt.core.JavaCore.callReadOnly(JavaCore.java:6150)
	at org.eclipse.jdt.internal.ui.javaeditor.JavaElementHyperlinkDetector.detectHyperlinks(JavaElementHyperlinkDetector.java:84)
	at org.eclipse.ui.texteditor.HyperlinkDetectorRegistry$HyperlinkDetectorDelegate.detectHyperlinks(HyperlinkDetectorRegistry.java:81)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.findHyperlinks(HyperlinkManager.java:289)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.findHyperlinks(HyperlinkManager.java:262)
	at org.eclipse.jface.text.hyperlink.HyperlinkManager.mouseMove(HyperlinkManager.java:457)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:229)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4368)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1173)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4166)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3754)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1151)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1042)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:663)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:570)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:178)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:208)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:143)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:109)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:439)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:271)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:668)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:605)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1481)

From the stack trace, I'm not sure if this is a bug in jdt.core or jdt.ui, but the exception itself happens in core.

eclipse.buildId=4.34.0.I20241101-1800
java.version=22
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_US

@srikanth-sankaran
Copy link

@subyssurendran666 would you like to work on this ?

@subyssurendran666
Copy link

With pleasure! Could you please assign this to me?

@subyssurendran666 would you like to work on this ?

@subyssurendran666
Copy link

I believe this issue is related to JDT.UI

In Java 22, a new feature called unnamed variables and patterns has been introduced. To accommodate this, certain changes have been incorporated into JDT.Core. For example, in a case literal like case R(_, long l) -> {}, the first parameter of the record is an unnamed pattern (_). In JDT.Core DOM, unnamed patterns are handled by TypePattern. Here, the PatternVariable of the TypePattern is a VariableDeclarationFragment (since it has no type). However, the visit method in ASTFlattener attempts to cast the patternVariable to SingleVariableDeclaration through getPatternVariable(), which is applicable only for Java version below 22.

Screenshot 2024-11-03 at 11 52 29 PM

This issue has been addressed by implementing a new method called getPatternVariable2(). I believe the code below, or a similar approach, should resolve the issue.

 public boolean visit(TypePattern node) {
		if (ASTHelper.isPatternSupported(node.getAST())) {
                         if (node.getAST().apiLevel() < ASTHelper.JLS22) {
			    node.getPatternVariable().accept(this);
                         } else {
                              node.getPatternVariable2().accept(this);
                         }
		}
		return false;
}

@nlisker
Copy link
Author

nlisker commented Nov 4, 2024

So should this be transferred to jdt.ui?

@srikanth-sankaran
Copy link

@subyssurendran666 - the code you cite is in jdt-core, no ?

@subyssurendran666
Copy link

No @srikanth-sankaran, the ASTFlattener(which is in JDT.UI) is calling the getPatternVariable() API from the DOM.

@srikanth-sankaran srikanth-sankaran transferred this issue from eclipse-jdt/eclipse.jdt.core Nov 4, 2024
@srikanth-sankaran
Copy link

@noopur2507 - Can you confirm this is a JDT.UI problem ? TIA

@noopur2507
Copy link
Member

Hold Ctrl and hover over the second case literal. The case will become clickable as if it's a method or parameter, which is wrong.

The 'case' becoming clickable is a feature that allows you to click the 'case' to jump to the corresponding 'switch' keyword. This is useful for quickly jumping to the beginning of a long switch-case.

Then, while still holding Ctrl, move the mouse to the first case label. A bunch of these errors will be thrown:

To be fixed.

@noopur2507
Copy link
Member

I believe this issue is related to JDT.UI

Thanks for the analysis, Suby. I will make the corresponding change in UI.

However, few changes are required in JDT Core as well:

  • The Javadoc of both APIs i.e. TypePattern.getPatternVariable() and TypePattern.getPatternVariable2() is same and not clear regarding this difference.
  • The methods in JDT UI's ASTFlattener are kept in sync with JDT Core's org.eclipse.jdt.internal.core.dom.NaiveASTFlattener. Hence, the change should be done in NaiveASTFlattener as well and then synced to ASTFlattener.

@subyssurendran666
Copy link

I believe this issue is related to JDT.UI

Thanks for the analysis, Suby. I will make the corresponding change in UI.

However, few changes are required in JDT Core as well:

  • The Javadoc of both APIs i.e. TypePattern.getPatternVariable() and TypePattern.getPatternVariable2() is same and not clear regarding this difference.
  • The methods in JDT UI's ASTFlattener are kept in sync with JDT Core's org.eclipse.jdt.internal.core.dom.NaiveASTFlattener. Hence, the change should be done in NaiveASTFlattener as well and then synced to ASTFlattener.

Thank you, @noopur2507 for your insights on JDT.Core. I'll make the necessary arrangements in JDT.Core.

@nlisker
Copy link
Author

nlisker commented Nov 6, 2024

The 'case' becoming clickable is a feature that allows you to click the 'case' to jump to the corresponding 'switch' keyword. This is useful for quickly jumping to the beginning of a long switch-case.

What an interesting feature. Didn't know about it.

jukzi pushed a commit to jukzi/eclipse.jdt.ui that referenced this issue Nov 6, 2024
Should help on errors where they showed up in the logfile but the
context is unclear like:

eclipse-jdt/eclipse.jdt.core#3262
eclipse-jdt/eclipse.jdt.core#2934
eclipse-jdt#1764
jukzi pushed a commit to jukzi/eclipse.jdt.ui that referenced this issue Nov 6, 2024
Should help on errors where they showed up in the logfile but the
context is unclear like:

eclipse-jdt/eclipse.jdt.core#3262
eclipse-jdt/eclipse.jdt.core#2934
eclipse-jdt#1764
jukzi pushed a commit to jukzi/eclipse.jdt.ui that referenced this issue Nov 7, 2024
Should help on errors where they showed up in the logfile but the
context is unclear like:

eclipse-jdt/eclipse.jdt.core#3262
eclipse-jdt/eclipse.jdt.core#2934
eclipse-jdt#1764
@noopur2507 noopur2507 added this to the 4.34 M3 milestone Nov 8, 2024
jukzi pushed a commit to jukzi/eclipse.jdt.ui that referenced this issue Nov 8, 2024
jukzi pushed a commit that referenced this issue Nov 8, 2024
noopur2507 pushed a commit that referenced this issue Nov 27, 2024
@subyssurendran666
Copy link

I believe this issue is related to JDT.UI

Thanks for the analysis, Suby. I will make the corresponding change in UI.

However, few changes are required in JDT Core as well:

  • The Javadoc of both APIs i.e. TypePattern.getPatternVariable() and TypePattern.getPatternVariable2() is same and not clear regarding this difference.
  • The methods in JDT UI's ASTFlattener are kept in sync with JDT Core's org.eclipse.jdt.internal.core.dom.NaiveASTFlattener. Hence, the change should be done in NaiveASTFlattener as well and then synced to ASTFlattener.

@noopur2507 this has been implemented though eclipse-jdt/eclipse.jdt.core#3261

@iloveeclipse
Copy link
Member

Reopening, after the change was reverted via eclipse-jdt/eclipse.jdt.core#3529

@iloveeclipse iloveeclipse reopened this Jan 7, 2025
@iloveeclipse iloveeclipse modified the milestones: 4.34 M3, 4.35 Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants