Bug 489107 - StringIndexOutOfBoundsException below LazyGenericTypeProposal.shouldAppendArguments
Summary: StringIndexOutOfBoundsException below LazyGenericTypeProposal.shouldAppendArg...
Status: CLOSED WORKSFORME
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.5   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 4.10 RC1   Edit
Assignee: Stephan Herrmann CLA
QA Contact:
URL:
Whiteboard: stalebug
Keywords: needinfo
Depends on:
Blocks:
 
Reported: 2016-03-07 00:00 EST by EPP Error Reports CLA
Modified: 2018-11-27 17:55 EST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description EPP Error Reports CLA 2016-03-07 00:00:01 EST
The following incident was reported via the automated error reporting:


    code:                   0
    plugin:                 org.eclipse.ui_3.107.0.v20150507-1945
    message:                Unhandled event loop exception
    fingerprint:            52699c27
    exception class:        java.lang.StringIndexOutOfBoundsException
    exception message:      String index out of range: 35
    number of children:     0
    
    java.lang.StringIndexOutOfBoundsException: String index out of range: 35
    at java.lang.String.charAt(null:-1)[REQUIRED, TOPMOST]
    at org.eclipse.jdt.internal.ui.text.java.LazyGenericTypeProposal.shouldAppendArguments(LazyGenericTypeProposal.java:670)[REQUIRED]
    at org.eclipse.jdt.internal.ui.text.java.LazyGenericTypeProposal.apply(LazyGenericTypeProposal.java:219)
    at org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.apply(AbstractJavaCompletionProposal.java:326)
    at org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.apply(AbstractJavaCompletionProposal.java:341)
    at org.eclipse.jdt.internal.ui.text.java.JavaMethodCompletionProposal.apply(JavaMethodCompletionProposal.java:58)
    at org.eclipse.recommenders.completion.rcp.processable.ProcessableParameterGuessingProposal.apply(ProcessableParameterGuessingProposal.java:172)[REQUIRED]
    at org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal.apply(AbstractJavaCompletionProposal.java:504)
    at org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal.apply(LazyJavaCompletionProposal.java:489)
    at org.eclipse.jface.text.contentassist.CompletionProposalPopup.insertProposal(CompletionProposalPopup.java:963)
    at org.eclipse.jface.text.contentassist.CompletionProposalPopup.insertSelectedProposalWithMask(CompletionProposalPopup.java:914)
    at org.eclipse.jface.text.contentassist.CompletionProposalPopup.verifyKey(CompletionProposalPopup.java:1358)
    at org.eclipse.jface.text.contentassist.ContentAssistant$InternalListener.verifyKey(ContentAssistant.java:814)
    at org.eclipse.jface.text.TextViewer$VerifyKeyListenersManager.verifyKey(TextViewer.java:493)
    at org.eclipse.swt.custom.StyledTextListener.handleEvent(StyledTextListener.java:66)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4362)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1113)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1137)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1122)
    at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:788)
    at org.eclipse.swt.custom.StyledText.handleKeyDown(StyledText.java:5990)
    at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5682)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4362)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1113)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1137)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1122)
    at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1164)
    at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1160)
    at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1581)
    at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4781)
    at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:343)
    at org.eclipse.swt.widgets.Control.windowProc(Control.java:4662)
    at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:339)
    at org.eclipse.swt.widgets.Display.windowProc(Display.java:5050)
    at org.eclipse.swt.internal.win32.OS.DispatchMessageW(OS.java:-2)
    at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2549)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3767)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$4.run(PartRenderingEngine.java:1127)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
    at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1018)
    at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:156)
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:654)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:337)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:598)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:139)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:380)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:235)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(null:-2)
    at sun.reflect.NativeMethodAccessorImpl.invoke(null:-1)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(null:-1)
    at java.lang.reflect.Method.invoke(null:-1)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:669)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:608)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1515)
   
  

General Information:

    reported-by:      
    anonymous-id:     25f19b00-0fdc-401b-8051-4765c9c1240b
    eclipse-build-id: 4.5.0.I20150603-2000
    eclipse-product:  org.eclipse.epp.package.java.product
    operating system: Windows8 6.2.0 (x86_64) - win32
    jre-version:      1.8.0_51-b16

