You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Eclipse插件中扩展IDocumentListener实现文档变更监听?

实现Eclipse插件中文档变更监听的方案

嘿,我来帮你搞定这个问题!确实,IDocumentListener本身没有对应的扩展点,没法直接通过扩展点注册实现,但我们可以换个思路——通过监听编辑器的生命周期,在编辑器打开时动态给文档绑定监听器,这样就能实现文档变更的监听和标记添加了。下面是具体的实现步骤:

1. 实现编辑器监听器,捕捉编辑器打开事件

我们可以用IPartListener2来监听工作台部件的状态变化,它能覆盖编辑器打开、激活、关闭等场景,比IEditorListener更全面。先创建一个监听器类:

import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentProvider;

public class EditorPartListener implements IPartListener2 {

    @Override
    public void partOpened(IWorkbenchPartReference partRef) {
        // 判断打开的部件是不是文本编辑器
        if (partRef.getPart(false) instanceof ITextEditor) {
            ITextEditor textEditor = (ITextEditor) partRef.getPart(false);
            IDocumentProvider provider = textEditor.getDocumentProvider();
            IDocument document = provider.getDocument(textEditor.getEditorInput());
            
            // 给文档添加自定义的文档监听器
            if (document != null) {
                document.addDocumentListener(new CustomDocumentListener(textEditor));
            }
        }
    }

    // 编辑器关闭时移除监听器,避免内存泄漏
    @Override
    public void partClosed(IWorkbenchPartReference partRef) {
        if (partRef.getPart(false) instanceof ITextEditor) {
            ITextEditor textEditor = (ITextEditor) partRef.getPart(false);
            IDocumentProvider provider = textEditor.getDocumentProvider();
            IDocument document = provider.getDocument(textEditor.getEditorInput());
            
            if (document != null) {
                document.removeDocumentListener(new CustomDocumentListener(textEditor));
            }
        }
    }

    // 其他未用到的方法可以留空实现
    @Override
    public void partActivated(IWorkbenchPartReference partRef) {}
    @Override
    public void partDeactivated(IWorkbenchPartReference partRef) {}
    @Override
    public void partBroughtToTop(IWorkbenchPartReference partRef) {}
    @Override
    public void partHidden(IWorkbenchPartReference partRef) {}
    @Override
    public void partVisible(IWorkbenchPartReference partRef) {}
    @Override
    public void partInputChanged(IWorkbenchPartReference partRef) {}
}

2. 在插件激活时注册编辑器监听器

在你的插件Activator类的start方法里,把上面的监听器注册到工作台的部件服务中,这样就能全局监听编辑器的状态变化了:

import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

public class Activator extends AbstractUIPlugin {
    private static Activator plugin;
    private EditorPartListener partListener;

    @Override
    public void start(BundleContext context) throws Exception {
        super.start(context);
        plugin = this;
        
        // 注册编辑器监听器
        IWorkbench workbench = PlatformUI.getWorkbench();
        partListener = new EditorPartListener();
        workbench.getActiveWorkbenchWindow().getPartService().addPartListener(partListener);
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        // 停止时移除监听器
        if (partListener != null) {
            PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPartService().removePartListener(partListener);
            partListener = null;
        }
        plugin = null;
        super.stop(context);
    }

    public static Activator getDefault() {
        return plugin;
    }
}

3. 实现自定义IDocumentListener,添加文本标记

接下来写核心逻辑:当文档变更时,在编辑器中添加标记。这里用Eclipse的Annotation和AnnotationModel实现编辑器内的标记(如果需要在项目资源管理器也显示标记,可以用IMarker),示例如下:

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;

public class CustomDocumentListener implements IDocumentListener {
    private ITextEditor textEditor;

    public CustomDocumentListener(ITextEditor editor) {
        this.textEditor = editor;
    }

    @Override
    public void documentAboutToBeChanged(DocumentEvent event) {
        // 可选:处理变更前的逻辑,比如记录旧内容
    }

    @Override
    public void documentChanged(DocumentEvent event) {
        // 文档变更后,添加标记到变更位置
        IAnnotationModel annotationModel = textEditor.getDocumentProvider().getAnnotationModel(textEditor.getEditorInput());
        if (annotationModel != null) {
            // 创建自定义注解,这里用默认警告样式,可自行定义注解类型
            Annotation annotation = new Annotation("com.your.plugin.annotation.documentChangeMarker", false, "文档已变更");
            // 将注解添加到变更发生的位置
            annotationModel.addAnnotation(annotation, new org.eclipse.jface.text.Position(event.getOffset(), event.getLength()));
        }
    }
}

4. 自定义注解样式(可选)

如果想让标记有专属样式,在plugin.xml中添加以下配置,定义注解类型和呈现方式:

<extension point="org.eclipse.ui.editors.annotationTypes">
    <type
        name="com.your.plugin.annotation.documentChangeMarker"
        super="org.eclipse.ui.workbench.texteditor.warning"
        markerType="com.your.plugin.documentChangeMarker">
    </type>
</extension>

<extension point="org.eclipse.ui.editors.annotationPresentation">
    <presentation
        annotationType="com.your.plugin.annotation.documentChangeMarker"
        class="org.eclipse.ui.texteditor.DefaultAnnotationPresenter">
    </presentation>
</extension>

注意事项

  • 一定要在编辑器关闭时移除文档监听器,避免内存泄漏(我们已经在partClosed方法中处理)
  • 若需要避免标记堆积,可以在每次变更前清除旧的同类型注解
  • 如果要监听非编辑器打开的文档,可以考虑监听IDocumentProvider的文档创建事件,不过这种场景比较少见

内容的提问来源于stack exchange,提问作者Maruthamalai A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:14:18