Skip to content

Commit

Permalink
feat: Detect deprecated deps in Lib.init call (#197)
Browse files Browse the repository at this point in the history
JIRA: CPOUI5FOUNDATION-825

The `.library` detection is addressed in the following PR:
#104
  • Loading branch information
d3xter666 authored Jul 17, 2024
1 parent dc1c887 commit 9c9c406
Show file tree
Hide file tree
Showing 11 changed files with 522 additions and 68 deletions.
10 changes: 10 additions & 0 deletions src/linter/linterReporting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const MESSAGES = {

SHORT__DEPRECATED_PROP_OF_CLASS: "Use of deprecated property '{0}' of class '{1}'",

SHORT__DEPRECATED_PROP: "Use of deprecated property {0}",

SHORT__DEPRECATED_FUNCTION_ACCESS: "Call to deprecated function {0}",

SHORT__DEPRECATED_API_ACCESS: "Use of deprecated API '{0}'",
Expand All @@ -17,10 +19,16 @@ export const MESSAGES = {

SHORT__DEPRECATED_MODULE_IMPORT: "Import of deprecated module '{0}'",

SHORT__DEPRECATED_COMPONENT: "Use of deprecated component '{0}'",

SHORT__GLOBAL_VAR_ACCESS: "Access of global variable '{0}' ({1})",

SHORT__LIB_INIT_2: "Call to {0}() must be declared with property {apiVersion: 2}",
DETAILS__LIB_INIT_2: "{@link sap.ui.core.Lib.init Lib.init}",

SHORT__DEPRECATED_LIBRARY: "Use of deprecated library '{0}'",

SHORT__DEPRECATED_MODEL_TYPE: "Use of deprecated model type '{0}'",
};

// TODO: Migrate to enum instead of Object/Map
Expand All @@ -32,6 +40,8 @@ export const RULES = {
"ui5-linter-no-pseudo-modules": "ui5-linter-no-pseudo-modules",
"ui5-linter-no-globals-js": "ui5-linter-no-globals-js",
"ui5-linter-parsing-error": "ui5-linter-parsing-error",
"ui5-linter-no-deprecated-library": "ui5-linter-no-deprecated-library",
"ui5-linter-no-deprecated-component": "ui5-linter-no-deprecated-component",
};

export function formatMessage(message: string, ...params: string[]) {
Expand Down
27 changes: 15 additions & 12 deletions src/linter/manifestJson/ManifestLinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {LintMessageSeverity, ResourcePath} from "../LinterContext.js";
import jsonMap from "json-source-map";
import LinterContext from "../LinterContext.js";
import {deprecatedLibraries, deprecatedComponents} from "../../utils/deprecations.js";
import {RULES, MESSAGES, formatMessage} from "../linterReporting.js";

interface locType {
line: number;
Expand Down Expand Up @@ -69,8 +70,8 @@ export default class ManifestLinter {
this.#reporter?.addMessage({
node: `/sap.ui5/dependencies/libs/${libKey}`,
severity: LintMessageSeverity.Error,
ruleId: "ui5-linter-no-deprecated-library",
message: `Use of deprecated library '${libKey}'`,
ruleId: RULES["ui5-linter-no-deprecated-library"],
message: formatMessage(MESSAGES.SHORT__DEPRECATED_LIBRARY, libKey),
});
}
});
Expand All @@ -82,8 +83,8 @@ export default class ManifestLinter {
this.#reporter?.addMessage({
node: `/sap.ui5/dependencies/components/${componentKey}`,
severity: LintMessageSeverity.Error,
ruleId: "ui5-linter-no-deprecated-component",
message: `Use of deprecated component '${componentKey}'`,
ruleId: RULES["ui5-linter-no-deprecated-component"],
message: formatMessage(MESSAGES.SHORT__DEPRECATED_COMPONENT, componentKey),
});
}
});
Expand All @@ -92,8 +93,8 @@ export default class ManifestLinter {
this.#reporter?.addMessage({
node: "/sap.ui5/resources/js",
severity: LintMessageSeverity.Error,
ruleId: "ui5-linter-no-deprecated-api",
message: `Use of deprecated property 'sap.ui5/resources/js'`,
ruleId: RULES["ui5-linter-no-deprecated-api"],
message: formatMessage(MESSAGES.SHORT__DEPRECATED_PROP, "'sap.ui5/resources/js'"),
});
}

