WTP 結構化源碼編輯框架 (SSE) 的核心在於兩大數據模型:語法層的 `IStructuredDocument` 與語義層的 `IStructuredModel`。本文深入剖析 `IStructuredDocument` 的類型體系、Composite 模式結構、區域劃分機制,並開發一個「Document 結構分析視圖」工具,以可視化方式驗證模型理解,為後續編輯器定制建立堅實模型認知。
IStructuredDocument 類型體系與核心實現
IDocument (JFace Text)
↑
IStructuredDocument (org.eclipse.wst.sse.core.internal.provisional.text)
↑
BasicStructuredDocument (抽象基類,適配器模式)
↑
JobSafeStructuredDocument (實際運行時實現,線程安全)
↑
StructuredDocument (具體實現,持有區域列表、節點樹)
- `IDocument`:JFace Text 基礎文檔接口,純文本操作(get, replace, addPosition)。
- `IStructuredDocument`:擴展 `IDocument`,增加**結構化能力**——區域劃分、節點樹、模型同步通知。
- `JobSafeStructuredDocument`:線程安全包裝,所有修改操作提交至 Job 队列,保證 UI 線程與協調器線程並發安全。
結構化文檔核心結構:區域與節點樹
1. 文本區域劃分
文檔被劃分為互不重疊、覆蓋全文的 `ITextRegion` 區域,每個區域有類型(Partition Type):
| JSP 分區類型 | 內容範例 | 用途 |
| JSP_DEFAULT | HTML 文本、標籤 | 默認 HTML 區域 |
| JSP_SCRIPTLET | <% ... %> | Java 代碼片段 |
| JSP_EXPRESSION | <%= ... %> | 表達式輸出 |
| JSP_DIRECTIVE | <%@ page ... %> | 頁面指令 |
| JSP_DECLARATION | <%! ... %> | 成員變量/方法聲明 |
| JSP_COMMENT | <%-- --%> | JSP 註釋(不輸出到客戶端) |
| HTML_COMMENT | <!-- --> | HTML 註釋 |
分區器 (`IDocumentPartitioner`) 負責維護區域列表,文本變更時增量更新。
2. 節點樹 — Composite 模式
`IStructuredDocument` 構建節點樹,每個節點實現 `INode` / `IStructuredNode`:
IStructuredNode (接口)
├── getType() : String // 節點類型:ELEMENT, TEXT, COMMENT, CDATA...
├── getStartOffset() : int // 文檔起始偏移
├── getEndOffset() : int // 文檔結束偏移
├── getParent() : IStructuredNode
├── getChildren() : List<IStructuredNode>
├── getAttributes() : Map<String, String> // 僅元素節點
└── getText() : String // 文本內容
樹根為 `StructuredDocument` 實例,葉子節點為文本/註釋,內部節點為元素。此樹反映語法結構,而非語義(如 `` 只是元素節點,不知其語義為包含動作)。
實戰工具:Structured Document 分析視圖
開發一個 Eclipse View,實時展示當前編輯器的 `IStructuredDocument` 節點樹,支援:
- 編輯器激活 → 視圖自動刷新樹模型
- 光標移動 → 視圖自動選中對應節點(偏移量匹配)
- 文本變更 → 增量更新樹(監聽 `IDocumentListener`)
- 雙擊樹節點 → 編輯器高亮對應文本區域
- 編輯器關閉 → 清空視圖
核心實現片段
// 1. 獲取當前編輯器的 StructuredDocument
IEditorPart editor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editor instanceof StructuredTextEditor) {
IDocumentProvider provider = ((StructuredTextEditor) editor).getDocumentProvider();
IDocument document = provider.getDocument(editor.getEditorInput());
if (document instanceof IStructuredDocument) {
IStructuredDocument sdoc = (IStructuredDocument) document;
// 2. 遍歷節點樹構建視圖輸入
IStructuredNode root = sdoc.getStructuredNode(); // 根節點
buildTreeViewer(root);
}
}
// 3. 光標位置 → 節點選中
int offset = ((StructuredTextEditor) editor).getSelectionProvider().getSelection().getOffset();
IStructuredNode node = sdoc.findNodeAtOffset(offset); // 關鍵 API
if (node != null) treeViewer.setSelection(new StructuredSelection(node));
為什麼區分 Document (語法) 與 Model (語義)?
| 維度 | IStructuredDocument (語法層) | IStructuredModel / IDOMDocument (語義層) |
| 關注點 | 文本區域劃分、標籤匹配、語法結構 | 元素語義、屬性類型、命名空間、Schema 驗證 |
| 構建來源 | 直接解析文本,容錯性強(不完整標籤也能分區) | 基於 Document 節點樹轉換,需較完整語法 |
| 典型用途 | 語法著色、大綱視圖、折疊、基本內容助手 | 高級內容助手(屬性值枚舉)、驗證器、重構、超鏈接 |
| 更新頻率 | 每次按鍵觸發增量協調 | 延遲構建,或協調後批量同步 |
關鍵認知總結
- `IStructuredDocument` 是**所有編輯器功能的基石**——分區器、協調器、節點樹、偏移量映射。
- 節點樹採用 **Composite 模式**,統一 `IStructuredNode` 接口,便於統一遍歷、查詢、修改。
3. `findNodeAtOffset(offset)` 是**光標位置映射到語法節點**的核心 API,驅動大綱同步、上下文感知提示、錯誤定位。
4. Document **不感知 Model**,但 Model **依賴 Document** 構建。這種單向依賴簡化了協調邏輯。
5. 開發分析視圖是理解模型的**最佳實踐**——可視化即驗證,調試時可實時觀察模型變化。
下一篇預告
深入 `IStructuredModel`:模型句柄機制、XML DOM 構建流程、模型管理器、CSS/JS 模型差異、Model 分析視圖開發。理解語義模型,才能實現「屬性值智能枚舉」、「標籤嵌套語義驗證」、「跳轉到 TLD 定義」等高級功能。
- 上一篇文章: Eclipse 插件開發實戰:基於 WTP 打造自定義 JSP 編輯器(二)— 構建編輯器雛形與 JFace Text 基石
- 下一篇文章: Eclipse 插件開發實戰:基於 WTP 打造自定義 JSP 編輯器(四)— 開發 Structured Document 分析視圖驗證模型認知
Copyright ©
程式碼之家 All Rights Reserved