首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Eclipse 插件開發:程序化刷新工作區與觸發增量構建

     編輯:Java 相關知識

Eclipse 插件開發中,自動生成代碼、模型轉換代碼 (UML→Java) 後,必須通知工作區刷新並觸發增量構建,否則生成文件不會被編譯、索引、顯示在 Package Explorer 中。本文給出核心 API 直接可用的代碼片段。

核心接口體系:IResource 及其子類型

所有可刷新/構建對象實現 org.eclipse.core.resources.IResource:

接口代表典型實現類
IResource統一根接口Resource (抽象基類)
IContainer容器 (項目/文件夾)Container
IProject項目Project
IFolder文件夾Folder
IFile文件File
IWorkspaceRoot工作區根WorkspaceRoot

繼承關係

IResource
  ├─ IContainer
  │    ├─ IFolder
  │    ├─ IProject
  │    └─ IWorkspaceRoot
  └─ IFile

一、程序化刷新資源

核心方法

void refreshLocal(int depth, IProgressMonitor monitor) throws CoreException

參數說明

  • depth:
    • IResource.DEPTH_ZERO (0) — 僅刷新資源本身
    • IResource.DEPTH_ONE (1) — 刷新資源及直接子成員
    • IResource.DEPTH_INFINITE (2) — 遞歸刷新整棵子樹 (最常用)
  • monitor:進度監控器,可傳 null (無進度上報) 或 new NullProgressMonitor()

常用場景代碼

// 1. 刷新整個項目 (生成代碼後最常用)
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject("MyProject");
project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());

// 2. 刷新特定文件夾 (如 target/generated-sources)
IFolder folder = project.getFolder("target/generated-sources");
folder.refreshLocal(IResource.DEPTH_INFINITE, monitor);

// 3. 刷新單個文件
IFile file = folder.getFile("GeneratedClass.java");
file.refreshLocal(IResource.DEPTH_ZERO, monitor);

// 4. 刷新整個工作區 (慎用,性能開銷大)
ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, monitor);

異步刷新 (非阻塞 UI)

WorkspaceJob job = new WorkspaceJob("刷新生成代碼") {
    @Override
    public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
        project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
        return Status.OK_STATUS;
    }
};
job.setUser(true);  // 用戶可見任務
job.schedule();

二、觸發增量構建 (Clean/Full/Incremental)

核心 API

IWorkspace.build(int kind, IProgressMonitor monitor)

構建類型常量 (IncrementalProjectBuilder)

FULL_BUILDINCREMENTAL_BUILDCLEAN_BUILDAUTO_BUILD
常量值行為
0全量構建 (清理後重建)
1增量構建 (默認,僅編譯變更)
2清理構建輸出 (不編譯)
3觸發自動構建 (若啟用)

代碼示例

IWorkspace workspace = ResourcesPlugin.getWorkspace();

// 1. Clean All (最徹底)
workspace.build(IncrementalProjectBuilder.CLEAN_BUILD, new NullProgressMonitor());
// 緊接觸發全量構建
workspace.build(IncrementalProjectBuilder.FULL_BUILD, monitor);

// 2. 僅 Clean 單個項目
IProject project = workspace.getRoot().getProject("MyProject");
project.build(IncrementalProjectBuilder.CLEAN_BUILD, 
    new SubProgressMonitor(monitor, 1));  // 進度分配

// 3. 觸發單項目增量構建
project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);

// 4. 自動構建模式下,通常無需手動調用
// 但代碼生成後立即需編譯時,建議顯式調用 INCREMENTAL_BUILD

三、組合最佳實踐:生成代碼 → 刷新 → 構建

public void generateAndBuild(IProject project, IProgressMonitor monitor) throws CoreException {
    try {
        // 1. 執行代碼生成邏輯 (寫入文件到項目中)
        CodeGenerator.generate(project);  // 你的生成邏輯

        // 2. 刷新工作區 (讓 Eclipse 感知文件系統變更)
        project.refreshLocal(IResource.DEPTH_INFINITE, monitor);

        // 3. 觸發增量構建 (編譯新生成的 Java 文件)
        project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);

    } catch (CoreException e) {
        // 回滾或報錯
        throw new CoreException(new Status(IStatus.ERROR, PLUGIN_ID, "生成構建失敗", e));
    }
}

四、進階:參與構建生命周期 (Builder)

若插件需深度集成構建過程 (如自定義編譯器、模型驗證),實現 IncrementalProjectBuilder:

public class MyCustomBuilder extends IncrementalProjectBuilder {
    public static final String BUILDER_ID = "com.example.myCustomBuilder";

    @Override
    protected IProject[] build(int kind, Map args, IProgressMonitor monitor) 
            throws CoreException {
        // kind: FULL/INCREMENTAL/CLEAN
        if (kind == CLEAN_BUILD) {
            clean(monitor);
            return null;
        }
        
        // 增量構建:獲取變更資源
        IResourceDelta delta = getDelta(project);
        if (delta == null) {  // 全量構建
            fullBuild(monitor);
        } else {
            incrementalBuild(delta, monitor);
        }
        return null;
    }
    
    // 在 plugin.xml 註冊
    // 
    //   
    //     
    //   
    // 
}

避坑指南

  1. 空指針防護:獲取資源前檢查 exists(),避免 CoreException: Resource not found
  2. 進度監控器:長耗操作必須傳入真實 IProgressMonitor,支持取消/進度顯示
  3. 線程規則:工作區修改操作需在 WorkspaceJob 或 IWorkspaceRunnable 中運行 (自動獲取寫鎖)
  4. 避免死循環:構建過程中產生文件再觸發刷新構建 → 無限循環,需在 Builder 中標記 derived=true 排除衍生資源
  5. 性能:盡量針對最小範圍刷新/構建,全工作區操作極其耗時

掌握 refreshLocal 與 build 核心 API,即可實現「代碼生成即時生效」的流暢插件體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved