Source code for this tutorial is available on googlecode as a single zip archive, as a Team Project Set or you can checkout the SVN projects directly.
Step 1: Preparations
As we will have dependencies to JSDT you either need to check out the source code from gerrit or add JSDT to your target platform.
Step 2: Defining the extension point
Create a new Plug-in Project com.codeandme.jsdt.contentassist and add following dependencies:
- org.eclipse.wst.jsdt.ui
- org.eclipse.core.runtime
- org.eclipse.jface.text
Create a second extension of the same type for our implementation. Again provide an ID. Create a javaCompletionProposalComputer subnode with a class and activate set to true. The categoryID consists of your plugin name followed by the category ID we provided earlier.
If you use a target definition containing JSDT plugins you might not be able to use the Plug-in Manifest Editor for creating these extensions. In that case you have to edit the xml code directly:
<?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.4"?> <plugin> <extension point="org.eclipse.wst.jsdt.ui.javaCompletionProposalComputer" id="codeandme_category" name="Code and me proposals"> <proposalCategory/> </extension> <extension id="codeandme_proposal" point="org.eclipse.wst.jsdt.ui.javaCompletionProposalComputer"> <javaCompletionProposalComputer class="com.codeandme.jsdt.contentassist.CustomCompletionProposalComputer" categoryId="com.codeandme.jsdt.contentassist.codeandme_category" activate="true"> </javaCompletionProposalComputer> </extension> </plugin>Step 3: Proposal computer implementation
Now for the easy part:create a new class CustomCompletionProposalComputer with following content:
package com.codeandme.jsdt.contentassist; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.wst.jsdt.ui.text.java.ContentAssistInvocationContext; import org.eclipse.wst.jsdt.ui.text.java.IJavaCompletionProposalComputer; public class CustomCompletionProposalComputer implements IJavaCompletionProposalComputer { @Override public void sessionStarted() { } @Override public List computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) { ArrayList<CompletionProposal> proposals = new ArrayList<CompletionProposal>(); proposals.add(new CompletionProposal("codeandme.blogspot.com", context.getInvocationOffset(), 0, "codeandme.blogspot.com".length())); proposals.add(new CompletionProposal("<your proposal here>", context.getInvocationOffset(), 0, "<your proposal here>".length())); return proposals; } @Override public List computeContextInformation(ContentAssistInvocationContext context, IProgressMonitor monitor) { return null; } @Override public String getErrorMessage() { return null; } @Override public void sessionEnded() { } }
CompletionProposals could contain more information like attached documentation or ContextInformation for variables and other dynamic content. See this post for some information on the Contextinformation.
Optional: Helper methods
Typically you would need to evaluate the last characters before the cursor position to filter your proposals. You also might be interested in the content of the current line left of the cursor position. Maybe these helper methods are of some interest:
private static final Pattern LINE_DATA_PATTERN = Pattern.compile(".*?([^\\p{Alnum}]?)(\\p{Alnum}*)$"); /** * Extract context relevant information from current line. The returned matcher locates the last alphanumeric word in the line and an optional non * alphanumeric character right before that word. result.group(1) contains the last non-alphanumeric token (eg a dot, brackets, arithmetic operators, ...), * result.group(2) contains the alphanumeric text. This text can be used to filter content assist proposals. * * @param context * content assist context * @return matcher containing content assist information * @throws BadLocationException */ protected Matcher matchLastToken(final ContentAssistInvocationContext context) throws BadLocationException { String data = getCurrentLine(context); return LINE_DATA_PATTERN.matcher(data); } /** * Extract text from current line up to the cursor position * * @param context * content assist context * @return current line data * @throws BadLocationException */ protected String getCurrentLine(final ContentAssistInvocationContext context) throws BadLocationException { IDocument document = context.getDocument(); int lineNumber = document.getLineOfOffset(context.getInvocationOffset()); IRegion lineInformation = document.getLineInformation(lineNumber); return document.get(lineInformation.getOffset(), context.getInvocationOffset() - lineInformation.getOffset()); }
Very nice. Thanks!
ReplyDeleteSurely one of the few good resources regarding content assist available on internet.Can you tell me how to add content assist (or even syntax highlighting) in the CDATA part of an xml file. I have script tags written in the CDATA section of my xml file.
ReplyDeleteThanks
Sorry, I never looked at the xml editor. I guess the implementation will be similar, but you have to look for the extension points and Interface names on your own. Best grab the source of the ui bundles for the xml editor (I guess org.eclipse.wst.xml.ui ?) and check the plugin.xml.
DeleteDo you have any idea on how to "inject" custom content into an existing code outline?
ReplyDeleteI got the ContentAssistant working just fine for my framework, but I'm looking for a way to display a class hierarchy in the JavaScript outline view. I've been searching for this for 3 days straight now, but still no success.
Any help is greatly appriciated!
I was looking for such a feature too. But as far as I can tell there seems to be no way to do that without changing JSDT sources, which is why I abandoned the idea for now. The outline content is created by the JSDT editor when asked for an IContentOutlinePage adapter. I could not find any extension points allowing to extend that model.
DeleteNice tutorial. I followed the same steps but for the java editor using Eclipse Luna (org.eclipse.jdt.ui.javaCompletionProposalComputer). But I could not find the proposal category on the contentAssist->Advanced page. The plugin is also not loaded. I already set the activate value to true. Can you suggest me any solution?
ReplyDeleteSorry, did that only for JS. Best ask for support on the forums or the JDT mailing lists
DeleteHow to debug CustomCompletionProposalComputer class ?
ReplyDeletebest set a breakpoint somewhere in computeCompletionProposals and trigger a code completion in your debug IDE
Delete