如何在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
相关产品推荐
相关产品推荐

