Skip to content

feat(autofix): Fix additional deprecated Core APIs #639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
2268a60
feat: Autofix Core APIs (base)
maxreichmann Apr 24, 2025
d604f20
refactor: Remove redundant functionality
d3xter666 May 28, 2025
9e4a043
refactor: Test cases
d3xter666 May 28, 2025
bbf57c9
refactor: Remove redundant code
d3xter666 May 28, 2025
765347b
refactor: Remove redundant tests
d3xter666 May 29, 2025
a372c0d
refactor: Improve samples
d3xter666 May 30, 2025
a0d7121
feat: Autofix Core APIs (base)
maxreichmann Apr 24, 2025
1e604c9
fix: Merge conflicts
d3xter666 May 27, 2025
240b461
feat: Add a map with the Core fixHints
d3xter666 May 15, 2025
b9c55eb
refactor: Extract namespace resolver into util
d3xter666 May 16, 2025
4af0469
refactor: Reuse extractNamespace
d3xter666 May 16, 2025
56bdf76
refactor: Renames of variable names
d3xter666 May 19, 2025
784f94f
feat: Enable exportCodeToBeUsed
d3xter666 May 19, 2025
7d2303b
feat: Migrate applyTheme
d3xter666 May 19, 2025
d83c513
fix: Enable/disable/postpone certain cases
d3xter666 May 19, 2025
febb990
feat: Enable getComponent migration
d3xter666 May 19, 2025
f7eaae9
feat: Enable loadLibrary migration
d3xter666 May 20, 2025
759ff95
feat: Enable createComponent migration
d3xter666 May 20, 2025
66d8607
feat: Enable getLibraryResourceBundle migration
d3xter666 May 20, 2025
9fb5729
refactor: Cleanup code
d3xter666 May 21, 2025
beb723c
refactor: Handle properly getResourceBundleFor
d3xter666 May 21, 2025
06a72a1
refactor: Do not migrate unknown lib names
d3xter666 May 21, 2025
c5a0fe9
test: Update snapshots
d3xter666 May 21, 2025
baafedc
feat: Detect libs from manifest.json
d3xter666 May 27, 2025
13b147e
feat: Detect lib namespace
d3xter666 May 27, 2025
090971e
fix: Use modules, not globals
d3xter666 May 27, 2025
70df1ed
test: Update snapshots
d3xter666 May 27, 2025
504f923
fix: Resolve merge conflicts
d3xter666 May 27, 2025
d5b1134
fix: Rebase conflicts
d3xter666 May 28, 2025
9d4d11b
refactor: Cleanups
d3xter666 May 28, 2025
bf21c66
refactor: Remove redundant code
d3xter666 May 28, 2025
cc792c0
fix: Update snapshots
d3xter666 May 28, 2025
d82460b
test: Remove redundant code
d3xter666 May 28, 2025
7807eb5
test: Update snapshots
d3xter666 May 28, 2025
5e285f8
fix: Resolve merge conflicts
d3xter666 May 28, 2025
ccf7bf2
fix: Resolve value of getActiveElement()
d3xter666 May 29, 2025
2d0e904
refactor: Postpone migration of loadLibrary & createComponent
d3xter666 May 29, 2025
e9da582
refactor: Cleanups
d3xter666 May 29, 2025
1eafe45
test: Remove not migrated test cases
d3xter666 May 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/autofix/solutions/codeReplacer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ function patchMessageFixHints(fixHints?: FixHints, apiName?: string) {
`$moduleIdentifier.${fnName}(${cleanRedundantArguments(fixHints.exportCodeToBeUsed.args)})`;
}
}
} else if (apiName === "applyTheme" && fixHints?.moduleName === "sap/ui/core/Theming") {
if ((fixHints?.exportCodeToBeUsed?.args?.length ?? 0) > 1 &&
fixHints?.exportCodeToBeUsed?.args?.[1]?.value !== "undefined") {
fixHints = undefined; // We cannot handle this case
log.verbose(`Autofix skipped for ${apiName}. Transpilation is too ambiguous.`);
}
}

