Java 如何在eclipse插件中修改函数体?

Java 如何在eclipse插件中修改函数体?,java,eclipse-plugin,eclipse-jdt,Java,Eclipse Plugin,Eclipse Jdt,我已经设法创建了一个弹出菜单并获得了一个I方法,但我不知道如何修改该方法。对于本例,假设我想添加文本system.out.println(“Hello,world!”)添加到现有方法的底部 我目前的情况如下: import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; impo

我已经设法创建了一个弹出菜单并获得了一个
I方法
,但我不知道如何修改该方法。对于本例,假设我想添加文本
system.out.println(“Hello,world!”)添加到现有方法的底部

我目前的情况如下:

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.jdt.core.IMethod;

public class HelloWorldAction implements IObjectActionDelegate {

    private Shell shell;

    private IMethod currentMethod;

    /**
     * Constructor for Action1.
     */
    public HelloWorldAction() {
        super();
    }

    /**
     * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
     */
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
        shell = targetPart.getSite().getShell();
    }

    /**
     * @see IActionDelegate#run(IAction)
     */
    public void run(IAction action) {
        //TODO: preform the actions.
    }

    /**
     * @see IActionDelegate#selectionChanged(IAction, ISelection)
     */
    public void selectionChanged(IAction action, ISelection selection) {
        if (!(selection instanceof IStructuredSelection)) {
            action.setEnabled(false);
            return;
        }
        IStructuredSelection sel = (IStructuredSelection) selection;

        if (!(sel.getFirstElement() instanceof IMethod)) {
            //Only handles IMethods.
            action.setEnabled(false);
            return;
        }

        action.setEnabled(true);
        this.currentMethod = (IMethod) sel.getFirstElement();
    }
}
我一直在修改
currentMethod
。我见过,但我不知道如何获得
文档
AST
,或者真正从
I方法
获得所需的任何东西。正确的方法是什么?

根据:

修改编译单元是对Java源代码最简单的修改 可以使用Java元素API来完成

例如,可以从编译单元查询类型。一旦你 如果有IType,您可以使用诸如createField之类的协议, createInitializer、createMethod或createType以添加源代码 类型的成员。源代码和有关 这些方法提供了成员的位置

我会尝试使用:

currentMethod.getCompilationUnit().getTypes()[0].createMethod(" hello world code goes here ",null,true,null); 
//not sure if progress monitor can be null, please check
根据:

i方法createMethod(字符串内容, Ijava元素的兄弟姐妹, 布尔力, IProgressMonitor(监视器) 抛出JavaModelException

创建并返回具有给定内容的此类型的方法或构造函数。 (可选)可以将新元素放置在指定的 兄弟姐妹如果未指定同级,则元素将附加到 这种

中可能已经存在具有相同签名的方法 这种。“力”参数的值会影响图像的分辨率 这种冲突:

true-在这种情况下,使用新内容创建方法

false-在这种情况下会引发JavaModelException


让我知道这是否是你想要的。

我已经弄明白了

以下内容以文本
System.out.println(“Hello”+“world”)为基础,并添加了到现有函数的末尾

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.dom.*;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;

public class HelloWorldAction implements IObjectActionDelegate {

    private Shell shell;

    private IMethod currentMethod;

    /**
     * Constructor for Action1.
     */
    public AddFace2() {
        super();
    }

    /**
     * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
     */
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
        shell = targetPart.getSite().getShell();
    }

    /**
     * @see IActionDelegate#run(IAction)
     */
    public void run(IAction action) {
        //Following is based off of the sample at http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.isv%2Fguide%2Fjdt_api_manip.htm

        try {
            ICompilationUnit cu = currentMethod.getCompilationUnit(); 
            String source = cu.getSource();
            Document document= new Document(source);


            //Get the compilation unit for traversing AST
            final ASTParser parser = ASTParser.newParser(AST.JLS8);
            parser.setSource(currentMethod.getCompilationUnit());
            parser.setResolveBindings(true);

            final CompilationUnit compilationUnit = (CompilationUnit) parser.createAST(null);

            // record modification - to be later written with ASTRewrite
            compilationUnit.recordModifications();

            // Get AST node for IMethod
            int methodIndex = currentMethod.getCompilationUnit().getSource().indexOf(currentMethod.getSource());

            //Convert to a MethodDeclaration.
            MethodDeclaration methodASTNode = (MethodDeclaration)NodeFinder.perform(compilationUnit.getRoot(), methodIndex, currentMethod.getSource().length());

            ASTRewrite rewrite = ASTRewrite.create(compilationUnit.getAST());

            Block blockOld = methodASTNode.getBody();

            //Create a copy of the old block.
            AST blockAST = AST.newAST(AST.JLS8);
            Block block = (Block) Block.copySubtree(blockAST, blockOld);

            //Add "System.out.println("hello" + " world");".
            MethodInvocation methodInvocation = blockAST.newMethodInvocation();

            QualifiedName name =  blockAST.newQualifiedName(
                    blockAST.newSimpleName("System"),
                    blockAST.newSimpleName("out"));

            methodInvocation.setExpression(name);
            methodInvocation.setName(blockAST.newSimpleName("println")); 
            InfixExpression infixExpression = blockAST.newInfixExpression();
            infixExpression.setOperator(InfixExpression.Operator.PLUS);
            StringLiteral literal = blockAST.newStringLiteral();
            literal.setLiteralValue("Hello");
            infixExpression.setLeftOperand(literal);
            literal = blockAST.newStringLiteral();
            literal.setLiteralValue(" world");
            infixExpression.setRightOperand(literal);
            methodInvocation.arguments().add(infixExpression);
            ExpressionStatement expressionStatement = blockAST.newExpressionStatement(methodInvocation);
            block.statements().add(expressionStatement);

            rewrite.replace(blockOld, block, null);


            // computation of the text edits
            TextEdit edits = rewrite.rewriteAST(document, cu.getJavaProject().getOptions(true));

            // computation of the new source code
            edits.apply(document);
            String newSource = document.get();

            // update of the compilation unit
            cu.getBuffer().setContents(newSource);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }

    /**
     * @see IActionDelegate#selectionChanged(IAction, ISelection)
     */
    public void selectionChanged(IAction action, ISelection selection) {
        if (!(selection instanceof IStructuredSelection)) {
            action.setEnabled(false);
            return;
        }
        IStructuredSelection sel = (IStructuredSelection) selection;

        if (!(sel.getFirstElement() instanceof IMethod)) {
            //Only handles IMethods.
            action.setEnabled(false);
            return;
        }

        action.setEnabled(true);
        this.currentMethod = (IMethod) sel.getFirstElement();
    }

}
这很有用(虽然我用另一种方法解决了它),但它不会将文本附加到现有方法中。但它有帮助。我会用我使用的解决方案发布一个答案。