diff --git a/src/linter/ui5Types/SourceFileLinter.ts b/src/linter/ui5Types/SourceFileLinter.ts index e86c61420..ded0a3512 100644 --- a/src/linter/ui5Types/SourceFileLinter.ts +++ b/src/linter/ui5Types/SourceFileLinter.ts @@ -385,6 +385,9 @@ export default class SourceFileLinter { return apiVersionNode; }; + const nodeType = this.checker.getTypeAtLocation(node); + const nodeValueDeclaration = nodeType.getSymbol()?.valueDeclaration; + // Analyze renderer property when it's an ObjectLiteralExpression // i.e. { renderer: {apiVersion: "2", render: () => {}} } if (node && (ts.isObjectLiteralExpression(node) || ts.isVariableDeclaration(node))) { @@ -420,7 +423,13 @@ export default class SourceFileLinter { this.analyzeIconCallInRenderMethod(node); // Analyze renderer property when it's a function i.e. { renderer: () => {} } } else if (ts.isMethodDeclaration(node) || ts.isArrowFunction(node) || - ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) { + ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ( + nodeValueDeclaration && ( + ts.isFunctionExpression(nodeValueDeclaration) || + ts.isFunctionDeclaration(nodeValueDeclaration) || + ts.isArrowFunction(nodeValueDeclaration) + ) + )) { // reporter.addMessage() won't work in this case as it's bound to the current analyzed file. // The findings can be in different file i.e. Control being analyzed, // but reporting might be in ControlRenderer diff --git a/test/fixtures/linter/projects/sap.f/test/sap/f/LinterTest.js b/test/fixtures/linter/projects/sap.f/test/sap/f/LinterTest.js index bd2ae9084..40c6f6fb0 100644 --- a/test/fixtures/linter/projects/sap.f/test/sap/f/LinterTest.js +++ b/test/fixtures/linter/projects/sap.f/test/sap/f/LinterTest.js @@ -2,8 +2,16 @@ sap.ui.require([ "sap/f/Avatar", - "sap/m/DateTimeInput" -], (Avatar, DateTimeInput) => { + "sap/m/DateTimeInput", + "sap/f/ProductSwitchRenderer" +], (Avatar, DateTimeInput, ProductSwitchRenderer) => { new Avatar(); new DateTimeInput(); + + Avatar.extend("CustomControl", { + // Usage of render function without object is deprecated as no apiVersion is defined + // TODO detect: This is currently not detected as the module resolution is not working correctly. + // This needs to be solved in a separate change. + renderer: ProductSwitchRenderer.render + }); }); diff --git a/test/fixtures/linter/rules/renderer/10Control.js b/test/fixtures/linter/rules/renderer/10Control.js new file mode 100644 index 000000000..aa0f1de85 --- /dev/null +++ b/test/fixtures/linter/rules/renderer/10Control.js @@ -0,0 +1,8 @@ +sap.ui.define(["sap/ui/core/Control", "./8ControlRenderer"], function (Control, Renderer) { + var myControl = Control.extend("mycomp.myControl", { + metadata: {}, + renderer: Renderer.render, + }); + + return myControl; +}); diff --git a/test/fixtures/linter/rules/renderer/11Control.js b/test/fixtures/linter/rules/renderer/11Control.js new file mode 100644 index 000000000..06f1a2a9a --- /dev/null +++ b/test/fixtures/linter/rules/renderer/11Control.js @@ -0,0 +1,11 @@ +sap.ui.define(["sap/ui/core/Control"], function (Control) { + function render(oRm, oMyControl) {} + const Renderer = {render}; + + var myControl = Control.extend("mycomp.myControl", { + metadata: {}, + renderer: Renderer.render, + }); + + return myControl; +}); diff --git a/test/fixtures/linter/rules/renderer/2ControlRenderer.js b/test/fixtures/linter/rules/renderer/2ControlRenderer.js index 242f3194d..049d7956f 100644 --- a/test/fixtures/linter/rules/renderer/2ControlRenderer.js +++ b/test/fixtures/linter/rules/renderer/2ControlRenderer.js @@ -3,7 +3,7 @@ sap.ui.define([], function () { myControlRenderer.apiVersion = 1; // Deprecated - myControlRenderer.render = function (oRm, oMyControl) {}; + myControlRenderer.render = (oRm, oMyControl) => {}; return myControlRenderer; }); diff --git a/test/fixtures/linter/rules/renderer/9Control.js b/test/fixtures/linter/rules/renderer/9Control.js new file mode 100644 index 000000000..a1cb36d67 --- /dev/null +++ b/test/fixtures/linter/rules/renderer/9Control.js @@ -0,0 +1,8 @@ +sap.ui.define(["sap/ui/core/Control", "./2ControlRenderer"], function (Control, Renderer) { + var myControl = Control.extend("mycomp.myControl", { + metadata: {}, + renderer: Renderer.render, + }); + + return myControl; +}); diff --git a/test/lib/linter/rules/snapshots/renderer.ts.md b/test/lib/linter/rules/snapshots/renderer.ts.md index 2ba67a1a4..61ca809ec 100644 --- a/test/lib/linter/rules/snapshots/renderer.ts.md +++ b/test/lib/linter/rules/snapshots/renderer.ts.md @@ -9,6 +9,40 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 [ + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: '10Control.js', + messages: [ + { + column: 13, + line: 4, + message: 'Use of deprecated renderer detected. Define explicitly the {apiVersion: 2} parameter in the renderer object', + messageDetails: '"Renderer Object (https://ui5.sap.com/#/topic/c9ab34570cc14ea5ab72a6d1a4a03e3f)",', + ruleId: 'no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: '11Control.js', + messages: [ + { + column: 13, + line: 7, + message: 'Use of deprecated renderer detected. Define explicitly the {apiVersion: 2} parameter in the renderer object', + messageDetails: '"Renderer Object (https://ui5.sap.com/#/topic/c9ab34570cc14ea5ab72a6d1a4a03e3f)",', + ruleId: 'no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, { coverageInfo: [ { @@ -376,6 +410,23 @@ Generated by [AVA](https://avajs.dev). ], warningCount: 0, }, + { + coverageInfo: [], + errorCount: 1, + fatalErrorCount: 0, + filePath: '9Control.js', + messages: [ + { + column: 13, + line: 4, + message: 'Use of deprecated renderer detected. Define explicitly the {apiVersion: 2} parameter in the renderer object', + messageDetails: '"Renderer Object (https://ui5.sap.com/#/topic/c9ab34570cc14ea5ab72a6d1a4a03e3f)",', + ruleId: 'no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, { coverageInfo: [], errorCount: 3, diff --git a/test/lib/linter/rules/snapshots/renderer.ts.snap b/test/lib/linter/rules/snapshots/renderer.ts.snap index 0e1f909bc..95ce23e85 100644 Binary files a/test/lib/linter/rules/snapshots/renderer.ts.snap and b/test/lib/linter/rules/snapshots/renderer.ts.snap differ