fix-pseudo-modules について
疑似モジュールや暗黙のグローバルに関するリンター指摘を解決する、UI5 開発者向けのスキルです。列挙型のライブラリインポート、直接インポート、OData 式アドオンの使い方を説明します。
主な機能
- 01列挙型とデータ型をライブラリからインポート
- 02クラスとコントロールを直接インポート
- 03OData 関数用に ODataExpressionAddons を追加
- 04XML ビューの core:require に対応
活用シーン
- 01非推奨の列挙型疑似モジュールの修正
- 02ライブラリにエクスポートされないモジュールの解決
- 03暗黙の OData グローバルの除去
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ui5/ plugins-coding-agents --skill fix-pseudo-modulesインストール後、Claude Code で/fix-pseudo-modulesを入力して読み込まれたか確認します。
詳細
疑似モジュールと暗黙的なグローバルの修正
このスキルは、UI5 リンターが検出するものの、適切なモジュールのインポートパターンを理解する必要があるため自動修正できない、疑似モジュールへのアクセスと暗黙的なグローバルの問題を修正します。
対応するリンタールール
| ルール ID | メッセージパターン | このスキルでの対応 |
|---|---|---|
no-pseudo-modules | 列挙型の疑似モジュール '...' への非推奨のアクセス | ライブラリモジュール経由でインポート |
no-pseudo-modules | DataType 疑似モジュール '...' への非推奨のアクセス | ライブラリモジュール経由でインポート |
no-implicit-globals | モジュール '...' へのアクセスが、ライブラリ '...' からエクスポートされていない | モジュールを直接インポート |
no-implicit-globals | OData の組み込みグローバルシンボルを暗黙的に使用してはならない | ODataExpressionAddons をインポート |
使用するタイミング
次のようなリンターの出力が表示された場合に、このスキルを適用してください。
MyController.js:5:5 error Deprecated access of enum pseudo module 'sap/ui/core/BarColor' no-pseudo-modules
MyController.js:8:5 error Deprecated access of DataType pseudo module 'sap/ui/core/CSSSize' no-pseudo-modules
MyController.js:15:5 error Access of module 'sap/ui/unified/DateRange' not exported by library 'sap/ui/unified/library' no-implicit-globals
MyView.view.xml:20:5 error OData built-in global symbols must not be used implicitly no-implicit-globals
背景:疑似モジュール
UI5 では、列挙型と DataType はこれまでモジュールであるかのようにアクセスされていました(例:sap/ui/core/BarColor)。これらは「疑似モジュール」です。実際のファイルとしては存在しませんが、実行時にライブラリモジュールから解決されます。最新の UI5 では、疑似モジュールを直接インポートする方法は非推奨です。
修正方法
1. 列挙型の疑似モジュールへのアクセス
問題:列挙型をモジュールとして直接インポートしています。
// Before - triggers no-pseudo-modules
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/BarColor", // Pseudo module!
"sap/m/ListSeparators" // Pseudo module!
], function(Controller, BarColor, ListSeparators) {
"use strict";
return Controller.extend("my.app.controller.Main", {
onInit: function() {
var color = BarColor.Positive;
var separator = ListSeparators.All;
}
});
});
修正方法:ライブラリモジュールからインポートし、プロパティとして列挙型にアクセスします。
// After - import from library
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/library", // Import library
"sap/m/library" // Import library
], function(Controller, coreLibrary, mLibrary) {
"use strict";
// Extract enums from library
var BarColor = coreLibrary.BarColor;
var ListSeparators = mLibrary.ListSeparators;
return Controller.extend("my.app.controller.Main", {
onInit: function() {
var color = BarColor.Positive;
var separator = ListSeparators.All;
}
});
});
よく使われる列挙型の疑似モジュールとそのライブラリ:
| 疑似モジュール | ライブラリモジュール | 列挙型へのアクセス |
|---|---|---|
sap/ui/core/BarColor | sap/ui/core/library | coreLibrary.BarColor |
sap/ui/core/ValueState | sap/ui/core/library | coreLibrary.ValueState |
sap/ui/core/TextDirection | sap/ui/core/library | coreLibrary.TextDirection |
sap/ui/core/TextAlign | sap/ui/core/library | coreLibrary.TextAlign |
sap/ui/core/MessageType | sap/ui/core/library | coreLibrary.MessageType |
sap/m/ListSeparators | sap/m/library | mLibrary.ListSeparators |
sap/m/ListMode | sap/m/library | mLibrary.ListMode |
sap/m/ListType | sap/m/library | mLibrary.ListType |
sap/m/ButtonType | sap/m/library | mLibrary.ButtonType |
sap/m/InputType | sap/m/library | mLibrary.InputType |
2. DataType 疑似モジュールへのアクセス
問題:DataType をモジュールとして直接インポートしています。
// Before - triggers no-pseudo-modules
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/CSSSize" // DataType pseudo module!
], function(Controller, CSSSize) {
"use strict";
return Controller.extend("my.app.controller.Main", {
// Using CSSSize type
});
});
修正方法:ライブラリモジュールからインポートします。
// After - import from library
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/library"
], function(Controller, coreLibrary) {
"use strict";
var CSSSize = coreLibrary.CSSSize;
return Controller.extend("my.app.controller.Main", {
// Using CSSSize type
});
});
よく使われる DataType 疑似モジュール:
| 疑似モジュール | ライブラリモジュール |
|---|---|
sap/ui/core/CSSSize | sap/ui/core/library |
sap/ui/core/CSSColor | sap/ui/core/library |
sap/ui/core/URI | sap/ui/core/library |
sap/ui/core/ID | sap/ui/core/library |
sap/ui/core/Percentage | sap/ui/core/library |
3. ライブラリ経由のアクセスによる暗黙的なグローバル
問題:実際にはエクスポートされていないモジュールに、ライブラリのエクスポート経由でアクセスしています。
// Before - triggers no-implicit-globals
sap.ui.define([
"sap/ui/unified/library",
"sap/ui/core/library"
], function(unifiedLibrary, coreLibrary) {
"use strict";
// These modules are NOT exported by the library!
var DateRange = unifiedLibrary.DateRange; // Error
var DOMAttribute = coreLibrary.tmpl.DOMAttribute; // Error
});
修正方法:モジュールを直接インポートします。
// After - import modules directly
sap.ui.define([
"sap/ui/unified/DateRange", // Direct import
"sap/ui/core/tmpl/DOMAttribute" // Direct import
], function(DateRange, DOMAttribute) {
"use strict";
// Use directly
});
目安:
- 列挙型と DataType:ライブラリモジュール経由でアクセスします(例:
library.EnumName) - クラス/コントロール:直接インポートします(例:
sap/ui/unified/DateRange)
4. OData 式アドオン
問題:インポートせずに式バインディングで OData の組み込み関数を使用しています。
// Before - triggers no-implicit-globals
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/Text"
], function(Controller, Text) {
"use strict";
return Controller.extend("my.app.controller.Main", {
onInit: function() {
var oText = new Text({
// Using odata.compare without import!
text: "{= odata.compare(${/value1}, ${/value2}) }"
});
}
});
});
修正方法:ODataExpressionAddons モジュールをインポートします。
// After - import ODataExpressionAddons
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/Text",
"sap/ui/model/odata/ODataExpressionAddons" // Required for odata.* functions
], function(Controller, Text, ODataExpressionAddons) {
"use strict";
return Controller.extend("my.app.controller.Main", {
onInit: function() {
var oText = new Text({
// Now works - ODataExpressionAddons is imported
text: "{= odata.compare(${/value1}, ${/value2}) }"
});
}
});
});
インポートが必要な OData 関数:
| OData 関数 | 代替の直接モジュール |
|---|---|
odata.compare | sap/ui/model/odata/v4/ODataUtils |
odata.fillUriTemplate | sap/ui/thirdparty/URITemplate |
odata.uriEncode | sap/ui/model/odata/ODataUtils |
注:sap/ui/model/odata/ODataExpressionAddons をインポートするのが最も簡単な解決策です。これにより、すべての OData 式関数が登録されます。
5. XML ビュー内の OData 関数
問題:インポートせずに XML ビューのバインディングで OData 関数を使用しています。
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m">
<Text text="{= odata.compare(${/price1}, ${/price2}) }" />
</mvc:View>
修正方法:ODataExpressionAddons に対する core:require を追加します。
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
xmlns:core="sap.ui.core"
core:require="{
ODataAddons: 'sap/ui/model/odata/ODataExpressionAddons'
}">
<Text text="{= odata.compare(${/price1}, ${/price2}) }" />
</mvc:View>
実装手順
-
リンターのメッセージから問題の種類を特定します。
- 「enum pseudo module」→ ライブラリからインポートします
- 「DataType pseudo module」→ ライブラリからインポートします
- 「not exported by library」→ モジュールを直接インポートします
- 「OData built-in global」→ ODataExpressionAddons をインポートします
-
列挙型/DataType に適したライブラリを特定します。
- モジュールパスのプレフィックスを確認します(例:
sap/ui/core/→sap/ui/core/library)
- モジュールパスのプレフィックスを確認します(例:
-
インポートを更新します。
- 列挙型/DataType 用のライブラリインポートを追加します
- クラス用のモジュール直接インポートを追加します
- OData 関数用に ODataExpressionAddons を追加します
-
コード内の参照を更新します。
- 列挙型/DataType をライブラリから取り出します:
var EnumName = library.EnumName; - 直接インポートしたモジュールを使用します
- 列挙型/DataType をライブラリから取り出します:
-
XML ビューの場合:必要に応じて
core:requireを追加します
修正セッションの例
次のリンター出力がある場合:
MyController.js:3:5 error Deprecated access of enum pseudo module 'sap/ui/core/ValueState' no-pseudo-modules
MyController.js:4:5 error Access of module 'sap/ui/unified/DateRange' not exported by library 'sap/ui/unified/library' no-implicit-globals
MyController.js:25:5 error OData built-in global symbols must not be used implicitly no-implicit-globals
修正前:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/ValueState",
"sap/ui/unified/library"
], function(Controller, ValueState, unifiedLibrary) {
"use strict";
var DateRange = unifiedLibrary.DateRange; // Error: not exported
return Controller.extend("my.app.controller.Main", {
onInit: function() {
var state = ValueState.Error;
var oDateRange = new DateRange({
startDate: new Date()
});
},
formatComparison: function() {
return "{= odata.compare(${/val1}, ${/val2}) }"; // Error: no import
}
});
});
修正後:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/library", // For ValueState enum
"sap/ui/unified/DateRange", // Direct import
"sap/ui/model/odata/ODataExpressionAddons" // For odata.* functions
], function(Controller, coreLibrary, DateRange, ODataExpressionAddons) {
"use strict";
var ValueState = coreLibrary.ValueState; // Extract from library
return Controller.extend("my.app.controller.Main", {
onInit: function() {
var state = ValueState.Error;
var oDateRange = new DateRange({
startDate: new Date()
});
},
formatComparison: function() {
return "{= odata.compare(${/val1}, ${/val2}) }"; // Now works
}
});
});
注意事項
- ライブラリモジュールがエクスポートするのは列挙型と DataType のみで、クラスやコントロールは含まれません
- コントロールとクラスは、常に完全なモジュールパスを指定して直接インポートしてください
ODataExpressionAddonsのインポートは、変数を直接使用しない場合でも必要です。読み込み時に関数を登録するためです- 疑似モジュールの非推奨化は、不適切な依存関係を特定し、読み込み時間の最適化に役立ちます
関連スキル
- fix-js-globals:その他の JavaScript グローバルアクセスパターン(JS ファイルの
no-globals— 例:sap.ui.getCore()、jQuery、sap.ui.controller())には、fix-js-globals を使用します - fix-control-renderer:レンダラー固有の問題とともにレンダラーコードで疑似モジュールエラーが発生する場合は、レンダラーの最新化に fix-control-renderer を使用します