Geertjan's Blog

  • August 10, 2008

How to Create a Caret Aware Code Completion Box

Geertjan Wielenga
Product Manager
Casper Bang asked a great question at the end of my previous blog entry about the new code completion tutorial:

We have a desire in our team to get code completion for JPA queries. However, JPA is an embedded DSL inside string annotations. Does the approach described in the tutorial also apply if one wanted to "sub-tokenize" and provide completion inside a String token of a x-java MIME type?

The answer is, of course, "Yes!" To set up a scenario, I recreated my code completion plugin so that it now ONLY works for Java parameters. I.e., as you can see in the screenshot below (more or less), whenever I invoke code completion and ONLY IF the cursor is on a parameter (or in the place where a parameter SHOULD BE defined), will my custom items be displayed in the code completion box:

The three high level clues to understanding how to do this are provided by the following:

Especially the last of the above is extremely relevant (it is from Sandip's great blog), it taught me everything I now know in this case, but the other two should be read first (especially the first, don't worry too much about the second, just be aware that it is there and can be useful when actually implementing a scenario).

In short, starting from the sample that the code completion tutorial provides, you need to do the following:

  1. Change the layer.xml file so that the code completion plugin will apply to Java files instead of HTML files. Do this by simply replacing "text/html" with "text/x-java" in the folder hierarchy. Now, anywhere in a Java file, you will see your code completion entries. That's not what you want, you only want to see it in very specific cases.

  2. So, as discussed in Sandip's blog entry, you need to create a class that extends CaretAwareJavaSourceTaskFactory:

    import org.netbeans.api.java.source.CancellableTask;
    import org.netbeans.api.java.source.CompilationInfo;
    import org.netbeans.api.java.source.JavaSource.Phase;
    import org.netbeans.api.java.source.JavaSource.Priority;
    import org.netbeans.api.java.source.support.CaretAwareJavaSourceTaskFactory;
    import org.openide.filesystems.FileObject;
    public class CountriesCompletionJavaSourceTaskFactory extends CaretAwareJavaSourceTaskFactory {
    public CountriesCompletionJavaSourceTaskFactory() {
    super(Phase.ELEMENTS_RESOLVED, Priority.LOW);
    public CancellableTask<CompilationInfo> createTask(FileObject fileObject) {
    return new CountriesCompletionTask(this, fileObject);

  3. Next, register the above class in META-INF/Services, for the "org.netbeans.api.java.source.JavaSourceTaskFactory" interface.

  4. Then create the task that you see referred to above, i.e., "CountriesCompletionTask", which exists for no other reason than to toggle a boolean whenever the required element is found under the cursor:

    import com.sun.source.util.TreePath;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.ElementKind;
    import org.netbeans.api.java.source.CancellableTask;
    import org.netbeans.api.java.source.CompilationInfo;
    import org.openide.awt.StatusDisplayer;
    import org.openide.filesystems.FileObject;
    public class CountriesCompletionTask implements CancellableTask<CompilationInfo> {
    private CountriesCompletionJavaSourceTaskFactory
    private FileObject fileObject;
    private boolean canceled;
    //Toggle whether code completion should be shown:
    private static boolean showCC = false;
    public static boolean isShowCC() {
    return showCC;
    public static void setShowCC(boolean showCC) {
    CountriesCompletionTask.showCC = showCC;
    countriesCompletionJavaSourceTaskFactory, FileObject fileObject) {
    this.countriesCompletionJavaSourceTaskFactory =
    this.fileObject = fileObject;
    public void run(CompilationInfo compilationInfo) {
    //Find the TreePath for the caret position:
    TreePath tp =
    //If cancelled, return:
    if (isCancelled()) {
    //Get Element:
    Element element = compilationInfo.getTrees().getElement(tp);
    //If cancelled, return:
    if (isCancelled()) {
    if (element != null) {
    //If the element is a parameter...
    if (element.getKind() == ElementKind.PARAMETER) {
    //...toggle the boolean to show the code completion:
    showCC = true;
    StatusDisplayer.getDefault().setStatusText("" +
    "You can invoke code completion for \\'"
    + element.getSimpleName()+"\\'");
    public final synchronized void cancel() {
    canceled = true;
    protected final synchronized boolean isCancelled() {
    return canceled;

    So, Casper, you'd need to identify the element in the code that you want to deal with. I.e., instead of a parameter, you'd look for a certain kind of string for your JPA queries. Here's something I've been playing with, although it doesn't get into the strings:

    Refer to the documents referenced earlier for details.

  5. Finally, in the CompletionProvider class, which is discussed at length in the code completion tutorial, check whether the boolean has been switched or not and, if so, show the code completion box. Once shown, set the boolean back to false so that it is back in its default state. All that's done in the lines in bold below:

    import java.util.Locale;
    import javax.swing.text.Document;
    import javax.swing.text.JTextComponent;
    import org.netbeans.spi.editor.completion.CompletionProvider;
    import org.netbeans.spi.editor.completion.CompletionResultSet;
    import org.netbeans.spi.editor.completion.CompletionTask;
    import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery;
    import org.netbeans.spi.editor.completion.support.AsyncCompletionTask;
    public class CountriesCompletionProvider implements CompletionProvider {
    public CompletionTask createTask(int i, final JTextComponent jTextComponent) {
    if (i != CompletionProvider.COMPLETION_QUERY_TYPE) {
    return null;
    return new AsyncCompletionTask(new AsyncCompletionQuery() {
    protected void query(CompletionResultSet completionResultSet, final Document document, int caretOffset) {
    //Iterate through the available locales
    //and assign each country display name
    //to a CompletionResultSet:
    Locale[] locales = Locale.getAvailableLocales();
    for (int i = 0; i < locales.length; i++) {
    final Locale locale = locales[i];
    final String country = locale.getDisplayCountry();
    if (!country.equals("") && CountriesCompletionTask.isShowCC()) {
    completionResultSet.addItem(new CountriesCompletionItem(country, caretOffset));
    }, jTextComponent);
    public int getAutoQueryTypes(JTextComponent arg0, String arg1) {
    return 0;

And that's all. Now you can have a code completion box for very specific elements within your Java code.

Join the discussion

Comments ( 7 )
  • Casper Bang Sunday, August 10, 2008

    Extremely cool, thanks for not only answering my question but making it hard for me not to make word of my proposal.

    Following the steps you outline works well, a note to other thought that since the NetBeans API's have been generified in 6.0, you will want to implement CancellableTask<CompilationInfo> rather than CancellableTask.

  • Geertjan Monday, August 11, 2008

    Thanks, fixed that. Simply wasn't rendered properly in the blog entry, but was there in the code. Looking forward to hearing what results from this with your JPA queries!

  • Casper Bang Monday, August 11, 2008

    I have been trying to understand the difference between this approach and the seemingly similar one laid out in the RCP book (Manifest example) where it, among other things, is not necessary to register a TaskFactory SPI.

    Correct to assume that the CodeCompletion example in the RCP book is strictly lexer/token based and very limited, while this one is AST/element based with maximum potential?

  • Geertjan Monday, August 11, 2008

    Reason is simple: Manifest files are not Java files.

  • Geertjan Monday, August 11, 2008

    "Correct to assume that the CodeCompletion example in the RCP book is strictly lexer/token based and very limited, while this one is AST/element based with maximum potential?"

    That sums it up very well.

  • Aljoscha Rittner Thursday, November 27, 2008

    In my blog I've a info about semantic code modification with code completion:


    The code completion works only with swing components, but for global (syntax aware) modifications we need the Java Infrastructure. My blog entry shows how to glue "Code Completion" with the "Java Infrastructure".

    best regards,


  • Neeraj Sharma Sunday, August 15, 2010

    Dear sir,

    i am creating my own java ide and i done 50% of work like syntax recognition and code grouping and noy for java but several other laguages also now i want to create netbeans like intelligence window in java swings please guide me how can i do it?

    Thanks in advance

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.