return fixHints;
Expand Down
38 changes: 19 additions & 19 deletions src/linter/ui5Types/fixHints/CoreFixHintsGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,21 @@ const coreModulesReplacements = new Map<string, FixHints>([
["byFieldGroupId", {
moduleName: "sap/ui/core/Control", exportCodeToBeUsed: "$moduleIdentifier.getControlsByFieldGroupId($1)",
}],
["getCurrentFocusedControlId", {
// The legacy API used to return null if no control was focused.
moduleName: "sap/ui/core/Element", exportCodeToBeUsed: "$moduleIdentifier.getActiveElement()?.getId() || null",
}],
["isStaticAreaRef", {
moduleName: "sap/ui/core/StaticArea",
exportCodeToBeUsed: "$moduleIdentifier.getDomRef() === $1",
}],
// TODO: The legacy API return null if the control is not found.
// ["getCurrentFocusedControlId", {
// moduleName: "sap/ui/core/Element", exportNameToBeUsed: "getActiveElement()?.getId",
// }],
// // Migrate only if second argument is omitted or undefined
// ["applyTheme", {
// moduleName: "sap/ui/core/Theming",
// exportCodeToBeUsed: "$moduleIdentifier.setTheme($1)",
// }],
// // Individual arguments must be mapped to "options" object
// // The new API has no sync loading option, replacement is only safe when the options contain async:true
// Migrate only if second argument is omitted or undefined
["applyTheme", {
moduleName: "sap/ui/core/Theming",
exportCodeToBeUsed: "$moduleIdentifier.setTheme($1)",
}],
// Individual arguments must be mapped to "options" object
// The new API has no sync loading option, replacement is only safe when the options contain async:true
// ["loadLibrary", {
// moduleName: "sap/ui/core/Lib", exportCodeToBeUsed: "$moduleIdentifier.load($1)",
// }],
Expand All @@ -63,14 +63,14 @@ const coreModulesReplacements = new Map<string, FixHints>([
// ["createComponent", {
// moduleName: "sap/ui/core/Component", exportCodeToBeUsed: "$moduleIdentifier.create($1)",
// }],
// // Note that alternative replacement Component.get is meanwhile deprecated, too
// ["getComponent", {
// moduleName: "sap/ui/core/Component", exportNameToBeUsed: "getComponentById",
// }],
// // Parameter bAsync has to be omitted or set to false since the new API returns
// // the resource bundle synchronously. When bAsync is true, the new API is not a replacement
// // as it does not return a promise. In an await expression, it would be okay, but otherwise not.
// // TODO: To be discussed: sLibrary must be a library, that might not be easy to check
// Note that alternative replacement Component.get is meanwhile deprecated, too
["getComponent", {
moduleName: "sap/ui/core/Component", exportNameToBeUsed: "getComponentById",
}],
// Parameter bAsync has to be omitted or set to false since the new API returns
// the resource bundle synchronously. When bAsync is true, the new API is not a replacement
// as it does not return a promise. In an await expression, it would be okay, but otherwise not.
// TODO: To be discussed: sLibrary must be a library, that might not be easy to check
// ["getLibraryResourceBundle", {
// moduleName: "sap/ui/core/Lib", exportCodeToBeUsed: "$moduleIdentifier.getResourceBundleFor($1, $2)",
// }],
Expand Down
8 changes: 8 additions & 0 deletions test/fixtures/autofix/coreApi/DeprecatedCoreApi.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
sap.ui.define(["sap/ui/core/Core",], function(CoreRenamed) {
CoreRenamed.applyTheme("themeName");
CoreRenamed.applyTheme("customTheme", "find/my/theme/here"); // Should not be autofixed if there is a 2nd argument
CoreRenamed.applyTheme("customTheme", undefined); // Can be migrated when the 2nd argument is undefined

CoreRenamed.attachInit(function() {console.log();});

CoreRenamed.attachInitEvent(function() {console.log();});
Expand All @@ -8,8 +12,12 @@ sap.ui.define(["sap/ui/core/Core",], function(CoreRenamed) {

CoreRenamed.byId("id");

CoreRenamed.getComponent("componentId");

CoreRenamed.getControl("controlId");

CoreRenamed.getCurrentFocusedControlId();

CoreRenamed.getElementById("elementId");

CoreRenamed.getEventBus();
Expand Down
15 changes: 11 additions & 4 deletions test/fixtures/autofix/coreApi/DeprecatedCoreApiWithoutImport.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
sap.ui.define([], function() {
const globalCore = sap.ui.getCore();

globalCore.attachInit(function() {console.log();});

sap.ui.getCore().applyTheme("themeName");
sap.ui.getCore().applyTheme("customTheme", "find/my/theme/here"); // Should not be autofixed if there is a 2nd argument
sap.ui.getCore().applyTheme("customTheme", undefined); // Can be autofixed when the 2nd argument is undefined

sap.ui.getCore().attachInit(function() {console.log();});

globalCore.attachInitEvent(function() {console.log();});
Expand All @@ -13,10 +16,14 @@ sap.ui.define([], function() {
globalCore.byId("id");
sap.ui.getCore().byId("id");

globalCore.getControl("controlId");
globalCore.getComponent("componentId");
sap.ui.getCore().getComponent("componentId");

sap.ui.getCore().getControl("controlId");

globalCore.getElementById("elementId");
globalCore.getCurrentFocusedControlId();
sap.ui.getCore().getCurrentFocusedControlId();

sap.ui.getCore().getElementById("elementId");

globalCore.getEventBus();
Expand Down
71 changes: 61 additions & 10 deletions test/lib/autofix/snapshots/autofix.fixtures.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -5213,7 +5213,12 @@ Generated by [AVA](https://avajs.dev).

> AutofixResult: /coreApi/DeprecatedCoreApi.js

`sap.ui.define(["sap/ui/core/Core", "sap/ui/core/Control", "sap/ui/core/Element", "sap/ui/core/EventBus", "sap/ui/core/Lib", "sap/ui/core/StaticArea", "sap/ui/core/Theming", "sap/ui/Device",], function(CoreRenamed, Control, Element, EventBus, Lib, StaticArea, Theming, Device) {␊
`sap.ui.define(["sap/ui/core/Core", "sap/ui/core/Component", "sap/ui/core/Control", "sap/ui/core/Element", "sap/ui/core/EventBus", "sap/ui/core/Lib", "sap/ui/core/StaticArea", "sap/ui/core/Theming",␊
"sap/ui/Device",], function(CoreRenamed, Component, Control, Element, EventBus, Lib, StaticArea, Theming, Device) {␊
Theming.setTheme("themeName");␊
CoreRenamed.applyTheme("customTheme", "find/my/theme/here"); // Should not be autofixed if there is a 2nd argument␊
Theming.setTheme("customTheme"); // Can be migrated when the 2nd argument is undefined␊
CoreRenamed.ready(function() {console.log();});␊
CoreRenamed.ready(function() {console.log();});␊
Expand All @@ -5222,8 +5227,12 @@ Generated by [AVA](https://avajs.dev).
Control.getControlsByFieldGroupId(["id", "id2"]);␊
Element.getElementById("id");␊
Component.getComponentById("componentId");␊
Element.getElementById("controlId");␊
Element.getActiveElement()?.getId() || null;␊
Element.getElementById("elementId");␊
Expand Down Expand Up @@ -5258,13 +5267,21 @@ Generated by [AVA](https://avajs.dev).
[
{
coverageInfo: [],
errorCount: 1,
errorCount: 2,
fatalErrorCount: 0,
filePath: 'DeprecatedCoreApi.js',
messages: [
{
column: 14,
line: 4,
message: 'Call to deprecated function \'applyTheme\' of class \'Core\'',
messageDetails: 'Deprecated test message',
ruleId: 'no-deprecated-api',
severity: 2,
},
{
column: 2,
line: 19,
line: 28,
message: 'Deprecated call to Lib.init(). Use the {apiVersion: 2} parameter instead',
messageDetails: 'Lib.init (https://ui5.sap.com/1.120/#/api/sap.ui.core.Lib)',
ruleId: 'no-deprecated-api',
Expand All @@ -5279,9 +5296,14 @@ Generated by [AVA](https://avajs.dev).

> AutofixResult: /coreApi/DeprecatedCoreApiWithoutImport.js

`sap.ui.define(["sap/ui/core/Control", "sap/ui/core/Core", "sap/ui/core/Element", "sap/ui/core/EventBus", "sap/ui/core/Lib", "sap/ui/core/StaticArea", "sap/ui/core/Theming", "sap/ui/Device"], function(Control, Core, Element, EventBus, Lib, StaticArea, Theming, Device) {␊
`sap.ui.define(["sap/ui/core/Component", "sap/ui/core/Control", "sap/ui/core/Core", "sap/ui/core/Element", "sap/ui/core/EventBus", "sap/ui/core/Lib", "sap/ui/core/StaticArea", "sap/ui/core/Theming",␊
"sap/ui/Device"], function(Component, Control, Core, Element, EventBus, Lib, StaticArea, Theming, Device) {␊
const globalCore = sap.ui.getCore();␊
Theming.setTheme("themeName");␊
sap.ui.getCore().applyTheme("customTheme", "find/my/theme/here"); // Should not be autofixed if there is a 2nd argument␊
Theming.setTheme("customTheme"); // Can be autofixed when the 2nd argument is undefined␊
Core.ready(function() {console.log();});␊
Core.ready(function() {console.log();});␊
Expand All @@ -5293,9 +5315,14 @@ Generated by [AVA](https://avajs.dev).
Element.getElementById("id");␊
Element.getElementById("id");␊
Component.getComponentById("componentId");␊
Component.getComponentById("componentId");␊
Element.getElementById("controlId");␊
Element.getElementById("controlId");␊
Element.getActiveElement()?.getId() || null;␊
Element.getActiveElement()?.getId() || null;␊
Element.getElementById("elementId");␊
Element.getElementById("elementId");␊
Expand Down Expand Up @@ -5336,29 +5363,53 @@ Generated by [AVA](https://avajs.dev).
[
{
coverageInfo: [],
errorCount: 3,
errorCount: 6,
fatalErrorCount: 0,
filePath: 'DeprecatedCoreApiWithoutImport.js',
messages: [
{
column: 21,
line: 2,
line: 3,
message: 'Access of global variable \'sap\' (sap.ui.getCore)',
messageDetails: 'Do not use global variables to access UI5 modules or APIs. See Best Practices for Developers (https://ui5.sap.com/#/topic/28fcd55b04654977b63dacbee0552712)',
ruleId: 'no-globals',
severity: 2,
},
{
column: 28,
line: 2,
line: 3,
message: 'Call to deprecated function \'getCore\' (sap.ui.getCore)',
messageDetails: 'Deprecated test message',
ruleId: 'no-deprecated-api',
severity: 2,
},
{
column: 2,
line: 28,
line: 6,
message: 'Access of global variable \'sap\' (sap.ui.getCore)',
messageDetails: 'Do not use global variables to access UI5 modules or APIs. See Best Practices for Developers (https://ui5.sap.com/#/topic/28fcd55b04654977b63dacbee0552712)',
ruleId: 'no-globals',
severity: 2,
},
{
column: 9,
line: 6,
message: 'Call to deprecated function \'getCore\' (sap.ui.getCore)',
messageDetails: 'Deprecated test message',
ruleId: 'no-deprecated-api',
severity: 2,
},
{
column: 19,
line: 6,
message: 'Call to deprecated function \'applyTheme\' of class \'Core\'',
messageDetails: 'Deprecated test message',
ruleId: 'no-deprecated-api',
severity: 2,
},
{
column: 2,
line: 36,
message: 'Deprecated call to Lib.init(). Use the {apiVersion: 2} parameter instead',
messageDetails: 'Lib.init (https://ui5.sap.com/1.120/#/api/sap.ui.core.Lib)',
ruleId: 'no-deprecated-api',
Expand Down
Binary file modified test/lib/autofix/snapshots/autofix.fixtures.ts.snap
Binary file not shown.