Skip to content

refactor(autofix): Refactor autofix definition, add abstraction before creating changes#662

Merged
RandomByte merged 19 commits into
mainfrom
refactor-autofix
Jun 11, 2025
Merged

refactor(autofix): Refactor autofix definition, add abstraction before creating changes#662
RandomByte merged 19 commits into
mainfrom
refactor-autofix

Conversation

@RandomByte

@RandomByte RandomByte commented May 19, 2025

Copy link
Copy Markdown
Member

FixHints are still present but should be completely replaced by the Fix class and its subclasses and the generateChanges module.

Concept

  1. Traverse the Transpiled-AST, detect problems and if possible, attempt to create fixes for them
  2. Traverse Source-AST and
    a) Collect all module declarations/requires
    b) Provide fixes with corresponding nodes of the Source-AST
  3. For all fixes, request the ranges (start and end positions) of their planned modifications (replace, delete or insert operations)
  4. Compare modification ranges and identify conflicts
    a) In case of conflicts, discard the whole fix associated with the conflicting range. Prefer smaller range fixes
  5. For all remaining fixes:
    a) Request a list of modules they require, the positions where they want to access them and optionally a preferred name for the identifier (all together referred to as "import requests")
    b) Request a list of modules they no longer require, together with the identifier currently used to access those
  6. Sort the import requests into the module declarations/requires collected in step 2 and determine the corresponding identifiers
  7. For all remaining fixes, request the final source code changes (replace, delete or insert), providing them with the identifiers determined in step 6
    image

image

Fixes, Improvements and Changes

See my review comments below for fixes, improvements and changes

@RandomByte
RandomByte force-pushed the refactor-autofix branch 6 times, most recently from 9a61882 to 27e5265 Compare June 6, 2025 12:42
], function(Input, TableTable) {␊
const input = new Input();␊
const Button = new SapMButton2();␊
const Button = new SapMButton1();␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: Existing import form surrounding sap.ui.define is now reused.

var isPhone = Device.system.phone;␊
var isTablet = Device.system.tablet;␊
var isAndroidPhone = Device.os.android && Device.system.tablet;␊
var isAndroidPhone = Device.os.android && Device.system.phone;␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix: This is the correct replacement for jQuery.device.is.android_phone

var isAndroidTablet = Device.os.android && Device.system.tablet;␊
var isIPhone = Device.os.ios && Device.system.phone;␊
var isIPad = Device.os.ios && Device.system.ipad;␊
var isIPad = Device.os.ios && Device.system.tablet;␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix: This is the correct replacement for jQuery.device.is.ipad. There is no Device.system.ipad property: https://sapui5.hana.ondemand.com/sdk/#/api/sap.ui.Device.system%23properties

`sap.ui.define(["sap/ui/thirdparty/jquery"], async function (jQuery) {␊
// https://github.com/SAP/ui5-linter/issues/590␊
var isStandAlone = window.navigator.standalone;␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: window or rather globalThis is only used when needed (i.e. if an identifier with name navigator already exists)

var intervalCallId3 = jQuery.sap.intervalCall(1000, window, Array.isArray, ["myParam1"]);␊
jQuery.sap.clearIntervalCall(intervalCallId);␊
var element = window.document.getElementById("popup");␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: See above

var person = {firstname: "Peter", lastname: "Miller" };␊
var newObj = Object.create(person || null);␊
var newObj = Object.create(person);␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: Autofix can now evaluate the type of identifiers, correctly detecting the object here.

var myDetails = "These are the details";␊
var myComponent = "jquery.sap.logger.jsunit";␊
Log.debug(myLogMessage, myDetails, myComponent, function () { });␊
Log.debug(myLogMessage, myDetails, myComponent, function () {});␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: Whitespaces in parameters are preserved

var textUpperCase2 = jQuery.sap.charToUpperCase(xy); // Do not migrate vars. We don't know the type of xy
var textUpperCase2 = jQuery.sap.charToUpperCase(xy, 0); // Do not migrate vars. We don't know the type of xy
var textUpperCase2 = jQuery.sap.charToUpperCase(xy, 3); // // Do not migrate vars. We don't know the type of xy
var textUpperCase2 = capitalize(xy);␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: Type and value of identifiers is now checked

ObjectPath.set("name.lastname", "Miller", { name: { firstname: "me" } });␊
ObjectPath.set("name.lastname", "Miller", { name: { firstname: "me" } });␊
ObjectPath.set("", "Miller", { name: { firstname: "me" } });␊
ObjectPath.set(undefined, "Miller", { name: { firstname: "me" } });␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ CHANGE: If the first argument is explicitly set to undefined or null, replace it with an empty string.

I'm not sure why the first iteration kept the undefined (but not null). My understanding is that jQuery.sap.setObject always defaults falsy values to an empty string: https://github.com/SAP/openui5/blob/aad2c54fa60d58f681840a954395a08bfb96cb6c/src/sap.ui.core/src/jquery.sap.global.js#L898

ObjectPath.set(undefined, "Miller", { name: { firstname: "me" } }); will definitely result in an exception due to the missing split function on undefined: https://github.com/SAP/openui5/blob/7ac020cdf6e5fa56a96d17aadeec7a0159beff14/src/sap.ui.core/src/sap/base/util/ObjectPath.js#L37

// 2. Replace the code with the following:␊
// -> var store = new Storage(Storage.Type.local, "mystore");␊
var store = new Storage(jQuery.sap.storage.Type.local, "mystore");␊
var store = new Storage(Storage.Type.local, "mystore");␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: Simultaneous fixes in a call expression's property access and its arguments are now possible.


> AutofixResult: /jQuerySapExtendNoFix.js

`sap.ui.define(["sap/base/util/merge"], function(merge) {␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improvement: Import is not added if fixes are not applied

Theming.setTheme("customTheme"); // Can be autofixed when the 2nd argument is undefined␊
Core.ready(function() {console.log();});␊
Core.ready(function() {console.log();});␊

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix: Duplicate fixes resolved

@RandomByte
RandomByte marked this pull request as ready for review June 10, 2025 16:38
@RandomByte

Copy link
Copy Markdown
Member Author

Test failure is due to code coverage only. Will try to improve it 👍

@RandomByte
RandomByte requested a review from a team June 10, 2025 16:47
d3xter666
d3xter666 previously approved these changes Jun 11, 2025

@d3xter666 d3xter666 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread src/linter/ui5Types/Ui5TypeInfoMatcher.ts Outdated
Comment thread src/linter/ui5Types/Ui5TypeInfoMatcher.ts Outdated
d3xter666
d3xter666 previously approved these changes Jun 11, 2025
@RandomByte
RandomByte merged commit 894cb84 into main Jun 11, 2025
22 checks passed
@RandomByte
RandomByte deleted the refactor-autofix branch June 11, 2025 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants