【问题标题】:Eclipse Validator: Listen to inherited ResourceEclipse Validator:监听继承的资源
【发布时间】:2014-11-24 15:50:17
【问题描述】:

我有一些用于 Eclipse 的自定义(逻辑)验证器,但都面临同样的问题:

某些逻辑的实际实现可以在任何父类中进行。

因此,每当有问题的资源发生变化时,我都可以在继承树上查看所需的代码是否发生在任何父类中 - 如果没有,我将在经过验证的文件本身中放置一个标记。

这个标记来自c。每当对有问题的资源进行更改时,都会得到验证。但是,如果其中一个父类发生更改,我如何触发重新验证?

是否可以将某种“验证器回调”放入其他文件中,这将触发对给定文件的验证?

即三个类:A extends BB extends C - 现在,验证器在 A 上注明,ABC 都没有扩展 X - 由于注释,这是 A 所必需的. (逻辑合约)

现在A 中的错误标记应在BC 被修改后立即重新评估。 (目前我正在使用一个 delta-builder ,只要A 发生变化,它就会调用验证......)

简而言之:我想放置一个“标记”,每当 X 资源中的一个发生变化时都会重新验证。

【问题讨论】:

    标签: eclipse validation delta


    【解决方案1】:

    玩了一段时间后,我终于找到了一个99% 的解决方案


    好消息:有可能。

    坏消息:这是 DIY。我找不到任何有用的方法来实现我想要的。


    以下帖子应概述有关我的问题的解决方案。可能有更好、更有效或更简单的解决方案,但不幸的是,围绕 eclipse 验证框架的文档非常薄 - 所以我想分享我的解决方案 - 接受它,改进它 - 或者忽略它:)


    首先,您应该了解我试图解决的实际问题。因此,我提供了简短的 sn-ps,而不涉及验证器或我的代码线路的太多细节:

    在我的项目中,我使用的是 Hibernate——因此很多类都使用 @Entity 注释。当使用 Hibernate 和 LazyLoadingone 时,需要(手动)确保 PersistentBags 在访问时被初始化。

    在我们的应用程序中,LazyEntity 类中有一个名为initializeCollection(Collection c) 的方法,它处理它周围的一切。

    这导致了一个逻辑合约我的验证器应该验证:

    • 只要有一个带有@Entity 注释的class,并且该类在其任何集合中使用FetchType.LAZY必须满足两个约束:
    • A.) 类 - 或其任何祖先 - 需要扩展 LazyEntity
    • B.) 有问题的collectiongetter 需要在返回collection 之前调用initializeCollection()

    我将重点关注B 点,因为这是验证问题出现的地方:如何重新验证实际实体,当它的祖先发生变化时?


    我修改了实际的验证方法,有两个IFiles作为属性:

    public void checkLazyLoadingViolations(IFile actualFile, IFile triggeredFile) {
        //validation of actualFile takes place here
    }
    

    增量构建器和增量构建器都像这样调用这个方法:

    class LazyLoadingResourceVisitor implements IResourceVisitor {
        public boolean visit(IResource resource) {
            if (resource instanceof IFile) {
                checkLazyLoadingViolations((IFile) resource, (IFile) resource);
            }
            // return true to continue visiting children.
            return true;
        }
    }
    

    现在 - 在第一步中 - 验证器本身正在注意验证 actualFile 并冒泡继承树以验证任何父文件。如果验证器命中最顶层父级,但没有找到所需的扩展,则放置一个额外的标记

    标记的放置是通过以下方法进行的。 如果应该放置标记的文件与 eclipse 调用验证的文件不同,IMarker.USER_EDITABLE 属性用于存储调用验证的文件的路径(在为了重新触发验证)

    /**
         * Creates a Marker in the give IFile, considering if it should be a direct
         * marker, or a dependency marker, which our Validator can resolve later.
         * 
         * @param actualFile
         *            The file that is currently validated.
         * @param triggeredFile
         *            The file on which eclipse invoked the validation.
         * @param message
         *            The message for the Marker.
         * @param lineNumber
         *            the line number, where the Marker should appear.
         * @param severity
         *            the severity of the marker.
         * @param callbackPath
         *            The full path to the file that should be validated, when the
         *            marker is revalidated.
         */
        public void addMarker(IFile actualFile, IFile triggeredFile,
                String message, int lineNumber, int severity, String callbackPath) {
    
            try {
                IMarker marker = actualFile.createMarker(MARKER_TYPE);
                marker.setAttribute(IMarker.MESSAGE, message);
                marker.setAttribute(IMarker.SEVERITY, severity);
                marker.setAttribute(IMarker.LINE_NUMBER, lineNumber == -1 ? 1
                        : lineNumber);
                if (callbackPath != null) {
                    marker.setAttribute(IMarker.USER_EDITABLE, "callback:"
                            + triggeredFile.getFullPath());
                }
            } catch (CoreException e) {
                // eclipse made a boo boo.
            }
        }
    

    现在,设置了验证错误:每个实际类都包含其错误 - 如果继承树中的验证失败,父类也包含一个标记:

    (本例中为AdminUser extends TestUser

    当验证器因更改而在“父”文件上触发时,它会抓取所有标记,并检查标记是否提供 callback 属性。如果是这样,验证器会调用资源的验证而不是,而不仅仅是验证父级:

    IMarker[] markers = null;
                try {
                    markers = actualFile.findMarkers(IMarker.PROBLEM, true,
                            IResource.DEPTH_INFINITE);
    
                    for (IMarker m : markers) {
    
                        // Our marker type?
                        if (m.getType().equals(MARKER_TYPE)) {
    
                            // dependent resource defined?
                            if (m.getAttribute(IMarker.USER_EDITABLE) != null) {
                                if (m.getAttribute(IMarker.USER_EDITABLE)
                                        .toString().startsWith("callback:")) {
                                    String otherFile = m
                                            .getAttribute(IMarker.USER_EDITABLE)
                                            .toString().replace("callback:", "");
    
                                    // call validation for that file as well.
                                    // (recursion)
                                    String relOther = otherFile.split(Pattern.quote(actualFile.getProject().getFullPath().toString()))[1];
                                    IFile fileToValidateAsWell = actualFile
                                            .getProject().getFile(relOther);
    
                                    //remove old markers!
                                    deleteMarkers(fileToValidateAsWell);
    
                                    //revalidate - which has no impact but triggering the root-resource again!
                                    //this will recreate the just deleted markers if problem is not resolved.
                                    checkLazyLoadingViolations(
                                            fileToValidateAsWell, triggeredFile);
                                }
                            }
                        }
                    }
                } catch (CoreException e1) {
    
                }
    

    最后,对继承树中 root 文件的更改会导致 leaf 文件被重新验证:

    • 等等。正确调用initializeCollection-Method 时,完全没有错误:)


    目前唯一的权衡是:IF父文件有效 - 并被修改为无效 - 它不会重新触发叶的验证,因为没有 error-marker 包含任何回调信息。

    第一次执行完整构建时会出现该错误。 - 目前,我可以忍受。

    简而言之逻辑

    • 如果经过验证的资源是叶子
      • 在叶子中放置标记
      • 将标记放在最顶层的父级中,同时添加callback link 作为标记属性。
    • 如果经过验证的资源是 root
      • 删除标记​​li>
      • 在现有标记内callback link 提供的链接 上调用验证,实际情况为1,并在适用时重新创建所有标记。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多