Skip to content

Commit

Permalink
refactor: Rename path variables and types for clarity
Browse files Browse the repository at this point in the history
* Use "ResourcePath" for virtual paths (= always POSIX)
* Use "FilePath" for physical FS paths (POSIX or Windows)
  • Loading branch information
RandomByte committed Apr 11, 2024
1 parent 42421cf commit 583e026
Show file tree
Hide file tree
Showing 17 changed files with 139 additions and 143 deletions.
4 changes: 2 additions & 2 deletions src/cli/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ async function handleLint(argv: ArgumentsCamelCase<LinterArg>) {

const res = await lintProject({
rootDir: path.join(process.cwd()),
filePaths: filePaths?.map((filePath) => path.resolve(process.cwd(), filePath)),
pathsToLint: filePaths?.map((filePath) => path.resolve(process.cwd(), filePath)),
reportCoverage,
messageDetails: details,
includeMessageDetails: details,
});

if (reportCoverage) {
Expand Down
86 changes: 41 additions & 45 deletions src/linter/LinterContext.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {AbstractAdapter, AbstractReader} from "@ui5/fs";
import {createReader} from "@ui5/fs/resourceFactory";

export type FilePath = string;
export type FilePath = string; // Platform-dependent path
export type ResourcePath = string; // Always POSIX

// Data types are structured very similar to the ESLint types for better compatibility into existing integrations:
// https://eslint.org/docs/latest/integrate/nodejs-api#-lintresult-type
Expand Down Expand Up @@ -53,9 +54,9 @@ export interface TranspileResult {
export interface LinterOptions {
rootDir: string;
namespace?: string;
filePaths?: FilePath[];
pathsToLint?: FilePath[];
reportCoverage?: boolean;
messageDetails?: boolean;
includeMessageDetails?: boolean;
}

export interface LinterParameters {
Expand Down Expand Up @@ -83,24 +84,24 @@ export interface LintMetadata {
export default class LinterContext {
#rootDir: string;
#namespace: string | undefined;
#messages = new Map<FilePath, LintMessage[]>();
#coverageInfo = new Map<FilePath, CoverageInfo[]>();
#metadata = new Map<FilePath, LintMetadata>();
#messages = new Map<ResourcePath, LintMessage[]>();
#coverageInfo = new Map<ResourcePath, CoverageInfo[]>();
#metadata = new Map<ResourcePath, LintMetadata>();
#rootReader: AbstractReader | undefined;

#filePaths: FilePath[] | undefined;
// Mapping original file paths to aliases, such as the paths of transpiled resources
#filePathAliases = new Map<FilePath, FilePath>();
#resourcePathsToLint: ResourcePath[] | undefined;
// Mapping original resource paths to aliases, such as the paths of transpiled resources
#resourcePathAliases = new Map<ResourcePath, ResourcePath>();

#reportCoverage: boolean;
#messageDetails: boolean;
#includeMessageDetails: boolean;

constructor(options: LinterOptions) {
this.#rootDir = options.rootDir;
this.#namespace = options.namespace;
this.#filePaths = options.filePaths ? [...options.filePaths] : undefined;
this.#resourcePathsToLint = options.pathsToLint ? [...options.pathsToLint] : undefined;
this.#reportCoverage = !!options.reportCoverage;
this.#messageDetails = !!options.messageDetails;
this.#includeMessageDetails = !!options.includeMessageDetails;
}

getRootDir(): string {
Expand All @@ -122,60 +123,60 @@ export default class LinterContext {
return this.#namespace;
}

getFilePaths(): FilePath[] | undefined {
return this.#filePaths;
getPathsToLint(): ResourcePath[] | undefined {
return this.#resourcePathsToLint;
}

getReportCoverage(): boolean {
return this.#reportCoverage;
}

getMessageDetails(): boolean {
return this.#messageDetails;
getIncludeMessageDetails(): boolean {
return this.#includeMessageDetails;
}

getMetadata(filePath: FilePath): LintMetadata {
let metadata = this.#metadata.get(filePath);
getMetadata(resourcePath: ResourcePath): LintMetadata {
let metadata = this.#metadata.get(resourcePath);
if (!metadata) {
metadata = {} as LintMetadata;
this.#metadata.set(filePath, metadata);
this.#metadata.set(resourcePath, metadata);
}
return metadata;
}

addFilePathToLint(filePath: FilePath) {
this.#filePaths?.push(filePath);
addPathToLint(resourcePath: ResourcePath) {
this.#resourcePathsToLint?.push(resourcePath);
}

getLintingMessages(filePath: FilePath): LintMessage[] {
let messages = this.#messages.get(filePath);
getLintingMessages(resourcePath: ResourcePath): LintMessage[] {
let messages = this.#messages.get(resourcePath);
if (!messages) {
messages = [];
this.#messages.set(filePath, messages);
this.#messages.set(resourcePath, messages);
}
return messages;
}

addLintingMessage(filePath: FilePath, message: LintMessage) {
this.getLintingMessages(filePath).push(message);
addLintingMessage(resourcePath: ResourcePath, message: LintMessage) {
this.getLintingMessages(resourcePath).push(message);
}

getCoverageInfo(filePath: FilePath): CoverageInfo[] {
let coverageInfo = this.#coverageInfo.get(filePath);
getCoverageInfo(resourcePath: ResourcePath): CoverageInfo[] {
let coverageInfo = this.#coverageInfo.get(resourcePath);
if (!coverageInfo) {
coverageInfo = [];
this.#coverageInfo.set(filePath, coverageInfo);
this.#coverageInfo.set(resourcePath, coverageInfo);
}
return coverageInfo;
}

addCoverageInfo(filePath: FilePath, coverageInfo: CoverageInfo) {
this.getCoverageInfo(filePath).push(coverageInfo);
addCoverageInfo(resourcePath: ResourcePath, coverageInfo: CoverageInfo) {
this.getCoverageInfo(resourcePath).push(coverageInfo);
}

generateLintResult(filePath: FilePath): LintResult {
const messages = this.#messages.get(filePath) ?? [];
const coverageInfo = this.#coverageInfo.get(filePath) ?? [];
generateLintResult(resourcePath: ResourcePath): LintResult {
const messages = this.#messages.get(resourcePath) ?? [];
const coverageInfo = this.#coverageInfo.get(resourcePath) ?? [];
let errorCount = 0;
let warningCount = 0;
let fatalErrorCount = 0;
Expand All @@ -190,13 +191,8 @@ export default class LinterContext {
}
}

// Map aliases back to the original file
if (this.#filePathAliases.has(filePath)) {
filePath = this.#filePathAliases.get(filePath)!;
}

return {
filePath,
filePath: resourcePath,
messages,
coverageInfo,
errorCount,
Expand All @@ -207,14 +203,14 @@ export default class LinterContext {

generateLintResults(): LintResult[] {
const lintResults: LintResult[] = [];
let filePaths;
let resourcePaths;
if (this.#reportCoverage) {
filePaths = new Set([...this.#messages.keys(), ...this.#coverageInfo.keys()]).values();
resourcePaths = new Set([...this.#messages.keys(), ...this.#coverageInfo.keys()]).values();
} else {
filePaths = this.#messages.keys();
resourcePaths = this.#messages.keys();
}
for (const filePath of filePaths) {
lintResults.push(this.generateLintResult(filePath));
for (const resourcePath of resourcePaths) {
lintResults.push(this.generateLintResult(resourcePath));
}
return lintResults;
}
Expand Down
12 changes: 6 additions & 6 deletions src/linter/html/HtmlReporter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Tag as SaxTag} from "sax-wasm";
import LinterContext, {CoverageInfo, LintMessage, LintMessageSeverity} from "../LinterContext.js";
import LinterContext, {CoverageInfo, LintMessage, LintMessageSeverity, ResourcePath} from "../LinterContext.js";
import {resolveLinks} from "../../formatter/lib/resolveLinks.js";

interface ReporterMessage extends LintMessage {
Expand All @@ -11,11 +11,11 @@ interface ReporterCoverageInfo extends CoverageInfo {
}

export default class HtmlReporter {
#filePath: string;
#resourcePath: string;
#context: LinterContext;

constructor(filePath: string, context: LinterContext) {
this.#filePath = filePath;
constructor(resourcePath: ResourcePath, context: LinterContext) {
this.#resourcePath = resourcePath;
this.#context = context;
}

Expand All @@ -29,7 +29,7 @@ export default class HtmlReporter {
({line, character: column} = node.openStart);
}

this.#context.addLintingMessage(this.#filePath, {
this.#context.addLintingMessage(this.#resourcePath, {
ruleId,
severity,
fatal,
Expand All @@ -47,7 +47,7 @@ export default class HtmlReporter {
({line: endLine, character: endColumn} = node.closeEnd);
}

this.#context.addCoverageInfo(this.#filePath, {
this.#context.addCoverageInfo(this.#resourcePath, {
category,
// One-based to be aligned with most IDEs
line: line + 1,
Expand Down
12 changes: 6 additions & 6 deletions src/linter/html/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import {Resource} from "@ui5/fs";

export default async function lintHtml({workspace, context}: LinterParameters) {
let htmlResources: Resource[];
const filePaths = context.getFilePaths();
if (filePaths?.length) {
const pathsToLint = context.getPathsToLint();
if (pathsToLint?.length) {
htmlResources = [];
await Promise.all(filePaths.map(async (filePath) => {
if (!filePath.endsWith(".html")) {
await Promise.all(pathsToLint.map(async (resourcePath) => {
if (!resourcePath.endsWith(".html")) {
return;
}
const resource = await workspace.byPath(filePath);
const resource = await workspace.byPath(resourcePath);
if (!resource) {
throw new Error(`Resource not found: ${filePath}`);
throw new Error(`Resource not found: ${resourcePath}`);
}
htmlResources.push(resource);
}));
Expand Down
10 changes: 5 additions & 5 deletions src/linter/html/transpiler.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {ReadStream} from "node:fs";
import {extractJSScriptTags} from "./parser.js";
import HtmlReporter from "./HtmlReporter.js";
import LinterContext, {LintMessageSeverity, TranspileResult} from "../LinterContext.js";
import LinterContext, {LintMessageSeverity, ResourcePath, TranspileResult} from "../LinterContext.js";
import {taskStart} from "../../util/perf.js";

export default async function transpileHtml(
resourceName: string, contentStream: ReadStream, context: LinterContext
resourcePath: ResourcePath, contentStream: ReadStream, context: LinterContext
): Promise<TranspileResult> {
try {
const taskEnd = taskStart("Transpile XML", resourceName, true);
const report = new HtmlReporter(resourceName, context);
const taskEnd = taskStart("Transpile XML", resourcePath, true);
const report = new HtmlReporter(resourcePath, context);
const jsScriptTags = await extractJSScriptTags(contentStream);

jsScriptTags.forEach((tag) => {
Expand All @@ -30,7 +30,7 @@ export default async function transpileHtml(
return {source: "", map: ""};
} catch (err) {
if (err instanceof Error) {
throw new Error(`Failed to transpile resource ${resourceName}: ${err.message}`, {
throw new Error(`Failed to transpile resource ${resourcePath}: ${err.message}`, {
cause: err,
});
} else {
Expand Down
26 changes: 13 additions & 13 deletions src/linter/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ async function lint(
}

export async function lintProject({
rootDir, filePaths, reportCoverage, messageDetails,
rootDir, pathsToLint, reportCoverage, includeMessageDetails,
}: LinterOptions): Promise<LintResult[]> {
const projectGraphDone = taskStart("Project Graph creation");
const graph = await getProjectGraph(rootDir);
Expand Down Expand Up @@ -60,18 +60,18 @@ export async function lintProject({
});
}
let resolvedFilePaths;
if (filePaths?.length) {
const absoluteFilePaths = resolveFilePaths(rootDir, filePaths);
if (pathsToLint?.length) {
const absoluteFilePaths = resolveFilePaths(rootDir, pathsToLint);
resolvedFilePaths = transformFilePathsToVirtualPaths(
absoluteFilePaths, fsBasePath, virBasePath, fsBasePathTest, virBasePathTest);
}

const res = await lint(reader, {
rootDir,
namespace: project.getNamespace(),
filePaths: resolvedFilePaths,
pathsToLint: resolvedFilePaths,
reportCoverage,
messageDetails,
includeMessageDetails,
});

const relFsBasePath = path.relative(rootDir, fsBasePath);
Expand All @@ -85,25 +85,25 @@ export async function lintProject({
}

export async function lintFile({
rootDir, filePaths, namespace, reportCoverage, messageDetails,
rootDir, pathsToLint, namespace, reportCoverage, includeMessageDetails,
}: LinterOptions): Promise<LintResult[]> {
const reader = createReader({
fsBasePath: rootDir,
virBasePath: "/",
});
let resolvedFilePaths;
if (filePaths?.length) {
const absoluteFilePaths = resolveFilePaths(rootDir, filePaths);
if (pathsToLint?.length) {
const absoluteFilePaths = resolveFilePaths(rootDir, pathsToLint);
resolvedFilePaths = transformFilePathsToVirtualPaths(
absoluteFilePaths, rootDir, "/", rootDir);
}

const res = await lint(reader, {
rootDir,
namespace,
filePaths: resolvedFilePaths,
pathsToLint: resolvedFilePaths,
reportCoverage,
messageDetails,
includeMessageDetails,
});

res.forEach((result) => {
Expand Down Expand Up @@ -221,12 +221,12 @@ function transformVirtualPathToFilePath(
testFsBasePath?: string, testVirBasePath?: string
): FilePath {
if (virtualPath.startsWith(srcVirBasePath)) {
return posixPath.join(srcFsBasePath, path.relative(srcVirBasePath, virtualPath));
return path.join(srcFsBasePath, posixPath.relative(srcVirBasePath, virtualPath));
} else if (testFsBasePath && testVirBasePath && virtualPath.startsWith(testVirBasePath)) {
return posixPath.join(testFsBasePath, path.relative(testVirBasePath, virtualPath));
return path.join(testFsBasePath, posixPath.relative(testVirBasePath, virtualPath));
} else {
throw new Error(
`File path ${virtualPath} is not located within the virtual source or test directories of the project`);
`Resource path ${virtualPath} is not located within the virtual source or test directories of the project`);
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/linter/manifestJson/ManifestLinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
} from "../../manifest.d.ts";

import ManifestReporter from "./ManifestReporter.js";
import {LintMessageSeverity} from "../LinterContext.js";
import {LintMessageSeverity, ResourcePath} from "../LinterContext.js";
import jsonMap from "json-source-map";
import LinterContext from "../LinterContext.js";

Expand Down Expand Up @@ -52,19 +52,19 @@ export interface jsonSourceMapType {
export default class ManifestLinter {
#reporter: ManifestReporter | undefined;
#content = "";
#path = "";
#resourcePath = "";
#context: LinterContext;

constructor(content: string, path: string, context: LinterContext) {
constructor(resourcePath: ResourcePath, content: string, context: LinterContext) {
this.#resourcePath = resourcePath;
this.#content = content;
this.#path = path;
this.#context = context;
}

// eslint-disable-next-line @typescript-eslint/require-await
async lint() {
const source = this.#parseManifest(this.#content);
this.#reporter = new ManifestReporter(this.#path, this.#context, source);
this.#reporter = new ManifestReporter(this.#resourcePath, this.#context, source);
this.#analyzeManifest(source.data);
}

Expand Down
Loading

0 comments on commit 583e026

Please sign in to comment.