Community
Participate
Working Groups
HEAD (N20090212-2000) - Open Type dialog - enter pattern ".HMap" -> AIOOBE We call SearchPattern.getMatchingRegions(String, String, int) with arguments: pattern= "?*" (id=475) name= "java.util - [jdk1.4.2]" (id=476) matchRule= 2 [0x2] [^B] !ENTRY org.eclipse.jface 4 2 2009-02-13 10:17:19.906 !MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.jface". !STACK 0 java.lang.ArrayIndexOutOfBoundsException: 0 at org.eclipse.jdt.internal.core.search.StringOperation.getPatternMatchingRegions(StringOperation.java:372) at org.eclipse.jdt.core.search.SearchPattern.getMatchingRegions(SearchPattern.java:828) at org.eclipse.jdt.internal.ui.dialogs.FilteredTypesSelectionDialog$TypeItemLabelProvider.getStyledText(FilteredTypesSelectionDialog.java:874) at org.eclipse.ui.dialogs.FilteredItemsSelectionDialog$ItemsListLabelProvider.getStyledText(FilteredItemsSelectionDialog.java:1703) at org.eclipse.ui.dialogs.FilteredItemsSelectionDialog$ItemsListLabelProvider.update(FilteredItemsSelectionDialog.java:1720) at org.eclipse.jface.viewers.ViewerColumn.refresh(ViewerColumn.java:145) at org.eclipse.jface.viewers.AbstractTableViewer.doUpdateItem(AbstractTableViewer.java:393) at org.eclipse.jface.viewers.StructuredViewer$UpdateItemSafeRunnable.run(StructuredViewer.java:475) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37) at org.eclipse.core.runtime.Platform.run(Platform.java:874) at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:48) at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) at org.eclipse.jface.viewers.StructuredViewer.refreshItem(StructuredViewer.java:1492) at org.eclipse.jface.viewers.AbstractTableViewer.replace(AbstractTableViewer.java:1053) at org.eclipse.ui.dialogs.FilteredItemsSelectionDialog$ContentProvider.updateElement(FilteredItemsSelectionDialog.java:2935) at org.eclipse.jface.viewers.AbstractTableViewer$1.handleEvent(AbstractTableViewer.java:85) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:87) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1027) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1012) at org.eclipse.swt.widgets.Table.checkData(Table.java:933) at org.eclipse.swt.widgets.Table.wmNotifyChild(Table.java:6343) at org.eclipse.swt.widgets.Control.wmNotify(Control.java:4843) at org.eclipse.swt.widgets.Composite.wmNotify(Composite.java:1755) at org.eclipse.swt.widgets.Control.WM_NOTIFY(Control.java:4473) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3966) at org.eclipse.swt.widgets.Display.windowProc(Display.java:4601) at org.eclipse.swt.internal.win32.OS.$$YJP$$CallWindowProcW(Native Method) at org.eclipse.swt.internal.win32.OS.CallWindowProcW(OS.java) at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:2297) at org.eclipse.swt.widgets.Table.callWindowProc(Table.java:333) at org.eclipse.swt.widgets.Table.callWindowProc(Table.java:199) at org.eclipse.swt.widgets.Control.windowProc(Control.java:4002) at org.eclipse.swt.widgets.Table.windowProc(Table.java:5520) at org.eclipse.swt.widgets.Display.windowProc(Display.java:4601) at org.eclipse.swt.internal.win32.OS.$$YJP$$DispatchMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.DispatchMessageW(OS.java) at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2394) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3470) at org.eclipse.jface.window.Window.runEventLoop(Window.java:825) at org.eclipse.jface.window.Window.open(Window.java:801) at org.eclipse.jdt.internal.ui.dialogs.FilteredTypesSelectionDialog.open(FilteredTypesSelectionDialog.java:504) at org.eclipse.jdt.internal.ui.actions.OpenTypeAction.runWithEvent(OpenTypeAction.java:71) at org.eclipse.jdt.internal.ui.actions.OpenTypeAction.runWithEvent(OpenTypeAction.java:132) at org.eclipse.ui.internal.handlers.ActionDelegateHandlerProxy.execute(ActionDelegateHandlerProxy.java:281) at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476) at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508) at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.executeCommand(WorkbenchKeyboard.java:471) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:823) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:879) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.filterKeySequenceBindings(WorkbenchKeyboard.java:570) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.access$3(WorkbenchKeyboard.java:511) at org.eclipse.ui.internal.keys.WorkbenchKeyboard$KeyDownFilter.handleEvent(WorkbenchKeyboard.java:126) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:87) at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1190) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1002) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1027) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1012) at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1040) at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1036) at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1358) at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4019) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3912) at org.eclipse.swt.widgets.Display.windowProc(Display.java:4588) at org.eclipse.swt.internal.win32.OS.$$YJP$$DispatchMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.DispatchMessageW(OS.java) at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2394) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3470) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2388) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2352) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2204) at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:499) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:333) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:492) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:556) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:511) at org.eclipse.equinox.launcher.Main.run(Main.java:1284) at org.eclipse.equinox.launcher.Main.main(Main.java:1260)
The problem comes when the pattern is only made of with '?' and/or '*'. The algorithm of the StringOperation.getPatternMatchingRegions(...) first counts the number of expected matching parts in the name and in this case gets 0, hence create a empty array. Of course trying to put anything in this kind of array leads to an AIOOBE! So, I think the peculiar issue shows that the behavior needs to be changed when the pattern is either null or equals to '*'. Currently, it's specified that the returned regions will be the entire name. I missed the fact that any other pattern with only '?' and/or '*' characters should behave the same. If we agree to change the API behavior to return in such case an empty array, then the problem could be easily fixed. Furthermore, this would allow clients to distinguish the three following cases: 1) The name does not match the pattern: null is returned 2) The name matches the pattern and they have some characters in common: an array of the common characters is returned 3) The name matches the pattern but they have no common character: an empty array is returned Of course not all clients would need to distinguish these 3 different cases (e.g. Open Type dialog do not care of case 1 as the styled text is applied in the acceptMatch method of the SearchRequestor, hence the name _always_ matches the pattern), but I think it could be interesting for some clients calling this API without having made a search request before... Finally, the other advantage of modifying this behavior would be to make the returned array consistent when the given pattern has '?' and/or '*'. Currently, the API returns an array [0, length] when the pattern is only '*' and this can make the clients think that the characters matched by the '*' are included in the matching regions. However, this is not the case as soon as a character other than '?' or '*' is in the pattern; e.g. for 'H*M*' pattern and 'HashMap' name, the returned array is {0,1,4,1}, hence characters matched by the 2 stars are obviously not included in the array... If everybody agrees on this change, I'll be back soon with a patch for it which, of course, will also fix the AIOOBE...
Sounds good.
+1
Created attachment 125623 [details] Proposed patch
Created attachment 125631 [details] Proposed patch+tests It looks like I forgot to add tests I wrote to previous patch...
Released for 3.5M6 in HEAD stream.
When verifying this bug fix, please note that it won't be possible to reproduce the exception using any I-build as the problem has been fixed before the new functionality was present in such a build... The only build exhibiting this issue would be the N20090212-2000 build, but I'm not sure it will be available.
Verified in HEAD.