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

Casted receiver completion with inline comment results in string index OOBE #3740

Open
datho7561 opened this issue Feb 14, 2025 · 0 comments
Labels
bug Something isn't working

Comments

@datho7561
Copy link
Contributor

datho7561 commented Feb 14, 2025

According to this test case: CompletionTests.testCompletionAfterInstanceof19, opening completion at the | and accepting myField:

public class DemoClass  {
	int myField = 12;
	public void myMethod() {
		Object obj = new Object();
		if (obj instanceof DemoClass) {
			obj /* obj is definitely a DemoClass */ . myF`|`
		}
	}
}

should result in

public class DemoClass  {
	int myField = 12;
	public void myMethod() {
		Object obj = new Object();
		if (obj instanceof DemoClass) {
			((DemoClass)obj) /* obj is definitely a DemoClass */ . myField
		}
	}
}

However, instead I get the following stacktrace:

Stacktrace with a StringIndexOutOfBoundsException

!ENTRY org.eclipse.jdt.ui 4 0 2025-02-14 15:25:05.278
!MESSAGE Error retrieving proposal text.
Display string:
myField : int - DemoClass
Pattern:
obj /* obj is definitely a DemoClass */ . myF
!STACK 0
java.lang.StringIndexOutOfBoundsException: Range [0, 45) out of bounds for length 25
	at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
	at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
	at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
	at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:112)
	at java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:349)
	at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4865)
	at java.base/java.lang.String.substring(String.java:2834)
	at org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.getPatternMatchRule(AbstractJavaCompletionProposal.java:928)
	at org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.getStyledDisplayString(AbstractJavaCompletionProposal.java:1258)
	at org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposal.getStyledDisplayString(JavaCompletionProposal.java:186)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.handleSetData(CompletionProposalPopup.java:879)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5857)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1652)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1678)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1661)
	at org.eclipse.swt.widgets.Table.checkData(Table.java:289)
	at org.eclipse.swt.widgets.Table.cellDataProc(Table.java:227)
	at org.eclipse.swt.widgets.Display.cellDataProc(Display.java:995)
	at org.eclipse.swt.internal.gtk.GTK.gtk_tree_view_column_cell_set_cell_data(Native Method)
	at org.eclipse.swt.widgets.Table.getItemHeightInPixels(Table.java:1689)
	at org.eclipse.swt.widgets.Table.getItemHeight(Table.java:1660)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.getMinimalHeight(CompletionProposalPopup.java:720)
	at org.eclipse.jface.text.contentassist.ContentAssistant$LayoutManager.computeBoundsBelowAbove(ContentAssistant.java:705)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.getLocation(CompletionProposalPopup.java:1207)
	at org.eclipse.jface.text.contentassist.CompletionProposalPopup.setProposals(CompletionProposalPopup.java:1192)
	at org.eclipse.jface.text.contentassist.AsyncCompletionProposalPopup.computeAndPopulateProposals(AsyncCompletionProposalPopup.java:221)
	at org.eclipse.jface.text.contentassist.AsyncCompletionProposalPopup.showProposals(AsyncCompletionProposalPopup.java:172)
	at org.eclipse.jface.text.contentassist.ContentAssistant.showPossibleCompletions(ContentAssistant.java:1874)
	at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer.doOperation(CompilationUnitEditor.java:189)
	at org.eclipse.ui.texteditor.ContentAssistAction.lambda$0(ContentAssistAction.java:85)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:67)
	at org.eclipse.ui.texteditor.ContentAssistAction.run(ContentAssistAction.java:84)
	at org.eclipse.ui.texteditor.RetargetTextEditorAction.run(RetargetTextEditorAction.java:232)
	at org.eclipse.jface.action.Action.runWithEvent(Action.java:474)
	at org.eclipse.jface.commands.ActionHandler.execute(ActionHandler.java:124)
	at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:98)
	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.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:299)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:233)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:174)
	at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:165)
	at org.eclipse.core.commands.Command.executeWithChecks(Command.java:488)
	at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:485)
	at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:204)
	at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.executeCommand(KeyBindingDispatcher.java:308)
	at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.press(KeyBindingDispatcher.java:569)
	at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.processKeyEvent(KeyBindingDispatcher.java:644)
	at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher.filterKeySequenceBindings(KeyBindingDispatcher.java:439)
	at org.eclipse.e4.ui.bindings.keys.KeyBindingDispatcher$KeyDownFilter.handleEvent(KeyBindingDispatcher.java:96)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1956)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1651)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1678)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1661)
	at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1700)
	at org.eclipse.swt.widgets.Widget.gtk_key_press_event(Widget.java:996)
	at org.eclipse.swt.widgets.Control.gtk_key_press_event(Control.java:3999)
	at org.eclipse.swt.widgets.Composite.gtk_key_press_event(Composite.java:931)
	at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2630)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:6842)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:6164)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_do_event(Native Method)
	at org.eclipse.swt.widgets.Display.eventProc(Display.java:1600)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_iteration_do(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4516)
	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:668)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:576)
	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:149)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
	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)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1454)

The stacktrace goes through jdt.ui. I think the root cause is that the receiver range ends after obj instead of at the ., and the jdt.ui code to calculate the display string gets tripped up by this. I think this could be resolved in jdt.core by adjusting the receiver range to include everything up to but excluding the ., but perhaps it's better to fix in jdt.ui?

datho7561 added a commit to datho7561/eclipse.jdt.core that referenced this issue Feb 14, 2025
eg.

```java
if (node instanceof MethodDeclaration) {
  node.getB|
}
```

completes to

```java
if (node instanceof MethodDeclaration) {
  ((MethodDeclaration)node).getBody()|
}
```

Fixes # 1242

I also took liberty in implementing/fixing:
- eclipse-jdt#3738
- eclipse-jdt#3737
- eclipse-jdt#3739
- eclipse-jdt#3740
- Overall doing a bit more flow analysis to suggest this completion in more cases

Overall, this causes two regressions which are related to limitations in
how JDT handles this type of completion.

Signed-off-by: David Thompson <[email protected]>
@jukzi jukzi added the bug Something isn't working label Feb 18, 2025
datho7561 added a commit to datho7561/eclipse.jdt.core that referenced this issue Feb 18, 2025
eg.

```java
if (node instanceof MethodDeclaration) {
  node.getB|
}
```

completes to

```java
if (node instanceof MethodDeclaration) {
  ((MethodDeclaration)node).getBody()|
}
```

Fixes # 1242

I also took liberty in implementing/fixing:
- eclipse-jdt#3738
- eclipse-jdt#3737
- eclipse-jdt#3739
- eclipse-jdt#3740
- Overall doing a bit more flow analysis to suggest this completion in more cases

Overall, this causes two regressions which are related to limitations in
how JDT handles this type of completion.

Signed-off-by: David Thompson <[email protected]>
datho7561 added a commit to eclipse-jdtls/eclipse-jdt-core-incubator that referenced this issue Feb 18, 2025
eg.

```java
if (node instanceof MethodDeclaration) {
  node.getB|
}
```

completes to

```java
if (node instanceof MethodDeclaration) {
  ((MethodDeclaration)node).getBody()|
}
```

Fixes # 1242

I also took liberty in implementing/fixing:
- eclipse-jdt#3738
- eclipse-jdt#3737
- eclipse-jdt#3739
- eclipse-jdt#3740
- Overall doing a bit more flow analysis to suggest this completion in more cases

Overall, this causes two regressions which are related to limitations in
how JDT handles this type of completion.

Signed-off-by: David Thompson <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants