語法模型 (`IStructuredDocument`) 解決「文本結構」問題,語義模型 (`IStructuredModel`) 解決「業務含義」問題。本文深入剖析 `IStructuredModel` 的架構角色、模型句柄機制、基於 Document 的 DOM 構建流程、模型管理器協調邏輯,並揭示為什麼高級編輯功能(智能屬性提示、語義驗證、重構)必須依賴語義模型。
IStructuredModel (公共模型接口)
├── getDocument() : IStructuredDocument // 關聯的語法文檔
├── getModelState() : int // 模型狀態:UNLOADED, LOADING, LOADED, RECONCILING...
├── getModelListenerList() : ModelListenerList // 監聽器管理
├── addModelListener / removeModelListener
└── getAdapter(Class) : Object // 適配器模式,獲取 IDOMDocument/ICSSDocument
IDOMDocument extends IStructuredModel // XML/HTML/JSP 語義模型
├── getDocumentElement() : Element // DOM 根元素
├── getElementById / getElementsByTagName...
└── 完整 W3C DOM Level 2/3 接口
ICSSDocument extends IStructuredModel // CSS 語義模型 (WTP 自研,非標準 DOM)
└── getStylesheet() : CSSStyleSheet
`IStructuredModel` 實例不直接持有文檔內容,而是通過 **句柄** 間接引用:
interface IModelHandle {
String getModelTypeId(); // 如 "org.eclipse.wst.xml.core.xmlsource"
String getLocation(); // 文件路徑/URI
long getModificationTime(); // 文件修改時間戳
boolean isLoaded(); // 模型是否已載入內存
IStructuredModel getModel(); // 獲取/觸發模型加載
}
文本變更
↓
IDocumentPartitioner 增量分區 (語法區域更新)
↓
StructuredDocumentReconciler 協調器觸發
↓
IStructuredDocument 節點樹增量更新 (語法層)
↓
ModelBuilder 建構器 遍歷語法節點樹
↓
轉換規則引擎 (每種語言自定義)
├── HTML: HTMLTagRule, HTMLEntityRule...
├── JSP: JSPDirectiveRule, JSPScriptletRule, JSPActionRule...
├── XML: XMLDeclarationRule, XMLElementRule...
└── CSS: CSSRuleSetRule, CSSPropertyRule...
↓
構建 W3C DOM 樹 (IDOMDocument)
├── Element 節點 → 對應語法 ELEMENT 節點
├── Attr 節點 → 對應語法 ATTRIBUTE 區域
├── Text/CDATA/Comment → 對應語法 TEXT/COMMENT 節點
└── 命名空間解析、Schema 關聯、ID 屬性註冊
↓
ModelManager 緩存模型實例,通知 ModelListener
↓
編輯器功能消費模型:
- Content Assist: 查詢 DOM 元素定義、屬性類型、枚舉值
- Validator: 遍歷 DOM 核對 Schema/DTD、檢查必需屬性、嵌套規則
- Hyperlink: 解析屬性值中的 URI、TLD 標籤定義、CSS 類定義
- Formatter: 基於 DOM 結構重新序列化格式化
| 直接文本 → Model | Document → Model (WTP 選擇) |
|---|---|
| 需自行實現完整語法分析器(極其複雜) | 復用 SSE 成熟的分區器、協調器、節點樹 |
| 容錯性差:語法錯誤導致模型構建失敗 | 語法層天然容錯(不完整標籤也有區域),模型構建可部分成功 |
| 增量更新極難實現 | 語法層增量更新成熟,模型僅需處理受影響子樹 |
| 多語言混合 (JSP=HTML+Java+JSP標籤) 幾乎不可維護 | 分區器天然分離語言區域,各語言 ModelBuilder 獨立處理 |
ModelManager (單例)
├── getModelForRead(IModelHandle) : IStructuredModel
│ └── 1. 緩存命中 → 返回
│ └── 2. 未命中 → 創建 ModelBuilder → 構建 → 緩存 → 返回
├── getModelForWrite(IModelHandle) : IStructuredModel
│ └── 獲取寫鎖,確保同一時刻僅一寫入者
├── releaseModel(IStructuredModel)
│ └── 引用計數歸零 → 可選釋放 (內存壓力時)
├── addModelListener / removeModelListener
└── 模型釋放策略:LRU + 內存閾值 + 文件修改時間檢查
| 功能 | 僅靠語法模型 (Document) | 語義模型 (Model) 支撐 |
|---|---|---|
| 屬性值智能提示 | 只知屬性名字符串,不知類型/枚舉 | 查詢 Schema/DTD/TLD 獲取類型、枚舉、必填性 |
| 標籤嵌套驗證 | 只知標籤匹配,不知語義父子關係 | 基於 Schema/DTD 校驗嵌套合法性 |
| 跳轉到定義 | 無法解析引用目標 | 解析 TLD、XSD、CSS 類定義位置 |
| 重構 (重命名 ID/類) | 純文本替換,極易誤傷 | 基於 DOM 節點精準重命名,更新所有引用 |
| 格式化 | 基於縮進規則,不理解語義結構 | 基於 DOM 樹結構智能換行、縮進、屬性排序 |
下一篇將開發 `StructuredModelView`,可視化 `IDOMDocument` DOM 樹,對比語法樹差異,實時觀察:
這將徹底釐清「語法區域」與「語義節點」的邊界,為定制 Content Assist/Validator 奠定不可動搖的模型認知基石。