漸進式專案建立器

漸進式專案建立器是一種物件,它以建立器本身定義的方式來操作專案內的 資源。 漸進式專案建立器通常用於應用資源轉換來產生另一種資源或加工品。

外掛程式提供漸進式專案建立器資料給平台,以便實作專用資源轉換。 例如,平台 SDK 提供的 Java Development Tooling (JDT) 外掛程式定義一個漸進 式專案建立器,該建立器可於 Java 專案中新增或修改檔案的任何時候,將 Java 原 始檔編譯成類別檔,以及重新編譯受變更影響的其他任何檔案。

平台定義兩種建置類型:

漸進式建置隨資源變更差量起始。此差量反映建立器上次建立專案後所有資源變更的 網路效應。 此差量類似資源變更事件內使用的差量。

建立器最能經由範例來瞭解。Java Development Tooling (JDT) 提供一個 Java 編 譯程式(它由 Java 漸進式專案建立器驅動)來重新編譯受變更影響的檔案。 當觸發完整建置時,會編譯專案中所有 .java 檔。 任何發現的編譯 問題都會新增為受影響 .java 檔上的問題標示元。當觸發漸進式建置時,建 立器會選擇性地重新編譯資源差量中描述的新增、變更或其他受影響的 .java 檔,並在必要時更新問題標示元。任何不再適合的 .class 檔 或標示元都會被除去。

漸進式建置對於具有數以百計或千計資源的專案有顯著的效能優點,大部份資源在將 來任何給定的時間上不會改變。

漸進式建置的技術盤查是正確判定哪些需要重新建置。例如,Java 建立器維護的內 部狀態,包括像報告編譯問題清單及相依關係圖形等事件。此資訊在漸進式建 置期間用來識別為回應 Java 資源變更而需要重新編譯的類別。

雖然建置的基本結構是在平台中定義,但實際工作是在外掛程式中完成。 實作複雜漸進式建立器的型樣超出本討論範圍,因為實作方式與特定建立器設計有關。

呼叫建置

下列其中一種方法可明確地呼叫建立器:

事實上,工作台使用者藉由選取資源導覽器功能表中的對應指令來觸發建置。

自動建置期間,平台也可隱含地呼叫漸進式專案建立器。 若啟用,則每當工作區有變更便會執行自動建置。

定義漸進式專案建立器

org.eclipse.core.resources.builders 延伸點用來提供漸進式專案建立器資料給平台。下列標記顯示假設的外掛程 式 com.example.builders 如何提供漸進式專案建立器資料。

<extension
    point="org.eclipse.core.resources.builders">
    <builder
        id="com.example.builders"
        name="MyBuilder">
        <run 
            class="com.example.builders.BuilderExample">
            <parameter name="optimize" value="true" />
            <parameter name="comment" value="Builder comment" />
        </run>

    </builder>

</extension>

延伸點中識別的類別必須延伸平台類別 IncrementalProjectBuilder

public class BuilderExample extends IncrementalProjectBuilder {
    IProject[] build(int kind, Map args, IProgressMonitor monitor)
            throws CoreException {
        // 在此處新增建置邏輯
        return null;
    }
    protected void startupOnInitialize() {
        // 在此處新增建立器 init 邏輯
    }
}

build() 方法起始的建置處理程序,它包括所要求建置種類 FULL_BUILDINCREMENTAL_BUILDAUTO_BUILD 的相關資 訊。如果所要求的是漸進式建置,便會提供資源差量來說明上次建置後專案資源的變 更。 下列片段進一步修正 build() 方法。

protected IProject[] build(int kind, Map args, IProgressMonitor monitor
        throws CoreException {
    if (kind == IncrementalProjectBuilder.FULL_BUILD) {
        fullBuild(monitor);
    } else {
        IResourceDelta delta = getDelta(getProject());
        if (delta == null) {
            fullBuild(monitor);
        } else {
            incrementalBuild(delta, monitor);
        }
    }
    return null;
}

有時在建置專案 "X"、建立器需要其他某個專案 "Y" 變更 的相關資訊時會發生這個修正。 (例如,如果 X 中的 Java 類別實作 Y 中提 供的介面。)當建置 X 時,呼叫 getDelta(Y) 可取得 Y 的差量。 為確保平台可提供這種差量,X 的建立器必須宣告 X 和 Y 之間的相依關係 ,方法是從上一個 build() 呼叫傳回含有 Y 的陣列。如果建立器沒 有相依關係,則僅傳回空值。有關進一步資訊,請參閱 IncrementalProjectBuilder

完整建置

處理完整建置要求所需的邏輯對外掛程式而言是特定的。可能包括造訪專案中每個資 源(如果建置是針對專案觸發),甚或查驗其他專案間是否有相依關係。下 列片段建議如何實作完整建置。

protected void fullBuild(final IProgressMonitor monitor) throws CoreException {
    try {
        getProject().accept(new MyBuildVisitor());
    } catch (CoreException e) { }
}

建置訪客針對特定資源執行建置(然後回答 True 來繼續造訪所有子項資源)。

class MyBuildVisitor implements IResourceVisitor {
    public boolean visit(IResource res) {
        //建置指定的資源。
        //傳回 True 以繼續造訪子項。
        return true;
    }
}

繼續執行造訪處理程序,直到訪遍整個資源樹狀結構為止。

漸進式建置

當執行漸進式建置時,您使用資源變更差量代替整個專案。

protected void incrementalBuild(IResourceDelta delta, 
        IProgressMonitor monitor) throws CoreException {
    // 由訪客完成此工作。
    delta.accept(new MyBuildDeltaVisitor());
}

請注意:以漸進式建置而言,建置訪客使用資源差量樹狀結構代替整個資源樹狀結構。

繼續執行造訪處理程序,直到訪遍整個資源差量樹狀結構為止。 變更的特定本質類似說明於實作資源變 更接聽器中的本質。關於漸進式專案建立器的一個重要差異,通常您是 根據特定專案而非整個工作區來使用資源差量。

建立漸進式專案建立器與專案的關聯性

欲使建立器適用指定的專案,它必須併入專案的建置規格中。 專案的建置規格是建置專案時依序執行的指令清單。每一個指令命名單一漸進式專案 建立器。

下列片段新增建立器為現行建立器清單中第一個建立器。

IProjectDescription desc = project.getDescription();
ICommand[] commands = desc.getBuildSpec();
boolean found = false;

for (int i = 0; i < commands.length; ++i) {
    if (commands[i].getBuilderName().equals(BUILDER_ID)) {
        found = true;
        break;
    }
}
if (!found) { 
    //新增建立器到專案中
    ICommand command = desc.newCommand();
    command.setBuilderName(BUILDER_ID);
    ICommand[] newCommands = new ICommand[commands.length + 1];

    // 在其他建立器之前新增它。
    System.arraycopy(commands, 0, newCommands, 1, commands.length);
    newCommands[0] = command;
    desc.setBuildSpec(newCommands);
    project.setDescription(desc, null);
}

配置專案的建立器只做一次,通常是在專案建立完成時。