--- name: fix-pseudo-modules description: | Fix pseudo module and implicit global issues that UI5 linter reports but cannot auto-fix. Use this skill when linter outputs: - `no-pseudo-modules` with messages about deprecated enum or DataType pseudo module access - `no-implicit-globals` with messages about module not exported by library or OData globals Trigger on: direct enum imports (sap/ui/core/BarColor), direct DataType imports (sap/ui/core/CSSSize), library.EnumName access, odata.compare/fillUriTemplate/uriEncode in bindings. Provides guidance on proper module imports for enums, DataTypes, and OData expression addons. --- # Fix Pseudo Modules and Implicit Globals This skill fixes pseudo module access and implicit global issues that the UI5 linter detects but cannot auto-fix because they require understanding proper module import patterns. ## Linter Rules Handled | Rule ID | Message Pattern | This Skill's Action | |---------|-----------------|---------------------| | `no-pseudo-modules` | Deprecated access of enum pseudo module '...' | Import via library module | | `no-pseudo-modules` | Deprecated access of DataType pseudo module '...' | Import via library module | | `no-implicit-globals` | Access of module '...' not exported by library '...' | Import module directly | | `no-implicit-globals` | OData built-in global symbols must not be used implicitly | Import ODataExpressionAddons | ## When to Use Apply this skill when you see linter output like: ``` 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 ``` ## Background: Pseudo Modules In UI5, enums and DataTypes were historically accessed as if they were modules (e.g., `sap/ui/core/BarColor`). These are "pseudo modules" - they don't exist as real files but are resolved at runtime from the library module. In modern UI5, direct pseudo module imports are deprecated. ## Fix Strategy ### 1. Enum Pseudo Module Access **Problem**: Importing enums as direct modules. ```javascript // 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; } }); }); ``` **Fix Strategy**: Import from the library module and access the enum as a property. ```javascript // 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; } }); }); ``` **Common Enum Pseudo Modules and Their Libraries:** | Pseudo Module | Library Module | Enum Access | |---------------|----------------|-------------| | `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 Pseudo Module Access **Problem**: Importing DataTypes as direct modules. ```javascript // 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 }); }); ``` **Fix Strategy**: Import from the library module. ```javascript // 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 }); }); ``` **Common DataType Pseudo Modules:** | Pseudo Module | Library Module | |---------------|----------------| | `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. Implicit Globals via Library Access **Problem**: Accessing modules via library exports that aren't actually exported. ```javascript // 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 }); ``` **Fix Strategy**: Import the module directly. ```javascript // 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 }); ``` **Rule of Thumb**: - **Enums and DataTypes**: Access via library module (e.g., `library.EnumName`) - **Classes/Controls**: Import directly (e.g., `sap/ui/unified/DateRange`) ### 4. OData Expression Addons **Problem**: Using OData built-in functions in expression bindings without importing. ```javascript // 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}) }" }); } }); }); ``` **Fix Strategy**: Import `ODataExpressionAddons` module. ```javascript // 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 Functions Requiring Import:** | OData Function | Alternative Direct Module | |----------------|---------------------------| | `odata.compare` | `sap/ui/model/odata/v4/ODataUtils` | | `odata.fillUriTemplate` | `sap/ui/thirdparty/URITemplate` | | `odata.uriEncode` | `sap/ui/model/odata/ODataUtils` | **Note**: Importing `sap/ui/model/odata/ODataExpressionAddons` is the simplest solution as it registers all OData expression functions. ### 5. OData Functions in XML Views **Problem**: Using OData functions in XML view bindings without import. ```xml ``` **Fix Strategy**: Add `core:require` for ODataExpressionAddons. ```xml ``` ## Implementation Steps 1. **Identify the issue type** from the linter message: - "enum pseudo module" → Import from library - "DataType pseudo module" → Import from library - "not exported by library" → Import module directly - "OData built-in global" → Import ODataExpressionAddons 2. **Determine the correct library** for enums/DataTypes: - Check the module path prefix (e.g., `sap/ui/core/` → `sap/ui/core/library`) 3. **Update imports**: - Add library import for enums/DataTypes - Add direct module import for classes - Add ODataExpressionAddons for OData functions 4. **Update code references**: - Extract enum/DataType from library: `var EnumName = library.EnumName;` - Use directly imported modules 5. **For XML views**: Add `core:require` when needed ## Example Fix Session Given linter output: ``` 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 ``` **Before:** ```javascript 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 } }); }); ``` **After:** ```javascript 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 } }); }); ``` ## Notes - Library modules only export enums and DataTypes, not classes/controls - Always import controls and classes directly by their full module path - The `ODataExpressionAddons` import is needed even though you don't use the variable directly - it registers the functions at load time - Pseudo module deprecation helps identify improper dependencies and improves load time optimization ## Related Skills - **fix-js-globals**: For other JavaScript global access patterns (`no-globals` on JS files — e.g., `sap.ui.getCore()`, jQuery, `sap.ui.controller()`), use fix-js-globals - **fix-control-renderer**: If pseudo module errors appear in renderer code alongside renderer-specific issues, use fix-control-renderer for the renderer modernization