Community
Participate
Working Groups
In 3.8 M4, the core context returned by JavaContentAssistInvocationContext differs for the 'default content assist list' (the one you get when triggering ctrl+space once) and any other subsequent content assist list (all subsequent content assist lists you get when triggering ctrl+space twice and more, i.e., when cycling through the proposal engines). For @Override public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext javaContext, IProgressMonitor monitor) { boolean isExtended = ((JavaContentAssistInvocationContext) javaContext).getCoreContext().isExtended() // isExtended == true iff proposal computer was configured to run on the first ('default') content assist, and false otherwise. Any idea what's going wrong here? A stacktrace that might help to nail down the problem: java.lang.UnsupportedOperationException: Operation only supported in extended context at org.eclipse.jdt.internal.codeassist.InternalCompletionContext.getCompletionNode(InternalCompletionContext.java:387) at org.eclipse.recommenders.internal.completion.rcp.RecommendersCompletionContext.getCompletionNode(RecommendersCompletionContext.java:45) at org.eclipse.recommenders.internal.completion.rcp.calls.engine.CallsCompletionProposalComputer.isCompletionRequestSupported(CallsCompletionProposalComputer.java:126) at org.eclipse.recommenders.internal.completion.rcp.calls.engine.CallsCompletionProposalComputer.computeCompletionProposals(CallsCompletionProposalComputer.java:100) at org.eclipse.jdt.internal.ui.text.java.CompletionProposalComputerDescriptor.computeCompletionProposals(CompletionProposalComputerDescriptor.java:318) at org.eclipse.jdt.internal.ui.text.java.CompletionProposalCategory.computeCompletionProposals(CompletionProposalCategory.java:267) at org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor.collectProposals(ContentAssistProcessor.java:283) at org.eclipse.jdt.internal.ui.text.java.ContentAssistProcessor.computeCompletionProposals(ContentAssistProcessor.java:243) at org.eclipse.jface.text.contentassist.ContentAssistant.computeCompletionProposals(ContentAssistant.java:1830) at org.eclipse.jface.text.contentassist.CompletionProposalPopup.computeProposals(CompletionProposalPopup.java:556) at org.eclipse.jface.text.contentassist.CompletionProposalPopup.handleRepeatedInvocation(CompletionProposalPopup.java:541) at org.eclipse.jface.text.contentassist.CompletionProposalPopup.showProposals(CompletionProposalPopup.java:506) at org.eclipse.jface.text.contentassist.ContentAssistant.showPossibleCompletions(ContentAssistant.java:1656) at org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor$AdaptedSourceViewer.doOperation(CompilationUnitEditor.java:183) at org.eclipse.ui.texteditor.ContentAssistAction$1.run(ContentAssistAction.java:82) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ui.texteditor.ContentAssistAction.run(ContentAssistAction.java:80) at org.eclipse.jface.action.Action.runWithEvent(Action.java:498) at org.eclipse.ui.commands.ActionHandler.execute(ActionHandler.java:185) at org.eclipse.ui.internal.handlers.LegacyHandlerWrapper.execute(LegacyHandlerWrapper.java:109) 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:468) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.press(WorkbenchKeyboard.java:786) at org.eclipse.ui.internal.keys.WorkbenchKeyboard.processKeyEvent(WorkbenchKeyboard.java:885)
FWIW, this bug report has its origins here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=340945
Whether the extended context is available in the first invocation already depends on the enabled categories and whether argument names are requested. It's up to each processor to request the extended context by calling setRequireExtendedContext(true) on its own collector.
I wasn't aware that it's the responsibility of the engine to recreate the context if it's not extended. After digging into JavaCompletionProposalComputer#internalComputeCompletionProposals and its subclasses this became clearer to me. I added the some additional logic to my code that creates and extended context if the currently given one isn't an extended one. This still looks odd to me but it seems to work. Please let me know if this violates or breaks some JDT concepts. Thanks for your assistance! public BaseRecommendersCompletionContext(final JavaContentAssistInvocationContext jdtContext) { this.javaContext = jdtContext; this.coreContext = cast(jdtContext.getCoreContext()); if (!coreContext.isExtended()) { requestExtendedContext(); } } private void requestExtendedContext() { CompletionProposalCollector collector = new CompletionProposalCollector(getCompilationUnit()) { @Override public void acceptContext(final CompletionContext context) { super.acceptContext(context); coreContext = (InternalCompletionContext) context; } }; collector.setInvocationContext(javaContext); collector.setRequireExtendedContext(true); try { getCompilationUnit().codeComplete(getInvocationOffset(), collector); } catch (JavaModelException e) { log(e) } }
(In reply to comment #3) > I wasn't aware that it's the responsibility of the engine to recreate the > context if it's not extended. After digging into > JavaCompletionProposalComputer#internalComputeCompletionProposals and its > subclasses this became clearer to me. > I added the some additional logic to my > code that creates and extended context if the currently given one isn't an > extended one. You don't need to check. Simply request it. Don't you already need/have a collector to get the proposals from JDT Core? If so, simply require it on this collector. If not, how do you get the proposals from JDT Core without collector? > This still looks odd to me The main purpose is to avoid additional computation if it is not needed. > but it seems to work. Of course ;-)
(In reply to comment #4) > Don't you already need/have a > collector to get the proposals from JDT Core? If so, simply require it on this > collector. If not, how do you get the proposals from JDT Core without > collector? I changed that part for Juno. I now create my own proposals w/o using cu.codeComplete. I though this would be 'smarter' than requesting all proposals first and filtering them afterwards.
> I now create my own proposals w/o using > cu.codeComplete. Why do you then need the context from JDT Core, then?
(In reply to comment #6) > Why do you then need the context from JDT Core, then? To get access of all visible locals, methods, fields and the *Completion node. The latter is used to figure out on which variable (name and type) or type (static) completion was triggered and what kind of proposals we want to make. For call completion a pure filtering could work (given that we get simple access to the variable's type completion was triggered on. Other engines like template completion need more information to filter which templates may apply in the given completion context.
(In reply to comment #7) > (In reply to comment #6) > > Why do you then need the context from JDT Core, then? > To get access of all visible locals, methods, fields and the *Completion node. > > The latter is used to figure out on which variable (name and type) or type > (static) completion was triggered and what kind of proposals we want to make. > For call completion a pure filtering could work (given that we get simple > access to the variable's type completion was triggered on. Other engines like > template completion need more information to filter which templates may apply > in the given completion context. I see. Makes sense.