Community
Participate
Working Groups
Invoking the SpyHandler from a dialog (e.g., the Preferences dialog) fails with an IllegalStateException. Thread [main] (Suspended (exception IllegalStateException)) ApplicationPartServiceImpl.getActiveWindowService() line: 43 ApplicationPartServiceImpl.findPart(String) line: 92 SpyHandler.run(EPartService, String, MApplication, EModelService) line: 68 EPartService#findPart() is documented to return null if the view cannot be found. But ApplicationPartServiceImpl#getActiveWindowService() throws an IllegalStateException which isn't caught. findPart() should catch the IllegalStateException and return null.
Created attachment 251814 [details] Spy is working on dialog Unable to reproduce. This is how I tried to reproduce the error: 1. open a dialog. from menu Window > Preferences 2. Open spy with ALT+SHIFT+F1 Observed behavior: - Spy is working - no exception is logged
I misclassified this bug, Patrik: this error was caused by the E4 Tools Spy and not the PDE spy. I suspect I may have messed up the model (this was a debugging image), so it may be a spurious error. Keeping this open as I'll try to reproduce.
*** Bug 498505 has been marked as a duplicate of this bug. ***
Moving to Platform/UI. Finally took a few minutes to look at this in more detail. Steps to repeat: 0. Install the E4 Spies (e.g., the CSS Spy) 1. Open the Preferences dialog 2. Now try opening one of the Spies, like the CSS Spy (Shift-Alt-F5) Notice an IllegalStateException is logged to the console. The SpyHandler looks like the following (lightly reformatted to fit) @Execute public void run(EPartService ps, @Optional @Named(SpyProcessor.SPY_COMMAND_PARAM) String viewID, MApplication appli, EModelService modelService) { MWindow spyWindow = getOrCreateSpyWindow(appli, modelService); MPartStack partStack = (MPartStack) modelService.find(E4_SPIES_PART_STACK, spyWindow); MPart p = ps.findPart(viewID); // XXX if (p == null) { // Create the part in the spyWindow... p = ps.createPart(viewID); partStack.getChildren().add(p); partStack.setSelectedElement(p); … etc … There's actually a few issues here. When the Spy is triggered, the dialog's IEclipseContext is used for lookups, which is rooted from the WorkbenchContext and not its parent window. I can only think this is so handler lookups don't inadvertently pull in the window handlers? I haven't investigated this further. As a result, the SpyHandler's EPartService is resolved to the workbench-level ApplicationPartServiceImpl. The ApplicationPartServiceImpl attempts to delegate to the active window's EPartService. It does so by looking at the MApplication's context's activeChild, which in this case is the dialog's context, and so it finds itself. Since no real EPartService can be found, it throws an IllegalStateException. The ApplicationPartServiceImpl should be a bit smarter and attempt to look at the MApplication's active window. But the root cause of this problem is that EPartService is only necessary to create an MPart in a new window. Really creating a part should be possible from an EModelService. Especially since we're creating a new window and the EPartService is not actually for that window. Solutions here: 1. Enhance ApplicationPartServiceImpl#getActiveWindowService() to attempt to retrieve the EPartService from MApplication's #selectedElement. 2. Add EModelService#createPart and cause PartServiceImpl#createPart() to delegate to it. That lets EPartService to still define part-creation policies, but also means that pure E4 windows can be pieced together without an EPartService. #2 is the preferred solution, I think: EPartService is contextualized to a particular window, and fetching what could be another window's EPartService seems a bit problematic. Thread [main] (Suspended (exception IllegalStateException)) ApplicationPartServiceImpl.getActiveWindowService() line: 43 ApplicationPartServiceImpl.findPart(String) line: 92 SpyHandler.run(EPartService, String, MApplication, EModelService) line: 67 NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62 DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 Method.invoke(Object, Object...) line: 498 MethodRequestor.execute() line: 56 InjectorImpl.invokeUsingClass(Object, Class<?>, Class<Annotation>, Object, PrimaryObjectSupplier, PrimaryObjectSupplier, boolean) line: 252 InjectorImpl.invoke(Object, Class<Annotation>, Object, PrimaryObjectSupplier, PrimaryObjectSupplier) line: 234 ContextInjectionFactory.invoke(Object, Class<Annotation>, IEclipseContext, IEclipseContext, Object) line: 132 WorkbenchHandlerServiceHandler(HandlerServiceHandler).execute(ExecutionEvent) line: 152 Command.executeWithChecks(ExecutionEvent) line: 493 ParameterizedCommand.executeWithChecks(Object, Object) line: 486 HandlerServiceImpl.executeHandler(ParameterizedCommand, IEclipseContext) line: 210 KeyBindingDispatcher.executeCommand(ParameterizedCommand, Event) line: 286
It's an absolute MUST to use the part-service connected to the window you are dealing with so IMHO only option #2 is viable
New Gerrit change created: https://git.eclipse.org/r/78019
Gerrit change https://git.eclipse.org/r/78019 was merged to [master]. Commit: http://git.eclipse.org/c/platform/eclipse.platform.ui.git/commit/?id=56bfbcc4dcddb8871aeca7cbe893036ce38e59c1
Is this done, or more work needed for M2?
Oops, it's done.