zpavlinovic
zpavlinovic

Reputation: 1547

Add Java code template programmatically

I like when Eclipse lets me jump between parameters in a method call using a Tab key. I would like my plugin to provide a similar functionality. To be precise, I am injecting some piece of text into the editor and I would like to highlight specific syntax and let the programmer jump to the next match using the Tab key.

Here is an example. Lets suppose I dynamically created the following snippet:

String a = "bogus string";
int i = a.[?]

I will inject that into the editor and I would like that [?] is highlighted and ready for modification (user might type length()). Moreover, if there is more [?] fragments, I would like user to use Tab to move to the next one.

After researching a bit, I found that it might be done using templates. However, I can't find any relevant examples on the Web. Does anybody have experience with this?

UPDATE:

I found two links that might be useful, although I am still not able to come up with a solution.

link one

link two

Upvotes: 7

Views: 2190

Answers (3)

32kda
32kda

Reputation: 63

My answer is based on jeeeyul's answer. The difference is that I wanted not only template itself, but also imports for it to be resolved and added automatically. This can be done in following way, using JDT stuff:

AbstractTextEditor activeEditor = 
            (AbstractTextEditor) HandlerUtil.getActiveEditor(event);
    if (activeEditor == null) {
        return null;
    }
    ITypeRoot element = EditorUtility.getEditorInputJavaElement(activeEditor, true);
    if (element == null) {
        return null;
    }
    ICompilationUnit unit = element.getAdapter(ICompilationUnit.class);
    if (unit == null) {
        return null;
    }
    ISourceViewer sourceViewer = (ISourceViewer) activeEditor.getAdapter(ITextOperationTarget.class);
    Point range = sourceViewer.getSelectedRange();
    // You can generate template dynamically here!
    Template template = new Template("new List", "Add new list creation", JavaContextType.ID_STATEMENTS,
            "List<${type}> ${name:newName(java.util.List)} = new ArrayList<${type}>();${:import(java.util.List, java.util.ArrayList)}",
            true);
    IRegion region = new Region(range.x, range.y);
    JavaContextType contextType = new JavaContextType();
    contextType.setId(JavaContextType.ID_STATEMENTS); //Set context type, for which we apply this template
    contextType.addResolver(new ImportsResolver("import","import")); //Add imports resolver if we want imports to be added automatically for some template
    CompilationUnitContext ctx = new JavaContext(contextType, sourceViewer.getDocument(), range.x,
            range.y, unit);
    TemplateProposal proposal = new TemplateProposal(template, ctx, region, null);
    proposal.apply(sourceViewer, (char) 0, 0, 0);

Upvotes: 0

jeeeyul
jeeeyul

Reputation: 3787

Sample Handler Codes:

AbstractTextEditor activeEditor = 
        (AbstractTextEditor) HandlerUtil.getActiveEditor(event);

ISourceViewer sourceViewer = 
        (ISourceViewer) activeEditor.getAdapter(ITextOperationTarget.class);

Point range = sourceViewer.getSelectedRange();

// You can generate template dynamically here!
Template template = new Template("sample", 
        "sample description", 
        "no-context", 
        "private void ${name}(){\r\n" + 
        "\tSystem.out.println(\"${name}\")\r\n"
        + "}\r\n", true);

IRegion region = new Region(range.x, range.y);
TemplateContextType contextType = new TemplateContextType("test");
TemplateContext ctx =
    new DocumentTemplateContext(contextType, 
        sourceViewer.getDocument(), 
        range.x, 
        range.y);

TemplateProposal proposal 
    = new TemplateProposal(template, ctx, region, null);

proposal.apply(sourceViewer, (char) 0, 0, 0);

Result:

enter image description here

I suggest you use org.eclipse.jdt.ui.javaCompletionProposalComputer extension. It allows you can contribute Template more legal way.

In my codes, there are hacks since there is no way to get ISourceViewer legally. I know ISourceViewer is ITextTargetOperation itself, but it is not API(Illegal Casting). And Template is intended to designed to be used by TemplateCompletionProcessor or TemplateCompletionProposalComputer.

Upvotes: 8

sbridges
sbridges

Reputation: 25150

I'm not entirely sure what you want, but you may be able to do what you want with templates.

For example, open a java editor, place the cursor inside a method, type arraya then ctlr-space, and select arrayadd from the pop up menu. You will get a template with String highlighted, pressing tab jumps to the next variable. The template source can be seen in,

Preferences -> java -> editor ->templates

${array_type}[] ${result:newName(array)} = new ${array_type}[${array}.length + 1];
System.arraycopy(${array}, 0, ${result}, 0, ${array}.length);
${result}[${array}.length]= ${var};

Everything starting the a $ is a variable that you can fill in, and you can tab between variables while filling in the template.

Upvotes: 1

Related Questions