diff --git a/resources/overrides/index.d.ts b/resources/overrides/index.d.ts index 9bf823e08..d0085e99e 100644 --- a/resources/overrides/index.d.ts +++ b/resources/overrides/index.d.ts @@ -1 +1,2 @@ import "./jquery.sap.mobile"; +import "./jquery.sap"; diff --git a/resources/overrides/jquery.sap.d.ts b/resources/overrides/jquery.sap.d.ts new file mode 100644 index 000000000..3818f9c0b --- /dev/null +++ b/resources/overrides/jquery.sap.d.ts @@ -0,0 +1,65 @@ +// General deprecation of jQuery.sap namespace +interface JQueryStatic { + /** + * @deprecated since 1.58. To avoid usage of global variables in general, please + * do not use the jQuery.sap namespace any longer. Most of the jQuery.sap functionalities + * are replaced by alternative modules which can be found in the API doc. + */ + sap: object; +} + +// Add exports of all jquery.sap.* modules (except for "jquery.sap.promise" which does not export jQuery) +declare module "jquery.sap.act" { + export default jQuery; +} +declare module "jquery.sap.dom" { + export default jQuery; +} +declare module "jquery.sap.encoder" { + export default jQuery; +} +declare module "jquery.sap.events" { + export default jQuery; +} +declare module "jquery.sap.global" { + export default jQuery; +} +declare module "jquery.sap.history" { + export default jQuery; +} +declare module "jquery.sap.keycodes" { + export default jQuery; +} +declare module "jquery.sap.mobile" { + export default jQuery; +} +declare module "jquery.sap.properties" { + export default jQuery; +} +declare module "jquery.sap.resources" { + export default jQuery; +} +declare module "jquery.sap.script" { + export default jQuery; +} +declare module "jquery.sap.sjax" { + export default jQuery; +} +declare module "jquery.sap.storage" { + export default jQuery; +} +declare module "jquery.sap.strings" { + export default jQuery; +} +declare module "jquery.sap.stubs" { + export default jQuery; +} +declare module "jquery.sap.trace" { + export default jQuery; +} +declare module "jquery.sap.ui" { + export default jQuery; +} +declare module "jquery.sap.xml" { + export default jQuery; +} diff --git a/resources/overrides/jquery.sap.mobile.d.ts b/resources/overrides/jquery.sap.mobile.d.ts index 87ffad010..a2d446c65 100644 --- a/resources/overrides/jquery.sap.mobile.d.ts +++ b/resources/overrides/jquery.sap.mobile.d.ts @@ -11,7 +11,3 @@ interface JQueryStatic { */ device: object; } - -declare module "jquery.sap.mobile" { - export default jQuery; -} diff --git a/src/detectors/typeChecker/FileLinter.ts b/src/detectors/typeChecker/FileLinter.ts index bd01018f6..e797296dd 100644 --- a/src/detectors/typeChecker/FileLinter.ts +++ b/src/detectors/typeChecker/FileLinter.ts @@ -229,15 +229,32 @@ export default class FileLinter { const symbol = this.isDeprecatedAccess(node); if (symbol) { - this.#reporter.addMessage({ - node, - severity: LintMessageSeverity.Error, - ruleId: "ui5-linter-no-deprecated-property", - message: - `Access of deprecated property ` + - `'${symbol.escapedName as string}'`, - messageDetails: this.extractDeprecatedMessage(symbol), - }); + const messageDetails = this.extractDeprecatedMessage(symbol); + if (this.isSymbolOfJquerySapType(symbol)) { + let namespace; + if (ts.isPropertyAccessExpression(node)) { + namespace = this.extractNamespace(node); + } + this.#reporter.addMessage({ + node, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-deprecated-api", + message: + `Use of deprecated API ` + + `'${namespace ?? "jQuery.sap"}'`, + messageDetails, + }); + } else { + this.#reporter.addMessage({ + node, + severity: LintMessageSeverity.Error, + ruleId: "ui5-linter-no-deprecated-property", + message: + `Access of deprecated property ` + + `'${symbol.escapedName as string}'`, + messageDetails, + }); + } } } @@ -372,6 +389,10 @@ export default class FileLinter { return false; } + isSymbolOfJquerySapType(symbol: ts.Symbol) { + return symbol.valueDeclaration?.getSourceFile().fileName === "/types/@ui5/linter/overrides/jquery.sap.d.ts"; + } + findClassOrInterface(node: ts.Node): ts.Type | undefined { let nodeType: ts.Type | undefined = this.#checker.getTypeAtLocation(node); if (nodeType.isClassOrInterface()) { diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-global.js b/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-global.js deleted file mode 100644 index 7e7e4af1a..000000000 --- a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-global.js +++ /dev/null @@ -1,3 +0,0 @@ -sap.ui.define([], function() { - var oProperties = jQuery.sap.properties(); // jQuery.sap.properties is deprecated -}); diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-jquery.js b/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-jquery.js deleted file mode 100644 index e50bdde83..000000000 --- a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-jquery.js +++ /dev/null @@ -1,3 +0,0 @@ -sap.ui.define(["sap/ui/thirdparty/jquery"], function(jQuery) { - var oProperties = jQuery.sap.properties(); // TODO detect: jQuery.sap.properties is deprecated -}); diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-module.js b/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-module.js deleted file mode 100644 index fffe37b42..000000000 --- a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap-module.js +++ /dev/null @@ -1,3 +0,0 @@ -sap.ui.define(["jquery.sap.properties"], function(jQuery) { - var oProperties = jQuery.sap.properties(); // TODO detect: jQuery.sap.properties is deprecated -}); diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap.js b/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap.js new file mode 100644 index 000000000..cb3075d78 --- /dev/null +++ b/test/fixtures/linter/rules/NoDeprecatedApi/jQuery.sap.js @@ -0,0 +1,17 @@ +sap.ui.define(["sap/ui/thirdparty/jquery", "jquery.sap.properties"], function(importedJQuery, importedJQuerySapProperties) { + + // Global access + var oProperties1 = jQuery.sap.properties(); // jQuery.sap.properties is deprecated + var oProperties2 = jQuery["sap"].properties(); // jQuery.sap.properties is deprecated + var oProperties3 = jQuery["sap"]["properties"](); // jQuery.sap.properties is deprecated + + // via thirdparty jQuery + var oProperties1 = importedJQuery.sap.properties(); // jQuery.sap.properties is deprecated + var oProperties2 = importedJQuery["sap"].properties(); // jQuery.sap.properties is deprecated + var oProperties3 = importedJQuery["sap"]["properties"](); // jQuery.sap.properties is deprecated + + // via jquery.sap module + var oProperties1 = importedJQuerySapProperties.sap.properties(); // jQuery.sap.properties is deprecated + var oProperties2 = importedJQuerySapProperties["sap"].properties(); // jQuery.sap.properties is deprecated + var oProperties3 = importedJQuerySapProperties["sap"]["properties"](); // jQuery.sap.properties is deprecated +}); diff --git a/test/fixtures/linter/rules/NoGlobals/NoGlobals.js b/test/fixtures/linter/rules/NoGlobals/NoGlobals.js index 432bb5131..ae107ec79 100644 --- a/test/fixtures/linter/rules/NoGlobals/NoGlobals.js +++ b/test/fixtures/linter/rules/NoGlobals/NoGlobals.js @@ -26,7 +26,7 @@ sap.ui.define(["sap/ui/core/mvc/Controller"], jQuery.ajax(); // ERROR: Global third-party variable "jQuery" jQuery("#foo"); // ERROR: Global third-party variable "jQuery" - jQuery.sap.require(); // ERROR: Global variable "jQuery.sap" + jQuery.sap.require(); // ERROR: Global + deprecated variable "jQuery.sap" QUnit.test(); // OK: Global third-party variable "QUnit" sinon.stub(); // OK: Global third-party variable "sinon" diff --git a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md index d02a5430f..f25c9cd98 100644 --- a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md +++ b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md @@ -636,7 +636,7 @@ Generated by [AVA](https://avajs.dev). }, ] -## General: jQuery.sap-global.js +## General: jQuery.sap.js > Snapshot 1 @@ -645,68 +645,145 @@ Generated by [AVA](https://avajs.dev). coverageInfo: [ { category: 1, - column: 20, - line: 2, + column: 21, + line: 4, message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery.sap.properties()"" could not be determined', }, + { + category: 1, + column: 21, + line: 5, + message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery["sap"].properties()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 6, + message: 'Unable to analyze this method call because the type of identifier in "jQuery["sap"]["properties"]()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 9, + message: 'Unable to analyze this method call because the type of identifier "properties" in "importedJQuery.sap.properties()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 10, + message: 'Unable to analyze this method call because the type of identifier "properties" in "importedJQuery["sap"].properties()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 11, + message: 'Unable to analyze this method call because the type of identifier in "importedJQuery["sap"]["properties"]()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 14, + message: 'Unable to analyze this method call because the type of identifier "properties" in "importedJQuerySapProperties.sap.properties()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 15, + message: 'Unable to analyze this method call because the type of identifier "properties" in "importedJQuerySapProperties["sap"].properties()"" could not be determined', + }, + { + category: 1, + column: 21, + line: 16, + message: 'Unable to analyze this method call because the type of identifier in "importedJQuerySapProperties["sap"]["properties"]()"" could not be determined', + }, ], - errorCount: 1, + errorCount: 9, fatalErrorCount: 0, - filePath: 'jQuery.sap-global.js', + filePath: 'jQuery.sap.js', messages: [ { - column: 20, + column: 21, fatal: undefined, - line: 2, - message: 'Access of global variable \'jQuery\' (jQuery.sap.properties)', - ruleId: 'ui5-linter-no-globals-js', + line: 4, + message: 'Use of deprecated API \'jQuery.sap.properties\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', severity: 2, }, - ], - warningCount: 0, - }, - ] - -## General: jQuery.sap-jquery.js - -> Snapshot 1 - - [ - { - coverageInfo: [ { - category: 1, - column: 20, - line: 2, - message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery.sap.properties()"" could not be determined', + column: 21, + fatal: undefined, + line: 5, + message: 'Use of deprecated API \'jQuery.sap\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, }, - ], - errorCount: 0, - fatalErrorCount: 0, - filePath: 'jQuery.sap-jquery.js', - messages: [], - warningCount: 0, - }, - ] - -## General: jQuery.sap-module.js - -> Snapshot 1 - - [ - { - coverageInfo: [ { - category: 1, - column: 20, - line: 2, - message: 'Unable to analyze this method call because the type of identifier "properties" in "jQuery.sap.properties()"" could not be determined', + column: 21, + fatal: undefined, + line: 6, + message: 'Use of deprecated API \'jQuery.sap\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 9, + message: 'Use of deprecated API \'importedJQuery.sap.properties\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 10, + message: 'Use of deprecated API \'jQuery.sap\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 11, + message: 'Use of deprecated API \'jQuery.sap\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 14, + message: 'Use of deprecated API \'importedJQuerySapProperties.sap.properties\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 15, + message: 'Use of deprecated API \'jQuery.sap\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 21, + fatal: undefined, + line: 16, + message: 'Use of deprecated API \'jQuery.sap\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, }, ], - errorCount: 0, - fatalErrorCount: 0, - filePath: 'jQuery.sap-module.js', - messages: [], warningCount: 0, }, ] diff --git a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap index a9eec832d..988be851f 100644 Binary files a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap and b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap differ diff --git a/test/lib/linter/rules/snapshots/NoGlobals.ts.md b/test/lib/linter/rules/snapshots/NoGlobals.ts.md index 5b61b0c72..b5fa2c06d 100644 --- a/test/lib/linter/rules/snapshots/NoGlobals.ts.md +++ b/test/lib/linter/rules/snapshots/NoGlobals.ts.md @@ -154,8 +154,9 @@ Generated by [AVA](https://avajs.dev). column: 4, fatal: undefined, line: 29, - message: 'Access of global variable \'jQuery\' (jQuery.sap.require)', - ruleId: 'ui5-linter-no-globals-js', + message: 'Use of deprecated API \'jQuery.sap.require\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', severity: 2, }, ], diff --git a/test/lib/linter/rules/snapshots/NoGlobals.ts.snap b/test/lib/linter/rules/snapshots/NoGlobals.ts.snap index c8de38df7..c0d1f72e1 100644 Binary files a/test/lib/linter/rules/snapshots/NoGlobals.ts.snap and b/test/lib/linter/rules/snapshots/NoGlobals.ts.snap differ