The following plug-ins were present on the execution stack (*):
    1. org.eclipse.core.databinding.observable_1.5.0.v20150422-0725
    2. org.eclipse.core.databinding_1.5.0.v20150422-0725
    3. org.eclipse.core.runtime_3.11.0.v20150405-1723
    4. org.eclipse.e4.ui.workbench_1.3.0.v20150531-1948
    5. org.eclipse.e4.ui.workbench.swt_0.13.0.v20150504-0621
    6. org.eclipse.equinox.app_1.3.300.v20150423-1356
    7. org.eclipse.equinox.launcher_1.3.100.v20150511-1540
    8. org.eclipse.jdt.ui_3.11.0.v20150527-0925
    9. org.eclipse.jdt_3.11.0.v20150603-2000
    10. org.eclipse.jface.text_3.10.0.v20150603-1752
    11. org.eclipse.jface_3.11.0.v20150602-1400
    12. org.eclipse.recommenders.completion.rcp_2.2.0.v20150609-1848
    13. org.eclipse.swt_3.104.0.v20150528-0211
    14. org.eclipse.ui_3.107.0.v20150507-1945
    15. org.eclipse.ui.ide.application_1.1.0.v20150422-0725
    16. org.eclipse.ui.ide_3.11.0.v20150510-1749

Please note that:
* Messages, stacktraces, and nested status objects may be shortened.
* Bug fields like status, resolution, and whiteboard are sent
  back to reporters.
* The list of present bundles and their respective versions was
  calculated by package naming heuristics. This may or may not reflect reality.

Other Resources:
* Report: https://dev.eclipse.org/recommenders/committers/confess/#/problems/55c7261ee4b09560a8aa3727  
* Manual: https://dev.eclipse.org/recommenders/community/confess/#/guide


Thank you for your assistance.
Your friendly error-reports-inbox.
Comment 1 Andreas Sewe CLA 2016-03-07 03:15:14 EST
This is very likely a bug in JDT, as the only Code Recommenders frame on the stack trace...

