From 7fb5036adb252cd0761f81c78cb59224f681b018 Mon Sep 17 00:00:00 2001 From: Matthias Osswald Date: Fri, 22 Mar 2024 18:52:24 +0100 Subject: [PATCH] fix: Resolve types for framework libraries --- src/detectors/typeChecker/index.ts | 14 +++++- .../linter/projects/sap.f/src/sap/f/.library | 9 ++++ .../projects/sap.f/src/sap/f/LinterTest.js | 1 + .../projects/sap.f/test/sap/f/LinterTest.js | 9 ++++ test/lib/linter/linter.ts | 18 ++++++++ test/lib/linter/snapshots/linter.ts.md | 42 ++++++++++++++++++ test/lib/linter/snapshots/linter.ts.snap | Bin 7509 -> 7765 bytes 7 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/linter/projects/sap.f/src/sap/f/.library create mode 100644 test/fixtures/linter/projects/sap.f/src/sap/f/LinterTest.js create mode 100644 test/fixtures/linter/projects/sap.f/test/sap/f/LinterTest.js diff --git a/src/detectors/typeChecker/index.ts b/src/detectors/typeChecker/index.ts index 4f6de0e53..9a95d6769 100644 --- a/src/detectors/typeChecker/index.ts +++ b/src/detectors/typeChecker/index.ts @@ -57,9 +57,21 @@ export class TsProjectDetector extends ProjectBasedDetector { const namespace = project.getNamespace(); this.#projectBasePath = `/resources/${namespace}/`; + + const namespacePathMapping = [ + `${this.#projectBasePath}*`, + ]; + + // Special handling when linting sap/* namespaces (UI5 framework libraries): + // Add mapping for dynamic type lookup. Otherwise types within the sap library itself + // can't be resolved. + if (namespace.startsWith("sap/")) { + namespacePathMapping.push(`/types/@ui5/linter/dynamic-types/${namespace}/*`); + } + this.compilerOptions.paths = { - [`${namespace}/*`]: [`${this.#projectBasePath}*`], "sap/*": ["/types/@ui5/linter/dynamic-types/sap/*"], + [`${namespace}/*`]: namespacePathMapping, }; } diff --git a/test/fixtures/linter/projects/sap.f/src/sap/f/.library b/test/fixtures/linter/projects/sap.f/src/sap/f/.library new file mode 100644 index 000000000..1fd082a08 --- /dev/null +++ b/test/fixtures/linter/projects/sap.f/src/sap/f/.library @@ -0,0 +1,9 @@ + + + sap.f + + + sap.ui.core + + + diff --git a/test/fixtures/linter/projects/sap.f/src/sap/f/LinterTest.js b/test/fixtures/linter/projects/sap.f/src/sap/f/LinterTest.js new file mode 100644 index 000000000..abfb6fc2b --- /dev/null +++ b/test/fixtures/linter/projects/sap.f/src/sap/f/LinterTest.js @@ -0,0 +1 @@ +// This project is used to test the linter with the namespace of an OpenUI5 project. 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 new file mode 100644 index 000000000..bd2ae9084 --- /dev/null +++ b/test/fixtures/linter/projects/sap.f/test/sap/f/LinterTest.js @@ -0,0 +1,9 @@ +// This project is used to test the linter with the namespace of an OpenUI5 project. + +sap.ui.require([ + "sap/f/Avatar", + "sap/m/DateTimeInput" +], (Avatar, DateTimeInput) => { + new Avatar(); + new DateTimeInput(); +}); diff --git a/test/lib/linter/linter.ts b/test/lib/linter/linter.ts index c772de935..4b4b1e1f7 100644 --- a/test/lib/linter/linter.ts +++ b/test/lib/linter/linter.ts @@ -89,3 +89,21 @@ test.serial("lint: All files of library.with.custom.paths", async (t) => { t.snapshot(res); }); + +test.serial("lint: All files of library with sap.f namespace", async (t) => { + const projectPath = path.join(fixturesProjectsPath, "sap.f"); + const {lintProject} = t.context; + + let res = await lintProject({ + rootDir: projectPath, + filePaths: [], + reportCoverage: true, + messageDetails: true, + }); + + res = res.sort((a: {filePath: string}, b: {filePath: string}) => { + return a.filePath.localeCompare(b.filePath); + }); + + t.snapshot(res); +}); diff --git a/test/lib/linter/snapshots/linter.ts.md b/test/lib/linter/snapshots/linter.ts.md index 64d85ed8d..6552b2386 100644 --- a/test/lib/linter/snapshots/linter.ts.md +++ b/test/lib/linter/snapshots/linter.ts.md @@ -981,3 +981,45 @@ Generated by [AVA](https://avajs.dev). warningCount: 0, }, ] + +## lint: All files of library with sap.f namespace + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 0, + fatalErrorCount: 0, + filePath: 'src/sap/f/LinterTest.js', + messages: [], + warningCount: 0, + }, + { + coverageInfo: [], + errorCount: 2, + fatalErrorCount: 0, + filePath: 'test/sap/f/LinterTest.js', + messages: [ + { + column: 2, + fatal: undefined, + line: 4, + message: 'Import of deprecated module \'sap/f/Avatar\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + { + column: 2, + fatal: undefined, + line: 5, + message: 'Import of deprecated module \'sap/m/DateTimeInput\'', + messageDetails: 'Deprecated test message', + ruleId: 'ui5-linter-no-deprecated-api', + severity: 2, + }, + ], + warningCount: 0, + }, + ] diff --git a/test/lib/linter/snapshots/linter.ts.snap b/test/lib/linter/snapshots/linter.ts.snap index 7bd19f66763824b11328dd95e719d98c199aa26e..f7ba49539e86cc08cb504212f8ee2a6581eee130 100644 GIT binary patch literal 7765 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