Expand Down Expand Up @@ -123,9 +124,10 @@ export default class ManifestLinter {
this.#reporter?.addMessage({
node: `/sap.ui5/models/${modelKey}/type`,
severity: LintMessageSeverity.Error,
ruleId: "ui5-linter-no-deprecated-api",
message: `Use of deprecated model type ` +
`'sap.ui5/models/${modelKey}/type="${curModel.type}"'`,
ruleId: RULES["ui5-linter-no-deprecated-api"],
message: formatMessage(MESSAGES.SHORT__DEPRECATED_MODEL_TYPE,
`sap.ui5/models/${modelKey}/type="${curModel.type}"`)
,
});
}

Expand All @@ -134,9 +136,10 @@ export default class ManifestLinter {
this.#reporter?.addMessage({
node: `/sap.ui5/models/${modelKey}/settings/synchronizationMode`,
severity: LintMessageSeverity.Error,
ruleId: "ui5-linter-no-deprecated-api",
message: `Use of deprecated property ` +
`'sap.ui5/models/${modelKey}/settings/synchronizationMode' of sap.ui.model.odata.v4.ODataModel`,
ruleId: RULES["ui5-linter-no-deprecated-api"],
message: formatMessage(MESSAGES.SHORT__DEPRECATED_PROP,
`'sap.ui5/models/${modelKey}/settings/synchronizationMode' of sap.ui.model.odata.v4.ODataModel`
),
});
}
});
Expand Down
38 changes: 38 additions & 0 deletions src/linter/ui5Types/SourceFileLinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import SourceFileReporter from "./SourceFileReporter.js";
import LinterContext, {ResourcePath, CoverageCategory, LintMessageSeverity} from "../LinterContext.js";
import {RULES, MESSAGES, formatMessage} from "../linterReporting.js";
import analyzeComponentJson from "./asyncComponentFlags.js";
import {deprecatedLibraries} from "../../utils/deprecations.js";

interface DeprecationInfo {
symbol: ts.Symbol;
Expand Down Expand Up @@ -325,6 +326,43 @@ export default class SourceFileLinter {
messageDetails: this.#messageDetails ? formatMessage(MESSAGES.DETAILS__LIB_INIT_2) : undefined,
});
}

if (initArg) {
this.#analyzeLibInitDeprecatedLibs(initArg);
}
}

#analyzeLibInitDeprecatedLibs(initArg: ts.ObjectLiteralExpression) {
const dependenciesNode = initArg.properties.find((prop) => {
return ts.isPropertyAssignment(prop) &&
ts.isIdentifier(prop.name) &&
prop.name.text === "dependencies";
});

if (!dependenciesNode ||
!ts.isPropertyAssignment(dependenciesNode) ||
!ts.isArrayLiteralExpression(dependenciesNode.initializer)) {
return;
}

dependenciesNode.initializer.elements.forEach((dependency) => {
if (!ts.isStringLiteral(dependency)) {
// We won't be interested if the elements of the Array are not of type
// StringLiteral, so we ignore such cases here (if such at all).
return;
}

const curLibName = dependency.text;

if (deprecatedLibraries.includes(curLibName)) {
this.#reporter.addMessage({
ruleId: RULES["ui5-linter-no-deprecated-library"],
severity: LintMessageSeverity.Error,
node: dependency,
message: formatMessage(MESSAGES.SHORT__DEPRECATED_LIBRARY, curLibName),
});
}
});
}