(In reply to EPP Error Reports from comment #0)
>     at
> org.eclipse.recommenders.completion.rcp.processable.
> ProcessableParameterGuessingProposal.
> apply(ProcessableParameterGuessingProposal.java:172)[REQUIRED]

...starts the apply method with a super-call in line 172. In other words, the stacktrace contains effectively just JDT code. (FWIW, as of Code Recommenders 2.2.2, we don't copy apply at all: Bug 472474).

That being said, looking at code of LazyGenericTypeProposal.shouldAppendArguments, maybe it's worth catching a StringIndexOutOfBoundsException and rethrowing it with a better error message that includes the "line" String. Having just the index seems not enough to diagnose the issue. :-(
Comment 2 Stephan Herrmann CLA 2016-03-07 19:52:24 EST
Trying to understand the logic in the block in question:

Looking at this line in shouldAppendArguments():

	int index= offset - region.getOffset();

if at this point 'index <= line.length()' then 'index' cannot get out of bounds without first triggering 'index == line.lenght()' at what point we would return true and all is fine.

Hence, I assume, that 'offset - region.getOffset()' already computes a point beyond the current 'line'. Which is odd, given that 'region' was computed as to contain 'offset', and 'line' represents the text corresponding to 'region'.

That would seem to indicate that these two lines:

	IRegion region= document.getLineInformationOfOffset(offset);
	String line= document.get(region.getOffset(), region.getLength());

- either produce a 'region' that is strictly to the left of 'offset',
- or produce a 'line' that's too short to contain the char at 'offset'

Both would IMHO indicate a bug in the underlying IDocument implementation, *or* a *concurrency* issue with the document being modified between these two lines??

What are the odds that 11 users independently encountered a concurrency problem hitting at such a short window?
Comment 3 Andreas Sewe CLA 2016-03-08 03:52:06 EST
(In reply to Stephan Herrmann from comment #2)
> Trying to understand the logic in the block in question:
> 
> Looking at this line in shouldAppendArguments():
> 
> 	int index= offset - region.getOffset();
> 
> if at this point 'index <= line.length()' then 'index' cannot get out of
> bounds without first triggering 'index == line.lenght()' at what point we
> would return true and all is fine.

Agreed. In order to throw at

  char ch= line.charAt(index);

'index >= line.length' has to hold before the while loop. The alternative explanation, 'index < 0', cannot be true, as that would have thrown a StringIndexOutOfBoundsException in the condition of the while loop already:

  Character.isUnicodeIdentifierPart(line.charAt(index))

> Hence, I assume, that 'offset - region.getOffset()' already computes a point
> beyond the current 'line'. Which is odd, given that 'region' was computed as
> to contain 'offset', and 'line' represents the text corresponding to
> 'region'.
> 
> That would seem to indicate that these two lines:
> 
> 	IRegion region= document.getLineInformationOfOffset(offset);
> 	String line= document.get(region.getOffset(), region.getLength());
> 
> - either produce a 'region' that is strictly to the left of 'offset',
> - or produce a 'line' that's too short to contain the char at 'offset'

What do you mean by "too short"? 'line.length() == 0'? AFAICT, that would return true rather than throwing.

> Both would IMHO indicate a bug in the underlying IDocument implementation,
> *or* a *concurrency* issue with the document being modified between these
> two lines??
> 
> What are the odds that 11 users independently encountered a concurrency
> problem hitting at such a short window?

Well, it's 11 users in 8 months [1] and content assist is triggered quite frequently, so I wouldn't rule that out completely, although it sounds unlikely.

[1] <https://dev.eclipse.org/recommenders/committers/confess/#/problems/55c7261ee4b09560a8aa3727/similar?page=0&size=20&sort=timestamp,desc>
Comment 4 Stephan Herrmann CLA 2016-03-08 08:10:47 EST
(In reply to Andreas Sewe from comment #3)
> > - or produce a 'line' that's too short to contain the char at 'offset'
> 
> What do you mean by "too short"? 'line.length() == 0'? AFAICT, that would
> return true rather than throwing.

Illustration of what I meant:
offset = 110
region.getOffset() = 100 (line starts at offset 100)
index = 10 (from (110 - 100))
line.length() = 5 (line doesn't include the char at 110)

> > What are the odds that 11 users independently encountered a concurrency
> > problem hitting at such a short window?
> 
> Well, it's 11 users in 8 months [1] and content assist is triggered quite
> frequently, so I wouldn't rule that out completely, although it sounds
> unlikely.

so currently it's an "unlikely" explanation vs. no explanation :-/

To further elaborate the theory: if region was computed correctly, (with length > 10 in the above example) then a too short line sounds like a result of a shorter buffer, that has EOF before position 110, otherwise regardless of any shift of positions the returned line should have a length > 10. But wouldn't a region that extends beyond the current document throw IAE or similar in document.get()? Difficult to tell without knowing the exact type of document.
Comment 5 Andreas Sewe CLA 2016-03-09 03:34:14 EST
(In reply to Stephan Herrmann from comment #4)
> (In reply to Andreas Sewe from comment #3)
> > > - or produce a 'line' that's too short to contain the char at 'offset'
> > 
> > What do you mean by "too short"? 'line.length() == 0'? AFAICT, that would
> > return true rather than throwing.
> 
> Illustration of what I meant:
> offset = 110
> region.getOffset() = 100 (line starts at offset 100)
> index = 10 (from (110 - 100))
> line.length() = 5 (line doesn't include the char at 110)

FWIW, in the reported incidents 'line.length()' ranges from 5 to 44 (== to the 'index' at which StringIndexOutOfBoundsException is thrown), which seems pretty "normal" for a IDocument containing Java code.

> To further elaborate the theory: if region was computed correctly, (with
> length > 10 in the above example) then a too short line sounds like a result
> of a shorter buffer, that has EOF before position 110, otherwise regardless
> of any shift of positions the returned line should have a length > 10. But
> wouldn't a region that extends beyond the current document throw IAE or
> similar in document.get()?

At least AbstractDocument.get would throw BadLocationException (which LazyGenericTypeProposal.shouldAppendArguments handles, BTW).

> Difficult to tell without knowing the exact type of document.

Agreed. Or even more specifically, the ILineTracker and ITextStore used under the hood by the IDocument in question.

I've added a "neeedinfo" request. Maybe some use provides the necessary information through the automated error reporting.
Comment 6 Eclipse Genie CLA 2018-11-20 17:35:08 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 7 Stephan Herrmann CLA 2018-11-27 17:55:30 EST
Anyone able to provide more information: please re-open.

Until then there's nothing we can do, sorry.