mcpField
F
fix-cyclic-deps

fix-cyclic-deps

github.com/ui5開発44145 回インストール1 週間前に更新
リポジトリ

fix-cyclic-deps について

fix-cyclic-depsは、UI5モジュールの循環依存を検出して解消する開発スキルです。モダナイズで生じた依存関係も解析し、実行時の到達性を確認したうえで、選択した静的インポートを遅延sap.ui.require呼び出しに置き換えます。

主な機能

  1. 01UI5モジュール依存グラフの作成と確認
  2. 022ノードおよび長い循環の検出
  3. 03到達性と使用状況に基づく遅延辺の選択
  4. 04静的インポートから遅延requireへの置換
  5. 05自動修正できない循環の報告

活用シーン

  1. 01実行時にundefinedとなるモジュールの調査
  2. 02UI5モダナイズ後の循環依存の確認
  3. 03新しいモジュールインポートによる循環の解消
  4. 04手動での再構成が必要な循環の記録

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ui5/plugins-coding-agents --skill fix-cyclic-deps

インストール後、Claude Code で/fix-cyclic-depsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
dependency-graph-analysis.md
scripts/
detect-cycles.js
detect-unsafe-lazy.js
detect-unsafe-lazy.test.js
scripts/lib/
graph-utils.js

詳細

循環するモジュール依存関係の修正

このスキルは、UI5 のモダナイゼーション中に発生する循環モジュール依存関係を検出して解決します。モダナイゼーションによってグローバル名前空間へのアクセスが sap.ui.define のインポートに変換されると、新たな依存関係のエッジが循環インポート(A が B をインポートし、B が A をインポートする)を生み、UI5 AMD ローダーが逆方向のエッジにあるモジュールに対して undefined を返すことがあります。

修正方法:逆方向のエッジにあたる sap.ui.define の依存関係を、各呼び出し箇所で遅延読み込みの sap.ui.require("path/to/Module")(同期形式)に置き換えます。これにより、依存関係のエッジを作らずに、ローダーのキャッシュから読み込み済みのモジュールを取得できます。

Linter ルール

ルール IDメッセージのパターンこのスキルの対応
(なし — 構造上の問題)実行時:インポートパスが正しいにもかかわらず、モジュールが undefined依存関係グラフ内の循環を検出し、逆方向のエッジを遅延読み込みの sap.ui.require() に変換する

このスキルは UI5 リンターのルールによって起動されるものではありません。モジュール依存関係グラフにおける構造上の問題に対処します。モダナイゼーションのワークフローで最終修正フェーズとして起動されるか、実行時にモジュールが undefined となった場合に単独で実行されます。

使用するタイミング

  • モダナイゼーションのワークフロー内:フェーズ 3 のステップ 3.3(最終ステップ)として、フェーズ 3 の他のすべてのステップが完了した後に実行します。複数のステップで sap.ui.define のエッジが追加され、循環が発生する可能性があるため、最終的な依存関係グラフを対象に最後に一度実行します。
  • 単独で実行:インポートパスが正しいにもかかわらず、実行時にモジュールが undefined を返す場合に使用します。
  • 手動でのリファクタリング後:開発者が新しい sap.ui.define の依存関係を追加し、予期せず undefined が発生した場合に使用します。

循環の発生源

モダナイゼーションの 3 つの操作で、新しい sap.ui.define の依存関係エッジが追加され、循環が発生する可能性があります。

1. fix-js-globals ケース 1c — グローバル名前空間の読み取り

var Helper = com.example.app.utils.Helper; を sap.ui.define の依存関係に変換します。Helper がすでに現在のモジュールをインポートしている場合、逆方向のエッジを追加すると 2 ノードの循環が発生します。

2. fix-js-globals ケース 10 — jQuery.sap.declare/require のモダナイゼーション

従来の jQuery.sap.declare / jQuery.sap.require コードを sap.ui.define でラップします。jQuery.sap.require の呼び出しは依存関係となり、従来の同期ローダーとは異なる方法で処理されていた循環が発生する可能性があります。

3. modernize-test-starter — テストファイルの依存関係

以前はグローバル名前空間のチェーン経由でモジュールにアクセスしていたテストファイルに、適切な sap.ui.define インポートが追加されます。相互に参照するテストユーティリティファイルは、循環を発生させる可能性があります。

背景 — 循環によって UI5 ローダーが機能しなくなる理由

