如何捕获Eclipse插件中的方法内的更改 [英] How to capture changes inside methods in an Eclipse plugin

查看:162
本文介绍了如何捕获Eclipse插件中的方法内的更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为我Eclipse插件项目的一部分,我需要跟踪添加,删除和更改方法,以实现我之后的功能。

As part of my Eclipse plugin project I need to track additions, deletions and changes to methods in order to implement the functionality I'm after.

通过注册通过 JavaCore.addElementChangedListener 收听,并递归地遍历 IJavaElementDelta 直到 IJavaElementDelta.getElement()给出了一个受影响的方法的引用,我可以捕获添加和删除方法。

By registering a listener through JavaCore.addElementChangedListener and recursively traversing the IJavaElementDelta until the IJavaElementDelta.getElement() gives a reference to an affected method, I am able to capture method additions and deletions.

例如我将方法 a 加入课程 B 我得到:

E.g. I add method a into class B I get:

[Working copy] B.java[*]: {CHILDREN | FINE GRAINED | AST AFFECTED}
    B[*]: {CHILDREN | FINE GRAINED}
        a()[+]: {}]

问题是这个当已经存在的方法被编辑时不会发生:当我修改一个方法的实现并且为它触发一个改变事件时,增量的分辨率将停止在包含该方法的类中,而不是扩展到它。

The problem is that this does not take place when already existing methods are edited: when I modify the implementation of a method and a change event is triggered for it, the delta's resolution stops at the class containing this method instead of extending to it.

例如我修改课程 a 中的方法 B 我得到:

E.g. I modify the method a in class B I get:

[Working copy] B.java[*]: {CONTENT | FINE GRAINED | AST AFFECTED}

此信息不包含有关方法的信息 a ,即使它的实现刚刚改变。此问题可能部分连接到此旧的Eclipse错误报告 https://bugs.eclipse .org / bugs / show_bug.cgi?id = 327753

This information contains no information about method a, even though its implementation was just changed. This problem might be partially connected to this old Eclipse bug report https://bugs.eclipse.org/bugs/show_bug.cgi?id=327753

因此,问题是:如何跟踪和获取通知有更改实施方法的方法(不建立并存储AST多次)?

Thus, the question is: how can I track and get notified about methods that have their implementation changed (without building and storing the AST multiple times)?

推荐答案

经过有限的调查,我得出结论,在没有AST相关信息的情况下,不可能捕获方法中的更改。因此,我寻找最有效的方式来存储所需的最低限度的信息,以及最适合的方法来比较这些信息。

After a somewhat rigorous investigation, I've concluded that it is impossible to capture changes inside methods without AST-related information. Thus, I've looked for the most efficient way to store the bare minimum of information needed as well as for the most suitable approach to comparing this information.

这里是解决方案,我已经出来,根据几天的测试,它似乎是有效的,以便在每一个 ElementChangedEvent 中执行

Here is the solution that I've come up and according to a couple of days of testing it seems to be efficient enough to be feasible to execute during every single ElementChangedEvent.

// during each user-invoked-compile, these are processed and cleared
private static HashMap<String, IMethod> added = new HashMap<String, IMethod>();
private static HashMap<String, IMethod> changed = new HashMap<String, IMethod>();
private static HashMap<String, IMethod> removed = new HashMap<String, IMethod>();

// this persists through out the entire session
private static HashMap<String, ASTNode> subtrees = new HashMap<String, ASTNode>();

private static void attachModelPart() {
    JavaCore.addElementChangedListener(new IElementChangedListener() {

        @Override
        public void elementChanged(ElementChangedEvent event) {
            ... // added and removed IMethod handling
            IJavaElementDelta delta = event.getDelta();
            if (delta.getElement() instanceof CompilationUnit) {
                delta.getCompilationUnitAST().accept(new ASTVisitor() {

                    @Override
                    public boolean visit(MethodDeclaration node) {
                        String mName = ((TypeDeclaration) node.getParent()).getName()
                                .getFullyQualifiedName() + "." + node.getName().getFullyQualifiedName();
                        // Finding match for this methods name(mName) in saved method subtrees...
                        boolean methodHasChanged = false;
                        if (subtrees.containsKey(mName)) {
                            // Found match
                            // Comparing new subtree to one saved during an earlier event (using ASTNode.subtreeMatch())
                            methodHasChanged = !node.subtreeMatch(new ASTMatcher(), subtrees.get(mName));
                        } else {
                            // No earlier entry found, definitely changed
                            methodHasChanged = true;
                        }
                        if (methodHasChanged) {
                            // "changed" is a HashMap of IMethods that have been earlierly identified as changed
                            // "added" works similarly but for added methods (using IJavaElementDelta.getAddedChildren())
                            if (!changed.containsKey(mName) && !added.containsKey(mName)) {
                                // Method has indeed changed and is not yet queued for further actions
                                changed.put(mName, (IMethod) node.resolveBinding().getJavaElement());
                            }
                        }
                        // "subtrees" must be updated with every method's AST subtree in order for this to work
                        subtrees.put(mName, node);
                        // continue visiting after first MethodDeclaration
                        return true;
                    }
                });
            }
        }
    }
}

评论最受欢迎!

这篇关于如何捕获Eclipse插件中的方法内的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