getDeprecationInfoForAccess(node: ts.AccessExpression): DeprecationInfo | null {
Expand Down
7 changes: 4 additions & 3 deletions src/linter/yaml/YamlLinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {LintMessageSeverity} from "../LinterContext.js";
import LinterContext from "../LinterContext.js";
import {deprecatedLibraries, deprecatedThemeLibraries} from "../../utils/deprecations.js";
import {DataWithPosition, fromYaml, getPosition} from "data-with-position";
import {RULES, MESSAGES, formatMessage} from "../linterReporting.js";

interface YamlWithPosInfo extends DataWithPosition {
framework?: {
Expand Down Expand Up @@ -53,7 +54,7 @@ export default class YamlLinter {
this.#context.addLintingMessage(this.#resourcePath, {
severity: LintMessageSeverity.Error,
message,
ruleId: "ui5-linter-parsing-error",
ruleId: RULES["ui5-linter-parsing-error"],
fatal: true,
});
}
Expand All @@ -71,12 +72,12 @@ export default class YamlLinter {
if (deprecatedLibraries.includes(libraryName) || deprecatedThemeLibraries.includes(libraryName)) {
const positionInfo = getPosition(lib);
this.#context.addLintingMessage(this.#resourcePath, {
ruleId: "ui5-linter-no-deprecated-api",
ruleId: RULES["ui5-linter-no-deprecated-library"],
severity: LintMessageSeverity.Error,
fatal: undefined,
line: positionInfo.start.line + offset,
column: positionInfo.start.column,
message: `Use of deprecated library '${libraryName}'`,
message: formatMessage(MESSAGES.SHORT__DEPRECATED_LIBRARY, libraryName),
});
}
});
Expand Down
64 changes: 58 additions & 6 deletions test/fixtures/linter/rules/NoDeprecatedApi/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,21 @@ sap.ui.define([

Library.init();
Library.init("a");
Library.init({});
Library.init({
test: 12
dependencies: []
});
Library.init({
test: 12,
dependencies: [
"sap.ui.commons",
"sap.ui.suite",
"sap.ui.ux3",
"sap.ui.vtm",
"sap.uiext.inbox",
"sap.webanalytics.core",
"sap.zen.commons",
"sap.zen.crosstab",
]
});
Library.init({
apiVersion: "23"
Expand All @@ -22,21 +34,61 @@ sap.ui.define([
apiVersion: "2"
});
Library["init"]({
apiVersion: 1
apiVersion: 1,
dependencies: [
"sap.ui.commons",
"sap.ui.suite",
"sap.ui.ux3",
"sap.ui.vtm",
"sap.uiext.inbox",
"sap.webanalytics.core",
"sap.zen.commons",
"sap.zen.crosstab",
]
});

const LibInit = Library.init;
LibInit({
apiVersion: 1
apiVersion: 1,
dependencies: [
"sap.ui.commons",
"sap.ui.suite",
"sap.ui.ux3",
"sap.ui.vtm",
"sap.uiext.inbox",
"sap.webanalytics.core",
"sap.zen.commons",
"sap.zen.crosstab",
]
});

const {init} = Library;
init({
apiVersion: 1
apiVersion: 1,
dependencies: [
"sap.ui.commons",
"sap.ui.suite",
"sap.ui.ux3",
"sap.ui.vtm",
"sap.uiext.inbox",
"sap.webanalytics.core",
"sap.zen.commons",
"sap.zen.crosstab",
]
});

const {init: intRenames} = Library;
intRenames({
apiVersion: 1
apiVersion: 1,
dependencies: [
"sap.ui.commons",
"sap.ui.suite",
"sap.ui.ux3",
"sap.ui.vtm",
"sap.uiext.inbox",
"sap.webanalytics.core",
"sap.zen.commons",
"sap.zen.crosstab",
]
});
});
42 changes: 36 additions & 6 deletions test/fixtures/linter/rules/NoDeprecatedApi/library_negative.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,60 @@ sap.ui.define([
"use strict";

Library.init({
apiVersion: 2
apiVersion: 2,
dependencies: [
"sap.ui.core",
"sap.m",
"sap.f",
]
});

Library["init"]({
apiVersion: 2
apiVersion: 2,
dependencies: [
"sap.ui.core",
"sap.m",
"sap.f",
]
});

// Should be ignored
Library.load({
apiVersion: 23
apiVersion: 23,
dependencies: [
"sap.ui.core",
"sap.m",
"sap.f",
]
});

const LibInit = Library.init;
LibInit({
apiVersion: 2
apiVersion: 2,
dependencies: [
"sap.ui.core",
"sap.m",
"sap.f",
]
});

const {init} = Library;
init({
apiVersion: 2
apiVersion: 2,
dependencies: [
"sap.ui.core",
"sap.m",
"sap.f",
]
});

const {init: intRenames} = Library;
intRenames({
apiVersion: 2
apiVersion: 2,
dependencies: [
"sap.ui.core",
"sap.m",
"sap.f",
]
});
});
Loading

0 comments on commit 9c9c406

Please sign in to comment.