Skip to content

Commit 87c21e6

Browse files
committed
fix(ConfigManager): Resolve ESM import exception on Windows
import(path) does not accept absolute Windows-paths since those seem to get confused with URLs. Before, this was mitigated by always calculating a relative path (relative to the UI5 linter install directory). This however breaks on Windows if the target project is located on another drive as reported in #458 Instead convert all paths to "file://"-URLs before passing them to import(). Also, in linter.ts, enforce the project root path to always be absolute to simplify handling the path later on. Resolves #458
1 parent 2bb7e9d commit 87c21e6

File tree

4 files changed

+27
-13
lines changed

4 files changed

+27
-13
lines changed

src/linter/linter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import {Minimatch} from "minimatch";
1414
export async function lintProject({
1515
rootDir, filePatterns, ignorePatterns, coverage, details, configPath, ui5Config, noConfig,
1616
}: LinterOptions): Promise<LintResult[]> {
17+
if (!path.isAbsolute(rootDir)) {
18+
throw new Error(`rootDir must be an absolute path. Received: ${rootDir}`);
19+
}
1720
let config: UI5LintConfigType = {};
1821
if (noConfig !== true) {
1922
const configMngr = new ConfigManager(rootDir, configPath);

src/utils/ConfigManager.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import path, {dirname} from "node:path";
2-
import {fileURLToPath} from "node:url";
2+
import {fileURLToPath, pathToFileURL} from "node:url";
33
import {FilePattern} from "../linter/LinterContext.js";
44
const __dirname = dirname(fileURLToPath(import.meta.url));
55

@@ -28,22 +28,16 @@ export default class ConfigManager {
2828
}
2929

3030
#resolveModulePaths(fileName: string): string {
31-
// Node on Windows behaves strange, does not work with absolute paths
32-
// and modifies files extensions in tests i.e. js -> ts, mjs -> tjs
33-
// Keeping the relative path in POSIX format resolves those issues.
34-
return path.posix.join(
35-
path.relative(__dirname, this.#projectRootDir).replaceAll(path.win32.sep, path.posix.sep),
36-
fileName);
31+
const resolvedPath = path.join(this.#projectRootDir, fileName);
32+
return pathToFileURL(resolvedPath).toString();
3733
}
3834

3935
async getConfiguration(): Promise<UI5LintConfigType> {
4036
let config = {} as UI5LintConfigType;
4137

4238
if (this.#configFile) {
4339
// If it's an relative path, transform to POSIX format
44-
const configFilePath = path.isAbsolute(this.#configFile) ?
45-
this.#configFile :
46-
this.#resolveModulePaths(this.#configFile);
40+
const configFilePath = this.#resolveModulePaths(this.#configFile);
4741

4842
({default: config} = await import(configFilePath) as {default: UI5LintConfigType});
4943
} else {

test/lib/linter/linter.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,3 +424,18 @@ test.serial("lint: getProjectGraph with different directory structures", async (
424424
},
425425
});
426426
});
427+
428+
// Test project fixtures individually
429+
test.serial("lint: Relative rootDir path throws an exception", async (t) => {
430+
const projectPath = path.join(fixturesProjectsPath, "com.ui5.troublesome.app");
431+
const {lintProject} = t.context;
432+
433+
await t.throwsAsync(() => {
434+
return lintProject({
435+
rootDir: path.relative(__dirname, projectPath),
436+
filePatterns: [],
437+
coverage: true,
438+
details: true,
439+
});
440+
});
441+
});

test/lib/utils/configManager.ts renamed to test/lib/utils/ConfigManager.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ const fixturesBasePath = path.join(__dirname, "..", "..", "fixtures", "linter");
99
const fixturesProjectsPath = path.join(fixturesBasePath, "projects");
1010

1111
test("Check config file", async (t) => {
12-
const confManager = new ConfigManager("./test/fixtures/linter/projects/com.ui5.troublesome.app/",
12+
const confManager = new ConfigManager(
13+
path.join(fixturesProjectsPath, "com.ui5.troublesome.app"),
1314
"ui5lint-custom.config.cjs");
1415

1516
const config = await confManager.getConfiguration();
@@ -24,7 +25,8 @@ test("Check config file", async (t) => {
2425
});
2526

2627
test("Check config file auto discovery", async (t) => {
27-
const confManager = new ConfigManager("./test/fixtures/linter/projects/com.ui5.troublesome.app/");
28+
const confManager = new ConfigManager(
29+
path.join(fixturesProjectsPath, "com.ui5.troublesome.app"));
2830

2931
const config = await confManager.getConfiguration();
3032

@@ -48,7 +50,7 @@ test("Throws an error if config file has Syntax errors", async (t) => {
4850

4951
test("Resolves to an empty config if default module is not found", async (t) => {
5052
const confManager = new ConfigManager(
51-
"./test/fixtures/linter/projects/library.with.custom.paths/");
53+
path.join(fixturesProjectsPath, "library.with.custom.paths/"));
5254

5355
const config = await confManager.getConfiguration();
5456

0 commit comments

Comments
 (0)