UI5 AMD ローダーは、深さ優先探索によって sap.ui.define の依存関係を解決します。循環を検出すると、次のように処理します。

  1. ローダーがモジュール A の読み込みを開始する
  2. A は B に依存しているため、ローダーが B の読み込みを開始する
  3. B は A に依存しているが、A の読み込みはまだ完了していない
  4. ローダーは逆方向のエッジにあたる A のファクトリーの戻り値として undefined を返す
  5. B のファクトリーは、A のエクスポートを想定していた箇所に undefined を受け取る

**2 ノードの循環(A↔B)**は必ず問題を引き起こします。**より長い循環(A→B→C→A)**は、読み込み順序によって実行時に問題が発生する場合としない場合がありますが、潜在的なバグです。

sap.ui.require(同期)が循環を解消する理由

同期形式の sap.ui.require("path/to/Module") は、ローダーの依存関係エッジを作成しません。ロードを開始せず、モジュールキャッシュから読み取ります。

重要な注意点:sap.ui.require(path) は、対象モジュールのファクトリーがまだ実行されていない場合、undefined を返します。そのため安全なのは、遅延呼び出し箇所が実行される前に、対象モジュールがアクティブなエントリーポイントから始まる静的依存のみのパスで到達可能な場合に限られます。

静的エッジ A → B を削除して、A の関数内で var B = sap.ui.require("B") に置き換える場合、A をロードするすべてのエントリーポイントコントローラーから、B に引き続き到達できることを確認する必要があります。

sap.ui.require の3つの形式 — 違いを把握してください:

  • sap.ui.require("path/to/B") — 同期キャッシュ読み取りです。ロードは開始されません。キャッシュにない場合は undefined を返します。
  • sap.ui.require(["path/to/B"], function(B) {...}) — 非同期ロードとコールバックです。ロードを開始します。
  • sap.ui.requireSync("path/to/B") — 同期ロードして返します。ロードを開始します。非推奨です。

主な違い:

  • sap.ui.define(["path/to/B"], ...) — ローダーのエッジ A→B を作成します(循環のリスクがあります)
  • 関数本体内の var B = sap.ui.require("path/to/B") — ローダーのエッジは作成されません(B がキャッシュにあれば安全です)

検出アルゴリズム

自動検出スクリプト

同梱のスクリプトで、検出(グラフの構築、検証、循環の検出、使用数のカウント、ハブの特定)を自動化できます:

node <skill-dir>/scripts/detect-cycles.js <project-root>

スクリプトは次の処理を行います:

  1. manifest.json からプロジェクトの名前空間を特定します
  2. すべての .js ファイル(アプリとテスト)をスキャンし、コメントを除去して、sap.ui.define 配列を解析します
  3. 依存関係グラフを構築します(プロジェクト内部のモジュールのみ)
  4. フォールバック分析によってグラフの完全性を検証します
  5. 2ノードの循環と、より長いチェーンを検出します(Tarjan の SCC)
  6. 使用数をカウントし、遅延側(2ノード)またはハブ(3ノード以上)を特定します

出力は標準出力への JSON です。これを修正フェーズの指針として使用してください。利用できない場合は、以下および references/dependency-graph-analysis.md に記載されている手動の手順に従ってください。

手動の手順
ステップ1 — プロジェクトの名前空間を特定する

