Eclipse插件开发:打开XML文件到指定行且不触发资源变更事件
解决Eclipse插件中跳转XML指定行不触发资源变更监听的问题
我之前开发Eclipse插件时也碰到过一模一样的问题——定位到文件指定行号时不小心触发了FileSystemChangesListener的resourceChanged()事件,搅乱了插件里的其他逻辑。设置TRANSIENT参数没用,是因为这个参数主要控制资源的临时状态,而我们常规的打开方式可能还是触发了不必要的资源状态变更。
下面是我摸索出来的纯视图定位、不修改资源本身的解决方案,完全不会触发资源变更监听:
核心思路
跳过任何可能修改资源属性的操作,只做编辑器内部的视图定位:先打开目标XML文件的编辑器,再通过文本编辑器的API直接定位到指定行号,整个过程不会改动文件的内容或元数据。
具体实现代码
import org.eclipse.core.resources.IFile; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; public void jumpToXmlLine(IFile xmlFile, int targetLine) { // 1. 创建编辑器输入(仅关联文件,不修改任何属性) IEditorInput editorInput = new FileEditorInput(xmlFile); try { // 2. 获取当前工作台页面并打开XML编辑器 IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); // 这里用WST的XML编辑器ID,也可以替换为DefaultTextEditor的ID:org.eclipse.ui.DefaultTextEditor IEditorPart editor = page.openEditor(editorInput, "org.eclipse.wst.xml.ui.internal.editor.XMLEditor"); // 3. 转换为文本编辑器,定位到指定行 if (editor instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editor; IDocument document = textEditor.getDocumentProvider().getDocument(editorInput); if (document != null) { // 注意:Eclipse文档的行号是0-based,若你的错误行号是1-based,需要减1 int zeroBasedLine = targetLine - 1; int offset = document.getLineOffset(zeroBasedLine); int lineLength = document.getLineLength(zeroBasedLine); // 仅做视图定位,不修改文件 textEditor.selectAndReveal(offset, lineLength); } } } catch (Exception e) { // 根据你的插件需求处理异常 e.printStackTrace(); } }
关键细节说明
编辑器ID选择:
- 如果是使用Eclipse自带的XML编辑器,用
org.eclipse.wst.xml.ui.internal.editor.XMLEditor(需要确保安装了WST插件); - 也可以通用文本编辑器ID
org.eclipse.ui.DefaultTextEditor,只要XML文件和该编辑器关联正确。
- 如果是使用Eclipse自带的XML编辑器,用
行号转换:
Eclipse的IDocument行号是从0开始计数的,如果你的错误信息里的行号是1-based(比如XML校验错误通常是1-based),一定要转换为0-based再传入。为什么不会触发资源变更:
selectAndReveal()只是编辑器内部的视图操作,仅改变编辑器的显示位置,不会修改文件的内容、修改时间或任何资源属性,因此FileSystemChangesListener不会收到变更事件。
排查之前的问题
你之前设置TRANSIENT无效,大概率是因为实现中调用了会修改资源状态的方法(比如标记资源为已修改、更新文件元数据等),换成上面的纯视图定位方式就能彻底避免这个问题。
内容的提问来源于stack exchange,提问作者The Impaler