manifest.json の sap.app.id を確認します。例:"com.example.myapp"。これをスラッシュ区切り表記の "com/example/myapp" に変換します。これにより、プロジェクト内部のモジュールと sap/* フレームワークの依存関係を識別できます。

ステップ2 — 依存関係グラフを構築する

すべての .js ファイル(アプリのソースとテストの両方)を解析します。各ファイルについて、次の処理を行います:

  1. コメント(// と /* */)を除去します(文字列の内容は保持します)。これにより、コメントアウトされたコード内の sap.ui.define が一致するのを防ぎます。

  2. トークン間に任意の空白を許容する正規表現を使用して、sap.ui.define を検索します:

    /sap\s*\.\s*ui\s*\.\s*define\s*\(/
    

    重要:単純な sap\.ui\.define\s*\( では、sap.ui.define が複数行に分割されているファイルを見落とします。このようなパターンは実際のコードベースに存在します。

  3. 依存関係配列を抽出します:define の後の ( から、角括弧のネストの深さを考慮しながら [ ... ] を探します。文字列リテラルを抽出します。

  4. 名前空間に一致するプロジェクト内部のモジュールのみに絞り込みます。test-resources/ 接頭辞が付いたパスも含めます。

  5. 有向グラフを構築します:ノード = モジュールパス(.js なし)、エッジ = 依存関係です。

除外対象:フレームワークの依存関係(sap/*)、関数本体内の sap.ui.require 呼び出し、文字列リテラル(拡張名、フラグメントパス)。

ステップ2b — グラフの完全性を検証する

グラフの構築後、参照されているすべての依存関係も解析されていることを確認します。モジュールが欠けていると、循環チェーン全体を見落とす可能性があります。

依存関係として参照されているものの、グラフのノードエントリーがないモジュールすべてについて:

  1. ソースファイルが存在するか確認します。存在しない場合は、情報メモを付けてスキップします。
  2. ファイルが存在する場合は、フォールバック分析を実行します:[...] 配列内のプロジェクト内部の名前空間文字列をスキャンします。見つかったものの、プライマリーパーサーが何も抽出していない場合は、グラフに追加します。
  3. sap.ui.define が見つかったものの、最初の引数が配列ではなかったファイルも確認します。同じフォールバック分析を実行します。
ステップ3 — 2ノードの循環を検出する

各エッジ A→B について、B→A も存在するか確認します。重複を除いた一意なペアを収集します。

ステップ 4 — より長いチェーンを検出する(3 ノード以上)

Tarjan の SCC アルゴリズムを実行します。3 ノード以上の SCC は、より長い循環チェーンです。アルゴリズムの擬似コード全体については、references/dependency-graph-analysis.md を参照してください。

2 ノードの循環を修正する方法

判断:どちらを遅延読み込みにするか
フェーズ 1 — 実行時の到達可能性を確認する
  1. エントリーポイントを特定します。Component.js と、A または B を静的インポートするすべてのコントローラーです。
  2. 各エントリーポイントについて、静的依存関係グラフをたどり、{A, B} のどちらに到達できるかを確認します。
  3. 到達範囲に基づいて、遅延読み込みにする側を選びます。
    • B を使用してすべてのエントリーポイントから A に到達できる場合は、B で A を遅延読み込みにしても安全です。
    • A を使用してすべてのエントリーポイントから B に到達できる場合は、A で B を遅延読み込みにしても安全です。
    • 両方とも完全に到達できる場合は、フェーズ 2 に進みます。
    • どちらも完全に到達できない場合は、コントローラーへの静的依存関係の追加も必要です(「コントローラーに追加する修正方法」を参照)。
フェーズ 2 — 使用箇所数で決着をつける

両方の方法が同じ程度に安全な場合:

  1. 使用箇所を数えます。A のコード本体にある B への参照と、B のコード本体にある A への参照を数えます(文字列、コメント、sap.ui.define 配列は除外)。
  2. 使用箇所が少ない側を選びます。コードの変更量を抑えられます。
  3. タイブレーカー 1:依存関係の合計数が多いモジュールでは、通常のインポートを維持します(オーケストレーターパターン)。
  4. タイブレーカー 2:アルファベット順で先のモジュールでは、通常のインポートを維持します。
変換手順

A で B を遅延読み込みにする場合(A が B を静的インポートしなくなる):

ステップ 1 — A の依存関係配列と対応するパラメーターから B を削除します:

// Before:
sap.ui.define(["path/to/B", "path/to/C"], function(B, C) {
// After:
sap.ui.define(["path/to/C"], function(C) {

ステップ 2 — 各使用箇所に遅延読み込みを追加します:

// Before:
someMethod: function() {
    B.doSomething();
    B.doSomethingElse();
}
// After:
someMethod: function() {
    var B = sap.ui.require("path/to/B");
    B.doSomething();
    B.doSomethingElse();
}

関数ごとに sap.ui.require を 1 つ — B を使用する各関数に、それぞれ独自の宣言が必要です。

宣言キーワード:周囲のスタイルに合わせます(モダンなコードでは const、レガシーコードでは var)。

ステップ 3 — 整理します:var X = X; の自己代入を削除します。B へのコード上の参照がない場合は、依存関係から削除するだけで構いません。遅延読み込みは不要です。

特殊なケース:モジュールがすでに部分的に遅延読み込みされている場合

A にすでに sap.ui.require("path/to/B") の呼び出しがあり、かつ sap.ui.define 配列に B が含まれている場合は、sap.ui.define から B を削除し、残りのすべての使用箇所に遅延読み込みがあることを確認します。既存の呼び出しを重複させないでください。

より長いチェーン(3 ノード以上)— ハブベースの自動修正

より長いチェーンは、ハブベースのアプローチで自動修正します。各 SCC 内のハブモジュールを特定し、循環を引き起こす依存関係を遅延読み込みにします。ハブを 1 つ修正するだけで、多数のチェーンを同時に解消できます。

ハブベースの方法を使う理由

ハブモジュールは、複数の循環パスの中心に位置します。多くのファイルにあるエッジを修正する代わりに、ハブ内の少数の依存関係を変換することで、すべての循環を一度に解消できます。

ハブ特定アルゴリズム

3 ノード以上の各 SCC について:

  1. ノードごとの循環参加スコア:他の SCC メンバーへの出エッジ数を数えます。スコアが高いほど、それらの依存関係を遅延読み込みにした際に、より多くの循環を解消できます。
  2. ハブを選択します:スコアが最も高いノードを選びます。同点の場合は、依存関係の合計数が多いノードを優先します(オーケストレーター)。それでも同点の場合は、アルファベット順で選びます。
  3. 循環を引き起こす依存関係を特定します:ハブの sap.ui.define 依存関係のうち、SCC メンバーであるものを特定します。
  4. 2 ノードの循環と同じ変換を適用します。
  5. SCC の検出を再実行します:循環が残っている場合は繰り返します。
判断:どのハブ依存関係を遅延読み込みにするか

ハブの SCC 内部依存関係をすべて遅延読み込みにします。これにより、ハブを通るすべての循環が確実に解消されます。ハブの SCC 内部依存関係に使用箇所がない場合は、その依存関係を削除するだけで構いません。

フォールバック:MODERNIZATION-ISSUES.md に報告する

モジュールが、関数本体の外にあるトップレベルで循環を引き起こす依存関係を参照している場合(遅延読み込みの sap.ui.require が undefined を返す場合)は、次のように報告します。

### Cyclic Dependency Chain (unfixable automatically)

- **SCC nodes**: A, B, C, D
- **Hub identified**: A (3 outgoing SCC edges, 4 incoming)
- **Blocking reason**: A references B at module top level (line 15), outside any function body.
- **Suggested manual fix**: Restructure A to defer the B reference into a function body, or extract the top-level initialization into a separate non-cyclic module.

変更前/変更後の例

例 1 — 使用箇所が 1 つの 2 ノード循環(ModuleA ↔ ModuleB)

ModuleA は ModuleB をインポートし、ModuleB は ModuleA をインポートします。ModuleB は、1 つの呼び出し箇所でのみ ModuleA を使用します。

変更前(問題あり):

// ModuleB.js
sap.ui.define([
    "com/example/myapp/utils/ModuleA",
    "sap/ui/thirdparty/jquery"
], function(ModuleA, jQuery) {
    var ModuleB = {
        handleStatus: function(aSelectedItems, sId) {
            ModuleA.processStatus(aSelectedItems, sId);  // undefined!
        }
    };
    return ModuleB;
});

変更後(修正済み):

// ModuleB.js
sap.ui.define([
    "sap/ui/thirdparty/jquery"
], function(jQuery) {
    var ModuleB = {
        handleStatus: function(aSelectedItems, sId) {
            var ModuleA = sap.ui.require("com/example/myapp/utils/ModuleA");
            ModuleA.processStatus(aSelectedItems, sId);
        }
    };
    return ModuleB;
});
例 2 — 複数の使用箇所がある 2 ノード循環(オーケストレーター ↔ ヘルパー)

オーケストレーターはヘルパーをインポートします(使用箇所 5 件)。ヘルパーはオーケストレーターをインポートします(使用箇所 25 件)。判断:オーケストレーターでヘルパーを遅延読み込みにします(修正箇所が少ないため)。

変更前(問題あり):

// Orchestrator.js
sap.ui.define([
    "com/example/myapp/utils/Helper",
    "com/example/myapp/utils/Validator"
], function(Helper, Validator) {
    var Orchestrator = {
        openDialog: function() { Helper.openDialog(); },
        refreshAll: function() { Helper.refreshAll(); }
        // ... 3 more Helper usage sites
    };
    return Orchestrator;
});

変更後(修正済み):

// Orchestrator.js
sap.ui.define([
    "com/example/myapp/utils/Validator"
], function(Validator) {
    var Orchestrator = {
        openDialog: function() {
            var Helper = sap.ui.require("com/example/myapp/utils/Helper");
            Helper.openDialog();
        },
        refreshAll: function() {
            var Helper = sap.ui.require("com/example/myapp/utils/Helper");
            Helper.refreshAll();
        }
        // ... each function gets its own lazy require
    };
    return Orchestrator;
});
例 3 — 未使用の依存関係の削除

ModuleX は ModuleY をインポートしていますが、コード内で参照していません。不要なインポートを削除するだけです。

変更前:

sap.ui.define([
    "com/example/myapp/utils/ModuleY",
    "com/example/myapp/utils/ModuleZ"
], function(ModuleY, ModuleZ) {
    // ModuleY never used

変更後:

sap.ui.define([
    "com/example/myapp/utils/ModuleZ"
], function(ModuleZ) {
例 4 — Hub を介して長いチェーンを自動修正(ModelManager Hub)

ModelManager は、依存関係 FilterHelper と ChartHelper を介して 7 つの循環チェーンに関与しています。Hub 分析の結果、ModelManager には SCC の出辺が 2 つあり、Hub であることが分かります。

変更前(問題あり):

// ModelManager.js
sap.ui.define(["sap/ui/thirdparty/jquery",
    "com/example/myapp/utils/FilterHelper",
    "com/example/myapp/utils/Payload",
    "com/example/myapp/utils/ChartHelper",
    "sap/base/Log"
], function(jQuery, FilterHelper, oPayload, ChartHelper, Log) {
    var ModelManager = {
        getFilterConfig: function() {
            var oFilterConfig = FilterHelper;  // undefined due to cycle!
        },
        getChartType: function() {
            var oChartType = ChartHelper.getAnnotationType();  // undefined!
        }
    };
    return ModelManager;
});

変更後(修正済み — SCC 内部の依存関係を両方とも遅延読み込みに変更):

// ModelManager.js
sap.ui.define(["sap/ui/thirdparty/jquery",
    "com/example/myapp/utils/Payload",
    "sap/base/Log"
], function(jQuery, oPayload, Log) {
    var ModelManager = {
        getFilterConfig: function() {
            var FilterHelper = sap.ui.require("com/example/myapp/utils/FilterHelper");
            var oFilterConfig = FilterHelper;
        },
        getChartType: function() {
            var ChartHelper = sap.ui.require("com/example/myapp/utils/ChartHelper");
            var oChartType = ChartHelper.getAnnotationType();
        }
    };
    return ModelManager;
});

1 つのファイルから依存関係を 2 つ削除することで、7 つすべての循環チェーンを解消しました。注:var oFilterConfig = FilterHelper; はレガシーなエイリアスパターンです。このスキルは既存のコードを保持し、インポートの仕組みのみを変換します。

実装手順

  1. 検出スクリプトを実行して依存関係グラフを作成し、すべての循環を検出します:

    node <skill-dir>/scripts/detect-cycles.js <project-root>
    

    JSON 出力には、使用回数と遅延読み込み側の判定を含む twoNodeCycles と、Hub の特定結果を含む longerChains が含まれます。利用できない場合は、上記の手動手順に従ってください。

  2. 出力を確認します。グラフの完全性に関する問題がないか、warnings と errors の配列を確認してください。先にエラーに対処してください。

  3. 各 2 ノード循環を修正します(twoNodeCycles[] から):

    • lazySide フィールドで、修正対象のモジュールを特定します
    • sap.ui.define 配列と関数パラメーターから循環する依存関係を削除します
    • 各使用箇所に var Module = sap.ui.require("path/to/Module") を追加します
    • 不要になった要素を整理します
  4. Hub を介して長いチェーンを修正します(longerChains[] から):

    • hub と hubInternalDeps フィールドで、遅延読み込みにするモジュールと依存関係を特定します
    • すべての使用箇所が関数本体内にある場合は、遅延 require への変換を適用します
    • モジュールのトップレベルに使用箇所がある場合は、MODERNIZATION-ISSUES.md に報告します
    • SCC 検出を再実行します。循環が残っている場合は繰り返します
  5. 検証 — 循環検出を再実行します:

    node <skill-dir>/scripts/detect-cycles.js <project-root>
    

    出力に twoNodeCycles: [] と longerChains: [] が表示されるはずです。その後、回帰チェックのために npx @ui5/linter --details を実行します。

  6. 静的カバレッジを検証します:

    node <skill-dir>/scripts/detect-unsafe-lazy.js <project-root>
    

    すべてのエントリーポイントコントローラーから静的チェーンをたどって到達できる M を、すべての sap.ui.require("M") について確認します。検出結果がある場合は、以下の「コントローラーへの追加による対処」を適用してください。unsafeCount: 0 になるまで再実行します。両方のスクリプトで問題が 0 件と報告されるまで、スキルは完了ではありません。

コントローラーへの追加による対処

detect-unsafe-lazy.js が未カバーのエントリーポイントを報告した場合は、読み込みのみを行う副作用インポートとして、遅延読み込みの対象をコントローラーの sap.ui.define 配列に追加します。

// Before — controller does NOT statically import DialogHelper
sap.ui.define([
    "com/example/myapp/utils/ActionHandler",
    "sap/ui/core/mvc/Controller"
], function(ActionHandler, Controller) {
    // ActionHandler has lazy require to DialogHelper
    // → sap.ui.require("DialogHelper") returns undefined

// After — append as load-only dep (no factory param)
sap.ui.define([
    "com/example/myapp/utils/ActionHandler",
    "sap/ui/core/mvc/Controller",
    "com/example/myapp/utils/DialogHelper"
], function(ActionHandler, Controller /* no DialogHelper param */) {
    // DialogHelper now in cache → lazy require works

ルール:

  • 依存関係の配列の末尾に追加し、対応するファクトリーパラメーターは追加しません
  • staticUncovered に 3 つ以上のコントローラーが列挙されている場合は、代わりに BaseController.js または Component.js に依存関係を追加します
  • 修正のたびに detect-unsafe-lazy.js を再実行し、解決したことを確認します

注意事項 — 重要なルール

  1. 関数本体内で遅延 require する:var B = sap.ui.require("path/to/B") はモジュールのトップレベルではなく、B を使用する関数内に記述します。define 時点では、B がまだキャッシュにない場合があります。

  2. 関数ごとに require は 1 つ:モジュールを使用する各関数本体に、それぞれ宣言が必要です。変数のスコープは関数です。

  3. プロジェクト内部のモジュールのみ:フレームワーク依存関係(sap/*)がプロジェクトレベルの循環を引き起こすことはありません。処理するのは、プロジェクトの名前空間に一致する依存関係のみです。

  4. 文字列リテラルは使用箇所ではありません:ログメッセージ、.extend() のクラス名、フラグメントパスは文字列であり、コード参照ではありません。数えたり変更したりしないでください。

  5. コメントアウトされたコードは使用箇所ではありません:// または /* */ 内の行は、使用箇所として数えません。

  6. パラメーターの位置を合わせる:インデックス N の依存関係を削除する場合は、インデックス N の関数パラメーターを削除します。削除した依存関係に対応するパラメーターがある場合にのみ調整してください。

  7. 既存の遅延 require は依存関係のエッジではありません:関数本体内の sap.ui.require("path/to/X") は、ローダーのエッジを作成しません。エッジとなるのは sap.ui.define 配列のエントリーのみです。

  8. 冪等性:2 回実行しても安全です。2 回目の実行では、循環はすでに解消されているため、変更は行われません。

  9. テストファイルも対象です:依存関係グラフにはテストファイルも含める必要があります。modernize-test-starter が sap.ui.define の依存関係を追加すると、循環に関与することがあります。

  10. 非同期 sap.ui.require には手を加えない:非同期形式の sap.ui.require(["path/to/B"], function(B) {...}) は、ローダーのエッジを作成します。このスキルで使用するのは、同期形式の単一文字列のみです。

  11. 複数行の sap.ui.define パターン:正規表現では、sap、.、ui、.、define、( の間に任意の空白や改行を許容する必要があります。単純な正規表現では、分割されたパターンを見落とし、循環チェーンが隠れてしまいます。

  12. 解析前にコメントを取り除く:sap.ui.define を検索する前に、常にコメントを削除してください。その際、文字列リテラルを考慮します。ファイル内にセクションマーカーとしてコメント内に記述されている場合があります。

  13. グラフが完全であることを確認する:参照されている依存関係がすべて解析されたか確認します。最初の解析で何も見つからなかったファイルに対して、フォールバック分析を実行します。循環の検出前に、見つかった依存関係をマージします。

関連スキル

  • fix-js-globals:ケース 1c とケース 10 は、循環を引き起こす新しい依存関係エッジが追加される主な原因です。fix-js-globals の完了後に fix-cyclic-deps を実行してください。
  • modernize-test-starter:テストファイルのモダナイズにより、sap.ui.define の依存関係が追加され、テストユーティリティ同士、またはテストモジュールとアプリモジュール間で循環が発生することがあります。
  • modernize-ui5-app:フェーズの順序を調整する親ワークフローです。このスキルはフェーズ 3、ステップ 3.3(最終ステップ)として実行されます。

コメント